Skip to content

Commit

Permalink
Suite of scripts to look at certificate expiry on endpoints belonging…
Browse files Browse the repository at this point in the history
… to no-key (PKIX-only) entities.
  • Loading branch information
iay committed Feb 5, 2013
1 parent 7fc2fb7 commit 8c52106
Show file tree
Hide file tree
Showing 4 changed files with 429 additions and 0 deletions.
54 changes: 54 additions & 0 deletions build/extract_nk_cert_locs.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
extract_nk_cert_locs.xsl
XSL stylesheet that takes a SAML 2.0 metadata file and extracts
a list of service locations that require certificates to be
presented to them.
Author: Ian A. Young <ian@iay.org.uk>
-->
<xsl:stylesheet version="1.0"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
exclude-result-prefixes="md">

<!-- Output is plain text -->
<xsl:output method="text"/>

<!--
Exclude entities which have embedded certificates.
I.e., restrict output to entities which only have PKIX trust.
-->
<xsl:template match="md:EntityDescriptor[descendant::ds:X509Data]">
<!-- do nothing -->
</xsl:template>

<xsl:template match="//md:AttributeService">
<xsl:value-of select="ancestor::md:EntityDescriptor/@ID"/>
<xsl:text> </xsl:text>
<xsl:value-of select="@Location"/>
<xsl:text>&#x0a;</xsl:text>
</xsl:template>

<!--
ArtifactResolutionService endpoints on IdPs are assumed to be
authenticated by TLS; those on SPs are assumed to be authenticated
using other mechanisms.
-->
<xsl:template match="//md:IDPSSODescriptor/md:ArtifactResolutionService">
<xsl:value-of select="ancestor::md:EntityDescriptor/@ID"/>
<xsl:text> </xsl:text>
<xsl:value-of select="@Location"/>
<xsl:text>&#x0a;</xsl:text>
</xsl:template>

<xsl:template match="text()">
<!-- do nothing -->
</xsl:template>
</xsl:stylesheet>
57 changes: 57 additions & 0 deletions build/extract_nk_nocert_locs.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
extract_nk_nocert_locs.xsl
XSL stylesheet that takes a SAML 2.0 metadata file and extracts
a list of service locations that do not require certificates to be
presented to them.
Author: Ian A. Young <ian@iay.org.uk>
-->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:wayf="http://sdss.ac.uk/2006/06/WAYF"
exclude-result-prefixes="md ds wayf">

<!-- Output is plain text -->
<xsl:output method="text"/>

<!--
Exclude entities which have embedded certificates.
I.e., restrict output to entities which only have PKIX trust.
-->
<xsl:template match="md:EntityDescriptor[descendant::ds:X509Data]">
<!-- do nothing -->
</xsl:template>

<xsl:template match="//md:SingleSignOnService">
<xsl:value-of select="ancestor::md:EntityDescriptor/@ID"/>
<xsl:text> </xsl:text>
<xsl:value-of select="@Location"/>
<xsl:text>&#x0a;</xsl:text>
</xsl:template>

<xsl:template match="//md:AssertionConsumerService">
<xsl:value-of select="ancestor::md:EntityDescriptor/@ID"/>
<xsl:text> </xsl:text>
<xsl:value-of select="@Location"/>
<xsl:text>&#x0a;</xsl:text>
</xsl:template>

<xsl:template match="//md:SPSSODescriptor/md:ArtifactResolutionService">
<xsl:value-of select="ancestor::md:EntityDescriptor/@ID"/>
<xsl:text> </xsl:text>
<xsl:value-of select="@Location"/>
<xsl:text>&#x0a;</xsl:text>
</xsl:template>

<xsl:template match="text()">
<!-- do nothing -->
</xsl:template>
</xsl:stylesheet>
156 changes: 156 additions & 0 deletions build/probe_nk_certs.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#!/usr/bin/perl -w

use POSIX qw(floor);
use Date::Parse;
use ExtractCert;
use Xalan;

sub error {
my($s) = @_;
print ' *** ' . $s . ' ***' . "\n";
$printme = 1;
}

sub warning {
my ($s) = @_;
print ' ' . $s . "\n";
$printme = 1;
}

sub comment {
my($s) = @_;
print ' (' . $s . ')' . "\n";
}

#
# Number of days in the past we should regard as "long expired".
#
my $longExpiredDays = 30*3; # about three months

print "Loading endpoint locations...\n";
open(XML, xalanCall . " -IN ../xml/ukfederation-metadata.xml -XSL extract_nk_cert_locs.xsl|") || die "could not open input file";
while (<XML>) {
my ($entity, $url) = split;
if ($url =~ /^https:\/\/([^\/:]+(:\d+)?)\//) {
my $location = $1;
$location .= ":443" unless defined $2;
$locations{$location} = $entity;
} else {
print "bad location: $_";
}
}
close XML;

$count = scalar keys %locations;
print "Unique SSL with-certificate locations: $count\n";

#
# Temporary output file for certificate extraction tool.
#
$temp_der = '/tmp/probe_certs.der';

#
# Extract the certificate from each location.
#
foreach $loc (sort keys %locations) {
my $entity = $locations{$loc};
print "$count: probing $entity: $loc\n";
$count--;

#
# Remove any old copy of the DER file.
#
unlink $temp_der;

#
# Separate location into host and port.
#
my ($host, $port) = split(/:/, $loc);
#print "host: $host, port: $port\n";
my $hostPort = "$host:$port";

#
# Attempt certificate extraction
#
system extractCertCall . " $host $port $temp_der";

#
# If the output file doesn't exist, the extraction failed.
#
if (!-e $temp_der) {
print "*** $hostPort: certificate extraction failed\n";
$failed{$loc} = 1;
next;
}

#
# Use openssl to convert the certificate to text
#
my(@lines, $subject, $issuer);
$cmd = "openssl x509 -in $temp_der -inform der -noout -text -nameopt RFC2253 -modulus |";
open(SSL, $cmd) || die "could not open openssl subcommand";
while (<SSL>) {
push @lines, $_;

if (/^\s*Issuer:\s*(.*)$/) {
$issuer = $1;
#print "$hostPort: issuer is $issuer\n";
}

if (/^\s*Subject:\s*(.*)$/) {
$subject = $1;
}

if (/Not After : (.*)$/) {
$notAfter = $1;
$notAfterTime = str2time($notAfter);
$days = ($notAfterTime-time())/86400.0;
if ($days < -$longExpiredDays) {
my $d = floor(-$days);
error("EXPIRED LONG AGO ($d days; $notAfter)");
} elsif ($days < 0) {
error("EXPIRED ($notAfter)");
} elsif ($days < 18) {
$days = int($days);
error("expires in $days days ($notAfter)");
} elsif ($days < 36) {
$days = int($days);
warning("expires in $days days ($notAfter)");
}
next;
}

}

if ($subject eq $issuer) {
$issuer = "(self-signed certificate)";
}

$issuers{$issuer}{$loc} = 1;
$numissued++;
}
print "\n\n";

$count = scalar keys %failed;
print "\n\nProbes that failed: $count\n";
foreach $loc (sort keys %failed) {
print " $loc\n";
}
print "\n\n";

print "Probes we got an issuer back from: $numissued\n";
$count = scalar keys %issuers;
print "Unique issuers: $count\n";
foreach $issuer (sort keys %issuers) {
%locs = %{ $issuers{$issuer} };
$n = scalar keys %locs;
print "$n: $issuer\n";
foreach $loc (sort keys %locs) {
print " $loc\n";
}
}

#
# Clean up
#
unlink $temp_der;
Loading

0 comments on commit 8c52106

Please sign in to comment.