#!/usr/local/bin/perl -Tw

# Copyright distributed.net 1997-1998 - All Rights Reserved
# For use in distributed.net projects only.
# Any other distribution or use of this source violates copyright.
#
# This is a simple Perl script that can be placed on a public web
# server that is also accessible from within your intranet firewall
# to allow rc5des clients to communicate to the outside.  
#
# There are two ways to use this script:
#
# 1) Simply configure your rc5des clients to use "HTTP+UUE Encoding" and
#    the "Local HTTP proxy" set to the address/port of your *webserver*.
#    The value that is entered for the "Preferred Keyserver" and
#    "Keyserver port" are ignored.  This method will only work if your
#    webserver is configured not to be a "web proxy" when a full URL is
#    specified by the client (ie: including the protocol and host in the
#    requested document is ignored and the request is processed locally).
#    Apache 1.3.x (and older?) falls under this category when it is *not*
#    compiled for mod_proxy support.
#
# 2) Configure your rc5des clients to use "HTTP+UUE Encoding" and the
#    "Local HTTP proxy" set to the address/port of a web proxy.  The value
#    that is entered for the "Preferred Keyserver" and "Keyserver port"
#    should be the address/port of the webserver that you installed this
#    script on.
#
# The first method is obviously preferable, but not all webservers may be
# compatible with the requirement that it ignore the protocol and host of
# fully qualified requests.  Arguably with the second method, if you have
# access to a web proxy, it probably already allows you to access public
# internet addresses anyways, so that method probably won't be very useful
# for many people.
#
# Note that on whatever webserver you install this script, it *must* be
# accessible via the URL "/cgi-bin/rc5.cgi" or else things will not work.
# You can apply host-access restrictions to that script if you are
# paranoid about external people being able to access this script.
#
# $Revision: 1.3 $
#

use strict;
require IO::Socket;

# Target proxy address needs to consistently resolve to only a single
# proxy, or else your clients will receive 'Bad scramble' errors.
my $targetproxyaddr = 'nodezero.distributed.net';
my $targetproxyport = 2064;


# Read in the information about the request
my $method = $ENV{'REQUEST_METHOD'} || "GET";
my $remoteaddr = $ENV{'REMOTE_HOST'} || $ENV{'REMOTE_ADDR'} || "unknown";
my $servername = $ENV{'HTTP_HOST'} || $ENV{'SERVER_NAME'} || undef;
if ( $method ne "POST" )
{
    print "Content-type: text/plain\n\n";
    print "Malformed packet submission.\n";
    exit 0;
}


# Read in the POST data
$/ = undef;
my $content = <STDIN> || "";
if ( length($content) <= 0 )
{
    print "Content-type: text/plain\n\n";
    print "No packet submission found.\n";
    exit 0;
}
print STDERR "rc5cgi: Read ", length($content), 
    " bytes from client at $remoteaddr.\n";


# Try to connect to the remote keyserver and service the request.
for ( my $i = 0; $i < 5; $i++)
{
    my $sock = IO::Socket::INET->new(PeerAddr => $targetproxyaddr,
				     PeerPort => $targetproxyport,
				     Proto    => 'tcp');
    if ( $sock )
    {
	# Send the client's original request to the server.
	if ( ! $sock->send($content, 0) )
	{
	    print "Content-type: text/plain\n\n";
	    print "Error sending packet to host.";
	    print STDERR "rc5cgi: Failed to send request to target proxy.\n";
	    exit 0;
	}

	# Read the response sent back to us.
	my $response = '';
	$sock->recv($response, 10240);
	print STDERR "rc5cgi: Read ", length($response), " bytes from proxy.\n";

	# Send back the response, wrapped in an http header.
	print "Content-type: application/binary-stream\n";
	print "X-KeyServer: $servername\n" if $servername;
	print "\n";
	print $response;
	exit 0;
    }
    sleep 2;
}


# If we reached this point, our multiple tries to connect failed.
print STDERR "rc5cgi: Failed to connect to target proxy.\n";
print "Content-type: text/plain\n\n";
print "Could not establish server connection.";
exit 0;

