# -*- perl -*- # # Copyright (c) 2003-2007 by Jeremy Kister # Author: Jeremy Kister # Date: 2007/07/09 16:06 (EDT) # Function: authenticate via sql server # # take a look at http://jeremy.kister.net/ # for hosting/colo/Internet stuff, check out http://www.nntx.net # Table structure for table `users` # # CREATE TABLE `users` ( # `id` int(10) unsigned NOT NULL auto_increment, # `username` varchar(16) NOT NULL default '', # `crypt` char(13) NOT NULL default '', # `home` varchar(255) NOT NULL default '', # `pref` varchar(255) NOT NULL default '-', # `groups` varchar(255) NOT NULL default '', # PRIMARY KEY (`id`), # KEY `username` (`username`), # ) TYPE=MyISAM COMMENT='argus.example.net user data' AUTO_INCREMENT=1 ; # # Table structure for table `sessions` # # CREATE TABLE `sessions` ( # `id` int(10) unsigned NOT NULL, # `sess_id` char(64) NOT NULL default '', # `start` int(10) unsigned NOT NULL default '0', # `hush` int(10) unsigned NOT NULL default '0', # PRIMARY KEY (`sess_id`), # ) TYPE=MyISAM COMMENT='argus.example.net session data' ; # # INSERT INTO argus VALUES ('anonymous', 'any', 'Top', 'user'); use DBI; my $dbun = 'db_username'; my $dbpw = 'db_password'; my $dsn = 'DBI:mysql:host=mysql.example.net;database=argus'; my $dbh; sub db_connect { my $tries = 1; until(dbping($dbh)){ eval { local $SIG{ALRM} = sub { die "DBI connect timeout!\n"; }; alarm(5); $dbh = DBI->connect($dsn, $dbun, $dbpw); alarm(0); }; alarm(0); sleep 1; $tries++; if($tries == 3){ # arbitrary die "cannot connect to database after 3 tries.\n"; } } $dbh; } sub auth_session { my $sess_id = shift; # returns (username,start,last,home,groups) on success # undef on failure eval { local $SIG{ALRM} = sub { die "auth_session timeout!\n"; }; alarm(5); db_connect() unless(dbping($dbh)); my $sql = 'SELECT users.username,sessions.start,sessions.hush,users.home,sessions.pref,users.groups'; $sql .= ' FROM users,sessions'; $sql .= ' WHERE users.id = sessions.id AND sessions.sess_id = ' . $dbh->quote($sess_id); my $sth = $dbh->prepare($sql); $sth->execute; my $row = $sth->fetchrow_arrayref; alarm(0); return (@{$row} == 6) ? @{$row} : undef; }; alarm(0); if($@){ warn "timed out connecting to database ($@): allowing root login from [$ENV{'REMOTE_ADDR'}].\n"; return('root',time(),0,'Top','-','root'); # dont want to be blind if db is off-line } return; } sub auth_user { my $user = shift; my $pass = shift; my $sess_id = shift; # returns (home_obj, groups) on success # undef on failure eval { local $SIG{ALRM} = sub { die "auth_user timeout!\n"; }; alarm(5); db_connect() unless(dbping($dbh)); my $sql = 'SELECT id,crypt,home,groups FROM users WHERE username = ' . $dbh->quote($user); my $sth = $dbh->prepare($sql); $sth->execute; my $row=$sth->fetchrow_arrayref; my ($id,$crypt,$home) = ($row->[0],$row->[1],$row->[2]); my @cgroups = split /\s+/, $row->[3]; if( (($crypt eq crypt($pass, $crypt)) && defined($crypt)) || ($crypt eq 'any') ){ my $sql = 'INSERT INTO sessions (id,sess_id,start) VALUES ('; $sql .= $dbh->quote($id) . ',' . $dbh->quote($sess_id) . ','; $sql .= $dbh->quote(time()) . ')'; # start my $sth = $dbh->prepare($sql); $sth->execute; alarm(0); return ($home, @cgroups); } alarm(0); }; alarm(0); if($@){ warn "timed out connecting to database ($@): allowing root for user [${user}] from [$ENV{'REMOTE_ADDR'}].\n"; return('Top','root'); # dont want to be blind if db is off-line } return; } sub dbping { my $test_dbh = shift; my $xcode = 0; eval { $SIG{ALRM} = sub { die "dbping timeout!"; }; alarm(2); if($test_dbh){ if(my $sth = $test_dbh->prepare('SELECT 1')){ if(defined(my $rc = $sth->execute)){ $sth->finish; $xcode=1; # good } } } alarm(0); }; alarm(0); return $xcode; } 1;