#!/usr/bin/perl

# EZproxy::SSO
# Written by Chris Zagar <zagar@usefulutilities.com>

package EZproxy::SSO;

use strict;

use vars qw($VERSION);
$VERSION = '1.0';

use MIME::Base64;
use Digest::SHA1;
use Crypt::CBC;
use Crypt::DES_EDE3;

sub new {
  my $package = shift;
  return bless({}, $package);
}

sub decode {
  my $self = shift;
  my ($sso, $ts, $key, $tolerance) = @_;
  if ($sso eq "" || $ts eq "" || $key eq "") {
    return $self->{'error'} = "sso, timestamp, and/or key values missing";
  }

  if (! defined $tolerance) {
    $tolerance = 60;
  }

  my $crypt = decode_base64($sso);
  my $iv = sprintf("%08x", $ts);

  my $cipher = Crypt::CBC->new( -literal_key => 1,
                                -key => $key,
                                -cipher => 'Crypt::DES_EDE3',
                                -iv => $iv,
                                -header => 'none');
  my $plain = $cipher->decrypt($crypt);
  my ($hash, $packet) = split(/\|/, $plain, 2);
  if ($packet eq "") {
    return $self->{'error'} = "Decryption failed";
  }

  my $verify = Digest::SHA1::sha1_hex($packet);
  if ($hash ne $verify) {
    return $self->{'error'} = "Hash verification failed";
  }

  ($self->{'salt'}, $self->{'datetime'}, $self->{'ip'}, $self->{'user'}) =
    split(/\|/, $packet, 4);

  if ($self->{'user'} eq "") {
    return $self->{'error'} = "Malformed packet";
  }

  $self->{'expired'} = abs($ts - time()) > $tolerance;

  return $self->{'error'} = "";
}

sub error {
  my $self = shift;
  return $self->{'error'};
}
 

sub salt {
  my $self = shift;
  return $self->{'salt'};
}
 
sub datetime {
  my $self = shift;
  return $self->{'datetime'};
}

sub ip {
  my $self = shift;
  return $self->{'ip'};
}

sub user {
  my $self = shift;
  return $self->{'user'};
}

sub expired {
  my $self = shift;
  return $self->{'expired'};
}

1;
