aboutsummaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rwxr-xr-xclient33
1 files changed, 22 insertions, 11 deletions
diff --git a/client b/client
index e62541c..7a63259 100755
--- a/client
+++ b/client
@@ -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));