#! /usr/bin/perl

# set up environment (change according to local configuration)
$GLOBUS_LOCATION = "/usr/local/globus-4.0.1";
$MYPROXY_SERVER = "myproxy-pubcookie.ncsa.uiuc.edu";

# To run this script, use pubcookie's verify_fork mechanism, which
# calls an external executable and bases its authentication decision
# on the return value.  A return value of zero is interpreted as pass,
# and non-zero is interpreted as fail.  The config file will have a
# section like this:
#
#   basic_verifier: verify_fork
#   verify_exe: /usr/local/pubcookie/myproxy_fork.pl

# Note on debugging: as of pubcookie 3.3.0, writing anything to STDOUT
# or STDERR will trigger an "internal server error" in pubcookie's CGI
# script.  Instead, you can redirect debug this script in two steps:
#
# 1. Write pubcookie's output to an external file, for example with
#    this shell script (which you can also run via verify_fork, by
#    substituting its name for myproxy_fork.pl in the config file):
#
#       #! /bin/sh
#       cat > /tmp/pubcookie_input
#
# 2. Add debugging output to this script and remove the redirection of
#    myproxy-logon's STDOUT and STDERR to /dev/null, so that you can
#    see what's going on.
#
# 3. Run this script outside of pubcookie
#
#       /usr/local/pubcookie/myproxy_fork.pl < /tmp/pubcookie_input

# Another option for debugging is to send the stdout and stderr of
# myproxy-logon, where the real complexity tends to be, to files,
# which you can monitor with "tail -f <outfile> <errfile>".  See the
# commented form of $myproxy_command for an example.

# read up to 1000 characters from STDIN
read(STDIN, $contents, 1000);
# read up to 1000 characters of a null-terminated string from the
# beginning of $contents
my ($username) = unpack("Z1000", $contents);

# skip past the first null, which terminates the username, and read up
# to 1000 more characters of null-terminated string from $contents
my ($password) = unpack("Z1000", substr($contents,length($username)+1));

# debugging
#print "--- username = $username\n";
#print "--- password = $password\n";
#print "--- raw input = $contents\n";

# pass username and password to myproxy-logon
$myproxy_handle;
mkdir "/tmp/creds";
my $cred_location = "/tmp/creds/$username";
my $myproxy_command = "| $GLOBUS_LOCATION/bin/myproxy-logon -t 9 -s $MYPROXY_SERVER -l $username -o $cred_location --stdin_pass > /dev/null 2> /dev/null";

# debugging version, sending stdout and stderr to files
#my $myproxy_command = "| $GLOBUS_LOCATION/bin/myproxy-logon -t 9 -s $MYPROXY_SERVER -l $username -o $cred_location --stdin_pass >> /tmp/myproxy_out 2>> /tmp/myproxy_err";

# debugging version, to be used outside of pubcookie (see above),
# sending stdout and stderr to the console
#my $myproxy_command = "| $GLOBUS_LOCATION/bin/myproxy-logon -t 9 -s $MYPROXY_SERVER -l $username -o $cred_location --stdin_pass";

open(myproxy_handle, $myproxy_command)
    or die "Unable to run myproxy-logon: $!\n";

print myproxy_handle "$password\n";

$closed_successfully = close(myproxy_handle);
$myproxy_exit = $?; # return value is stored in $? by close()

if ($myproxy_exit != 0) {
    # note: unfortunately, this message will not be visible in
    # Pubcookie's login web page; authentication will simply fail
    die "login failed ($myproxy_exit)";
}

# create unencrypted proxy based on login credential
$ENV{"X509_USER_CERT"} = $cred_location;
$ENV{"X509_USER_KEY"} = $cred_location;
$ENV{"PATH"} = $ENV{"PATH"}
    . ":" . $GLOBUS_LOCATION . "/bin"
    . ":" . $GLOBUS_LOCATION . "/sbin";
#my $myproxy_init_cmd = "$GLOBUS_LOCATION/bin/myproxy-init -c 8 -k pubcookie -n -s $MYPROXY_SERVER -l $username";
my $myproxy_init_cmd = "$GLOBUS_LOCATION/bin/myproxy-init -c 8 -k pubcookie -n -s $MYPROXY_SERVER -l $username > /dev/null 2> /dev/null";
#my $myproxy_init_cmd = "$GLOBUS_LOCATION/bin/myproxy-init -c 8 -k pubcookie -n -s $MYPROXY_SERVER -l $username >> /tmp/myproxy_out 2>> /tmp/myproxy_err";
system($myproxy_init_cmd);

# success!
exit 0;
