#!@PERL@ use strict; use DBI; use Getopt::Long; use Pod::Usage; $|=1; =pod =head1 NAME db_auth.pl - Database auth helper for Squid =cut my $dsn = "DBI:mysql:database=squid"; my $db_user = undef; my $db_passwd = undef; my $db_table = "passwd"; my $db_usercol = "user"; my $db_passwdcol = "password"; my $db_cond = "enabled = 1"; my $plaintext = 0; my $persist = 0; =pod =head1 SYNOPSIS db_auth.pl [options] =head1 DESCRIPTOIN This program verifies username & password to a database =over 8 =item B<--dsn> Database DSN. Default "DBI:mysql:database=squid" =item B<--user> Database User =item B<--password> Database password =item B<--table> Database table. Default "passwd". =item B<--usercol> Username column. Default "user". =item B<--passwdcol> Password column. Default "password". =item B<--cond> Condition, defaults to enabled=1. Specify 1 or "" for no condition =item B<--plaintext> Database contains plain-text passwords =item B<--persist> Keep a persistent database connection open between queries. =back =cut GetOptions( 'dsn=s' => \$dsn, 'user=s' => \$db_user, 'password=s' => \$db_passwd, 'table=s' => \$db_table, 'usercol=s' => \$db_usercol, 'passwdcol=s' => \$db_passwdcol, 'cond=s' => \$db_cond, 'plaintext' => \$plaintext, 'persist' => \$persist, ); my ($_dbh, $_sth); sub close_db() { return if !defined($_dbh); $_dbh->disconnect(); undef $_dbh; undef $_sth; } sub open_db() { return $_sth if defined $_sth; $_dbh = DBI->connect($dsn, $db_user, $db_passwd); if (!defined $_dbh) { warn ("Could not connect to $dsn\n"); return undef; } $_sth = $_dbh->prepare("SELECT $db_passwdcol FROM $db_table WHERE $db_usercol = ?" . ($db_cond ne "" ? " AND $db_cond" : "")) || die; return $_sth; } sub check_password($$) { my ($password, $key) = @_; return 1 if crypt($password, $key) eq $key; return 1 if $plaintext && $password eq $key; return 0; } sub query_db($) { my ($user) = @_; my ($sth) = open_db() || return undef; if (!$sth->execute($user)) { close_db(); open_db() || return undef; $sth->execute($user) || return undef;; } return $sth; } my $status; while (<>) { my ($user, $password) = split; $status = "ERR"; $user =~ s/%(..)/pack("H*", $1)/ge; $password =~ s/%(..)/pack("H*", $1)/ge; $status = "ERR database error"; my $sth = query_db($user) || next; $status = "ERR unknown login"; my $row = $sth->fetchrow_arrayref() || next; $status = "ERR login failure"; next if (!check_password($password, @$row[0])); $status = "OK"; } continue { close_db() if (!$persist); print $status . "\n"; } =pod =head1 COPYRIGHT Copyright (C) 2007 Henrik Nordstrom This program is free software. You may redistribute copies of it under the terms of the GNU General Public License version 2, or (at youropinion) any later version. =cut .