1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25 #include "private-lwsgs.h"
26
27 #if defined(LWS_WITH_SMTP)
28
29 static int
lwsgs_smtp_client_done(struct lws_smtp_email * e,void * buf,size_t len)30 lwsgs_smtp_client_done(struct lws_smtp_email *e, void *buf, size_t len)
31 {
32 free(e);
33
34 return 0;
35 }
36
37 static int
lwsgs_smtp_client_done_sentvfy(struct lws_smtp_email * e,void * buf,size_t len)38 lwsgs_smtp_client_done_sentvfy(struct lws_smtp_email *e, void *buf, size_t len)
39 {
40 struct per_vhost_data__gs *vhd = (struct per_vhost_data__gs *)e->data;
41 const char *username = (const char *)e->extra;
42 char s[200], esc[96];
43
44 lwsl_notice("%s: registration email sent: %s\n", __func__, username);
45
46 /* mark the user as having sent the verification email */
47 lws_snprintf(s, sizeof(s) - 1,
48 "update users set verified=1 where username='%s' and verified==0;",
49 lws_sql_purify(esc, username, sizeof(esc) - 1));
50 if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
51 lwsl_err("%s: Unable to update user: %s\n", __func__,
52 sqlite3_errmsg(vhd->pdb));
53 return 1;
54 }
55
56 free(e);
57
58 return 0;
59 }
60 #endif
61
62 /* handle account confirmation links */
63
64 int
lwsgs_handler_confirm(struct per_vhost_data__gs * vhd,struct lws * wsi,struct per_session_data__gs * pss)65 lwsgs_handler_confirm(struct per_vhost_data__gs *vhd, struct lws *wsi,
66 struct per_session_data__gs *pss)
67 {
68 char cookie[1024], s[256], esc[90];
69 struct lws_gs_event_args a;
70 struct lwsgs_user u;
71
72 if (lws_hdr_copy_fragment(wsi, cookie, sizeof(cookie),
73 WSI_TOKEN_HTTP_URI_ARGS, 0) < 0) {
74 lwsl_err("%s: missing URI_ARGS\n", __func__);
75 goto verf_fail;
76 }
77
78 if (strncmp(cookie, "token=", 6)) {
79 lwsl_err("%s: missing URI_ARGS token=\n", __func__);
80 goto verf_fail;
81 }
82
83 u.username[0] = '\0';
84 u.verified = -1;
85 lws_snprintf(s, sizeof(s) - 1,
86 "select username,email,verified from users where token = '%s';",
87 lws_sql_purify(esc, &cookie[6], sizeof(esc) - 1));
88 puts(s);
89 if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) !=
90 SQLITE_OK) {
91 lwsl_err("Unable to lookup token: %s\n",
92 sqlite3_errmsg(vhd->pdb));
93 goto verf_fail;
94 }
95
96 if (!u.username[0] || u.verified != 1) {
97 lwsl_notice("verify token %s doesn't map to unverified user (user='%s', verified=%d)\n",
98 &cookie[6], u.username, u.verified);
99 goto verf_fail;
100 }
101
102 lwsl_notice("Verifying %s\n", u.username);
103 lws_snprintf(s, sizeof(s) - 1,
104 "update users set verified=%d where username='%s';",
105 LWSGS_VERIFIED_ACCEPTED,
106 lws_sql_purify(esc, u.username, sizeof(esc) - 1));
107 if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) !=
108 SQLITE_OK) {
109 lwsl_err("Unable to lookup token: %s\n",
110 sqlite3_errmsg(vhd->pdb));
111
112 goto verf_fail;
113 }
114
115 lwsl_notice("deleting account\n");
116
117 a.event = LWSGSE_CREATED;
118 a.username = u.username;
119 a.email = u.email;
120 lws_callback_vhost_protocols_vhost(lws_get_vhost(wsi),
121 LWS_CALLBACK_GS_EVENT, &a, 0);
122
123 lws_snprintf(pss->onward, sizeof(pss->onward),
124 "%s/post-verify-ok.html", vhd->email_confirm_url);
125
126 pss->login_expires = lws_now_secs() + vhd->timeout_absolute_secs;
127
128 pss->delete_session.id[0] = '\0';
129 lwsgs_get_sid_from_wsi(wsi, &pss->delete_session);
130
131 /* we need to create a new, authorized session */
132
133 if (lwsgs_new_session_id(vhd, &pss->login_session, u.username,
134 pss->login_expires))
135 goto verf_fail;
136
137 lwsl_notice("Creating new session: %s, redir to %s\n",
138 pss->login_session.id, pss->onward);
139
140 return 0;
141
142 verf_fail:
143 pss->delete_session.id[0] = '\0';
144 lwsgs_get_sid_from_wsi(wsi, &pss->delete_session);
145 pss->login_expires = 0;
146
147 lws_snprintf(pss->onward, sizeof(pss->onward), "%s/post-verify-fail.html",
148 vhd->email_confirm_url);
149
150 return 1;
151 }
152
153 /* handle forgot password confirmation links */
154
155 int
lwsgs_handler_forgot(struct per_vhost_data__gs * vhd,struct lws * wsi,struct per_session_data__gs * pss)156 lwsgs_handler_forgot(struct per_vhost_data__gs *vhd, struct lws *wsi,
157 struct per_session_data__gs *pss)
158 {
159 char cookie[1024], s[256], esc[96];
160 struct lwsgs_user u;
161 const char *a;
162
163 a = lws_get_urlarg_by_name(wsi, "token=", cookie, sizeof(cookie));
164 if (!a)
165 goto forgot_fail;
166
167 u.username[0] = '\0';
168 lws_snprintf(s, sizeof(s) - 1,
169 "select username,verified from users where verified=%d and "
170 "token = '%s' and token_time != 0;",
171 LWSGS_VERIFIED_ACCEPTED,
172 lws_sql_purify(esc, &cookie[6], sizeof(esc) - 1));
173 if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) !=
174 SQLITE_OK) {
175 lwsl_err("Unable to lookup token: %s\n",
176 sqlite3_errmsg(vhd->pdb));
177
178 goto forgot_fail;
179 }
180
181 if (!u.username[0]) {
182 puts(s);
183 lwsl_notice("forgot token doesn't map to verified user\n");
184 goto forgot_fail;
185 }
186
187 /* mark user as having validated forgot flow just now */
188
189 lws_snprintf(s, sizeof(s) - 1,
190 "update users set token_time=0,last_forgot_validated=%lu "
191 "where username='%s';",
192 (unsigned long)lws_now_secs(),
193 lws_sql_purify(esc, u.username, sizeof(esc) - 1));
194
195 if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) !=
196 SQLITE_OK) {
197 lwsl_err("Unable to lookup token: %s\n",
198 sqlite3_errmsg(vhd->pdb));
199 goto forgot_fail;
200 }
201
202 a = lws_get_urlarg_by_name(wsi, "good=", cookie, sizeof(cookie));
203 if (!a)
204 a = "broken-forget-post-good-url";
205
206 lws_snprintf(pss->onward, sizeof(pss->onward),
207 "%s/%s", vhd->email_confirm_url, a);
208
209 pss->login_expires = lws_now_secs() + vhd->timeout_absolute_secs;
210
211 pss->delete_session.id[0] = '\0';
212 lwsgs_get_sid_from_wsi(wsi, &pss->delete_session);
213
214 /* we need to create a new, authorized session */
215 if (lwsgs_new_session_id(vhd, &pss->login_session,
216 u.username,
217 pss->login_expires))
218 goto forgot_fail;
219
220 lwsl_notice("Creating new session: %s, redir to %s\n",
221 pss->login_session.id, pss->onward);
222
223 return 0;
224
225 forgot_fail:
226 pss->delete_session.id[0] = '\0';
227 lwsgs_get_sid_from_wsi(wsi, &pss->delete_session);
228 pss->login_expires = 0;
229
230 a = lws_get_urlarg_by_name(wsi, "bad=", cookie, sizeof(cookie));
231 if (!a)
232 a = "broken-forget-post-bad-url";
233
234 lws_snprintf(pss->onward, sizeof(pss->onward), "%s/%s",
235 vhd->email_confirm_url, a);
236
237 return 1;
238 }
239
240 /* support dynamic username / email checking */
241
242 int
lwsgs_handler_check(struct per_vhost_data__gs * vhd,struct lws * wsi,struct per_session_data__gs * pss,const char * in)243 lwsgs_handler_check(struct per_vhost_data__gs *vhd,
244 struct lws *wsi, struct per_session_data__gs *pss,
245 const char *in)
246 {
247 static const char * const colname[] = { "username", "email" };
248 char s[256], esc[96], *pc;
249 unsigned char *p, *start, *end, buffer[LWS_PRE + 1024];
250 struct lwsgs_user u;
251 int n;
252
253 /*
254 * either /check/email=xxx@yyy or: /check/username=xxx
255 * returns '0' if not already registered, else '1'
256 */
257
258 u.username[0] = '\0';
259
260 n = !strncmp(in, "email=", 6);
261 pc = strchr(in, '=');
262 if (!pc) {
263 lwsl_notice("cookie has no =\n");
264 goto reply;
265 }
266 pc++;
267
268 /* admin user cannot be registered in user db */
269 if (!strcmp(vhd->admin_user, pc)) {
270 u.username[0] = 'a';
271 goto reply;
272 }
273
274 lws_snprintf(s, sizeof(s) - 1,
275 "select username, email from users where %s = '%s';",
276 colname[n], lws_sql_purify(esc, pc, sizeof(esc) - 1));
277 if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) !=
278 SQLITE_OK) {
279 lwsl_err("Unable to lookup token: %s\n",
280 sqlite3_errmsg(vhd->pdb));
281 goto reply;
282 }
283
284 reply:
285 s[0] = '0' + !!u.username[0];
286 p = buffer + LWS_PRE;
287 start = p;
288 end = p + sizeof(buffer) - LWS_PRE;
289
290 if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end))
291 return -1;
292 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
293 (unsigned char *)"text/plain", 10,
294 &p, end))
295 return -1;
296
297 if (lws_add_http_header_content_length(wsi, 1, &p, end))
298 return -1;
299
300 if (lws_finalize_http_header(wsi, &p, end))
301 return -1;
302
303 n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS);
304 if (n != (p - start)) {
305 lwsl_err("_write returned %d from %ld\n", n, (long)(p - start));
306 return -1;
307 }
308
309 pss->check_response_value = s[0];
310 pss->check_response = 1;
311
312 lws_callback_on_writable(wsi);
313
314 return 0;
315 }
316
317 /* handle forgot password confirmation links */
318
319 int
lwsgs_handler_change_password(struct per_vhost_data__gs * vhd,struct lws * wsi,struct per_session_data__gs * pss)320 lwsgs_handler_change_password(struct per_vhost_data__gs *vhd, struct lws *wsi,
321 struct per_session_data__gs *pss)
322 {
323 char s[256], esc[96], username[96];
324 struct lwsgs_user u;
325 lwsgw_hash sid;
326 int n = 0;
327
328 /* see if he's logged in */
329 username[0] = '\0';
330 if (!lwsgs_get_sid_from_wsi(wsi, &sid)) {
331 u.username[0] = '\0';
332 if (!lwsgs_lookup_session(vhd, &sid, username, sizeof(username))) {
333 n = 1; /* yes, logged in */
334 if (lwsgs_lookup_user(vhd, username, &u))
335 return 1;
336
337 /* did a forgot pw ? */
338 if (u.last_forgot_validated > (time_t)lws_now_secs() - 300) {
339 n |= LWSGS_AUTH_FORGOT_FLOW;
340 lwsl_debug("within forgot password flow\n");
341 }
342 }
343 }
344
345 lwsl_debug("auth value %d\n", n);
346
347 /* if he just did forgot pw flow, don't need old pw */
348 if ((n & (LWSGS_AUTH_FORGOT_FLOW | 1)) != (LWSGS_AUTH_FORGOT_FLOW | 1)) {
349 /* otherwise user:pass must be right */
350 lwsl_debug("checking pw\n");
351 if (lwsgs_check_credentials(vhd,
352 lws_spa_get_string(pss->spa, FGS_USERNAME),
353 lws_spa_get_string(pss->spa, FGS_CURPW))) {
354 lwsl_notice("credentials bad\n");
355 return 1;
356 }
357
358 lwsl_debug("current pw checks out\n");
359
360 lws_strncpy(u.username, lws_spa_get_string(pss->spa, FGS_USERNAME),
361 sizeof(u.username));
362 }
363
364 /* does he want to delete his account? */
365
366 if (lws_spa_get_length(pss->spa, FGS_DELETE)) {
367 struct lws_gs_event_args a;
368
369 lwsl_notice("deleting account\n");
370
371 a.event = LWSGSE_DELETED;
372 a.username = u.username;
373 a.email = "";
374 lws_callback_vhost_protocols_vhost(lws_get_vhost(wsi),
375 LWS_CALLBACK_GS_EVENT, &a, 0);
376
377 lws_snprintf(s, sizeof(s) - 1,
378 "delete from users where username='%s';"
379 "delete from sessions where username='%s';",
380 lws_sql_purify(esc, u.username, sizeof(esc) - 1),
381 lws_sql_purify(esc, u.username, sizeof(esc) - 1));
382 goto sql;
383 }
384
385 if (lwsgs_hash_password(vhd, lws_spa_get_string(pss->spa, FGS_PASSWORD), &u))
386 return 1;
387
388 lwsl_notice("updating password hash\n");
389
390 lws_snprintf(s, sizeof(s) - 1,
391 "update users set pwhash='%s', pwsalt='%s', "
392 "last_forgot_validated=0 where username='%s';",
393 u.pwhash.id, u.pwsalt.id,
394 lws_sql_purify(esc, u.username, sizeof(esc) - 1));
395
396 sql:
397 if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
398 lwsl_err("Unable to update pw hash: %s\n",
399 sqlite3_errmsg(vhd->pdb));
400 return 1;
401 }
402
403 return 0;
404 }
405
406 int
lwsgs_handler_forgot_pw_form(struct per_vhost_data__gs * vhd,struct lws * wsi,struct per_session_data__gs * pss)407 lwsgs_handler_forgot_pw_form(struct per_vhost_data__gs *vhd,
408 struct lws *wsi, struct per_session_data__gs *pss)
409 {
410 char esc[96], esc1[96], esc2[96], esc3[96], esc4[96];
411 char s[LWSGS_EMAIL_CONTENT_SIZE];
412 unsigned char sid_rand[32];
413 #if defined(LWS_WITH_SMTP)
414 lws_smtp_email_t *em;
415 #endif
416 struct lwsgs_user u;
417 lwsgw_hash hash;
418 int n;
419
420 lwsl_notice("FORGOT %s %s\n",
421 lws_spa_get_string(pss->spa, FGS_USERNAME),
422 lws_spa_get_string(pss->spa, FGS_EMAIL));
423
424 if (!lws_spa_get_string(pss->spa, FGS_USERNAME) &&
425 !lws_spa_get_string(pss->spa, FGS_EMAIL)) {
426 lwsl_err("Form must provide either "
427 "username or email\n");
428 return -1;
429 }
430
431 if (!lws_spa_get_string(pss->spa, FGS_FORGOT_GOOD) ||
432 !lws_spa_get_string(pss->spa, FGS_FORGOT_BAD) ||
433 !lws_spa_get_string(pss->spa, FGS_FORGOT_POST_GOOD) ||
434 !lws_spa_get_string(pss->spa, FGS_FORGOT_POST_BAD)) {
435 lwsl_err("Form must provide reg-good "
436 "and reg-bad (and post-*)"
437 "targets\n");
438 return -1;
439 }
440
441 u.username[0] = '\0';
442 if (lws_spa_get_string(pss->spa, FGS_USERNAME))
443 lws_snprintf(s, sizeof(s) - 1,
444 "select username,email "
445 "from users where username = '%s';",
446 lws_sql_purify(esc, lws_spa_get_string(pss->spa, FGS_USERNAME),
447 sizeof(esc) - 1));
448 else
449 lws_snprintf(s, sizeof(s) - 1,
450 "select username,email "
451 "from users where email = '%s';",
452 lws_sql_purify(esc, lws_spa_get_string(pss->spa, FGS_EMAIL), sizeof(esc) - 1));
453 if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) !=
454 SQLITE_OK) {
455 lwsl_err("Unable to lookup token: %s\n",
456 sqlite3_errmsg(vhd->pdb));
457 return 1;
458 }
459 if (!u.username[0]) {
460 lwsl_err("No match found %s\n", s);
461 return 1;
462 }
463
464 lws_get_peer_simple(wsi, pss->ip, sizeof(pss->ip));
465 if (lws_get_random(vhd->context, sid_rand,
466 sizeof(sid_rand)) !=
467 sizeof(sid_rand)) {
468 lwsl_err("Problem getting random for token\n");
469 return 1;
470 }
471 sha256_to_lwsgw_hash(sid_rand, &hash);
472
473 lws_snprintf(s, sizeof(s) - 1,
474 "update users set token='%s',token_time='%ld' where username='%s';",
475 hash.id, (long)lws_now_secs(),
476 lws_sql_purify(esc, u.username, sizeof(esc) - 1));
477 if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) !=
478 SQLITE_OK) {
479 lwsl_err("Unable to set token: %s\n",
480 sqlite3_errmsg(vhd->pdb));
481 return 1;
482 }
483
484 n = lws_snprintf(s, sizeof(s),
485 "From: Forgot Password Assistant Noreply <%s>\n"
486 "To: %s <%s>\n"
487 "Subject: Password reset request\n"
488 "\n"
489 "Hello, %s\n\n"
490 "We received a password reset request from IP %s for this email,\n"
491 "to confirm you want to do that, please click the link below.\n\n",
492 lws_sql_purify(esc, vhd->email_from, sizeof(esc) - 1),
493 lws_sql_purify(esc1, u.username, sizeof(esc1) - 1),
494 lws_sql_purify(esc2, u.email, sizeof(esc2) - 1),
495 lws_sql_purify(esc3, u.username, sizeof(esc3) - 1),
496 lws_sql_purify(esc4, pss->ip, sizeof(esc4) - 1));
497 lws_snprintf(s + n, sizeof(s) - n,
498 "%s/lwsgs-forgot?token=%s"
499 "&good=%s"
500 "&bad=%s\n\n"
501 "If this request is unexpected, please ignore it and\n"
502 "no further action will be taken.\n\n"
503 "If you have any questions or concerns about this\n"
504 "automated email, you can contact a real person at\n"
505 "%s.\n"
506 "\n.\n",
507 vhd->email_confirm_url, hash.id,
508 lws_urlencode(esc1,
509 lws_spa_get_string(pss->spa, FGS_FORGOT_POST_GOOD),
510 sizeof(esc1) - 1),
511 lws_urlencode(esc3,
512 lws_spa_get_string(pss->spa, FGS_FORGOT_POST_BAD),
513 sizeof(esc3) - 1),
514 vhd->email_contact_person);
515
516 puts(s);
517 #if defined(LWS_WITH_SMTP)
518
519 em = lws_smtpc_alloc_email_helper(s, n, vhd->email_from, u.email,
520 u.username, strlen(u.username),
521 vhd, lwsgs_smtp_client_done);
522 if (!em)
523 return 1;
524 if (lws_smtpc_add_email(vhd->smtp_client, em))
525 return 1;
526 #endif
527 return 0;
528 }
529
530 int
lwsgs_handler_register_form(struct per_vhost_data__gs * vhd,struct lws * wsi,struct per_session_data__gs * pss)531 lwsgs_handler_register_form(struct per_vhost_data__gs *vhd,
532 struct lws *wsi,
533 struct per_session_data__gs *pss)
534 {
535 unsigned char buffer[LWS_PRE + LWSGS_EMAIL_CONTENT_SIZE];
536 char esc[96], esc1[96], esc2[96], esc3[96], esc4[96];
537 char s[LWSGS_EMAIL_CONTENT_SIZE];
538 unsigned char sid_rand[32];
539 #if defined(LWS_WITH_SMTP)
540 lws_smtp_email_t *em;
541 #endif
542 struct lwsgs_user u;
543 lwsgw_hash hash;
544 size_t n;
545
546 lwsl_notice("REGISTER %s %s %s\n",
547 lws_spa_get_string(pss->spa, FGS_USERNAME),
548 lws_spa_get_string(pss->spa, FGS_PASSWORD),
549 lws_spa_get_string(pss->spa, FGS_EMAIL));
550 if (lwsgs_get_sid_from_wsi(wsi,
551 &pss->login_session))
552 return 1;
553
554 lws_get_peer_simple(wsi, pss->ip, sizeof(pss->ip));
555 lwsl_notice("IP=%s\n", pss->ip);
556
557 if (!lws_spa_get_string(pss->spa, FGS_REG_GOOD) ||
558 !lws_spa_get_string(pss->spa, FGS_REG_BAD)) {
559 lwsl_info("Form must provide reg-good and reg-bad targets\n");
560 return -1;
561 }
562
563 /* admin user cannot be registered in user db */
564 if (!strcmp(vhd->admin_user,
565 lws_spa_get_string(pss->spa, FGS_USERNAME)))
566 return 1;
567
568 if (!lwsgs_lookup_user(vhd,
569 lws_spa_get_string(pss->spa, FGS_USERNAME), &u)) {
570 lwsl_notice("user %s already registered\n",
571 lws_spa_get_string(pss->spa, FGS_USERNAME));
572 return 1;
573 }
574
575 u.username[0] = '\0';
576 lws_snprintf(s, sizeof(s) - 1, "select username, email from users where email = '%s';",
577 lws_sql_purify(esc, lws_spa_get_string(pss->spa, FGS_EMAIL),
578 sizeof(esc) - 1));
579
580 if (sqlite3_exec(vhd->pdb, s,
581 lwsgs_lookup_callback_user, &u, NULL) != SQLITE_OK) {
582 lwsl_err("Unable to lookup token: %s\n",
583 sqlite3_errmsg(vhd->pdb));
584 return 1;
585 }
586
587 if (u.username[0]) {
588 lwsl_notice("email %s already in use\n",
589 lws_spa_get_string(pss->spa, FGS_USERNAME));
590 return 1;
591 }
592
593 if (lwsgs_hash_password(vhd, lws_spa_get_string(pss->spa, FGS_PASSWORD),
594 &u)) {
595 lwsl_err("Password hash failed\n");
596 return 1;
597 }
598
599 if (lws_get_random(vhd->context, sid_rand, sizeof(sid_rand)) !=
600 sizeof(sid_rand)) {
601 lwsl_err("Problem getting random for token\n");
602 return 1;
603 }
604 sha256_to_lwsgw_hash(sid_rand, &hash);
605
606 lws_snprintf((char *)buffer, sizeof(buffer) - 1,
607 "insert into users(username,"
608 " creation_time, ip, email, verified,"
609 " pwhash, pwsalt, token, last_forgot_validated)"
610 " values ('%s', %lu, '%s', '%s', 0,"
611 " '%s', '%s', '%s', 0);",
612 lws_sql_purify(esc, lws_spa_get_string(pss->spa, FGS_USERNAME), sizeof(esc) - 1),
613 (unsigned long)lws_now_secs(),
614 lws_sql_purify(esc1, pss->ip, sizeof(esc1) - 1),
615 lws_sql_purify(esc2, lws_spa_get_string(pss->spa, FGS_EMAIL), sizeof(esc2) - 1),
616 u.pwhash.id, u.pwsalt.id, hash.id);
617
618 if (sqlite3_exec(vhd->pdb, (char *)buffer, NULL, NULL, NULL) != SQLITE_OK) {
619 lwsl_err("Unable to insert user: %s\n",
620 sqlite3_errmsg(vhd->pdb));
621 return 1;
622 }
623
624 n = lws_snprintf(s, sizeof(s),
625 "From: Noreply <%s>\n"
626 "To: %s <%s>\n"
627 "Subject: Registration verification\n"
628 "\n"
629 "Hello, %s\n\n"
630 "We received a registration from IP %s using this email,\n"
631 "to confirm it is legitimate, please click the link below.\n\n"
632 "%s/lwsgs-confirm?token=%s\n\n"
633 "If this request is unexpected, please ignore it and\n"
634 "no further action will be taken.\n\n"
635 "If you have any questions or concerns about this\n"
636 "automated email, you can contact a real person at\n"
637 "%s.\n"
638 "\n.\n",
639 lws_sql_purify(esc, vhd->email_from, sizeof(esc) - 1),
640 lws_sql_purify(esc1, lws_spa_get_string(pss->spa, FGS_USERNAME), sizeof(esc1) - 1),
641 lws_sql_purify(esc2, lws_spa_get_string(pss->spa, FGS_EMAIL), sizeof(esc2) - 1),
642 lws_sql_purify(esc3, lws_spa_get_string(pss->spa, FGS_USERNAME), sizeof(esc3) - 1),
643 lws_sql_purify(esc4, pss->ip, sizeof(esc4) - 1),
644 vhd->email_confirm_url, hash.id,
645 vhd->email_contact_person);
646
647 #if defined(LWS_WITH_SMTP)
648 em = lws_smtpc_alloc_email_helper(s, n, vhd->email_from,
649 lws_spa_get_string(pss->spa, FGS_EMAIL),
650 lws_spa_get_string(pss->spa, FGS_USERNAME),
651 strlen(lws_spa_get_string(pss->spa, FGS_USERNAME)),
652 vhd, lwsgs_smtp_client_done_sentvfy);
653 if (!em)
654 return 1;
655
656 if (lws_smtpc_add_email(vhd->smtp_client, em))
657 return 1;
658 #else
659 (void)n;
660 #endif
661
662 return 0;
663 }
664