2016-05-19 15:28:31 +08:00
|
|
|
/*
|
2019-08-14 10:44:14 +01:00
|
|
|
* libwebsockets - small server side websockets and web server implementation
|
2016-05-19 15:28:31 +08:00
|
|
|
*
|
2019-08-14 10:44:14 +01:00
|
|
|
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
2016-05-19 15:28:31 +08:00
|
|
|
*
|
2019-08-14 10:44:14 +01:00
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to
|
|
|
|
* deal in the Software without restriction, including without limitation the
|
|
|
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
|
* sell copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
2016-05-19 15:28:31 +08:00
|
|
|
*
|
2019-08-14 10:44:14 +01:00
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
2016-05-19 15:28:31 +08:00
|
|
|
*
|
2019-08-14 10:44:14 +01:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
* IN THE SOFTWARE.
|
2016-05-19 15:28:31 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "private-lwsgs.h"
|
2017-10-18 09:41:44 +08:00
|
|
|
#include <stdlib.h>
|
2016-05-19 15:28:31 +08:00
|
|
|
|
|
|
|
/* 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[];
|
|
|
|
|
|
|
|
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;
|
2019-04-05 21:13:59 +08:00
|
|
|
char esc[96], s[100];
|
2016-05-19 15:28:31 +08:00
|
|
|
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;
|
|
|
|
}
|
2016-09-15 02:22:57 +08:00
|
|
|
lws_snprintf(s, sizeof(s) - 1, "select username,email "
|
2016-05-19 15:28:31 +08:00
|
|
|
"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");
|
|
|
|
|
2018-03-12 09:28:26 +08:00
|
|
|
lws_strncpy(a->pss->result + 32, u.email, 100);
|
2016-05-19 15:28:31 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-04-05 21:13:59 +08:00
|
|
|
static int
|
|
|
|
lws_get_effective_host(struct lws *wsi, char *buf, size_t buflen)
|
|
|
|
{
|
2020-02-28 10:31:04 +00:00
|
|
|
#if defined(LWS_ROLE_H2)
|
2019-04-05 21:13:59 +08:00
|
|
|
/* h2 */
|
|
|
|
if (lws_hdr_copy(wsi, buf, buflen - 1,
|
|
|
|
WSI_TOKEN_HTTP_COLON_AUTHORITY) > 0)
|
|
|
|
return 0;
|
2020-02-28 10:31:04 +00:00
|
|
|
#endif
|
2019-04-05 21:13:59 +08:00
|
|
|
/* h1 */
|
|
|
|
if (lws_hdr_copy(wsi, buf, buflen - 1, WSI_TOKEN_HOST) > 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-05-19 15:28:31 +08:00
|
|
|
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),
|
2019-04-05 21:13:59 +08:00
|
|
|
lws_vhost_name_to_protocol(lws_get_vhost(wsi),
|
|
|
|
"protocol-generic-sessions"));
|
2016-05-19 15:28:31 +08:00
|
|
|
char cookie[1024], username[32], *pc = cookie;
|
|
|
|
unsigned char buffer[LWS_PRE + LWSGS_EMAIL_CONTENT_SIZE];
|
2019-04-05 21:13:59 +08:00
|
|
|
struct lws_process_html_args *args = in;
|
2016-05-19 15:28:31 +08:00
|
|
|
struct lws_session_info *sinfo;
|
|
|
|
char s[LWSGS_EMAIL_CONTENT_SIZE];
|
|
|
|
unsigned char *p, *start, *end;
|
2019-04-05 21:13:59 +08:00
|
|
|
const char *cp, *cp1;
|
2016-05-19 15:28:31 +08:00
|
|
|
sqlite3_stmt *sm;
|
|
|
|
lwsgw_hash sid;
|
2020-01-02 08:32:23 +00:00
|
|
|
#if defined(LWS_WITH_SMTP)
|
2019-06-22 06:59:49 +01:00
|
|
|
lws_abs_t abs;
|
2020-01-02 08:32:23 +00:00
|
|
|
#endif
|
2016-05-19 15:28:31 +08:00
|
|
|
int n;
|
|
|
|
|
|
|
|
switch (reason) {
|
|
|
|
case LWS_CALLBACK_PROTOCOL_INIT: /* per vhost */
|
|
|
|
|
|
|
|
vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
|
2019-04-05 21:13:59 +08:00
|
|
|
lws_get_protocol(wsi), sizeof(struct per_vhost_data__gs));
|
2016-05-19 15:28:31 +08:00
|
|
|
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;
|
|
|
|
|
2019-04-21 19:57:19 +01:00
|
|
|
|
2019-06-22 06:59:49 +01:00
|
|
|
strcpy(vhd->helo, "unconfigured.com");
|
|
|
|
strcpy(vhd->ip, "127.0.0.1");
|
2019-04-21 19:57:19 +01:00
|
|
|
strcpy(vhd->email_from, "noreply@unconfigured.com");
|
|
|
|
strcpy(vhd->email_title, "Registration Email from unconfigured");
|
2019-04-05 21:13:59 +08:00
|
|
|
vhd->urlroot[0] = '\0';
|
2016-05-19 15:28:31 +08:00
|
|
|
|
|
|
|
pvo = (const struct lws_protocol_vhost_options *)in;
|
|
|
|
while (pvo) {
|
|
|
|
if (!strcmp(pvo->name, "admin-user"))
|
2018-03-12 09:28:26 +08:00
|
|
|
lws_strncpy(vhd->admin_user, pvo->value,
|
|
|
|
sizeof(vhd->admin_user));
|
2019-04-05 21:13:59 +08:00
|
|
|
if (!strcmp(pvo->name, "urlroot"))
|
|
|
|
lws_strncpy(vhd->urlroot, pvo->value,
|
|
|
|
sizeof(vhd->urlroot));
|
|
|
|
if (!strcmp(pvo->name, "admin-password-sha256"))
|
2019-04-21 19:57:19 +01:00
|
|
|
lws_strncpy(vhd->admin_password_sha256.id, pvo->value,
|
|
|
|
sizeof(vhd->admin_password_sha256.id));
|
2016-05-19 15:28:31 +08:00
|
|
|
if (!strcmp(pvo->name, "session-db"))
|
2018-03-12 09:28:26 +08:00
|
|
|
lws_strncpy(vhd->session_db, pvo->value,
|
|
|
|
sizeof(vhd->session_db));
|
2016-05-19 15:28:31 +08:00
|
|
|
if (!strcmp(pvo->name, "confounder"))
|
2018-03-12 09:28:26 +08:00
|
|
|
lws_strncpy(vhd->confounder, pvo->value,
|
|
|
|
sizeof(vhd->confounder));
|
2016-05-19 15:28:31 +08:00
|
|
|
if (!strcmp(pvo->name, "email-from"))
|
2019-04-21 19:57:19 +01:00
|
|
|
lws_strncpy(vhd->email_from, pvo->value,
|
|
|
|
sizeof(vhd->email_from));
|
2016-05-19 15:28:31 +08:00
|
|
|
if (!strcmp(pvo->name, "email-helo"))
|
2019-06-22 06:59:49 +01:00
|
|
|
lws_strncpy(vhd->helo, pvo->value, sizeof(vhd->helo));
|
2016-05-19 15:28:31 +08:00
|
|
|
if (!strcmp(pvo->name, "email-template"))
|
2018-03-12 09:28:26 +08:00
|
|
|
lws_strncpy(vhd->email_template, pvo->value,
|
|
|
|
sizeof(vhd->email_template));
|
2016-05-19 15:28:31 +08:00
|
|
|
if (!strcmp(pvo->name, "email-title"))
|
2018-03-12 09:28:26 +08:00
|
|
|
lws_strncpy(vhd->email_title, pvo->value,
|
|
|
|
sizeof(vhd->email_title));
|
2016-05-19 15:28:31 +08:00
|
|
|
if (!strcmp(pvo->name, "email-contact-person"))
|
2018-03-12 09:28:26 +08:00
|
|
|
lws_strncpy(vhd->email_contact_person, pvo->value,
|
|
|
|
sizeof(vhd->email_contact_person));
|
2016-05-19 15:28:31 +08:00
|
|
|
if (!strcmp(pvo->name, "email-confirm-url-base"))
|
2018-03-12 09:28:26 +08:00
|
|
|
lws_strncpy(vhd->email_confirm_url, pvo->value,
|
|
|
|
sizeof(vhd->email_confirm_url));
|
2016-05-19 15:28:31 +08:00
|
|
|
if (!strcmp(pvo->name, "email-server-ip"))
|
2019-06-22 06:59:49 +01:00
|
|
|
lws_strncpy(vhd->ip, pvo->value, sizeof(vhd->ip));
|
2016-05-19 15:28:31 +08:00
|
|
|
|
|
|
|
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] ||
|
2019-04-21 19:57:19 +01:00
|
|
|
!vhd->admin_password_sha256.id[0] ||
|
2016-05-19 15:28:31 +08:00
|
|
|
!vhd->session_db[0]) {
|
|
|
|
lwsl_err("generic-sessions: "
|
|
|
|
"You must give \"admin-user\", "
|
2019-04-21 19:57:19 +01:00
|
|
|
"\"admin-password-sha256\", "
|
2016-05-19 15:28:31 +08:00
|
|
|
"and \"session_db\" per-vhost options\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-04-05 21:13:59 +08:00
|
|
|
if (lws_struct_sq3_open(lws_get_context(wsi),
|
|
|
|
vhd->session_db, &vhd->pdb)) {
|
2016-05-19 15:28:31 +08:00
|
|
|
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 ("
|
2019-04-05 21:13:59 +08:00
|
|
|
" name char(65),"
|
2016-05-19 15:28:31 +08:00
|
|
|
" 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),"
|
2019-04-05 21:13:59 +08:00
|
|
|
" pwhash varchar(65),"
|
|
|
|
" pwsalt varchar(65),"
|
2016-05-19 15:28:31 +08:00
|
|
|
" pwchange_time integer,"
|
2019-04-05 21:13:59 +08:00
|
|
|
" token varchar(65),"
|
2016-05-19 15:28:31 +08:00
|
|
|
" 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;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
#if defined(LWS_WITH_SMTP)
|
|
|
|
|
2019-06-22 06:59:49 +01:00
|
|
|
memset(&abs, 0, sizeof(abs));
|
|
|
|
abs.vh = lws_get_vhost(wsi);
|
2019-04-21 19:57:19 +01:00
|
|
|
|
2019-06-22 06:59:49 +01:00
|
|
|
/* select the protocol and bind its tokens */
|
|
|
|
|
|
|
|
abs.ap = lws_abs_protocol_get_by_name("smtp");
|
|
|
|
if (!abs.ap)
|
2019-04-21 19:57:19 +01:00
|
|
|
return 1;
|
context deprecation
1) This makes lwsws run a parent process with the original permissions.
But this process is only able to respond to SIGHUP, it doesn't do anything
else.
2) You can send this parent process a SIGHUP now to cause it to
- close listening sockets in existing lwsws processes
- mark those processes as to exit when the number of active connections
on the falls to zero
- spawn a fresh child process from scratch, using latest configuration
file content, latest plugins, etc. It can now reopen listening sockets
if it chooses to, or open different listen ports or whatever.
Notes:
1) lws_context_destroy() has been split into two pieces... the reason for
the split is the first part closes the per-vhost protocols, but since
they may have created libuv objects in the per-vhost protocol storage,
these cannot be freed until after the loop has been run.
That's the purpose of the second part of the context destruction,
lws_context_destroy2().
For compatibility, if you are not using libuv, the first part calls the
second part. However if you are using libuv, you must now call the
second part from your own main.c after the first part.
2016-12-16 07:37:43 +08:00
|
|
|
|
2019-06-22 06:59:49 +01:00
|
|
|
vhd->protocol_tokens[0].name_index = LTMI_PSMTP_V_HELO;
|
|
|
|
vhd->protocol_tokens[0].u.value = vhd->helo;
|
|
|
|
|
|
|
|
abs.ap_tokens = vhd->protocol_tokens;
|
|
|
|
|
|
|
|
/* select the transport and bind its tokens */
|
|
|
|
|
|
|
|
abs.at = lws_abs_transport_get_by_name("raw_skt");
|
|
|
|
if (!abs.at)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
vhd->transport_tokens[0].name_index = LTMI_PEER_V_DNS_ADDRESS;
|
|
|
|
vhd->transport_tokens[0].u.value = vhd->ip;
|
|
|
|
vhd->transport_tokens[1].name_index = LTMI_PEER_LV_PORT;
|
|
|
|
vhd->transport_tokens[1].u.lvalue = 25;
|
|
|
|
|
|
|
|
abs.at_tokens = vhd->transport_tokens;
|
2019-04-05 21:13:59 +08:00
|
|
|
|
2019-06-22 06:59:49 +01:00
|
|
|
vhd->smtp_client = lws_abs_bind_and_create_instance(&abs);
|
|
|
|
if (!vhd->smtp_client)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
lwsl_notice("%s: created SMTP client\n", __func__);
|
2020-01-02 08:32:23 +00:00
|
|
|
#endif
|
2016-05-19 15:28:31 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_CALLBACK_PROTOCOL_DESTROY:
|
context deprecation
1) This makes lwsws run a parent process with the original permissions.
But this process is only able to respond to SIGHUP, it doesn't do anything
else.
2) You can send this parent process a SIGHUP now to cause it to
- close listening sockets in existing lwsws processes
- mark those processes as to exit when the number of active connections
on the falls to zero
- spawn a fresh child process from scratch, using latest configuration
file content, latest plugins, etc. It can now reopen listening sockets
if it chooses to, or open different listen ports or whatever.
Notes:
1) lws_context_destroy() has been split into two pieces... the reason for
the split is the first part closes the per-vhost protocols, but since
they may have created libuv objects in the per-vhost protocol storage,
these cannot be freed until after the loop has been run.
That's the purpose of the second part of the context destruction,
lws_context_destroy2().
For compatibility, if you are not using libuv, the first part calls the
second part. However if you are using libuv, you must now call the
second part from your own main.c after the first part.
2016-12-16 07:37:43 +08:00
|
|
|
// lwsl_notice("gs: LWS_CALLBACK_PROTOCOL_DESTROY: v=%p, ctx=%p\n", vhd, vhd->context);
|
2016-05-19 15:28:31 +08:00
|
|
|
if (vhd->pdb) {
|
|
|
|
sqlite3_close(vhd->pdb);
|
|
|
|
vhd->pdb = NULL;
|
|
|
|
}
|
2020-01-02 08:32:23 +00:00
|
|
|
#if defined(LWS_WITH_SMTP)
|
2019-04-21 19:57:19 +01:00
|
|
|
if (vhd->smtp_client)
|
2019-06-22 06:59:49 +01:00
|
|
|
lws_abs_destroy_instance(&vhd->smtp_client);
|
2020-01-02 08:32:23 +00:00
|
|
|
#endif
|
2016-05-19 15:28:31 +08:00
|
|
|
break;
|
|
|
|
|
2018-01-14 20:57:34 +08:00
|
|
|
case LWS_CALLBACK_HTTP_WRITEABLE:
|
|
|
|
if (!pss->check_response)
|
|
|
|
break;
|
2019-04-05 21:13:59 +08:00
|
|
|
pss->check_response = 0;
|
2019-04-21 19:57:19 +01:00
|
|
|
n = lws_write(wsi, (unsigned char *)&pss->check_response_value,
|
2019-04-05 21:13:59 +08:00
|
|
|
1, LWS_WRITE_HTTP | LWS_WRITE_H2_STREAM_END);
|
2018-01-14 20:57:34 +08:00
|
|
|
if (n != 1)
|
|
|
|
return -1;
|
|
|
|
goto try_to_reuse;
|
|
|
|
|
2016-05-19 15:28:31 +08:00
|
|
|
case LWS_CALLBACK_HTTP:
|
2019-04-05 21:13:59 +08:00
|
|
|
if (!pss) {
|
|
|
|
lwsl_err("%s: no valid pss\n", __func__);
|
|
|
|
return 1;
|
|
|
|
}
|
2016-05-19 15:28:31 +08:00
|
|
|
|
|
|
|
pss->login_session.id[0] = '\0';
|
|
|
|
pss->phs.pos = 0;
|
|
|
|
|
2019-04-05 21:13:59 +08:00
|
|
|
cp = in;
|
|
|
|
if ((*(const char *)in == '/'))
|
|
|
|
cp++;
|
|
|
|
|
|
|
|
if (lws_get_effective_host(wsi, cookie, sizeof(cookie))) {
|
|
|
|
lwsl_err("%s: HTTP: no effective host\n", __func__);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
lwsl_notice("LWS_CALLBACK_HTTP: %s, HOST '%s'\n",
|
|
|
|
(const char *)in, cookie);
|
|
|
|
|
|
|
|
n = strlen(cp);
|
|
|
|
|
|
|
|
lws_snprintf(pss->onward, sizeof(pss->onward),
|
|
|
|
"%s%s", vhd->urlroot, (const char *)in);
|
|
|
|
|
|
|
|
if (n >= 12 &&
|
|
|
|
!strcmp(cp + n - 12, "lwsgs-forgot")) {
|
2016-05-19 15:28:31 +08:00
|
|
|
lwsgs_handler_forgot(vhd, wsi, pss);
|
|
|
|
goto redirect_with_cookie;
|
|
|
|
}
|
|
|
|
|
2019-04-05 21:13:59 +08:00
|
|
|
if (n >= 13 &&
|
|
|
|
!strcmp(cp + n - 13, "lwsgs-confirm")) {
|
2016-05-19 15:28:31 +08:00
|
|
|
lwsgs_handler_confirm(vhd, wsi, pss);
|
|
|
|
goto redirect_with_cookie;
|
|
|
|
}
|
2020-01-02 08:32:23 +00:00
|
|
|
cp1 = strstr(cp, "lwsgs-check/");
|
|
|
|
if (cp1) {
|
|
|
|
lwsgs_handler_check(vhd, wsi, pss, cp1 + 12);
|
2018-01-14 20:57:34 +08:00
|
|
|
/* second, async part will complete transaction */
|
|
|
|
break;
|
2016-05-19 15:28:31 +08:00
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
if (n >= 11 && cp && !strcmp(cp + n - 11, "lwsgs-login"))
|
2016-05-19 15:28:31 +08:00
|
|
|
break;
|
2020-01-02 08:32:23 +00:00
|
|
|
if (n >= 12 && cp && !strcmp(cp + n - 12, "lwsgs-logout"))
|
2016-05-19 15:28:31 +08:00
|
|
|
break;
|
2020-01-02 08:32:23 +00:00
|
|
|
if (n >= 12 && cp && !strcmp(cp + n - 12, "lwsgs-forgot"))
|
2016-05-19 15:28:31 +08:00
|
|
|
break;
|
2020-01-02 08:32:23 +00:00
|
|
|
if (n >= 12 && cp && !strcmp(cp + n - 12, "lwsgs-change"))
|
2016-05-19 15:28:31 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* if no legitimate url for GET, return 404 */
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
lwsl_err("%s: http doing 404 on %s\n", __func__, cp ? cp : "null");
|
2016-05-19 15:28:31 +08:00
|
|
|
lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
|
2019-04-05 21:13:59 +08:00
|
|
|
|
2018-01-12 10:22:26 +08:00
|
|
|
return -1;
|
|
|
|
//goto try_to_reuse;
|
2016-05-19 15:28:31 +08:00
|
|
|
|
2019-04-05 21:13:59 +08:00
|
|
|
case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
|
|
|
|
args = (struct lws_process_html_args *)in;
|
|
|
|
if (!args->chunked)
|
|
|
|
break;
|
2016-05-19 15:28:31 +08:00
|
|
|
case LWS_CALLBACK_CHECK_ACCESS_RIGHTS:
|
|
|
|
n = 0;
|
|
|
|
username[0] = '\0';
|
|
|
|
sid.id[0] = '\0';
|
|
|
|
args = (struct lws_process_html_args *)in;
|
2019-04-05 21:13:59 +08:00
|
|
|
lwsl_notice("%s: LWS_CALLBACK_CHECK_ACCESS_RIGHTS: need 0x%x\n",
|
|
|
|
__func__, args->max_len);
|
2016-05-19 15:28:31 +08:00
|
|
|
if (!lwsgs_get_sid_from_wsi(wsi, &sid)) {
|
2019-04-05 21:13:59 +08:00
|
|
|
if (lwsgs_lookup_session(vhd, &sid, username,
|
|
|
|
sizeof(username))) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* if we're authenticating for ws, we don't
|
|
|
|
* want to redirect it or gain a cookie on that,
|
|
|
|
* he'll need to get the cookie from http
|
|
|
|
* interactions outside of this.
|
|
|
|
*/
|
|
|
|
if (args->chunked) {
|
|
|
|
lwsl_notice("%s: ws auth failed\n",
|
|
|
|
__func__);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
lwsl_notice("session lookup for %s failed, "
|
|
|
|
"probably expired\n", sid.id);
|
2016-05-19 15:28:31 +08:00
|
|
|
pss->delete_session = sid;
|
|
|
|
args->final = 1; /* signal we dealt with it */
|
2016-09-15 02:22:57 +08:00
|
|
|
lws_snprintf(pss->onward, sizeof(pss->onward) - 1,
|
2019-04-05 21:13:59 +08:00
|
|
|
"%s%s", vhd->urlroot, args->p);
|
|
|
|
lwsl_notice("redirecting to ourselves with "
|
|
|
|
"cookie refresh\n");
|
|
|
|
/* we need a redirect to ourselves,
|
|
|
|
* session cookie is expired */
|
2016-05-19 15:28:31 +08:00
|
|
|
goto redirect_with_cookie;
|
|
|
|
}
|
|
|
|
} else
|
2020-02-09 09:33:59 +00:00
|
|
|
lwsl_notice("%s: failed to get sid from wsi\n", __func__);
|
2016-05-19 15:28:31 +08:00
|
|
|
|
|
|
|
n = lwsgs_get_auth_level(vhd, username);
|
2020-02-09 09:33:59 +00:00
|
|
|
lwsl_notice("%s: lwsgs_get_auth_level '%s' says %d\n", __func__, username, n);
|
2016-05-19 15:28:31 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2016-09-15 02:22:57 +08:00
|
|
|
lws_snprintf(s, sizeof(s) - 1,
|
2016-05-19 15:28:31 +08:00
|
|
|
"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;
|
|
|
|
}
|
2018-03-12 09:28:26 +08:00
|
|
|
lws_strncpy(sinfo->username, u.username, sizeof(sinfo->username));
|
|
|
|
lws_strncpy(sinfo->email, u.email, sizeof(sinfo->email));
|
|
|
|
lws_strncpy(sinfo->session, sid.id, sizeof(sinfo->session));
|
2016-05-19 15:28:31 +08:00
|
|
|
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;
|
2018-08-16 19:10:32 +08:00
|
|
|
pss->phs.count_vars = LWS_ARRAY_SIZE(vars);
|
2016-05-19 15:28:31 +08:00
|
|
|
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:
|
2020-02-09 09:33:59 +00:00
|
|
|
if (len < 2) {
|
|
|
|
lwsl_err("%s: HTTP_BODY: len %d < 2\n", __func__, (int)len);
|
2016-05-19 15:28:31 +08:00
|
|
|
break;
|
2020-02-09 09:33:59 +00:00
|
|
|
}
|
2016-05-19 15:28:31 +08:00
|
|
|
|
|
|
|
if (!pss->spa) {
|
|
|
|
pss->spa = lws_spa_create(wsi, param_names,
|
2018-08-16 19:10:32 +08:00
|
|
|
LWS_ARRAY_SIZE(param_names), 1024,
|
2016-05-19 15:28:31 +08:00
|
|
|
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:
|
|
|
|
|
2020-02-09 09:33:59 +00:00
|
|
|
lwsl_debug("%s: LWS_CALLBACK_HTTP_BODY_COMPLETION\n", __func__);
|
|
|
|
|
2016-05-19 15:28:31 +08:00
|
|
|
if (!pss->spa)
|
|
|
|
break;
|
|
|
|
|
2019-04-05 21:13:59 +08:00
|
|
|
cp1 = (const char *)pss->onward;
|
|
|
|
if (*cp1 == '/')
|
|
|
|
cp1++;
|
|
|
|
|
|
|
|
|
2016-05-19 15:28:31 +08:00
|
|
|
lws_spa_finalize(pss->spa);
|
2019-04-05 21:13:59 +08:00
|
|
|
n = strlen(cp1);
|
2016-05-19 15:28:31 +08:00
|
|
|
|
2019-04-05 21:13:59 +08:00
|
|
|
if (lws_get_effective_host(wsi, cookie, sizeof(cookie)))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (!strcmp(cp1 + n - 12, "lwsgs-change")) {
|
2016-05-19 15:28:31 +08:00
|
|
|
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));
|
2019-04-05 21:13:59 +08:00
|
|
|
lws_snprintf(pss->onward, sizeof(pss->onward),
|
|
|
|
"%s%s", vhd->urlroot, cp);
|
|
|
|
|
2016-05-19 15:28:31 +08:00
|
|
|
pss->onward[sizeof(pss->onward) - 1] = '\0';
|
|
|
|
goto completion_flow;
|
|
|
|
}
|
|
|
|
|
2019-04-05 21:13:59 +08:00
|
|
|
if (!strcmp(cp1 + n - 11, "lwsgs-login")) {
|
|
|
|
lwsl_err("%s: lwsgs-login\n", __func__);
|
2016-05-19 15:28:31 +08:00
|
|
|
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;
|
|
|
|
}
|
2020-01-02 08:32:23 +00:00
|
|
|
#if defined(LWS_WITH_SMTP)
|
2016-05-19 15:28:31 +08:00
|
|
|
/* get the email monitor to take a look */
|
2019-07-05 09:38:32 +01:00
|
|
|
lws_smtpc_kick(vhd->smtp_client);
|
2020-01-02 08:32:23 +00:00
|
|
|
#endif
|
2016-05-19 15:28:31 +08:00
|
|
|
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",
|
2019-04-05 21:13:59 +08:00
|
|
|
lws_spa_get_string(pss->spa, FGS_USERNAME),
|
|
|
|
lws_spa_get_string(pss->spa, FGS_PASSWORD));
|
2016-05-19 15:28:31 +08:00
|
|
|
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;
|
2020-01-02 08:32:23 +00:00
|
|
|
#if defined(LWS_WITH_SMTP)
|
2016-05-19 15:28:31 +08:00
|
|
|
/* get the email monitor to take a look */
|
2019-07-05 09:38:32 +01:00
|
|
|
lws_smtpc_kick(vhd->smtp_client);
|
2020-01-02 08:32:23 +00:00
|
|
|
#endif
|
2016-05-19 15:28:31 +08:00
|
|
|
}
|
|
|
|
reg_done:
|
2019-04-05 21:13:59 +08:00
|
|
|
lws_snprintf(pss->onward, sizeof(pss->onward),
|
|
|
|
"%s%s", vhd->urlroot,
|
|
|
|
lws_spa_get_string(pss->spa, n));
|
|
|
|
|
2016-05-19 15:28:31 +08:00
|
|
|
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 */
|
|
|
|
|
2019-04-05 21:13:59 +08:00
|
|
|
if (!lwsgs_check_credentials(vhd,
|
|
|
|
lws_spa_get_string(pss->spa, FGS_USERNAME),
|
|
|
|
lws_spa_get_string(pss->spa, FGS_PASSWORD))) {
|
|
|
|
lwsl_notice("pw hash check met\n");
|
2016-05-19 15:28:31 +08:00
|
|
|
cp = lws_spa_get_string(pss->spa, FGS_GOOD);
|
|
|
|
goto pass;
|
|
|
|
} else
|
2019-04-05 21:13:59 +08:00
|
|
|
lwsl_notice("user/password no good %s %s\n",
|
|
|
|
lws_spa_get_string(pss->spa, FGS_USERNAME),
|
|
|
|
lws_spa_get_string(pss->spa, FGS_PASSWORD));
|
2016-05-19 15:28:31 +08:00
|
|
|
|
|
|
|
if (!lws_spa_get_string(pss->spa, FGS_BAD)) {
|
|
|
|
lwsl_info("No admin or good target url in form\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2019-04-05 21:13:59 +08:00
|
|
|
lws_snprintf(pss->onward, sizeof(pss->onward),
|
|
|
|
"%s%s", vhd->urlroot,
|
|
|
|
lws_spa_get_string(pss->spa, FGS_BAD));
|
|
|
|
|
|
|
|
lwsl_notice("failed: %s\n", pss->onward);
|
2016-05-19 15:28:31 +08:00
|
|
|
|
|
|
|
goto completion_flow;
|
|
|
|
}
|
|
|
|
|
2019-04-05 21:13:59 +08:00
|
|
|
if (!strcmp(cp1 + n - 12, "lwsgs-logout")) {
|
2016-05-19 15:28:31 +08:00
|
|
|
|
|
|
|
lwsl_notice("/logout\n");
|
|
|
|
|
|
|
|
if (lwsgs_get_sid_from_wsi(wsi, &pss->login_session)) {
|
|
|
|
lwsl_notice("not logged in...\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-04-05 21:13:59 +08:00
|
|
|
/*
|
|
|
|
* We keep the same session, but mark it as not
|
|
|
|
* being associated to any authenticated user
|
|
|
|
*/
|
|
|
|
|
2016-05-19 15:28:31 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-04-05 21:13:59 +08:00
|
|
|
lws_snprintf(pss->onward, sizeof(pss->onward),
|
|
|
|
"%s%s", vhd->urlroot,
|
|
|
|
lws_spa_get_string(pss->spa, FGS_GOOD));
|
2016-05-19 15:28:31 +08:00
|
|
|
|
|
|
|
pss->login_expires = 0;
|
|
|
|
pss->logging_out = 1;
|
|
|
|
|
|
|
|
goto completion_flow;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
pass:
|
2019-04-05 21:13:59 +08:00
|
|
|
lws_snprintf(pss->onward, sizeof(pss->onward),
|
|
|
|
"%s%s", vhd->urlroot, cp);
|
2016-05-19 15:28:31 +08:00
|
|
|
|
|
|
|
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,
|
2019-04-05 21:13:59 +08:00
|
|
|
lws_spa_get_string(pss->spa, FGS_USERNAME),
|
|
|
|
pss->login_expires))
|
2016-05-19 15:28:31 +08:00
|
|
|
goto try_to_reuse;
|
|
|
|
|
2020-02-09 09:33:59 +00:00
|
|
|
lwsl_notice("%s: Creating new session: %s\n", __func__,
|
2016-05-19 15:28:31 +08:00
|
|
|
pss->login_session.id);
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* we can just update the existing session to be
|
|
|
|
* authorized
|
|
|
|
*/
|
2020-02-09 09:33:59 +00:00
|
|
|
lwsl_notice("%s: Authorizing existing session %s, name %s\n",
|
|
|
|
__func__, sid.id,
|
|
|
|
lws_spa_get_string(pss->spa, FGS_USERNAME));
|
2016-05-19 15:28:31 +08:00
|
|
|
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:
|
2016-06-15 12:24:38 +08:00
|
|
|
if (pss && pss->spa) {
|
2016-05-19 15:28:31 +08:00
|
|
|
lws_spa_destroy(pss->spa);
|
|
|
|
pss->spa = NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_CALLBACK_ADD_HEADERS:
|
|
|
|
lwsgw_expire_old_sessions(vhd);
|
|
|
|
|
2019-04-05 21:13:59 +08:00
|
|
|
lwsl_warn("ADD_HEADERS\n");
|
|
|
|
|
2016-05-19 15:28:31 +08:00
|
|
|
args = (struct lws_process_html_args *)in;
|
2018-01-14 20:37:45 +08:00
|
|
|
if (!pss)
|
|
|
|
return 1;
|
2016-05-19 15:28:31 +08:00
|
|
|
if (pss->delete_session.id[0]) {
|
|
|
|
pc = cookie;
|
|
|
|
lwsgw_cookie_from_session(&pss->delete_session, 0, &pc,
|
|
|
|
cookie + sizeof(cookie) - 1);
|
|
|
|
|
2019-04-05 21:13:59 +08:00
|
|
|
lwsl_notice("deleting cookie '%s'\n", cookie);
|
2016-05-19 15:28:31 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2019-04-05 21:13:59 +08:00
|
|
|
lwsl_warn("%s: redirect_with_cookie\n", __func__);
|
|
|
|
|
2016-05-19 15:28:31 +08:00
|
|
|
if (lws_add_http_header_status(wsi, HTTP_STATUS_SEE_OTHER, &p, end))
|
|
|
|
return 1;
|
|
|
|
|
2019-04-05 21:13:59 +08:00
|
|
|
{
|
|
|
|
char loc[1024], uria[128];
|
|
|
|
|
|
|
|
uria[0] = '\0';
|
|
|
|
lws_hdr_copy_fragment(wsi, uria, sizeof(uria),
|
|
|
|
WSI_TOKEN_HTTP_URI_ARGS, 0);
|
|
|
|
n = lws_snprintf(loc, sizeof(loc), "%s?%s",
|
|
|
|
pss->onward, uria);
|
|
|
|
lwsl_notice("%s: redirect to '%s'\n", __func__, loc);
|
|
|
|
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_LOCATION,
|
|
|
|
(unsigned char *)loc, n, &p, end))
|
|
|
|
return 1;
|
|
|
|
}
|
2016-05-19 15:28:31 +08:00
|
|
|
|
|
|
|
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,
|
2019-04-05 21:13:59 +08:00
|
|
|
&p, end)) {
|
|
|
|
lwsl_err("fail0\n");
|
2016-05-19 15:28:31 +08:00
|
|
|
return 1;
|
2019-04-05 21:13:59 +08:00
|
|
|
}
|
2016-05-19 15:28:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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, "",
|
2019-04-05 21:13:59 +08:00
|
|
|
pss->login_expires)) {
|
|
|
|
lwsl_err("fail1\n");
|
2016-05-19 15:28:31 +08:00
|
|
|
return 1;
|
2019-04-05 21:13:59 +08:00
|
|
|
}
|
2016-05-19 15:28:31 +08:00
|
|
|
} 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);
|
|
|
|
|
2019-04-05 21:13:59 +08:00
|
|
|
lwsl_err("%s: setting cookie '%s'\n", __func__, cookie);
|
2016-05-19 15:28:31 +08:00
|
|
|
|
|
|
|
pss->logging_out = 0;
|
|
|
|
|
|
|
|
if (lws_add_http_header_by_name(wsi,
|
|
|
|
(unsigned char *)"set-cookie:",
|
|
|
|
(unsigned char *)cookie, pc - cookie,
|
2019-04-05 21:13:59 +08:00
|
|
|
&p, end)) {
|
|
|
|
lwsl_err("fail2\n");
|
2016-05-19 15:28:31 +08:00
|
|
|
return 1;
|
2019-04-05 21:13:59 +08:00
|
|
|
}
|
2016-05-19 15:28:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (lws_finalize_http_header(wsi, &p, end))
|
|
|
|
return 1;
|
|
|
|
|
2019-04-05 21:13:59 +08:00
|
|
|
// lwsl_hexdump_notice(start, p - start);
|
|
|
|
|
|
|
|
n = lws_write(wsi, start, p - start, LWS_WRITE_H2_STREAM_END |
|
|
|
|
LWS_WRITE_HTTP_HEADERS);
|
2016-05-19 15:28:31 +08:00
|
|
|
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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
LWS_VISIBLE int
|
2016-05-19 15:28:31 +08:00
|
|
|
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;
|
2018-08-16 19:10:32 +08:00
|
|
|
c->count_protocols = LWS_ARRAY_SIZE(protocols);
|
2016-05-19 15:28:31 +08:00
|
|
|
c->extensions = NULL;
|
|
|
|
c->count_extensions = 0;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
LWS_VISIBLE int
|
2016-05-19 15:28:31 +08:00
|
|
|
destroy_protocol_generic_sessions(struct lws_context *context)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|