#!/usr/bin/perl
#   $Id: keysockmap,v 1.2 2015/08/28 12:38:53 az Exp $
# 
#   File:		keysockmap
#   Date:		28 Aug 2015 17:04:35
#   Author:		Alexander Zangerl <az@snafu.priv.at>
# 
#   Abstract:
#	socket map protocol wrapper around keyctl
# 	this is for postfix and its socketmap table,
#	so that smtp auth credentials don't have to be hardcoded anymore :-)
#	see http://www.postfix.org/socketmap_table.5.html
#
use strict;
use IO::Socket::UNIX;
use Getopt::Std;
use File::Basename;

my $socketname = "/tmp/keysockmap";

my $usage = "Usage: ".basename($0)." [-g group] [-o name] [-s path] [ -p prefix] \n
-g: socket rw for this group
-o: answer only for this map
-s: use this socketpath (instead of default $socketname)
-p prefix for returning prefix:keydata\n\n";

my %opts;
die $usage if (!getopts("g:o:s:p:", \%opts) or @ARGV);

$socketname = $opts{s} if $opts{s};

# unix domain socket files can't exist at creation time
unlink($socketname) if (-e $socketname);

my $sfd = IO::Socket::UNIX->new(Type => SOCK_STREAM,
				Local => $socketname,
				Listen => 1);

if ($opts{g})
{
    my $gid = getgrnam($opts{g});
    chown(-1, $gid, $socketname);
}
chmod(0660, $socketname);

while (my $c = $sfd->accept)
{
    my $cmd;
    recv($c, $cmd, 10000, 0);
    
    my $response = "PERM invalid request";
    
    if ($cmd =~ /^\d+:(\S+) (\S+),$/)
    {
	my ($mapname,$keyname) = ($1, lc($2));
	
	# check if allowed to serve?
	if ($opts{o} and $mapname ne $opts{o})
	{
	    $response = "PERM not allowed to access this map";
	}
	else
	{
	    $keyname =~ s/[^a-z0-9\._@-]//g; # cleanup
	    # now request and pull the key
	    
	    my $kid = `keyctl request2 user $keyname $keyname \@u 2>/dev/null`;
	    my $res = $? >> 8;
	    
	    chomp($kid);
	    if ($res or !$kid)
	    {
		$response = "TEMP keytcl request2 failed";
	    }
	    else
	    {
		my $keydata = `keyctl pipe $kid 2>/dev/null`;
		$res = $? >> 8;
		if ($res)
		{
		    $response = "TEMP keyctl pipe failed";
		}
		else
		{
		    $response = "OK ". ($opts{p}? ($opts{p}.":".$keydata) : $keydata);
		}
	    }
	}
    }

    send($c, sprintf("%d:%s,", 
		     length($response), 
		     $response), 0);
    shutdown($c, 2);
}

exit(0);   



