X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=cgi-auth-flexible.git;a=blobdiff_plain;f=cgi-auth-flexible.pm;h=21805cffd8057a177222a6177d3dd3113d6a2bb6;hp=79e12d3e80e308a31eca672bd04c42c156331919;hb=48521dbb3f433c4a63df6564c4f095555a2dee95;hpb=d4cf8c70946f34cc9f46f9b5fe25962df77154ba diff --git a/cgi-auth-flexible.pm b/cgi-auth-flexible.pm index 79e12d3..21805cf 100644 --- a/cgi-auth-flexible.pm +++ b/cgi-auth-flexible.pm @@ -701,7 +701,6 @@ sub construct_cookie ($$$) { # any - POST nrmuoi bug or attack, fail # any - GET rmuoi bug or attack, fail # any any GET muoi bug or attack, fail - # any t any nrmu bug or attack, fail # # - - GET O "just logged out" page # (any other) O bug or attack, fail @@ -746,38 +745,38 @@ sub construct_cookie ($$$) { # revoke y2 # treat as y1 n POST # - # y n GET n intra-site link from stale page, + # y nt GET n intra-site link from stale page, # treat as cross-site link, show data # - # y n POST n m intra-site form submission from stale page + # y nt POST n m intra-site form submission from stale page # show "session interrupted" # with link to main data page # - # y n GET r intra-site request from stale page + # y nt GET r intra-site request from stale page # fail # - # y n POST r u intra-site request from stale page + # y nt POST r u intra-site request from stale page # fail # - # -/n y2 GET nr intra-site link from cleared session + # -n y2 GET nr intra-site link from cleared session # do not revoke y2 as not RESTful # treat as -/n n GET # - # -/n y2 POST nrmu request from cleared session + # -n y2 POST nrmu request from cleared session # revoke y2 # treat as -/n n POST # - # -/n -/n GET n cross-site link but user not logged in + # -nt -nt GET n cross-site link but user not logged in # show login form with redirect to orig params # generate fresh cookie # - # -/n n GET rmu user not logged in + # -nt nt GET rmu user not logged in # fail # - # -/n n POST n m user not logged in + # -nt nt POST n m user not logged in # show login form # - # -/n n POST r u user not logged in + # -nt nt POST r u user not logged in # fail sub _check_divert_core ($) { @@ -873,7 +872,6 @@ sub _check_divert_core ($) { if ($cookt eq 't') { $cookt = ''; } - die if $parmt eq 't'; if ($cookt eq 'y' && $parmt eq 'y' && $cookh ne $parmh) { $r->_db_revoke($parmh) if $meth eq 'POST'; @@ -882,7 +880,7 @@ sub _check_divert_core ($) { if ($cookt ne 'y') { die unless !$cookt || $cookt eq 'n'; - die unless !$parmt || $parmt eq 'n' || $parmt eq 'y'; + die unless !$parmt || $parmt eq 't' || $parmt eq 'n' || $parmt eq 'y'; my $news = $r->_fresh_secret(); if ($meth eq 'GET') { return ({ Kind => 'LOGIN-INCOMINGLINK', @@ -912,9 +910,17 @@ sub _check_divert_core ($) { die unless $cookt eq 'y'; unless ($r->{S}{promise_check_mutate} && $meth eq 'GET') { + if ($parmt eq 't' || $parmt eq 'n') { + return ({ Kind => 'STALE', + Message => $r->_gt("Login session interrupted."), + _CookieRaw => $cooks, + Params => { } }); + } die unless $parmt eq 'y'; die unless $cookh eq $parmh; } + $r->_db_update_last($cooku,$parmh); + $r->{ParmT} = $parmt; $r->{AssocRaw} = $cooks; $r->{UserOK} = $cooku; @@ -1020,6 +1026,16 @@ sub _db_record_login_ok ($$$) { $h, $user, time); } +sub _db_update_last ($$) { + # revokes $h if it's valid; no-op if it's not + my ($r,$user,$h) = @_; + my $dbh = $r->{Dbh}; + $dbh->do("UPDATE $r->{S}{db_prefix}_assocs". + " SET last = ?". + " WHERE username = ? AND assochash = ?", {}, + time, $user, $h); +} + sub check_divert ($) { my ($r) = @_; if (exists $r->{Divert}) { @@ -1030,9 +1046,9 @@ sub check_divert ($) { $dbh->commit(); my $divert = $r->{Divert}; - my $cookraw = $divert->{_CookieRaw}; - $divert->{CookieSecret} = $r->_blind($cookraw); + my $cookraw = $divert && $divert->{_CookieRaw}; if ($cookraw) { + $divert->{CookieSecret} = $r->_blind($cookraw); $divert->{Params}{$r->{S}{assoc_param_name}} = [ $r->_blind($r->hash($cookraw)) ]; @@ -1123,6 +1139,10 @@ sub check_ok ($) { $title = $r->_gt('Not logged in'); push @body, $divert->{Message}; push @body, $r->_ch('gen_login_link', $params); + } elsif ($kind =~ m/^STALE/) { + $title = $r->_gt('Re-entering secure site.'); + push @body, $divert->{Message}; + push @body, $r->_ch('gen_postmainpage_form', $params); } elsif ($kind =~ m/^MAINPAGEONLY$/) { $title = $r->_gt('Entering secure site.'); push @body, $divert->{Message}; @@ -1362,7 +1382,7 @@ sub check_nonpage ($$) { my ($r, $reqtype) = @_; $r->_assert_checked(); return unless $r->resource_get_needs_secret_hidden($reqtype); - return if $r->{ParmT}; + return if $r->{ParmT} eq 'y'; die "missing hidden secret parameter on nonpage request $reqtype"; }