All pastes #385574 Raw Edit

TicketTool

public text v1 · immutable
·published 2007-03-07 22:34 UTC
rendered paste body
package Apache2::TicketTool;
use strict;

use Apache2::RequestRec qw(user);
use Apache2::Access (); 
use Apache2::ServerUtil ();
use Apache2::Reload;
use Apache2::Const 	-compile => qw(:log OK);
use Apache2::Log ();
use Apache2::URI qw(parse uri);

use CGI::Cookie ();
use Cluster::Loader;

my %CACHE;  # cache objects by their parameters to minimize time-consuming operations

# Set up default parameters by passing in a request object
sub new 
	{
	my($class, $r) = @_;
	my %self = ();
	$self{TicketDomain} = '30';
	$self{ServerName} = $r->server->server_hostname;
	($self{TicketDomain} = $r->server->server_hostname) =~ s/^[^.]+//;
	bless(\%self,$class);
	} 

# TicketTool::authenticate()
# ($result,$explanation) = $ticketTool->authenticate($user,$passwd)
sub authenticate 
	{
	my($self, $user, $passwd) = @_;

	my $entite =Cluster::Entite->retrieve(
			email	 => $user, 
			passwd => $passwd, 
			domain => $self->{TicketDomain},
			);	
	unless (defined $entite)
		{return (undef, "password mismatch");}

	return (1, '');
	}

# TicketTool::fetch_secret()
# Call as:
# $ticketTool->fetch_secret();
sub fetch_secret 
	{
	my $self = shift;
	unless ($self->{SECRET_KEY}) 
		{
		$self->{SECRET_KEY} =  "hlaghlaghlaghlag";
		}
	$self->{SECRET_KEY};
	}

# invalidate the cached secret
sub invalidate_secret { undef shift->{SECRET_KEY}; }

# TicketTool::make_ticket()
# Call as:
# $cookie = $ticketTool->make_ticket($r);
#
sub make_ticket 
	{
	my($self, $r, $user_name) = @_;
	my $ip_address = $r->connection->remote_ip;
	my $expires = $self->{TicketExpires};
	my $now = time;
	my $secret = $self->fetch_secret() or return undef;
# SHAKE IT... 
	my $hash = MD5->hexhash($secret .
			MD5->hexhash(join ':', $secret, $ip_address, $now,
				$expires, $user_name)
			);
# ...BEFORE YOU BAKE IT !
	return CGI::Cookie->new(-name => 'Ticket',
			-path => '/',
			-domain => $self->{TicketDomain},
			-value => {
			'ip' => $ip_address,
			'time' => $now,
			'user' => $user_name,
			'hash' => $hash,
			'expires' => $expires,
			});
	}


# TicketTool::verify_ticket()
# ($result,$msg) = $ticketTool->verify_ticket($r)
sub verify_ticket 
	{
	my($self, $r) = @_;
	my %cookies = CGI::Cookie->parse($r->headers_in('Cookie'));
# Got cookies ?
	unless (%cookies)
		{
		return (0, 'user has no cookies');
		}
	unless ($cookies{'Ticket'})
		{
		return (0, 'user has no ticket')
		}
# Now we have a ticket
	my %ticket = $cookies{'Ticket'}->value;
	unless ( $ticket{'hash'} && $ticket{'user'} && $ticket{'time'} && $ticket{'expires'} )
		{	
		return (0, 'malformed ticket')
		}
	unless ($ticket{'ip'} eq $r->connection->remote_ip)
		{
		return (0, 'IP address mismatch in ticket')
		}
	unless ( (time - $ticket{'time'})/60 < $ticket{'expires'})
		{
		return (0, 'ticket has expired')
		}
	my $secret;
	unless ($secret = $self->fetch_secret)
		{
		return (0, "can't retrieve secret") 
		}
# HLAGHLAGHLAGHLAG
	my $newhash = MD5->hexhash($secret .
			MD5->hexhash(join ':', $secret,
				@ticket{qw(ip time expires user)})
			);
	unless ($newhash eq $ticket{'hash'}) 
		{
		$self->invalidate_secret;  #maybe it's changed?
			return (0, 'ticket mismatch');
		}
	$r->connection->user($ticket{'user'});
	return (1, 'ok');
	}

# $cookie = $ticketTool->make_return_address()
sub make_return_address 
	{
	my($self, $r) = @_;
	my $uri = Apache2::URI->parse($r, $r->uri);
	$uri->scheme("http");
	$uri->hostname($r->get_server_name);
	$uri->port($r->get_server_port);
	$uri->query(scalar $r->args);

	return CGI::Cookie->new
		(
		 -name => 'request_uri',
		 -value => $uri->unparse,
		 -domain => $self->{TicketDomain},
		 -path => '/'
		);
	}

1;
__END__