package Auth; use CGI qw(:standard); use CGI::Cookie (); use MD5 (); use Crypt::CBC (); use constant COOKIE_NAME => 'Cname'; use constant SECRET => '0mn1um ex 0vum'; $CIPHER ||= Crypt::CBC->new(SECRET, 'IDEA'); sub set_cookie { my $usrname=shift; ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $year = $year + 1900; $mon++; my $time = "$year$mon$mday$hour$min$sec"; $state=initialize($state,$time,$usrname); print header(-cookie => save_state($state)); } sub initialize { my $state = shift; my $time=shift; my $usrname=shift; $state = {} unless $state; $state->{TIME} =$time ; $state->{USRNAME} = $usrname; return $state; } # Check or generate the MAC authentication information sub MAC { my($state, $action) = @_; return undef unless ref($state); my @fields = @{$state}{qw(TIME USRNAME)}; my ($newmac) = MD5->hexhash(SECRET . MD5->hexhash(join '', SECRET, @fields)); return $newmac eq $state->{MAC} if $action eq 'check'; return $state->{MAC} = $newmac if $action eq 'generate'; undef; } # Save the current state sub save_state { my $state = shift; MAC($state, 'generate'); # add MAC to the state # encrypt the cookie my $encrypted = $CIPHER->encrypt_hex(join ':', %{$state}); return CGI::Cookie->new(-name => COOKIE_NAME, -value => $encrypted, ); } # Retrieve an existing state sub get_state { my $cookie = CGI::cookie(COOKIE_NAME); return undef unless $cookie; # decrypt the cookie my %state = split ':', $CIPHER->decrypt_hex($cookie); authentication_error() unless MAC(\%state, 'check'); return \%state; } sub authentication_error { print"

Authentication error

"; } 1;