aboutsummaryrefslogtreecommitdiffstats
path: root/lacme-accountd
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem@fripost.org>2021-02-18 21:07:01 +0100
committerGuilhem Moulin <guilhem@fripost.org>2021-02-20 22:13:41 +0100
commit0ef94d85e58497dcb2c4c954cadcac918032467a (patch)
tree9ff32832dc06f0c8b17ae19c9e9fbcd46e48d2ba /lacme-accountd
parent4a502836164821b9faa56d363c8fb116ce032321 (diff)
Add %-specifiers support.
lacme(8): for --config=, --socket=, --config-certs= (and ‘socket’/ ‘config-certs’/‘challenge-directory’ configuration options *before* privilege drop; and for the [accountd] section ‘command’/‘config’ configuration options *after* privilege drop). lacme-accountd(1): for --config=, --socket= and --privkey= (and ‘socket’/‘privkey’ configuration options). This also changes the default configuration file location. lacme(8) and lacme-accountd(1) now respectively use /etc/lacme/lacme.conf resp. /etc/lacme/lacme-accountd.conf when running as root, and $XDG_CONFIG_HOME/lacme/lacme.conf resp. $XDG_CONFIG_HOME/lacme/lacme-accountd.conf when running as a normal user. There is no fallback to /etc anymore.
Diffstat (limited to 'lacme-accountd')
-rwxr-xr-xlacme-accountd35
1 files changed, 27 insertions, 8 deletions
diff --git a/lacme-accountd b/lacme-accountd
index b9a6e33..e170637 100755
--- a/lacme-accountd
+++ b/lacme-accountd
@@ -30,7 +30,6 @@ my $NAME = 'lacme-accountd';
use Errno 'EINTR';
use File::Basename 'dirname';
use Getopt::Long qw/:config posix_default no_ignore_case gnu_getopt auto_version/;
-use List::Util 'first';
use MIME::Base64 'encode_base64url';
use Socket qw/PF_UNIX SOCK_STREAM SHUT_RDWR/;
@@ -64,11 +63,32 @@ sub usage(;$$) {
usage(1) unless GetOptions(\%OPTS, qw/config=s privkey=s socket=s stdio quiet|q debug help|h/);
usage(0) if $OPTS{help};
+sub env_fallback($$) {
+ my $v = $ENV{ shift() };
+ return (defined $v and $v ne "") ? $v : shift;
+}
+sub spec_expand($) {
+ my $str = shift;
+ $str =~ s#%(.)# my $x =
+ $1 eq "C" ? ($< == 0 ? "@@localstatedir@@/cache" : env_fallback(XDG_CACHE_HOME => "$ENV{HOME}/.cache"))
+ : $1 eq "E" ? ($< == 0 ? "@@sysconfdir@@" : env_fallback(XDG_CONFIG_HOME => "$ENV{HOME}/.config"))
+ : $1 eq "g" ? (getgrgid((split /\s/,$()[0]))[0]
+ : $1 eq "G" ? $( =~ s/\s.*//r
+ : $1 eq "h" ? (getpwuid($<))[7]
+ : $1 eq "u" ? (getpwuid($<))[0]
+ : $1 eq "U" ? $<
+ : $1 eq "t" ? ($< == 0 ? "@@runstatedir@@" : $ENV{XDG_RUNTIME_DIR})
+ : $1 eq "T" ? env_fallback(TMPDIR => "/tmp")
+ : $1 eq "%" ? "%"
+ : die "Error: \"$str\" has unknown specifier %$1\n";
+ die "Error: undefined expansion %$1 in \"$str\"\n" unless defined $x;
+ $x;
+ #ge;
+ return $str;
+}
+
do {
- my $conffile = $OPTS{config} // first { -f $_ }
- ( ($ENV{XDG_CONFIG_HOME} // "$ENV{HOME}/.config") . "/lacme/$NAME.conf"
- , "@@sysconfdir@@/lacme/$NAME.conf"
- );
+ my $conffile = spec_expand($OPTS{config} // "%E/lacme/$NAME.conf");
if (defined $OPTS{config} or -e $conffile) {
print STDERR "Using configuration file: $conffile\n" if $OPTS{debug};
@@ -94,7 +114,7 @@ do {
#
my ($JWK, $SIGN);
if ($OPTS{privkey} =~ /\A(file|gpg):(\p{Print}+)\z/) {
- my ($method, $filename) = ($1,$2);
+ my ($method, $filename) = ($1, spec_expand($2));
my ($fh, @command);
if ($method eq 'file') {
# generate with `openssl genpkey -algorithm RSA`
@@ -142,8 +162,7 @@ my $JWK_STR = JSON::->new->encode($JWK);
# delete the file manually.
#
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;
+ my $sockname = spec_expand($OPTS{socket} // '%t/S.lacme');
$sockname = $sockname =~ /\A(\p{Print}+)\z/ ? $1 : die "Invalid socket name\n"; # untaint $sockname
# ensure we're the only user with write access to the parent dir