From 3a5c3f0596398d64bb34498f40becbcd32ffa5de Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Wed, 17 Feb 2021 11:42:18 +0100 Subject: Consolidate error messages for consistency. --- Changelog | 1 + client | 8 ++-- lacme | 116 ++++++++++++++++++++++++++++----------------------------- lacme-accountd | 16 ++++---- 4 files changed, 71 insertions(+), 70 deletions(-) diff --git a/Changelog b/Changelog index ac8102c..cda155f 100644 --- a/Changelog +++ b/Changelog @@ -27,6 +27,7 @@ lacme (0.7.1) upstream; + Add support for TLS Feature extension from RFC 7633; this is mostly useful for OCSP Must-Staple. + client: use "lacme-client/$VERSION" as User-Agent header. + + Consolidate error messages for consistency. - lacme: delay webserver socket shutdown to after the process has terminated. - documentation: suggest to generate private key material with diff --git a/client b/client index e29d2a0..a5490f8 100755 --- a/client +++ b/client @@ -97,7 +97,7 @@ my $NONCE; my $CONFIG = do { my $conf = do { local $/ = undef; <$CONFFILE> }; - close $CONFFILE or die "Can't close: $!"; + close $CONFFILE or die "close: $!"; my $h = Config::Tiny::->read_string($conf) or die Config::Tiny::->errstr()."\n"; $h->{_} //= {}; $h->{client}->{$_} //= $h->{_}->{$_} foreach keys %{$h->{_}}; # add defaults @@ -303,11 +303,11 @@ elsif ($COMMAND eq 'newOrder') { # serve $keyAuthorization at http://$domain/.well-known/acme-challenge/$challenge->{token} if (sysopen(my $fh, $challenge->{token}, O_CREAT|O_EXCL|O_WRONLY, 0644)) { $fh->print($keyAuthorization); - $fh->close() or die "Can't close: $!"; + $fh->close() or die "close: $!"; } elsif ($! == EEXIST) { print STDERR "WARNING: File exists: $challenge->{token}\n"; } else { - die "Can't open $challenge->{token}: $!"; + die "open($challenge->{token}): $!"; } my $r = acme($challenge->{url}, {}); request_json_decode($r); @@ -378,7 +378,7 @@ elsif ($COMMAND eq 'newOrder') { elsif ($COMMAND eq 'revokeCert') { die if @ARGV; my $der = do { local $/ = undef; }; - close STDIN or die "Can't close: $!"; + close STDIN or die "close: $!"; # send a KID if the request is signed with the acccount key, otherwise send a JWK set_kid(0); diff --git a/lacme b/lacme index 33f947c..f0beac1 100755 --- a/lacme +++ b/lacme @@ -159,7 +159,7 @@ sub gen_csr(%) { $config->print("keyUsage = critical, $args{keyUsage}\n") if defined $args{keyUsage}; $config->print("subjectAltName = $args{subjectAltName}\n") if defined $args{subjectAltName}; $config->print("tlsfeature = $args{tlsfeature}\n") if defined $args{tlsfeature}; - $config->close() or die "Can't close: $!"; + $config->close() or die "close: $!"; my @args = (qw/-new -batch -key/, $args{'certificate-key'}); push @args, "-$args{hash}" if defined $args{hash}; @@ -167,20 +167,20 @@ sub gen_csr(%) { open my $fh, '-|', qw/openssl req -outform DER/, @args or die "fork: $!"; my $csr = do { local $/ = undef; <$fh> }; - close $fh or $! ? die "Can't close: $!" : return; + close $fh or $! ? die "close: $!" : return; if ($OPTS{debug}) { # print out the CSR in text form pipe my $rd, my $wd or die "pipe: $!"; my $pid = fork // die "fork: $!"; unless ($pid) { - open STDIN, '<&', $rd or die "Can't dup: $!"; - open STDOUT, '>&', \*STDERR or die "Can't dup: $!"; + open STDIN, '<&', $rd or die "dup: $!"; + open STDOUT, '>&', \*STDERR or die "dup: $!"; exec qw/openssl req -noout -text -inform DER/ or die; } - $rd->close() or die "Can't close: $!"; + $rd->close() or die "close: $!"; $wd->print($csr); - $wd->close() or die "Can't close: $!"; + $wd->close() or die "close: $!"; waitpid $pid => 0; die $? if $? > 0; @@ -220,21 +220,21 @@ sub drop_privileges($$$) { # set effective and real gid; also set the list of supplementary gids to that single gid if ($group ne '') { - my $gid = getgrnam($group) // die "Can't getgrnam($group): $!"; + my $gid = getgrnam($group) // die "getgrnam($group): $!"; $) = "$gid $gid"; - die "Can't setgroups: $!" if $@; - POSIX::setgid($gid) or die "Can't setgid: $!"; + die "setgroups: $!" if $@; + POSIX::setgid($gid) or die "setgid: $!"; die "Couldn't setgid/setguid" unless $( eq "$gid $gid" and $) eq "$gid $gid"; # safety check } # set effective and real uid if ($user ne '') { - my $uid = getpwnam($user) // die "Can't getpwnam($user): $!"; - POSIX::setuid($uid) or die "Can't setuid: $!"; + my $uid = getpwnam($user) // die "getpwnam($user): $!"; + POSIX::setuid($uid) or die "setuid: $!"; die "Couldn't setuid/seteuid" unless $< == $uid and $> == $uid; # safety check } - chdir $dir or die "Can't chdir to $dir: $!"; + chdir $dir or die "chdir($dir): $!"; } @@ -243,10 +243,10 @@ sub drop_privileges($$$) { # sub set_FD_CLOEXEC($$) { my ($fd, $set) = @_; - my $flags = fcntl($fd, F_GETFD, 0) or die "Can't fcntl F_GETFD: $!"; + my $flags = fcntl($fd, F_GETFD, 0) or die "fcntl F_GETFD: $!"; my $flags2 = $set ? ($flags | FD_CLOEXEC) : ($flags & ~FD_CLOEXEC); return if $flags == $flags2; - fcntl($fd, F_SETFD, $flags2) or die "Can't fcntl F_SETFD: $!"; + fcntl($fd, F_SETFD, $flags2) or die "fcntl F_SETFD: $!"; } @@ -321,10 +321,10 @@ sub spawn_webserver() { # create a temporary directory; give write access to the ACME client # and read access to the webserver my $tmpdir = File::Temp::->newdir(CLEANUP => 1, TMPDIR => 1) // die; - chmod 0755, $tmpdir or die "Can't chmod: $!"; + chmod 0755, $tmpdir or die "chmod: $!"; if ((my $username = $CONFIG->{client}->{user}) ne '') { - my $uid = getpwnam($username) // die "Can't getpwnam($username): $!"; - chown($uid, -1, $tmpdir) or die "Can't chown: $!"; + my $uid = getpwnam($username) // die "getpwnam($username): $!"; + chown($uid, -1, $tmpdir) or die "chown: $!"; } # create socket(s) and spawn webserver(s) @@ -353,7 +353,7 @@ sub spawn_webserver() { bind($sock, $sockaddr) or die "Couldn't bind to $p: $!"; push @CLEANUP, sub() { print STDERR "Unlinking $path\n" if $OPTS{debug}; - unlink $path or warn "Warning: Can't unlink $path: $!"; + unlink $path or warn "Warning: Couldn't unlink $path: $!"; }; umask($umask) // die "umask: $!"; } @@ -428,8 +428,8 @@ sub iptables_save($@) { my $pid = fork() // die "fork: $!"; unless ($pid) { - open STDIN, '<', '/dev/null' or die "Can't open /dev/null: $!"; - open STDOUT, '>&', $iptables_tmp or die "Can't dup: $!"; + open STDIN, '<', '/dev/null' or die "open(/dev/null): $!"; + open STDOUT, '>&', $iptables_tmp or die "dup: $!"; $| = 1; # turn off buffering for STDOUT exec "/usr/sbin/$iptables_bin-save", "-c" or die; } @@ -440,14 +440,14 @@ sub iptables_save($@) { # handle and not from the file. XXX if there was a way in Perl to # use open(2) with the O_TMPFILE flag we would use that to avoid # creating a file to start with - seek($iptables_tmp, SEEK_SET, 0) or die "Can't seek: $!"; + seek($iptables_tmp, SEEK_SET, 0) or die "seek: $!"; push @CLEANUP, sub() { print STDERR "[$$] Restoring $iptables_bin\n" if $OPTS{debug}; my $pid = fork() // die "fork: $!"; unless ($pid) { - open STDIN, '<&', $iptables_tmp or die "Can't dup: $!"; - open STDOUT, '>', '/dev/null' or die "Can't open /dev/null: $!"; + open STDIN, '<&', $iptables_tmp or die "dup: $!"; + open STDOUT, '>', '/dev/null' or die "open(/dev/null): $!"; exec "/usr/sbin/$iptables_bin-restore", "-c" or die; } waitpid $pid => 0; @@ -496,7 +496,7 @@ sub acme_client($@) { unless ($pid) { drop_privileges($accountd->{user}, $accountd->{group}, '/'); set_FD_CLOEXEC($s, 0); - $client->close() or die "Can't close: $!"; + $client->close() or die "close: $!"; my @cmd = ($accountd->{command}, '--conn-fd='.fileno($s)); push @cmd, '--config='.$accountd->{config} if defined $accountd->{config}; push @cmd, '--privkey='.$accountd->{privkey} if defined $accountd->{privkey}; @@ -505,7 +505,7 @@ sub acme_client($@) { exec { $cmd[0] } @cmd or die; } print STDERR "[$$] Forking lacme-accountd, child PID $pid\n" if $OPTS{debug}; - $s->close() or die "Can't close: $!"; + $s->close() or die "close: $!"; $cleanup = sub() { print STDERR "[$$] Shutting down lacme-accountd\n" if $OPTS{debug}; shutdown($client, SHUT_RDWR) or warn "shutdown: $!"; @@ -520,11 +520,11 @@ sub acme_client($@) { # ensure we're the only user with write access to the parent dir my $dirname = $sockname =~ s/[^\/]+$//r; - @stat = stat($dirname) or die "Can't stat $dirname: $!"; + @stat = stat($dirname) or die "stat($dirname): $!"; die "Error: insecure permissions on $dirname\n" if ($stat[2] & 0022) != 0; # ensure we're the only user with read/write access to the socket - @stat = stat($sockname) or die "Can't stat $sockname: $! (Is lacme-accountd running?)\n"; + @stat = stat($sockname) or die "Can't stat $sockname: $! (Is lacme-accountd running?)\n"; die "Error: insecure permissions on $sockname\n" if ($stat[2] & 0066) != 0; # connect(2) to the socket @@ -543,7 +543,7 @@ sub acme_client($@) { my $rv = spawn({in => $args->{in}, out => $args->{out}, child => sub() { drop_privileges($conf->{user}, $conf->{group}, $args->{chdir} // '/'); set_FD_CLOEXEC($_, 0) foreach ($CONFFILE, $client); - seek($CONFFILE, SEEK_SET, 0) or die "Can't seek: $!"; + seek($CONFFILE, SEEK_SET, 0) or die "seek: $!"; $ENV{DEBUG} = $OPTS{debug}; }}, $conf->{command}, $COMMAND, @fileno, @args); @@ -572,18 +572,18 @@ sub spawn($@) { # child $args->{child}->() if defined $args->{child}; if (defined $args->{in}) { - close $in_wd or die "Can't close: $!"; - open STDIN, '<&', $in_rd or die "Can't dup: $!"; + close $in_wd or die "close: $!"; + open STDIN, '<&', $in_rd or die "dup: $!"; } else { - open STDIN, '<', '/dev/null' or die "Can't open /dev/null: $!"; + open STDIN, '<', '/dev/null' or die "open(/dev/null): $!"; } if (!defined $args->{out}) { - open STDOUT, '>', '/dev/null' or die "Can't open /dev/null: $!"; + open STDOUT, '>', '/dev/null' or die "open(/dev/null): $!"; } elsif (ref $args->{out} ne 'GLOB') { - close $out_rd or die "Can't close: $!"; - open STDOUT, '>&', $out_wd or die "Can't dup: $!"; + close $out_rd or die "close: $!"; + open STDOUT, '>&', $out_wd or die "dup: $!"; } elsif (fileno(STDOUT) != fileno($args->{out})) { - open STDOUT, '>&', $args->{out} or die "Can't dup: $!"; + open STDOUT, '>&', $args->{out} or die "dup: $!"; } exec { $exec[0] } @exec or die; } @@ -595,18 +595,18 @@ sub spawn($@) { # parent print STDERR "[$$] Forking $exec[0], child PID $pid\n" if $OPTS{debug}; if (defined $args->{in}) { - $in_rd->close() or die "Can't close: $!"; + $in_rd->close() or die "close: $!"; $in_wd->print($args->{in}); - $in_wd->close() or die "Can't close: $!"; + $in_wd->close() or die "close: $!"; } if (defined $args->{out} and ref $args->{out} ne 'GLOB') { - $out_wd->close() or die "Can't close: $!"; + $out_wd->close() or die "close: $!"; if (ref $args->{out} eq 'CODE') { $args->{out}->($out_rd); } elsif (ref $args->{out} eq 'SCALAR') { ${$args->{out}} = do { local $/ = undef; $out_rd->getline() }; } - $out_rd->close() or die "Can't close: $!"; + $out_rd->close() or die "close: $!"; } waitpid $pid => 0; pop @CLEANUP; @@ -631,31 +631,31 @@ sub install_cert($$;$) { chmod(0644 &~ $umask, $fh) or die "chmod: $!"; if ($leafonly) { # keep only the leaf certificate - pipe my $rd, my $wd or die "Can't pipe: $!"; - my $pid = fork // die "Can't fork: $!"; + pipe my $rd, my $wd or die "pipe: $!"; + my $pid = fork // die "fork: $!"; unless ($pid) { - open STDIN, '<&', $rd or die "Can't dup: $!"; - open STDOUT, '>&', $fh or die "Can't dup: $!"; + open STDIN, '<&', $rd or die "dup: $!"; + open STDOUT, '>&', $fh or die "dup: $!"; exec qw/openssl x509 -outform PEM/ or die; } - $rd->close() or die "Can't close: $!"; + $rd->close() or die "close: $!"; $wd->print($chain); - $wd->close() or die "Can't close: $!"; + $wd->close() or die "close: $!"; waitpid $pid => 0; die $? if $? > 0; } else { - $fh->print($chain) or die "Can't print: $!"; + $fh->print($chain) or die "print: $!"; } - $fh->close() or die "Can't close: $!"; + $fh->close() or die "close: $!"; }; my $path = $fh->filename(); if ($@) { print STDERR "Unlinking $path\n" if $OPTS{debug}; - unlink $path or warn "Can't unlink $path: $!"; + unlink $path or warn "unlink($path): $!"; die $@; } - rename($path, $filename) or die "Can't rename $path to $filename: $!"; + rename($path, $filename) or die "rename($path, $filename): $!"; } @@ -687,7 +687,7 @@ elsif ($COMMAND eq 'newOrder' or $COMMAND eq 'new-cert') { unless ($conffile =~ s#/\z## or -d $conffile) { @filenames = ($conffile); } else { - opendir my $dh, $conffile or die "Can't opendir $conffile: $!\n"; + opendir my $dh, $conffile or die "opendir($conffile): $!\n"; while (readdir $dh) { if (/\.conf\z/) { push @filenames, "$conffile/$_"; @@ -723,7 +723,7 @@ elsif ($COMMAND eq 'newOrder' or $COMMAND eq 'new-cert') { if ($OPTS{debug}) { print STDERR "Configuration option for $s:\n"; - print " $_ = $conf->{$_}\n" foreach grep { defined $conf->{$_} } (sort keys %$conf); + print STDERR " $_ = $conf->{$_}\n" foreach grep { defined $conf->{$_} } (sort keys %$conf); } my $certtype = first { defined $conf->{$_} } qw/certificate certificate-chain/; @@ -809,16 +809,16 @@ elsif ($COMMAND eq 'newOrder' or $COMMAND eq 'new-cert') { if (defined $conf->{chown}) { my ($user, $group) = split /:/, $conf->{chown}, 2; - my $uid = getpwnam($user) // die "Can't getpwnam($user): $!"; - my $gid = defined $group ? (getgrnam($group) // die "Can't getgrnam($group): $!") : -1; + my $uid = getpwnam($user) // die "getpwnam($user): $!"; + my $gid = defined $group ? (getgrnam($group) // die "getgrnam($group): $!") : -1; foreach (grep defined, @$conf{qw/certificate certificate-chain/}) { - chown($uid, $gid, $_) or die "Can't chown: $!"; + chown($uid, $gid, $_) or die "chown: $!"; } } if (defined $conf->{chmod}) { my $mode = oct($conf->{chmod}) // die; foreach (grep defined, @$conf{qw/certificate certificate-chain/}) { - chmod($mode, $_) or die "Can't chown: $!"; + chmod($mode, $_) or die "chown: $!"; } } @@ -827,7 +827,7 @@ elsif ($COMMAND eq 'newOrder' or $COMMAND eq 'new-cert') { or die "fork: $!"; print $fh $x509; close $fh or die $! ? - "Can't close: $!" : + "close: $!" : "Error: x509(1ssl) exited with value ".($? >> 8)."\n"; if (defined $conf->{notify}) { @@ -857,7 +857,7 @@ elsif ($COMMAND eq 'revokeCert' or $COMMAND eq 'revoke-cert') { open my $fh, '-|', qw/openssl x509 -outform DER -in/, $filename or die "fork: $!"; my $der = do { local $/ = undef; <$fh> }; close $fh or die $! ? - "Can't close: $!" : + "close: $!" : "Error: x509(1ssl) exited with value ".($? >> 8)."\n"; my @certopts = join ',', qw/no_header no_version no_pubkey no_sigdump no_extensions/; @@ -865,7 +865,7 @@ elsif ($COMMAND eq 'revokeCert' or $COMMAND eq 'revoke-cert') { or die "fork: $!"; print $fh2 $der; close $fh2 or die $! ? - "Can't close: $!" : + "close: $!" : "Error: x509(1ssl) exited with value ".($? >> 8)."\n"; if (acme_client({in => $der})) { diff --git a/lacme-accountd b/lacme-accountd index 36e9d9f..c00530f 100755 --- a/lacme-accountd +++ b/lacme-accountd @@ -106,7 +106,7 @@ if ($OPTS{privkey} =~ /\A(file|gpg):(\p{Print}+)\z/) { my $str = do {local $/ = undef; <$fh>}; close $fh or die $! ? - "Can't close: $!" : + "close: $!" : "Error: $command[0] exited with value ".($? >> 8)."\n"; require 'Crypt/OpenSSL/RSA.pm'; @@ -140,7 +140,7 @@ my $JWK_STR = JSON::->new->encode($JWK); if (defined $OPTS{'conn-fd'}) { die "Invalid file descriptor" unless $OPTS{'conn-fd'} =~ /\A(\d+)\z/; # untaint and fdopen(3) our end of the socket pair - open ($S, '+<&=', $1+0) or die "fdopen $1: $!"; + open ($S, '+<&=', $1+0) or die "fdopen($1): $!"; } else { my $sockname = $OPTS{socket} // (defined $ENV{XDG_RUNTIME_DIR} ? "$ENV{XDG_RUNTIME_DIR}/S.lacme" : undef); die "Missing socket option\n" unless defined $sockname; @@ -148,7 +148,7 @@ if (defined $OPTS{'conn-fd'}) { # ensure we're the only user with write access to the parent dir my $dirname = $sockname =~ s/[^\/]+$//r; - my @stat = stat($dirname) or die "Can't stat $dirname: $!"; + my @stat = stat($dirname) or die "stat($dirname): $!"; die "Error: insecure permissions on $dirname\n" if ($stat[2] & 0022) != 0; my $umask = umask(0177) // die "umask: $!"; @@ -172,14 +172,14 @@ if (defined $OPTS{'conn-fd'}) { sub conn($;$) { my $conn = shift; my $count = shift; - $conn->printflush( "$PROTOCOL_VERSION OK", "\r\n", $JWK_STR, "\r\n" ); + $conn->printflush( "$PROTOCOL_VERSION OK", "\r\n", $JWK_STR, "\r\n" ) or warn "print: $!"; # sign whatever comes in while (defined (my $data = $conn->getline())) { $data =~ s/\r\n\z// or die; print STDERR "[$count] >>> Issuing SHA-256 signature for: $data\n" unless $OPTS{quiet}; my $sig = $SIGN->($data); - $conn->printflush( encode_base64url($sig), "\r\n" ); + $conn->printflush( encode_base64url($sig), "\r\n" ) or warn "print: $!"; } } @@ -195,7 +195,7 @@ if (defined $OPTS{'conn-fd'}) { print STDERR "[$count] >>> Accepted new connection\n" unless $OPTS{quiet}; conn($conn, $count); print STDERR "[$count] >>> Connection terminated\n" unless $OPTS{quiet}; - close $conn or warn "Can't close: $!"; + $conn->close() or warn "close: $!"; } } @@ -205,11 +205,11 @@ if (defined $OPTS{'conn-fd'}) { END { if (defined $SOCKNAME and -S $SOCKNAME) { print STDERR "Unlinking $SOCKNAME\n" if $OPTS{debug}; - unlink $SOCKNAME or print STDERR "Can't unlink $SOCKNAME: $!\n"; + unlink $SOCKNAME or print STDERR "Couldn't unlink $SOCKNAME: $!\n"; } if (defined $S) { print STDERR "Shutting down and closing lacme Account Key Manager\n" unless $OPTS{quiet}; shutdown($S, SHUT_RDWR) or warn "shutdown: $!"; - close $S or print STDERR "Can't close: $!\n"; + close $S or print STDERR "close: $!\n"; } } -- cgit v1.2.3