chiark / gitweb /
wip
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 31 Aug 2012 19:25:54 +0000 (20:25 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 31 Aug 2012 19:25:54 +0000 (20:25 +0100)
.gitignore [new file with mode: 0644]
DESIGN [new file with mode: 0644]
cgi-auth-hybrid.pm [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..b25c15b
--- /dev/null
@@ -0,0 +1 @@
+*~
diff --git a/DESIGN b/DESIGN
new file mode 100644 (file)
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 (file)
index 0000000..9536ba7
--- /dev/null
@@ -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;
+}