#!/usr/bin/perl -w
# ***************************************************************************
# *                                  _   _ ____  _
# *  Project                     ___| | | |  _ \| |
# *                             / __| | | | |_) | |
# *                            | (__| |_| |  _ <| |___
# *                             \___|\___/|_| \_\_____|
# *
# * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
# *
# * This software is licensed as described in the file COPYING, which
# * you should have received as part of this distribution. The terms
# * are also available at http://curl.haxx.se/docs/copyright.html.
# *
# * You may opt to use, copy, modify, merge, publish, distribute and/or sell
# * copies of the Software, and permit persons to whom the Software is
# * furnished to do so, under the terms of the COPYING file.
# *
# * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# * KIND, either express or implied.
# *
# * $Id: mk-ca-bundle.pl,v 1.10 2008/02/15 00:41:54 gknauf Exp $
# ***************************************************************************
# This Perl script creates a fresh ca-bundle.crt file for use with libcurl. 
# It downloads certdata.txt from Mozilla's source tree (see URL below),
# then parses certdata.txt and extracts CA Root Certificates into PEM format.
# These are then processed with the OpenSSL commandline tool to produce the
# final ca-bundle.crt file.
# The script is based on the parse-certs script written by Roland Krikava.
# This Perl script works on almost any platform since its only external
# dependency is the OpenSSL commandline tool for optional text listing.
# Hacked by Guenter Knauf.
#
# Hacked again by Cameron Kaiser to use cURL *instead* of LWP.
#
use Getopt::Std;
use MIME::Base64;
use strict;
use vars qw($opt_h $opt_q $opt_v);  

getopts('hqv');

$0 =~ s/\\/\//g;
$0 = substr($0, rindex($0, '/') + 1);
if ($opt_h) {
  printf("Usage:\t%s [-b] [-i] [-l] [-n] [-q] [-t] [-u] [-v] [<outputfile>]\n", $0);
  print "\t-q\tbe really quiet (no progress output at all)\n";
  print "\t-v\tbe verbose and print out processed CAs\n";
  exit;
}

my $caname;
my $pem;
my $certnum = 0;

sub emit_cert {
  my $crt = sprintf("cacert%03d.pem", $certnum);
  open(CRT, ">$crt") or die "Couldn't open $crt: $!";
  print CRT "$caname\n";
  print CRT ("=" x length($caname) . "\n");
  print CRT $pem;
  close(CRT) or die "Couldn't close $crt: $!";
  print "Parsing: $caname\n" if ($opt_v);
  $certnum++
}

my $txt = 'certdata.txt';
print "Processing  '$txt' ...\n" if (!$opt_q);
open(TXT,"$txt") or die "Couldn't open $txt: $!";

my $get_cert;
my $goodcert;

while (<TXT>) {
  if (/\*\*\*\*\* BEGIN LICENSE BLOCK \*\*\*\*\*/) {
    while (<TXT>) {
      last if (/\*\*\*\*\* END LICENSE BLOCK \*\*\*\*\*/);
    }
  }
  next if /^#|^\s*$/;
  chomp;
  if (/^CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE$/) {
    $get_cert = 1
  }
  if ($get_cert && /^CKA_LABEL UTF8 \"(.*)\"$/) {
    $caname = $1;
  }
  if ($get_cert && /^CKA_VALUE MULTILINE_OCTAL$/) {
    my $data;
    while (<TXT>) {
      last if (/^END/);
      chomp;
      my @octets = split(/\\/);
      shift @octets;
      for (@octets) {
        $data .= chr(oct)
      }
    }
    $pem = "-----BEGIN CERTIFICATE-----\n"
         . MIME::Base64::encode($data)
         . "-----END CERTIFICATE-----\n";
    $get_cert = 0;
    $goodcert = 1
  }
  if (/NOT_TRUSTED/) {
    $goodcert = 0
  }
  if (/^CKA_TRUST_STEP_UP_APPROVED/) {
    if ($goodcert) {
      emit_cert
    }
  }
}

close(TXT) or die "Couldn't close $txt: $!";
print "Done ($certnum CA certs processed).\n" if (!$opt_q);

exit;
