30
30
# dependency is the OpenSSL commandline tool for optional text listing.
31
31
# Hacked by Guenter Knauf.
32
32
#
33
+ use File::Basename ' dirname' ;
33
34
use Getopt::Std;
34
35
use MIME::Base64;
35
- use LWP::UserAgent;
36
36
use strict;
37
- use vars qw( $opt_b $opt_d $opt_f $ opt_h $opt_i $opt_l $opt_n $ opt_p $opt_q $opt_s $opt_t $opt_u $opt_v $opt_w) ;
37
+ use vars qw( $opt_h $opt_i $opt_l $opt_p $opt_q $opt_s $opt_t $opt_v $opt_w) ;
38
38
use List::Util;
39
39
use Text::Wrap;
40
- my $MOD_SHA = " Digest::SHA" ;
41
- eval " require $MOD_SHA " ;
42
- if ($@ ) {
43
- $MOD_SHA = " Digest::SHA::PurePerl" ;
44
- eval " require $MOD_SHA " ;
45
- }
46
-
47
- my %urls = (
48
- ' nss' =>
49
- ' http://hg.mozilla.org/projects/nss/raw-file/tip/lib/ckfw/builtins/certdata.txt' ,
50
- ' central' =>
51
- ' http://hg.mozilla.org/mozilla-central/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt' ,
52
- ' aurora' =>
53
- ' http://hg.mozilla.org/releases/mozilla-aurora/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt' ,
54
- ' beta' =>
55
- ' http://hg.mozilla.org/releases/mozilla-beta/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt' ,
56
- ' release' =>
57
- ' http://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt' ,
58
- );
59
-
60
- $opt_d = ' release' ;
61
40
62
41
# If the OpenSSL commandline is not in search path you can configure it here!
63
42
my $openssl = ' openssl' ;
64
43
65
44
my $version = ' 1.25' ;
66
45
67
- $opt_w = 76 ; # default base64 encoded lines length
46
+ $opt_w = 72 ; # default base64 encoded lines length
68
47
69
48
# default cert types to include in the output (default is to include CAs which may issue SSL server certs)
70
49
my $default_mozilla_trust_purposes = " SERVER_AUTH" ;
111
90
$Getopt::Std::STANDARD_HELP_VERSION = 1;
112
91
getopts(' bd:fhilnp:qs:tuvw:' );
113
92
114
- if (!defined ($opt_d )) {
115
- # to make plain "-d" use not cause warnings, and actually still work
116
- $opt_d = ' release' ;
117
- }
118
-
119
- # Use predefined URL or else custom URL specified on command line.
120
- my $url = ( defined ( $urls {$opt_d } ) ) ? $urls {$opt_d } : $opt_d ;
121
-
122
- my $curl = ` curl -V` ;
123
-
124
93
if ($opt_i ) {
125
94
print (" =" x 78 . " \n " );
126
95
print " Script Version : $version \n " ;
127
96
print " Perl Version : $] \n " ;
128
97
print " Operating System Name : $^O\n " ;
129
98
print " Getopt::Std.pm Version : ${Getopt::Std::VERSION} \n " ;
130
99
print " MIME::Base64.pm Version : ${MIME::Base64::VERSION} \n " ;
131
- print " LWP::UserAgent.pm Version : ${LWP::UserAgent::VERSION} \n " ;
132
- print " LWP.pm Version : ${LWP::VERSION} \n " ;
133
- print " Digest::SHA.pm Version : ${Digest::SHA::VERSION} \n " if ($Digest::SHA::VERSION );
134
- print " Digest::SHA::PurePerl.pm Version : ${Digest::SHA::PurePerl::VERSION} \n " if ($Digest::SHA::PurePerl::VERSION );
135
100
print (" =" x 78 . " \n " );
136
101
}
137
102
138
- sub warning_message () {
139
- if ( $opt_d =~ m / ^risk$ / i ) { # Long Form Warning and Exit
140
- print " Warning: Use of this script may pose some risk:\n " ;
141
- print " \n " ;
142
- print " 1) Using http is subject to man in the middle attack of certdata content\n " ;
143
- print " 2) Default to 'release', but more recent updates may be found in other trees\n " ;
144
- print " 3) certdata.txt file format may change, lag time to update this script\n " ;
145
- print " 4) Generally unwise to blindly trust CAs without manual review & verification\n " ;
146
- print " 5) Mozilla apps use additional security checks aren't represented in certdata\n " ;
147
- print " 6) Use of this script will make a security engineer grind his teeth and\n " ;
148
- print " swear at you. ;)\n " ;
149
- exit ;
150
- } else { # Short Form Warning
151
- print " Warning: Use of this script may pose some risk, -d risk for more details.\n " ;
152
- }
153
- }
154
-
155
103
sub HELP_MESSAGE () {
156
- print " Usage:\t ${0} [-b] [-d<certdata>] [-f] [-i] [-l] [-n] [-p<purposes:levels>] [-q] [-s<algorithms>] [-t] [-u] [-v] [-w<l>] [<outputfile>]\n " ;
157
- print " \t -b\t backup an existing version of ca-bundle.crt\n " ;
158
- print " \t -d\t specify Mozilla tree to pull certdata.txt or custom URL\n " ;
159
- print " \t\t Valid names are:\n " ;
160
- print " \t\t " , join ( " , " , map { ( $_ =~ m /$opt_d / ) ? " $_ (default)" : " $_ " } sort keys %urls ), " \n " ;
161
- print " \t -f\t force rebuild even if certdata.txt is current\n " ;
104
+ print " Usage:\t ${0} [-i] [-l] [-p<purposes:levels>] [-q] [-s<algorithms>] [-t] [-v] [-w<l>] [<outputfile>]\n " ;
162
105
print " \t -i\t print version info about used modules\n " ;
163
106
print " \t -l\t print license info about certdata.txt\n " ;
164
- print " \t -n\t no download of certdata.txt (to use existing)\n " ;
165
107
print wrap(" \t " ," \t\t " , " -p\t list of Mozilla trust purposes and levels for certificates to include in output. Takes the form of a comma separated list of purposes, a colon, and a comma separated list of levels. (default: $default_mozilla_trust_purposes :$default_mozilla_trust_levels )" ), " \n " ;
166
108
print " \t\t Valid purposes are:\n " ;
167
109
print wrap(" \t\t " ," \t\t " , join ( " , " , " ALL" , @valid_mozilla_trust_purposes ) ), " \n " ;
172
114
print " \t\t Valid signature algorithms are:\n " ;
173
115
print wrap(" \t\t " ," \t\t " , join ( " , " , " ALL" , @valid_signature_algorithms ) ), " \n " ;
174
116
print " \t -t\t include plain text listing of certificates\n " ;
175
- print " \t -u\t unlink (remove) certdata.txt after processing\n " ;
176
117
print " \t -v\t be verbose and print out processed CAs\n " ;
177
118
print " \t -w <l>\t wrap base64 output lines after <l> chars (default: ${opt_w} )\n " ;
178
119
exit ;
182
123
print " ${0} version ${version} running Perl ${]} on ${^O}\n " ;
183
124
}
184
125
185
- warning_message() unless ($opt_q || $url =~ m / ^(ht|f)tps:/ i );
186
126
HELP_MESSAGE() if ($opt_h );
187
127
188
128
sub report ($@) {
@@ -224,35 +164,6 @@ ($$@)
224
164
return @values ;
225
165
}
226
166
227
- sub sha1 {
228
- my $result ;
229
- if ($Digest::SHA::VERSION || $Digest::SHA::PurePerl::VERSION ) {
230
- open (FILE, $_ [0]) or die " Can't open '$_ [0]': $! " ;
231
- binmode (FILE);
232
- $result = $MOD_SHA -> new(1)-> addfile(*FILE)-> hexdigest;
233
- close (FILE);
234
- } else {
235
- # Use OpenSSL command if Perl Digest::SHA modules not available
236
- $result = (split (/ |\r |\n / ,` $openssl dgst -sha1 $_ [0]` ))[1];
237
- }
238
- return $result ;
239
- }
240
-
241
-
242
- sub oldsha1 {
243
- my $sha1 = " " ;
244
- open (C, " <$_ [0]" ) || return 0;
245
- while (<C>) {
246
- chomp ;
247
- if ($_ =~ / ^\#\# SHA1: (.*)/ ) {
248
- $sha1 = $1 ;
249
- last ;
250
- }
251
- }
252
- close (C);
253
- return $sha1 ;
254
- }
255
-
256
167
if ( $opt_p !~ m / :/ ) {
257
168
print " Error: Mozilla trust identifier list must include both purposes and levels\n " ;
258
169
HELP_MESSAGE();
@@ -275,98 +186,17 @@ (%)
275
186
return 0;
276
187
}
277
188
278
- my $crt = $ARGV [0] || ' ca-bundle.crt ' ;
279
- ( my $txt = $url ) =~ s @ (.*/| \? .*) @@ g ;
189
+ my $crt = $ARGV [0] || dirname( __FILE__ ) . ' /../src/node_root_certs.h ' ;
190
+ my $txt = dirname( __FILE__ ) . ' /certdata.txt ' ;
280
191
281
192
my $stdout = $crt eq ' -' ;
282
- my $resp ;
283
- my $fetched ;
284
-
285
- my $oldsha1 = oldsha1($crt );
286
193
287
- report " SHA1 of old file: $oldsha1 " ;
288
-
289
- report " Downloading '$txt ' ..." ;
290
-
291
- if ($curl && !$opt_n ) {
292
- my $https = $url ;
293
- $https =~ s / ^http:/ https:/ ;
294
- report " Get certdata over HTTPS with curl!" ;
295
- my $quiet = $opt_q ? " -s" : " " ;
296
- my @out = ` curl -w %{response_code} $quiet -O $https ` ;
297
- if (@out && $out [0] == 200) {
298
- $fetched = 1;
299
- } else {
300
- report " Failed downloading HTTPS with curl, trying HTTP with LWP" ;
301
- }
302
- }
303
-
304
- unless ($fetched || ($opt_n and -e $txt )) {
305
- my $ua = new LWP::UserAgent(agent => " $0 /$version " );
306
- $ua -> env_proxy();
307
- $resp = $ua -> mirror($url , $txt );
308
- if ($resp && $resp -> code eq ' 304' ) {
309
- report " Not modified" ;
310
- exit 0 if -e $crt && !$opt_f ;
311
- } else {
312
- $fetched = 1;
313
- }
314
- if ( !$resp || $resp -> code !~ / ^(?:200|304)$ / ) {
315
- report " Unable to download latest data: "
316
- . ($resp ? $resp -> code . ' - ' . $resp -> message : " LWP failed" );
317
- exit 1 if -e $crt || ! -r $txt ;
318
- }
319
- }
320
-
321
- my $filedate = $resp ? $resp -> last_modified : (stat ($txt ))[9];
322
- my $datesrc = " as of" ;
323
- if (!$filedate ) {
324
- # mxr.mozilla.org gave us a time, hg.mozilla.org does not!
325
- $filedate = time ();
326
- $datesrc =" downloaded on" ;
327
- }
328
-
329
- # get the hash from the download file
330
- my $newsha1 = sha1($txt );
331
-
332
- if (!$opt_f && $oldsha1 eq $newsha1 ) {
333
- report " Downloaded file identical to previous run\' s source file. Exiting" ;
334
- exit ;
335
- }
336
-
337
- report " SHA1 of new file: $newsha1 " ;
338
-
339
- my $currentdate = scalar gmtime ($filedate );
340
-
341
- my $format = $opt_t ? " plain text and " : " " ;
342
194
if ( $stdout ) {
343
195
open (CRT, ' > -' ) or die " Couldn't open STDOUT: $! \n " ;
344
196
} else {
345
197
open (CRT," >$crt .~" ) or die " Couldn't open $crt .~: $! \n " ;
346
198
}
347
- print CRT <<EOT ;
348
- ##
349
- ## Bundle of CA Root Certificates
350
- ##
351
- ## Certificate data from Mozilla ${datesrc} : ${currentdate}
352
- ##
353
- ## This is a bundle of X.509 certificates of public Certificate Authorities
354
- ## (CA). These were automatically extracted from Mozilla's root certificates
355
- ## file (certdata.txt). This file can be found in the mozilla source tree:
356
- ## ${url}
357
- ##
358
- ## It contains the certificates in ${format} PEM format and therefore
359
- ## can be directly used with curl / libcurl / php_curl, or with
360
- ## an Apache+mod_ssl webserver for SSL client authentication.
361
- ## Just configure this file as the SSLCACertificateFile.
362
- ##
363
- ## Conversion done with mk-ca-bundle.pl version $version .
364
- ## SHA1: $newsha1
365
- ##
366
-
367
- EOT
368
-
369
- report " Processing '$txt ' ..." ;
199
+
370
200
my $caname ;
371
201
my $certnum = 0;
372
202
my $skipnum = 0;
386
216
next if / ^#|^\s *$ / ;
387
217
chomp ;
388
218
if (/ ^CVS_ID\s +\" (.*)\" / ) {
389
- print CRT " # $1 \n " ;
219
+ print CRT " /* $1 */ \n " ;
390
220
}
391
221
392
222
# this is a match for the start of a certificate
@@ -431,11 +261,11 @@ (%)
431
261
$skipnum ++;
432
262
} else {
433
263
my $encoded = MIME::Base64::encode_base64($data , ' ' );
434
- $encoded =~ s / (.{1,${opt_w}})/ $1 \n / g ;
435
- my $pem = " -----BEGIN CERTIFICATE-----\n "
264
+ $encoded =~ s / (.{1,${opt_w}})/ " $1 \\ n" \n / g ;
265
+ my $pem = " \" -----BEGIN CERTIFICATE-----\\ n \" \n"
436
266
. $encoded
437
- . " -----END CERTIFICATE-----\n " ;
438
- print CRT " \n $caname \n " ;
267
+ . " \" -----END CERTIFICATE-----\\ n \" , \n " ;
268
+ print CRT " \n /* $caname */ \n " ;
439
269
440
270
my $maxStringLength = length ($caname );
441
271
if ($opt_t ) {
445
275
print CRT $string . " \n " ;
446
276
}
447
277
}
448
- print CRT (" =" x $maxStringLength . " \n " );
449
278
if (!$opt_t ) {
450
279
print CRT $pem ;
451
280
} else {
484
313
close (TXT) or die " Couldn't close $txt : $! \n " ;
485
314
close (CRT) or die " Couldn't close $crt .~: $! \n " ;
486
315
unless ( $stdout ) {
487
- if ($opt_b && -e $crt ) {
488
- my $bk = 1;
489
- while (-e " $crt .~${bk} ~" ) {
490
- $bk ++;
491
- }
492
- rename $crt , " $crt .~${bk} ~" or die " Failed to create backup $crt .~$bk }~: $! \n " ;
493
- } elsif ( -e $crt ) {
494
- unlink ( $crt ) or die " Failed to remove $crt : $! \n " ;
495
- }
496
316
rename " $crt .~" , $crt or die " Failed to rename $crt .~ to $crt : $! \n " ;
497
317
}
498
- unlink $txt if ($opt_u );
499
318
report " Done ($certnum CA certs processed, $skipnum skipped)." ;
0 commit comments