diff options
author | Guilhem Moulin <guilhem@debian.org> | 2024-06-13 17:54:21 +0200 |
---|---|---|
committer | Guilhem Moulin <guilhem@debian.org> | 2024-06-13 17:54:21 +0200 |
commit | 31168af791066a43adf6a52d2f51da6185bab15e (patch) | |
tree | 134768f15684231732ef2640e5a60a630c5886ea /lacme | |
parent | d531c00ae1c422b3f0948d297098722fb448edb5 (diff) | |
parent | ce6a95d172dbefd0e310c46e0a0d9c56d19e34ca (diff) |
Merge tag 'v0.8.3' into debian/latest
Release version 0.8.3
Diffstat (limited to 'lacme')
-rwxr-xr-x | lacme | 42 |
1 files changed, 29 insertions, 13 deletions
@@ -22,7 +22,7 @@ use v5.14.2; use strict; use warnings; -our $VERSION = '0.8.2'; +our $VERSION = '0.8.3'; my $NAME = 'lacme'; use Errno 'EINTR'; @@ -184,7 +184,7 @@ sub gen_csr(%) { push @args, "-$args{hash}" if defined $args{hash}; push @args, '-subj', $args{subject}, '-config', $config->filename(), qw/-reqexts v3_req/; - open my $fh, '-|', qw/openssl req -outform DER/, @args or die "fork: $!"; + open my $fh, '-|', qw{openssl req -outform DER}, @args or die "fork: $!"; my $csr = do { local $/ = undef; <$fh> }; close $fh or $! ? die "close: $!" : return; @@ -195,7 +195,7 @@ sub gen_csr(%) { unless ($pid) { open STDIN, '<&', $rd or die "dup: $!"; open STDOUT, '>&', \*STDERR or die "dup: $!"; - exec qw/openssl req -noout -text -inform DER/ or die; + exec qw{openssl req -in /dev/stdin -inform DER -noout -text} or die; } $rd->close() or die "close: $!"; $wd->print($csr); @@ -822,28 +822,38 @@ elsif ($COMMAND eq 'newOrder' or $COMMAND eq 'new-cert') { next; } - my $cert; + my @chain; eval { my $mem = Net::SSLeay::BIO_s_mem() or die; my $bio = Net::SSLeay::BIO_new($mem) or die; die "incomplete write" unless Net::SSLeay::BIO_write($bio, $chain) == length($chain); - my $x509 = Net::SSLeay::PEM_read_bio_X509($bio); - $cert = Net::SSLeay::PEM_get_string_X509($x509); + + my $sk_x509_info = Net::SSLeay::PEM_X509_INFO_read_bio($bio); + + my $n = Net::SSLeay::sk_X509_INFO_num($sk_x509_info); + for (my $i = 0; $i < $n; $i++) { + my $x509_info = Net::SSLeay::sk_X509_INFO_value($sk_x509_info, $i); + my $x509 = Net::SSLeay::P_X509_INFO_get_x509($x509_info); + my $cert = Net::SSLeay::PEM_get_string_X509($x509); + push @chain, $cert; + } + Net::SSLeay::BIO_free($bio) or die; }; - if ($@) { + if ($@ or !@chain) { print STDERR "[$s] Error: Received bogus X.509 certificate from ACME server!\n"; $rv = 1; next; } + my $cert = shift @chain; # leave only the intermediate in @chain # extract pubkeys from CSR and cert, and ensure they match # XXX would be nice to use X509_get_X509_PUBKEY and X509_REQ_get_X509_PUBKEY here, # or EVP_PKEY_cmp(), but unfortunately Net::SSLeay 1.88 doesn't support these my ($cert_pubkey, $csr_pubkey); - spawn({in => $cert, out => \$cert_pubkey}, qw/openssl x509 -inform PEM -noout -pubkey/); - spawn({in => $csr, out => \$csr_pubkey }, qw/openssl req -inform DER -noout -pubkey/); + spawn({in => $cert, out => \$cert_pubkey}, qw{openssl x509 -in /dev/stdin -inform PEM -noout -pubkey}); + spawn({in => $csr, out => \$csr_pubkey }, qw{openssl req -in /dev/stdin -inform DER -noout -pubkey}); unless (defined $cert_pubkey and defined $csr_pubkey and $cert_pubkey eq $csr_pubkey) { print STDERR "[$s] Error: Received bogus X.509 certificate from ACME server!\n"; $rv = 1; @@ -852,9 +862,15 @@ elsif ($COMMAND eq 'newOrder' or $COMMAND eq 'new-cert') { # verify certificate validity against the CA bundle if ((my $CAfile = $conf->{CAfile} // '@@datadir@@/lacme/ca-certificates.crt') ne '') { + my $chain_tmp = File::Temp::->new(SUFFIX => '.crt', TMPDIR => 1) // die; + $chain_tmp->say($_) foreach @chain; + $chain_tmp->flush(); + my %args = (in => $cert); $args{out} = \*STDERR if $OPTS{debug}; - my @options = ('-trusted', $CAfile, '-purpose', 'sslserver', '-x509_strict'); + my @options = ('-trusted', $CAfile); + push @options, '-untrusted', $chain_tmp->filename() if @chain; + push @options, ('-purpose', 'sslserver', '-x509_strict'); push @options, '-show_chain' if $OPTS{debug}; if (spawn(\%args, 'openssl', 'verify', @options)) { print STDERR "[$s] Error: Received invalid X.509 certificate from ACME server!\n"; @@ -878,7 +894,7 @@ elsif ($COMMAND eq 'newOrder' or $COMMAND eq 'new-cert') { } my @certopts = join ',', qw/no_header no_version no_pubkey no_sigdump/; - open my $fh, '|-', qw/openssl x509 -noout -fingerprint -sha256 -text -certopt/, @certopts + open my $fh, '|-', qw{openssl x509 -in /dev/stdin -noout -fingerprint -sha256 -text -certopt}, @certopts or die "fork: $!"; print $fh $cert; close $fh or die $! ? @@ -909,14 +925,14 @@ elsif ($COMMAND eq 'revokeCert' or $COMMAND eq 'revoke-cert') { print STDERR "Revoking $filename\n"; # conversion PEM -> DER - open my $fh, '-|', qw/openssl x509 -outform DER -in/, $filename or die "fork: $!"; + open my $fh, '-|', qw{openssl x509 -in}, $filename, qw{-outform DER} or die "fork: $!"; my $der = do { local $/ = undef; <$fh> }; close $fh or die $! ? "close: $!" : "Error: x509(1ssl) exited with value ".($? >> 8)."\n"; my @certopts = join ',', qw/no_header no_version no_pubkey no_sigdump no_extensions/; - open my $fh2, '|-', qw/openssl x509 -inform DER -noout -fingerprint -sha256 -text -certopt/, @certopts + open my $fh2, '|-', qw{openssl x509 -in /dev/stdin -inform DER -noout -fingerprint -sha256 -text -certopt}, @certopts or die "fork: $!"; print $fh2 $der; close $fh2 or die $! ? |