ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/WEBTOOLS/SecurityModule/SecurityModule.pm
(Generate patch)

Comparing COMP/WEBTOOLS/SecurityModule/SecurityModule.pm (file contents):
Revision 1.1 by dfeichti, Wed Feb 7 11:46:10 2007 UTC vs.
Revision 1.2 by dfeichti, Fri Feb 16 10:25:08 2007 UTC

# Line 37 | Line 37 | REQCERT_FAIL_HANDLER REVPROXY_MODE);
37    $self->{CALLER_URL}=""; # true URL (including any proxy transform.)
38  
39    $self->{ERRMSG} = "";
40 <  $self->{LOGFILE} = "/tmp/SecMod.log"; #maybe default to apache log
40 >  $self->{LOGFILE} = undef; # defaults to stderr (apache err log)
41    $self->{LOGH} = undef; # Log filehandle
42    $self->{LOGLEVEL} = 1;
43  
# Line 316 | Line 316 | sub _cookieAuthen {
316    }
317  
318    my ($state,$user,$time,$orighash) = $self->_decryptCookie($cookie);
319 <  #TODO test cookie time in addition to key validity time?
319 >  #TODO test cookie creation time in addition to key validity time?
320    if($state==0 && $orighash eq $self->_getOriginatorHash()) {
321      $self->{AUTHNSTATE} = "passwd";
322      $self->{USERDN} = $user;
# Line 342 | Line 342 | sub _log {
342  
343    return if($level>$self->{LOGLEVEL});
344  
345 +  my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
346 +  $year+=1900;
347 +  $mon++;
348 +  my $date = sprintf("$year-%02d-%02d %02d:%02d:%02d",
349 +                     $mon,$mday,$hour,$min,$sec);
350 +
351 +  if (! $self->{LOGFILE}) {
352 +    print STDERR "$self->{REMOTE_ADDR} $date SecurityModule: $msg\n";
353 +    return 0;
354 +  }
355 +
356    if( !$self->{LOGH} ) {
357      if(! ($self->{LOGH} = IO::File->new(">>$self->{LOGFILE}")) )  {
358        $self->{ERRMSG} = "Failed to open logfile " . $self->{LOGFILE};
359 <      print STDERR "Failed to open logfile " . $self->{LOGFILE}
359 >      print STDERR "$date SecurityModule: Failed to open logfile " . $self->{LOGFILE}
360          . ": $msg\n";
361        return 1;
362      }
363      chmod 0600,$self->{LOGFILE};
364    }
365  
366 <  my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
356 <  $year+=1900;
357 <  $mon++;
366 >
367    #TODO: better log date formatting
368 <  print {$self->{LOGH}} "$year-$mon-$mday $hour:$min:$sec (L$level)" . $msg . "\n";
368 >  print {$self->{LOGH}} "$self->{REMOTE_ADDR} $date (L$level)" . $msg . "\n";
369  
370    return 0;
371   }
# Line 499 | Line 508 | sub _passwordAuthen {
508    if ($dbpasswd eq $hash) {
509      $self->{AUTHNSTATE} = "passwd";
510      if ($self->{USERDN} = $self->_getDNfromUsername($username)) {
511 <      #TODO: set correct expires value
511 >      # for now we use no 'expires' value -expires =>'',
512        $self->{COOKIE} = cookie(-name => "SecMod",
513                                 -value => $self->_prepareCookie(),
505                               -expires =>'+5h',
514                                 -secure => 1
515                                );
516 +      $self->_log(4,"Successful password authentication by $username for $self->{USERDN}");
517        return(1);
518      }
519  
520 <
512 <    #TODO: if the entry is not present we should probably set it based
513 <    #      on the current USERDN from the SSL authentication
520 >    $self->_log(3,"No distinguished name known for user $username");
521      $self->{ERRMSG} = "No distinguished name known for user $username";
522      return(0);
523    }
524  
525    $self->{ERRMSG} = "Password verification failed";
526 +  $self->_log(3,"Password verification failed for user $username");
527    # TODO: pass on amount of failed attempts in hidden field and redirect after certain
528    # number of failures?
529    return(0);
# Line 575 | Line 583 | sub _reqcertFailHandler {
583    if ($authnstate eq "passwd") {
584      print " (and you are logged in via password)";
585    } else {
586 <    print $q->p,"Your Browser presented: " . $userdn if $userdn;
586 >    print $q->p,"Your Browser presented this certificate: " . $userdn if $userdn;
587    }
588    print $q->end_html;
589    exit(0);
# Line 609 | Line 617 | a SecurityModule::SQLite implementation.
617  
618    $errmsg = $sec->getErrMsg(); # returns error message
619  
620 <  # if getCookie() is defined, your page needs to make sure that this
621 <  # cookie will be set using CGI.pm's header(-cookie => $cookie )
620 >  # if getCookie() returns a defined value, your page needs to make
621 >  # sure that this cookie will be set using CGI.pm's
622 >  # header(-cookie => $cookie ) command
623    if( ($cookie=$sec->getCookie) ) {
624      print header(-cookie => $cookie );
625    } else {
# Line 621 | Line 630 | a SecurityModule::SQLite implementation.
630    # Access to authentication / authorization information
631    $state = $sec->getAuthnState(); # returns (failed | cert | passwd)
632    $user_dn = $sec->getDN(); # returns user's distinguished name
633 <  $roles = $sec->getRoles(); # returns a hash of roles, each role pointing to a
633 >  $roles = $sec->getRoles(); # returns a hash of roles, each role mapping to a
634                               # list of scopes
635  
636  
# Line 638 | Line 647 | a SecurityModule::SQLite implementation.
647   =head1 DESCRIPTION
648  
649   The SecurityModule handles authentication and authorization to a web site. Users
650 < are identified via a certificate loaded in their browser or via a previously
650 > are identified by a certificate loaded in their browser or by a previously
651   set cookie that was issued upon a successful password authentication.
652  
653 + Certificate based authentication is the strongest authentication type,
654 + so functions protected by the reqAuthnPasswd() method will allow
655 + access to certificate authenticated users, but reqAuthnCert() will deny
656 + access to password authenticated users.
657 +
658   The SecurityModule was written for a setup where a B<remote Proxy> mediates access
659   to a number of backend servers. The remote proxy handles
660 < the SSL authentication and sets the following request headers to
660 > the SSL authentication and is required to set the following request headers to
661   the values of the respective environment variables for this request:
662  
663   B<SSL_CLIENT_VERIFY>,
# Line 669 | Line 683 | Arguments which can be passed to the con
683  
684   =item *
685  
686 < B<CALLER_URL>: URL of the current page that was invoked by the browser, i.e. it
687 < must contain the URL which the reverse proxy got before redirecting to the backend
688 < server.
686 > B<CALLER_URL>: (Required) URL of the current page that was invoked by
687 > the browser, i.e. it must contain the URL which the reverse proxy got
688 > before redirecting to the backend server.
689  
690   =item *
691  
# Line 710 | Line 724 | back) and a status message describing wh
724   called. If an URL is given, the two values will be passed using a
725   query string (?caller_url=...&msg=...) in the redirection.
726  
727 < Status messages: password authentication required, reauthentication, invalid cookie
727 >        Status messages: password authentication required
728 >                         reauthentication
729 >                         invalid cookie
730  
731   =item *
732  
# Line 724 | Line 740 | B<LOGFILE>: Filename of the logfile
740  
741   =item *
742  
743 < B<LOGLEVEL>: (from 1 to 5)
743 > B<LOGLEVEL>: Integer value from 0-5
744 >
745 >      0: no log messages at all
746 >      1: error and security relevant messages only
747 >      3: Logs password authentications (standard log level)
748 >      5: debugging messages
749  
750   =item *
751  
# Line 738 | Line 759 | with the location of the data base file.
759  
760   =back
761  
762 < =head2 Calling the password form via a page "Login" link:
762 > =head2 Calling the password form via a web page "Login" link:
763  
764   You can pass B<SecModPwd=1> as a GET variable to any page using the
765   SecurityModule. This will call the handler for / redirect to the password form
# Line 764 | Line 785 | POST arguments are not carried across th
785  
786   =item *
787  
788 < The mapping from username to certificate distinguished name needs to be established,
789 < either by letting a cert authenticated user log in and storing his username, or by
769 < providing a special page where the user can password authenticate and establish the
770 < mapping.
788 > The mapping from username to certificate distinguished name needs to be established
789 > separately.
790  
791   =item *
792  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines