From: Ian Jackson Date: Fri, 31 Aug 2012 19:25:54 +0000 (+0100) Subject: wip X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=cgi-auth-flexible.git;a=commitdiff_plain;h=f3fce9867ccbb9b591c682d699009af6ceb1c341;ds=sidebyside wip --- f3fce9867ccbb9b591c682d699009af6ceb1c341 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b25c15b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*~ diff --git a/DESIGN b/DESIGN new file mode 100644 index 0000000..33ea592 --- /dev/null +++ b/DESIGN @@ -0,0 +1,42 @@ +cookie + user assoc id + +hidden form parameter + user assoc id + +same or different ? + +unused session expiry ? + + +logged in user associations database + +user login details form + +user authentication form + +user is abstract ? + string suitable for database + not interpreted by session code + + + +app needs to first check is it a login form submission +if so check details +if ok then call + create new login assoc(username) + which returns a cookie to set + +check function + checks for assoc id in cookie and form + if assoc id in cookie and op is GET, allow + otherwise demand in form too + checks for timeout too of course + +if failure, app must show login form + +app needs to check for logout button submission + if so then call + delete this login + which mostly does what check does and then also deletes the + assoc and the cookie diff --git a/cgi-auth-hybrid.pm b/cgi-auth-hybrid.pm new file mode 100644 index 0000000..9536ba7 --- /dev/null +++ b/cgi-auth-hybrid.pm @@ -0,0 +1,77 @@ +# -*- perl -*- + +BEGIN { + use Exporter (); + our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS); + + $VERSION = 1.00; + @ISA = qw(Exporter); + @EXPORT = qw(); + %EXPORT_TAGS = ( ); # eg: TAG => [ qw!name1 name2! ], + + @EXPORT_OK = qw(setup); +} +our @EXPORT_OK; + +our %_s = ( + assocdb_path => 'cah-assocs.db'; + assocdb_dsn => undef, + assocdb_user => '', + assocdb_password => '', + assocdb_table => 'assocs', + random_source => '/dev/urandom', + associdlen => 128, # bits + ); + +use DBI; + +our $dbh; + +sub setup { + my ($k,$v); + while (($k,$v,@_) = @_) { + die "unknown setting $k" unless %_s{$k}; + $_s{$k} = $v; + } +} + +sub _dbopen () { + return if $dbh; + + $_s{assocdb_dsn}="dbi:SQLite:dbname=$s_{assocdb_path}" + if !$_s{assocdb_dsn}; + + my $u = umask 077; + $dbh = DBI->open($_s{assocdb_dsn}, $s_{assocdb_user}, + $s_{assocdb_password}, { + AutoCommit => 0, RaiseError => 1, + }); + die "${assocdb_dsn} $! ?" unless $dbh; + + $dbh->do("BEGIN"); + + eval { + $dbh->do("CREATE TABLE $_s{assocdb_table} (". + " associd VARCHAR PRIMARY KEY,". + " username VARCHAR". + ")"); + }; +} + +sub record_login ($) { + my ($nusername) = @_; + my $rs = new IO::File $_s{random_source}, '<' + or die "$_s{random_source} $!"; + my $bytes = ($_s{associdlen} + 7) >> 3; + my $nassocbin; + $!=0; + read($rs,$nassocbin,$bytes) == $bytes or die "$s_{random_source} $!"; + my $nassoc = unpack "H*", $nassocbin; + _dbopen(); + $dbh->do("INSERT INTO $_s{assocdb_table}". + " (associd, username) VALUES (?,?)", {}, + $nassoc, $nusername); + $dbh->do("COMMIT"); + $username = $nusername; + $assoc = $nassoc; +}