Skip to content

Commit

Permalink
Added One Time Password support.
Browse files Browse the repository at this point in the history
This is only for time-based OTP for now ("TOPT" algorithm), but that's more
or less what one expects to see in the wild anyhow.

This is sort of a placeholder UI until I replace the entire existing UI with
something better.
  • Loading branch information
icculus committed Jun 18, 2017
1 parent a6a3b5a commit 0e1ae31
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 18 deletions.
11 changes: 11 additions & 0 deletions 1pass.c
Expand Up @@ -18,6 +18,7 @@
#include "md5.h"
#include "sha256.h"
#include "keyhook.h"
#include "otp.h"

#include <gtk/gtk.h>
#include <gdk/gdk.h>
Expand Down Expand Up @@ -364,6 +365,15 @@ static int decryptBase64UsingKey(lua_State *L)
} // decryptBase64UsingKey


static int decryptTopt(lua_State *L)
{
const char *base32_secret = luaL_checkstring(L, 1);
char otpstr[16];
const int rc = totp(base32_secret, otpstr, sizeof (otpstr));
return retvalString(L, (rc == -1) ? NULL : otpstr);
} // decryptTopt


static void calcSha256(const BYTE *buf, const size_t len, BYTE *hash)
{
SHA256_CTX sha256;
Expand Down Expand Up @@ -766,6 +776,7 @@ static int initLua(const int argc, char **argv)
// Set up initial C functions, etc we want to expose to Lua code...
luaSetCFunc(luaState, decryptUsingPBKDF2, "decryptUsingPBKDF2");
luaSetCFunc(luaState, decryptBase64UsingKey, "decryptBase64UsingKey");
luaSetCFunc(luaState, decryptTopt, "decryptTopt");
luaSetCFunc(luaState, giveControlToGui, "giveControlToGui");
luaSetCFunc(luaState, runGuiPasswordPrompt, "runGuiPasswordPrompt");
luaSetCFunc(luaState, copyToClipboard, "copyToClipboard");
Expand Down
62 changes: 61 additions & 1 deletion 1pass.lua
Expand Up @@ -140,7 +140,7 @@ local function setMenuItemChecked(menuitem, ischecked)
end


local function build_secret_menuitem(menu, type, str, hidden)
local function build_secret_menuitem(menu, type, str, hidden, transform)
if str == nil then
return nil
end
Expand All @@ -152,20 +152,65 @@ local function build_secret_menuitem(menu, type, str, hidden)
local text = type .. " " .. valuestr

local callback = function()
if transform ~= nil then
str = transform(str)
end
copyToClipboard(str)
--print("Copied data [" .. str .. "] to clipboard.")
guiDestroyMenu(keyhookGuiMenus[1])
end
return appendMenuItem(menu, text, callback)
end

local function transform_otp(str)
local algorithm, name, argstr = string.match(str, "^otpauth://(.-)/(.-)?(.+)$")
if algorithm == nil then algorithm = "" end
if algorithm ~= "totp" then
print("FIXME: don't know how to handle One Time Passwords using the '" .. algorithm .. "' algorithm!")
return "000000"
end

local args = {}
while argstr ~= nil and argstr ~= "" do
local arg
local idx = string.find(argstr, "&")
if idx == nil then
arg = argstr
argstr = nil
else
arg = string.sub(argstr, 0, idx);
argstr = string.sub(argstr, idx + 1);
end

local key, val = string.match(arg, "^(.-)=(.*)$")
if (key ~= nil) and (val ~= nil) then
args[key] = val
end
end

--dumptable("otpauth://" .. algorithm .. "/" .. name, args);

if args["secret"] == nil then
print("FIXME: this One Time Password doesn't seem to have a secret key!")
return "000000"
end

local retval = decryptTopt(args["secret"]);
if retval == nil then
print("FIXME: failed to generate One Time Password; is the secret key bogus?")
retval = "000000"
end
return retval
end


local secret_menuitem_builders = {}

local function build_secret_menuitem_webform(menu, info, secure)
local addthis = false
local username = nil
local password = nil
local otp = nil
local designated_password = nil
local designated_username = nil
local email = nil
Expand Down Expand Up @@ -199,6 +244,20 @@ local function build_secret_menuitem_webform(menu, info, secure)
end
end

-- this is probably all wrong.
if secure.sections ~= nil then
for i,v in ipairs(secure.sections) do
if v.fields ~= nil then
for i2,v2 in ipairs(v.fields) do
if (type(v2.v) == "string") and (string.sub(v2.v, 0, 10) == "otpauth://") then
otp = v2.v
addthis = true
end
end
end
end
end

if addthis then
-- designated fields always win out.
if (designated_username ~= nil) then
Expand All @@ -216,6 +275,7 @@ local function build_secret_menuitem_webform(menu, info, secure)
build_secret_menuitem(menu, "username", username)
build_secret_menuitem(menu, "email", email)
build_secret_menuitem(menu, "password", password, true)
build_secret_menuitem(menu, "otp", otp, true, transform_otp)
end
end
secret_menuitem_builders["webforms.WebForm"] = build_secret_menuitem_webform
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Expand Up @@ -82,6 +82,7 @@ add_executable(1pass
sha1.c
sha256.c
base64.c
otp.c
lua/lapi.c
lua/ldebug.c
lua/ldo.c
Expand Down
19 changes: 2 additions & 17 deletions otp.c
Expand Up @@ -3,6 +3,7 @@
#include <string.h>
#include <time.h>
#include "sha1.h"
#include "otp.h"

static int base32_decode(const char *src, const int srclen, uint8_t *dst, const int dstlen)
{
Expand Down Expand Up @@ -56,7 +57,7 @@ static int base32_decode(const char *src, const int srclen, uint8_t *dst, const
return retval;
}

static int totp(const char *base32_secret, char *dst, int dstlen)
int totp(const char *base32_secret, char *dst, int dstlen)
{
uint8_t decoded[64];
int decodedlen;
Expand Down Expand Up @@ -88,21 +89,5 @@ static int totp(const char *base32_secret, char *dst, int dstlen)
return 0;
}

int main(int argc, char **argv)
{
char result[16];
int i;
for (i = 1; i < argc; i++) {
printf("%s: ", argv[i]);
if (totp(argv[i], result, sizeof (result)) == -1) {
printf("[FAILED!]");
} else {
printf("%s (valid for %d more seconds)", result, 30 - ((int) (time(NULL) % 30)));
}
printf("\n");
}
return 0;
}

/* end of otp.c ... */

9 changes: 9 additions & 0 deletions otp.h
@@ -0,0 +1,9 @@
#ifndef _OTP_H_
#define _OTP_H_

int totp(const char *base32_secret, char *dst, int dstlen);

#endif

/* end of otp.h ... */

0 comments on commit 0e1ae31

Please sign in to comment.