local sql = require("lsqlite3") local db = require("db") local util = require("util") local session = require("session") local config = require("config") local pages = require("pages") local stmnt_author_acct local oldconfigure = configure function configure(...) --Get the data we need to check if someone can log in stmnt_author_acct = assert(db.conn:prepare([[ SELECT id, salt, passhash FROM authors WHERE name = :name; ]])) return oldconfigure(...) end local function login_post(req) --Try to log in http_populate_multipart_form(req) local name = assert(http_argument_get_string(req,"user")) local pass = assert(http_file_get(req,"pass")) stmnt_author_acct:bind_names{ name = name } local text local err = util.do_sql(stmnt_author_acct) if err == sql.ROW then local id, salt, passhash = unpack(stmnt_author_acct:get_values()) stmnt_author_acct:reset() local todigest = salt .. pass local hash = sha3(todigest) if hash == passhash then local mysession = session.start(id) local domain_no_port = config.domain:match("(.*):.*") or config.domain http_response_header(req,"set-cookie",string.format( [[session=%s; SameSite=Lax; Path=/; Domain=%s; HttpOnly; Secure]],mysession,domain_no_port )) local loc = string.format("https://%s.%s",name,config.domain) http_response_header(req,"Location",loc) http_response(req,303,"") return else text = pages.login{ err = "Incorrect username or password" } end elseif err == sql.DONE then --Allows user enumeration, do we want this? --Probably not a problem since all passwords are forced to be "good" stmnt_author_acct:reset() text = pages.login{ err = "Failed to find user:" .. name } else stmnt_author_acct:reset() error("Other sql error during login") end http_response(req,200,text) end return login_post