From cd46261fd0407325a4271bccdeaf851f6e4d7ebf Mon Sep 17 00:00:00 2001 From: Ian Young Date: Mon, 14 Jul 2008 18:08:18 +0000 Subject: [PATCH] Stand-alone script to check the certificates extracted from a list of host+port locations. Notable checks are for the Debian key issue and short keys. --- build/check_locs_list.pl | 128 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100755 build/check_locs_list.pl diff --git a/build/check_locs_list.pl b/build/check_locs_list.pl new file mode 100755 index 00000000..31a40a79 --- /dev/null +++ b/build/check_locs_list.pl @@ -0,0 +1,128 @@ +#!/usr/bin/perl -w +use File::Temp qw(tempfile); +use Date::Parse; +use Digest::SHA1 qw(sha1 sha1_hex sha1_base64); + +# +# Load RSA key blacklists. +# +print "Loading key blacklists...\n"; +open KEYS, '../build/blacklist.RSA-1024' || die "can't open RSA 1024 blacklist"; +while () { + chomp; + $rsa1024{$_} = 1; +} +close KEYS; +open KEYS, '../build/blacklist.RSA-2048' || die "can't open RSA 2048 blacklist"; +while () { + chomp; + $rsa2048{$_} = 1; +} +close KEYS; +print "Blacklists loaded.\n"; + +# +# Temporary output file for certificate extraction tool. +# +$temp_der = '/tmp/cert.der'; + +while (<>) { + + # + # Each line of input contains at least a host name, and optionally + # a port number. The latter defaults to 443 if absent. + # + @args = split; + $host = $args[0]; + $port = $args[1]; + $port = 443 unless $port; + $hostPort = "$host:$port"; + + # + # Output header line. + # + print "Testing $hostPort\n"; + + # + # Remove any old copy of the DER file. + # + unlink $temp_der; + + # + # Attempt certificate extraction + # + system "java -classpath ../bin uk.org.ukfederation.apps.cert.ExtractCert " . + "$host $port $temp_der"; + + # + # If the output file doesn't exist, the extraction failed. + # + if (!-e $temp_der) { + print "*** $hostPort: certificate extraction failed\n"; + next; + } + + # + # Use openssl to convert the certificate to text + # + my(@lines, $issuer, $subjectCN, $issuerCN); + $cmd = "openssl x509 -in $temp_der -inform der -noout -text -nameopt RFC2253 -modulus |"; + open(SSL, $cmd) || die "could not open openssl subcommand"; + while () { + push @lines, $_; + if (/^\s*Issuer:\s*(.*)$/) { + $issuer = $1; + if ($issuer =~ /CN=([^,]+)/) { + $issuerCN = $1; + } else { + $issuerCN = $issuer; + } + } + if (/^\s*Subject:\s*.*?CN=([a-z0-9\-\.]+).*$/) { + $subjectCN = $1; + # print "subjectCN = $subjectCN\n"; + } + if (/RSA Public Key: \((\d+) bit\)/) { + $pubSize = $1; + # print " Public key size: $pubSize\n"; + if ($pubSize < 1024) { + print "*** $hostPort: PUBLIC KEY TOO SHORT ($pubSize bits)\n"; + } + } + if (/Not After : (.*)$/) { + $notAfter = $1; + $days = (str2time($notAfter)-time())/86400.0; + if ($days < 0) { + print "*** $hostPort: EXPIRED\n"; + } elsif ($days < 30) { + $days = int($days); + print "*** $hostPort: expires in $days days\n"; + } elsif ($days < 90) { + $days = int($days); + print "$hostPort: expires in $days days\n"; + } + } + + # + # Check for weak (Debian) keys + # + # Weak key fingerprints loaded from files are hex SHA-1 digests of the + # line you get from "openssl x509 -modulus", including the "Modulus=". + # + if (/^Modulus=(.*)$/) { + $modulus = $_; + # print " modulus: $modulus\n"; + $fpr = sha1_hex($modulus); + # print " fpr: $fpr\n"; + if ($pubSize == 1024) { + if (defined($rsa1024{$fpr})) { + print "*** $hostPort: WEAK DEBIAN KEY\n"; + } + } elsif ($pubSize == 2048) { + if (defined($rsa2048{$fpr})) { + print "*** $hostPort: WEAK DEBIAN KEY\n"; + } + } + } + } +}