From 401cf93da4b4afc20498f6b5729567c89e8f6f5a Mon Sep 17 00:00:00 2001 From: Florian Pritz Date: Mon, 5 Nov 2018 12:04:16 +0100 Subject: initial commit Signed-off-by: Florian Pritz --- alass | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 alass diff --git a/alass b/alass new file mode 100644 index 0000000..a1fe986 --- /dev/null +++ b/alass @@ -0,0 +1,86 @@ +#!/usr/bin/perl -T + +use strictures; + +use autodie; +use Function::Parameters; +use Path::Tiny; +use Sys::Syslog qw(:standard :macros); + +=head1 SYNOPSIS + +[cat \$file | ] SSH_ORIGINAL_COMMAND="" alass + +commands: + sign Request a signature for the file data + +=head1 DESCRIPTION + +The Arch Linux Automated Signing Server (ALASS) is supposed to be called via an +SSH forced command. It parses SSH_ORIGINAL_COMMAND, recieves file data via +STDIN and returns a signature for the file via STDOUT if the command and file +data pass various security checks. + +=cut + +fun main() { + my $prog_name = 'alass'; + + my $command = $ENV{SSH_ORIGINAL_COMMAND}; + + # reset PATH since taint mode requires a secure path + $ENV{PATH} = "/usr/local/sbin:/usr/local/bin:/usr/bin"; + + openlog($prog_name, "ndelay,pid", "local0"); + syslog(LOG_NOTICE, "Signing script called with arguments: %s", $command); + + # when this variable goes out of scope the temp dir is removed! + my $tmpdir = Path::Tiny->tempdir(); + my $input_file = $tmpdir->child("input"); + + copy_stdin_to_file($input_file); + + if (allowed_to_sign($command, $input_file)) { + syslog(LOG_NOTICE, "Signing request granted by security checks"); + my $signature = get_signature($input_file); + print $signature; + } else { + syslog(LOG_ERR, "Sign requst failed security checks"); + exit 1; + } +} + +fun copy_stdin_to_file($destination) { + my $data; + my $bufsize = 4096; + my $total_size = 0; + while (my $read_size = sysread(STDIN, $data, $bufsize)) { + $destination->append_raw($data); + $total_size += $read_size; + } + syslog(LOG_NOTICE, "Input file has %d bytes", $total_size); +} + +fun allowed_to_sign($command, $input_file) { + if ($command =~ m/^sign (?[^ ]+)/) { + my $filename = $+{filename}; + if ($filename =~ m/\.pkg\.tar\.xz$/) { + return 1; + } + } + return 0; +} + +fun get_signature($input_file) { + execute_command([qw(gpg --detach-sign --use-agent --no-armor), $input_file->stringify]); + return $input_file->sibling("input.sig")->slurp_raw(); +} + +fun execute_command($command) { + syslog(LOG_NOTICE, "Executing command: %s", join(" ", @$command)); + system(@$command); +} + + +main(); + -- cgit v1.2.3-24-g4f1b