#!/usr/bin/perl -w # # authenticate.pl # # Code based from Eric Bivona's sidecar.pl and Omen Wild's # SSL authentication example from the PKI Lab's website # at http://www.dartmouth.edu/~pkilab # Checks first to see if a user has a valid cert in the # environment variables. If it does not, then it sends a # Sidecar request to the client. # If the script authenticates the user, then it starts sending # the file specified as part of the called URL back to the # client. # # Copyright 1996-2004 by the Trustees of Dartmouth College # require 5.002; use strict; use CGI; use CUSSP; my ($I_DN_O, $S_DN_O) = ("Dartmouth College", "Dartmouth College"); my ($error_email) = "webmaster\@dartmouth.edu"; my ($page_title) = "Dartmouth College Software Downloads"; sub verify_cert { # This routine could get arbitrarily complex. This version verifies # that the certificate was issued by Dartmouth, issued to Dartmouth, # and (optionally) that the organization the certificate was issued # to matches a regular expression. # # It returns the name of the person the cert was issued to, or undef # if not authorized. my $department_regex = shift || ""; # Check that these enviroment variables at least exist my @must_exist = ( 'SSL_CLIENT_CERT', 'SSL_CLIENT_I_DN_O', 'SSL_CLIENT_S_DN_O', 'SSL_CLIENT_S_DN_CN', 'SSL_CLIENT_S_DN_OU', 'SSL_CIPHER', ); foreach my $env (@must_exist) { if (!defined($ENV{$env}) || $ENV{$env} eq "") { return undef; } } # SSL_CIPHER: the cipher used for encryption if($ENV{'SSL_CIPHER'} =~ m/^(EXP|NULL)-/) { return undef; } # SSL_CLIENT_I_DN_O is the Organization that issued the certificate if($ENV{'SSL_CLIENT_I_DN_O'} ne $I_DN_O) { return undef; } # SSL_CLIENT_S_DN_O is the Organization that the certificate was # issued for. if($ENV{'SSL_CLIENT_S_DN_O'} ne $S_DN_O) { return undef; } # SSL_CLIENT_S_DN_OU is the Organizational Unit that the certificate was # issued for. if ($department_regex) { if ($ENV{'SSL_CLIENT_S_DN_OU'} !~ m/$department_regex/) { return undef; } } # SSL_CLIENT_S_DN_CN is the user that the certificate belongs to. return $ENV{'SSL_CLIENT_S_DN_CN'}; } sub verify_kerb { my ($rc, $em, %tckt, $key, $val); ($rc, $em, %tckt) = CUSSP::GetK4Ticket("WWW-agent", "WWW", $ENV{'REMOTE_ADDR'}, undef, $ENV{'REMOTE_PORT'}, 120); if ($rc) { return undef; } else { return $tckt{'name'}; } } { my ($cgi) = new CGI; my ($name); if ( (!defined($name = verify_cert())) && (!defined($name = verify_kerb()))) { # Authentication failed print($cgi->header(-type => "text/html"), $cgi->start_html(-title => $page_title, -author => $error_email, -base => undef)); print ("

$page_title

\n"); print($cgi->p("We are sorry, you failed in authenticating.")); print ($cgi->end_html()); } else { # print($cgi->p("Congratulations $name!"), # $cgi->p("You have successfully authenticated!")); my ($dl) = $cgi->param('file'); my ($path) = "/usr/local/apache/htdocs/downloads/secured/"; my ($cat) = "/bin/cat "; # Sanitize by making sure only valid characters are included # and that we don't have an ".." in the path if (($dl =~ /^([\w\. -\/]+)$/)) { if (!($dl =~ /\.\./)) { if (! ($dl =~ /^\//) ) { # print($cgi->p("The file you want to download is $dl\n")); if (-e $path . $dl) { my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev, $size,@rest) = stat($path . $dl); my ($filename); $filename = $dl; $filename =~ s/.*\/([\w\. -]+)$/$1/; print($cgi->header(-type => "application/octet-stream", -attachment=>"$filename", -content_length=>"$size")); system($cat . $path . $dl); } elsif ($dl eq "testing") { print($cgi->header(-type => "text/html"), $cgi->start_html(-title => $page_title, -author => $error_email, -base => undef)); print ("

$page_title

\n"); print($cgi->p("File Input: $dl")); # print ($cgi->p("Filename: $filename")); print ($cgi->end_html()); } else { # Error for file not found print($cgi->header(-type => "text/html"), $cgi->start_html(-title => $page_title, -author => $error_email, -base => undef)); print ("

$page_title

\n"); print($cgi->p("File $dl was not found.")); print ($cgi->end_html()); } exit(0); } } } print($cgi->header(-type => "text/html"), $cgi->start_html(-title => $page_title, -author => $error_email, -base => undef)); print ("

i$page_title

\n"); print($cgi->p("Malformed filename $dl ")); print ($cgi->end_html()); exit(1); } } 0;