summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/doc-txt/experimental-spec.txt15
-rwxr-xr-xsrc/util/ocsp_fetch.pl83
2 files changed, 98 insertions, 0 deletions
diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt
index d58f3961b..7fd2bd8ec 100644
--- a/doc/doc-txt/experimental-spec.txt
+++ b/doc/doc-txt/experimental-spec.txt
@@ -92,10 +92,25 @@ is requested and required for the connection to proceed. The host(s)
should also be in "hosts_require_tls", and "tls_verify_certificates"
configured for the transport.
+For the client to be able to verify the stapled OCSP the server must
+also supply, in its stapled information, any intermediate
+certificates for the chain leading to the OCSP proof from the signer
+of the server certificate. There may be zero or one such. These
+intermediate certificates should be added to the server OCSP stapling
+file (named by tls_ocsp_file).
+
At this point in time, we're gathering feedback on use, to determine if
it's worth adding complexity to the Exim daemon to periodically re-fetch
OCSP files and somehow handling multiple files.
+ A helper script "ocsp_fetch.pl" for fetching a proof from a CA
+ OCSP server is supplied. The server URL may be included in the
+ server certificate, if the CA is helpful.
+
+ One fail mode seen was the OCSP Signer cert expiring before the end
+ of vailidity of the OCSP proof. The checking done by Exim/OpenSSL
+ noted this as invalid overall, but the re-fetch script did not.
+
diff --git a/src/util/ocsp_fetch.pl b/src/util/ocsp_fetch.pl
new file mode 100755
index 000000000..0d214d62a
--- /dev/null
+++ b/src/util/ocsp_fetch.pl
@@ -0,0 +1,83 @@
+#!/usr/bin/perl
+# Copyright (C) 2012 Wizards Internet Ltd
+# License GPLv2: GNU GPL version 2 <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
+use strict;
+use Getopt::Std;
+$Getopt::Std::STANDARD_HELP_VERSION=1;
+use IO::Handle;
+use Date::Parse;
+my ($o,$i,$s,$f,$t,$u,$VERSION);
+$VERSION='1.0';
+$o={'m'=>10};
+getopts("c:i:u:a:o:m:fv",$o);
+usage('No issuer specified') if ! $o->{'i'} && ! -f $o->{'i'};
+usage('No certificate specified') if ! $o->{'c'} && ! -f $o->{'c'};
+usage('No CA chain specified') if ! $o->{'a'} && ! -f $o->{'a'};
+usage('No OCSP file specified') if ! $o->{'o'};
+usage('No URL specified') if ! $o->{'u'};
+$o->{'t'}=$o->{'o'}.'.tmp';
+
+# check if we need to
+if ( $o->{'f'}
+ || ! -f $o->{'o'}
+ || ( -M $o->{'o'} > 0 )
+ )
+{
+ $i = new IO::Handle;
+ open( $i, "openssl ocsp -issuer $o->{'i'} -cert $o->{'c'} -url $o->{'u'} -CAfile $o->{'a'} -respout $o->{'t'} 2>/dev/null |" ) || die 'Unable to execute ocsp command';
+ $s = <$i> || die 'Unable to read status';
+ $f = <$i> || die 'Unable to read update time';
+ $t = <$i> || die 'Unable to read next update time';
+ close $i;
+ # Status ok ?
+ chomp($s);
+ chomp($f);
+ chomp($t);
+ $s =~ s/[^:]*: //;
+ $f =~ s/[^:]*: //;
+ $t =~ s/[^:]*: //;
+ $t = str2time($t);
+ die "OCSP status is $s" if $s ne 'good';
+ warn "Next Update $t" if $o->{'v'};
+ # response is good, adjust mod time and move into place.
+ $u = $t - $o->{'m'} * (($t - time)/100);
+ utime $u,$u,$o->{'t'};
+ rename $o->{'t'},$o->{'o'};
+}
+exit;
+
+sub
+usage
+{
+ my $m = shift;
+ print STDERR "$m\n" if $m;
+ HELP_MESSAGE(\*STDERR);
+ die;
+}
+sub
+HELP_MESSAGE
+{
+ my $h = shift;
+ print $h <<EOF
+Usage: $0 -i issuer -c certificate -u ocsp_url -a ca_certs -o response [-v] [-f]
+
+For a certificate "www.example.com.pem"
+ signed by "signing.example.net.pem"
+ signed by root CA "ca.example.net.pem"
+ with OCSP server http://ocsp.example.net/
+
+Ensure there is a file with the signing chain
+
+ cat ca.example.net.pem signing.example.net.pem >chain.pem
+
+The update procedure would be
+
+ ocsp_fetch -i signing.example.net.pem \
+ -c www.example.com.pem \
+ -u http://ocsp.example.net/ \
+ -a chain.pem \
+ -o www.example.com.ocsp.der
+EOF
+}
+# vi: aw ai sw=4
+# End of File