xref: /aosp_15_r20/external/libwebsockets/lib/roles/http/cookie.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
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