diff options
Diffstat (limited to 'client')
-rwxr-xr-x | client | 33 |
1 files changed, 22 insertions, 11 deletions
@@ -49,7 +49,7 @@ my $NAME = 'lacme-client'; use Errno 'EEXIST'; use Fcntl qw/O_CREAT O_EXCL O_WRONLY/; -use Digest::SHA qw/sha256 sha256_hex/; +use Digest::SHA 'sha256'; use MIME::Base64 qw/encode_base64 encode_base64url/; use Date::Parse (); @@ -70,24 +70,34 @@ open (my $CONFFILE, '<&=', $1+0) or die "fdopen $1: $!"; (shift @ARGV // die) =~ /\A(\d+)\z/ or die; open (my $S, '+<&=', $1+0) or die "fdopen $1: $!"; +# JSON keys need to be sorted lexicographically (for instance in the thumbprint) +sub json() { JSON::->new->utf8->canonical(); } + ############################################################################# # Read the protocol version and JSON Web Key (RFC 7517) from the # lacme-accountd socket # + +my ($JWK, $JWK_thumbprint, $ALG, $KID); do { my $greeting = $S->getline(); die "Error: Invalid client version\n" unless defined $greeting and - $greeting =~ /\A(\d+) OK(?:.*)\r\n\z/ and $1 == $PROTOCOL_VERSION; + $greeting =~ /\A(\d+) OK(?: (.*))?\r\n\z/ and $1 == $PROTOCOL_VERSION; + if (defined (my $extra = $2)) { + my $h = eval { JSON::->new->decode($extra) }; + if ($@ or !defined $h) { + print STDERR "WARN: Ignoring extra greeting data from accountd \"$extra\"\n"; + } else { + print STDERR "Received extra greeting data from accountd: $extra\n" if $ENV{DEBUG}; + ($JWK_thumbprint, $ALG) = @$h{qw/jwk-thumbprint alg/}; + } + } + my $jwk_str = $S->getline() // die "ERROR: No JWK from lacme-accountd\n"; + $JWK = JSON::->new->decode($jwk_str); + $JWK_thumbprint //= encode_base64url(sha256(json()->encode($JWK))); # SHA-256 is hardcoded, see RFC 8555 sec. 8.1 + $ALG //= "RS256"; }; -my $JWK = JSON::->new->decode($S->getline()); -my $KID; - -# JSON keys need to be sorted lexicographically (for instance in the thumbprint) -sub json() { JSON::->new->utf8->canonical(); } - -my $JWK_thumbprint = encode_base64url(sha256(json()->encode($JWK))); -my $NONCE; ############################################################################# @@ -111,6 +121,7 @@ my $UA = do { LWP::UserAgent::->new( agent => "$NAME/$VERSION", ssl_opts => \%ssl_opts ); } // die "Can't create LWP::UserAgent object"; $UA->default_header( 'Accept-Language' => 'en' ); +my $NONCE; ############################################################################# @@ -192,7 +203,7 @@ sub acme($;$) { die "Missing nonce\n" unless defined $NONCE; # Produce the JSON Web Signature: RFC 7515 section 5 - my %header = ( alg => 'RS256', nonce => $NONCE, url => $uri ); + my %header = ( alg => $ALG, nonce => $NONCE, url => $uri ); defined $KID ? ($header{kid} = $KID) : ($header{jwk} = $JWK); my $payload = defined $h ? encode_base64url(json()->encode($h)) : ""; my $protected = encode_base64url(json()->encode(\%header)); |