diff --git a/door/.token.lua.swp b/door/.token.lua.swp index e33d720..675dc83 100644 Binary files a/door/.token.lua.swp and b/door/.token.lua.swp differ diff --git a/door/addtoken.lua b/door/addtoken.lua index f59663a..119d05d 100644 --- a/door/addtoken.lua +++ b/door/addtoken.lua @@ -4,6 +4,13 @@ require 'luasql.postgres' require 'helper' require 'config' require 'token' +require 'base64' + +function exit(env, con) + con:close() + env:close() + os.exit() +end print "* adding token ..." @@ -19,19 +26,47 @@ name = io.stdin:read() if name == "" then print "* action canceled" else + token = generate_token() + print "* generate token" + + io.stdout:write("enter prefix (length "..config.prefix_len.." chars): [default random] ") + prefix = io.stdin:read() + if prefix == "" then + prefix = token:sub(1,config.prefix_len) + else + if prefix:len() ~= config.prefix_len then + print("ERROR - prefix must have given length "..config.prefix_len..".") + exit(env,con) + end + if not is_base64(prefix) then + print "ERROR - prefix must be a valid base64 string." + exit(env,con) + end + if 0 ~= con:execute("select ttl from tokens where prefix='"..prefix.."';"):numrows() then + print "ERROR - prefix already in use." + exit(env,con) + end + end + token = set_prefix(prefix,token) + + if 0 ~= con:execute("select ttl from tokens where token='"..token.."';"):numrows() then + print(token) + print "ERROR - token already exists .. please try again." + exit(env,con) + end + cur = con:execute("insert into users (name, ntc) values ('"..name.."', 1);") if cur == 1 then print("* add user " .. name) else assert(con:execute("update users set ntc=ntc+1 where name='"..name.."';")) end - token = generate_token() - print "* generate token" ttl = os.time() + config.ttl - assert(con:execute("insert into tokens (pid, valid, token, ttl) values (NULL, true, '"..token.."', "..ttl..");")) + assert(con:execute("insert into tokens (prefix, token, ttl) values ('"..prefix.."', '"..token.."', "..ttl..");")) print "* add token:" print(token) + print("* prefix to remember: "..prefix) end -con:close() -env:close() +exit(env,con) + diff --git a/door/base64.lua b/door/base64.lua index 9cb3fc6..ac5a338 100644 --- a/door/base64.lua +++ b/door/base64.lua @@ -52,10 +52,19 @@ end -- decryption table local base64bytes = {['A']=0,['B']=1,['C']=2,['D']=3,['E']=4,['F']=5,['G']=6,['H']=7,['I']=8,['J']=9,['K']=10,['L']=11,['M']=12,['N']=13,['O']=14,['P']=15,['Q']=16,['R']=17,['S']=18,['T']=19,['U']=20,['V']=21,['W']=22,['X']=23,['Y']=24,['Z']=25,['a']=26,['b']=27,['c']=28,['d']=29,['e']=30,['f']=31,['g']=32,['h']=33,['i']=34,['j']=35,['k']=36,['l']=37,['m']=38,['n']=39,['o']=40,['p']=41,['q']=42,['r']=43,['s']=44,['t']=45,['u']=46,['v']=47,['w']=48,['x']=49,['y']=50,['z']=51,['0']=52,['1']=53,['2']=54,['3']=55,['4']=56,['5']=57,['6']=58,['7']=59,['8']=60,['9']=61,['-']=62,['_']=63,['=']=nil} -function is_b64_char(c) +local function is_b64_char(c) return base64bytes[c] ~= nil end +function is_base64(text) + for c in text:gmatch(".") do + if not is_b64_char(c) then + return false + end + end + return true +end + -- function decode -- decode base64 input to string function dec(data) diff --git a/door/config.lua b/door/config.lua index b203319..329be0c 100644 --- a/door/config.lua +++ b/door/config.lua @@ -2,6 +2,7 @@ config = { ['db'] = "cricket", + ['prefix_len'] = 4, ['open_cmd'] = "ssh root@fe80::218:84ff:fe1d:3fbc%eth0 door", ['key_len'] = 164, -- key_len/8*6 must be an integer!!!1! ['ttl'] = 60 * 60 * 24 * 7 * 8, -- s m h d w factor Time To Life (while alive) diff --git a/door/createdb.lua b/door/createdb.lua index 5caa163..2dc4bda 100644 --- a/door/createdb.lua +++ b/door/createdb.lua @@ -5,12 +5,13 @@ require 'config' print("* creating db ...") +pl = config.prefix_len len = config.key_len env = luasql.postgres() con = env:connect(config.db) -assert(con:execute("create table tokens ( id serial primary key, pid int, valid bool not null, token char("..len..") unique not null, ttl int );")) -- ttl - time to live -assert(con:execute("create table graveyard ( token char("..len..") unique not null, ttrd int );")) -- ttrd - time to real death +assert(con:execute("create table tokens ( prefix char("..pl..") primary key, token char("..len..") unique not null, ttl int );")) -- ttl - time to live +assert(con:execute("create table graveyard ( prefix char("..pl..") primary key, token char("..len..") unique not null, ttrd int );")) -- ttrd - time to real death assert(con:execute("create table users ( name text primary key, ntc int );")) -- ntc - new token count con:close() diff --git a/door/open.lua b/door/open.lua index ec18002..9feb46b 100644 --- a/door/open.lua +++ b/door/open.lua @@ -23,11 +23,11 @@ if token == nil or token == "" then if token:len() == config.key_len then print "" - id = check_token(token) - token = generate_token() - if id ~= false then - add_token(id, token) - qspawn("door") + b = check_token(token) + token = set_prefix(token,generate_token()) + if b ~= false then + add_token(token) + qspawn("lua door.lua") end print(token) else diff --git a/door/statistic.lua b/door/statistic.lua index b83b994..102c297 100644 --- a/door/statistic.lua +++ b/door/statistic.lua @@ -9,8 +9,7 @@ con = env:connect(config.db) print "* statistic:" -print("unvalid tokens: "..con:execute("select count(*) from tokens where valid=false;"):fetch()) -print("valid tokens: "..con:execute("select count(*) from tokens where valid=true;"):fetch()) +print("valid tokens: "..con:execute("select count(*) from tokens;"):fetch()) print("dead tokens: "..con:execute("select count(*) from graveyard;"):fetch()) print("users: "..con:execute("select count(*) from users;"):fetch()) diff --git a/door/token.lua b/door/token.lua index ec45a21..f3d752b 100644 --- a/door/token.lua +++ b/door/token.lua @@ -12,34 +12,42 @@ function generate_token() -- generates a new token (the next) return base64(r) end -function add_token(id, token) -- add token to the database +function add_token(token) -- add token to the database local env = luasql.postgres() local con = env:connect(config.db) local now = os.time() math.randomseed(now) + local prefix = token:sub(1, config.prefix_len) local ttl = now + config.ttl + math.floor(math.random() * config.ruttl) local ttrd = config.ttrd + math.floor(math.random() * config.ruttl) local ruttl = math.floor((math.random()+0.5) * config.ruttl) - local update = "update tokens set ttl=ttl+"..ruttl..", valid=false where id="..id..";" - local insert = "insert into tokens (pid, valid, token, ttl) values ("..id..", true, '"..token.."', "..ttl..");" - local gravedigger = "insert into graveyard (token, ttrd) select token, ttl+"..ttrd.." from tokens where ttl<"..now.." and valid=true;" + local update = "delete from tokens where prefix='"..prefix.."';" + local insert = "insert into tokens (prefix, token, ttl) values ('"..prefix.."', '"..token.."', "..ttl..");" + local gravedigger = "insert into graveyard (prefix, token, ttrd) select prefix, token, ttl+"..ttrd.." from tokens where ttl<"..now..";" local clean = "delete from tokens where ttl<"..now..";" local dig = "delete from graveyard where ttrd<"..now..";" - assert(con:execute(update .. insert .. gravedigger .. clean .. dig)) + assert(con:execute(gravedigger .. clean .. dig .. update .. insert .. update .. insert)) con:close() env:close() end function check_token(token) -- checks if the token is valid - for c in token:gmatch(".") do if not is_b64_char(c) then return false end end + if not is_base64(token) then return false end local env = luasql.postgres() local con = env:connect(config.db) - result = con:execute("select id from tokens where token='"..token.."' and valid=true;"):fetch() - if result == nil then result = false end + local result = true + local ttl = con:execute("select ttl from tokens where token='"..token.."';"):fetch() + if ttl == nil then result = false end + if type(ttl) == "number" then if tonumber(ttl) < os.time() then result = false end end con:close() env:close() return result end +function set_prefix(old, new) -- sets the prefix from the old token on the new token + local prefix = old:sub(1, config.prefix_len) + return prefix .. new:sub(config.prefix_len+1) +end +