package Splitref::auth;

use strict;
use warnings;
use Authen::PAM qw(:constants);
use Apache2::RequestRec();
use Apache2::Access();
use Apache2::ServerUtil();
use MIME::Base64;

my %AUTH;
#use Apache2::Const -compile => 'OK';

sub access_handler
{
  my $self = shift;
  my $r = shift;
#  if(!$r->some_auth_required)
#  {
#    $r->log_reason("No authentication has been configured");
#    return \&Apache2::Const::FORBIDDEN;
#  }
  ## Read the auth cookie and set our http auth info
  ## In: auth=b64(calin:blachlock)
  my %cookies = split /=|; /, $r->headers_in->{Cookie} || '';
  if($cookies{'auth'})
  {
    $cookies{'auth'} =~ s/%3D/=/g;
    $r->headers_in->set(Authorization => "Basic $cookies{'auth'}");
  }
  if($r->dir_config("ALLOWGUEST") && !$r->headers_in->get("Authorization"))
  {
    $r->headers_in->set(Authorization => "Basic ".encode_base64("GUEST:"));
  }
  
  ## Some code to verify we're allowed to get in
  return &Apache2::Const::OK;
}

sub authen_handler
{
  my $self = shift;
  my $r = shift;
  my ($tmp, $auth) = split / /, $r->headers_in->get("Authorization");
  my ($user, $pw) = split /:/, decode_base64($auth);
  my $reason;
  if($user eq "GUEST")
  {
    $reason = "Guest Access";
  }
  elsif($user eq "" || $pw eq "")
  {
    $reason = "Blank username or password";
  }
  else
  {
    $reason = &authenticate($user, $pw);
  }
  if($reason && $r->dir_config("ALLOWGUEST"))
  {
    $r->headers_in->set(Authorization => "Basic ".encode_base64("GUEST:"));
    $user = "GUEST";
    $reason = 0;
  }
  my ($res, $sent_pw) = $r->get_basic_auth_pw;
  return $res if $res != &Apache2::Const::OK;
  if($reason)
  {
    $r->note_basic_auth_failure;
    $r->log_reason($reason, $r->uri);
    return(&Apache2::Const::AUTH_REQUIRED);
  }
  if($user ne "GUEST" && !$r->dir_config("NOCOOKIE"))
  {
    my ($tmp, $auth) = split / /, $r->headers_in->get("Authorization");
    my $cookie = "auth=$auth; path=/; expires=".expires(time + 4*60*60)."; secure";
    $r->headers_out->add('Set-Cookie' => $cookie);
  }
  return &Apache2::Const::OK;
}

sub authenticate
{
  my @errors;
  $errors[10] = "Unknown User";
  $errors[7] = "Bad Password";
  my $user = shift;
  my $sent_pw = shift;
  my $auth = new Authen::PAM("passwd", $user, sub
  	{
	  return (0, $sent_pw, &PAM_SUCCESS());
	});
  my $retval = $auth->pam_authenticate();
  if($retval != &PAM_SUCCESS())
  { return "$user: $errors[$retval]"; }
}

sub expires
{
  my $time = shift;
  my @months = qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/;
  my @days = qw/Sun Mon Tue Wed Thu Fri Sat/;

  my($sec,$min,$hour,$mday,$mon,$year,$wday) = gmtime($time);
  $year += 1900;
  return sprintf("%s, %02d %s %04d %02d:%02d:%02d GMT",
  $days[$wday],$mday,$months[$mon],$year,$hour,$min,$sec);
}

1;
