5 # Copyright (c) 2015 DeNA Co., Ltd.
7 # Permission is hereby granted, free of charge, to any person obtaining a copy
8 # of this software and associated documentation files (the "Software"), to
9 # deal in the Software without restriction, including without limitation the
10 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11 # sell copies of the Software, and to permit persons to whom the Software is
12 # furnished to do so, subject to the following conditions:
14 # The above copyright notice and this permission notice shall be included in
15 # all copies or substantial portions of the Software.
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
27 use File::Temp qw(tempdir);
31 use constant EX_TEMPFAIL => 75;
33 my ($issuer_fn, $opt_help);
34 my $openssl_cmd = 'openssl';
37 "issuer=s" => \$issuer_fn,
38 "openssl=s", => \$openssl_cmd,
43 Usage: $0 [<options>] <certificate-file>
46 --issuer <file> issuer certificate (if omitted, is extracted from the
48 --openssl <cmd> openssl command to use (default: "openssl")
49 --help prints this help
51 The command issues an OCSP request for given server certificate, verifies the
52 response and prints the resulting DER.
54 The command exits 0 if successful, or 75 (EX_TEMPFAIL) on temporary error.
55 Other exit codes may be returned in case of hard errors.
61 die "no certificate file\n"
63 my $cert_fn = shift @ARGV;
65 my $tempdir = tempdir(CLEANUP => 1);
67 my $openssl_version = run_openssl("version");
68 chomp $openssl_version;
69 print STDERR "fetch-ocsp-response (using $openssl_version)\n";
72 my $ocsp_uri = run_openssl("x509 -in $cert_fn -noout -ocsp_uri");
74 die "failed to extract ocsp URI from $cert_fn\n"
75 if $ocsp_uri !~ m{^https?://};
76 my($ocsp_host) = $ocsp_uri =~ m{^https?://([^/:]+)};
78 # save issuer certificate
79 if (! defined $issuer_fn) {
80 my $chain = read_file($cert_fn);
81 $chain =~ m{-----END CERTIFICATE-----.*?(-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----)}s
82 or die "--issuer option was not used, and failed to extract issuer certificate from the certificate\n";
83 $issuer_fn = "$tempdir/issuer.crt";
84 write_file($issuer_fn, "$1\n");
87 # obtain response (without verification)
88 print STDERR "sending OCSP request to $ocsp_uri\n";
89 my $resp = run_openssl(
90 "ocsp -issuer $issuer_fn -cert $cert_fn -url $ocsp_uri"
91 . ($openssl_version =~ /^OpenSSL 1\./is ? " -header Host $ocsp_host" : "")
92 . " -noverify -respout $tempdir/resp.der " . join(' ', @ARGV),
98 print STDERR "verifying the response signature\n";
101 # try from exotic options
102 "-VAfile $issuer_fn", # for comodo
103 "-partial_chain -trusted_first -CAfile $issuer_fn", # these options are only available in OpenSSL >= 1.0.2
104 "-CAfile $issuer_fn", # for OpenSSL <= 1.0.1
106 if (system("$openssl_cmd ocsp -respin $tempdir/resp.der $args > $tempdir/verify.out 2>&1") == 0) {
107 print STDERR "verify OK (used: $args)\n";
113 print STDERR read_file("$tempdir/verify.out");
114 tempfail("failed to verify the response\n");
118 print read_file("$tempdir/resp.der");
122 my ($args, $tempfail) = @_;
123 open my $fh, "-|", "$openssl_cmd $args"
124 or die "failed to invoke $openssl_cmd:$!";
125 my $resp = do { local $/; <$fh> };
127 or ($tempfail ? \&tempfail : \&die)->("OpenSSL exitted abnormally: $openssl_cmd $args:$!");
133 open my $fh, "<", $fn
134 or die "failed to open file:$fn:$!";
140 my ($fn, $data) = @_;
141 open my $fh, ">", $fn
142 or die "failed to open file:$fn:$!";