123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909 |
- /*
- * ws protocol handler plugin for "generic sessions"
- *
- * Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
- #include "private-lwsgs.h"
- /* keep changes in sync with the enum in lwsgs.h */
- static const char * const param_names[] = {
- "username",
- "password",
- "password2",
- "email",
- "register",
- "good",
- "bad",
- "reg-good",
- "reg-bad",
- "admin",
- "forgot",
- "forgot-good",
- "forgot-bad",
- "forgot-post-good",
- "forgot-post-bad",
- "change",
- "curpw",
- "delete"
- };
- struct lwsgs_fill_args {
- char *buf;
- int len;
- };
- static const struct lws_protocols protocols[];
- static int
- lwsgs_lookup_callback_email(void *priv, int cols, char **col_val,
- char **col_name)
- {
- struct lwsgs_fill_args *a = (struct lwsgs_fill_args *)priv;
- int n;
- for (n = 0; n < cols; n++) {
- if (!strcmp(col_name[n], "content")) {
- strncpy(a->buf, col_val[n], a->len - 1);
- a->buf[a->len - 1] = '\0';
- continue;
- }
- }
- return 0;
- }
- static int
- lwsgs_email_cb_get_body(struct lws_email *email, char *buf, int len)
- {
- struct per_vhost_data__gs *vhd = (struct per_vhost_data__gs *)email->data;
- struct lwsgs_fill_args a;
- char ss[150], esc[50];
- a.buf = buf;
- a.len = len;
- lws_snprintf(ss, sizeof(ss) - 1,
- "select content from email where username='%s';",
- lws_sql_purify(esc, vhd->u.username, sizeof(esc) - 1));
- strncpy(buf, "failed", len);
- if (sqlite3_exec(vhd->pdb, ss, lwsgs_lookup_callback_email, &a,
- NULL) != SQLITE_OK) {
- lwsl_err("Unable to lookup email: %s\n",
- sqlite3_errmsg(vhd->pdb));
- return 1;
- }
- return 0;
- }
- static int
- lwsgs_email_cb_sent(struct lws_email *email)
- {
- struct per_vhost_data__gs *vhd = (struct per_vhost_data__gs *)email->data;
- char s[200], esc[50];
- /* mark the user as having sent the verification email */
- lws_snprintf(s, sizeof(s) - 1,
- "update users set verified=1 where username='%s' and verified==0;",
- lws_sql_purify(esc, vhd->u.username, sizeof(esc) - 1));
- if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
- lwsl_err("%s: Unable to update user: %s\n", __func__,
- sqlite3_errmsg(vhd->pdb));
- return 1;
- }
- lws_snprintf(s, sizeof(s) - 1,
- "delete from email where username='%s';",
- lws_sql_purify(esc, vhd->u.username, sizeof(esc) - 1));
- if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
- lwsl_err("%s: Unable to delete email text: %s\n", __func__,
- sqlite3_errmsg(vhd->pdb));
- return 1;
- }
- return 0;
- }
- static int
- lwsgs_email_cb_on_next(struct lws_email *email)
- {
- struct per_vhost_data__gs *vhd = lws_container_of(email,
- struct per_vhost_data__gs, email);
- char s[LWSGS_EMAIL_CONTENT_SIZE], esc[50];
- time_t now = lws_now_secs();
- /*
- * users not verified in 24h get deleted
- */
- lws_snprintf(s, sizeof(s) - 1, "delete from users where ((verified != %d)"
- " and (creation_time <= %lu));", LWSGS_VERIFIED_ACCEPTED,
- (unsigned long)now - vhd->timeout_email_secs);
- if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
- lwsl_err("Unable to expire users: %s\n",
- sqlite3_errmsg(vhd->pdb));
- return 1;
- }
- lws_snprintf(s, sizeof(s) - 1, "update users set token_time=0 where "
- "(token_time <= %lu);",
- (unsigned long)now - vhd->timeout_email_secs);
- if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
- lwsl_err("Unable to expire users: %s\n",
- sqlite3_errmsg(vhd->pdb));
- return 1;
- }
- vhd->u.username[0] = '\0';
- lws_snprintf(s, sizeof(s) - 1, "select username from email limit 1;");
- if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &vhd->u,
- NULL) != SQLITE_OK) {
- lwsl_err("Unable to lookup user: %s\n", sqlite3_errmsg(vhd->pdb));
- return 1;
- }
- lws_snprintf(s, sizeof(s) - 1,
- "select username, creation_time, email, ip, verified, token"
- " from users where username='%s' limit 1;",
- lws_sql_purify(esc, vhd->u.username, sizeof(esc) - 1));
- if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &vhd->u,
- NULL) != SQLITE_OK) {
- lwsl_err("Unable to lookup user: %s\n",
- sqlite3_errmsg(vhd->pdb));
- return 1;
- }
- if (!vhd->u.username[0])
- /*
- * nothing to do, we are idle and no suitable
- * accounts waiting for verification. When a new user
- * is added we will get kicked to try again.
- */
- return 1;
- strncpy(email->email_to, vhd->u.email, sizeof(email->email_to) - 1);
- return 0;
- }
- struct lwsgs_subst_args
- {
- struct per_session_data__gs *pss;
- struct per_vhost_data__gs *vhd;
- struct lws *wsi;
- };
- static const char *
- lwsgs_subst(void *data, int index)
- {
- struct lwsgs_subst_args *a = (struct lwsgs_subst_args *)data;
- struct lwsgs_user u;
- lwsgw_hash sid;
- char esc[50], s[100];
- int n;
- a->pss->result[0] = '\0';
- u.email[0] = '\0';
- if (!lwsgs_get_sid_from_wsi(a->wsi, &sid)) {
- if (lwsgs_lookup_session(a->vhd, &sid, a->pss->result, 31)) {
- lwsl_notice("sid lookup for %s failed\n", sid.id);
- a->pss->delete_session = sid;
- return NULL;
- }
- lws_snprintf(s, sizeof(s) - 1, "select username,email "
- "from users where username = '%s';",
- lws_sql_purify(esc, a->pss->result, sizeof(esc) - 1));
- if (sqlite3_exec(a->vhd->pdb, s, lwsgs_lookup_callback_user,
- &u, NULL) != SQLITE_OK) {
- lwsl_err("Unable to lookup token: %s\n",
- sqlite3_errmsg(a->vhd->pdb));
- a->pss->delete_session = sid;
- return NULL;
- }
- } else
- lwsl_notice("no sid\n");
- strncpy(a->pss->result + 32, u.email, 100);
- switch (index) {
- case 0:
- return a->pss->result;
- case 1:
- n = lwsgs_get_auth_level(a->vhd, a->pss->result);
- sprintf(a->pss->result, "%d", n);
- return a->pss->result;
- case 2:
- return a->pss->result + 32;
- }
- return NULL;
- }
- static int
- callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason,
- void *user, void *in, size_t len)
- {
- struct per_session_data__gs *pss = (struct per_session_data__gs *)user;
- const struct lws_protocol_vhost_options *pvo;
- struct per_vhost_data__gs *vhd = (struct per_vhost_data__gs *)
- lws_protocol_vh_priv_get(lws_get_vhost(wsi),
- &protocols[0]);
- char cookie[1024], username[32], *pc = cookie;
- unsigned char buffer[LWS_PRE + LWSGS_EMAIL_CONTENT_SIZE];
- struct lws_process_html_args *args;
- struct lws_session_info *sinfo;
- char s[LWSGS_EMAIL_CONTENT_SIZE];
- unsigned char *p, *start, *end;
- sqlite3_stmt *sm;
- lwsgw_hash sid;
- const char *cp;
- int n;
- switch (reason) {
- case LWS_CALLBACK_PROTOCOL_INIT: /* per vhost */
- vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
- &protocols[0], sizeof(struct per_vhost_data__gs));
- if (!vhd)
- return 1;
- vhd->context = lws_get_context(wsi);
- /* defaults */
- vhd->timeout_idle_secs = 600;
- vhd->timeout_absolute_secs = 36000;
- vhd->timeout_anon_absolute_secs = 1200;
- vhd->timeout_email_secs = 24 * 3600;
- strcpy(vhd->email.email_helo, "unconfigured.com");
- strcpy(vhd->email.email_from, "noreply@unconfigured.com");
- strcpy(vhd->email_title, "Registration Email from unconfigured");
- strcpy(vhd->email.email_smtp_ip, "127.0.0.1");
- vhd->email.on_next = lwsgs_email_cb_on_next;
- vhd->email.on_get_body = lwsgs_email_cb_get_body;
- vhd->email.on_sent = lwsgs_email_cb_sent;
- vhd->email.data = (void *)vhd;
- pvo = (const struct lws_protocol_vhost_options *)in;
- while (pvo) {
- if (!strcmp(pvo->name, "admin-user"))
- strncpy(vhd->admin_user, pvo->value,
- sizeof(vhd->admin_user) - 1);
- if (!strcmp(pvo->name, "admin-password-sha1"))
- strncpy(vhd->admin_password_sha1.id, pvo->value,
- sizeof(vhd->admin_password_sha1.id) - 1);
- if (!strcmp(pvo->name, "session-db"))
- strncpy(vhd->session_db, pvo->value,
- sizeof(vhd->session_db) - 1);
- if (!strcmp(pvo->name, "confounder"))
- strncpy(vhd->confounder, pvo->value,
- sizeof(vhd->confounder) - 1);
- if (!strcmp(pvo->name, "email-from"))
- strncpy(vhd->email.email_from, pvo->value,
- sizeof(vhd->email.email_from) - 1);
- if (!strcmp(pvo->name, "email-helo"))
- strncpy(vhd->email.email_helo, pvo->value,
- sizeof(vhd->email.email_helo) - 1);
- if (!strcmp(pvo->name, "email-template"))
- strncpy(vhd->email_template, pvo->value,
- sizeof(vhd->email_template) - 1);
- if (!strcmp(pvo->name, "email-title"))
- strncpy(vhd->email_title, pvo->value,
- sizeof(vhd->email_title) - 1);
- if (!strcmp(pvo->name, "email-contact-person"))
- strncpy(vhd->email_contact_person, pvo->value,
- sizeof(vhd->email_contact_person) - 1);
- if (!strcmp(pvo->name, "email-confirm-url-base"))
- strncpy(vhd->email_confirm_url, pvo->value,
- sizeof(vhd->email_confirm_url) - 1);
- if (!strcmp(pvo->name, "email-server-ip"))
- strncpy(vhd->email.email_smtp_ip, pvo->value,
- sizeof(vhd->email.email_smtp_ip) - 1);
- if (!strcmp(pvo->name, "timeout-idle-secs"))
- vhd->timeout_idle_secs = atoi(pvo->value);
- if (!strcmp(pvo->name, "timeout-absolute-secs"))
- vhd->timeout_absolute_secs = atoi(pvo->value);
- if (!strcmp(pvo->name, "timeout-anon-absolute-secs"))
- vhd->timeout_anon_absolute_secs = atoi(pvo->value);
- if (!strcmp(pvo->name, "email-expire"))
- vhd->timeout_email_secs = atoi(pvo->value);
- pvo = pvo->next;
- }
- if (!vhd->admin_user[0] ||
- !vhd->admin_password_sha1.id[0] ||
- !vhd->session_db[0]) {
- lwsl_err("generic-sessions: "
- "You must give \"admin-user\", "
- "\"admin-password-sha1\", "
- "and \"session_db\" per-vhost options\n");
- return 1;
- }
- if (sqlite3_open_v2(vhd->session_db, &vhd->pdb,
- SQLITE_OPEN_READWRITE |
- SQLITE_OPEN_CREATE, NULL) != SQLITE_OK) {
- lwsl_err("Unable to open session db %s: %s\n",
- vhd->session_db, sqlite3_errmsg(vhd->pdb));
- return 1;
- }
- if (sqlite3_prepare(vhd->pdb,
- "create table if not exists sessions ("
- " name char(40),"
- " username varchar(32),"
- " expire integer"
- ");",
- -1, &sm, NULL) != SQLITE_OK) {
- lwsl_err("Unable to prepare session table init: %s\n",
- sqlite3_errmsg(vhd->pdb));
- return 1;
- }
- if (sqlite3_step(sm) != SQLITE_DONE) {
- lwsl_err("Unable to run session table init: %s\n",
- sqlite3_errmsg(vhd->pdb));
- return 1;
- }
- sqlite3_finalize(sm);
- if (sqlite3_exec(vhd->pdb,
- "create table if not exists users ("
- " username varchar(32),"
- " creation_time integer,"
- " ip varchar(46),"
- " email varchar(100),"
- " pwhash varchar(42),"
- " pwsalt varchar(42),"
- " pwchange_time integer,"
- " token varchar(42),"
- " verified integer,"
- " token_time integer,"
- " last_forgot_validated integer,"
- " primary key (username)"
- ");",
- NULL, NULL, NULL) != SQLITE_OK) {
- lwsl_err("Unable to create user table: %s\n",
- sqlite3_errmsg(vhd->pdb));
- return 1;
- }
- sprintf(s, "create table if not exists email ("
- " username varchar(32),"
- " content blob,"
- " primary key (username)"
- ");");
- if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
- lwsl_err("Unable to create user table: %s\n",
- sqlite3_errmsg(vhd->pdb));
- return 1;
- }
- lws_email_init(&vhd->email, lws_uv_getloop(vhd->context, 0),
- LWSGS_EMAIL_CONTENT_SIZE);
- vhd->email_inited = 1;
- break;
- case LWS_CALLBACK_PROTOCOL_DESTROY:
- // lwsl_notice("gs: LWS_CALLBACK_PROTOCOL_DESTROY: v=%p, ctx=%p\n", vhd, vhd->context);
- if (vhd->pdb) {
- sqlite3_close(vhd->pdb);
- vhd->pdb = NULL;
- }
- if (vhd->email_inited) {
- lws_email_destroy(&vhd->email);
- vhd->email_inited = 0;
- }
- break;
- case LWS_CALLBACK_HTTP:
- lwsl_info("LWS_CALLBACK_HTTP: %s\n", (const char *)in);
- pss->login_session.id[0] = '\0';
- pss->phs.pos = 0;
- strncpy(pss->onward, (char *)in, sizeof(pss->onward) - 1);
- pss->onward[sizeof(pss->onward) - 1] = '\0';
- if (!strcmp((const char *)in, "/lwsgs-forgot")) {
- lwsgs_handler_forgot(vhd, wsi, pss);
- goto redirect_with_cookie;
- }
- if (!strcmp((const char *)in, "/lwsgs-confirm")) {
- lwsgs_handler_confirm(vhd, wsi, pss);
- goto redirect_with_cookie;
- }
- if (!strcmp((const char *)in, "/lwsgs-check")) {
- lwsgs_handler_check(vhd, wsi, pss);
- goto try_to_reuse;
- }
- if (!strcmp((const char *)in, "/lwsgs-login"))
- break;
- if (!strcmp((const char *)in, "/lwsgs-logout"))
- break;
- if (!strcmp((const char *)in, "/lwsgs-forgot"))
- break;
- if (!strcmp((const char *)in, "/lwsgs-change"))
- break;
- /* if no legitimate url for GET, return 404 */
- lwsl_err("http doing 404 on %s\n", (const char *)in);
- lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
- goto try_to_reuse;
- case LWS_CALLBACK_CHECK_ACCESS_RIGHTS:
- n = 0;
- username[0] = '\0';
- sid.id[0] = '\0';
- args = (struct lws_process_html_args *)in;
- lwsl_debug("LWS_CALLBACK_CHECK_ACCESS_RIGHTS\n");
- if (!lwsgs_get_sid_from_wsi(wsi, &sid)) {
- if (lwsgs_lookup_session(vhd, &sid, username, sizeof(username))) {
- static const char * const oprot[] = {
- "http://", "https://"
- };
- lwsl_notice("session lookup for %s failed, probably expired\n", sid.id);
- pss->delete_session = sid;
- args->final = 1; /* signal we dealt with it */
- if (lws_hdr_copy(wsi, cookie, sizeof(cookie) - 1,
- WSI_TOKEN_HOST) < 0)
- return 1;
- lws_snprintf(pss->onward, sizeof(pss->onward) - 1,
- "%s%s%s", oprot[lws_is_ssl(wsi)],
- cookie, args->p);
- lwsl_notice("redirecting to ourselves with cookie refresh\n");
- /* we need a redirect to ourselves, session cookie is expired */
- goto redirect_with_cookie;
- }
- } else
- lwsl_notice("failed to get sid from wsi\n");
- n = lwsgs_get_auth_level(vhd, username);
- if ((args->max_len & n) != args->max_len) {
- lwsl_notice("Access rights fail 0x%X vs 0x%X (cookie %s)\n",
- args->max_len, n, sid.id);
- return 1;
- }
- lwsl_debug("Access rights OK\n");
- break;
- case LWS_CALLBACK_SESSION_INFO:
- {
- struct lwsgs_user u;
- sinfo = (struct lws_session_info *)in;
- sinfo->username[0] = '\0';
- sinfo->email[0] = '\0';
- sinfo->ip[0] = '\0';
- sinfo->session[0] = '\0';
- sinfo->mask = 0;
- sid.id[0] = '\0';
- lwsl_debug("LWS_CALLBACK_SESSION_INFO\n");
- if (lwsgs_get_sid_from_wsi(wsi, &sid))
- break;
- if (lwsgs_lookup_session(vhd, &sid, username, sizeof(username)))
- break;
- lws_snprintf(s, sizeof(s) - 1,
- "select username, email from users where username='%s';",
- username);
- if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) !=
- SQLITE_OK) {
- lwsl_err("Unable to lookup token: %s\n",
- sqlite3_errmsg(vhd->pdb));
- break;
- }
- strncpy(sinfo->username, u.username, sizeof(sinfo->username) - 1);
- sinfo->username[sizeof(sinfo->username) - 1] = '\0';
- strncpy(sinfo->email, u.email, sizeof(sinfo->email) - 1);
- strncpy(sinfo->session, sid.id, sizeof(sinfo->session) - 1);
- sinfo->mask = lwsgs_get_auth_level(vhd, username);
- lws_get_peer_simple(wsi, sinfo->ip, sizeof(sinfo->ip));
- }
- break;
- case LWS_CALLBACK_PROCESS_HTML:
- args = (struct lws_process_html_args *)in;
- {
- static const char * const vars[] = {
- "$lwsgs_user",
- "$lwsgs_auth",
- "$lwsgs_email"
- };
- struct lwsgs_subst_args a;
- a.vhd = vhd;
- a.pss = pss;
- a.wsi = wsi;
- pss->phs.vars = vars;
- pss->phs.count_vars = ARRAY_SIZE(vars);
- pss->phs.replace = lwsgs_subst;
- pss->phs.data = &a;
- if (lws_chunked_html_process(args, &pss->phs))
- return -1;
- }
- break;
- case LWS_CALLBACK_HTTP_BODY:
- if (len < 2)
- break;
- if (!pss->spa) {
- pss->spa = lws_spa_create(wsi, param_names,
- ARRAY_SIZE(param_names), 1024,
- NULL, NULL);
- if (!pss->spa)
- return -1;
- }
- if (lws_spa_process(pss->spa, in, len)) {
- lwsl_notice("spa process blew\n");
- return -1;
- }
- break;
- case LWS_CALLBACK_HTTP_BODY_COMPLETION:
- if (!pss->spa)
- break;
- lwsl_info("LWS_CALLBACK_HTTP_BODY_COMPLETION: %s\n", pss->onward);
- lws_spa_finalize(pss->spa);
- if (!strcmp((char *)pss->onward, "/lwsgs-change")) {
- if (!lwsgs_handler_change_password(vhd, wsi, pss)) {
- cp = lws_spa_get_string(pss->spa, FGS_GOOD);
- goto pass;
- }
- cp = lws_spa_get_string(pss->spa, FGS_BAD);
- lwsl_notice("user/password no good %s\n",
- lws_spa_get_string(pss->spa, FGS_USERNAME));
- strncpy(pss->onward, cp, sizeof(pss->onward) - 1);
- pss->onward[sizeof(pss->onward) - 1] = '\0';
- goto completion_flow;
- }
- if (!strcmp((char *)pss->onward, "/lwsgs-login")) {
- if (lws_spa_get_string(pss->spa, FGS_FORGOT) &&
- lws_spa_get_string(pss->spa, FGS_FORGOT)[0]) {
- if (lwsgs_handler_forgot_pw_form(vhd, wsi, pss)) {
- n = FGS_FORGOT_BAD;
- goto reg_done;
- }
- /* get the email monitor to take a look */
- lws_email_check(&vhd->email);
- n = FGS_FORGOT_GOOD;
- goto reg_done;
- }
- if (!lws_spa_get_string(pss->spa, FGS_USERNAME) ||
- !lws_spa_get_string(pss->spa, FGS_PASSWORD)) {
- lwsl_notice("username '%s' or pw '%s' missing\n",
- lws_spa_get_string(pss->spa, FGS_USERNAME),
- lws_spa_get_string(pss->spa, FGS_PASSWORD));
- return -1;
- }
- if (lws_spa_get_string(pss->spa, FGS_REGISTER) &&
- lws_spa_get_string(pss->spa, FGS_REGISTER)[0]) {
- if (lwsgs_handler_register_form(vhd, wsi, pss))
- n = FGS_REG_BAD;
- else {
- n = FGS_REG_GOOD;
- /* get the email monitor to take a look */
- lws_email_check(&vhd->email);
- }
- reg_done:
- strncpy(pss->onward, lws_spa_get_string(pss->spa, n),
- sizeof(pss->onward) - 1);
- pss->onward[sizeof(pss->onward) - 1] = '\0';
- pss->login_expires = 0;
- pss->logging_out = 1;
- goto completion_flow;
- }
- /* we have the username and password... check if admin */
- if (lwsgw_check_admin(vhd, lws_spa_get_string(pss->spa, FGS_USERNAME),
- lws_spa_get_string(pss->spa, FGS_PASSWORD))) {
- if (lws_spa_get_string(pss->spa, FGS_ADMIN))
- cp = lws_spa_get_string(pss->spa, FGS_ADMIN);
- else
- if (lws_spa_get_string(pss->spa, FGS_GOOD))
- cp = lws_spa_get_string(pss->spa, FGS_GOOD);
- else {
- lwsl_info("No admin or good target url in form\n");
- return -1;
- }
- lwsl_debug("admin\n");
- goto pass;
- }
- /* check users in database */
- if (!lwsgs_check_credentials(vhd, lws_spa_get_string(pss->spa, FGS_USERNAME),
- lws_spa_get_string(pss->spa, FGS_PASSWORD))) {
- lwsl_info("pw hash check met\n");
- cp = lws_spa_get_string(pss->spa, FGS_GOOD);
- goto pass;
- } else
- lwsl_notice("user/password no good %s\n",
- lws_spa_get_string(pss->spa, FGS_USERNAME));
- if (!lws_spa_get_string(pss->spa, FGS_BAD)) {
- lwsl_info("No admin or good target url in form\n");
- return -1;
- }
- strncpy(pss->onward, lws_spa_get_string(pss->spa, FGS_BAD),
- sizeof(pss->onward) - 1);
- pss->onward[sizeof(pss->onward) - 1] = '\0';
- lwsl_debug("failed\n");
- goto completion_flow;
- }
- if (!strcmp((char *)pss->onward, "/lwsgs-logout")) {
- lwsl_notice("/logout\n");
- if (lwsgs_get_sid_from_wsi(wsi, &pss->login_session)) {
- lwsl_notice("not logged in...\n");
- return 1;
- }
- lwsgw_update_session(vhd, &pss->login_session, "");
- if (!lws_spa_get_string(pss->spa, FGS_GOOD)) {
- lwsl_info("No admin or good target url in form\n");
- return -1;
- }
- strncpy(pss->onward, lws_spa_get_string(pss->spa, FGS_GOOD), sizeof(pss->onward) - 1);
- pss->onward[sizeof(pss->onward) - 1] = '\0';
- pss->login_expires = 0;
- pss->logging_out = 1;
- goto completion_flow;
- }
- break;
- pass:
- strncpy(pss->onward, cp, sizeof(pss->onward) - 1);
- pss->onward[sizeof(pss->onward) - 1] = '\0';
- if (lwsgs_get_sid_from_wsi(wsi, &sid))
- sid.id[0] = '\0';
- pss->login_expires = lws_now_secs() +
- vhd->timeout_absolute_secs;
- if (!sid.id[0]) {
- /* we need to create a new, authorized session */
- if (lwsgs_new_session_id(vhd, &pss->login_session,
- lws_spa_get_string(pss->spa, FGS_USERNAME),
- pss->login_expires))
- goto try_to_reuse;
- lwsl_info("Creating new session: %s\n",
- pss->login_session.id);
- } else {
- /*
- * we can just update the existing session to be
- * authorized
- */
- lwsl_info("Authorizing existing session %s", sid.id);
- lwsgw_update_session(vhd, &sid,
- lws_spa_get_string(pss->spa, FGS_USERNAME));
- pss->login_session = sid;
- }
- completion_flow:
- lwsgw_expire_old_sessions(vhd);
- goto redirect_with_cookie;
- case LWS_CALLBACK_HTTP_DROP_PROTOCOL:
- if (pss && pss->spa) {
- lws_spa_destroy(pss->spa);
- pss->spa = NULL;
- }
- break;
- case LWS_CALLBACK_ADD_HEADERS:
- lwsgw_expire_old_sessions(vhd);
- args = (struct lws_process_html_args *)in;
- if (pss->delete_session.id[0]) {
- pc = cookie;
- lwsgw_cookie_from_session(&pss->delete_session, 0, &pc,
- cookie + sizeof(cookie) - 1);
- lwsl_info("deleting cookie '%s'\n", cookie);
- if (lws_add_http_header_by_name(wsi,
- (unsigned char *)"set-cookie:",
- (unsigned char *)cookie, pc - cookie,
- (unsigned char **)&args->p,
- (unsigned char *)args->p + args->max_len))
- return 1;
- }
- if (!pss->login_session.id[0])
- lwsgs_get_sid_from_wsi(wsi, &pss->login_session);
- if (!pss->login_session.id[0] && !pss->logging_out) {
- pss->login_expires = lws_now_secs() +
- vhd->timeout_anon_absolute_secs;
- if (lwsgs_new_session_id(vhd, &pss->login_session, "",
- pss->login_expires))
- goto try_to_reuse;
- pc = cookie;
- lwsgw_cookie_from_session(&pss->login_session,
- pss->login_expires, &pc,
- cookie + sizeof(cookie) - 1);
- lwsl_info("LWS_CALLBACK_ADD_HEADERS: setting cookie '%s'\n", cookie);
- if (lws_add_http_header_by_name(wsi,
- (unsigned char *)"set-cookie:",
- (unsigned char *)cookie, pc - cookie,
- (unsigned char **)&args->p,
- (unsigned char *)args->p + args->max_len))
- return 1;
- }
- break;
- default:
- break;
- }
- return 0;
- redirect_with_cookie:
- p = buffer + LWS_PRE;
- start = p;
- end = p + sizeof(buffer) - LWS_PRE;
- if (lws_add_http_header_status(wsi, HTTP_STATUS_SEE_OTHER, &p, end))
- return 1;
- if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_LOCATION,
- (unsigned char *)pss->onward,
- strlen(pss->onward), &p, end))
- return 1;
- if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
- (unsigned char *)"text/html", 9, &p, end))
- return 1;
- if (lws_add_http_header_content_length(wsi, 0, &p, end))
- return 1;
- if (pss->delete_session.id[0]) {
- lwsgw_cookie_from_session(&pss->delete_session, 0, &pc,
- cookie + sizeof(cookie) - 1);
- lwsl_notice("deleting cookie '%s'\n", cookie);
- if (lws_add_http_header_by_name(wsi,
- (unsigned char *)"set-cookie:",
- (unsigned char *)cookie, pc - cookie,
- &p, end))
- return 1;
- }
- if (!pss->login_session.id[0]) {
- pss->login_expires = lws_now_secs() +
- vhd->timeout_anon_absolute_secs;
- if (lwsgs_new_session_id(vhd, &pss->login_session, "",
- pss->login_expires))
- return 1;
- } else
- pss->login_expires = lws_now_secs() +
- vhd->timeout_absolute_secs;
- if (pss->login_session.id[0] || pss->logging_out) {
- /*
- * we succeeded to login, we must issue a login
- * cookie with the prepared data
- */
- pc = cookie;
- lwsgw_cookie_from_session(&pss->login_session,
- pss->login_expires, &pc,
- cookie + sizeof(cookie) - 1);
- lwsl_info("setting cookie '%s'\n", cookie);
- pss->logging_out = 0;
- if (lws_add_http_header_by_name(wsi,
- (unsigned char *)"set-cookie:",
- (unsigned char *)cookie, pc - cookie,
- &p, end))
- return 1;
- }
- if (lws_finalize_http_header(wsi, &p, end))
- return 1;
- n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS);
- if (n < 0)
- return 1;
- /* fallthru */
- try_to_reuse:
- if (lws_http_transaction_completed(wsi))
- return -1;
- return 0;
- }
- static const struct lws_protocols protocols[] = {
- {
- "protocol-generic-sessions",
- callback_generic_sessions,
- sizeof(struct per_session_data__gs),
- 1024,
- },
- };
- LWS_EXTERN LWS_VISIBLE int
- init_protocol_generic_sessions(struct lws_context *context,
- struct lws_plugin_capability *c)
- {
- if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
- lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
- c->api_magic);
- return 1;
- }
- c->protocols = protocols;
- c->count_protocols = ARRAY_SIZE(protocols);
- c->extensions = NULL;
- c->count_extensions = 0;
- return 0;
- }
- LWS_EXTERN LWS_VISIBLE int
- destroy_protocol_generic_sessions(struct lws_context *context)
- {
- return 0;
- }
|