From f3f067ebc11dd490930016c1bba90ef29d864914 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sun, 31 Aug 2014 17:56:32 +1000 Subject: [PATCH] ckdb - add address authorisation --- src/ckdb.c | 182 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 133 insertions(+), 49 deletions(-) diff --git a/src/ckdb.c b/src/ckdb.c index 7024c0a0..58d21d88 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -767,6 +767,7 @@ enum cmd_values { CMD_LOGLEVEL, CMD_SHARELOG, CMD_AUTH, + CMD_ADDRAUTH, CMD_ADDUSER, CMD_NEWPASS, CMD_CHKPASS, @@ -2478,7 +2479,7 @@ unparam: return ok; } -static bool users_add(PGconn *conn, char *username, char *emailaddress, +static K_ITEM *users_add(PGconn *conn, char *username, char *emailaddress, char *passwordhash, char *by, char *code, char *inet, tv_t *cd, K_TREE *trf_root) { @@ -2571,7 +2572,10 @@ unitem: } K_WUNLOCK(users_free); - return ok; + if (ok) + return item; + else + return NULL; } static bool users_fill(PGconn *conn) @@ -5558,7 +5562,8 @@ static cmp_t cmp_auths(K_ITEM *a, K_ITEM *b) static char *auths_add(PGconn *conn, char *poolinstance, char *username, char *workername, char *clientid, char *enonce1, char *useragent, char *preauth, char *by, char *code, - char *inet, tv_t *cd, bool igndup, K_TREE *trf_root) + char *inet, tv_t *cd, bool igndup, K_TREE *trf_root, + bool addressuser) { ExecStatusType rescode; bool conned = false; @@ -5584,8 +5589,18 @@ static char *auths_add(PGconn *conn, char *poolinstance, char *username, K_RLOCK(users_free); u_item = find_users(username); K_RUNLOCK(users_free); - if (!u_item) - goto unitem; + if (!u_item) { + if (addressuser) { + if (conn == NULL) { + conn = dbconnect(); + conned = true; + } + u_item = users_add(conn, username, EMPTY, EMPTY, + by, code, inet, cd, trf_root); + } + if (!u_item) + goto unitem; + } STRNCPY(row->poolinstance, poolinstance); row->userid = DATA_USERS(u_item)->userid; @@ -5607,6 +5622,9 @@ static char *auths_add(PGconn *conn, char *poolinstance, char *username, k_add_head(auths_free, a_item); K_WUNLOCK(auths_free); + if (conned) + PQfinish(conn); + if (!igndup) { tv_to_buf(cd, cd_buf, sizeof(cd_buf)); LOGERR("%s(): Duplicate auths ignored %s/%s/%s", @@ -6939,9 +6957,7 @@ static char *cmd_adduser(PGconn *conn, char *cmd, char *id, tv_t *now, char *by, { char reply[1024] = ""; size_t siz = sizeof(reply); - - K_ITEM *i_username, *i_emailaddress, *i_passwordhash; - bool ok; + K_ITEM *i_username, *i_emailaddress, *i_passwordhash, *u_item; LOGDEBUG("%s(): cmd '%s'", __func__, cmd); @@ -6957,12 +6973,12 @@ static char *cmd_adduser(PGconn *conn, char *cmd, char *id, tv_t *now, char *by, if (!i_passwordhash) return strdup(reply); - ok = users_add(conn, DATA_TRANSFER(i_username)->data, - DATA_TRANSFER(i_emailaddress)->data, - DATA_TRANSFER(i_passwordhash)->data, - by, code, inet, now, trf_root); + u_item = users_add(conn, DATA_TRANSFER(i_username)->data, + DATA_TRANSFER(i_emailaddress)->data, + DATA_TRANSFER(i_passwordhash)->data, + by, code, inet, now, trf_root); - if (!ok) { + if (!u_item) { LOGERR("%s() %s.failed.DBE", __func__, id); return strdup("failed.DBE"); } @@ -8279,7 +8295,7 @@ static char *cmd_auth_do(PGconn *conn, char *cmd, char *id, char *by, DATA_TRANSFER(i_enonce1)->data, DATA_TRANSFER(i_useragent)->data, DATA_TRANSFER(i_preauth)->data, - by, code, inet, cd, igndup, trf_root); + by, code, inet, cd, igndup, trf_root, false); if (!secuserid) { LOGDEBUG("%s() %s.failed.DBE", __func__, id); @@ -8309,6 +8325,83 @@ static char *cmd_auth(PGconn *conn, char *cmd, char *id, return cmd_auth_do(conn, cmd, id, by, code, inet, cd, igndup, trf_root); } +static char *cmd_addrauth_do(PGconn *conn, char *cmd, char *id, char *by, + char *code, char *inet, tv_t *cd, bool igndup, + K_TREE *trf_root) +{ + char reply[1024] = ""; + size_t siz = sizeof(reply); + K_ITEM *i_poolinstance, *i_username, *i_workername, *i_clientid; + K_ITEM *i_enonce1, *i_useragent, *i_preauth; + char *secuserid; + + LOGDEBUG("%s(): cmd '%s'", __func__, cmd); + + i_poolinstance = optional_name(trf_root, "poolinstance", 1, NULL); + if (!i_poolinstance) + i_poolinstance = &auth_poolinstance; + + i_username = require_name(trf_root, "username", 1, NULL, reply, siz); + if (!i_username) + return strdup(reply); + + i_workername = require_name(trf_root, "workername", 1, NULL, reply, siz); + if (!i_workername) + return strdup(reply); + + i_clientid = require_name(trf_root, "clientid", 1, NULL, reply, siz); + if (!i_clientid) + return strdup(reply); + + i_enonce1 = require_name(trf_root, "enonce1", 1, NULL, reply, siz); + if (!i_enonce1) + return strdup(reply); + + i_useragent = require_name(trf_root, "useragent", 0, NULL, reply, siz); + if (!i_useragent) + return strdup(reply); + + i_preauth = require_name(trf_root, "preauth", 1, NULL, reply, siz); + if (!i_preauth) + return strdup(reply); + + secuserid = auths_add(conn, DATA_TRANSFER(i_poolinstance)->data, + DATA_TRANSFER(i_username)->data, + DATA_TRANSFER(i_workername)->data, + DATA_TRANSFER(i_clientid)->data, + DATA_TRANSFER(i_enonce1)->data, + DATA_TRANSFER(i_useragent)->data, + DATA_TRANSFER(i_preauth)->data, + by, code, inet, cd, igndup, trf_root, true); + + if (!secuserid) { + LOGDEBUG("%s() %s.failed.DBE", __func__, id); + return strdup("failed.DBE"); + } + + LOGDEBUG("%s.ok.auth added for %s", id, secuserid); + snprintf(reply, siz, "ok.%s", secuserid); + return strdup(reply); +} + +static char *cmd_addrauth(PGconn *conn, char *cmd, char *id, + __maybe_unused tv_t *now, char *by, + char *code, char *inet, tv_t *cd, + K_TREE *trf_root) +{ + bool igndup = false; + + // confirm_summaries() doesn't call this + if (reloading) { + if (tv_equal(cd, &(dbstatus.newest_createdate_auths))) + igndup = true; + else if (tv_newer(cd, &(dbstatus.newest_createdate_auths))) + return NULL; + } + + return cmd_addrauth_do(conn, cmd, id, by, code, inet, cd, igndup, trf_root); +} + static char *cmd_homepage(__maybe_unused PGconn *conn, char *cmd, char *id, __maybe_unused tv_t *now, __maybe_unused char *by, __maybe_unused char *code, __maybe_unused char *inet, @@ -8972,6 +9065,7 @@ static struct CMDS { { CMD_SHARELOG, STR_SHAREERRORS, false, true, cmd_sharelog, ACCESS_POOL }, { CMD_SHARELOG, STR_AGEWORKINFO, false, true, cmd_sharelog, ACCESS_POOL }, { CMD_AUTH, "authorise", false, true, cmd_auth, ACCESS_POOL }, + { CMD_ADDRAUTH, "addrauth", false, true, cmd_addrauth, ACCESS_POOL }, { CMD_ADDUSER, "adduser", false, false, cmd_adduser, ACCESS_WEB }, { CMD_NEWPASS, "newpass", false, false, cmd_newpass, ACCESS_WEB }, { CMD_CHKPASS, "chkpass", false, false, cmd_chkpass, ACCESS_WEB }, @@ -9478,6 +9572,16 @@ static void *logger(__maybe_unused void *arg) return NULL; } +#define STORELASTREPLY(_cmd) do { \ + if (last_ ## _cmd) \ + free(last_ ## _cmd); \ + last_ ## _cmd = buf; \ + buf = NULL; \ + if (reply_ ## _cmd) \ + free(reply_ ## _cmd); \ + reply_ ## _cmd = rep; \ + } while (0) + static void *socketer(__maybe_unused void *arg) { proc_instance_t *pi = (proc_instance_t *)arg; @@ -9485,6 +9589,7 @@ static void *socketer(__maybe_unused void *arg) char *end, *ans = NULL, *rep = NULL, *buf = NULL, *dot; char cmd[CMD_SIZ+1], id[ID_SIZ+1], reply[1024+1]; char *last_auth = NULL, *reply_auth = NULL; + char *last_addrauth = NULL, *reply_addrauth = NULL; char *last_chkpass = NULL, *reply_chkpass = NULL; char *last_adduser = NULL, *reply_adduser = NULL; char *last_newpass = NULL, *reply_newpass = NULL; @@ -9555,6 +9660,7 @@ static void *socketer(__maybe_unused void *arg) * the reply without reprocessing the message */ dup = false; + // These are ordered approximately most likely first if (last_auth && strcmp(last_auth, buf) == 0) { reply_last = reply_auth; dup = true; @@ -9570,6 +9676,9 @@ static void *socketer(__maybe_unused void *arg) } else if (last_newid && strcmp(last_newid, buf) == 0) { reply_last = reply_newid; dup = true; + } else if (last_addrauth && strcmp(last_addrauth, buf) == 0) { + reply_last = reply_auth; + dup = true; } else if (last_web && strcmp(last_web, buf) == 0) { reply_last = reply_web; dup = true; @@ -9644,6 +9753,7 @@ static void *socketer(__maybe_unused void *arg) break; // Always process immediately: case CMD_AUTH: + case CMD_ADDRAUTH: // First message from the pool if (want_first) { ck_wlock(&fpm_lock); @@ -9670,49 +9780,22 @@ static void *socketer(__maybe_unused void *arg) ans = NULL; switch (cmdnum) { case CMD_AUTH: - if (last_auth) - free(last_auth); - last_auth = buf; - buf = NULL; - if (reply_auth) - free(reply_auth); - reply_auth = rep; + STORELASTREPLY(auth); + break; + case CMD_ADDRAUTH: + STORELASTREPLY(addrauth); break; case CMD_CHKPASS: - if (last_chkpass) - free(last_chkpass); - last_chkpass = buf; - buf = NULL; - if (reply_chkpass) - free(reply_chkpass); - reply_chkpass = rep; + STORELASTREPLY(chkpass); break; case CMD_ADDUSER: - if (last_adduser) - free(last_adduser); - last_adduser = buf; - buf = NULL; - if (reply_adduser) - free(reply_adduser); - reply_adduser = rep; + STORELASTREPLY(adduser); break; case CMD_NEWPASS: - if (last_newpass) - free(last_newpass); - last_newpass = buf; - buf = NULL; - if (reply_newpass) - free(reply_newpass); - reply_newpass = rep; + STORELASTREPLY(newpass); break; case CMD_NEWID: - if (last_newid) - free(last_newid); - last_newid = buf; - buf = NULL; - if (reply_newid) - free(reply_newid); - reply_newid = rep; + STORELASTREPLY(newid); break; default: free(rep); @@ -9912,6 +9995,7 @@ static bool reload_line(PGconn *conn, char *filename, uint64_t count, char *buf) __func__, count, cmd); break; case CMD_AUTH: + case CMD_ADDRAUTH: case CMD_POOLSTAT: case CMD_USERSTAT: case CMD_BLOCK: