#!/usr/local/bin/perl
# $Id: testauth_rcv_pgp,v 1.1 1999/10/24 19:47:54 papowell Exp papowell $
# 
# LPRng authorization test program
# 
#   - used to receive and decode remote authenticated
#     information
#   command line:
#   /filter -S -P printer -n server_id -A authtype -R remote_id -Ttempfile
#   The server_id and remote_id are URL escaped values
#   tempfile is a path to a tempfile for working information
# 
#    FD Options Purpose
#    0  R/W     socket connection to remote host (R/W)
#    1  W       for status report about authentication
#    2  W       error log
#    3  R       for server status to be sent to client
# 
#   Actions:
# 1. read a single line from FD 0.  This will be the number
#    of bytes to transfer.
# 2. read the specified number of bytes into tempfile
# 3. Run whatever consistency checks are needed,  and then
#    decode the transferred file.
# 4. The transferred file has a header, blank line, and body.
#    write the authentication information to FD 1.
#    The ID of the sender (from) is sent as:
#    from=xxxx   where xxx is the appropriate value.
# 5. close FD 1,  and read information from FD 3 into the tempfile.
# 6. encode the tempfile,  and then transfer to the remote
#    host over FD 0.

use Getopt::Std;
use FileHandle;
use Shell;
use URI::Escape;

my($debug, %args,$key,$value,$v, $tempfile, $temp, $socket,
	$buf, $done, $line, $len, $n, $r, $test, @lines, $from,
	$user, $dir, $pwfile );

$|= 1;
$debug = 0;
$test = 0;

getopts("CFSD:P:n:A:R:T:",\%args);

if( defined($line = $args{'D'}) ){
	$debug = 1 if( $line =~ /debug/ );
	$test = 1 if( $line =~ /test/ );
}

if( $debug ){
	$v = "$0";
	foreach $key (sort keys %args){
		$v .= " $key=$args{$key}"
	}
	print STDERR $v . "\n";
	print STDERR "ARGV @ARGV\n";
	for $i (sort keys %ENV ){
		print STDERR "ENV $i=$ENV{$i}\n";
	}
}

$temp = new FileHandle;
$socket = new FileHandle;

$tempfile = $args{'T'};
if( not $tempfile ){
	warn "missing tempfile\n";
	exit(1);
}

$user = uri_unescape($args{'n'});
if( not $user ){
	warn "missing user\n";
	exit(1);
}

goto done if( $test );

$temp->open(">$tempfile") or die "cannot open '$tempfile'";
$socket->open("<&0") or die "cannot open fd 0";
defined( $len = <$socket> ) or die "cannot read from fd 0";

while( $len > 0 ){
	$n = $len;
	$n = 10240 if( $n > 10240 );
	$r = read( $socket, $buf, $n );
	$r == $n or die "failed read from fd 0";
	print STDERR "FILE '$buf'\n" if $debug;
	print $temp $buf;
	$len -= $n;
}

$temp->close();
$socket->close();

print STDERR "finished transfer\n" if( $debug );

done:

#  The following illustrates how you can use pgp to decode the
#  transferred file.  Replace with your own stuff
#  Note: the PGPPASSFD is a safe way to give PGP the passphrase

$dir = (getpwnam($user))[7];
if( not defined($dir) ){
	warn "user does not have home dir\n";
	exit(1);
}
$pwfile = "$dir/.pgp/serverkey";
$temp ->open("<$pwfile") or die "cannot open '$pwfile'";

print STDERR "server key '" . `cat $pwfile ` . "\n" if $debug;
$ENV{'PGPPASSFD'} = 5;
$line = "pgp +force +batch $tempfile -u $args{'n'} -o $tempfile 2>&1 5<$pwfile";

print STDERR "$line\n" if $debug;
eval{ @lines = `$line`; };
if( $@ ){
	print STDERR "eval error '$@'\n";
	exit(1);
} elsif( $? ){
	$line = join( '', @lines);
	chomp($line);
	$i = $? >> 8;
	print STDERR "pgp error '$line'\n";
	exit(1);
}

for( $i = 0; $i <@lines; ++$i ){
	$line = $lines[$i];
	chomp $line;
	print STDERR " [$i] = '$line'\n" if $debug;
	if( $line =~ /^Good signature[^"]*"([^"]*)"/ ){
		$from = $1;
	}
}

$temp->open("<$tempfile") or die "cannot open '$tempfile'";

$done = 0;
while( not $done and defined( $line = <$temp> ) ){
	chomp($line);
	if( $line ){
		print STDERR "HEADER '$line'\n" if( $debug );
		print "$line\n";
	} else {
		if( $from ){
			print "from=$from\n";
		}
		close(STDOUT);
		$done = 1;
	}
}

print STDERR "finished header\n" if( $debug );
$temp->close();

exit(0) if $test;

$temp->open("<&3") or die "cannot open fd 3";
$socket->open(">&0") or die "cannot open fd 0";
$socket->autoflush(1);

while( defined ($line = <$temp>) ){
	print STDERR "RETURN '$line'\n" if( $debug );
	print $socket $line;
}
