+ my $authtoken = shift;
+
+ my $fn = GetFNfromAuthToken($authtoken);
+
+ unlink $fn || &HTMLError("Error removing authtoken: $!");
+}
+
+# Load the base key for our keyed hash function from disk and
+# compute a derived key for use in our HMAC function.
+sub getAuthTokenHMACkey {
+ open (F, "<$config{passdir}/key-hmac-$UID") || &Util::HTMLError($!);
+ my $base_hmac_key = <F>;
+ close(F);
+ chomp($base_hmac_key);
+
+ my $derived_key_hmac = hmac_sha1_hex("authtoken hmac key", $base_hmac_key);
+ return $derived_key_hmac;
+}
+
+# return a Mac (Message Authentication Code) for data.
+sub getDataMac {
+ my $data = shift;
+
+ my $hmac_key = getAuthTokenHMACkey();
+ my $hmac = hmac_sha1_hex($data, $hmac_key);
+
+ return $hmac;
+}
+
+# Given a userid, create an authtoken.
+#
+# The authtoken consists of the encoded username and a key to decrypt the
+# password stored on disk. the authtoken is protected from modification
+# by an hmac.
+sub CreateAuthToken {
+ my $userid = shift;
+
+ my $cryptuser = crypt($userid, CreateCryptSalt(1));
+ $cryptuser =~ y,/,_,; # translate slashes to underscores
+
+ my $key = &Util::CreateKey($config{blowfishkeylen});
+ my $hexkey = unpack("H".($config{blowfishkeylen}*2), $key);
+
+ my $data = "$cryptuser,$hexkey";
+ my $hmac = getDataMac($data);
+ my $authtoken = "$hmac,$data";
+
+ return $authtoken;
+}
+
+# Parse an authtoken into encoded userid and key information and validate its mac.
+sub ParseAuthToken {
+ my $authtoken = shift;
+ my ($hmac_got, $data) = split(/,/, $authtoken, 2);
+ my $hmac_want = getDataMac($data);
+
+ HTMLError("Failed to validate authtoken\n") unless ($hmac_got eq $hmac_want);
+
+ my ($cryptuserid, $hexkey) = split(/,/, $data, 2);
+ return ($cryptuserid, $hexkey);