#!/usr/bin/perl -w

# myproxy test script
# written by Jim Basney <jbasney@ncsa.uiuc.edu>

# Assumes myproxy-server running as root on the local machine if
# MYPROXY_SERVER not set.
# Requires a valid proxy credential with lifetime of at least 3 hours
# unless the -generatecerts option is used
# Assumes myproxy-server.config has default policy.
#
# Some tests only run if -startserver is given.

use File::Temp qw(tempdir);
use File::Copy;
use IPC::Open3;
use Socket;

$tmpdir = tempdir(CLEANUP => 1);
my $openssl = $ENV{OPENSSL} || "openssl";

$PROXYBITS = "-bits 2048";

#
# handle cmdline options
#
$usage = "usage: myproxy-test [-help] [-verbose] [-startserver]\n" .
         "                    [-performance iterations clients]\n" .
         "                    [-dbperformance] [-valgrind]\n" .
         "                    [-generatecerts]\n" ;
$startserver = 0;
$performance = 0;
$dbperformance = 0;
$perfiters = 0;
$perfclients = 0;
$verbose = 0;
$generatecerts = 0;
while (($arg = shift @ARGV)) {
    if ($arg eq "-h" || $arg eq "-help") {
	print STDERR $usage;
	exit 1;
    } elsif ($arg eq "-v" || $arg eq "-verbose") {
	$verbose = 1;
    } elsif ($arg eq "-startserver") {
	$startserver = 1;
    } elsif ($arg eq "-performance") {
	$performance = 1;
	$perfiters = shift @ARGV;
	$perfclients = shift @ARGV;
    } elsif ($arg eq "-dbperformance") {
	$dbperformance = 1;
    } elsif ($arg eq "-valgrind") {
	chomp($valgrind = `which valgrind 2>/dev/null`);
	die "valgrind not in PATH, stopped" if (!(-x $valgrind));
    &write_valgrind_supp();
	$valgrind .= " --leak-check=full";
	$valgrind .= " --suppressions=$tmpdir/valgrind.supp";
	$valgrind .= " --undef-value-errors=no";
	$valgrind .= " --gen-suppressions=all";
	$valgrind .= " --num-callers=50 -q ";
    } elsif ($arg eq "-generatecerts" ) {
        $generatecerts = 1;
    } else {
	print STDERR $usage;
	exit 1;
    }
}

#
# If generatecerts option is specified then create
# a private CA and proxy locally and use them.
if ( $generatecerts) {
die("-generatecerts option requires -startserver option") unless ($startserver);
my $privcerts = "$tmpdir/privcerts.$$" ;
print STDERR "creating a CA in ", $privcerts, "\n" if ($verbose);
mkdir("$privcerts") ||
 die("failed to create $privcerts directory, stopped") ;
open(SSLCNF, ">$privcerts/openssl.cnf") || 
 die("failed to create $privcerts/openssl.cnf: $!");
print SSLCNF <<EOF;
[ ca ]
default_ca      = CA_default            # The default ca section

[ CA_default ]
dir            = $privcerts              # top dir
database       = $privcerts/index.txt        # index file.
new_certs_dir  = $privcerts/         # new certs dir
 
certificate    = $privcerts/cacert.pem       # The CA cert
serial         = $privcerts/serial           # serial no file
private_key    = $privcerts/cakey.pem # CA private key
RANDFILE       = $privcerts/.rand    # random number file
default_md     = default

[ req ]
default_bits   = 2048
default_md     = sha1
distinguished_name = req_distinguished_name

[ req_distinguished_name ]
commonName = Common Name (hostname, IP, or your name)
commonName_max = 64

[ v3_ca ]
basicConstraints = CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always

[ policy_anything ]
commonName              = supplied

EOF

close(SSLCNF);
open(CAINDEX,">$privcerts/index.txt") ||
  die("failed to create $privcerts/index.txt");
close(CAINDEX);
open(SERIAL,">$privcerts/serial") ||
  die("failed to create $privcerts/serial");
print SERIAL "01\n";
close(SERIAL);
&runcmd("$openssl req -batch -subj '/CN=MyProxy Test CA' -config $privcerts/openssl.cnf -new -x509 -extensions v3_ca -nodes -keyout $privcerts/cakey.pem -out $privcerts/cacert.pem -days 30");

chomp($hash = `$openssl x509 -in $privcerts/cacert.pem -hash -noout`) ;
mkdir("$privcerts/grid-security")  ||
 die("failed to create $privcerts/grid-security");
copy("$privcerts/cacert.pem","$privcerts/grid-security/$hash.0") ||
 die("failed to copy $privcerts/cacert.pem","$privcerts/grid-security/$hash.0");
open(POLICY,">$privcerts/grid-security/$hash.signing_policy") ||
 die("failed to create $privcerts/grid-security/$hash.signing_policy");
print POLICY  "access_id_CA            X509    '/CN=MyProxy Test CA'\n";
print POLICY  "pos_rights              globus  CA:sign\n";
print POLICY  "cond_subjects           globus  '\"/*\"'\n";
close(POLICY);
print STDERR "creating a user certificate request ", $privcerts, "\n" if ($verbose);
&runcmd("$openssl req -batch -subj '/CN=MyProxy Test User'  -config $privcerts/openssl.cnf -new -nodes -keyout $privcerts/userkey.pem -out $privcerts/usercert.csr -days 7") ;
print STDERR "signing user certificate with by CA in ", $privcerts, "\n" if ($verbose);
&runcmd("$openssl ca -batch -days 7 -config $privcerts/openssl.cnf -policy policy_anything -out $privcerts/usercert.pem -infiles $privcerts/usercert.csr");
chmod(oct("0600"),"$privcerts/userkey.pem","$privcerts/usercert.pem") ||
 die("failed to chmod $privcerts/userkey.pem or $privcerts/usercert.pem");
$ENV{'X509_USER_CERT'} = "$privcerts/usercert.pem" ;
$ENV{'X509_USER_KEY'}  = "$privcerts/userkey.pem" ;
$ENV{'X509_CERT_DIR'}  = "$privcerts/grid-security" ;
print STDERR "generating a user proxy\n" if ($verbose);
chomp($grid_proxy_init = `which grid-proxy-init 2>/dev/null`);
  die "grid-proxy-init not found, stopped" if (!(-x $grid_proxy_init));
&runcmd("$grid_proxy_init -debug $PROXYBITS");
} #end of generatecerts.

#
# make sure I have a valid proxy
#
chomp($grid_proxy_init = `which grid-proxy-init 2>/dev/null`);
die "grid-proxy-init not found, stopped" if (!(-x $grid_proxy_init));
chomp($grid_proxy_info = `which grid-proxy-info 2>/dev/null`);
die "grid-proxy-info not found, stopped" if (!(-x $grid_proxy_info));
chomp($grid_cert_info = `which grid-cert-info 2>/dev/null`);
die "grid-cert-info not found, stopped" if (!(-x $grid_cert_info));
$timeleft = `$grid_proxy_info -timeleft 2>/dev/null`;
if (!defined($timeleft) || $timeleft eq "" || ($timeleft < 60*60*3)) {
    &debug("Problem with proxy.  Will try to create a new one.");
    `$grid_proxy_init $PROXYBITS -pwstdin </dev/null >/dev/null 2>&1`;
    $timeleft = `$grid_proxy_info -timeleft 2>/dev/null`;
}
if (!defined($timeleft) || $timeleft eq "") {
  print STDERR "grid-proxy-info failed:\n";
  system("$grid_proxy_info -timeleft"); # show the error
  die "stopped";
}
die "proxy expired, stopped" if ($timeleft < 60);
die "proxy lifetime too short, stopped" if ($timeleft < 60*60*6);
die "proxy is limited, stopped" if (`$grid_proxy_info -type` =~ /limited/);
chomp($cert_subject = `$grid_proxy_info -identity`);
die "grid-proxy-info -identity failed, stopped"
    if (!defined($cert_subject) || $cert_subject eq "");
chomp($proxy_path = `$grid_proxy_info -path 2>/dev/null`);
die "grid-proxy-info -path failed, stopped" if (!(-e $proxy_path));
($exitstatus, $output) = &verifyproxy($proxy_path);
if ($exitstatus) {
  print STDERR $output;
  die if ($exitstatus);
}

#
# check for the commands I want to run
#
chomp($myproxy_store = `which myproxy-store 2>/dev/null`);
die "myproxy-store not in PATH, stopped" if (!(-x $myproxy_store));
chomp($myproxy_init = `which myproxy-init 2>/dev/null`);
die "myproxy-init not in PATH, stopped" if (!(-x $myproxy_init));
chomp($myproxy_retrieve = `which myproxy-retrieve 2>/dev/null`);
die "myproxy-retrieve not in PATH, stopped" if (!(-x $myproxy_retrieve));
chomp($myproxy_info = `which myproxy-info 2>/dev/null`);
die "myproxy-info not in PATH, stopped" if (!(-x $myproxy_info));
chomp($myproxy_destroy = `which myproxy-destroy 2>/dev/null`);
die "myproxy-destroy not in PATH, stopped" if (!(-x $myproxy_destroy));
chomp($myproxy_get = `which myproxy-logon 2>/dev/null`);
die "myproxy-logon not in PATH, stopped" if (!(-x $myproxy_get));
chomp($myproxy_passwd = `which myproxy-change-pass-phrase 2>/dev/null`);
die "myproxy-change-pass-phrase not in PATH, stopped"
    if (!(-x $myproxy_passwd));
chomp($bintrue = `which true 2>/dev/null`);

#
# setup environment variables
#
if (!defined($ENV{'MYPROXY_SERVER'})) {
    chomp($hostname = `hostname 2>/dev/null`);
    $ENV{'MYPROXY_SERVER'} = $hostname;
}
if (!defined($ENV{'X509_USER_PROXY'})) {
    $ENV{'X509_USER_PROXY'} = "/tmp/x509up_u$<";
}
# make proxy from existing proxy, so we don't need to deal with long-term cred
$ENV{'X509_USER_CERT'} = $ENV{'X509_USER_PROXY'};
$ENV{'X509_USER_KEY'} = $ENV{'X509_USER_PROXY'};
$ENV{'LOGNAME'} = $ENV{'USER'} if (!defined($ENV{'LOGNAME'}));
$ENV{'LOGNAME'} = $ENV{'LOGNAME'} . ".myproxy-test";

#
# make an independent proxy for a separate identity
#
$iproxyloc = "$tmpdir/iproxy.pem";
&runcmd("$grid_proxy_init $PROXYBITS -out $iproxyloc -independent -hours 0");
chomp($iproxysubject = `$grid_proxy_info -file $iproxyloc -identity`);
die "grid-proxy-info -file $iproxyloc -identity failed, stopped"
    if (!defined($iproxysubject) || $iproxysubject eq "");

srand(time||$$);
$passphrase = sprintf "%010.d", int(rand(0x7fffffff));
$trustrootdir = "$tmpdir/.globus/certificates.test.$$";
$origtrustrootdir = $ENV{'X509_CERT_DIR'} if defined($ENV{'X509_CERT_DIR'});

&opensslsanitycheck();

# all temporary files accessible only by running user
umask(0077);

#
# start server if requested
#
if ($startserver) {
    $ENV{'MYPROXY_SERVER'} = "localhost";
    $ENV{'MYPROXY_SERVER_DN'} = $cert_subject;
    chomp($myproxy_server = `which myproxy-server 2>/dev/null`);
    die "myproxy-server not in PATH, stopped" if (!(-x $myproxy_server));
    $serverdir = "$tmpdir/myproxy-test.serverdir.$$";
    mkdir($serverdir, 0700) ||
	die "failed to create $serverdir, stopped";
    $serverconf = "$tmpdir/myproxy-test.serverconf.$$";
    open(CONF, ">$serverconf") ||
	 die "failed to open $serverconf, stopped";
    print CONF "accepted_credentials  \"*\"\n";
    print CONF "authorized_retrievers \"*\"\n";
    print CONF "default_retrievers    \"*\"\n";
    print CONF "authorized_renewers   \"*\"\n";
    print CONF "default_renewers      \"none\"\n";
    print CONF "authorized_key_retrievers \"*\"\n";
    print CONF "default_key_retrievers    \"none\"\n";
    print CONF "trusted_retrievers    \"*\"\n";
    print CONF "default_trusted_retrievers \"none\"\n";
    print CONF "passphrase_policy_program $bintrue\n" if (-x $bintrue);
    print CONF "accepted_credentials_mapapp $bintrue\n" if (-x $bintrue);
    print CONF "allow_self_authorization true\n"; # for renewal testing
    print CONF "check_multiple_credentials true\n";
    print CONF "disable_usage_stats \"false\"\n";
    print CONF "usage_stats_target \"default\"\n";
    close(CONF);
    $SERVERPIDFILE = "$tmpdir/myproxy-test.serverpid.$$";
    $SERVERPORTFILE = "$tmpdir/myproxy-test.serverport.$$";
    $servercmd = "$myproxy_server -s $serverdir -c $serverconf";
    $servercmd .= " -p 0 -P $SERVERPIDFILE -z $SERVERPORTFILE";
    if (defined($valgrind)) {
        $valgrindlog = File::Temp::tempnam($tmpdir, "valgrind.log.");
        $valgrindlogopt = " --log-file=$valgrindlog ";
        $servercmd = $valgrind . $valgrindlogopt . $servercmd;
    }
    &debug("running '$servercmd'");
    system($servercmd);
    sleep(2);			# give server a chance to startup
    sleep(4) if (defined($valgrind)); # valgrind slows things down
    if (open SERVERPIDFILE) {
      chomp($serverpid = <SERVERPIDFILE>);
      close SERVERPIDFILE;
    }
    if (!defined($serverpid) || $serverpid eq "") {
      print STDERR "failed to start myproxy-server:\n";
      system("$servercmd -d");	# send errors to STDERR
      if (defined($valgrindlog) && -e $valgrindlog) {
        print STDERR "valgrind log follows:\n";
        system("cat $valgrindlog");
      }
      &docleanup();
      exit 1;
    }
    if (open SERVERPORTFILE) {
      chomp($serverport = <SERVERPORTFILE>);
      close SERVERPORTFILE;
    }
    if (!defined($serverport) || $serverport eq "") {
      print STDERR "myproxy-server didn't write portfile!\n";
      &docleanup();
      exit 1;
    } else {
      $ENV{'MYPROXY_SERVER_PORT'} = $serverport;
      print STDERR "server listening on port ", $serverport, "\n" if ($verbose);
    }
}

#
# run performance tests if requested
#
if ($performance) {
    &doperftests();
    exit 0;
}

#
# BEGIN TESTS
#
$SUCCESSES = $FAILURES = 0;

# commands to test: myproxy-init, myproxy-info, myproxy-destroy,
#                   myproxy-logon, and myproxy-change-pass-phrase

($exitstatus, $output) =
    &runtest("myproxy-init -v -a -c 1 -t 1 -S",
	     $passphrase . "\n");
print "MyProxy Test 1 (store credential with default name): ";
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
    print "Skipping remaining tests.\n";
    goto end_of_all_tests;
}

($exitstatus, $output) = &runtest("myproxy-info -v", undef);
print "MyProxy Test 2 (get info for stored credential): ";
if ($exitstatus == 0 && $output =~ /username/) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

($exitstatus, $output) =
    &runtest("myproxy-logon -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
	     $passphrase . "\n");
print "MyProxy Test 3 (retrieve stored credential): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifyproxy("$tmpdir/myproxy-test.$$");
}
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

($exitstatus, $output) =
    &runtest("myproxy-logon -t 1 -o - -v -S > $tmpdir/myproxy-test.$$",
	     $passphrase . "\n");
print "MyProxy Test 3- (retrieve stored credential to stdout): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifyproxy("$tmpdir/myproxy-test.$$");
}
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

($exitstatus, $output) =
    &runtest("myproxy-logon -t 1 -N -v -S",
	     $passphrase . "\n");
print "MyProxy Test 3N (authenticate w/o retrieving credential): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifyproxy("$tmpdir/myproxy-test.$$");
}
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

$ENV{'X509_CERT_DIR'} = $trustrootdir;
($exitstatus, $output) =
  &runtest("myproxy-logon -T -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
           $passphrase . "\n");
print "MyProxy Test 3T (retrieve stored credential w/ trustroots): ";
if ($exitstatus == 0) {
  ($exitstatus, $output) =
    &verifyproxy("$tmpdir/myproxy-test.$$");
}
if ($exitstatus == 0) {
  ($exitstatus, $output) =
    &verifytrustroots();
}
if ($exitstatus == 0) {
  print "SUCCEEDED\n"; $SUCCESSES++;
} else {
  print "FAILED\n"; $FAILURES++; print STDERR $output;
}
if (defined($origtrustrootdir)) {
  $ENV{'X509_CERT_DIR'} = $origtrustrootdir;
} else {
  delete $ENV{'X509_CERT_DIR'};
}

if (defined($serverconf)) {
system("touch $serverconf") && die "failed to touch $serverconf, stopped";
($exitstatus, $output) =
    &runtest("myproxy-logon -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
	     $passphrase . "\n");
print "MyProxy Test 3R1 (retrieve stored credential after server reconfig): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifyproxy("$tmpdir/myproxy-test.$$");
}
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}
system("touch $serverconf") && die "failed to touch $serverconf, stopped";
($exitstatus, $output) =
    &runtest("myproxy-logon -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
	     $passphrase . "\n");
print "MyProxy Test 3R2 (retrieve stored credential after server reconfig): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifyproxy("$tmpdir/myproxy-test.$$");
}
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}
system("touch $serverconf") && die "failed to touch $serverconf, stopped";
($exitstatus, $output) =
    &runtest("myproxy-logon -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
	     $passphrase . "\n");
print "MyProxy Test 3R3 (retrieve stored credential after server reconfig): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifyproxy("$tmpdir/myproxy-test.$$");
}
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}
}

($exitstatus, $output) =
    &runtest("myproxy-logon -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
	     "badpassphrase\n");
print "MyProxy Test 4 (verify passphrase checking on retrieve): ";
if ($exitstatus != 0 && $output =~ /invalid credential passphrase/) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

($exitstatus, $output) =
    &runtest("myproxy-logon -t 1 -N -v -S",
	     "badpassphrase\n");
print "MyProxy Test 4N (verify passphrase checking on authenticate): ";
if ($exitstatus != 0 && $output =~ /invalid credential passphrase/) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

$old_passphrase = $passphrase;
$passphrase = sprintf "%010.d", int(rand(0x7fffffff));
($exitstatus, $output) =
    &runtest("myproxy-change-pass-phrase -v -S",
	     "$old_passphrase\n$passphrase\n");
print "MyProxy Test 5 (change passphrase for credential): ";
if ($exitstatus == 0 && $output =~ /Pass phrase changed/) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

($exitstatus, $output) =
    &runtest("myproxy-logon -t 1 -N -v -S",
	     $passphrase . "\n");
print "MyProxy Test 6 (verify new passphrase): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifyproxy("$tmpdir/myproxy-test.$$");
}
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

($exitstatus, $output) =
    &runtest("myproxy-logon -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
	     $old_passphrase . "\n");
print "MyProxy Test 7 (verify old passphrase fails): ";
if ($exitstatus != 0 && $output =~ /invalid credential passphrase/) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

($exitstatus, $output) =
    &runtest("myproxy-logon -a \$X509_USER_PROXY -t 1 -o $tmpdir/myproxy-test.$$ -v", undef);
print "MyProxy Test 8 (verify default renewal policy): ";
if ($exitstatus != 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

($exitstatus, $output) =
    &runtest("myproxy-destroy -v", undef);
print "MyProxy Test 9 (remove credential from repository): ";
if ($exitstatus == 0 && $output =~ /was successfully removed/) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

($exitstatus, $output) =
    &runtest("myproxy-info -v", undef);
print "MyProxy Test 10 (verify credentials are removed): ";
if (!($output =~ /default credential/)) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

#
# Test 10.a
#
if ($startserver && defined($serverpid)) { # only case we have direct access to server
#  ($exitstatus, $output) = kill('HUP', $serverpid);
  ($exitstatus, $output) = &runtest("/bin/kill -HUP $serverpid");
  print "MyProxy Test 10.a (kill -HUP $serverpid): ";
  if ($exitstatus != 0) {
      print "FAILED with $exitstatus\n"; $FAILURES++;
      print STDERR $output;
  } else {
    print "SUCCEEDED\n"; $SUCCESSES++;
  }
} else {
  print "MyProxy Test 10.a (kill -HUP <myproxy-server>): SKIPPED\n";
}


($exitstatus, $output) =
    &runtest("myproxy-init -v -r 'nobody' -k 'nobody' -c 1 -t 1 -S",
	     $passphrase . "\n");
print "MyProxy Test 11 (store credentials with retrieval policies): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&runtest("myproxy-init -v -x -r '$cert_subject' -k 'mine' -c 1 -t 1 -S",
		 $passphrase . "\n");
}
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

($exitstatus, $output) =
    &runtest("myproxy-logon -k 'mine' -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
	     $passphrase . "\n");
print "MyProxy Test 12 (verify retrieval policies): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifyproxy("$tmpdir/myproxy-test.$$");
}
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&runtest("myproxy-logon -k 'nobody' -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
		 $passphrase . "\n");
    if ($exitstatus != 0) {
	print "SUCCEEDED\n"; $SUCCESSES++;
    } else {
	print "FAILED\n"; $FAILURES++;
	print STDERR "Shouldn't have allowed retrieval.\n";
	print STDERR $output;
    }
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}
&runtest("myproxy-destroy -v -k 'mine'", undef);
&runtest("myproxy-destroy -v -k 'nobody'", undef);

($exitstatus, $output) =
    &runtest("myproxy-init -v -R 'nobody' -k 'nobody' -c 1 -t 1 -d -S",
	     $passphrase . "\n");
print "MyProxy Test 13 (store credentials with renewal policies): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&runtest("myproxy-init -v -x -R '$cert_subject' -k 'mine' -c 1 -t 1 -d -S",
		 $passphrase . "\n");
}
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

($exitstatus, $output) = &runtest("myproxy-info -v -d", undef);
print "MyProxy Test 14 (get info for stored renewal credentials): ";
if ($exitstatus == 0 && $output =~ /username/) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

($exitstatus, $output) =
    &runtest("myproxy-logon -k 'mine' -a $ENV{'X509_USER_PROXY'} -t 1 -o $tmpdir/myproxy-test.$$ -v -d",
	     undef);
print "MyProxy Test 15 (verify renewal policies): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifyproxy("$tmpdir/myproxy-test.$$");
} elsif ($output =~ /self-authz not allowed/) {
    $exitstatus = 0;            # default policy will give this response
}
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&runtest("myproxy-logon -k 'nobody' -a $ENV{'X509_USER_PROXY'} -t 1 -o $tmpdir/myproxy-test.$$ -v -d",
		 undef);
    if ($exitstatus != 0) {
	print "SUCCEEDED\n"; $SUCCESSES++;
    } else {
	print "FAILED\n"; $FAILURES++;
	print STDERR "Shouldn't have allowed retrieval.\n";
	print STDERR $output;
    }
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}
&runtest("myproxy-destroy -v -k 'mine' -d", undef);
&runtest("myproxy-destroy -v -k 'nobody' -d", undef);

($exitstatus, $output) =
    &runtest("myproxy-init -v -a -c 3 -t 2 -S",
	     $passphrase . "\n");
print "MyProxy Test 16 (verify lifetime of retrieved credentials): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&runtest("myproxy-logon -o $tmpdir/myproxy-test.$$ -v -S",
		 $passphrase . "\n");
    $timeleft = `$grid_proxy_info -file $tmpdir/myproxy-test.$$ -timeleft`;
    if (defined($timeleft) &&
	$timeleft > 60*60*2+300 || $timeleft < 60*60*2-300) {
	$output = "Credential lifetime ($timeleft) incorrect." .
	    "It should be " . (60*60*2) . ".\n";
	$exitstatus = 1;
    }
}
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifyproxy("$tmpdir/myproxy-test.$$");
}
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&runtest("myproxy-logon -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
		 $passphrase . "\n");
    $timeleft = `$grid_proxy_info -file $tmpdir/myproxy-test.$$ -timeleft`;
    if ($timeleft > 60*61 || $timeleft < 60*59) {
	$output = "Credential lifetime ($timeleft) incorrect." .
	    "It should be " . (60*60) . ".\n";
	$exitstatus = 1;
    }
}
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifyproxy("$tmpdir/myproxy-test.$$");
}
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}
&runtest("myproxy-destroy -v", undef);

#
# Start of myproxy-store and myproxy-retrieve tests
#

# commands to test: myproxy-store, myproxy-info, myproxy-destroy,
#                   myproxy-logon, myproxy-retrieve, and 
#                   myproxy-change-pass-phrase

# For myproxy-store, we need an encrypted key to store.
# So, let's encrypt our proxy key.
$passphrase = sprintf "%010.d", int(rand(0x7fffffff));
$testkey = "$tmpdir/myproxy-test.$$.key";
&runcmd("$openssl rsa -des3 -passout stdin -in \$X509_USER_KEY -out $testkey",
	 $passphrase . "\n");
chmod(0600, $testkey);

#
# Test 17
#
($exitstatus, $output) =
    &runtest("myproxy-store -x -E '$cert_subject' -v -t 1 -y $testkey", undef);
print "MyProxy Test 17 (store credential with default name): ";
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} elsif (($output =~ /Error checking authorization/) ||
         ($output =~ /unknown command/)) {
    print "UNSUPPORTED\n"; $FAILURES++;
    print "Server does not support myproxy-store. Skipping futher myproxy-store tests.\n";
    goto end_of_store_tests;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
    print "Skipping futher myproxy-store tests.\n";
    goto end_of_store_tests;
}

#
# Test 18
#
($exitstatus, $output) = &runtest("myproxy-info -v", undef);
print "MyProxy Test 18 (get info for stored credential): ";
if ($exitstatus == 0 && $output =~ /username/) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

#
# Test 19
#
($exitstatus, $output) =
    &runtest("myproxy-logon -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
	     $passphrase . "\n");
print "MyProxy Test 19 (create proxy from stored credential): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifyproxy("$tmpdir/myproxy-test.$$");
}
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}


#
# Test 20
#

($exitstatus, $output) =
    &runtest("myproxy-retrieve -c $tmpdir/myproxy-test.cert.$$.pem -y $tmpdir/myproxy-test.key.$$.pem -v -S",
	     $passphrase . "\n");
print "MyProxy Test 20 (retrieve stored credential): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifycert("$tmpdir/myproxy-test.cert.$$.pem", "$tmpdir/myproxy-test.key.$$.pem");
}
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}
unlink( "$tmpdir/myproxy-test.cert.$$.pem" );
unlink( "$tmpdir/myproxy-test.key.$$.pem" );

$ENV{'X509_CERT_DIR'} = $trustrootdir;
($exitstatus, $output) =
  &runtest("myproxy-retrieve -T -c $tmpdir/myproxy-test.cert.$$.pem -y $tmpdir/myproxy-test.key.$$.pem -v -S",
           $passphrase . "\n");
print "MyProxy Test 20T (retrieve stored credential w/ trustroots): ";
if ($exitstatus == 0) {
  ($exitstatus, $output) =
    &verifycert("$tmpdir/myproxy-test.cert.$$.pem", "$tmpdir/myproxy-test.key.$$.pem");
}
if ($exitstatus == 0) {
  ($exitstatus, $output) =
    &verifytrustroots();
}
if ($exitstatus == 0) {
  print "SUCCEEDED\n"; $SUCCESSES++;
} else {
  print "FAILED\n"; $FAILURES++; print STDERR $output;
}
unlink( "$tmpdir/myproxy-test.cert.$$.pem" );
unlink( "$tmpdir/myproxy-test.key.$$.pem" );
if (defined($origtrustrootdir)) {
  $ENV{'X509_CERT_DIR'} = $origtrustrootdir;
} else {
  delete $ENV{'X509_CERT_DIR'};
}

#
# Test 20.a
#
if ($startserver && defined($serverpid)) { # only case we have direct access to server
#  ($exitstatus, $output) = kill('HUP', $serverpid);
  ($exitstatus, $output) = &runtest("/bin/kill -HUP $serverpid");
  print "MyProxy Test 20.a (kill -HUP $serverpid): ";
  if ($exitstatus != 0) {
      print "FAILED with $exitstatus\n"; $FAILURES++;
      print STDERR $output;
  } else {
    print "SUCCEEDED\n"; $SUCCESSES++;
  }
} else {
  print "MyProxy Test 20.a (kill -HUP <myproxy-server>): SKIPPED\n";
}

#
# Test 21
#
($exitstatus, $output) =
    &runtest("myproxy-logon -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
	     "badpassphrase\n");
print "MyProxy Test 21 (verify passphrase checking on myproxy-logon): ";
if ($exitstatus != 0 && $output =~ /invalid credential passphrase/) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

#
# Test 22
#
($exitstatus, $output) =
    &runtest("myproxy-retrieve -c $tmpdir/myproxy-test-cert.$$.pem -y $tmpdir/myproxy-test-key.$$.pem -v -S",
	     "badpassphrase\n");
print "MyProxy Test 22 (verify passphrase checking on myproxy-retrieve): ";
if ($exitstatus != 0 && $output =~ /invalid credential passphrase/) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}
unlink( "$tmpdir/myproxy-test.cert.$$.pem" );
unlink( "$tmpdir/myproxy-test.key.$$.pem" );

#
# Test 23
#
($exitstatus, $output) =
    &runtest("myproxy-logon -a \$X509_USER_PROXY -t 1 -o $tmpdir/myproxy-test.$$ -v", undef);
print "MyProxy Test 23 (verify myproxy-logon default renewal policy): ";
if ($exitstatus != 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

#
# Test 24
#
($exitstatus, $output) =
    &runtest("myproxy-retrieve -a \$X509_USER_PROXY  -c $tmpdir/myproxy-test-cert.$$.pem -y $tmpdir/myproxy-test-key.$$.pem -v", undef);
print "MyProxy Test 24 (verify myproxy-retrieve default renewal policy): ";
if ($exitstatus != 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}
unlink( "$tmpdir/myproxy-test-cert.$$.pem" );
unlink( "$tmpdir/myproxy-test-key.$$.pem" );

#
# Test 25
#
($exitstatus, $output) =
    &runtest("myproxy-destroy -v", undef);
print "MyProxy Test 25 (remove credential from repository): ";
if ($exitstatus == 0 && $output =~ /was successfully removed/) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

#
# Test 26
#
($exitstatus, $output) =
    &runtest("myproxy-info -v", undef);
print "MyProxy Test 26 (verify credentials are removed): ";
if (!($output =~ /default credential/)) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

#
# Test 27
#
($exitstatus, $output) =
    &runtest("myproxy-store -v -r 'nobody' -k 'nobody' -t 1 -y $testkey",
	     undef);
print "MyProxy Test 27 (store credentials with retrieval policies): ";

if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&runtest("myproxy-store -x -E '$cert_subject' -v -r '$cert_subject' -k 'mine' -t 1 -y $testkey", undef);
}
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

#
# Test 28
#
($exitstatus, $output) =
    &runtest("myproxy-logon -k 'mine' -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
	     $passphrase . "\n");
print "MyProxy Test 28 (verify myproxy-logon retrieval policies): ";

if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifyproxy("$tmpdir/myproxy-test.$$");
}
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&runtest("myproxy-logon -k 'nobody' -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
		 $passphrase . "\n");

    if ($exitstatus != 0) {
	print "SUCCEEDED\n"; $SUCCESSES++;
    } else {
	print "FAILED\n"; $FAILURES++;
	print STDERR "Shouldn't have allowed retrieval.\n";
	print STDERR $output;
    }
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

#
# Test 29
#
($exitstatus, $output) =
    &runtest("myproxy-retrieve -k 'mine' -c $tmpdir/myproxy-test.cert.12.1.$$.pem -y $tmpdir/myproxy-test.key.12.1.$$.pem -v -S",
	     $passphrase . "\n");
print "MyProxy Test 29 (verify myproxy-retrieve retrieval policies): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifycert("$tmpdir/myproxy-test.cert.12.1.$$.pem", "$tmpdir/myproxy-test.key.12.1.$$.pem");
}
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&runtest("myproxy-retrieve -k 'nobody' -c $tmpdir/myproxy-test.cert.12.2.$$.pem -y $tmpdir/myproxy-test.key.12.2.$$.pem -v -S",
		 $passphrase . "\n");
    if ($exitstatus != 0) {
	print "SUCCEEDED\n"; $SUCCESSES++;
    } else {
	print "FAILED\n"; $FAILURES++;
	print STDERR "Shouldn't have allowed retrieval.\n";
	print STDERR $output;
    }
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}
&runtest("myproxy-destroy -v -k 'mine'", undef);
&runtest("myproxy-destroy -v -k 'nobody'", undef);
`rm -f $tmpdir/myproxy-test.*.12.*.$$.pem`;


#
# Test 30
#
($exitstatus, $output) =
    &runtest("myproxy-store -v -R 'nobody' -k 'nobody' -t 1 -d -y \$X509_USER_PROXY -c \$X509_USER_PROXY",
	     undef);
print "MyProxy Test 30 (store credentials with renewal policies): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&runtest("myproxy-store -v -x -R '$cert_subject' -k 'mine' -t 1 -d -y \$X509_USER_PROXY -c \$X509_USER_PROXY", undef);
}
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&runtest("myproxy-store -v -c $iproxyloc -y $iproxyloc -x -R '$cert_subject' -k 'independent' -t 1", undef);
}
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

#
# Test 30.a
#
if ($startserver && defined($serverpid)) { # only case we have direct access to server
#  ($exitstatus, $output) = kill('HUP', $serverpid);
  ($exitstatus, $output) = &runtest("/bin/kill -HUP $serverpid");
  print "MyProxy Test 30.a (kill -HUP $serverpid): ";
  if ($exitstatus != 0) {
      print "FAILED with $exitstatus\n"; $FAILURES++;
      print STDERR $output;
  } else {
    print "SUCCEEDED\n"; $SUCCESSES++;
  }
} else {
  print "MyProxy Test 30.a (kill -HUP <myproxy-server>): SKIPPED\n";
}

#
# Test 31
#
($exitstatus, $output) = &runtest("myproxy-info -v -d", undef);
print "MyProxy Test 31 (get info for stored renewal credentials): ";
if ($exitstatus == 0 && $output =~ /username/) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

#
# Test 32
#
($exitstatus, $output) =
    &runtest("myproxy-logon -k 'mine' -a $ENV{'X509_USER_PROXY'} -t 1 -o $tmpdir/myproxy-test.$$ -v -d -S",
	     $passphrase . "\n");
print "MyProxy Test 32 (verify renewal policies): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifyproxy("$tmpdir/myproxy-test.$$");
} elsif ($output =~ /self-authz not allowed/) {
    $exitstatus = 0;            # default policy will give this response
}
if ($exitstatus == 0) {
    ($exitstatus, $output) =
        &runtest("myproxy-logon -k 'independent' -a $iproxyloc -t 1 -o $tmpdir/myproxy-test.$$ -v",
                 undef);
}
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifyproxy("$tmpdir/myproxy-test.$$");
}
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&runtest("myproxy-logon -k 'nobody' -a $ENV{'X509_USER_PROXY'} -t 1 -o $tmpdir/myproxy-test.$$ -v -d -S",
		 $passphrase . "\n");
    if ($exitstatus != 0) {
	print "SUCCEEDED\n"; $SUCCESSES++;
    } else {
	print "FAILED\n"; $FAILURES++;
	print STDERR "Shouldn't have allowed retrieval.\n";
	print STDERR $output;
    }
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

&runtest("myproxy-destroy -v -k 'mine' -d", undef);
&runtest("myproxy-destroy -v -k 'nobody' -d", undef);
&runtest("env X509_USER_PROXY=$iproxyloc myproxy-destroy -v -k 'independent'", undef);

#
# Test 33
#
($exitstatus, $output) =
    &runtest("myproxy-store -x -E '$cert_subject' -v -a -t 2 -y $testkey", undef);
print "MyProxy Test 33 (verify lifetime of retrieved credentials): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&runtest("myproxy-logon -o $tmpdir/myproxy-test.$$ -v -S",
		 $passphrase . "\n");
    $timeleft = `$grid_proxy_info -file $tmpdir/myproxy-test.$$ -timeleft`;
    if (defined($timeleft) &&
	$timeleft > 60*60*2+300 || $timeleft < 60*60*2-300) {
	$output = "Credential lifetime ($timeleft) incorrect." .
	    "It should be " . (60*60*2) . ".\n";
	$exitstatus = 1;
    }
}
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifyproxy("$tmpdir/myproxy-test.$$");
}
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&runtest("myproxy-logon -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
		 $passphrase . "\n");
    $timeleft = `$grid_proxy_info -file $tmpdir/myproxy-test.$$ -timeleft`;
    if ($timeleft > 60*61 || $timeleft < 60*59) {
	$output = "Credential lifetime ($timeleft) incorrect." .
	    "It should be " . (60*60) . ".\n";
	$exitstatus = 1;
    }
}
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifyproxy("$tmpdir/myproxy-test.$$");
}
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}
&runtest("myproxy-destroy -v", undef);

#
# Test 34
#
($exitstatus, $output) =
    &runtest("myproxy-store -v -E 'nobody' -k 'nobody' -t 1 -y $testkey",
	     undef);
print "MyProxy Test 34 (store credentials with retrieve key policies): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&runtest("myproxy-store -v -x -E '$cert_subject' -k 'mine' -t 1 -y $testkey", undef);
}
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

#
# Test 35
#
($exitstatus, $output) = &runtest("myproxy-info -v", undef);
print "MyProxy Test 35 (get info for stored retrieve key credentials): ";
if ($exitstatus == 0 && $output =~ /username/) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

#
# Test 36
#
($exitstatus, $output) =
    &runtest("myproxy-retrieve -k 'mine' -c $tmpdir/myproxy-test.cert.12.1.$$.pem -y $tmpdir/myproxy-test.key.12.1.$$.pem -v -S",
	     $passphrase . "\n");
print "MyProxy Test 36 (verify myproxy-retrieve key retrieval policies): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifycert("$tmpdir/myproxy-test.cert.12.1.$$.pem", "$tmpdir/myproxy-test.key.12.1.$$.pem");
}
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&runtest("myproxy-retrieve -k 'nobody' -c $tmpdir/myproxy-test.cert.12.2.$$.pem -y $tmpdir/myproxy-test.key.12.2.$$.pem -v -S",
		 $passphrase . "\n");
    if ($exitstatus != 0) {
	print "SUCCEEDED\n"; $SUCCESSES++;
    } else {
	print "FAILED\n"; $FAILURES++;
	print STDERR "Shouldn't have allowed retrieval.\n";
	print STDERR $output;
    }
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}
end_of_store_tests:
&runtest("myproxy-destroy -v -k 'mine'", undef);
&runtest("myproxy-destroy -v -k 'nobody'", undef);
`rm -f $tmpdir/myproxy-test.*.12.*.$$.pem`;
unlink("$tmpdir/myproxy-test.$$.key.pem");

#
# Test 37
#
($exitstatus, $output) =
    &runtest("myproxy-init -v -Z 'nobody' -k 'nobody' -c 1 -t 1 -d -S -n",
	     $passphrase . "\n");
print "MyProxy Test 37 (store credentials w/ retrievable_by_cert policies): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
        &runtest("myproxy-store -v -x -Z '$cert_subject' -k 'mine' -c $iproxyloc -y $iproxyloc -t 1", undef);
}
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}

#
# Test 38
#
($exitstatus, $output) =
    &runtest("myproxy-logon -k 'mine' -t 1 -o $tmpdir/myproxy-test.$$ -v -n",
             undef);
print "MyProxy Test 38 (verify retrievable_by_cert policies): ";
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&verifyproxy("$tmpdir/myproxy-test.$$");
}
if ($exitstatus == 0) {
    ($exitstatus, $output) =
	&runtest("myproxy-logon -k 'nobody' -t 1 -o $tmpdir/myproxy-test.$$ -v -d -n",
		 undef);
    if ($exitstatus != 0) {
	print "SUCCEEDED\n"; $SUCCESSES++;
    } else {
	print "FAILED\n"; $FAILURES++;
	print STDERR "Shouldn't have allowed retrieval.\n";
	print STDERR $output;
    }
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}
&runtest("env X509_USER_PROXY=$iproxyloc myproxy-destroy -v -k 'mine'", undef);
&runtest("myproxy-destroy -v -k 'nobody' -d", undef);

#
# Test 39
#
&runtest("myproxy-init -v -a -c 1 -t 1 -S", $passphrase . "\n");
&runtest("myproxy-init -v -x -R '$cert_subject' -k renew -c 1 -t 1",
		 undef);
&runcmd("grid-proxy-init $PROXYBITS -limited -o \$X509_USER_PROXY.limited", undef);
rename("\$X509_USER_PROXY", "\$X509_USER_PROXY.orig");
rename("\$X509_USER_PROXY.limited", "\$X509_USER_PROXY");
($exitstatus, $output) =
    &runtest("myproxy-logon -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
	     $passphrase . "\n");
print "MyProxy Test 39 (verify limited proxy retrieves a limited proxy): ";
if ($exitstatus == 0) {
	($exitstatus, $output) =
	    &verifyproxy("$tmpdir/myproxy-test.$$");
}
if ($exitstatus != 0) {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
    goto cleanup_limited;
}
if (!`$grid_proxy_info -file $tmpdir/myproxy-test.$$ -type` =~ /limited/) {
    print "FAILED\nRetrieved proxy is not limited.\n"; $FAILURES++; 
}
print "SUCCEEDED\n"; $SUCCESSES++;


#
# Test 40
#
($exitstatus, $output) =
    &runtest("myproxy-logon -a \$X509_USER_PROXY -k renew -t 1 -o $tmpdir/myproxy-test.$$ -v", undef);
print "MyProxy Test 40 (verify renewed limited proxy is still limited): ";
if ($exitstatus == 0) {
	($exitstatus, $output) =
	    &verifyproxy("$tmpdir/myproxy-test.$$");
} elsif ($output =~ /self-authz not allowed/) {
    $exitstatus = 0;            # default policy will give this response
}
if ($exitstatus != 0) {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
    goto cleanup_limited;
}
if (!`$grid_proxy_info -file $tmpdir/myproxy-test.$$ -type` =~ /limited/) {
    print "FAILED\nRetrieved proxy is not limited.\n"; $FAILURES++; 
}
print "SUCCEEDED\n"; $SUCCESSES++;

cleanup_limited:
&runtest("myproxy-destroy -v", undef);
&runtest("myproxy-destroy -v -k renew", undef);
rename("\$X509_USER_PROXY.orig", "\$X509_USER_PROXY");

#
# Test 40.a
#
if ($startserver && defined($serverpid)) { # only case we have direct access to server
#  ($exitstatus, $output) = kill('HUP', $serverpid);
  ($exitstatus, $output) = &runtest("/bin/kill -HUP $serverpid");
  print "MyProxy Test 40.a (kill -HUP $serverpid): ";
  if ($exitstatus != 0) {
      print "FAILED with $exitstatus\n"; $FAILURES++;
      print STDERR $output;
  } else {
    print "SUCCEEDED\n"; $SUCCESSES++;
  }
} else {
  print "MyProxy Test 40.a (kill -HUP <myproxy-server>): SKIPPED\n";
}


#
# Test 41
#
$ENV{'X509_CERT_DIR'} = $trustrootdir;
($exitstatus, $output) =
  &runtest("myproxy-get-trustroots -v", undef);
print "MyProxy Test 41 (retrieve trustroots w/o authentication): ";
if ($exitstatus == 0) {
  ($exitstatus, $output) =
    &verifytrustroots();
}
if ($exitstatus == 0) {
  print "SUCCEEDED\n"; $SUCCESSES++;
} else {
  print "FAILED\n"; $FAILURES++; print STDERR $output;
}
if (defined($origtrustrootdir)) {
  $ENV{'X509_CERT_DIR'} = $origtrustrootdir;
} else {
  delete $ENV{'X509_CERT_DIR'};
}

#
# Test 42
#
if ($startserver) { # only way to know check_multiple_credentials is true
  $passphrase = sprintf "%010.d", int(rand(0x7fffffff));
  ($exitstatus, $output) =
    &runtest("myproxy-init -v -a -k multiple -c 1 -t 1 -S",
             $passphrase . "\n");
  print "MyProxy Test 42 (check_multiple_credentials): ";
  if ($exitstatus == 0) {
    ($exitstatus, $output) =
      &runtest("myproxy-logon -k multiple -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
               $passphrase . "\n");
  }
  if ($exitstatus == 0) {
    $passphrase = sprintf "%010.d", int(rand(0x7fffffff));
    ($exitstatus, $output) =
      &runtest("myproxy-logon -k multiple -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
               $passphrase . "\n");
    if ($exitstatus == 0) {
      print "FAILED\n"; $FAILURES++;
      print STDERR "Shouldn't have allowed retrieval with bad passphrase.\n";
      print STDERR $output;
    } else {
      print "SUCCEEDED\n"; $SUCCESSES++;
    }
  } else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
  }
  &runtest("myproxy-destroy -v -k multiple", undef);
} else {
  print "MyProxy Test 42 (check_multiple_credentials): SKIPPED\n";
}

#
# Test 43
#
if ($startserver) { # only case we have direct access to repository
  ($exitstatus, $output) =
    &runtest("myproxy-init -v -a -l test-user1 -c 2 -t 2 -S",
             $passphrase . "\n");
  print "MyProxy Test 43 (myproxy-admin-query): ";
  if ($exitstatus == 0) {
    ($exitstatus, $output) =
      &runtest("myproxy-init -v -a -l test-user2 -k test-credname -c 4 -t 4 -S",
               $passphrase . "\n");
  }
  if ($exitstatus == 0) {
    ($exitstatus, $output) =
      &runtest("myproxy-admin-query -s $serverdir -c $serverconf");
    @usernames = split(/username/, $output);
    if ($#usernames != 2) {
      $exitstatus = 1;
      print "FAILED\n"; $FAILURES++;
      print STDERR "CASE 1: Should have returned two credentials. Found ",
        $#usernames, ".\n";
      print STDERR $output;
    }
  }
  if ($exitstatus == 0) {
    ($exitstatus, $output) =
      &runtest("myproxy-admin-query -l test-user1 -s $serverdir -c $serverconf");
    @usernames = split(/username/, $output);
    if ($#usernames != 1) {
      $exitstatus = 1;
      print "FAILED\n"; $FAILURES++;
      print STDERR "CASE 2: Should have returned one credential. Found ",
        $#usernames, ".\n";
      print STDERR $output;
    }
  }
  if ($exitstatus == 0) {
    ($exitstatus, $output) =
      &runtest("myproxy-admin-query -e 5 -s $serverdir -c $serverconf");
    @usernames = split(/username/, $output);
    if ($#usernames != 2) {
      $exitstatus = 1;
      print "FAILED\n"; $FAILURES++;
      print STDERR "CASE 3: Should have returned two credentials. Found ",
        $#usernames, ".\n";
      print STDERR $output;
    }
  }
  if ($exitstatus == 0) {
    ($exitstatus, $output) =
      &runtest("myproxy-admin-query -t 5 -s $serverdir -c $serverconf");
    @usernames = split(/username/, $output);
    if ($#usernames != 0) {
      $exitstatus = 1;
      print "FAILED\n"; $FAILURES++;
      print STDERR "CASE 4: Should have returned no credentials. Found ",
        $#usernames, ".\n";
      print STDERR $output;
    }
  }
  if ($exitstatus == 0) {
    ($exitstatus, $output) =
      &runtest("myproxy-admin-query -e 3 -s $serverdir -c $serverconf");
    @usernames = split(/username/, $output);
    if ($#usernames != 1) {
      $exitstatus = 1;
      print "FAILED\n"; $FAILURES++;
      print STDERR "CASE 5: Should have returned one credential. Found ",
        $#usernames, ".\n";
      print STDERR $output;
    }
  }
  if ($exitstatus == 0) {
    ($exitstatus, $output) =
      &runtest("myproxy-admin-query -t 3 -s $serverdir -c $serverconf");
    @usernames = split(/username/, $output);
    if ($#usernames != 1) {
      $exitstatus = 1;
      print "FAILED\n"; $FAILURES++;
      print STDERR "CASE 6: Should have returned one credential. Found ",
        $#usernames, ".\n";
      print STDERR $output;
    }
  }
  if ($exitstatus == 0) {
    ($exitstatus, $output) =
      &runtest("myproxy-admin-query -e 1 -s $serverdir -c $serverconf");
    @usernames = split(/username/, $output);
    if ($#usernames != 0) {
      $exitstatus = 1;
      print "FAILED\n"; $FAILURES++;
      print STDERR "CASE 7: Should have returned no credentials. Found ",
        $#usernames, ".\n";
      print STDERR $output;
    }
  }
  if ($exitstatus == 0) {
    ($exitstatus, $output) =
      &runtest("myproxy-admin-query -t 1 -s $serverdir -c $serverconf");
    @usernames = split(/username/, $output);
    if ($#usernames != 2) {
      $exitstatus = 1;
      print "FAILED\n"; $FAILURES++;
      print STDERR "CASE 8: Should have returned two credentials. Found ",
        $#usernames, ".\n";
      print STDERR $output;
    }
  }
  if ($exitstatus == 0) {
    ($exitstatus, $output) =
      &runtest("myproxy-admin-query -i -s $serverdir -c $serverconf");
    @usernames = split(/username/, $output);
    if ($#usernames != 0) {
      $exitstatus = 1;
      print "FAILED\n"; $FAILURES++;
      print STDERR "CASE 9: Should have returned no credentials. Found ",
        $#usernames, ".\n";
      print STDERR $output;
    }
  }
  if ($exitstatus == 0) {
    ($exitstatus, $output) =
      &runtest("myproxy-admin-query -r -s $serverdir -c $serverconf");
  }
  if ($exitstatus == 0) {
    ($exitstatus, $output) =
      &runtest("myproxy-admin-query -s $serverdir -c $serverconf");
    @usernames = split(/username/, $output);
    if ($#usernames != 0) {
      $exitstatus = 1;
      print "FAILED\n"; $FAILURES++;
      print STDERR "CASE 10: Should have returned no credentials. Found ",
        $#usernames, ".\n";
      print STDERR $output;
    }
  }
  if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
  }
} else {
  print "MyProxy Test 43 (myproxy-admin-query): SKIPPED\n";
}

myproxy_header_test:
#
# Test 44
#
chomp($gcc = `which gcc 2>/dev/null`);
if (-x $gcc &&
    defined($ENV{'GLOBUS_LOCATION'}) &&
    -d "$ENV{'GLOBUS_LOCATION'}/include") {
  &write_myproxy_header_test;
  $basedir = "$ENV{'GLOBUS_LOCATION'}/include";
  $includedirs = "-I$basedir";
  opendir(DIRHANDLE, "$basedir")
    || die "can't opendir $basedir: $!";
  while (defined($filename = readdir(DIRHANDLE))) {
	next if $filename =~ /^\.\.?$/;     # skip . and ..
    if (-d "$basedir/$filename") {
      $includedirs .= " -I$basedir/$filename";
    }
  }
  closedir(DIRHANDLE);
  # should really just make this a recursive search...
  $basedir = "$ENV{'GLOBUS_LOCATION'}/include/globus";
  if (opendir(DIRHANDLE, "$basedir")) {
    while (defined($filename = readdir(DIRHANDLE))) {
      next if $filename =~ /^\.\.?$/;     # skip . and ..
      if (-d "$basedir/$filename") {
        $includedirs .= " -I$basedir/$filename";
      }
    }
    closedir(DIRHANDLE);
  }
  ($exitstatus, $output) =
    &runcmd("$gcc $includedirs -o $tmpdir/myproxy-header $tmpdir/myproxy.c");
  print "MyProxy Test 44 (myproxy.h): ";
  if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
  } else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
  }
} else {
  print "MyProxy Test 44 (myproxy.h): SKIPPED\n";
}

#
# Test 45
#
$SAVED_LOGNAME = $ENV{'LOGNAME'};
$ENV{'LOGNAME'} =  $ENV{'LOGNAME'} . "ruld9ocitegdatNigWaiwacWowd5blerUdCaxVanurs4OtNimEsDeicEgOakEkavTykEvenIpRipCarattAidcack3grirtigrimhuatwykCoth5QuicAtJawmAdutbi0QuekKabCugNelgAneuvCavNokdejnilevityixafyudGujBekIgDoadjel9shraruld9ocitegdatNigWaiwacWowd5blerUdCaxVanurs4OtNimEsDeicEgOakEkavTykEvenIpRipCarattAidcack3grirtigrimhuatwykCoth5QuicAtJawmAdutbi0QuekKabCugNelgAneuvCavNokdejnilevityixafyudGujBekIgDoadjel9shraruld9ocitegdatNigWaiwacWowd5blerUdCaxVanurs4OtNimEsDeicEgOakEkavTykEvenIpRipCarattAidcack3grirtigrimhuatwykCoth5QuicAtJawmAdutbi0QuekKabCugNelgAneuvCavNokdejnilevityixafyudGujBekIgDoadjel9shraruld9ocitegdatNigWaiwacWowd5blerUdCaxVanurs4OtNimEsDeicEgOakEkavTykEvenIpRipCarattAidcack3grirtigrimhuatwykCoth5QuicAtJawmAdutbi0QuekKabCugNelgAneuvCavNokdejnilevityixafyudGujBekIgDoadjel9shraruld9ocitegdatNigWaiwacWowd5blerUdCaxVanurs4OtNimEsDeicEgOakEkavTykEvenIpRipCarattAidcack3grirtigrimhuatwykCoth5QuicAtJawmAdutbi0QuekKabCugNelgAneuvCavNokdejnilevityixafyudGujBekIgDoadjel9shraruld9ocitegdatNigWaiwacWowd5blerUdCaxVanurs4OtNimEsDeicEgOakEkavTykEvenIpRipCarattAidcack3grirtigrimhuatwykCoth5QuicAtJawmAdutbi0QuekKabCugNelgAneuvCavNokdejnilevityixafyudGujBekIgDoadjel9shra";
($exitstatus, $output) =
    &runtest("myproxy-init -v -a -c 1 -t 1 -S", $passphrase . "\n");
if ($exitstatus == 0) {
    ($exitstatus, $output) =
        &runtest("myproxy-logon -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
                 $passphrase . "\n");
}
print "MyProxy Test 45 (verify long username handling): ";
if ($exitstatus == 0) {
	($exitstatus, $output) =
	    &verifyproxy("$tmpdir/myproxy-test.$$");
}
if ($exitstatus == 0) {
    print "SUCCEEDED\n"; $SUCCESSES++;
} else {
    print "FAILED\n"; $FAILURES++; print STDERR $output;
}
$ENV{'LOGNAME'} = $SAVED_LOGNAME;



#
# COG tests
#
if (defined($ENV{"COG_INSTALL_PATH"})) {
    &docogtests();
} else {
    print "\$COG_INSTALL_PATH undefined. Skipping Java CoG tests.\n";
}

#
# END TESTS
#
end_of_all_tests:
&docleanup();

print "MyProxy Tests Complete: ", $SUCCESSES, " tests passed, ";
print $FAILURES, " tests failed\n";

if (defined($valgrind)) {
    `cat $tmpdir/valgrind.log.* > valgrind.log.$$`;
    if (-s "valgrind.log.$$") {
	print "Valgrind errors in valgrind.log.$$.\n";
#	$FAILURES++;
    } else {
	print "Valgrind found no errors.\n";
	unlink("valgrind.log.$$");
    }
}

exit $FAILURES;

#
# SUBROUTINES
#

sub runtest {
    local($command, $input) = @_;

    if (defined($valgrind)) {
        $valgrindlog = File::Temp::tempnam($tmpdir, "valgrind.log.");
        $valgrindlogopt = " --log-file=$valgrindlog ";
        $command = $valgrind . $valgrindlogopt . $command;
    }
    return &runcmd($command, $input);
}

sub runcmd {
    local($command, $input) = @_;

    print STDERR "running: ", $command, "\n" if ($verbose); 
    $pid = open3(*Writer, *Reader, '', "exec $command") ||
	die "failed to run $command";
    print Writer $input if (defined($input));
    close(Writer);
    @output = <Reader>;
    close(Reader);
    waitpid($pid, 0);
    $exitstatus = $?;
    $output = join('', @output);
    print STDERR $output if ($verbose);

    return ($exitstatus, $output);
}

sub docogtests {

    $cogmyproxy = "$ENV{COG_INSTALL_PATH}/bin/myproxy -h $ENV{MYPROXY_SERVER}";

    if (defined($ENV{"MYPROXY_SERVER_DN"})) {
	$cogmyproxy .= " -s \"$ENV{MYPROXY_SERVER_DN}\"";
    }

    if (defined($ENV{"MYPROXY_SERVER_PORT"})) {
	$cogmyproxy .= " -p $ENV{MYPROXY_SERVER_PORT}";
    }

    $cogmyproxy .= " -l $ENV{'LOGNAME'}";

    $ENV{"COG_OPTS"} = " -DX509_USER_PROXY=$ENV{X509_USER_PROXY}"
                     . " -DX509_USER_CERT=$ENV{X509_USER_CERT}"
                     . " -DX509_USER_KEY=$ENV{X509_USER_KEY}";

    ($exitstatus, $output) =
	&runtest("myproxy-init -v -a -c 1 -t 1 -S",
		 $passphrase . "\n");
    if ($exitstatus == 0) {
	($exitstatus, $output) =
	    &runcmd("$cogmyproxy anonget -o $tmpdir/myproxy-test.$$",
		     $passphrase . "\n");
    }
    if ($exitstatus == 0) {
	($exitstatus, $output) =
	    &verifyproxy("$tmpdir/myproxy-test.$$");
    }
    print "MyProxy CoG Test 1 (anonget of myproxy-init credential): ";
    if ($exitstatus == 0) {
	print "SUCCEEDED\n"; $SUCCESSES++;
    } else {
	print "FAILED\n"; $FAILURES++; print STDERR $output;
    }

    if ($exitstatus == 0) {
	($exitstatus, $output) =
	    &runcmd("$cogmyproxy get -o $tmpdir/myproxy-test.$$",
		     $passphrase . "\n");
    }
    if ($exitstatus == 0) {
	($exitstatus, $output) =
	    &verifyproxy("$tmpdir/myproxy-test.$$");
    }
    print "MyProxy CoG Test 2 (get of myproxy-init credential): ";
    if ($exitstatus == 0) {
	print "SUCCEEDED\n"; $SUCCESSES++;
    } else {
	print "FAILED\n"; $FAILURES++; print STDERR $output;
    }

#   This test requires a recent Java CoG release
#   with certificate chain support:
#     (http://bugzilla.globus.org/globus/show_bug.cgi?id=1914)
#
    ($exitstatus, $output) =
        &runcmd("$cogmyproxy put -a -c 1 -t 1",
                 $passphrase . "\n");
    print "MyProxy CoG Test 3 (store credential with default name): ";
    if ($exitstatus == 0) {
        print "SUCCEEDED\n"; $SUCCESSES++;
    } else {
        print "FAILED\n"; $FAILURES++; print STDERR $output;
    }

    if ($exitstatus == 0) {
	($exitstatus, $output) =
	    &runcmd("$cogmyproxy anonget -o $tmpdir/myproxy-test.$$",
		     $passphrase . "\n");
    }
    if ($exitstatus == 0) {
	($exitstatus, $output) =
	    &verifyproxy("$tmpdir/myproxy-test.$$");
    }
    print "MyProxy CoG Test 4 (anonget of CoG stored credential): ";
    if ($exitstatus == 0) {
	print "SUCCEEDED\n"; $SUCCESSES++;
    } else {
	print "FAILED\n"; $FAILURES++; print STDERR $output;
    }

    if ($exitstatus == 0) {
	($exitstatus, $output) =
	    &runcmd("$cogmyproxy get -o $tmpdir/myproxy-test.$$",
		     $passphrase . "\n");
    }
    if ($exitstatus == 0) {
	($exitstatus, $output) =
	    &verifyproxy("$tmpdir/myproxy-test.$$");
    }
    print "MyProxy CoG Test 5 (get of CoG stored credential): ";
    if ($exitstatus == 0) {
	print "SUCCEEDED\n"; $SUCCESSES++;
    } else {
	print "FAILED\n"; $FAILURES++; print STDERR $output;
    }

    ($exitstatus, $output) = &runcmd("$cogmyproxy info", undef);
    print "MyProxy CoG Test 6 (get info for stored credentials): ";
    if ($exitstatus == 0 && $output =~ /Owner/) {
        print "SUCCEEDED\n"; $SUCCESSES++;
    } else {
        print "FAILED\n"; $FAILURES++; print STDERR $output;
    }


    ($exitstatus, $output) =
        &runcmd("$cogmyproxy destroy", undef);
    print "MyProxy CoG Test 7 (remove credential from repository): ";
    if ($exitstatus == 0 && $output =~ /was succes+fully/) {
        print "SUCCEEDED\n"; $SUCCESSES++;
    } else {
        print "FAILED\n"; $FAILURES++; print STDERR $output;
    }

    ($exitstatus, $output) =
        &runcmd("$cogmyproxy put -n -x -R '$cert_subject' -k 'mine' -c 1 -t 1",
                 $passphrase . "\n");
    print "MyProxy CoG Test 8 (store credential with renewal policy): ";
    if ($exitstatus == 0) {
      print "SUCCEEDED\n"; $SUCCESSES++;
    } else {
      print "FAILED\n"; $FAILURES++; print STDERR $output;
    }

    ($exitstatus, $output) =
      &runcmd("$cogmyproxy get -k 'mine' -a $ENV{'X509_USER_PROXY'} -t 1 -o $tmpdir/myproxy-test.$$", undef);
    print "MyProxy CoG Test 9 (renew credential): ";
    if ($exitstatus == 0) {
      ($exitstatus, $output) =
        &verifyproxy("$tmpdir/myproxy-test.$$");
    }
    if ($exitstatus == 0) {
      print "SUCCEEDED\n"; $SUCCESSES++;
    } else {
      print "FAILED\n"; $FAILURES++; print STDERR $output;
    }
    &runtest("myproxy-destroy -v -k 'mine' -d", undef);
}

#
# verify_proxy
#
# Check to see if user has a valid proxy, and verify proxy is usable
#
# Dependencies: (-x grid-proxy-info)
#
# grid-proxy-info -timeleft
#     die if no output, or output is less than 60 seconds
# $proxy = grid-proxy-info -path
# grid-proxy-init -debug -verify -cert $proxy -key $proxy
#     if $? == 0 then proxy is valid
#     if $? != 0, die, b/c proxy is invalid and won't work
#
sub verifyproxy {
    local($proxyfile) = @_;

    chomp (my $timeleft = `$grid_proxy_info -file $proxyfile -timeleft`);
    if (!defined($timeleft) || $timeleft eq "") {
	$output = "failed to verify proxy\n";
	$output .= "'grid-proxy-info -timeleft' failed\n";
	return (1, $output);
    }
    if ($timeleft < 1) {
	$output = "proxy is expired\n";
	return (1, $output);
    }
    chomp (my $proxytype = `$grid_proxy_info -file $proxyfile -type`);
    local($typeopt) = "";
    if ($proxytype =~ /legacy/) {
      $typeopt = "-old";
    } elsif ($proxytype =~ /RFC 3820 compliant/) {
      $typeopt = "-rfc";
    }
    $output = `$grid_proxy_init $PROXYBITS $typeopt -debug -verify -cert $proxyfile -key $proxyfile -valid 0:1 -out $tmpdir/tmpproxy.$$ 2>&1`;
    if ($? != 0) {
	$output = "failed to verify proxy\n" . $output;
	unlink("$tmpdir/tmpproxy.$$");
	return (1, $output);
    }

    # remove the new proxy we created for validation
    # NOTE: this does not affect the user's original proxy in any way
    unlink("$tmpdir/tmpproxy.$$");

    return (0, "");
}

#
# verifycert
#
# Check to see if user has a valid usable certificate
#
# Dependencies: (-x grid-proxy-int)
#
# grid-proxy-init -debug -verify -cert $certfile -key $keyfile
#     if $? == 0 then proxy is valid
#     if $? != 0, die, b/c proxy is invalid and won't work
#
sub verifycert {
    local($certfile, $keyfile) = @_;

    chomp (my $info = `$grid_cert_info -file $certfile`);
    local($proxytype) = "";
    if ($info =~ /Subject: .* CN=proxy|\/CN=limited proxy/) {
      $proxytype = "-old";
    } elsif ($info =~ /1.3.6.1.4.1.3536.1.222/) {
      # no option for this -- hope for the best
    } elsif ($info =~ /1.3.6.1.5.5.7.1.14/) {
      $proxytype = "-rfc";
    } elsif ($info =~ /Proxy Certificate Information/) {
      $proxytype = "-rfc";
    } else {
      # shrug
    }
    local($output) = &runcmd("$grid_proxy_init $PROXYBITS $proxytype -debug -verify -cert $certfile -key $keyfile -valid 0:1 -out $tmpdir/tmpproxy.$$ -pwstdin", $passphrase);
    if ($? != 0) {
	$output = "failed to verify certificate from: $certfile and $keyfile\n" . $output;
	unlink("$tmpdir/tmpproxy.$$");
	return (1, $output);
    }

    # remove the new proxy we created for validation
    # NOTE: this does not affect the user's original proxy in any way
    unlink("$tmpdir/tmpproxy.$$");

    return (0, "");
}

#
# verifytrustroots
#
# Check to see that trustroots were properly installed in
# ~/.globus/certificates, then remove that directory.
#
sub verifytrustroots {
    if (!(-d $trustrootdir)) {
	return (1, "trust root directory $trustrootdir doesn't exist!");
    }
    $diritems = 0;
    opendir(DIRHANDLE, $trustrootdir) or
	die "couldn't open $trustrootdir : $!";
    while (defined($filename = readdir(DIRHANDLE))) {
	next if $filename =~ /^\.\.?$/;     # skip . and ..
	$diritems++;
    }
    closedir(DIRHANDLE);
    if ($diritems == 0) {
	rmdir($trustrootdir);
	return (1, "trust root directory $trustrootdir is empty!");
    }
    `rm -rf $trustrootdir`;
    return (0, "");
}

sub opensslsanitycheck {
  $testkey = "$tmpdir/myproxy-test.$$.key";
  $cmd = "$openssl rsa -des3 -passout stdin -in $ENV{'X509_USER_KEY'} -out $testkey";
  ($exitstatus, $output) = &runcmd($cmd, $passphrase . "\n");
  if ($exitstatus) {
    print STDERR "$openssl rsa encrypt failed:\n", $cmd, "\n", $output;
    system("which $openssl");
    system("$openssl version");
    die;
  }
  $cmd = "$openssl rsa -passin stdin -in $testkey > /dev/null";
  ($exitstatus, $output) = &runcmd($cmd, $passphrase . "\n");
  if ($exitstatus) {
    print STDERR "$openssl rsa decrypt failed:\n", $cmd, "\n", $output;
    system("which $openssl");
    system("$openssl version");
    die;
  }
  unlink($testkey);
}

sub debug {
    print STDERR join('', @_), "\n" if ($verbose);
}

sub docleanup {
    unlink("$tmpdir/myproxy-test.$$");
    kill('TERM', $serverpid) if (defined($serverpid));
    unlink($SERVERPIDFILE) if (defined($SERVERPIDFILE));
    unlink($serverconf) if (defined($serverconf));
    `rm -rf $serverdir` if (defined($serverdir));
}

sub doperftests {
    &dogpiperftest();
    &doinitperftest();
    &dogetdelegperftest();
    &doinfoperftest();
    &docpperftest();
    &dodbperftest() if ($dbperformance);
    &docleanup();
}

sub dogpiperftest {
    $starttime = time();
    $i = $perfclients;
    while ($i--) {
	$pid = fork();
	last if ($pid == 0);
    }
    if ($pid == 0) {
	$i = $perfiters;
	while ($i--) {
	    ($exitstatus, $output) =
          &runcmd("grid-proxy-init $PROXYBITS -hours 1 -out $tmpdir/myproxy-test.$$", undef);
	    if ($exitstatus != 0) {
		print "$$: grid-proxy-init FAILED with $i iters to go.\n";
		print STDERR $output;
		exit($exitstatus>>8);
	    }
	}
	unlink("$tmpdir/myproxy-test.$$");
	&debug("$$ is done.");
	exit 0;
    }
    $i = $perfclients;
    while ($i--) {
	wait();
	if ($?) {
	    printf "child failed. aborting.\n";
	    &docleanup(); exit 1;
	}
    }
    $endtime = time();
    print $perfiters*$perfclients, " grid-proxy-inits in ";
    print $endtime-$starttime, " seconds.\n";
}

sub doinitperftest {
    $starttime = time();
    $i = $perfclients;
    while ($i--) {
	$pid = fork();
	last if ($pid == 0);
    }
    if ($pid == 0) {
	$i = $perfiters;
	while ($i--) {
	    ($exitstatus, $output) =
		&runtest("myproxy-init -v -a -c 1 -t 1 -S -k $$",
			 $passphrase . "\n");
	    if ($exitstatus != 0) {
		print "$$: myproxy-init FAILED with $i iters to go.\n";
		print STDERR $output;
		exit($exitstatus>>8);
	    }
	}
	&runtest("myproxy-destroy -v -k $$", undef);
	&debug("$$ is done.");
	exit 0;
    }
    $i = $perfclients;
    while ($i--) {
	wait();
	if ($?) {
	    printf "child failed. aborting.\n";
	    &docleanup(); exit 1;
	}
    }
    $endtime = time();
    print $perfiters*$perfclients, " myproxy-inits in ";
    print $endtime-$starttime, " seconds.\n";
}

sub dogetdelegperftest {
    ($exitstatus, $output) =
	&runtest("myproxy-init -v -a -c 1 -t 1 -S",
		 $passphrase . "\n");
    if ($exitstatus != 0) {
	print "myproxy-init failed\n"; print STDERR $output;
	exit($exitstatus>>8);
    }
    $starttime = time();
    $i = $perfclients;
    while ($i--) {
	$pid = fork();
	last if ($pid == 0);
    }
    if ($pid == 0) {
	$i = $perfiters;
	while ($i--) {
	    ($exitstatus, $output) =
		&runtest("myproxy-logon -t 1 -o $tmpdir/myproxy-test.$$ -v -S",
			 $passphrase . "\n");
	    if ($exitstatus != 0) {
		print "$$: myproxy-logon FAILED with $i iters to go.\n";
		print STDERR $output;
		exit($exitstatus>>8);
	    }
	}
	unlink("$tmpdir/myproxy-test.$$");
	&debug("$$ is done.");
	exit 0;
    }
    $i = $perfclients;
    while ($i--) {
	wait();
	if ($?) {
	    printf "child failed. aborting.\n";
	    &docleanup(); exit 1;
	}
    }
    $endtime = time();
    print $perfiters*$perfclients, " myproxy-logons in ";
    print $endtime-$starttime, " seconds.\n";
    &runtest("myproxy-destroy -v", undef);
}

sub doinfoperftest {
    ($exitstatus, $output) =
	&runtest("myproxy-init -v -a -c 1 -t 1 -S",
		 $passphrase . "\n");
    if ($exitstatus != 0) {
	print "myproxy-init failed\n"; print STDERR $output;
	exit($exitstatus>>8);
    }
    $starttime = time();
    $i = $perfclients;
    while ($i--) {
	$pid = fork();
	last if ($pid == 0);
    }
    if ($pid == 0) {
	$i = $perfiters;
	while ($i--) {
	    ($exitstatus, $output) = &runtest("myproxy-info -v", undef);
	    if ($exitstatus != 0) {
		print "$$: myproxy-info FAILED with $i iters to go.\n";
		print STDERR $output;
		exit($exitstatus>>8);
	    }
	}
	&debug("$$ is done.");
	exit 0;
    }
    $i = $perfclients;
    while ($i--) {
	wait();
	if ($?) {
	    printf "child failed. aborting.\n";
	    &docleanup(); exit 1;
	}
    }
    $endtime = time();
    print $perfiters*$perfclients, " myproxy-infos in ";
    print $endtime-$starttime, " seconds.\n";
    &runtest("myproxy-destroy -v", undef);
}

sub docpperftest {
    $starttime = time();
    $i = $perfclients;
    while ($i--) {
	$pid = fork();
	last if ($pid == 0);
    }
    if ($pid == 0) {
	($exitstatus, $output) =
	    &runtest("myproxy-init -v -a -c 1 -t 1 -S -k $$",
		     $passphrase . "\n");
	if ($exitstatus != 0) {
	    print "$$: myproxy-init FAILED with $i iters to go.\n";
	    print STDERR $output;
	    exit($exitstatus>>8);
	}
	$i = $perfiters;
	while ($i--) {
	    $old_passphrase = $passphrase;
	    $passphrase = sprintf "%010.d", int(rand(0x7fffffff));
	    ($exitstatus, $output) =
		&runtest("myproxy-change-pass-phrase -v -S -k $$",
			 "$old_passphrase\n$passphrase\n");
	    if ($exitstatus != 0) {
		print "$$: myproxy-change-pass-phrase FAILED with $i iters to go.\n";
		print STDERR $output;
		exit($exitstatus>>8);
	    }
	}
	&runtest("myproxy-destroy -v -k $$", undef);
	&debug("$$ is done.");
	exit 0;
    }
    $i = $perfclients;
    while ($i--) {
	wait();
	if ($?) {
	    printf "child failed. aborting.\n";
	    &docleanup(); exit 1;
	}
    }
    $endtime = time();
    print $perfiters*$perfclients, " myproxy-change-pass-phrases in ";
    print $endtime-$starttime, " seconds.\n";
}

sub dodbperftest {
    foreach $dbsize (10,100,1000,10000) {
	$i = $dbsize;
	while ($i--) {
	    ($exitstatus, $output) =
		&runtest("myproxy-admin-load-credential -v -d -l $i" .
			 " -c $ENV{X509_USER_CERT} -y $ENV{X509_USER_KEY}" .
			 (defined($serverdir) ? " -s $serverdir" : ""), undef);
	    if ($exitstatus != 0) {
		print "myproxy-admin-load-credential FAILED.\n";
		print STDERR $output;
		exit($exitstatus>>8);
	    }
	}
	$starttime = time();
	$i = $dbsize;
	while ($i--) {
	    ($exitstatus, $output) = &runtest("myproxy-info -v -l $i", undef);
	    if ($exitstatus != 0) {
		print "myproxy-info FAILED.\n";
		print STDERR $output;
		exit($exitstatus>>8);
	    }
	}
	$endtime = time();
	print $dbsize, " myproxy-infos in ", $endtime-$starttime, " seconds.\n";
	$starttime = $endtime;
	$i = $dbsize;
	while ($i--) {
	    ($exitstatus, $output) = &runtest("myproxy-destroy -v -l $i",
					      undef);
	    if ($exitstatus != 0) {
		print "myproxy-destroy FAILED.\n";
		print STDERR $output;
		exit($exitstatus>>8);
	    }
	}
	$endtime = time();
	print $dbsize, " myproxy-destroys in ";
	print $endtime-$starttime, " seconds.\n";
    }
}

sub openport {
  $sockaddr = 'S n a4 x8';
  $host = "127.0.0.1";
  local($port) = @_;
  @list = getprotobyname('tcp');
  $proto = $list[2];
  @list = gethostbyaddr(inet_aton($host), AF_INET);
  $addr = $list[4];
  while ($port < 65535) {
    $destaddr = pack($sockaddr, AF_INET, $port, $addr);
    socket(S, AF_INET, SOCK_STREAM, $proto) || die $!;
    connect(S, $destaddr);
    if ($! =~ /Connection refused/) {
      return $port;
    }
    close(S);
    $port++;
  }
  die "failed to find available port";
}

sub write_myproxy_header_test {
  open(SRC, ">$tmpdir/myproxy.c") ||
    die "failed to open $tmpdir/myproxy.c, stopped";
  print SRC <<EOF;
#include <myproxy.h>
int main() { return 0; }
EOF
  close(SRC);
}

sub write_valgrind_supp {
    open(SUPP, ">$tmpdir/valgrind.supp") ||
        die "failed to open $tmpdir/valgrind.supp, stopped";
    print SUPP <<EOF;
{
   SSL_library_init
   Memcheck:Leak
   ...
   fun:SSL_library_init
   ...
}
{
   SSL_load_error_strings
   Memcheck:Leak
   ...
   fun:SSL_load_error_strings
   ...
}
{
   ERR_load_SSL_strings
   Memcheck:Leak
   ...
   fun:ERR_load_SSL_strings
   ...
}
{
   OpenSSL_add_all_ciphers
   Memcheck:Leak
   ...
   fun:OpenSSL_add_all_ciphers
   ...
}
{
   getpwuid
   Memcheck:Leak
   ...
   fun:getpwuid
   ...
}
{
   getpw
   Memcheck:Leak
   ...
   fun:getpw
   ...
}
{
   tzset
   Memcheck:Leak
   ...
   fun:tzset
   ...
}
{
   localtime
   Memcheck:Leak
   ...
   fun:localtime
   ...
}
{
   gmtime
   Memcheck:Leak
   ...
   fun:gmtime
   ...
}
{
   gethostbyname
   Memcheck:Leak
   ...
   fun:gethostbyname
   ...
}
{
   sysloginitnotify
   Memcheck:Leak
   ...
   fun:_sl_init_notify
   ...
}
{
   AES_cbc_encrypt
   Memcheck:Addr4
   fun:AES_cbc_encrypt
}
{
   globus_i_gsi_gss_create_cred-fixed-Jan2009
   Memcheck:Leak
   fun:malloc
   ...
   fun:globus_gsi_cred_get_cert_chain
   fun:globus_i_gsi_gss_create_cred
   ...
}
{
   globus_gss_assist_acquire_cred
   Memcheck:Leak
   ...
   fun:CRYPTO_malloc
   ...
   fun:X509_STORE_new
   fun:SSL_CTX_new
   ...
   fun:globus_gss_assist_acquire_cred
   ...
}
{
   X509_STORE_CTX_get_ex_new_index
   Memcheck:Leak
   ...
   fun:CRYPTO_malloc
   ...
   fun:X509_STORE_CTX_get_ex_new_index
   ...
}
{
   globus_gss_assist_acquire_cred_new_ex_data
   Memcheck:Leak
   ...
   fun:CRYPTO_malloc
   ...
   fun:CRYPTO_new_ex_data
   ...
   fun:globus_gss_assist_acquire_cred
   fun:GSI_SOCKET_authentication_init
   ...
}
{
   globus_gss_assist_acquire_cred_asn1_item_d2i
   Memcheck:Leak
   ...
   fun:CRYPTO_malloc
   ...
   fun:ASN1_item_d2i
   ...
   fun:globus_gss_assist_acquire_cred
   fun:GSI_SOCKET_authentication_init
   ...
}
{
   gss_release_name
   Memcheck:Leak
   ...
   fun:gss_release_name
   fun:globus_gss_assist_accept_sec_context
   ...
}
{
   globus_i_gsi_gss_handshake
   Memcheck:Leak
   ...
   fun:globus_i_gsi_gss_handshake
   fun:gss_accept_sec_context
   fun:globus_gss_assist_accept_sec_context
   ...
}
{
   GSI_SOCKET_check_creds
   Memcheck:Leak
   ...
   fun:globus_gss_assist_acquire_cred
   fun:GSI_SOCKET_check_creds
   ...
}
{
   globus_gss_assist_init_sec_context
   Memcheck:Leak
   ...
   fun:globus_gss_assist_init_sec_context
   fun:GSI_SOCKET_authentication_init
   fun:myproxy_authenticate_init
   fun:myproxy_bootstrap_client
   ...
}
{
   globus_module_activate
   Memcheck:Leak
   ...
   fun:globus_module_activate
   ...
}
{
   __libc_dlopen_mode
   Memcheck:Addr4
   ...
   fun:__libc_dlopen_mode
   fun:__nss_lookup_function
   ...
}
{
   InitProxyCertInfoExtension
   Memcheck:Leak
   ...
   fun:OBJ_txt2obj
   fun:InitProxyCertInfoExtension
   ...
   fun:VOMS_Init
   ...
}
EOF
    close(SUPP);
}
