Sendmail wrapper
authorHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
Mon, 28 Nov 2016 08:57:02 +0000 (09:57 +0100)
committerHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
Fri, 24 Mar 2017 21:50:18 +0000 (22:50 +0100)
heiko/README [new file with mode: 0755]
heiko/sendmail [new file with mode: 0755]

diff --git a/heiko/README b/heiko/README
new file mode 100755 (executable)
index 0000000..a8311eb
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/sh
+# This is the reproducer. Call it as a shell script.
+# To test the sendmail wrapper call it as
+# ./README <wrapper>
+
+set -e
+
+user=${USER-$LOGNAME}
+test -z "$user" && user=$(id -un)
+
+sendmail=${1:-/usr/sbin/sendmail}
+
+
+exec sudo capsh --secbits=0x01 -- -c "date | /usr/sbin/sendmail $user"
diff --git a/heiko/sendmail b/heiko/sendmail
new file mode 100755 (executable)
index 0000000..b39cc76
--- /dev/null
@@ -0,0 +1,98 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+use feature qw'say';
+use IO::Socket::INET;
+use Pod::Usage;
+use Getopt::Long;
+use Sys::Hostname;
+
+exit main() unless caller;
+
+package X::IO::Socket::INET {
+    use parent 'IO::Socket::INET';
+    use strict;
+    use warnings;
+
+    sub new {
+        my $class = ref $_[0] ? ref shift : shift;
+        my %opt = @_;
+        {
+            no strict 'refs';
+            *{__PACKAGE__ .'::debug'} = delete $opt{Debug} ? sub { say STDERR @_ } : sub {};
+        }
+        return $class->SUPER::new(%opt);
+    }
+
+    sub say {
+        my $self = shift;
+        debug("-> @_");
+        say {$self} @_;
+    }
+
+    sub expect {
+        my $self = shift;
+        my $pattern = shift;
+        $pattern = qr/^$pattern/ unless ref $pattern;
+        my @got;
+        while (<$self>) {
+            chomp;
+            push @got, $_;
+            debug("<- $_");
+            die "$0: unexpected\n"
+                if not /$pattern/;
+            /^\d+-/ and next;
+            last;
+        }
+        return @got;
+    }
+    1;
+}
+
+sub main {
+
+    my @rcpts;
+    my ($opt_sendmail_t, $opt_from, $opt_debug);
+
+    my $host = hostname or die "$0: Can't get local hostname\n";
+    my $user = getpwuid($<) or die "$0: Can't get user name\n";
+    my $from = "$user\@$host";
+
+    GetOptions(
+        'debug' => \$opt_debug,
+        't'     => \$opt_sendmail_t,
+        'f=s'   => \$opt_from,
+    ) or pod2usage;
+    @rcpts = @ARGV;
+
+    my $socket = X::IO::Socket::INET->new(
+        PeerAddr => 'localhost',
+        PeerPort => 'smtp',
+        Debug => $opt_debug,
+    ) or die "$0: socket: $!\n";
+
+    $socket->expect(2);
+    $socket->say('EHLO ' . hostname());
+
+    $socket->expect(2);
+    $socket->say("MAIL FROM:<$from>");
+
+    $socket->expect(2);
+
+
+    return 0;
+}
+
+__END__
+
+=head1 NAME
+
+ sendmail - sendmail drop in
+
+=head1 SYNOPSIS
+
+ sendmail [-f <sender>] <recipient>...
+ sendmail -t
+
+=cut