------------------------------------------------------------ revno: 12172 revision-id: squid3@treenet.co.nz-20120612085053-baco8ybi1fod0zqd parent: squid3@treenet.co.nz-20120612070102-obd4t6i3h6ha6n8m committer: Amos Jeffries branch nick: trunk timestamp: Tue 2012-06-12 20:50:53 +1200 message: SQL database session helper Session lookup helper which utilizes any SQL database backend. For now it is a read-only session lookup. Session management is expected to be controlled by an external system, such as a captive portal login page. ------------------------------------------------------------ # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: squid3@treenet.co.nz-20120612085053-baco8ybi1fod0zqd # target_branch: http://bzr.squid-cache.org/bzr/squid3/trunk/ # testament_sha1: 084c6dee88a41a87c1138b21139541acba351108 # timestamp: 2012-06-12 08:57:04 +0000 # source_branch: http://bzr.squid-cache.org/bzr/squid3/trunk/ # base_revision_id: squid3@treenet.co.nz-20120612070102-\ # obd4t6i3h6ha6n8m # # Begin patch === modified file 'configure.ac' --- configure.ac 2012-05-29 12:20:02 +0000 +++ configure.ac 2012-06-12 08:50:53 +0000 @@ -3595,6 +3595,7 @@ helpers/external_acl/LDAP_group/Makefile \ helpers/external_acl/LM_group/Makefile \ helpers/external_acl/session/Makefile \ + helpers/external_acl/SQL_session/Makefile \ helpers/external_acl/unix_group/Makefile \ helpers/external_acl/wbinfo_group/Makefile \ helpers/external_acl/time_quota/Makefile \ === modified file 'helpers/external_acl/Makefile.am' --- helpers/external_acl/Makefile.am 2011-05-09 12:42:59 +0000 +++ helpers/external_acl/Makefile.am 2012-06-12 08:50:53 +0000 @@ -6,6 +6,7 @@ LDAP_group \ LM_group \ session \ + SQL_session \ time_quota \ unix_group \ wbinfo_group === added directory 'helpers/external_acl/SQL_session' === added file 'helpers/external_acl/SQL_session/Makefile.am' --- helpers/external_acl/SQL_session/Makefile.am 1970-01-01 00:00:00 +0000 +++ helpers/external_acl/SQL_session/Makefile.am 2012-06-12 08:50:53 +0000 @@ -0,0 +1,15 @@ +include $(top_srcdir)/src/Common.am + +libexec_SCRIPTS = ext_sql_session_acl +CLEANFILES += ext_sql_session_acl ext_sql_session_acl.8 +man_MANS = ext_sql_session_acl.8 +EXTRA_DIST= \ + ext_sql_session_acl.8 \ + ext_sql_session_acl.pl.in \ + config.test + +ext_sql_session_acl.8: ext_sql_session_acl + pod2man ext_sql_session_acl ext_sql_session_acl.8 + +ext_sql_session_acl: ext_sql_session_acl.pl.in + $(subst_perlshell) === added file 'helpers/external_acl/SQL_session/config.test' --- helpers/external_acl/SQL_session/config.test 1970-01-01 00:00:00 +0000 +++ helpers/external_acl/SQL_session/config.test 2012-06-12 08:50:53 +0000 @@ -0,0 +1,7 @@ +#!/bin/sh + +## Test: do we have perl to build the helper scripts? +## Test: do we have pod2man to build the manual? +perl --version >/dev/null && echo | pod2man >/dev/null + +exit $? === added file 'helpers/external_acl/SQL_session/ext_sql_session_acl.pl.in' --- helpers/external_acl/SQL_session/ext_sql_session_acl.pl.in 1970-01-01 00:00:00 +0000 +++ helpers/external_acl/SQL_session/ext_sql_session_acl.pl.in 2012-06-12 08:50:53 +0000 @@ -0,0 +1,177 @@ +#!@PERL@ +use strict; +use DBI; +use Getopt::Long; +use Pod::Usage; +$|=1; + +=pod + +=head1 NAME + +ext_sql_session_acl.pl - SQL Database session lookup helper for Squid + +=cut + +my $dsn = "DBI:mysql:database=squid"; +my $db_user = undef; +my $db_passwd = undef; +my $db_table = "passwd"; +my $db_uidcol = "id"; +my $db_usercol = "''"; +my $db_tagcol = "''"; +my $db_cond = "enabled = 1"; +my $persist = 0; +my $debug = 0; + +=pod + +=head1 SYNOPSIS + +ext_sql_session_acl [options] + +=head1 DESCRIPTION + +Validates an HTTP requests access authorization with a session database. + +Taking an identity token to be validated (as determined by the external_acl_type format) +it returns a username or tag associated with the identity token passed in. + +Common forms of identifiers are IP address, EUI (MAC) address, passwords, or UUID tokens. + +This program uses Squid concurrency support. + +=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<--uidcol> + +Unique Session Identifier column. Default "id". + +=item B<--usercol> + +External ACL user= result column. + +=item B<--tagcol> + +External ACL tag= result column. + +=item B<--cond> + +Condition, defaults to enabled=1. Specify 1 or "" for no condition + +=item B<--persist> + +Keep a persistent database connection open between queries. + +=item B<--debug> + +Print Debug output traces to stderr. + +=back + +=cut + +GetOptions( + 'dsn=s' => \$dsn, + 'user=s' => \$db_user, + 'password=s' => \$db_passwd, + 'table=s' => \$db_table, + 'uidcol=s' => \$db_uidcol, + 'usercol=s' => \$db_usercol, + 'tagcol=s' => \$db_tagcol, + 'cond=s' => \$db_cond, + 'persist' => \$persist, + 'debug' => \$debug, + ); + +my ($_dbh, $_sth); + +sub close_db() +{ + return if !defined($_dbh); + undef $_sth; + $_dbh->disconnect(); + undef $_dbh; +} + +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_usercol as 'user', $db_tagcol as 'tag' FROM $db_table WHERE ($db_uidcol = ?) " . + ($db_cond ne "" ? " AND $db_cond" : "")) || die; + + print(stderr "Query: SELECT $db_usercol as 'user', $db_tagcol as 'tag' FROM $db_table WHERE ($db_uidcol = ?) " . + ($db_cond ne "" ? " AND $db_cond" : "")) if ($debug); + + return $_sth; +} + +sub query_db($) { + my $uid = @_[0]; + my ($sth) = open_db() || return undef; + print(stderr "UID queried: '".$uid."'\n") if ($debug); + if (!$sth->execute($uid)) { + close_db(); + open_db() || return undef; + $sth->execute($uid) || return undef;; + } + return $sth; +} +my $status; + +while (<>) { + my $string = $_; + $string =~ m/^(\d+)\s(.*)$/; + my ($cid, $uid) = ($1, $2); + + $status = "ERR"; + $cid =~ s/%(..)/pack("H*", $1)/ge; + $uid =~ s/%(..)/pack("H*", $2)/ge; + + print(stderr "Received: Channel=".$cid.", UID='".$uid."'\n") if ($debug); + + $status = $cid . " ERR database error"; + my $sth = query_db($uid) || next; + print(stderr "Rows: ". $sth->rows()."\n") if ($debug); + $status = $cid . " ERR unknown UID '".$uid."'"; + my $row = $sth->fetchrow_hashref() || next; + $status = $cid . " OK" . ($row->{'user'} ne "" ? " user=" . $row->{'user'} : "" ) . ($row->{'tag'} ne "" ? " tag=" . $row->{'tag'} : "" ); + $sth->finish(); +} continue { + close_db() if (!$persist); + print $status . "\n"; +} + +=pod + +=head1 COPYRIGHT + +Copyright (C) 2012 Amos Jeffries +Based on original work in DB_auth by Henrik Nordstrom +With assistance of Nishant Sharma +This program is free software. You may redistribute copies of it under the +terms of the GNU General Public License version 2, or (at your opinion) any +later version. + +=cut