annotate mrjunejune/auth_api.c @ 279:b3b547563ec7

Add Google connector service and agent wiki Implement the C/Seobeo Google Drive and Gmail connector with encrypted OAuth storage, Zenbu authentication, browser testing, AI tool discovery, chunked HTTP decoding, and Bazel coverage. Consolidate repository guidance into progressive wiki documentation and enforce arena-first allocation for new first-party C code. Co-authored-by: Copilot <[email protected]> Copilot-Session: 84c338fd-0939-4bb3-b7f3-1062eb213e5d
author MrJuneJune <me@mrjunejune.com>
date Mon, 17 Aug 2026 22:22:36 -0700
parents 04fee26ecce0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1 #include "mrjunejune/auth_api.h"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2 #include "mrjunejune/template_renderer.h"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
3
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
4 #include "auth/auth_crypto.h"
279
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
5 #include "auth/auth_http.h"
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
6 #include "auth/auth_store.h"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
7 #include "seobeo/seobeo.h"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
8 #include "dowa/dowa.h"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
9
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
10 #include <openssl/hmac.h>
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
11 #include <openssl/evp.h>
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
12 #include <openssl/rand.h>
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
13 #include <openssl/crypto.h>
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
14
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
15 #include <arpa/inet.h>
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
16 #include <pthread.h>
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
17 #include <stdio.h>
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
18 #include <stdlib.h>
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
19 #include <string.h>
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
20 #include <strings.h>
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
21 #include <time.h>
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
22
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
23 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
24 /* Constants */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
25 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
26
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
27 #define BODY_MAX_BYTES 4096
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
28 #define COOKIE_VALUE_MAX 512
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
29 #define RATE_TABLE_SIZE 512 /* must be power of 2 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
30 #define RATE_PROBE_LIMIT 16
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
31 #define RATE_LIMIT_MAX_FAILURES 5
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
32 #define RATE_LIMIT_WINDOW_SECS (15 * 60)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
33 #define SESSION_COOKIE_MAX 512
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
34 #define GUEST_COOKIE_MAX (AUTH_CRYPTO_GUEST_COOKIE_SIZE + 256)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
35 #define RATE_KEY_MAX 65
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
36
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
37 /*
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
38 * Fixed precomputed scrypt hash of the constant string "dummy-zenbu-timing".
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
39 * Used only for timing-attack mitigation on nonexistent-username lookups.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
40 * Never used as an account credential; salt+hash are intentionally public.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
41 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
42 #define AUTH_DUMMY_PASSWORD_HASH \
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
43 "zenbu-scrypt$v=1$N=32768$r=8$p=1$" \
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
44 "c4ff27cc756429b17991b80e4c2c5f77$" \
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
45 "34e208b3a51796ebd3b39da1039611b1c7ffeb04090b07ef2bf4968ce8131ce3"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
46
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
47 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
48 /* Module state */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
49 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
50
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
51 static Auth_Store *g_auth_store = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
52 static uint8 g_cookie_secret[AUTH_CRYPTO_COOKIE_SECRET_MAX_BYTES];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
53 static size_t g_cookie_secret_length = 0;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
54 static char g_trusted_proxy_ip[AUTH_CRYPTO_IP_MAX_BYTES];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
55 static boolean g_has_trusted_proxy = FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
56 static int64 g_session_idle_ttl = AUTH_API_SESSION_IDLE_TTL_DEFAULT;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
57 static int64 g_session_abs_ttl = AUTH_API_SESSION_ABS_TTL_DEFAULT;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
58 static int64 g_guest_ttl = AUTH_API_GUEST_TTL_DEFAULT;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
59 static boolean g_dev_insecure_cookie = FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
60 static Auth_Guest_Transfer_Hook g_transfer_hook = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
61 static void *g_transfer_hook_ctx = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
62 static Auth_API_Guest_Quota_Cb g_guest_quota_cb = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
63 #ifdef AUTH_API_TEST_HOOKS
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
64 static Auth_API_Test_Login_Pre_Create_Hook g_login_pre_create_hook = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
65 static void *g_login_pre_create_context = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
66 #endif
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
67
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
68 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
69 /* Rate limiter (collision-safe open-addressing with LRU eviction) */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
70 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
71
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
72 typedef struct {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
73 char key[RATE_KEY_MAX]; /* HMAC hex binding; empty if slot unused */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
74 uint32 count;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
75 int64 window_start;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
76 } Auth_Rate_Entry;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
77
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
78 static Auth_Rate_Entry g_rate_table[RATE_TABLE_SIZE];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
79 static pthread_mutex_t g_rate_mutex = PTHREAD_MUTEX_INITIALIZER;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
80
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
81 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
82 /* Internal helpers */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
83 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
84
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
85 static int64 auth_now(void)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
86 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
87 return (int64)time(NULL);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
88 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
89
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
90 /*
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
91 * Generate a UUID v4 using RAND_bytes.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
92 * buf must be at least 37 bytes.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
93 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
94 static boolean auth_uuid4(char *buf, size_t capacity)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
95 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
96 if (capacity < 37) return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
97 uint8 rnd[16];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
98 if (RAND_bytes(rnd, sizeof(rnd)) != 1) return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
99 /* RFC 4122 version 4 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
100 rnd[6] = (rnd[6] & 0x0f) | 0x40;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
101 rnd[8] = (rnd[8] & 0x3f) | 0x80;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
102 snprintf(buf, capacity,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
103 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
104 "%02x%02x%02x%02x%02x%02x",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
105 rnd[0], rnd[1], rnd[2], rnd[3],
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
106 rnd[4], rnd[5],
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
107 rnd[6], rnd[7],
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
108 rnd[8], rnd[9],
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
109 rnd[10], rnd[11], rnd[12], rnd[13], rnd[14], rnd[15]);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
110 OPENSSL_cleanse(rnd, sizeof(rnd));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
111 return TRUE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
112 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
113
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
114 static void auth_hex_encode(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
115 const uint8 *src,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
116 size_t src_len,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
117 char *dst,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
118 size_t dst_capacity)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
119 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
120 static const char kHex[] = "0123456789abcdef";
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
121 size_t i = 0, o = 0;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
122 while (i < src_len && o + 2 < dst_capacity)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
123 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
124 dst[o++] = kHex[(src[i] >> 4) & 0xf];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
125 dst[o++] = kHex[src[i] & 0xf];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
126 i++;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
127 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
128 if (o < dst_capacity) dst[o] = '\0';
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
129 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
130
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
131 /*
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
132 * Derive a CSRF token deterministically from a session binding.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
133 * binding: session token_digest (user) or guest_id (guest).
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
134 * Output: base64url-encoded HMAC-SHA256, AUTH_CRYPTO_TOKEN_SIZE bytes.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
135 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
136 static boolean auth_derive_csrf(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
137 const char *binding,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
138 char *csrf_out,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
139 size_t csrf_capacity)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
140 {
279
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
141 return Auth_HTTP_Derive_CSRF(
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
142 g_cookie_secret, g_cookie_secret_length,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
143 binding, csrf_out, csrf_capacity);
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
144 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
145
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
146 /*
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
147 * Build the rate-limit key: HMAC(secret, peer_digest + ":" + norm_user).
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
148 * Output: 64-char hex string.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
149 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
150 static boolean auth_rate_key(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
151 const char *peer_binding_digest,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
152 const char *normalized_username,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
153 char *key_out)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
154 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
155 char input[AUTH_CRYPTO_IP_BINDING_DIGEST_SIZE + 1 + AUTH_STORE_USERNAME_MAX + 1];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
156 int n = snprintf(input, sizeof(input), "%s:%s",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
157 peer_binding_digest, normalized_username);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
158 if (n < 0 || (size_t)n >= sizeof(input))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
159 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
160
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
161 uint8 digest[32];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
162 uint32 digest_len = 32;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
163 if (!HMAC(EVP_sha256(),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
164 g_cookie_secret, (int)g_cookie_secret_length,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
165 (const uint8 *)input, (size_t)n,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
166 digest, &digest_len))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
167 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
168 OPENSSL_cleanse(input, sizeof(input));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
169 OPENSSL_cleanse(digest, sizeof(digest));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
170 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
171 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
172 OPENSSL_cleanse(input, sizeof(input));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
173
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
174 auth_hex_encode(digest, 32, key_out, RATE_KEY_MAX);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
175 OPENSSL_cleanse(digest, sizeof(digest));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
176 return TRUE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
177 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
178
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
179 static uint32 auth_rate_index(const char *key)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
180 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
181 /* Use the first 8 hex chars of the HMAC key as a uint32 hash seed. */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
182 uint32 h = 0;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
183 for (int i = 0; i < 8 && key[i] != '\0'; i++)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
184 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
185 char c = key[i];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
186 uint32 nibble = (c >= '0' && c <= '9') ? (uint32)(c - '0') :
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
187 (c >= 'a' && c <= 'f') ? (uint32)(c - 'a' + 10) : 0;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
188 h = (h << 4) | nibble;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
189 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
190 return h & (RATE_TABLE_SIZE - 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
191 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
192
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
193 /*
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
194 * Find or insert an entry for key in the open-addressing rate table.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
195 * Probes up to RATE_PROBE_LIMIT slots from the hash index.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
196 * On a full probe window, evicts the oldest entry by window_start.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
197 * Must be called with g_rate_mutex held.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
198 * Returns a pointer to the entry on success, NULL if internal error.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
199 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
200 static Auth_Rate_Entry *auth_rate_find_or_insert(const char *key, int64 now)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
201 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
202 uint32 start = auth_rate_index(key);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
203 Auth_Rate_Entry *evict_candidate = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
204 int64 evict_time = INT64_MAX;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
205
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
206 for (uint32 i = 0; i < (uint32)RATE_PROBE_LIMIT; i++)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
207 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
208 uint32 idx = (start + i) & (RATE_TABLE_SIZE - 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
209 Auth_Rate_Entry *e = &g_rate_table[idx];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
210
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
211 /* Exact match */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
212 if (e->key[0] != '\0' &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
213 memcmp(e->key, key, RATE_KEY_MAX) == 0)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
214 return e;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
215
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
216 /* Empty slot — claim it */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
217 if (e->key[0] == '\0')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
218 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
219 memcpy(e->key, key, RATE_KEY_MAX);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
220 e->count = 0;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
221 e->window_start = now;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
222 return e;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
223 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
224
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
225 /* Expired entry — reuse it immediately */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
226 if (now - e->window_start >= RATE_LIMIT_WINDOW_SECS)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
227 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
228 memcpy(e->key, key, RATE_KEY_MAX);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
229 e->count = 0;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
230 e->window_start = now;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
231 return e;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
232 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
233
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
234 /* Track the oldest live entry for eviction */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
235 if (e->window_start < evict_time)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
236 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
237 evict_time = e->window_start;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
238 evict_candidate = e;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
239 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
240 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
241
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
242 /* All probe slots occupied by live, non-matching entries — evict oldest */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
243 if (evict_candidate)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
244 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
245 memcpy(evict_candidate->key, key, RATE_KEY_MAX);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
246 evict_candidate->count = 0;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
247 evict_candidate->window_start = now;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
248 return evict_candidate;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
249 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
250
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
251 return NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
252 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
253
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
254 /*
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
255 * Returns TRUE if the caller should be rate-limited (too many failures).
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
256 * Caller must still call auth_rate_record_failure on a failed attempt.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
257 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
258 static boolean auth_rate_check(const char *key)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
259 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
260 pthread_mutex_lock(&g_rate_mutex);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
261 int64 now = auth_now();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
262 Auth_Rate_Entry *entry = auth_rate_find_or_insert(key, now);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
263 boolean limited = FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
264 if (entry && now - entry->window_start < RATE_LIMIT_WINDOW_SECS)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
265 limited = (entry->count >= RATE_LIMIT_MAX_FAILURES);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
266 pthread_mutex_unlock(&g_rate_mutex);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
267 return limited;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
268 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
269
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
270 static void auth_rate_record_failure(const char *key)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
271 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
272 pthread_mutex_lock(&g_rate_mutex);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
273 int64 now = auth_now();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
274 Auth_Rate_Entry *entry = auth_rate_find_or_insert(key, now);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
275 if (entry)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
276 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
277 if (now - entry->window_start >= RATE_LIMIT_WINDOW_SECS)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
278 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
279 /* Window expired; start fresh */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
280 entry->count = 1;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
281 entry->window_start = now;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
282 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
283 else
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
284 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
285 entry->count++;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
286 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
287 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
288 pthread_mutex_unlock(&g_rate_mutex);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
289 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
290
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
291 static void auth_rate_reset(const char *key)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
292 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
293 pthread_mutex_lock(&g_rate_mutex);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
294 uint32 start = auth_rate_index(key);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
295 for (uint32 i = 0; i < (uint32)RATE_PROBE_LIMIT; i++)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
296 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
297 uint32 idx = (start + i) & (RATE_TABLE_SIZE - 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
298 Auth_Rate_Entry *e = &g_rate_table[idx];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
299 if (e->key[0] != '\0' && memcmp(e->key, key, RATE_KEY_MAX) == 0)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
300 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
301 memset(e, 0, sizeof(*e));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
302 break;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
303 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
304 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
305 pthread_mutex_unlock(&g_rate_mutex);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
306 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
307
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
308 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
309 /* Request helpers */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
310 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
311
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
312 static const char *auth_req_value(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
313 Seobeo_Request_Entry *p_req,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
314 const char *key)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
315 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
316 void *p = Dowa_HashMap_Get_Ptr(p_req, (char *)key);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
317 return p ? ((Seobeo_Request_Entry *)p)->value : NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
318 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
319
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
320 static boolean auth_extract_secret_field(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
321 Dowa_JSON_Entry *obj,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
322 const char *key,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
323 char *out_buf,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
324 size_t max_len)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
325 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
326 char *arena_ptr = Dowa_JSON_Get_String(obj, key);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
327 if (!arena_ptr || arena_ptr[0] == '\0')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
328 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
329
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
330 size_t field_len = strlen(arena_ptr);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
331 if (field_len > max_len)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
332 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
333 OPENSSL_cleanse(arena_ptr, field_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
334 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
335 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
336
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
337 memcpy(out_buf, arena_ptr, field_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
338 out_buf[field_len] = '\0';
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
339 OPENSSL_cleanse(arena_ptr, field_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
340 return TRUE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
341 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
342
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
343 /*
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
344 * Parse a named cookie from the Cookie header.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
345 * Returns TRUE and fills value_out on success.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
346 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
347 static boolean auth_parse_cookie(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
348 const char *cookie_header,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
349 const char *name,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
350 char *value_out,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
351 size_t capacity)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
352 {
279
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
353 return Auth_HTTP_Parse_Cookie(
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
354 cookie_header, name, value_out, capacity);
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
355 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
356
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
357 /*
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
358 * Resolve effective peer IP.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
359 * If Remote-Addr matches configured trusted proxy, accept X-Real-IP.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
360 * Never logs raw IPs.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
361 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
362 static boolean auth_peer_ip(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
363 Seobeo_Request_Entry *p_req,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
364 char *ip_out,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
365 size_t capacity)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
366 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
367 const char *direct = auth_req_value(p_req, "Remote-Addr");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
368 if (!direct || direct[0] == '\0')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
369 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
370
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
371 if (g_has_trusted_proxy &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
372 strcmp(direct, g_trusted_proxy_ip) == 0)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
373 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
374 const char *forwarded = auth_req_value(p_req, "X-Real-IP");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
375 if (forwarded && forwarded[0] != '\0' && strlen(forwarded) < capacity)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
376 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
377 strncpy(ip_out, forwarded, capacity - 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
378 ip_out[capacity - 1] = '\0';
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
379 return TRUE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
380 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
381 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
382
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
383 if (strlen(direct) >= capacity)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
384 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
385 strncpy(ip_out, direct, capacity - 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
386 ip_out[capacity - 1] = '\0';
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
387 return TRUE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
388 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
389
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
390 static boolean auth_same_origin(Seobeo_Request_Entry *p_req)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
391 {
279
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
392 return Auth_HTTP_Same_Origin(p_req);
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
393 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
394
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
395 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
396 /* Response builders */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
397 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
398
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
399 /*
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
400 * Build a Set-Cookie directive string.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
401 * expires_max_age = 0 means no Max-Age (persistent); < 0 means Max-Age=0
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
402 * (clear the cookie).
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
403 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
404 static boolean auth_build_cookie_directive(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
405 const char *name,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
406 const char *value,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
407 int32 max_age,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
408 boolean http_only,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
409 char *out,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
410 size_t capacity)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
411 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
412 int n;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
413 if (max_age < 0)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
414 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
415 n = snprintf(out, capacity,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
416 "%s=; Path=/; %sSameSite=Lax; Max-Age=0%s",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
417 name,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
418 http_only ? "HttpOnly; " : "",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
419 g_dev_insecure_cookie ? "" : "; Secure");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
420 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
421 else if (max_age == 0)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
422 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
423 n = snprintf(out, capacity,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
424 "%s=%s; Path=/; %sSameSite=Lax%s",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
425 name, value,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
426 http_only ? "HttpOnly; " : "",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
427 g_dev_insecure_cookie ? "" : "; Secure");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
428 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
429 else
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
430 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
431 n = snprintf(out, capacity,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
432 "%s=%s; Path=/; %sSameSite=Lax; Max-Age=%d%s",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
433 name, value,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
434 http_only ? "HttpOnly; " : "",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
435 max_age,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
436 g_dev_insecure_cookie ? "" : "; Secure");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
437 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
438 return n > 0 && (size_t)n < capacity;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
439 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
440
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
441 static Seobeo_Request_Entry *auth_json_response(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
442 Dowa_Arena *p_arena,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
443 const char *status,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
444 const char *body)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
445 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
446 Seobeo_Request_Entry *resp = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
447 Dowa_HashMap_Push_Arena(resp, "status", (char *)status, p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
448 Dowa_HashMap_Push_Arena(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
449 resp, "content-type", "application/json; charset=utf-8", p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
450 Dowa_HashMap_Push_Arena(resp, "cache-control", "no-store", p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
451 Dowa_HashMap_Push_Arena(resp, "pragma", "no-cache", p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
452 Dowa_HashMap_Push_Arena(resp, "x-content-type-options", "nosniff", p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
453 Dowa_HashMap_Push_Arena(resp, "body", (char *)body, p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
454 return resp;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
455 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
456
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
457 static Seobeo_Request_Entry *auth_json_response_with_cookies(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
458 Dowa_Arena *p_arena,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
459 const char *status,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
460 const char *body,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
461 const char *cookie1, /* value for "Set-Cookie"; NULL to skip */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
462 const char *cookie2) /* value for "set-cookie"; NULL to skip */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
463 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
464 Seobeo_Request_Entry *resp = auth_json_response(p_arena, status, body);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
465 if (cookie1)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
466 Dowa_HashMap_Push_Arena(resp, "Set-Cookie", (char *)cookie1, p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
467 if (cookie2)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
468 Dowa_HashMap_Push_Arena(resp, "set-cookie", (char *)cookie2, p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
469 return resp;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
470 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
471
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
472 static Seobeo_Request_Entry *auth_error(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
473 Dowa_Arena *p_arena,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
474 const char *status,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
475 const char *code,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
476 const char *message)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
477 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
478 char body[512];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
479 snprintf(body, sizeof(body),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
480 "{\"error\":{\"code\":\"%s\",\"message\":\"%s\"}}",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
481 code, message);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
482 char *body_copy = Dowa_Arena_Allocate(p_arena, strlen(body) + 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
483 if (body_copy) strcpy(body_copy, body);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
484 return auth_json_response(p_arena, status, body_copy ? body_copy : "{}");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
485 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
486
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
487 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
488 /* Principal resolution */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
489 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
490
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
491 boolean Auth_API_Resolve_Principal(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
492 Seobeo_Request_Entry *p_request,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
493 Auth_Principal *p_principal,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
494 Dowa_Arena *p_arena,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
495 char *new_guest_cookie_out,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
496 size_t new_guest_cookie_capacity)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
497 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
498 if (!g_auth_store || !p_principal) return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
499
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
500 memset(p_principal, 0, sizeof(*p_principal));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
501 if (new_guest_cookie_out && new_guest_cookie_capacity > 0)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
502 new_guest_cookie_out[0] = '\0';
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
503
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
504 const char *cookie_header = auth_req_value(p_request, "Cookie");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
505 int64 now = auth_now();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
506
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
507 /* --- Try authenticated session first --- */
279
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
508 Auth_HTTP_Authenticated_User authenticated_user;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
509 Auth_HTTP_Resolve_Result user_result =
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
510 Auth_HTTP_Resolve_Authenticated_User(
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
511 p_request, g_auth_store, g_cookie_secret, g_cookie_secret_length,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
512 now, g_session_idle_ttl, &authenticated_user);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
513 if (user_result == AUTH_HTTP_RESOLVE_ERROR)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
514 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
515 if (user_result == AUTH_HTTP_RESOLVE_OK)
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
516 {
279
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
517 p_principal->kind = AUTH_PRINCIPAL_USER;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
518 strncpy(p_principal->user_id, authenticated_user.user.id,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
519 sizeof(p_principal->user_id) - 1);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
520 strncpy(p_principal->username, authenticated_user.user.username,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
521 sizeof(p_principal->username) - 1);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
522 strncpy(p_principal->role, authenticated_user.user.role,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
523 sizeof(p_principal->role) - 1);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
524 p_principal->must_change_password =
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
525 authenticated_user.user.must_change_password;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
526 strncpy(p_principal->_binding, authenticated_user.token_digest,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
527 sizeof(p_principal->_binding) - 1);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
528 strncpy(p_principal->csrf_token, authenticated_user.csrf_token,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
529 sizeof(p_principal->csrf_token) - 1);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
530 OPENSSL_cleanse(&authenticated_user, sizeof(authenticated_user));
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
531 return TRUE;
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
532 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
533
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
534 /* --- Try guest cookie --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
535 char peer_ip[AUTH_CRYPTO_IP_MAX_BYTES] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
536 boolean have_ip = auth_peer_ip(p_request, peer_ip, sizeof(peer_ip));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
537
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
538 char ip_binding[AUTH_CRYPTO_IP_BINDING_DIGEST_SIZE] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
539 if (have_ip &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
540 Auth_Crypto_IP_Binding_Digest(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
541 g_cookie_secret, g_cookie_secret_length,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
542 peer_ip, ip_binding, sizeof(ip_binding)) != AUTH_CRYPTO_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
543 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
544 OPENSSL_cleanse(peer_ip, sizeof(peer_ip));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
545 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
546 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
547
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
548 char guest_cookie_val[COOKIE_VALUE_MAX] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
549 boolean guest_valid = FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
550 Auth_Crypto_Guest_Cookie guest_parsed;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
551 memset(&guest_parsed, 0, sizeof(guest_parsed));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
552
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
553 if (cookie_header &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
554 auth_parse_cookie(cookie_header, AUTH_API_GUEST_COOKIE_NAME,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
555 guest_cookie_val, sizeof(guest_cookie_val)) &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
556 guest_cookie_val[0] != '\0' &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
557 have_ip)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
558 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
559 Auth_Crypto_Result cr = Auth_Crypto_Guest_Cookie_Verify(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
560 g_cookie_secret, g_cookie_secret_length,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
561 guest_cookie_val, (uint64)now,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
562 ip_binding, &guest_parsed);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
563 guest_valid = (cr == AUTH_CRYPTO_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
564 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
565
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
566 if (guest_valid)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
567 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
568 Auth_Guest_Identity_Record identity;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
569 Auth_Store_Result result = Auth_Store_Find_Guest_Identity(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
570 g_auth_store, guest_parsed.guest_uuid, now, &identity);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
571
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
572 if (result == AUTH_STORE_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
573 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
574 Auth_Store_Upsert_Guest_Identity(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
575 g_auth_store, guest_parsed.guest_uuid,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
576 ip_binding, now + g_guest_ttl, &identity);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
577
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
578 p_principal->kind = AUTH_PRINCIPAL_GUEST;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
579 strncpy(p_principal->guest_id, guest_parsed.guest_uuid,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
580 sizeof(p_principal->guest_id) - 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
581 strncpy(p_principal->_binding, guest_parsed.guest_uuid,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
582 sizeof(p_principal->_binding) - 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
583 if (!auth_derive_csrf(guest_parsed.guest_uuid, p_principal->csrf_token,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
584 sizeof(p_principal->csrf_token)))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
585 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
586 OPENSSL_cleanse(guest_cookie_val, sizeof(guest_cookie_val));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
587 OPENSSL_cleanse(peer_ip, sizeof(peer_ip));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
588 memset(p_principal, 0, sizeof(*p_principal));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
589 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
590 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
591 OPENSSL_cleanse(guest_cookie_val, sizeof(guest_cookie_val));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
592 OPENSSL_cleanse(peer_ip, sizeof(peer_ip));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
593 return TRUE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
594 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
595 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
596 OPENSSL_cleanse(guest_cookie_val, sizeof(guest_cookie_val));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
597
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
598 /* --- Create new guest identity --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
599 char guest_uuid[AUTH_CRYPTO_GUEST_UUID_SIZE];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
600 if (!auth_uuid4(guest_uuid, sizeof(guest_uuid)))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
601 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
602 OPENSSL_cleanse(peer_ip, sizeof(peer_ip));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
603 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
604 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
605
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
606 int64 guest_expires = now + g_guest_ttl;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
607 Auth_Guest_Identity_Record new_identity;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
608 if (Auth_Store_Upsert_Guest_Identity(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
609 g_auth_store, guest_uuid, ip_binding, guest_expires,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
610 &new_identity) != AUTH_STORE_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
611 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
612 OPENSSL_cleanse(peer_ip, sizeof(peer_ip));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
613 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
614 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
615
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
616 p_principal->kind = AUTH_PRINCIPAL_GUEST;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
617 strncpy(p_principal->guest_id, guest_uuid,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
618 sizeof(p_principal->guest_id) - 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
619 strncpy(p_principal->_binding, guest_uuid,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
620 sizeof(p_principal->_binding) - 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
621 if (!auth_derive_csrf(guest_uuid, p_principal->csrf_token,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
622 sizeof(p_principal->csrf_token)))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
623 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
624 OPENSSL_cleanse(peer_ip, sizeof(peer_ip));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
625 memset(p_principal, 0, sizeof(*p_principal));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
626 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
627 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
628
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
629 /* Build new guest cookie for the response */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
630 if (new_guest_cookie_out && new_guest_cookie_capacity > 0 && have_ip)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
631 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
632 char signed_cookie[AUTH_CRYPTO_GUEST_COOKIE_SIZE];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
633 if (Auth_Crypto_Guest_Cookie_Create(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
634 g_cookie_secret, g_cookie_secret_length,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
635 guest_uuid, (uint64)guest_expires, ip_binding,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
636 signed_cookie, sizeof(signed_cookie)) == AUTH_CRYPTO_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
637 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
638 auth_build_cookie_directive(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
639 AUTH_API_GUEST_COOKIE_NAME, signed_cookie,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
640 (int32)g_guest_ttl, TRUE,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
641 new_guest_cookie_out, new_guest_cookie_capacity);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
642 OPENSSL_cleanse(signed_cookie, sizeof(signed_cookie));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
643 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
644 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
645
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
646 OPENSSL_cleanse(peer_ip, sizeof(peer_ip));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
647 return TRUE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
648 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
649
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
650 boolean Auth_API_Resolve_Existing_Principal(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
651 Seobeo_Request_Entry *p_request,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
652 Auth_Principal *p_principal,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
653 Dowa_Arena *p_arena,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
654 boolean *p_found)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
655 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
656 if (!g_auth_store || !p_principal || !p_found) return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
657
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
658 memset(p_principal, 0, sizeof(*p_principal));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
659 *p_found = FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
660
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
661 const char *cookie_header = auth_req_value(p_request, "Cookie");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
662 int64 now = auth_now();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
663
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
664 /* --- Try authenticated session first --- */
279
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
665 Auth_HTTP_Authenticated_User authenticated_user;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
666 Auth_HTTP_Resolve_Result user_result =
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
667 Auth_HTTP_Resolve_Authenticated_User(
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
668 p_request, g_auth_store, g_cookie_secret, g_cookie_secret_length,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
669 now, g_session_idle_ttl, &authenticated_user);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
670 if (user_result == AUTH_HTTP_RESOLVE_ERROR)
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
671 return FALSE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
672 if (user_result == AUTH_HTTP_RESOLVE_OK)
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
673 {
279
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
674 p_principal->kind = AUTH_PRINCIPAL_USER;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
675 strncpy(p_principal->user_id, authenticated_user.user.id,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
676 sizeof(p_principal->user_id) - 1);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
677 strncpy(p_principal->username, authenticated_user.user.username,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
678 sizeof(p_principal->username) - 1);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
679 strncpy(p_principal->role, authenticated_user.user.role,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
680 sizeof(p_principal->role) - 1);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
681 p_principal->must_change_password =
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
682 authenticated_user.user.must_change_password;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
683 strncpy(p_principal->_binding, authenticated_user.token_digest,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
684 sizeof(p_principal->_binding) - 1);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
685 strncpy(p_principal->csrf_token, authenticated_user.csrf_token,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
686 sizeof(p_principal->csrf_token) - 1);
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
687 OPENSSL_cleanse(&authenticated_user, sizeof(authenticated_user));
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
688 *p_found = TRUE;
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
689 return TRUE;
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
690 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
691
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
692 /* --- Try existing guest cookie (no new guest created) --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
693 char peer_ip[AUTH_CRYPTO_IP_MAX_BYTES] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
694 boolean have_ip = auth_peer_ip(p_request, peer_ip, sizeof(peer_ip));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
695
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
696 char ip_binding[AUTH_CRYPTO_IP_BINDING_DIGEST_SIZE] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
697 if (have_ip &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
698 Auth_Crypto_IP_Binding_Digest(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
699 g_cookie_secret, g_cookie_secret_length,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
700 peer_ip, ip_binding, sizeof(ip_binding)) != AUTH_CRYPTO_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
701 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
702 OPENSSL_cleanse(peer_ip, sizeof(peer_ip));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
703 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
704 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
705
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
706 char guest_cookie_val[COOKIE_VALUE_MAX] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
707 Auth_Crypto_Guest_Cookie guest_parsed;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
708 memset(&guest_parsed, 0, sizeof(guest_parsed));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
709
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
710 if (cookie_header &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
711 auth_parse_cookie(cookie_header, AUTH_API_GUEST_COOKIE_NAME,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
712 guest_cookie_val, sizeof(guest_cookie_val)) &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
713 guest_cookie_val[0] != '\0' &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
714 have_ip)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
715 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
716 Auth_Crypto_Result cr = Auth_Crypto_Guest_Cookie_Verify(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
717 g_cookie_secret, g_cookie_secret_length,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
718 guest_cookie_val, (uint64)now,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
719 ip_binding, &guest_parsed);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
720 if (cr == AUTH_CRYPTO_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
721 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
722 Auth_Guest_Identity_Record identity;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
723 Auth_Store_Result result = Auth_Store_Find_Guest_Identity(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
724 g_auth_store, guest_parsed.guest_uuid, now, &identity);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
725
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
726 if (result == AUTH_STORE_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
727 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
728 Auth_Store_Upsert_Guest_Identity(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
729 g_auth_store, guest_parsed.guest_uuid,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
730 ip_binding, now + g_guest_ttl, &identity);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
731
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
732 p_principal->kind = AUTH_PRINCIPAL_GUEST;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
733 strncpy(p_principal->guest_id, guest_parsed.guest_uuid,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
734 sizeof(p_principal->guest_id) - 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
735 strncpy(p_principal->_binding, guest_parsed.guest_uuid,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
736 sizeof(p_principal->_binding) - 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
737 if (!auth_derive_csrf(guest_parsed.guest_uuid, p_principal->csrf_token,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
738 sizeof(p_principal->csrf_token)))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
739 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
740 OPENSSL_cleanse(guest_cookie_val, sizeof(guest_cookie_val));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
741 OPENSSL_cleanse(peer_ip, sizeof(peer_ip));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
742 memset(p_principal, 0, sizeof(*p_principal));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
743 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
744 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
745 OPENSSL_cleanse(guest_cookie_val, sizeof(guest_cookie_val));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
746 OPENSSL_cleanse(peer_ip, sizeof(peer_ip));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
747 *p_found = TRUE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
748 return TRUE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
749 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
750 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
751 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
752 OPENSSL_cleanse(guest_cookie_val, sizeof(guest_cookie_val));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
753 OPENSSL_cleanse(peer_ip, sizeof(peer_ip));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
754
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
755 /* No existing identity found — caller should return 401.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
756 * We do NOT create a guest row or generate a Set-Cookie directive. */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
757 *p_found = FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
758 return TRUE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
759 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
760
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
761 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
762 /* CSRF verification helper */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
763 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
764
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
765 /*
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
766 * Verify a CSRF token provided by the client against the binding for
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
767 * the current session/guest. Comparison is by SHA-256 digest equality
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
768 * to avoid timing-oracle attacks on the base64url token directly.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
769 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
770 static boolean auth_verify_csrf(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
771 const char *provided_token,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
772 const char *binding)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
773 {
279
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
774 return Auth_HTTP_Verify_CSRF_Token(
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
775 g_cookie_secret, g_cookie_secret_length, binding, provided_token);
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
776 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
777
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
778 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
779 /* Public: Auth_API_Verify_CSRF */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
780 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
781
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
782 boolean Auth_API_Verify_CSRF(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
783 Seobeo_Request_Entry *p_request,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
784 const Auth_Principal *p_principal)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
785 {
279
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
786 if (!p_principal)
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
787 return FALSE;
279
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
788 return Auth_HTTP_Verify_CSRF(
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
789 p_request, g_cookie_secret, g_cookie_secret_length,
b3b547563ec7 Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
790 p_principal->_binding);
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
791 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
792
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
793 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
794 /* Route: GET /api/auth/session */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
795 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
796
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
797 static Seobeo_Request_Entry *auth_session_handler(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
798 Seobeo_Request_Entry *p_req,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
799 Dowa_Arena *p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
800 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
801 if (!g_auth_store)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
802 return auth_error(p_arena, "503", "service_unavailable",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
803 "Auth not initialised");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
804
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
805 Auth_Principal principal;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
806 char new_guest_cookie[GUEST_COOKIE_MAX] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
807
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
808 if (!Auth_API_Resolve_Principal(p_req, &principal, p_arena,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
809 new_guest_cookie, sizeof(new_guest_cookie)))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
810 return auth_error(p_arena, "500", "internal_error", "Session error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
811
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
812 char body[2048];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
813 if (principal.kind == AUTH_PRINCIPAL_USER)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
814 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
815 char *safe_username =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
816 Dowa_JSON_Escape_String(principal.username, 0, p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
817 char *safe_role =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
818 Dowa_JSON_Escape_String(principal.role, 0, p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
819 char *safe_csrf =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
820 Dowa_JSON_Escape_String(principal.csrf_token, 0, p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
821 if (!safe_username || !safe_role || !safe_csrf)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
822 return auth_error(p_arena, "500", "internal_error", "Encode error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
823
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
824 snprintf(body, sizeof(body),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
825 "{\"kind\":\"user\",\"username\":\"%s\",\"role\":\"%s\","
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
826 "\"mustChangePassword\":%s,\"csrfToken\":\"%s\","
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
827 "\"quota\":null}",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
828 safe_username, safe_role,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
829 principal.must_change_password ? "true" : "false",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
830 safe_csrf);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
831 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
832 else
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
833 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
834 char *safe_csrf =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
835 Dowa_JSON_Escape_String(principal.csrf_token, 0, p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
836 if (!safe_csrf)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
837 return auth_error(p_arena, "500", "internal_error", "Encode error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
838
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
839 /* Ask conversation layer for quota JSON (null if not registered). */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
840 char quota_json[512] = "null";
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
841 if (g_guest_quota_cb)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
842 g_guest_quota_cb(principal.guest_id, auth_now(), quota_json,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
843 sizeof(quota_json));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
844
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
845 snprintf(body, sizeof(body),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
846 "{\"kind\":\"guest\",\"csrfToken\":\"%s\",\"quota\":%s}",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
847 safe_csrf, quota_json);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
848 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
849
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
850 char *body_copy = Dowa_Arena_Allocate(p_arena, strlen(body) + 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
851 if (!body_copy)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
852 return auth_error(p_arena, "500", "internal_error", "OOM");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
853 strcpy(body_copy, body);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
854
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
855 const char *cookie1 = (new_guest_cookie[0] != '\0') ? new_guest_cookie : NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
856 return auth_json_response_with_cookies(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
857 p_arena, "200", body_copy, cookie1, NULL);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
858 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
859
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
860 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
861 /* Route: POST /api/auth/login */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
862 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
863
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
864 static Seobeo_Request_Entry *auth_login_handler(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
865 Seobeo_Request_Entry *p_req,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
866 Dowa_Arena *p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
867 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
868 if (!g_auth_store)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
869 return auth_error(p_arena, "503", "service_unavailable",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
870 "Auth not initialised");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
871
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
872 if (!auth_same_origin(p_req))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
873 return auth_error(p_arena, "403", "forbidden", "Origin mismatch");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
874
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
875 /* --- Parse body --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
876 const char *body_str = auth_req_value(p_req, "Body");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
877 if (!body_str)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
878 return auth_error(p_arena, "400", "bad_request", "Invalid body");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
879
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
880 size_t body_len = strlen(body_str);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
881 if (body_len > BODY_MAX_BYTES)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
882 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
883 OPENSSL_cleanse((char *)body_str, body_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
884 return auth_error(p_arena, "400", "bad_request", "Invalid body");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
885 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
886 Dowa_JSON_Value jv =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
887 Dowa_JSON_Parse(body_str, (int32)body_len, p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
888 OPENSSL_cleanse((char *)body_str, body_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
889 if (jv.type != DOWA_JSON_OBJECT)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
890 return auth_error(p_arena, "400", "bad_request", "Expected JSON object");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
891
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
892 Dowa_JSON_Entry *obj = (Dowa_JSON_Entry *)jv.object_val;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
893 char *username_raw = Dowa_JSON_Get_String(obj, "username");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
894 char *csrf_provided = Dowa_JSON_Get_String(obj, "csrfToken");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
895 char password_buf[AUTH_CRYPTO_PASSWORD_MAX_BYTES + 1];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
896 memset(password_buf, 0, sizeof(password_buf));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
897 boolean have_password = auth_extract_secret_field(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
898 obj, "password", password_buf, AUTH_CRYPTO_PASSWORD_MAX_BYTES);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
899 char *password_raw = password_buf;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
900
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
901 if (!username_raw || !have_password || !csrf_provided ||
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
902 username_raw[0] == '\0' ||
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
903 csrf_provided[0] == '\0')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
904 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
905 OPENSSL_cleanse(password_buf, sizeof(password_buf));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
906 return auth_error(p_arena, "400", "bad_request", "Missing fields");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
907 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
908
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
909 /* --- Password length bounds --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
910 size_t pw_len = strlen(password_raw);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
911 if (pw_len < 12 || pw_len > AUTH_CRYPTO_PASSWORD_MAX_BYTES)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
912 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
913 OPENSSL_cleanse(password_raw, pw_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
914 return auth_error(p_arena, "401", "invalid_credentials",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
915 "Invalid credentials");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
916 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
917
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
918 /* --- Resolve existing principal for CSRF binding --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
919 Auth_Principal principal;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
920 char ignored_cookie[GUEST_COOKIE_MAX] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
921 if (!Auth_API_Resolve_Principal(p_req, &principal, p_arena,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
922 ignored_cookie, sizeof(ignored_cookie)))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
923 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
924 OPENSSL_cleanse(password_raw, pw_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
925 return auth_error(p_arena, "500", "internal_error", "Session error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
926 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
927
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
928 /* --- CSRF check --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
929 if (!auth_verify_csrf(csrf_provided, principal._binding))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
930 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
931 OPENSSL_cleanse(password_raw, pw_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
932 return auth_error(p_arena, "403", "csrf_invalid", "CSRF token invalid");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
933 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
934
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
935 /* --- Peer IP and rate-limit key --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
936 char peer_ip[AUTH_CRYPTO_IP_MAX_BYTES] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
937 boolean have_ip = auth_peer_ip(p_req, peer_ip, sizeof(peer_ip));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
938
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
939 char ip_binding[AUTH_CRYPTO_IP_BINDING_DIGEST_SIZE] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
940 if (have_ip &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
941 Auth_Crypto_IP_Binding_Digest(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
942 g_cookie_secret, g_cookie_secret_length,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
943 peer_ip, ip_binding, sizeof(ip_binding)) != AUTH_CRYPTO_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
944 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
945 OPENSSL_cleanse(peer_ip, sizeof(peer_ip));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
946 OPENSSL_cleanse(password_raw, pw_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
947 return auth_error(p_arena, "500", "internal_error", "Binding error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
948 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
949 OPENSSL_cleanse(peer_ip, sizeof(peer_ip));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
950
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
951 /* Normalize username */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
952 char norm_username[AUTH_STORE_USERNAME_MAX + 1] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
953 if (!Auth_Store_Normalize_Username(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
954 username_raw, norm_username, sizeof(norm_username)))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
955 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
956 OPENSSL_cleanse(password_raw, pw_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
957 return auth_error(p_arena, "401", "invalid_credentials",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
958 "Invalid credentials");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
959 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
960
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
961 /* Rate limit check */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
962 char rate_key[RATE_KEY_MAX] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
963 boolean have_rate_key =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
964 auth_rate_key(ip_binding, norm_username, rate_key);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
965
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
966 if (have_rate_key && auth_rate_check(rate_key))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
967 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
968 OPENSSL_cleanse(password_raw, pw_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
969 OPENSSL_cleanse(norm_username, sizeof(norm_username));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
970 return auth_error(p_arena, "429", "too_many_requests",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
971 "Too many login attempts");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
972 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
973
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
974 /* --- Fetch user record --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
975 Auth_User_Auth_Record auth_record;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
976 memset(&auth_record, 0, sizeof(auth_record));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
977 Auth_Store_Result find_result =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
978 Auth_Store_Find_User_By_Username(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
979 g_auth_store, norm_username, &auth_record);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
980
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
981 if (find_result != AUTH_STORE_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
982 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
983 /*
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
984 * User not found; run exactly one scrypt verification against a fixed
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
985 * precomputed hash to consume constant time, then return a generic error.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
986 * AUTH_DUMMY_PASSWORD_HASH is a valid zenbu-scrypt hash of a known
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
987 * constant string — it is never an account credential.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
988 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
989 Auth_Crypto_Password_Verify(password_raw, AUTH_DUMMY_PASSWORD_HASH);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
990 OPENSSL_cleanse(password_raw, pw_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
991 OPENSSL_cleanse(auth_record.password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
992 sizeof(auth_record.password_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
993 if (have_rate_key)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
994 auth_rate_record_failure(rate_key);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
995 return auth_error(p_arena, "401", "invalid_credentials",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
996 "Invalid credentials");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
997 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
998
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
999 if (strcmp(auth_record.user.status, "active") != 0)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1000 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1001 Auth_Crypto_Password_Verify(password_raw, auth_record.password_hash);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1002 OPENSSL_cleanse(password_raw, pw_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1003 OPENSSL_cleanse(auth_record.password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1004 sizeof(auth_record.password_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1005 if (have_rate_key)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1006 auth_rate_record_failure(rate_key);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1007 return auth_error(p_arena, "401", "invalid_credentials",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1008 "Invalid credentials");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1009 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1010
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1011 /* --- Verify password --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1012 Auth_Crypto_Result verify =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1013 Auth_Crypto_Password_Verify(password_raw, auth_record.password_hash);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1014 OPENSSL_cleanse(password_raw, pw_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1015
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1016 if (verify != AUTH_CRYPTO_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1017 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1018 OPENSSL_cleanse(auth_record.password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1019 sizeof(auth_record.password_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1020 if (have_rate_key)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1021 auth_rate_record_failure(rate_key);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1022 return auth_error(p_arena, "401", "invalid_credentials",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1023 "Invalid credentials");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1024 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1025
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1026 /* Successful authentication: reset rate limit */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1027 if (have_rate_key)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1028 auth_rate_reset(rate_key);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1029
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1030 /* --- Create new session (prevents session fixation) --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1031 char new_token[AUTH_CRYPTO_TOKEN_SIZE];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1032 if (Auth_Crypto_Token_Generate(new_token, sizeof(new_token)) !=
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1033 AUTH_CRYPTO_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1034 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1035 OPENSSL_cleanse(auth_record.password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1036 sizeof(auth_record.password_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1037 return auth_error(p_arena, "500", "internal_error", "Token error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1038 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1039
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1040 char new_token_digest[AUTH_CRYPTO_TOKEN_DIGEST_SIZE];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1041 if (Auth_Crypto_Token_Digest(new_token, new_token_digest,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1042 sizeof(new_token_digest)) != AUTH_CRYPTO_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1043 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1044 OPENSSL_cleanse(auth_record.password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1045 sizeof(auth_record.password_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1046 OPENSSL_cleanse(new_token, sizeof(new_token));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1047 return auth_error(p_arena, "500", "internal_error", "Digest error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1048 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1049
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1050 /* CSRF for this new session */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1051 char new_csrf[AUTH_CRYPTO_TOKEN_SIZE];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1052 if (!auth_derive_csrf(new_token_digest, new_csrf, sizeof(new_csrf)))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1053 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1054 OPENSSL_cleanse(auth_record.password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1055 sizeof(auth_record.password_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1056 OPENSSL_cleanse(new_token, sizeof(new_token));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1057 OPENSSL_cleanse(new_token_digest, sizeof(new_token_digest));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1058 return auth_error(p_arena, "500", "internal_error", "CSRF error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1059 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1060
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1061 char csrf_digest[AUTH_CRYPTO_TOKEN_DIGEST_SIZE];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1062 if (Auth_Crypto_Token_Digest(new_csrf, csrf_digest,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1063 sizeof(csrf_digest)) != AUTH_CRYPTO_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1064 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1065 OPENSSL_cleanse(auth_record.password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1066 sizeof(auth_record.password_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1067 OPENSSL_cleanse(new_token, sizeof(new_token));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1068 OPENSSL_cleanse(new_token_digest, sizeof(new_token_digest));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1069 OPENSSL_cleanse(new_csrf, sizeof(new_csrf));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1070 return auth_error(p_arena, "500", "internal_error", "CSRF digest error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1071 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1072
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1073 int64 now = auth_now();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1074 Auth_Session_Record session;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1075 #ifdef AUTH_API_TEST_HOOKS
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1076 if (g_login_pre_create_hook)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1077 g_login_pre_create_hook(g_login_pre_create_context);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1078 #endif
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1079 Auth_Store_Result create_result = Auth_Store_Create_Session_CAS(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1080 g_auth_store,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1081 auth_record.user.id,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1082 auth_record.password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1083 new_token_digest,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1084 csrf_digest,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1085 g_session_idle_ttl,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1086 g_session_abs_ttl,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1087 now,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1088 &session);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1089
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1090 OPENSSL_cleanse(auth_record.password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1091 sizeof(auth_record.password_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1092 OPENSSL_cleanse(csrf_digest, sizeof(csrf_digest));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1093 OPENSSL_cleanse(new_token_digest, sizeof(new_token_digest));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1094
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1095 if (create_result != AUTH_STORE_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1096 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1097 OPENSSL_cleanse(new_token, sizeof(new_token));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1098 OPENSSL_cleanse(new_csrf, sizeof(new_csrf));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1099 if (create_result == AUTH_STORE_STALE_PASSWORD)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1100 return auth_error(p_arena, "401", "invalid_credentials",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1101 "Invalid credentials");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1102 return auth_error(p_arena, "500", "internal_error", "Session create failed");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1103 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1104
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1105 /* --- Call guest transfer hook (before clearing guest state) --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1106 if (g_transfer_hook &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1107 principal.kind == AUTH_PRINCIPAL_GUEST &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1108 principal.guest_id[0] != '\0')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1109 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1110 boolean transferred = g_transfer_hook(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1111 principal.guest_id, auth_record.user.id, g_transfer_hook_ctx);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1112 if (!transferred)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1113 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1114 /* Transfer failed — revoke the new session and return 500.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1115 * Guest cookie/data are preserved (no clear_guest in response). */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1116 char rev_digest[AUTH_CRYPTO_TOKEN_DIGEST_SIZE];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1117 if (Auth_Crypto_Token_Digest(new_token, rev_digest,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1118 sizeof(rev_digest)) == AUTH_CRYPTO_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1119 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1120 Auth_Store_Result revoke_result =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1121 Auth_Store_Revoke_Session(g_auth_store, rev_digest);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1122 if (revoke_result == AUTH_STORE_ERROR)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1123 Seobeo_Log(SEOBEO_ERROR,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1124 "[AUTH] Failed to revoke session after transfer failure\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1125 OPENSSL_cleanse(rev_digest, sizeof(rev_digest));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1126 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1127 OPENSSL_cleanse(new_token, sizeof(new_token));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1128 OPENSSL_cleanse(new_csrf, sizeof(new_csrf));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1129 return auth_error(p_arena, "500", "transfer_failed",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1130 "Resource transfer failed");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1131 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1132 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1133
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1134 /* --- Build response --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1135 char *safe_username =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1136 Dowa_JSON_Escape_String(auth_record.user.username, 0, p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1137 char *safe_role =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1138 Dowa_JSON_Escape_String(auth_record.user.role, 0, p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1139 char *safe_csrf =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1140 Dowa_JSON_Escape_String(new_csrf, 0, p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1141 OPENSSL_cleanse(new_csrf, sizeof(new_csrf));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1142
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1143 if (!safe_username || !safe_role || !safe_csrf)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1144 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1145 OPENSSL_cleanse(new_token, sizeof(new_token));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1146 return auth_error(p_arena, "500", "internal_error", "Encode error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1147 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1148
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1149 char body_buf[512];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1150 snprintf(body_buf, sizeof(body_buf),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1151 "{\"kind\":\"user\",\"username\":\"%s\",\"role\":\"%s\","
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1152 "\"mustChangePassword\":%s,\"csrfToken\":\"%s\","
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1153 "\"quota\":null}",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1154 safe_username, safe_role,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1155 auth_record.user.must_change_password ? "true" : "false",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1156 safe_csrf);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1157
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1158 char *body_copy = Dowa_Arena_Allocate(p_arena, strlen(body_buf) + 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1159 if (!body_copy)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1160 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1161 OPENSSL_cleanse(new_token, sizeof(new_token));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1162 return auth_error(p_arena, "500", "internal_error", "OOM");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1163 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1164 strcpy(body_copy, body_buf);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1165
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1166 /* Session cookie */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1167 char session_cookie[SESSION_COOKIE_MAX];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1168 auth_build_cookie_directive(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1169 AUTH_API_SESSION_COOKIE_NAME, new_token, 0,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1170 TRUE, session_cookie, sizeof(session_cookie));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1171 OPENSSL_cleanse(new_token, sizeof(new_token));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1172
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1173 char *session_cookie_copy =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1174 Dowa_Arena_Allocate(p_arena, strlen(session_cookie) + 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1175 if (session_cookie_copy) strcpy(session_cookie_copy, session_cookie);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1176 OPENSSL_cleanse(session_cookie, sizeof(session_cookie));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1177
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1178 /* Clear guest cookie */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1179 char clear_guest[256];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1180 auth_build_cookie_directive(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1181 AUTH_API_GUEST_COOKIE_NAME, "", -1,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1182 TRUE, clear_guest, sizeof(clear_guest));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1183
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1184 char *clear_guest_copy =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1185 Dowa_Arena_Allocate(p_arena, strlen(clear_guest) + 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1186 if (clear_guest_copy) strcpy(clear_guest_copy, clear_guest);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1187
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1188 return auth_json_response_with_cookies(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1189 p_arena, "200", body_copy,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1190 session_cookie_copy, clear_guest_copy);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1191 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1192
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1193 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1194 /* Route: POST /api/auth/logout */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1195 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1196
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1197 static Seobeo_Request_Entry *auth_logout_handler(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1198 Seobeo_Request_Entry *p_req,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1199 Dowa_Arena *p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1200 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1201 if (!g_auth_store)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1202 return auth_error(p_arena, "503", "service_unavailable",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1203 "Auth not initialised");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1204
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1205 if (!auth_same_origin(p_req))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1206 return auth_error(p_arena, "403", "forbidden", "Origin mismatch");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1207
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1208 /* --- Resolve current principal for CSRF binding --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1209 Auth_Principal principal;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1210 char ignored_cookie[GUEST_COOKIE_MAX] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1211 if (!Auth_API_Resolve_Principal(p_req, &principal, p_arena,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1212 ignored_cookie, sizeof(ignored_cookie)))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1213 return auth_error(p_arena, "500", "internal_error", "Session error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1214
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1215 /* --- CSRF check --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1216 const char *body_str = auth_req_value(p_req, "Body");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1217 char csrf_provided[AUTH_CRYPTO_TOKEN_SIZE] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1218 if (body_str && strlen(body_str) <= BODY_MAX_BYTES)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1219 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1220 Dowa_JSON_Value jv =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1221 Dowa_JSON_Parse(body_str, (int32)strlen(body_str), p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1222 if (jv.type == DOWA_JSON_OBJECT)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1223 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1224 char *t = Dowa_JSON_Get_String((Dowa_JSON_Entry *)jv.object_val,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1225 "csrfToken");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1226 if (t)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1227 strncpy(csrf_provided, t,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1228 sizeof(csrf_provided) - 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1229 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1230 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1231
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1232 /* Also accept CSRF from X-CSRF-Token header */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1233 if (csrf_provided[0] == '\0')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1234 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1235 const char *hdr = auth_req_value(p_req, "X-CSRF-Token");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1236 if (hdr)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1237 strncpy(csrf_provided, hdr, sizeof(csrf_provided) - 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1238 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1239
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1240 if (!auth_verify_csrf(csrf_provided, principal._binding))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1241 return auth_error(p_arena, "403", "csrf_invalid", "CSRF token invalid");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1242
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1243 /* --- Revoke session if authenticated --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1244 const char *cookie_hdr = auth_req_value(p_req, "Cookie");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1245 char session_token[COOKIE_VALUE_MAX] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1246 if (cookie_hdr &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1247 auth_parse_cookie(cookie_hdr, AUTH_API_SESSION_COOKIE_NAME,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1248 session_token, sizeof(session_token)) &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1249 session_token[0] != '\0')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1250 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1251 char token_digest[AUTH_CRYPTO_TOKEN_DIGEST_SIZE] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1252 Auth_Crypto_Result digest_result =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1253 Auth_Crypto_Token_Digest(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1254 session_token, token_digest, sizeof(token_digest));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1255 if (digest_result == AUTH_CRYPTO_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1256 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1257 Auth_Store_Result revoke_result =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1258 Auth_Store_Revoke_Session(g_auth_store, token_digest);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1259 OPENSSL_cleanse(token_digest, sizeof(token_digest));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1260 if (revoke_result == AUTH_STORE_ERROR)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1261 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1262 OPENSSL_cleanse(session_token, sizeof(session_token));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1263 return auth_error(p_arena, "500", "internal_error", "Logout failed");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1264 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1265 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1266 else
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1267 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1268 OPENSSL_cleanse(token_digest, sizeof(token_digest));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1269 OPENSSL_cleanse(session_token, sizeof(session_token));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1270 return auth_error(p_arena, "500", "internal_error", "Logout failed");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1271 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1272 OPENSSL_cleanse(session_token, sizeof(session_token));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1273 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1274
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1275 /* --- Create fresh guest identity --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1276 char peer_ip[AUTH_CRYPTO_IP_MAX_BYTES] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1277 boolean have_ip = auth_peer_ip(p_req, peer_ip, sizeof(peer_ip));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1278
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1279 char ip_binding[AUTH_CRYPTO_IP_BINDING_DIGEST_SIZE] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1280 if (have_ip &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1281 Auth_Crypto_IP_Binding_Digest(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1282 g_cookie_secret, g_cookie_secret_length,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1283 peer_ip, ip_binding, sizeof(ip_binding)) != AUTH_CRYPTO_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1284 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1285 OPENSSL_cleanse(peer_ip, sizeof(peer_ip));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1286 return auth_error(p_arena, "500", "internal_error", "Binding error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1287 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1288 OPENSSL_cleanse(peer_ip, sizeof(peer_ip));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1289
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1290 char guest_uuid[AUTH_CRYPTO_GUEST_UUID_SIZE] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1291 if (!auth_uuid4(guest_uuid, sizeof(guest_uuid)))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1292 return auth_error(p_arena, "500", "internal_error", "UUID error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1293
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1294 int64 now = auth_now();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1295 int64 guest_expires = now + g_guest_ttl;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1296 Auth_Guest_Identity_Record new_identity;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1297 Auth_Store_Upsert_Guest_Identity(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1298 g_auth_store, guest_uuid, ip_binding, guest_expires, &new_identity);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1299
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1300 char new_csrf[AUTH_CRYPTO_TOKEN_SIZE] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1301 if (!auth_derive_csrf(guest_uuid, new_csrf, sizeof(new_csrf)))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1302 return auth_error(p_arena, "500", "internal_error", "CSRF error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1303
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1304 char signed_cookie[AUTH_CRYPTO_GUEST_COOKIE_SIZE] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1305 char new_guest_cookie[GUEST_COOKIE_MAX] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1306 if (have_ip &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1307 Auth_Crypto_Guest_Cookie_Create(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1308 g_cookie_secret, g_cookie_secret_length,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1309 guest_uuid, (uint64)guest_expires, ip_binding,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1310 signed_cookie, sizeof(signed_cookie)) == AUTH_CRYPTO_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1311 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1312 auth_build_cookie_directive(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1313 AUTH_API_GUEST_COOKIE_NAME, signed_cookie,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1314 (int32)g_guest_ttl, TRUE,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1315 new_guest_cookie, sizeof(new_guest_cookie));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1316 OPENSSL_cleanse(signed_cookie, sizeof(signed_cookie));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1317 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1318
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1319 /* --- Build response --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1320 char *safe_csrf = Dowa_JSON_Escape_String(new_csrf, 0, p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1321 OPENSSL_cleanse(new_csrf, sizeof(new_csrf));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1322 if (!safe_csrf)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1323 return auth_error(p_arena, "500", "internal_error", "Encode error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1324
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1325 char body_buf[256];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1326 snprintf(body_buf, sizeof(body_buf),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1327 "{\"kind\":\"guest\",\"csrfToken\":\"%s\",\"quota\":null}",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1328 safe_csrf);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1329
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1330 char *body_copy = Dowa_Arena_Allocate(p_arena, strlen(body_buf) + 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1331 if (!body_copy)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1332 return auth_error(p_arena, "500", "internal_error", "OOM");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1333 strcpy(body_copy, body_buf);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1334
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1335 /* Clear session cookie */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1336 char clear_session[256];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1337 auth_build_cookie_directive(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1338 AUTH_API_SESSION_COOKIE_NAME, "", -1,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1339 TRUE, clear_session, sizeof(clear_session));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1340
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1341 char *clear_session_copy =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1342 Dowa_Arena_Allocate(p_arena, strlen(clear_session) + 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1343 if (!clear_session_copy)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1344 return auth_error(p_arena, "500", "internal_error", "OOM");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1345 strcpy(clear_session_copy, clear_session);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1346
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1347 char *new_guest_copy = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1348 if (new_guest_cookie[0] != '\0')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1349 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1350 new_guest_copy =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1351 Dowa_Arena_Allocate(p_arena, strlen(new_guest_cookie) + 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1352 if (!new_guest_copy)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1353 return auth_error(p_arena, "500", "internal_error", "OOM");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1354 strcpy(new_guest_copy, new_guest_cookie);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1355 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1356
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1357 return auth_json_response_with_cookies(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1358 p_arena, "200", body_copy,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1359 clear_session_copy,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1360 new_guest_copy);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1361 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1362
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1363 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1364 /* Route: POST /api/auth/password */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1365 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1366
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1367 static Seobeo_Request_Entry *auth_password_handler(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1368 Seobeo_Request_Entry *p_req,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1369 Dowa_Arena *p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1370 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1371 if (!g_auth_store)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1372 return auth_error(p_arena, "503", "service_unavailable",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1373 "Auth not initialised");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1374
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1375 if (!auth_same_origin(p_req))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1376 return auth_error(p_arena, "403", "forbidden", "Origin mismatch");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1377
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1378 /* --- Resolve principal — must be authenticated user --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1379 Auth_Principal principal;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1380 char ignored_cookie[GUEST_COOKIE_MAX] = {0};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1381 if (!Auth_API_Resolve_Principal(p_req, &principal, p_arena,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1382 ignored_cookie, sizeof(ignored_cookie)))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1383 return auth_error(p_arena, "500", "internal_error", "Session error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1384
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1385 if (principal.kind != AUTH_PRINCIPAL_USER)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1386 return auth_error(p_arena, "401", "unauthenticated",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1387 "Authentication required");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1388
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1389 /* --- Parse body --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1390 const char *body_str = auth_req_value(p_req, "Body");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1391 if (!body_str)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1392 return auth_error(p_arena, "400", "bad_request", "Invalid body");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1393
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1394 size_t body_len = strlen(body_str);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1395 if (body_len > BODY_MAX_BYTES)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1396 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1397 OPENSSL_cleanse((char *)body_str, body_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1398 return auth_error(p_arena, "400", "bad_request", "Invalid body");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1399 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1400 Dowa_JSON_Value jv =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1401 Dowa_JSON_Parse(body_str, (int32)body_len, p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1402 OPENSSL_cleanse((char *)body_str, body_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1403 if (jv.type != DOWA_JSON_OBJECT)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1404 return auth_error(p_arena, "400", "bad_request", "Expected JSON object");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1405
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1406 Dowa_JSON_Entry *obj = (Dowa_JSON_Entry *)jv.object_val;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1407 char *csrf_provided = Dowa_JSON_Get_String(obj, "csrfToken");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1408 char current_pw_buf[AUTH_CRYPTO_PASSWORD_MAX_BYTES + 1];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1409 char new_pw_buf[AUTH_CRYPTO_PASSWORD_MAX_BYTES + 1];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1410 memset(current_pw_buf, 0, sizeof(current_pw_buf));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1411 memset(new_pw_buf, 0, sizeof(new_pw_buf));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1412 boolean have_current = auth_extract_secret_field(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1413 obj, "currentPassword", current_pw_buf,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1414 AUTH_CRYPTO_PASSWORD_MAX_BYTES);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1415 boolean have_new = auth_extract_secret_field(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1416 obj, "newPassword", new_pw_buf, AUTH_CRYPTO_PASSWORD_MAX_BYTES);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1417 char *current_pw_raw = current_pw_buf;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1418 char *new_pw_raw = new_pw_buf;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1419
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1420 /* Also accept CSRF from header */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1421 if (!csrf_provided || csrf_provided[0] == '\0')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1422 csrf_provided = (char *)auth_req_value(p_req, "X-CSRF-Token");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1423
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1424 if (!have_current || !have_new || !csrf_provided)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1425 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1426 OPENSSL_cleanse(current_pw_buf, sizeof(current_pw_buf));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1427 OPENSSL_cleanse(new_pw_buf, sizeof(new_pw_buf));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1428 return auth_error(p_arena, "400", "bad_request", "Missing fields");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1429 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1430
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1431 /* --- CSRF check --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1432 if (!auth_verify_csrf(csrf_provided, principal._binding))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1433 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1434 OPENSSL_cleanse(current_pw_buf, sizeof(current_pw_buf));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1435 OPENSSL_cleanse(new_pw_buf, sizeof(new_pw_buf));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1436 return auth_error(p_arena, "403", "csrf_invalid", "CSRF token invalid");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1437 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1438
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1439 /* --- Password policy --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1440 size_t new_pw_len = strlen(new_pw_raw);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1441 size_t cur_pw_len = strlen(current_pw_raw);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1442 if (new_pw_len < 12 || new_pw_len > AUTH_CRYPTO_PASSWORD_MAX_BYTES ||
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1443 cur_pw_len < 1 || cur_pw_len > AUTH_CRYPTO_PASSWORD_MAX_BYTES)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1444 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1445 OPENSSL_cleanse(current_pw_raw, cur_pw_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1446 OPENSSL_cleanse(new_pw_raw, new_pw_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1447 return auth_error(p_arena, "400", "password_policy",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1448 "New password must be at least 12 characters");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1449 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1450
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1451 /* --- Fetch user with password hash --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1452 char norm_username[AUTH_STORE_USERNAME_MAX + 1];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1453 if (!Auth_Store_Normalize_Username(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1454 principal.username, norm_username, sizeof(norm_username)))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1455 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1456 OPENSSL_cleanse(current_pw_raw, cur_pw_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1457 OPENSSL_cleanse(new_pw_raw, new_pw_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1458 return auth_error(p_arena, "500", "internal_error", "Username error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1459 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1460
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1461 Auth_User_Auth_Record auth_record;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1462 memset(&auth_record, 0, sizeof(auth_record));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1463 if (Auth_Store_Find_User_By_Username(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1464 g_auth_store, norm_username, &auth_record) != AUTH_STORE_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1465 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1466 OPENSSL_cleanse(current_pw_raw, cur_pw_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1467 OPENSSL_cleanse(new_pw_raw, new_pw_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1468 OPENSSL_cleanse(auth_record.password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1469 sizeof(auth_record.password_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1470 return auth_error(p_arena, "401", "invalid_credentials",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1471 "Invalid credentials");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1472 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1473
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1474 /* --- Verify current password --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1475 Auth_Crypto_Result verify =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1476 Auth_Crypto_Password_Verify(current_pw_raw, auth_record.password_hash);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1477 OPENSSL_cleanse(current_pw_raw, cur_pw_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1478
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1479 if (verify != AUTH_CRYPTO_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1480 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1481 OPENSSL_cleanse(auth_record.password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1482 sizeof(auth_record.password_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1483 OPENSSL_cleanse(new_pw_raw, new_pw_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1484 return auth_error(p_arena, "401", "invalid_credentials",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1485 "Invalid credentials");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1486 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1487
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1488 /* --- Hash new password --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1489 char new_encoded_hash[AUTH_CRYPTO_PASSWORD_HASH_ENCODED_SIZE];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1490 Auth_Crypto_Result hash_result = Auth_Crypto_Password_Hash(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1491 new_pw_raw, new_encoded_hash, sizeof(new_encoded_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1492 OPENSSL_cleanse(new_pw_raw, new_pw_len);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1493
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1494 if (hash_result != AUTH_CRYPTO_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1495 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1496 OPENSSL_cleanse(auth_record.password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1497 sizeof(auth_record.password_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1498 OPENSSL_cleanse(new_encoded_hash, sizeof(new_encoded_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1499 return auth_error(p_arena, "500", "internal_error", "Hash error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1500 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1501
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1502 /* Generate the replacement session before entering the transaction. */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1503 char new_token[AUTH_CRYPTO_TOKEN_SIZE];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1504 if (Auth_Crypto_Token_Generate(new_token, sizeof(new_token)) !=
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1505 AUTH_CRYPTO_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1506 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1507 OPENSSL_cleanse(auth_record.password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1508 sizeof(auth_record.password_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1509 OPENSSL_cleanse(new_encoded_hash, sizeof(new_encoded_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1510 return auth_error(p_arena, "500", "internal_error", "Token error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1511 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1512
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1513 char new_token_digest[AUTH_CRYPTO_TOKEN_DIGEST_SIZE];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1514 if (Auth_Crypto_Token_Digest(new_token, new_token_digest,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1515 sizeof(new_token_digest)) != AUTH_CRYPTO_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1516 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1517 OPENSSL_cleanse(auth_record.password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1518 sizeof(auth_record.password_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1519 OPENSSL_cleanse(new_encoded_hash, sizeof(new_encoded_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1520 OPENSSL_cleanse(new_token, sizeof(new_token));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1521 return auth_error(p_arena, "500", "internal_error", "Digest error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1522 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1523
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1524 char new_csrf[AUTH_CRYPTO_TOKEN_SIZE];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1525 if (!auth_derive_csrf(new_token_digest, new_csrf, sizeof(new_csrf)))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1526 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1527 OPENSSL_cleanse(auth_record.password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1528 sizeof(auth_record.password_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1529 OPENSSL_cleanse(new_encoded_hash, sizeof(new_encoded_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1530 OPENSSL_cleanse(new_token, sizeof(new_token));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1531 OPENSSL_cleanse(new_token_digest, sizeof(new_token_digest));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1532 return auth_error(p_arena, "500", "internal_error", "CSRF error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1533 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1534
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1535 char new_csrf_digest[AUTH_CRYPTO_TOKEN_DIGEST_SIZE];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1536 if (Auth_Crypto_Token_Digest(new_csrf, new_csrf_digest,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1537 sizeof(new_csrf_digest)) != AUTH_CRYPTO_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1538 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1539 OPENSSL_cleanse(auth_record.password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1540 sizeof(auth_record.password_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1541 OPENSSL_cleanse(new_encoded_hash, sizeof(new_encoded_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1542 OPENSSL_cleanse(new_token, sizeof(new_token));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1543 OPENSSL_cleanse(new_token_digest, sizeof(new_token_digest));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1544 OPENSSL_cleanse(new_csrf, sizeof(new_csrf));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1545 return auth_error(p_arena, "500", "internal_error", "CSRF digest error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1546 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1547
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1548 int64 now = auth_now();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1549 Auth_Session_Record new_session;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1550 Auth_Store_Result password_result = Auth_Store_Self_Change_Password(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1551 g_auth_store,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1552 principal.user_id,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1553 auth_record.password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1554 new_encoded_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1555 new_token_digest,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1556 new_csrf_digest,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1557 g_session_idle_ttl,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1558 g_session_abs_ttl,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1559 now,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1560 &new_session);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1561
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1562 OPENSSL_cleanse(auth_record.password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1563 sizeof(auth_record.password_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1564 OPENSSL_cleanse(new_encoded_hash, sizeof(new_encoded_hash));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1565 OPENSSL_cleanse(new_csrf_digest, sizeof(new_csrf_digest));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1566 OPENSSL_cleanse(new_token_digest, sizeof(new_token_digest));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1567
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1568 if (password_result != AUTH_STORE_OK)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1569 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1570 OPENSSL_cleanse(new_token, sizeof(new_token));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1571 OPENSSL_cleanse(new_csrf, sizeof(new_csrf));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1572 return auth_error(p_arena, "500", "internal_error",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1573 "Password update failed");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1574 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1575
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1576 /* --- Build response --- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1577 char *safe_username =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1578 Dowa_JSON_Escape_String(principal.username, 0, p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1579 char *safe_role =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1580 Dowa_JSON_Escape_String(principal.role, 0, p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1581 char *safe_csrf =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1582 Dowa_JSON_Escape_String(new_csrf, 0, p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1583 OPENSSL_cleanse(new_csrf, sizeof(new_csrf));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1584
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1585 if (!safe_username || !safe_role || !safe_csrf)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1586 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1587 OPENSSL_cleanse(new_token, sizeof(new_token));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1588 return auth_error(p_arena, "500", "internal_error", "Encode error");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1589 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1590
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1591 char body_buf[512];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1592 snprintf(body_buf, sizeof(body_buf),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1593 "{\"kind\":\"user\",\"username\":\"%s\",\"role\":\"%s\","
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1594 "\"mustChangePassword\":false,\"csrfToken\":\"%s\","
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1595 "\"quota\":null}",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1596 safe_username, safe_role, safe_csrf);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1597
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1598 char *body_copy = Dowa_Arena_Allocate(p_arena, strlen(body_buf) + 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1599 if (!body_copy)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1600 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1601 OPENSSL_cleanse(new_token, sizeof(new_token));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1602 return auth_error(p_arena, "500", "internal_error", "OOM");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1603 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1604 strcpy(body_copy, body_buf);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1605
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1606 /* Updated session cookie */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1607 char session_cookie[SESSION_COOKIE_MAX];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1608 auth_build_cookie_directive(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1609 AUTH_API_SESSION_COOKIE_NAME, new_token, 0,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1610 TRUE, session_cookie, sizeof(session_cookie));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1611 OPENSSL_cleanse(new_token, sizeof(new_token));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1612
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1613 char *session_cookie_copy =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1614 Dowa_Arena_Allocate(p_arena, strlen(session_cookie) + 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1615 if (session_cookie_copy) strcpy(session_cookie_copy, session_cookie);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1616 OPENSSL_cleanse(session_cookie, sizeof(session_cookie));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1617
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1618 return auth_json_response_with_cookies(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1619 p_arena, "200", body_copy,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1620 session_cookie_copy, NULL);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1621 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1622
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1623 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1624 /* Route: GET /account/password */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1625 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1626
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1627 static Seobeo_Request_Entry *auth_password_page_handler(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1628 Seobeo_Request_Entry *p_req,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1629 Dowa_Arena *p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1630 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1631 (void)p_req;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1632 char *body = Dowa_Arena_Allocate(p_arena, 128 * 1024);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1633 if (!body || !Mjj_Template_Render_File(body, 128 * 1024, "/account/password.html", p_arena))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1634 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1635 Seobeo_Request_Entry *resp = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1636 Dowa_HashMap_Push_Arena(resp, "status", "500", p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1637 Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain; charset=utf-8", p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1638 Dowa_HashMap_Push_Arena(resp, "cache-control", "no-store", p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1639 Dowa_HashMap_Push_Arena(resp, "body", "Internal Server Error", p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1640 return resp;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1641 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1642
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1643 Seobeo_Request_Entry *resp = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1644 Dowa_HashMap_Push_Arena(resp, "body", body, p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1645 Dowa_HashMap_Push_Arena(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1646 resp, "content-type", "text/html; charset=utf-8", p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1647 Dowa_HashMap_Push_Arena(resp, "cache-control", "no-store", p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1648 Dowa_HashMap_Push_Arena(resp, "pragma", "no-cache", p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1649 Dowa_HashMap_Push_Arena(resp, "x-content-type-options", "nosniff", p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1650 Dowa_HashMap_Push_Arena(resp, "referrer-policy", "no-referrer", p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1651 Dowa_HashMap_Push_Arena(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1652 resp, "content-security-policy", "frame-ancestors 'none'", p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1653 return resp;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1654 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1655
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1656 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1657 /* Public API */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1658 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1659
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1660 boolean Auth_API_Is_Forced_Password_Change_Only(const char *http_path)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1661 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1662 if (!http_path) return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1663 return strcmp(http_path, AUTH_API_PATH_SESSION) == 0 ||
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1664 strcmp(http_path, AUTH_API_PATH_LOGIN) == 0 ||
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1665 strcmp(http_path, AUTH_API_PATH_LOGOUT) == 0 ||
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1666 strcmp(http_path, AUTH_API_PATH_PASSWORD) == 0 ||
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1667 strcmp(http_path, AUTH_API_PATH_PASSWORD_PAGE) == 0;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1668 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1669
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1670 void Auth_API_Register_Guest_Transfer_Hook(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1671 Auth_Guest_Transfer_Hook hook,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1672 void *context)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1673 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1674 g_transfer_hook = hook;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1675 g_transfer_hook_ctx = context;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1676 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1677
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1678 void Auth_API_Register_Guest_Quota_Cb(Auth_API_Guest_Quota_Cb cb)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1679 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1680 g_guest_quota_cb = cb;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1681 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1682
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1683 boolean Auth_API_Init(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1684 const char *database_path,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1685 const uint8 *cookie_secret,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1686 size_t cookie_secret_length,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1687 const char *bootstrap_username,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1688 const char *bootstrap_password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1689 const char *trusted_proxy_ip,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1690 int64 session_idle_ttl_secs,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1691 int64 session_absolute_ttl_secs,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1692 int64 guest_ttl_secs,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1693 boolean dev_insecure_cookie)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1694 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1695 /* Fail closed: cookie secret required */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1696 if (!cookie_secret ||
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1697 cookie_secret_length < AUTH_CRYPTO_COOKIE_SECRET_MIN_BYTES ||
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1698 cookie_secret_length > AUTH_CRYPTO_COOKIE_SECRET_MAX_BYTES)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1699 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1700 Seobeo_Log(SEOBEO_ERROR,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1701 "[AUTH] Init failed: cookie secret missing or invalid length\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1702 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1703 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1704
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1705 if (!database_path || database_path[0] == '\0')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1706 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1707 Seobeo_Log(SEOBEO_ERROR,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1708 "[AUTH] Init failed: database path required\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1709 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1710 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1711
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1712 g_auth_store = Auth_Store_Create(database_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1713 if (!g_auth_store)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1714 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1715 Seobeo_Log(SEOBEO_ERROR, "[AUTH] Failed to open auth store\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1716 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1717 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1718
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1719 memcpy(g_cookie_secret, cookie_secret, cookie_secret_length);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1720 g_cookie_secret_length = cookie_secret_length;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1721
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1722 if (trusted_proxy_ip && trusted_proxy_ip[0] != '\0')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1723 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1724 /* Canonicalize via inet_pton/inet_ntop; reject invalid addresses. */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1725 struct in_addr addr4;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1726 struct in6_addr addr6;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1727 char canonical[AUTH_CRYPTO_IP_MAX_BYTES];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1728 canonical[0] = '\0';
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1729 if (inet_pton(AF_INET, trusted_proxy_ip, &addr4) == 1)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1730 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1731 if (!inet_ntop(AF_INET, &addr4, canonical, sizeof(canonical)))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1732 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1733 Seobeo_Log(SEOBEO_ERROR,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1734 "[AUTH] Init failed: trusted proxy IPv4 canonicalization\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1735 Auth_Store_Destroy(g_auth_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1736 g_auth_store = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1737 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1738 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1739 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1740 else if (inet_pton(AF_INET6, trusted_proxy_ip, &addr6) == 1)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1741 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1742 if (!inet_ntop(AF_INET6, &addr6, canonical, sizeof(canonical)))
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1743 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1744 Seobeo_Log(SEOBEO_ERROR,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1745 "[AUTH] Init failed: trusted proxy IPv6 canonicalization\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1746 Auth_Store_Destroy(g_auth_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1747 g_auth_store = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1748 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1749 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1750 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1751 else
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1752 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1753 Seobeo_Log(SEOBEO_ERROR,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1754 "[AUTH] Init failed: trusted proxy is not a valid IP address\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1755 Auth_Store_Destroy(g_auth_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1756 g_auth_store = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1757 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1758 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1759 strncpy(g_trusted_proxy_ip, canonical, sizeof(g_trusted_proxy_ip) - 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1760 g_trusted_proxy_ip[sizeof(g_trusted_proxy_ip) - 1] = '\0';
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1761 g_has_trusted_proxy = TRUE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1762 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1763
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1764 if (session_idle_ttl_secs > 0)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1765 g_session_idle_ttl = session_idle_ttl_secs;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1766 if (session_absolute_ttl_secs > 0)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1767 g_session_abs_ttl = session_absolute_ttl_secs;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1768 if (guest_ttl_secs > 0)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1769 g_guest_ttl = guest_ttl_secs;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1770
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1771 g_dev_insecure_cookie = dev_insecure_cookie;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1772
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1773 /* Bootstrap admin — fail closed on any store error. */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1774 if (bootstrap_username && bootstrap_username[0] != '\0' &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1775 bootstrap_password_hash && bootstrap_password_hash[0] != '\0')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1776 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1777 Auth_Store_Bootstrap_Result bootstrap_result;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1778 char bootstrap_id[37];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1779 Auth_Store_Result r = Auth_Store_Bootstrap_Admin(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1780 g_auth_store,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1781 bootstrap_username,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1782 bootstrap_password_hash,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1783 &bootstrap_result,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1784 bootstrap_id);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1785
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1786 if (r == AUTH_STORE_OK &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1787 bootstrap_result == AUTH_STORE_BOOTSTRAP_CREATED)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1788 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1789 Seobeo_Log(SEOBEO_INFO, "[AUTH] Bootstrap admin created\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1790 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1791 else if (r == AUTH_STORE_OK &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1792 bootstrap_result == AUTH_STORE_BOOTSTRAP_ALREADY_PRESENT)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1793 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1794 Seobeo_Log(SEOBEO_INFO, "[AUTH] Bootstrap admin already present\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1795 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1796 else
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1797 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1798 Seobeo_Log(SEOBEO_ERROR,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1799 "[AUTH] Bootstrap admin failed: store error %d — refusing to start\n", r);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1800 OPENSSL_cleanse(g_cookie_secret, sizeof(g_cookie_secret));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1801 g_cookie_secret_length = 0;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1802 g_has_trusted_proxy = FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1803 Auth_Store_Destroy(g_auth_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1804 g_auth_store = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1805 return FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1806 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1807 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1808
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1809 Seobeo_Log(SEOBEO_INFO, "[AUTH] Initialised (dev_insecure=%s)\n",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1810 dev_insecure_cookie ? "yes" : "no");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1811 return TRUE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1812 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1813
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1814 void Auth_API_Destroy(void)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1815 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1816 if (g_auth_store)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1817 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1818 Auth_Store_Destroy(g_auth_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1819 g_auth_store = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1820 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1821 OPENSSL_cleanse(g_cookie_secret, sizeof(g_cookie_secret));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1822 g_cookie_secret_length = 0;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1823 g_has_trusted_proxy = FALSE;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1824 g_transfer_hook = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1825 g_transfer_hook_ctx = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1826 g_guest_quota_cb = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1827 #ifdef AUTH_API_TEST_HOOKS
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1828 g_login_pre_create_hook = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1829 g_login_pre_create_context = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1830 #endif
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1831 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1832
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1833 void Auth_API_Register_Routes(void)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1834 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1835 Seobeo_Router_Register("GET", "/api/auth/session", auth_session_handler);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1836 Seobeo_Router_Register("POST", "/api/auth/login", auth_login_handler);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1837 Seobeo_Router_Register("POST", "/api/auth/logout", auth_logout_handler);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1838 Seobeo_Router_Register("POST", "/api/auth/password", auth_password_handler);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1839 Seobeo_Router_Register("GET", "/account/password", auth_password_page_handler);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1840 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1841
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1842 Auth_Store *Auth_API_Get_Store(void)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1843 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1844 return g_auth_store;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1845 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1846
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1847 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1848 /* Test hooks (compiled in only for test builds) */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1849 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1850
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1851 #ifdef AUTH_API_TEST_HOOKS
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1852 void Auth_API_Test_Set_Login_Pre_Create_Hook(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1853 Auth_API_Test_Login_Pre_Create_Hook hook,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1854 void *p_context)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1855 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1856 g_login_pre_create_hook = hook;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1857 g_login_pre_create_context = p_context;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1858 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1859
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1860 Seobeo_Request_Entry *Auth_API_Test_Session_Handler(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1861 Seobeo_Request_Entry *p_req, Dowa_Arena *p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1862 { return auth_session_handler(p_req, p_arena); }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1863
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1864 Seobeo_Request_Entry *Auth_API_Test_Login_Handler(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1865 Seobeo_Request_Entry *p_req, Dowa_Arena *p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1866 { return auth_login_handler(p_req, p_arena); }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1867
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1868 Seobeo_Request_Entry *Auth_API_Test_Logout_Handler(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1869 Seobeo_Request_Entry *p_req, Dowa_Arena *p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1870 { return auth_logout_handler(p_req, p_arena); }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1871
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1872 Seobeo_Request_Entry *Auth_API_Test_Password_Handler(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1873 Seobeo_Request_Entry *p_req, Dowa_Arena *p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1874 { return auth_password_handler(p_req, p_arena); }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1875 #endif /* AUTH_API_TEST_HOOKS */