1*1c60b9acSAndroid Build Coastguard Worker
2*1c60b9acSAndroid Build Coastguard Worker #include <libwebsockets.h>
3*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
4*1c60b9acSAndroid Build Coastguard Worker
5*1c60b9acSAndroid Build Coastguard Worker //#define LWS_COOKIE_DEBUG
6*1c60b9acSAndroid Build Coastguard Worker
7*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_COOKIE_DEBUG)
8*1c60b9acSAndroid Build Coastguard Worker #define lwsl_cookie lwsl_notice
9*1c60b9acSAndroid Build Coastguard Worker #else
10*1c60b9acSAndroid Build Coastguard Worker #define lwsl_cookie lwsl_debug
11*1c60b9acSAndroid Build Coastguard Worker #endif
12*1c60b9acSAndroid Build Coastguard Worker
13*1c60b9acSAndroid Build Coastguard Worker #define LWS_COOKIE_MAX_CACHE_NAME_LEN 128
14*1c60b9acSAndroid Build Coastguard Worker
15*1c60b9acSAndroid Build Coastguard Worker #define lws_tolower(_c) (((_c) >= 'A' && (_c) <= 'Z') ? \
16*1c60b9acSAndroid Build Coastguard Worker (char)((_c) + 'a' - 'A') : \
17*1c60b9acSAndroid Build Coastguard Worker (char)(_c))
18*1c60b9acSAndroid Build Coastguard Worker
19*1c60b9acSAndroid Build Coastguard Worker #define LWS_COOKIE_NSC_FORMAT "%.*s\t"\
20*1c60b9acSAndroid Build Coastguard Worker "%s\t"\
21*1c60b9acSAndroid Build Coastguard Worker "%.*s\t"\
22*1c60b9acSAndroid Build Coastguard Worker "%s\t"\
23*1c60b9acSAndroid Build Coastguard Worker "%llu\t"\
24*1c60b9acSAndroid Build Coastguard Worker "%.*s\t"\
25*1c60b9acSAndroid Build Coastguard Worker "%.*s"
26*1c60b9acSAndroid Build Coastguard Worker
27*1c60b9acSAndroid Build Coastguard Worker static const char *const mon = "janfebmaraprnayjunjulaugsepoctnovdec";
28*1c60b9acSAndroid Build Coastguard Worker
29*1c60b9acSAndroid Build Coastguard Worker enum lws_cookie_nsc_f {
30*1c60b9acSAndroid Build Coastguard Worker LWSC_NSC_DOMAIN,
31*1c60b9acSAndroid Build Coastguard Worker LWSC_NSC_HOSTONLY,
32*1c60b9acSAndroid Build Coastguard Worker LWSC_NSC_PATH,
33*1c60b9acSAndroid Build Coastguard Worker LWSC_NSC_SECURE,
34*1c60b9acSAndroid Build Coastguard Worker LWSC_NSC_EXPIRES,
35*1c60b9acSAndroid Build Coastguard Worker LWSC_NSC_NAME,
36*1c60b9acSAndroid Build Coastguard Worker LWSC_NSC_VALUE,
37*1c60b9acSAndroid Build Coastguard Worker
38*1c60b9acSAndroid Build Coastguard Worker LWSC_NSC_COUNT,
39*1c60b9acSAndroid Build Coastguard Worker };
40*1c60b9acSAndroid Build Coastguard Worker
41*1c60b9acSAndroid Build Coastguard Worker enum lws_cookie_elements {
42*1c60b9acSAndroid Build Coastguard Worker CE_DOMAIN,
43*1c60b9acSAndroid Build Coastguard Worker CE_PATH,
44*1c60b9acSAndroid Build Coastguard Worker CE_EXPIRES,
45*1c60b9acSAndroid Build Coastguard Worker CE_MAXAGE,
46*1c60b9acSAndroid Build Coastguard Worker CE_NAME,
47*1c60b9acSAndroid Build Coastguard Worker CE_VALUE,
48*1c60b9acSAndroid Build Coastguard Worker
49*1c60b9acSAndroid Build Coastguard Worker CE_HOSTONLY, /* these are bool, NULL = 0, non-NULL = 1 */
50*1c60b9acSAndroid Build Coastguard Worker CE_SECURE,
51*1c60b9acSAndroid Build Coastguard Worker
52*1c60b9acSAndroid Build Coastguard Worker CE_COUNT
53*1c60b9acSAndroid Build Coastguard Worker };
54*1c60b9acSAndroid Build Coastguard Worker
55*1c60b9acSAndroid Build Coastguard Worker struct lws_cookie {
56*1c60b9acSAndroid Build Coastguard Worker const char *f[CE_COUNT];
57*1c60b9acSAndroid Build Coastguard Worker size_t l[CE_COUNT];
58*1c60b9acSAndroid Build Coastguard Worker
59*1c60b9acSAndroid Build Coastguard Worker unsigned int httponly:1;
60*1c60b9acSAndroid Build Coastguard Worker };
61*1c60b9acSAndroid Build Coastguard Worker
62*1c60b9acSAndroid Build Coastguard Worker static int
lws_cookie_parse_date(const char * d,size_t len,time_t * t)63*1c60b9acSAndroid Build Coastguard Worker lws_cookie_parse_date(const char *d, size_t len, time_t *t)
64*1c60b9acSAndroid Build Coastguard Worker {
65*1c60b9acSAndroid Build Coastguard Worker struct tm date;
66*1c60b9acSAndroid Build Coastguard Worker int offset = 0, i;
67*1c60b9acSAndroid Build Coastguard Worker
68*1c60b9acSAndroid Build Coastguard Worker memset(&date, 0, sizeof(date));
69*1c60b9acSAndroid Build Coastguard Worker
70*1c60b9acSAndroid Build Coastguard Worker while (len) {
71*1c60b9acSAndroid Build Coastguard Worker if (isalnum((int)*d)) {
72*1c60b9acSAndroid Build Coastguard Worker offset++;
73*1c60b9acSAndroid Build Coastguard Worker goto next;
74*1c60b9acSAndroid Build Coastguard Worker }
75*1c60b9acSAndroid Build Coastguard Worker switch (offset) {
76*1c60b9acSAndroid Build Coastguard Worker case 2:
77*1c60b9acSAndroid Build Coastguard Worker if (*d == ':' && len >= 6) {
78*1c60b9acSAndroid Build Coastguard Worker date.tm_hour = atoi(d - 2);
79*1c60b9acSAndroid Build Coastguard Worker if (date.tm_hour < 0 || date.tm_hour > 23)
80*1c60b9acSAndroid Build Coastguard Worker return -1;
81*1c60b9acSAndroid Build Coastguard Worker date.tm_min = atoi(d + 1);
82*1c60b9acSAndroid Build Coastguard Worker if (date.tm_min < 0 || date.tm_min > 60)
83*1c60b9acSAndroid Build Coastguard Worker return -1;
84*1c60b9acSAndroid Build Coastguard Worker date.tm_sec = atoi(d + 4);
85*1c60b9acSAndroid Build Coastguard Worker if (date.tm_sec < 0 || date.tm_sec > 61)
86*1c60b9acSAndroid Build Coastguard Worker /* leap second */
87*1c60b9acSAndroid Build Coastguard Worker return -1;
88*1c60b9acSAndroid Build Coastguard Worker
89*1c60b9acSAndroid Build Coastguard Worker d += 6;
90*1c60b9acSAndroid Build Coastguard Worker len -= 6;
91*1c60b9acSAndroid Build Coastguard Worker offset = 0;
92*1c60b9acSAndroid Build Coastguard Worker continue;
93*1c60b9acSAndroid Build Coastguard Worker }
94*1c60b9acSAndroid Build Coastguard Worker
95*1c60b9acSAndroid Build Coastguard Worker if (!date.tm_mday) {
96*1c60b9acSAndroid Build Coastguard Worker date.tm_mday = atoi(d - 2);
97*1c60b9acSAndroid Build Coastguard Worker if (date.tm_mday < 1 || date.tm_mday > 31)
98*1c60b9acSAndroid Build Coastguard Worker return -1;
99*1c60b9acSAndroid Build Coastguard Worker goto next2;
100*1c60b9acSAndroid Build Coastguard Worker }
101*1c60b9acSAndroid Build Coastguard Worker
102*1c60b9acSAndroid Build Coastguard Worker if (!date.tm_year) {
103*1c60b9acSAndroid Build Coastguard Worker date.tm_year = atoi(d - 2);
104*1c60b9acSAndroid Build Coastguard Worker if (date.tm_year < 0 || date.tm_year > 99)
105*1c60b9acSAndroid Build Coastguard Worker return -1;
106*1c60b9acSAndroid Build Coastguard Worker if (date.tm_year < 70)
107*1c60b9acSAndroid Build Coastguard Worker date.tm_year += 100;
108*1c60b9acSAndroid Build Coastguard Worker }
109*1c60b9acSAndroid Build Coastguard Worker goto next2;
110*1c60b9acSAndroid Build Coastguard Worker
111*1c60b9acSAndroid Build Coastguard Worker case 3:
112*1c60b9acSAndroid Build Coastguard Worker for (i = 0; i < 36; i += 3) {
113*1c60b9acSAndroid Build Coastguard Worker if (lws_tolower(*(d - 3)) == mon[i] &&
114*1c60b9acSAndroid Build Coastguard Worker lws_tolower(*(d - 2)) == mon[i + 1] &&
115*1c60b9acSAndroid Build Coastguard Worker lws_tolower(*(d - 1)) == mon[i + 2]) {
116*1c60b9acSAndroid Build Coastguard Worker date.tm_mon = i / 3;
117*1c60b9acSAndroid Build Coastguard Worker break;
118*1c60b9acSAndroid Build Coastguard Worker }
119*1c60b9acSAndroid Build Coastguard Worker }
120*1c60b9acSAndroid Build Coastguard Worker goto next2;
121*1c60b9acSAndroid Build Coastguard Worker
122*1c60b9acSAndroid Build Coastguard Worker case 4:
123*1c60b9acSAndroid Build Coastguard Worker if (!date.tm_year) {
124*1c60b9acSAndroid Build Coastguard Worker date.tm_year = atoi(d - 4);
125*1c60b9acSAndroid Build Coastguard Worker if (date.tm_year < 1601)
126*1c60b9acSAndroid Build Coastguard Worker return -1;
127*1c60b9acSAndroid Build Coastguard Worker date.tm_year -= 1900;
128*1c60b9acSAndroid Build Coastguard Worker }
129*1c60b9acSAndroid Build Coastguard Worker goto next2;
130*1c60b9acSAndroid Build Coastguard Worker
131*1c60b9acSAndroid Build Coastguard Worker default:
132*1c60b9acSAndroid Build Coastguard Worker goto next2;
133*1c60b9acSAndroid Build Coastguard Worker }
134*1c60b9acSAndroid Build Coastguard Worker
135*1c60b9acSAndroid Build Coastguard Worker next2:
136*1c60b9acSAndroid Build Coastguard Worker offset = 0;
137*1c60b9acSAndroid Build Coastguard Worker next:
138*1c60b9acSAndroid Build Coastguard Worker d++;
139*1c60b9acSAndroid Build Coastguard Worker len--;
140*1c60b9acSAndroid Build Coastguard Worker }
141*1c60b9acSAndroid Build Coastguard Worker
142*1c60b9acSAndroid Build Coastguard Worker *t = mktime(&date);
143*1c60b9acSAndroid Build Coastguard Worker
144*1c60b9acSAndroid Build Coastguard Worker if (*t < 0)
145*1c60b9acSAndroid Build Coastguard Worker return -1;
146*1c60b9acSAndroid Build Coastguard Worker
147*1c60b9acSAndroid Build Coastguard Worker return 0;
148*1c60b9acSAndroid Build Coastguard Worker }
149*1c60b9acSAndroid Build Coastguard Worker
150*1c60b9acSAndroid Build Coastguard Worker static void
lws_cookie_rm_sws(const char ** buf_p,size_t * len_p)151*1c60b9acSAndroid Build Coastguard Worker lws_cookie_rm_sws(const char **buf_p, size_t *len_p)
152*1c60b9acSAndroid Build Coastguard Worker {
153*1c60b9acSAndroid Build Coastguard Worker const char *buf;
154*1c60b9acSAndroid Build Coastguard Worker size_t len;
155*1c60b9acSAndroid Build Coastguard Worker
156*1c60b9acSAndroid Build Coastguard Worker if (!buf_p || !*buf_p || !len_p || !*len_p) {
157*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: false parameter\n", __func__);
158*1c60b9acSAndroid Build Coastguard Worker return;
159*1c60b9acSAndroid Build Coastguard Worker }
160*1c60b9acSAndroid Build Coastguard Worker
161*1c60b9acSAndroid Build Coastguard Worker buf = *buf_p;
162*1c60b9acSAndroid Build Coastguard Worker len = *len_p;
163*1c60b9acSAndroid Build Coastguard Worker while (buf[0] == ' ' && len > 0) {
164*1c60b9acSAndroid Build Coastguard Worker buf++;
165*1c60b9acSAndroid Build Coastguard Worker len--;
166*1c60b9acSAndroid Build Coastguard Worker }
167*1c60b9acSAndroid Build Coastguard Worker while (buf[len - 1] == ' ' && len > 0)
168*1c60b9acSAndroid Build Coastguard Worker len--;
169*1c60b9acSAndroid Build Coastguard Worker
170*1c60b9acSAndroid Build Coastguard Worker *buf_p = buf;
171*1c60b9acSAndroid Build Coastguard Worker *len_p = len;
172*1c60b9acSAndroid Build Coastguard Worker }
173*1c60b9acSAndroid Build Coastguard Worker
174*1c60b9acSAndroid Build Coastguard Worker static int
is_iprefix(const char * h,size_t hl,const char * n,size_t nl)175*1c60b9acSAndroid Build Coastguard Worker is_iprefix(const char *h, size_t hl, const char *n, size_t nl)
176*1c60b9acSAndroid Build Coastguard Worker {
177*1c60b9acSAndroid Build Coastguard Worker if (!h || !n || nl > hl)
178*1c60b9acSAndroid Build Coastguard Worker return 0;
179*1c60b9acSAndroid Build Coastguard Worker
180*1c60b9acSAndroid Build Coastguard Worker while (nl) {
181*1c60b9acSAndroid Build Coastguard Worker nl--;
182*1c60b9acSAndroid Build Coastguard Worker if (lws_tolower(h[nl]) != lws_tolower(n[nl]))
183*1c60b9acSAndroid Build Coastguard Worker return 0;
184*1c60b9acSAndroid Build Coastguard Worker }
185*1c60b9acSAndroid Build Coastguard Worker return 1;
186*1c60b9acSAndroid Build Coastguard Worker }
187*1c60b9acSAndroid Build Coastguard Worker
188*1c60b9acSAndroid Build Coastguard Worker static int
lws_cookie_compile_cache_name(char * buf,size_t buf_len,struct lws_cookie * c)189*1c60b9acSAndroid Build Coastguard Worker lws_cookie_compile_cache_name(char *buf, size_t buf_len, struct lws_cookie *c)
190*1c60b9acSAndroid Build Coastguard Worker {
191*1c60b9acSAndroid Build Coastguard Worker if (!buf || !c->f[CE_DOMAIN] || !c->f[CE_PATH] || !c->f[CE_NAME] ||
192*1c60b9acSAndroid Build Coastguard Worker c->l[CE_DOMAIN] + c->l[CE_PATH] + c->l[CE_NAME] + 6 > buf_len)
193*1c60b9acSAndroid Build Coastguard Worker return -1;
194*1c60b9acSAndroid Build Coastguard Worker
195*1c60b9acSAndroid Build Coastguard Worker memcpy(buf, c->f[CE_DOMAIN], c->l[CE_DOMAIN]);
196*1c60b9acSAndroid Build Coastguard Worker buf += c->l[CE_DOMAIN];
197*1c60b9acSAndroid Build Coastguard Worker *buf++ = '|';
198*1c60b9acSAndroid Build Coastguard Worker
199*1c60b9acSAndroid Build Coastguard Worker memcpy(buf, c->f[CE_PATH], c->l[CE_PATH]);
200*1c60b9acSAndroid Build Coastguard Worker buf += c->l[CE_PATH];
201*1c60b9acSAndroid Build Coastguard Worker *buf++ = '|';
202*1c60b9acSAndroid Build Coastguard Worker
203*1c60b9acSAndroid Build Coastguard Worker memcpy(buf, c->f[CE_NAME], c->l[CE_NAME]);
204*1c60b9acSAndroid Build Coastguard Worker buf += c->l[CE_NAME];
205*1c60b9acSAndroid Build Coastguard Worker *buf = '\0';
206*1c60b9acSAndroid Build Coastguard Worker
207*1c60b9acSAndroid Build Coastguard Worker return 0;
208*1c60b9acSAndroid Build Coastguard Worker }
209*1c60b9acSAndroid Build Coastguard Worker
210*1c60b9acSAndroid Build Coastguard Worker static int
lws_cookie_parse_nsc(struct lws_cookie * c,const char * b,size_t l)211*1c60b9acSAndroid Build Coastguard Worker lws_cookie_parse_nsc(struct lws_cookie *c, const char *b, size_t l)
212*1c60b9acSAndroid Build Coastguard Worker {
213*1c60b9acSAndroid Build Coastguard Worker enum lws_cookie_nsc_f state = LWSC_NSC_DOMAIN;
214*1c60b9acSAndroid Build Coastguard Worker size_t n = 0;
215*1c60b9acSAndroid Build Coastguard Worker
216*1c60b9acSAndroid Build Coastguard Worker if (!c || !b || l < 13)
217*1c60b9acSAndroid Build Coastguard Worker return -1;
218*1c60b9acSAndroid Build Coastguard Worker
219*1c60b9acSAndroid Build Coastguard Worker memset(c, 0, sizeof(*c));
220*1c60b9acSAndroid Build Coastguard Worker lwsl_cookie("%s: parsing (%.*s) \n", __func__, (int)l, b);
221*1c60b9acSAndroid Build Coastguard Worker
222*1c60b9acSAndroid Build Coastguard Worker while (l) {
223*1c60b9acSAndroid Build Coastguard Worker l--;
224*1c60b9acSAndroid Build Coastguard Worker if (b[n] != '\t' && l) {
225*1c60b9acSAndroid Build Coastguard Worker n++;
226*1c60b9acSAndroid Build Coastguard Worker continue;
227*1c60b9acSAndroid Build Coastguard Worker }
228*1c60b9acSAndroid Build Coastguard Worker switch (state) {
229*1c60b9acSAndroid Build Coastguard Worker case LWSC_NSC_DOMAIN:
230*1c60b9acSAndroid Build Coastguard Worker c->f[CE_DOMAIN] = b;
231*1c60b9acSAndroid Build Coastguard Worker c->l[CE_DOMAIN] = n;
232*1c60b9acSAndroid Build Coastguard Worker break;
233*1c60b9acSAndroid Build Coastguard Worker case LWSC_NSC_PATH:
234*1c60b9acSAndroid Build Coastguard Worker c->f[CE_PATH] = b;
235*1c60b9acSAndroid Build Coastguard Worker c->l[CE_PATH] = n;
236*1c60b9acSAndroid Build Coastguard Worker break;
237*1c60b9acSAndroid Build Coastguard Worker case LWSC_NSC_EXPIRES:
238*1c60b9acSAndroid Build Coastguard Worker c->f[CE_EXPIRES] = b;
239*1c60b9acSAndroid Build Coastguard Worker c->l[CE_EXPIRES] = n;
240*1c60b9acSAndroid Build Coastguard Worker break;
241*1c60b9acSAndroid Build Coastguard Worker case LWSC_NSC_NAME:
242*1c60b9acSAndroid Build Coastguard Worker c->f[CE_NAME] = b;
243*1c60b9acSAndroid Build Coastguard Worker c->l[CE_NAME] = n;
244*1c60b9acSAndroid Build Coastguard Worker break;
245*1c60b9acSAndroid Build Coastguard Worker
246*1c60b9acSAndroid Build Coastguard Worker case LWSC_NSC_HOSTONLY:
247*1c60b9acSAndroid Build Coastguard Worker if (b[0] == 'T') {
248*1c60b9acSAndroid Build Coastguard Worker c->f[CE_HOSTONLY] = b;
249*1c60b9acSAndroid Build Coastguard Worker c->l[CE_HOSTONLY] = 1;
250*1c60b9acSAndroid Build Coastguard Worker }
251*1c60b9acSAndroid Build Coastguard Worker break;
252*1c60b9acSAndroid Build Coastguard Worker case LWSC_NSC_SECURE:
253*1c60b9acSAndroid Build Coastguard Worker if (b[0] == 'T') {
254*1c60b9acSAndroid Build Coastguard Worker c->f[CE_SECURE] = b;
255*1c60b9acSAndroid Build Coastguard Worker c->l[CE_SECURE] = 1;
256*1c60b9acSAndroid Build Coastguard Worker }
257*1c60b9acSAndroid Build Coastguard Worker break;
258*1c60b9acSAndroid Build Coastguard Worker
259*1c60b9acSAndroid Build Coastguard Worker case LWSC_NSC_VALUE:
260*1c60b9acSAndroid Build Coastguard Worker c->f[CE_VALUE] = b;
261*1c60b9acSAndroid Build Coastguard Worker c->l[CE_VALUE] = n + 1;
262*1c60b9acSAndroid Build Coastguard Worker
263*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < LWS_ARRAY_SIZE(c->f); n++)
264*1c60b9acSAndroid Build Coastguard Worker lwsl_cookie("%s: %d: %.*s\n", __func__,
265*1c60b9acSAndroid Build Coastguard Worker (int)n, (int)c->l[n], c->f[n]);
266*1c60b9acSAndroid Build Coastguard Worker
267*1c60b9acSAndroid Build Coastguard Worker return 0;
268*1c60b9acSAndroid Build Coastguard Worker default:
269*1c60b9acSAndroid Build Coastguard Worker return -1;
270*1c60b9acSAndroid Build Coastguard Worker }
271*1c60b9acSAndroid Build Coastguard Worker
272*1c60b9acSAndroid Build Coastguard Worker b += n + 1;
273*1c60b9acSAndroid Build Coastguard Worker n = 0;
274*1c60b9acSAndroid Build Coastguard Worker state++;
275*1c60b9acSAndroid Build Coastguard Worker }
276*1c60b9acSAndroid Build Coastguard Worker
277*1c60b9acSAndroid Build Coastguard Worker return -1;
278*1c60b9acSAndroid Build Coastguard Worker }
279*1c60b9acSAndroid Build Coastguard Worker
280*1c60b9acSAndroid Build Coastguard Worker static int
lws_cookie_write_nsc(struct lws * wsi,struct lws_cookie * c)281*1c60b9acSAndroid Build Coastguard Worker lws_cookie_write_nsc(struct lws *wsi, struct lws_cookie *c)
282*1c60b9acSAndroid Build Coastguard Worker {
283*1c60b9acSAndroid Build Coastguard Worker char cache_name[LWS_COOKIE_MAX_CACHE_NAME_LEN];
284*1c60b9acSAndroid Build Coastguard Worker struct lws_cache_ttl_lru *l1;
285*1c60b9acSAndroid Build Coastguard Worker struct client_info_stash *stash;
286*1c60b9acSAndroid Build Coastguard Worker char *cookie_string = NULL, *dl;
287*1c60b9acSAndroid Build Coastguard Worker /* 6 tabs + 20 for max time_t + 2 * TRUE/FALSE + null */
288*1c60b9acSAndroid Build Coastguard Worker size_t size = 6 + 20 + 10 + 1;
289*1c60b9acSAndroid Build Coastguard Worker time_t expires = 0;
290*1c60b9acSAndroid Build Coastguard Worker int ret = 0;
291*1c60b9acSAndroid Build Coastguard Worker
292*1c60b9acSAndroid Build Coastguard Worker if (!wsi || !c)
293*1c60b9acSAndroid Build Coastguard Worker return -1;
294*1c60b9acSAndroid Build Coastguard Worker
295*1c60b9acSAndroid Build Coastguard Worker l1 = wsi->a.context->l1;
296*1c60b9acSAndroid Build Coastguard Worker if (!l1 || !wsi->a.context->nsc)
297*1c60b9acSAndroid Build Coastguard Worker return -1;
298*1c60b9acSAndroid Build Coastguard Worker
299*1c60b9acSAndroid Build Coastguard Worker stash = wsi->stash ? wsi->stash : lws_get_network_wsi(wsi)->stash;
300*1c60b9acSAndroid Build Coastguard Worker if (!stash || !stash->cis[CIS_ADDRESS] ||
301*1c60b9acSAndroid Build Coastguard Worker !stash->cis[CIS_PATH])
302*1c60b9acSAndroid Build Coastguard Worker return -1;
303*1c60b9acSAndroid Build Coastguard Worker
304*1c60b9acSAndroid Build Coastguard Worker
305*1c60b9acSAndroid Build Coastguard Worker if (!c->f[CE_NAME] || !c->f[CE_VALUE]) {
306*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: malformed c\n", __func__);
307*1c60b9acSAndroid Build Coastguard Worker
308*1c60b9acSAndroid Build Coastguard Worker return -1;
309*1c60b9acSAndroid Build Coastguard Worker }
310*1c60b9acSAndroid Build Coastguard Worker
311*1c60b9acSAndroid Build Coastguard Worker if (!c->f[CE_EXPIRES]) {
312*1c60b9acSAndroid Build Coastguard Worker /*
313*1c60b9acSAndroid Build Coastguard Worker * Currently we just take the approach to reject session cookies
314*1c60b9acSAndroid Build Coastguard Worker */
315*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("%s: reject session cookies\n", __func__);
316*1c60b9acSAndroid Build Coastguard Worker
317*1c60b9acSAndroid Build Coastguard Worker return 0;
318*1c60b9acSAndroid Build Coastguard Worker }
319*1c60b9acSAndroid Build Coastguard Worker
320*1c60b9acSAndroid Build Coastguard Worker if (!c->f[CE_DOMAIN]) {
321*1c60b9acSAndroid Build Coastguard Worker c->f[CE_HOSTONLY] = "T";
322*1c60b9acSAndroid Build Coastguard Worker c->l[CE_HOSTONLY] = 1;
323*1c60b9acSAndroid Build Coastguard Worker c->f[CE_DOMAIN] = stash->cis[CIS_ADDRESS];
324*1c60b9acSAndroid Build Coastguard Worker c->l[CE_DOMAIN] = strlen(c->f[CE_DOMAIN]);
325*1c60b9acSAndroid Build Coastguard Worker }
326*1c60b9acSAndroid Build Coastguard Worker
327*1c60b9acSAndroid Build Coastguard Worker if (!c->f[CE_PATH]) {
328*1c60b9acSAndroid Build Coastguard Worker c->f[CE_PATH] = stash->cis[CIS_PATH];
329*1c60b9acSAndroid Build Coastguard Worker c->l[CE_PATH] = strlen(c->f[CE_PATH]);
330*1c60b9acSAndroid Build Coastguard Worker dl = memchr(c->f[CE_PATH], '?', c->l[CE_PATH]);
331*1c60b9acSAndroid Build Coastguard Worker if (dl)
332*1c60b9acSAndroid Build Coastguard Worker c->l[CE_PATH] = (size_t)(dl - c->f[CE_PATH]);
333*1c60b9acSAndroid Build Coastguard Worker }
334*1c60b9acSAndroid Build Coastguard Worker
335*1c60b9acSAndroid Build Coastguard Worker if (lws_cookie_compile_cache_name(cache_name, sizeof(cache_name), c))
336*1c60b9acSAndroid Build Coastguard Worker return -1;
337*1c60b9acSAndroid Build Coastguard Worker
338*1c60b9acSAndroid Build Coastguard Worker if (c->f[CE_EXPIRES] &&
339*1c60b9acSAndroid Build Coastguard Worker lws_cookie_parse_date(c->f[CE_EXPIRES], c->l[CE_EXPIRES], &expires)) {
340*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: can't parse date %.*s\n", __func__,
341*1c60b9acSAndroid Build Coastguard Worker (int)c->l[CE_EXPIRES], c->f[CE_EXPIRES]);
342*1c60b9acSAndroid Build Coastguard Worker return -1;
343*1c60b9acSAndroid Build Coastguard Worker }
344*1c60b9acSAndroid Build Coastguard Worker
345*1c60b9acSAndroid Build Coastguard Worker size += c->l[CE_NAME] + c->l[CE_VALUE] + c->l[CE_DOMAIN] + c->l[CE_PATH];
346*1c60b9acSAndroid Build Coastguard Worker cookie_string = (char *)lws_malloc(size, __func__);
347*1c60b9acSAndroid Build Coastguard Worker if (!cookie_string) {
348*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: OOM\n",__func__);
349*1c60b9acSAndroid Build Coastguard Worker
350*1c60b9acSAndroid Build Coastguard Worker return -1;
351*1c60b9acSAndroid Build Coastguard Worker }
352*1c60b9acSAndroid Build Coastguard Worker
353*1c60b9acSAndroid Build Coastguard Worker lws_snprintf(cookie_string, size, LWS_COOKIE_NSC_FORMAT,
354*1c60b9acSAndroid Build Coastguard Worker (int)c->l[CE_DOMAIN], c->f[CE_DOMAIN],
355*1c60b9acSAndroid Build Coastguard Worker c->f[CE_HOSTONLY] ? "TRUE" : "FALSE",
356*1c60b9acSAndroid Build Coastguard Worker (int)c->l[CE_PATH], c->f[CE_PATH],
357*1c60b9acSAndroid Build Coastguard Worker c->f[CE_SECURE] ? "TRUE" : "FALSE",
358*1c60b9acSAndroid Build Coastguard Worker (unsigned long long)expires,
359*1c60b9acSAndroid Build Coastguard Worker (int)c->l[CE_NAME], c->f[CE_NAME],
360*1c60b9acSAndroid Build Coastguard Worker (int)c->l[CE_VALUE], c->f[CE_VALUE]);
361*1c60b9acSAndroid Build Coastguard Worker
362*1c60b9acSAndroid Build Coastguard Worker lwsl_cookie("%s: name %s\n", __func__, cache_name);
363*1c60b9acSAndroid Build Coastguard Worker lwsl_cookie("%s: c %s\n", __func__, cookie_string);
364*1c60b9acSAndroid Build Coastguard Worker
365*1c60b9acSAndroid Build Coastguard Worker if (lws_cache_write_through(l1, cache_name,
366*1c60b9acSAndroid Build Coastguard Worker (const uint8_t *)cookie_string,
367*1c60b9acSAndroid Build Coastguard Worker strlen(cookie_string),
368*1c60b9acSAndroid Build Coastguard Worker (lws_usec_t)((unsigned long long)expires *
369*1c60b9acSAndroid Build Coastguard Worker (lws_usec_t)LWS_US_PER_SEC), NULL)) {
370*1c60b9acSAndroid Build Coastguard Worker ret = -1;
371*1c60b9acSAndroid Build Coastguard Worker goto exit;
372*1c60b9acSAndroid Build Coastguard Worker }
373*1c60b9acSAndroid Build Coastguard Worker
374*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_COOKIE_DEBUG)
375*1c60b9acSAndroid Build Coastguard Worker char *po;
376*1c60b9acSAndroid Build Coastguard Worker if (lws_cache_item_get(l1, cache_name, (const void **)&po, &size) ||
377*1c60b9acSAndroid Build Coastguard Worker size != strlen(cookie_string) || memcmp(po, cookie_string, size)) {
378*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: L1 '%s' missing\n", __func__, cache_name);
379*1c60b9acSAndroid Build Coastguard Worker }
380*1c60b9acSAndroid Build Coastguard Worker
381*1c60b9acSAndroid Build Coastguard Worker if (lws_cache_item_get(wsi->a.context->nsc, cache_name,
382*1c60b9acSAndroid Build Coastguard Worker (const void **)&po, &size) ||
383*1c60b9acSAndroid Build Coastguard Worker size != strlen(cookie_string) ||
384*1c60b9acSAndroid Build Coastguard Worker memcmp(po, cookie_string, size)) {
385*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: NSC '%s' missing, size %llu, po %s\n", __func__,
386*1c60b9acSAndroid Build Coastguard Worker cache_name, (unsigned long long)size, po);
387*1c60b9acSAndroid Build Coastguard Worker }
388*1c60b9acSAndroid Build Coastguard Worker #endif
389*1c60b9acSAndroid Build Coastguard Worker
390*1c60b9acSAndroid Build Coastguard Worker exit:
391*1c60b9acSAndroid Build Coastguard Worker lws_free(cookie_string);
392*1c60b9acSAndroid Build Coastguard Worker
393*1c60b9acSAndroid Build Coastguard Worker return ret;
394*1c60b9acSAndroid Build Coastguard Worker }
395*1c60b9acSAndroid Build Coastguard Worker
396*1c60b9acSAndroid Build Coastguard Worker static int
lws_cookie_attach_cookies(struct lws * wsi,char * buf,char * end)397*1c60b9acSAndroid Build Coastguard Worker lws_cookie_attach_cookies(struct lws *wsi, char *buf, char *end)
398*1c60b9acSAndroid Build Coastguard Worker {
399*1c60b9acSAndroid Build Coastguard Worker const char *domain, *path, *dl_domain, *dl_path, *po;
400*1c60b9acSAndroid Build Coastguard Worker char cache_name[LWS_COOKIE_MAX_CACHE_NAME_LEN];
401*1c60b9acSAndroid Build Coastguard Worker size_t domain_len, path_len, size, ret = 0;
402*1c60b9acSAndroid Build Coastguard Worker struct lws_cache_ttl_lru *l1;
403*1c60b9acSAndroid Build Coastguard Worker struct client_info_stash *stash;
404*1c60b9acSAndroid Build Coastguard Worker lws_cache_results_t cr;
405*1c60b9acSAndroid Build Coastguard Worker struct lws_cookie c;
406*1c60b9acSAndroid Build Coastguard Worker int hostdomain = 1;
407*1c60b9acSAndroid Build Coastguard Worker char *p, *p1;
408*1c60b9acSAndroid Build Coastguard Worker
409*1c60b9acSAndroid Build Coastguard Worker if (!wsi)
410*1c60b9acSAndroid Build Coastguard Worker return -1;
411*1c60b9acSAndroid Build Coastguard Worker
412*1c60b9acSAndroid Build Coastguard Worker stash = wsi->stash ? wsi->stash : lws_get_network_wsi(wsi)->stash;
413*1c60b9acSAndroid Build Coastguard Worker if (!stash || !stash->cis[CIS_ADDRESS] ||
414*1c60b9acSAndroid Build Coastguard Worker !stash->cis[CIS_PATH])
415*1c60b9acSAndroid Build Coastguard Worker return -1;
416*1c60b9acSAndroid Build Coastguard Worker
417*1c60b9acSAndroid Build Coastguard Worker l1 = wsi->a.context->l1;
418*1c60b9acSAndroid Build Coastguard Worker if (!l1 || !wsi->a.context->nsc){
419*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s:no cookiejar\n", __func__);
420*1c60b9acSAndroid Build Coastguard Worker return -1;
421*1c60b9acSAndroid Build Coastguard Worker }
422*1c60b9acSAndroid Build Coastguard Worker
423*1c60b9acSAndroid Build Coastguard Worker memset(&c, 0, sizeof(c));
424*1c60b9acSAndroid Build Coastguard Worker
425*1c60b9acSAndroid Build Coastguard Worker domain = stash->cis[CIS_ADDRESS];
426*1c60b9acSAndroid Build Coastguard Worker path = stash->cis[CIS_PATH];
427*1c60b9acSAndroid Build Coastguard Worker
428*1c60b9acSAndroid Build Coastguard Worker if (!domain || !path)
429*1c60b9acSAndroid Build Coastguard Worker return -1;
430*1c60b9acSAndroid Build Coastguard Worker
431*1c60b9acSAndroid Build Coastguard Worker path_len = strlen(path);
432*1c60b9acSAndroid Build Coastguard Worker
433*1c60b9acSAndroid Build Coastguard Worker /* remove query string if exist */
434*1c60b9acSAndroid Build Coastguard Worker dl_path = memchr(path, '?', path_len);
435*1c60b9acSAndroid Build Coastguard Worker if (dl_path)
436*1c60b9acSAndroid Build Coastguard Worker path_len = lws_ptr_diff_size_t(dl_path, path);
437*1c60b9acSAndroid Build Coastguard Worker
438*1c60b9acSAndroid Build Coastguard Worker /* remove last slash if exist */
439*1c60b9acSAndroid Build Coastguard Worker if (path_len != 1 && path[path_len - 1] == '/')
440*1c60b9acSAndroid Build Coastguard Worker path_len--;
441*1c60b9acSAndroid Build Coastguard Worker
442*1c60b9acSAndroid Build Coastguard Worker if (!path_len)
443*1c60b9acSAndroid Build Coastguard Worker return -1;
444*1c60b9acSAndroid Build Coastguard Worker
445*1c60b9acSAndroid Build Coastguard Worker lwsl_cookie("%s: path %.*s len %d\n", __func__, (int)path_len, path, (int)path_len);
446*1c60b9acSAndroid Build Coastguard Worker
447*1c60b9acSAndroid Build Coastguard Worker /* when dest buf is not provided, we only return size of cookie string */
448*1c60b9acSAndroid Build Coastguard Worker if (!buf || !end)
449*1c60b9acSAndroid Build Coastguard Worker p = NULL;
450*1c60b9acSAndroid Build Coastguard Worker else
451*1c60b9acSAndroid Build Coastguard Worker p = buf;
452*1c60b9acSAndroid Build Coastguard Worker
453*1c60b9acSAndroid Build Coastguard Worker /* iterate through domain and path levels to find matching cookies */
454*1c60b9acSAndroid Build Coastguard Worker dl_domain = domain;
455*1c60b9acSAndroid Build Coastguard Worker while (dl_domain) {
456*1c60b9acSAndroid Build Coastguard Worker domain_len = strlen(domain);
457*1c60b9acSAndroid Build Coastguard Worker dl_domain = memchr(domain, '.', domain_len);
458*1c60b9acSAndroid Build Coastguard Worker /* don't match top level domain */
459*1c60b9acSAndroid Build Coastguard Worker if (!dl_domain)
460*1c60b9acSAndroid Build Coastguard Worker break;
461*1c60b9acSAndroid Build Coastguard Worker
462*1c60b9acSAndroid Build Coastguard Worker if (domain_len + path_len + 6 > sizeof(cache_name))
463*1c60b9acSAndroid Build Coastguard Worker return -1;
464*1c60b9acSAndroid Build Coastguard Worker
465*1c60b9acSAndroid Build Coastguard Worker /* compile key string "[domain]|[path]|*"" */
466*1c60b9acSAndroid Build Coastguard Worker p1 = cache_name;
467*1c60b9acSAndroid Build Coastguard Worker memcpy(p1, domain, domain_len);
468*1c60b9acSAndroid Build Coastguard Worker p1 += domain_len;
469*1c60b9acSAndroid Build Coastguard Worker *p1 = '|';
470*1c60b9acSAndroid Build Coastguard Worker p1++;
471*1c60b9acSAndroid Build Coastguard Worker memcpy(p1, path, path_len);
472*1c60b9acSAndroid Build Coastguard Worker p1 += path_len;
473*1c60b9acSAndroid Build Coastguard Worker *p1 = '|';
474*1c60b9acSAndroid Build Coastguard Worker p1++;
475*1c60b9acSAndroid Build Coastguard Worker *p1 = '*';
476*1c60b9acSAndroid Build Coastguard Worker p1++;
477*1c60b9acSAndroid Build Coastguard Worker *p1 = '\0';
478*1c60b9acSAndroid Build Coastguard Worker
479*1c60b9acSAndroid Build Coastguard Worker lwsl_cookie("%s: looking for %s\n", __func__, cache_name);
480*1c60b9acSAndroid Build Coastguard Worker
481*1c60b9acSAndroid Build Coastguard Worker if (!lws_cache_lookup(l1, cache_name,
482*1c60b9acSAndroid Build Coastguard Worker (const void **)&cr.ptr, &cr.size)) {
483*1c60b9acSAndroid Build Coastguard Worker
484*1c60b9acSAndroid Build Coastguard Worker while (!lws_cache_results_walk(&cr)) {
485*1c60b9acSAndroid Build Coastguard Worker lwsl_cookie(" %s (%d)\n", (const char *)cr.tag,
486*1c60b9acSAndroid Build Coastguard Worker (int)cr.payload_len);
487*1c60b9acSAndroid Build Coastguard Worker
488*1c60b9acSAndroid Build Coastguard Worker if (lws_cache_item_get(l1, (const char *)cr.tag,
489*1c60b9acSAndroid Build Coastguard Worker (const void **)&po, &size) ||
490*1c60b9acSAndroid Build Coastguard Worker lws_cookie_parse_nsc(&c, po, size)) {
491*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: failed to get c '%s'\n",
492*1c60b9acSAndroid Build Coastguard Worker __func__, cr.tag);
493*1c60b9acSAndroid Build Coastguard Worker break;
494*1c60b9acSAndroid Build Coastguard Worker }
495*1c60b9acSAndroid Build Coastguard Worker
496*1c60b9acSAndroid Build Coastguard Worker if (c.f[CE_HOSTONLY] && !hostdomain){
497*1c60b9acSAndroid Build Coastguard Worker lwsl_cookie("%s: not sending this\n",
498*1c60b9acSAndroid Build Coastguard Worker __func__);
499*1c60b9acSAndroid Build Coastguard Worker continue;
500*1c60b9acSAndroid Build Coastguard Worker }
501*1c60b9acSAndroid Build Coastguard Worker
502*1c60b9acSAndroid Build Coastguard Worker if (p) {
503*1c60b9acSAndroid Build Coastguard Worker if (ret) {
504*1c60b9acSAndroid Build Coastguard Worker *p = ';';
505*1c60b9acSAndroid Build Coastguard Worker p++;
506*1c60b9acSAndroid Build Coastguard Worker *p = ' ';
507*1c60b9acSAndroid Build Coastguard Worker p++;
508*1c60b9acSAndroid Build Coastguard Worker }
509*1c60b9acSAndroid Build Coastguard Worker
510*1c60b9acSAndroid Build Coastguard Worker memcpy(p, c.f[CE_NAME], c.l[CE_NAME]);
511*1c60b9acSAndroid Build Coastguard Worker p += c.l[CE_NAME];
512*1c60b9acSAndroid Build Coastguard Worker *p = '=';
513*1c60b9acSAndroid Build Coastguard Worker p++;
514*1c60b9acSAndroid Build Coastguard Worker memcpy(p, c.f[CE_VALUE], c.l[CE_VALUE]);
515*1c60b9acSAndroid Build Coastguard Worker p += c.l[CE_VALUE];
516*1c60b9acSAndroid Build Coastguard Worker }
517*1c60b9acSAndroid Build Coastguard Worker
518*1c60b9acSAndroid Build Coastguard Worker if (ret)
519*1c60b9acSAndroid Build Coastguard Worker ret += 2;
520*1c60b9acSAndroid Build Coastguard Worker ret += c.l[CE_NAME] + 1 + c.l[CE_VALUE];
521*1c60b9acSAndroid Build Coastguard Worker
522*1c60b9acSAndroid Build Coastguard Worker }
523*1c60b9acSAndroid Build Coastguard Worker }
524*1c60b9acSAndroid Build Coastguard Worker
525*1c60b9acSAndroid Build Coastguard Worker domain = dl_domain + 1;
526*1c60b9acSAndroid Build Coastguard Worker hostdomain = 0;
527*1c60b9acSAndroid Build Coastguard Worker }
528*1c60b9acSAndroid Build Coastguard Worker
529*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: c len (%d)\n", __func__, (int)ret);
530*1c60b9acSAndroid Build Coastguard Worker
531*1c60b9acSAndroid Build Coastguard Worker return (int)ret;
532*1c60b9acSAndroid Build Coastguard Worker }
533*1c60b9acSAndroid Build Coastguard Worker
534*1c60b9acSAndroid Build Coastguard Worker static struct {
535*1c60b9acSAndroid Build Coastguard Worker const char *const name;
536*1c60b9acSAndroid Build Coastguard Worker uint8_t len;
537*1c60b9acSAndroid Build Coastguard Worker } cft[] = {
538*1c60b9acSAndroid Build Coastguard Worker { "domain=", 7 },
539*1c60b9acSAndroid Build Coastguard Worker { "path=", 5 },
540*1c60b9acSAndroid Build Coastguard Worker { "expires=", 8 },
541*1c60b9acSAndroid Build Coastguard Worker { "max-age=", 8 },
542*1c60b9acSAndroid Build Coastguard Worker { "httponly", 8 },
543*1c60b9acSAndroid Build Coastguard Worker { "secure", 6 }
544*1c60b9acSAndroid Build Coastguard Worker };
545*1c60b9acSAndroid Build Coastguard Worker
546*1c60b9acSAndroid Build Coastguard Worker int
lws_parse_set_cookie(struct lws * wsi)547*1c60b9acSAndroid Build Coastguard Worker lws_parse_set_cookie(struct lws *wsi)
548*1c60b9acSAndroid Build Coastguard Worker {
549*1c60b9acSAndroid Build Coastguard Worker char *tk_head, *tk_end, *buf_head, *buf_end, *cookiep, *dl;
550*1c60b9acSAndroid Build Coastguard Worker struct lws_cache_ttl_lru *l1;
551*1c60b9acSAndroid Build Coastguard Worker struct lws_cookie c;
552*1c60b9acSAndroid Build Coastguard Worker size_t fl;
553*1c60b9acSAndroid Build Coastguard Worker int f, n;
554*1c60b9acSAndroid Build Coastguard Worker
555*1c60b9acSAndroid Build Coastguard Worker if (!wsi)
556*1c60b9acSAndroid Build Coastguard Worker return -1;
557*1c60b9acSAndroid Build Coastguard Worker
558*1c60b9acSAndroid Build Coastguard Worker l1 = wsi->a.context->l1;
559*1c60b9acSAndroid Build Coastguard Worker if (!l1)
560*1c60b9acSAndroid Build Coastguard Worker return -1;
561*1c60b9acSAndroid Build Coastguard Worker
562*1c60b9acSAndroid Build Coastguard Worker f = wsi->http.ah->frag_index[WSI_TOKEN_HTTP_SET_COOKIE];
563*1c60b9acSAndroid Build Coastguard Worker
564*1c60b9acSAndroid Build Coastguard Worker while (f) {
565*1c60b9acSAndroid Build Coastguard Worker cookiep = wsi->http.ah->data + wsi->http.ah->frags[f].offset;
566*1c60b9acSAndroid Build Coastguard Worker fl = wsi->http.ah->frags[f].len;
567*1c60b9acSAndroid Build Coastguard Worker f = wsi->http.ah->frags[f].nfrag;
568*1c60b9acSAndroid Build Coastguard Worker
569*1c60b9acSAndroid Build Coastguard Worker if (!cookiep || !fl)
570*1c60b9acSAndroid Build Coastguard Worker continue;
571*1c60b9acSAndroid Build Coastguard Worker
572*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_COOKIE_DEBUG)
573*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s:parsing: %.*s\n", __func__, (int)fl, cookiep);
574*1c60b9acSAndroid Build Coastguard Worker #endif
575*1c60b9acSAndroid Build Coastguard Worker
576*1c60b9acSAndroid Build Coastguard Worker buf_head = cookiep;
577*1c60b9acSAndroid Build Coastguard Worker buf_end = cookiep + fl - 1;
578*1c60b9acSAndroid Build Coastguard Worker memset(&c, 0, sizeof(struct lws_cookie));
579*1c60b9acSAndroid Build Coastguard Worker
580*1c60b9acSAndroid Build Coastguard Worker do {
581*1c60b9acSAndroid Build Coastguard Worker tk_head = buf_head;
582*1c60b9acSAndroid Build Coastguard Worker tk_end = memchr(buf_head, ';',
583*1c60b9acSAndroid Build Coastguard Worker (size_t)(buf_end - buf_head + 1));
584*1c60b9acSAndroid Build Coastguard Worker if (!tk_end) {
585*1c60b9acSAndroid Build Coastguard Worker tk_end = buf_end;
586*1c60b9acSAndroid Build Coastguard Worker buf_head = buf_end;
587*1c60b9acSAndroid Build Coastguard Worker } else {
588*1c60b9acSAndroid Build Coastguard Worker buf_head = tk_end + 1;
589*1c60b9acSAndroid Build Coastguard Worker tk_end--;
590*1c60b9acSAndroid Build Coastguard Worker }
591*1c60b9acSAndroid Build Coastguard Worker
592*1c60b9acSAndroid Build Coastguard Worker if (c.f[CE_NAME])
593*1c60b9acSAndroid Build Coastguard Worker goto parse_av;
594*1c60b9acSAndroid Build Coastguard Worker
595*1c60b9acSAndroid Build Coastguard Worker /*
596*1c60b9acSAndroid Build Coastguard Worker * find name value, remove leading trailing
597*1c60b9acSAndroid Build Coastguard Worker * WS and DQ for value
598*1c60b9acSAndroid Build Coastguard Worker */
599*1c60b9acSAndroid Build Coastguard Worker
600*1c60b9acSAndroid Build Coastguard Worker dl = memchr(tk_head, '=', lws_ptr_diff_size_t(tk_end,
601*1c60b9acSAndroid Build Coastguard Worker tk_head + 1));
602*1c60b9acSAndroid Build Coastguard Worker if (!dl || dl == tk_head)
603*1c60b9acSAndroid Build Coastguard Worker return -1;
604*1c60b9acSAndroid Build Coastguard Worker
605*1c60b9acSAndroid Build Coastguard Worker c.f[CE_NAME] = tk_head;
606*1c60b9acSAndroid Build Coastguard Worker c.l[CE_NAME] = lws_ptr_diff_size_t(dl, tk_head);
607*1c60b9acSAndroid Build Coastguard Worker lws_cookie_rm_sws(&c.f[CE_NAME], &c.l[CE_NAME]);
608*1c60b9acSAndroid Build Coastguard Worker
609*1c60b9acSAndroid Build Coastguard Worker if (!c.l[CE_NAME])
610*1c60b9acSAndroid Build Coastguard Worker return -1;
611*1c60b9acSAndroid Build Coastguard Worker
612*1c60b9acSAndroid Build Coastguard Worker lwsl_cookie("%s: c name l %d v:%.*s\n", __func__,
613*1c60b9acSAndroid Build Coastguard Worker (int)c.l[CE_NAME],
614*1c60b9acSAndroid Build Coastguard Worker (int)c.l[CE_NAME], c.f[CE_NAME]);
615*1c60b9acSAndroid Build Coastguard Worker c.f[CE_VALUE] = dl + 1;
616*1c60b9acSAndroid Build Coastguard Worker c.l[CE_VALUE] = lws_ptr_diff_size_t(tk_end,
617*1c60b9acSAndroid Build Coastguard Worker c.f[CE_VALUE]) + 1;
618*1c60b9acSAndroid Build Coastguard Worker
619*1c60b9acSAndroid Build Coastguard Worker lws_cookie_rm_sws(&c.f[CE_VALUE], &c.l[CE_VALUE]);
620*1c60b9acSAndroid Build Coastguard Worker if (c.l[CE_VALUE] >= 2 && c.f[CE_VALUE][0] == '\"') {
621*1c60b9acSAndroid Build Coastguard Worker c.f[CE_VALUE]++;
622*1c60b9acSAndroid Build Coastguard Worker c.l[CE_VALUE] -= 2;
623*1c60b9acSAndroid Build Coastguard Worker }
624*1c60b9acSAndroid Build Coastguard Worker lwsl_cookie("%s: c value l %d v:%.*s\n", __func__,
625*1c60b9acSAndroid Build Coastguard Worker (int)c.l[CE_VALUE], (int)c.l[CE_VALUE],
626*1c60b9acSAndroid Build Coastguard Worker c.f[CE_VALUE]);
627*1c60b9acSAndroid Build Coastguard Worker continue;
628*1c60b9acSAndroid Build Coastguard Worker
629*1c60b9acSAndroid Build Coastguard Worker parse_av:
630*1c60b9acSAndroid Build Coastguard Worker while (*tk_head == ' ') {
631*1c60b9acSAndroid Build Coastguard Worker if (tk_head == tk_end)
632*1c60b9acSAndroid Build Coastguard Worker return -1;
633*1c60b9acSAndroid Build Coastguard Worker
634*1c60b9acSAndroid Build Coastguard Worker tk_head++;
635*1c60b9acSAndroid Build Coastguard Worker }
636*1c60b9acSAndroid Build Coastguard Worker
637*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < (int)LWS_ARRAY_SIZE(cft); n++) {
638*1c60b9acSAndroid Build Coastguard Worker if (lws_tolower(*tk_head) != cft[n].name[0])
639*1c60b9acSAndroid Build Coastguard Worker continue;
640*1c60b9acSAndroid Build Coastguard Worker
641*1c60b9acSAndroid Build Coastguard Worker if (!is_iprefix(tk_head,
642*1c60b9acSAndroid Build Coastguard Worker lws_ptr_diff_size_t(tk_end,
643*1c60b9acSAndroid Build Coastguard Worker tk_head) + 1,
644*1c60b9acSAndroid Build Coastguard Worker cft[n].name, cft[n].len))
645*1c60b9acSAndroid Build Coastguard Worker continue;
646*1c60b9acSAndroid Build Coastguard Worker
647*1c60b9acSAndroid Build Coastguard Worker if (n == 4 || n == 5) {
648*1c60b9acSAndroid Build Coastguard Worker c.f[n] = "T";
649*1c60b9acSAndroid Build Coastguard Worker c.l[n] = 1;
650*1c60b9acSAndroid Build Coastguard Worker break;
651*1c60b9acSAndroid Build Coastguard Worker }
652*1c60b9acSAndroid Build Coastguard Worker
653*1c60b9acSAndroid Build Coastguard Worker c.f[n] = tk_head + cft[n].len;
654*1c60b9acSAndroid Build Coastguard Worker c.l[n] = lws_ptr_diff_size_t(tk_end, c.f[n]) + 1;
655*1c60b9acSAndroid Build Coastguard Worker lws_cookie_rm_sws(&c.f[n], &c.l[n]);
656*1c60b9acSAndroid Build Coastguard Worker
657*1c60b9acSAndroid Build Coastguard Worker if (n == CE_DOMAIN && c.l[0] &&
658*1c60b9acSAndroid Build Coastguard Worker c.f[n][0] == '.'){
659*1c60b9acSAndroid Build Coastguard Worker c.f[n]++;
660*1c60b9acSAndroid Build Coastguard Worker c.l[n]--;
661*1c60b9acSAndroid Build Coastguard Worker }
662*1c60b9acSAndroid Build Coastguard Worker
663*1c60b9acSAndroid Build Coastguard Worker lwsl_cookie("%s: %s l %d v:%.*s\n", __func__,
664*1c60b9acSAndroid Build Coastguard Worker cft[n].name, (int)c.l[n],
665*1c60b9acSAndroid Build Coastguard Worker (int)c.l[n], c.f[n]);
666*1c60b9acSAndroid Build Coastguard Worker break;
667*1c60b9acSAndroid Build Coastguard Worker }
668*1c60b9acSAndroid Build Coastguard Worker
669*1c60b9acSAndroid Build Coastguard Worker } while (tk_end != buf_end);
670*1c60b9acSAndroid Build Coastguard Worker
671*1c60b9acSAndroid Build Coastguard Worker if (lws_cookie_write_nsc(wsi, &c))
672*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s:failed to write nsc\n", __func__);
673*1c60b9acSAndroid Build Coastguard Worker }
674*1c60b9acSAndroid Build Coastguard Worker
675*1c60b9acSAndroid Build Coastguard Worker return 0;
676*1c60b9acSAndroid Build Coastguard Worker }
677*1c60b9acSAndroid Build Coastguard Worker
678*1c60b9acSAndroid Build Coastguard Worker int
lws_cookie_send_cookies(struct lws * wsi,char ** pp,char * end)679*1c60b9acSAndroid Build Coastguard Worker lws_cookie_send_cookies(struct lws *wsi, char **pp, char *end)
680*1c60b9acSAndroid Build Coastguard Worker {
681*1c60b9acSAndroid Build Coastguard Worker char *p;
682*1c60b9acSAndroid Build Coastguard Worker int size;
683*1c60b9acSAndroid Build Coastguard Worker
684*1c60b9acSAndroid Build Coastguard Worker if (!wsi || !pp || !(*pp) || !end)
685*1c60b9acSAndroid Build Coastguard Worker return -1;
686*1c60b9acSAndroid Build Coastguard Worker
687*1c60b9acSAndroid Build Coastguard Worker size = lws_cookie_attach_cookies(wsi, NULL, NULL);
688*1c60b9acSAndroid Build Coastguard Worker
689*1c60b9acSAndroid Build Coastguard Worker if (!size)
690*1c60b9acSAndroid Build Coastguard Worker return 0;
691*1c60b9acSAndroid Build Coastguard Worker if (size < 0) {
692*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s:failed to get cookie string size\n", __func__);
693*1c60b9acSAndroid Build Coastguard Worker return -1;
694*1c60b9acSAndroid Build Coastguard Worker }
695*1c60b9acSAndroid Build Coastguard Worker
696*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: size %d\n", __func__, size);
697*1c60b9acSAndroid Build Coastguard Worker
698*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_COOKIE_DEBUG)
699*1c60b9acSAndroid Build Coastguard Worker char *p_dbg = *pp;
700*1c60b9acSAndroid Build Coastguard Worker #endif
701*1c60b9acSAndroid Build Coastguard Worker
702*1c60b9acSAndroid Build Coastguard Worker if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_COOKIE, NULL, size,
703*1c60b9acSAndroid Build Coastguard Worker (unsigned char **)pp, (unsigned char *)end))
704*1c60b9acSAndroid Build Coastguard Worker return -1;
705*1c60b9acSAndroid Build Coastguard Worker
706*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_COOKIE_DEBUG)
707*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: dummy copy (%.*s) \n", __func__, (int)(*pp - p_dbg), p_dbg);
708*1c60b9acSAndroid Build Coastguard Worker #endif
709*1c60b9acSAndroid Build Coastguard Worker
710*1c60b9acSAndroid Build Coastguard Worker
711*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_WITH_HTTP2
712*1c60b9acSAndroid Build Coastguard Worker if (lws_wsi_is_h2(wsi))
713*1c60b9acSAndroid Build Coastguard Worker p = *pp - size;
714*1c60b9acSAndroid Build Coastguard Worker else
715*1c60b9acSAndroid Build Coastguard Worker #endif
716*1c60b9acSAndroid Build Coastguard Worker p = *pp - size - 2;
717*1c60b9acSAndroid Build Coastguard Worker
718*1c60b9acSAndroid Build Coastguard Worker if (lws_cookie_attach_cookies(wsi, p, p + size) <= 0) {
719*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s:failed to attach cookies\n", __func__);
720*1c60b9acSAndroid Build Coastguard Worker return -1;
721*1c60b9acSAndroid Build Coastguard Worker }
722*1c60b9acSAndroid Build Coastguard Worker
723*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_COOKIE_DEBUG)
724*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: real copy (%.*s) total len %d\n", __func__, (int)(*pp - p_dbg), p_dbg, (int)(*pp - p_dbg));
725*1c60b9acSAndroid Build Coastguard Worker lwsl_hexdump_notice(p_dbg, (size_t)(*pp - p_dbg));
726*1c60b9acSAndroid Build Coastguard Worker #endif
727*1c60b9acSAndroid Build Coastguard Worker
728*1c60b9acSAndroid Build Coastguard Worker return 0;
729*1c60b9acSAndroid Build Coastguard Worker }
730