X-Git-Url: https://sipb.mit.edu/gitweb.cgi/ikiwiki.git/blobdiff_plain/1d1ef2003432d6993f0169b58e7b5f176948eb35..7d938559cb9994211d2917491c503f729d220abb:/IkiWiki/Plugin/passwordauth.pm diff --git a/IkiWiki/Plugin/passwordauth.pm b/IkiWiki/Plugin/passwordauth.pm index 6a5153efd..0cf2a26ea 100644 --- a/IkiWiki/Plugin/passwordauth.pm +++ b/IkiWiki/Plugin/passwordauth.pm @@ -99,11 +99,71 @@ sub setpassword ($$;$) { # Setting the password clears any passwordless login token. if ($field ne 'passwordless') { - IkiWiki::userinfo_set($user, "cryptpasswordless", ""); IkiWiki::userinfo_set($user, "passwordless", ""); } } +# Generates a token that can be used to log the user in. +# This needs to be hard to guess. Generating a cgi session id will +# make it as hard to guess as any cgi session. +sub gentoken ($$;$) { + my $user=shift; + my $tokenfield=shift; + my $reversable=shift; + + eval q{use CGI::Session}; + error($@) if $@; + my $token = CGI::Session->new->id; + if (! $reversable) { + setpassword($user, $token, $tokenfield); + } + else { + IkiWiki::userinfo_set($user, $tokenfield, $token); + } + return $token; +} + +# An anonymous user has no normal password, only a passwordless login +# token. Given an email address, this sets up such a user for that email, +# unless one already exists, and returns the username. +sub anonuser ($) { + my $email=shift; + + # Want a username for this email that won't overlap with any other. + my $user=$email; + $user=~s/@/_/g; + + my $userinfo=IkiWiki::userinfo_retrieve(); + if (! exists $userinfo->{$user} || ! ref $userinfo->{$user}) { + if (IkiWiki::userinfo_setall($user, { + 'email' => $email, + 'regdate' => time})) { + gentoken($user, "passwordless", 1); + return $user; + } + else { + error(gettext("Error creating account.")); + } + } + elsif (defined anonusertoken($userinfo->{$user})) { + return $user; + } + else { + return undef; + } +} + +sub anonusertoken ($) { + my $userhash=shift; + if (exists $userhash->{passwordless} && + length $userhash->{passwordless}) { + return $userhash->{passwordless}; + } + else { + return undef; + } +} + sub formbuilder_setup (@) { my %params=@_; @@ -283,20 +343,13 @@ sub formbuilder (@) { if (! length $email) { error(gettext("No email address, so cannot email password reset instructions.")); } - - # Store a token that can be used once - # to log the user in. This needs to be hard - # to guess. Generating a cgi session id will - # make it as hard to guess as any cgi session. - eval q{use CGI::Session}; - error($@) if $@; - my $token = CGI::Session->new->id; - setpassword($user_name, $token, "resettoken"); + + my $token=gentoken($user_name, "resettoken"); my $template=template("passwordmail.tmpl"); $template->param( user_name => $user_name, - passwordurl => IkiWiki::cgiurl( + passwordurl => IkiWiki::cgiurl_abs( 'do' => "reset", 'name' => $user_name, 'token' => $token, @@ -362,6 +415,22 @@ sub sessioncgi ($$) { IkiWiki::cgi_prefs($q, $session); exit; } + elsif ($q->param('do') eq 'tokenauth') { + my $name=$q->param("name"); + my $token=$q->param("token"); + + if (! defined $name || ! defined $token || + ! length $name || ! length $token) { + error(gettext("incorrect url")); + } + if (! checkpassword($name, $token, "passwordless")) { + error(gettext("access denied")); + } + + $session->param("name", $name); + IkiWiki::cgi_prefs($q, $session); + exit; + } elsif ($q->param("do") eq "register") { # After registration, need to go somewhere, so show prefs page. $session->param(postsignin => "do=prefs");