From 42a8f9813716ed3495b6f49edea429b127eef0f0 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Thu, 18 Feb 2021 00:49:46 +0100 Subject: accountd: replace internal option --conn-fd=FD with flag --stdio. Using stdin/stdout makes it possible to tunnel the accountd connection through ssh. --- Changelog | 7 ++++++- lacme | 6 ++++-- lacme-accountd | 27 +++++++++++---------------- lacme.8.md | 4 +++- 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/Changelog b/Changelog index 68a1f83..4d18b38 100644 --- a/Changelog +++ b/Changelog @@ -23,7 +23,9 @@ lacme (0.7.1) upstream; ./lacme.conf resp. ./lacme-accountd.conf as default location for the configuration file. * The client, webserver, and accountd commands are now split on - whitespace. This doesn't change the default behavior. + whitespace. This doesn't change the default behavior but allows + using `ssh -T lacme@account.example.net lacme-accountd` to spawn a + remote lacme-accountd server for instance. + Improve nginx/apache2 snippets for direct serving of challenge files (with the new 'challenge-directory' logic symlinks can be disabled). + Split Nginx and Apapche2 static configuration snippets into seperate @@ -36,6 +38,9 @@ lacme (0.7.1) upstream; + Consolidate error messages for consistency. + Sanitize environment when spawning the lacme client, webserver and accountd. + + accountd: replace internal option --conn-fd=FD with flag --stdio. + Using stdin/stdout makes it possible to tunnel the accountd + connection through ssh. - lacme: delay webserver socket shutdown to after the process has terminated. - documentation: suggest to generate private key material with diff --git a/lacme b/lacme index 019a5e7..3d3657f 100755 --- a/lacme +++ b/lacme @@ -504,10 +504,12 @@ sub acme_client($@) { my $pid = fork() // "fork: $!"; unless ($pid) { drop_privileges($accountd->{user}, $accountd->{group}, '/'); - set_FD_CLOEXEC($s, 0); + set_FD_CLOEXEC($s, 1); $client->close() or die "close: $!"; + open STDIN, '<&', $s or die "dup: $!"; + open STDOUT, '>&', $s or die "dup: $!"; my ($cmd, @args) = split(/\s+/, $accountd->{command}) or die "Empty accountd command\n"; - push @args, '--conn-fd='.fileno($s); + push @args, '--stdio'; push @args, '--config='.$accountd->{config} if defined $accountd->{config}; push @args, '--privkey='.$accountd->{privkey} if defined $accountd->{privkey}; push @args, '--quiet' unless lc $accountd->{quiet} eq 'no'; diff --git a/lacme-accountd b/lacme-accountd index c00530f..7b9b1ff 100755 --- a/lacme-accountd +++ b/lacme-accountd @@ -60,7 +60,7 @@ sub usage(;$$) { } exit $rv; } -usage(1) unless GetOptions(\%OPTS, qw/config=s privkey=s socket=s conn-fd=i quiet|q debug help|h/); +usage(1) unless GetOptions(\%OPTS, qw/config=s privkey=s socket=s stdio quiet|q debug help|h/); usage(0) if $OPTS{help}; do { @@ -137,11 +137,7 @@ my $JWK_STR = JSON::->new->encode($JWK); # to support the abstract namespace.) The downside is that we have to # delete the file manually. # -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): $!"; -} else { +unless (defined $OPTS{stdio}) { my $sockname = $OPTS{socket} // (defined $ENV{XDG_RUNTIME_DIR} ? "$ENV{XDG_RUNTIME_DIR}/S.lacme" : undef); die "Missing socket option\n" unless defined $sockname; $sockname = $sockname =~ /\A(\p{Print}+)\z/ ? $1 : die "Invalid socket name\n"; # untaint $sockname @@ -169,22 +165,21 @@ if (defined $OPTS{'conn-fd'}) { # For each new connection, send the protocol version and the account key's # public parameters, then sign whatever comes in # -sub conn($;$) { - my $conn = shift; - my $count = shift; - $conn->printflush( "$PROTOCOL_VERSION OK", "\r\n", $JWK_STR, "\r\n" ) or warn "print: $!"; +sub conn($$;$) { + my ($in, $out, $id) = @_; + $out->printflush( "$PROTOCOL_VERSION OK", "\r\n", $JWK_STR, "\r\n" ) or warn "print: $!"; # sign whatever comes in - while (defined (my $data = $conn->getline())) { + while (defined (my $data = $in->getline())) { $data =~ s/\r\n\z// or die; - print STDERR "[$count] >>> Issuing SHA-256 signature for: $data\n" unless $OPTS{quiet}; + print STDERR "[$id] >>> Issuing SHA-256 signature for: $data\n" unless $OPTS{quiet}; my $sig = $SIGN->($data); - $conn->printflush( encode_base64url($sig), "\r\n" ) or warn "print: $!"; + $out->printflush( encode_base64url($sig), "\r\n" ) or warn "print: $!"; } } -if (defined $OPTS{'conn-fd'}) { - conn($S, $$); +if (defined $OPTS{stdio}) { + conn(\*STDIN, \*STDOUT, $$); } else { $SIG{PIPE} = 'IGNORE'; # ignore broken pipes for (my $count = 0;; $count++) { @@ -193,7 +188,7 @@ if (defined $OPTS{'conn-fd'}) { die "accept: $!"; }; print STDERR "[$count] >>> Accepted new connection\n" unless $OPTS{quiet}; - conn($conn, $count); + conn($conn, $conn, $count); print STDERR "[$count] >>> Connection terminated\n" unless $OPTS{quiet}; $conn->close() or warn "close: $!"; } diff --git a/lacme.8.md b/lacme.8.md index 69870c4..c354c1a 100644 --- a/lacme.8.md +++ b/lacme.8.md @@ -308,7 +308,9 @@ UNIX-domain socket. the first item being the command to execute, the second its first argument etc. (Note that `lacme` appends more arguments when executing the command internally.) - Default: `@@bindir@@/lacme-accountd`. + Use for instance `ssh -T lacme@account.example.net lacme-accountd` + in order to spawn a remote [`lacme-accountd`(1)] server. Default: + `@@bindir@@/lacme-accountd`. *config* -- cgit v1.2.3