aboutsummaryrefslogtreecommitdiff
path: root/lib/mk-ca-bundle.pl
blob: 9357e3c3d2a5e5624f448bb5cbc37af8d4e787d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#!/usr/bin/perl
# ***************************************************************************
# *                                  _   _ ____  _
# *  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$
# ***************************************************************************
# 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 writtten by Roland Krikava.
# This Perl script works on almost any platform since its only external
# dependency is the OpenSSL commandline tool.
# Hacked by Guenter Knauf.
#
use Getopt::Std;
use MIME::Base64;
use LWP::UserAgent;

my $url = 'http://lxr.mozilla.org/seamonkey/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1';
# If the OpenSSL commandline is not in search path you can configure it here!
my $openssl = 'openssl';

getopts('hilnuv');

if ($opt_h) {
  $0 =~ s/\\/\//g;
  printf("Usage:\t%s [-i] [-l] [-n] [-u] [-v] [<outputfile>]\n", substr($0, rindex($0, '/') + 1));
  print "\t-i\tprint version info about used modules\n";
  print "\t-l\tprint license info about certdata.txt\n";
  print "\t-n\tno download of certdata.txt (to use existing)\n";
  print "\t-u\tunlink (remove) certdata.txt after processing\n";
  print "\t-v\tbe verbose and print out processed CAs\n";
  exit;
}

if ($opt_i) {
  print "Perl Version              : $]\n";
  print "Operating System Name     : $^O\n";
  printf("MIME::Base64.pm Version   : %s\n", $MIME::Base64::VERSION);
  printf("LWP::UserAgent.pm Version : %s\n", $LWP::UserAgent::VERSION);
  print ("=" x 78 . "\n");
}

my $crt = $ARGV[0] || 'ca-bundle.crt';
my $tmp = 'mytmpfile.txt';
my $txt = substr($url, rindex($url, '/') + 1);
$txt =~ s/\?.*//;
if (!$opt_n) {
  print "Downloading '$txt' ...\n" if ($opt_v);
  my $ua  = new LWP::UserAgent;
  my $req = new HTTP::Request('GET', $url);
  my $res = $ua->request($req);
  if ($res->is_success) {
    open(TXT,">$txt") or die "Couldn't open $txt: $!";
    print TXT $res->content . "\n";
    close(TXT) or die "Couldn't close $txt: $!";
  } else {
    die $res->status_line;
  }
}

die "File '$txt' doesnt exist - dont use -n switch to download the file!\n" if (!-e $txt);

my $currentdate = scalar gmtime() . " UTC";
open(CRT,">$crt") or die "Couldn't open $crt: $!";
print CRT <<EOT;
##
## $crt -- Bundle of CA Root Certificates
##
## Converted at: $currentdate
##
## This is a bundle of X.509 certificates of public Certificate Authorities
## (CA). These were automatically extracted from Mozilla's root certificates
## file (certdata.txt).  This file can be found in the mozilla source tree:
## '/mozilla/security/nss/lib/ckfw/builtins/certdata.txt'
##
## It contains the certificates in both plain text and PEM format
## and therefore can be directly used with curl / libcurl, or with an
## Apache+mod_ssl webserver for SSL client authentication.
## Just configure this file as the SSLCACertificateFile.
##

EOT

close(CRT) or die "Couldn't close $crt: $!";

my $certnum;
open(TXT,"$txt") or die "Couldn't open $file: $!";
while (<TXT>) {
  if (/\*\*\*\*\* BEGIN LICENSE BLOCK \*\*\*\*\*/) {
    open(CRT, ">>$crt") or die "Couldn't open $crt: $!";
    print CRT;
    print if ($opt_l);
    while (<TXT>) {
      print CRT;
      print if ($opt_l);
      last if (/\*\*\*\*\* END LICENSE BLOCK \*\*\*\*\*/);
    }
    close(CRT) or die "Couldn't close $crt: $!";
  }
  next if /^#/;
  next if /^\s*$/;
  chomp;
  if (/^CVS_ID\s+\"(.*)\"/) {
    open(CRT, ">>$crt") or die "Couldn't open $crt: $!";
    print CRT "# $1\n";
    close(CRT) or die "Couldn't close $crt: $!";
  }
  if (/^CKA_LABEL\s+[A-Z0-9]+\s+\"(.*)\"/) {
    $val = $1;
  }
  if (/^CKA_VALUE MULTILINE_OCTAL/) {
    my $data;
    while (<TXT>) {
      last if (/^END/);
      chomp;
      my @octets = split(/\\/);
      shift @octets;
      for (@octets) {
        $data .= chr(oct);
      }
    }
    open(CRT, ">>$crt") or die "Couldn't open $crt: $!";
    print CRT "\n";
    print CRT "$val\n";
    print CRT ("=" x length($val) . "\n");
    close(CRT) or die "Couldn't close $file: $!";
    open(TMP, ">$tmp") or die "Couldn't open $tmp: $!";
    print TMP "$val\n";
    print TMP "-----BEGIN CERTIFICATE-----\n";
    print TMP MIME::Base64::encode($data);
    print TMP "-----END CERTIFICATE-----\n";
    close(TMP) or die "Couldn't close $tmp: $!";
    system("$openssl x509 -md5 -fingerprint -text -in $tmp -inform PEM >> $crt");
    print "Parsing: $val\n" if ($opt_v);
    $certnum ++;
  }
}
close(TXT) or die "Couldn't close $txt: $!";
unlink $txt if ($opt_u);
unlink $tmp;
print "Done ($certnum CA certs processed).\n";

exit;