X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=lib%2Fmk-ca-bundle.pl;h=0b1331840f943a29317e0df3fa3af4f8f4416a3b;hb=df4392d06fac8fead7a2cbde19684f54c580af68;hp=232c36e4f50f430db12b1595fcb076c939e5ba4b;hpb=867eb33477c07331e7b58302119308d02a02ee01;p=platform%2Fupstream%2Fcurl.git diff --git a/lib/mk-ca-bundle.pl b/lib/mk-ca-bundle.pl index 232c36e..0b13318 100755 --- a/lib/mk-ca-bundle.pl +++ b/lib/mk-ca-bundle.pl @@ -37,20 +37,24 @@ use strict; 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); use List::Util; use Text::Wrap; +my $MOD_SHA = "Digest::SHA"; +eval "require $MOD_SHA"; +if ($@) { + $MOD_SHA = "Digest::SHA::PurePerl"; + eval "require $MOD_SHA"; +} my %urls = ( 'nss' => - 'http://mxr.mozilla.org/nss/source/lib/ckfw/builtins/certdata.txt?raw=1', + 'http://hg.mozilla.org/projects/nss/raw-file/tip/lib/ckfw/builtins/certdata.txt', 'central' => - 'http://mxr.mozilla.org/mozilla-central/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1', + 'http://hg.mozilla.org/mozilla-central/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt', 'aurora' => - 'http://mxr.mozilla.org/mozilla-aurora/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1', + 'http://hg.mozilla.org/releases/mozilla-aurora/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt', 'beta' => - 'http://mxr.mozilla.org/mozilla-beta/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1', + 'http://hg.mozilla.org/releases/mozilla-beta/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt', 'release' => - 'http://mxr.mozilla.org/mozilla-release/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1', - 'mozilla' => - 'http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1' + 'http://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt', ); $opt_d = 'release'; @@ -58,7 +62,7 @@ $opt_d = 'release'; # If the OpenSSL commandline is not in search path you can configure it here! my $openssl = 'openssl'; -my $version = '1.21'; +my $version = '1.25'; $opt_w = 76; # default base64 encoded lines length @@ -99,7 +103,8 @@ my @valid_signature_algorithms = ( "MD5", "SHA1", "SHA256", - "SHA512" + "SHA384", + "SHA512" ); $0 =~ s@.*(/|\\)@@; @@ -114,29 +119,33 @@ if(!defined($opt_d)) { # Use predefined URL or else custom URL specified on command line. my $url = ( defined( $urls{$opt_d} ) ) ? $urls{$opt_d} : $opt_d; +my $curl = `curl -V`; + if ($opt_i) { print ("=" x 78 . "\n"); - print "Script Version : $version\n"; - print "Perl Version : $]\n"; - print "Operating System Name : $^O\n"; - print "Getopt::Std.pm Version : ${Getopt::Std::VERSION}\n"; - print "MIME::Base64.pm Version : ${MIME::Base64::VERSION}\n"; - print "LWP::UserAgent.pm Version : ${LWP::UserAgent::VERSION}\n"; - print "LWP.pm Version : ${LWP::VERSION}\n"; + print "Script Version : $version\n"; + print "Perl Version : $]\n"; + print "Operating System Name : $^O\n"; + print "Getopt::Std.pm Version : ${Getopt::Std::VERSION}\n"; + print "MIME::Base64.pm Version : ${MIME::Base64::VERSION}\n"; + print "LWP::UserAgent.pm Version : ${LWP::UserAgent::VERSION}\n"; + print "LWP.pm Version : ${LWP::VERSION}\n"; + print "Digest::SHA.pm Version : ${Digest::SHA::VERSION}\n" if ($Digest::SHA::VERSION); + print "Digest::SHA::PurePerl.pm Version : ${Digest::SHA::PurePerl::VERSION}\n" if ($Digest::SHA::PurePerl::VERSION); print ("=" x 78 . "\n"); } -sub WARNING_MESSAGE() { +sub warning_message() { if ( $opt_d =~ m/^risk$/i ) { # Long Form Warning and Exit print "Warning: Use of this script may pose some risk:\n"; - print "\n"; - print " 1) Using http is subject to man in the middle attack of certdata content\n"; - print " 2) Default to 'release', but more recent updates may be found in other trees\n"; - print " 3) certdata.txt file format may change, lag time to update this script\n"; - print " 4) Generally unwise to blindly trust CAs without manual review & verification\n"; - print " 5) Mozilla apps use additional security checks aren't represented in certdata\n"; - print " 6) Use of this script will make a security engineer grind his teeth and\n"; - print " swear at you. ;)\n"; + print "\n"; + print " 1) Using http is subject to man in the middle attack of certdata content\n"; + print " 2) Default to 'release', but more recent updates may be found in other trees\n"; + print " 3) certdata.txt file format may change, lag time to update this script\n"; + print " 4) Generally unwise to blindly trust CAs without manual review & verification\n"; + print " 5) Mozilla apps use additional security checks aren't represented in certdata\n"; + print " 6) Use of this script will make a security engineer grind his teeth and\n"; + print " swear at you. ;)\n"; exit; } else { # Short Form Warning print "Warning: Use of this script may pose some risk, -d risk for more details.\n"; @@ -173,10 +182,10 @@ sub VERSION_MESSAGE() { print "${0} version ${version} running Perl ${]} on ${^O}\n"; } -WARNING_MESSAGE() unless ($opt_q || $url =~ m/^(ht|f)tps:/i ); +warning_message() unless ($opt_q || $url =~ m/^(ht|f)tps:/i ); HELP_MESSAGE() if ($opt_h); -sub IS_IN_LIST($@) { +sub is_in_list($@) { my $target = shift; return defined(List::Util::first { $target eq $_ } @_); @@ -184,7 +193,7 @@ sub IS_IN_LIST($@) { # Parses $param_string as a case insensitive comma separated list with optional whitespace # validates that only allowed parameters are supplied -sub PARSE_CSV_PARAM($$@) { +sub parse_csv_param($$@) { my $description = shift; my $param_string = shift; my @valid_values = @_; @@ -196,38 +205,67 @@ sub PARSE_CSV_PARAM($$@) { } split( ',', $param_string ); # Find all values which are not in the list of valid values or "ALL" - my @invalid = grep { !IS_IN_LIST($_,"ALL",@valid_values) } @values; + my @invalid = grep { !is_in_list($_,"ALL",@valid_values) } @values; if ( scalar(@invalid) > 0 ) { # Tell the user which parameters were invalid and print the standard help message which will exit print "Error: Invalid ", $description, scalar(@invalid) == 1 ? ": " : "s: ", join( ", ", map { "\"$_\"" } @invalid ), "\n"; HELP_MESSAGE(); } - - @values = @valid_values if ( IS_IN_LIST("ALL",@values) ); - + + @values = @valid_values if ( is_in_list("ALL",@values) ); + return @values; } +sub sha1 { + my $result; + if ($Digest::SHA::VERSION || $Digest::SHA::PurePerl::VERSION) { + open(FILE, $_[0]) or die "Can't open '$_[0]': $!"; + binmode(FILE); + $result = $MOD_SHA->new(1)->addfile(*FILE)->hexdigest; + close(FILE); + } else { + # Use OpenSSL command if Perl Digest::SHA modules not available + $result = (split(/ |\r|\n/,`$openssl dgst -sha1 $_[0]`))[1]; + } + return $result; +} + + +sub oldsha1 { + my $sha1 = ""; + open(C, "<$_[0]") || return 0; + while() { + chomp; + if($_ =~ /^\#\# SHA1: (.*)/) { + $sha1 = $1; + last; + } + } + close(C); + return $sha1; +} + if ( $opt_p !~ m/:/ ) { print "Error: Mozilla trust identifier list must include both purposes and levels\n"; HELP_MESSAGE(); } (my $included_mozilla_trust_purposes_string, my $included_mozilla_trust_levels_string) = split( ':', $opt_p ); -my @included_mozilla_trust_purposes = PARSE_CSV_PARAM( "trust purpose", $included_mozilla_trust_purposes_string, @valid_mozilla_trust_purposes ); -my @included_mozilla_trust_levels = PARSE_CSV_PARAM( "trust level", $included_mozilla_trust_levels_string, @valid_mozilla_trust_levels ); +my @included_mozilla_trust_purposes = parse_csv_param( "trust purpose", $included_mozilla_trust_purposes_string, @valid_mozilla_trust_purposes ); +my @included_mozilla_trust_levels = parse_csv_param( "trust level", $included_mozilla_trust_levels_string, @valid_mozilla_trust_levels ); -my @included_signature_algorithms = PARSE_CSV_PARAM( "signature algorithm", $opt_s, @valid_signature_algorithms ); +my @included_signature_algorithms = parse_csv_param( "signature algorithm", $opt_s, @valid_signature_algorithms ); -sub SHOULD_OUTPUT_CERT(%) { +sub should_output_cert(%) { my %trust_purposes_by_level = @_; - + foreach my $level (@included_mozilla_trust_levels) { # for each level we want to output, see if any of our desired purposes are included - return 1 if ( defined( List::Util::first { IS_IN_LIST( $_, @included_mozilla_trust_purposes ) } @{$trust_purposes_by_level{$level}} ) ); + return 1 if ( defined( List::Util::first { is_in_list( $_, @included_mozilla_trust_purposes ) } @{$trust_purposes_by_level{$level}} ) ); } - + return 0; } @@ -238,8 +276,26 @@ my $stdout = $crt eq '-'; my $resp; my $fetched; -unless ($opt_n and -e $txt) { - print STDERR "Downloading '$txt' ...\n" if (!$opt_q); +my $oldsha1 = oldsha1($crt); + +print STDERR "SHA1 of old file: $oldsha1\n" if (!$opt_q); + +print STDERR "Downloading '$txt' ...\n" if (!$opt_q); + +if($curl && !$opt_n) { + my $https = $url; + $https =~ s/^http:/https:/; + print STDERR "Get certdata over HTTPS with curl!\n" if (!$opt_q); + my $quiet = $opt_q ? "-s" : ""; + my @out = `curl -w %{response_code} $quiet -O $https`; + if(@out && $out[0] == 200) { + $fetched = 1; + } else { + print STDERR "Failed downloading HTTPS with curl, trying HTTP with LWP\n" if (!$opt_q); + } +} + +unless ($fetched || ($opt_n and -e $txt)) { my $ua = new LWP::UserAgent(agent => "$0/$version"); $ua->env_proxy(); $resp = $ua->mirror($url, $txt); @@ -257,7 +313,25 @@ unless ($opt_n and -e $txt) { } } -my $currentdate = scalar gmtime($fetched ? $resp->last_modified : (stat($txt))[9]); +my $filedate = $resp ? $resp->last_modified : (stat($txt))[9]; +my $datesrc = "as of"; +if(!$filedate) { + # mxr.mozilla.org gave us a time, hg.mozilla.org does not! + $filedate = time(); + $datesrc="downloaded on"; +} + +# get the hash from the download file +my $newsha1= sha1($txt); + +if(!$opt_f && $oldsha1 eq $newsha1) { + print STDERR "Downloaded file identical to previous run\'s source file. Exiting\n"; + exit; +} + +print STDERR "SHA1 of new file: $newsha1\n"; + +my $currentdate = scalar gmtime($filedate); my $format = $opt_t ? "plain text and " : ""; if( $stdout ) { @@ -267,9 +341,9 @@ if( $stdout ) { } print CRT <) { while () { last if (/^#/); if (/^CKA_TRUST_([A-Z_]+)\s+CK_TRUST\s+CKT_NSS_([A-Z_]+)\s*$/) { - if ( !IS_IN_LIST($1,@valid_mozilla_trust_purposes) ) { + if ( !is_in_list($1,@valid_mozilla_trust_purposes) ) { print STDERR "Warning: Unrecognized trust purpose for cert: $caname. Trust purpose: $1. Trust Level: $2\n" if (!$opt_q); - } elsif ( !IS_IN_LIST($2,@valid_mozilla_trust_levels) ) { + } elsif ( !is_in_list($2,@valid_mozilla_trust_levels) ) { print STDERR "Warning: Unrecognized trust level for cert: $caname. Trust purpose: $1. Trust Level: $2\n" if (!$opt_q); } else { push @{$trust_purposes_by_level{$2}}, $1; @@ -345,7 +422,7 @@ while () { } } - if ( !SHOULD_OUTPUT_CERT(%trust_purposes_by_level) ) { + if ( !should_output_cert(%trust_purposes_by_level) ) { $skipnum ++; } else { my $encoded = MIME::Base64::encode_base64($data, ''); @@ -415,7 +492,3 @@ unless( $stdout ) { } unlink $txt if ($opt_u); print STDERR "Done ($certnum CA certs processed, $skipnum skipped).\n" if (!$opt_q); - -exit; - -