Mercurial > dillo_port1.3
annotate dpi/cookies.c @ 1522:85062b64ae9d
cookies allow Expires attr's value to be quoted.
sourceforge sends cookies this way.
It seems that quotes around values are generally to be ignored, i.e.,
not stripped or anything, but I asked the draft spec author about this
case, and he reports that he has fixed his algorithm to allow leading and
trailing delimiters around cookie-date.
If I/someone eventually does make the timestamp code follow the algorithm more
closely, the stripping would no longer need to be done here. As for whether
we'd want to continue to use that code for the stricter server_date that
we get from the HTTP Date header, I'm not sure at the moment. I've already
added one case to it that wouldn't be legal for the header, though...
author | corvid <corvid@lavabit.com> |
---|---|
date | Mon, 18 Jan 2010 00:57:58 +0000 |
parents | 6fcb13a8b680 |
children | 03752405e0a9 |
rev | line source |
---|---|
0 | 1 /* |
2 * File: cookies.c | |
3 * Cookies server. | |
4 * | |
5 * Copyright 2001 Lars Clausen <lrclause@cs.uiuc.edu> | |
6 * Jörgen Viksell <jorgen.viksell@telia.com> | |
35 | 7 * Copyright 2002-2007 Jorge Arellano Cid <jcid@dillo.org> |
0 | 8 * |
9 * This program is free software; you can redistribute it and/or modify | |
10 * it under the terms of the GNU General Public License as published by | |
11 * the Free Software Foundation; either version 3 of the License, or | |
12 * (at your option) any later version. | |
13 * | |
14 */ | |
15 | |
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
16 /* This is written to follow the HTTP State Working Group's |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
17 * draft-ietf-httpstate-cookie-01.txt. |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
18 * |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
19 * We depart from the draft spec's domain format in that, rather than |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
20 * using a host-only flag, we continue to use the .domain notation |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
21 * internally to indicate cookies that may also be returned to subdomains. |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
22 * |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
23 * Info on cookies in the wild: |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
24 * http://www.ietf.org/mail-archive/web/http-state/current/msg00078.html |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
25 * And dates specifically: |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
26 * http://www.ietf.org/mail-archive/web/http-state/current/msg00128.html |
0 | 27 */ |
28 | |
29 #ifdef DISABLE_COOKIES | |
30 | |
31 int main(void) | |
32 { | |
33 return 0; /* never called */ | |
34 } | |
35 | |
36 #else | |
37 | |
38 | |
39 #include <sys/types.h> | |
40 #include <sys/socket.h> | |
41 #include <sys/stat.h> | |
42 #include <sys/un.h> | |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
43 #include <netinet/in.h> |
0 | 44 #include <fcntl.h> |
45 #include <unistd.h> | |
46 #include <errno.h> | |
47 #include <stddef.h> | |
48 #include <string.h> | |
49 #include <stdlib.h> | |
50 #include <stdio.h> | |
51 #include <time.h> /* for time() and time_t */ | |
52 #include <ctype.h> | |
53 #include <netdb.h> | |
54 #include <signal.h> | |
55 #include "dpiutil.h" | |
56 #include "../dpip/dpip.h" | |
57 | |
58 | |
59 /* | |
60 * Debugging macros | |
61 */ | |
62 #define _MSG(...) | |
63 #define MSG(...) printf("[cookies dpi]: " __VA_ARGS__) | |
64 | |
1508 | 65 #define DILLO_TIME_MAX ((time_t) ((1UL << (sizeof(time_t) * 8 - 1)) - 1)) |
0 | 66 |
67 /* | |
68 * a_List_add() | |
69 * | |
70 * Make sure there's space for 'num_items' items within the list | |
71 * (First, allocate an 'alloc_step' sized chunk, after that, double the | |
72 * list size --to make it faster) | |
73 */ | |
74 #define a_List_add(list,num_items,alloc_step) \ | |
75 if (!list) { \ | |
76 list = dMalloc(alloc_step * sizeof((*list))); \ | |
77 } \ | |
78 if (num_items >= alloc_step){ \ | |
79 while ( num_items >= alloc_step ) \ | |
80 alloc_step <<= 1; \ | |
81 list = dRealloc(list, alloc_step * sizeof((*list))); \ | |
82 } | |
83 | |
84 /* The maximum length of a line in the cookie file */ | |
85 #define LINE_MAXLEN 4096 | |
86 | |
87 typedef enum { | |
88 COOKIE_ACCEPT, | |
89 COOKIE_ACCEPT_SESSION, | |
90 COOKIE_DENY | |
91 } CookieControlAction; | |
92 | |
93 typedef struct { | |
94 char *domain; | |
95 CookieControlAction action; | |
96 } CookieControl; | |
97 | |
98 typedef struct { | |
99 char *domain; | |
100 Dlist *dlist; | |
101 } CookieNode; | |
102 | |
103 typedef struct { | |
104 char *name; | |
105 char *value; | |
106 char *domain; | |
107 char *path; | |
108 time_t expires_at; | |
109 bool_t secure; | |
110 bool_t session_only; | |
1504
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
111 long last_used; |
0 | 112 } CookieData_t; |
113 | |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
114 typedef struct { |
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
115 Dsh *sh; |
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
116 int status; |
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
117 } ClientInfo; |
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
118 |
0 | 119 /* |
120 * Local data | |
121 */ | |
122 | |
123 /* List of CookieNode. Each node holds a domain and its list of cookies */ | |
124 static Dlist *cookies; | |
125 | |
126 /* Variables for access control */ | |
127 static CookieControl *ccontrol = NULL; | |
128 static int num_ccontrol = 0; | |
129 static int num_ccontrol_max = 1; | |
130 static CookieControlAction default_action = COOKIE_DENY; | |
131 | |
1504
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
132 static long cookies_use_counter = 0; |
0 | 133 static bool_t disabled; |
134 static FILE *file_stream; | |
1503 | 135 static const char *const cookies_txt_header_str = |
0 | 136 "# HTTP Cookie File\n" |
1503 | 137 "# This is a generated file! Do not edit.\n" |
138 "# [domain TRUE path secure expiry_time name value]\n\n"; | |
0 | 139 |
140 | |
141 /* | |
142 * Forward declarations | |
143 */ | |
144 | |
145 static CookieControlAction Cookies_control_check_domain(const char *domain); | |
146 static int Cookie_control_init(void); | |
147 static void Cookies_add_cookie(CookieData_t *cookie); | |
148 static int Cookies_cmp(const void *a, const void *b); | |
149 | |
150 /* | |
151 * Compare function for searching a cookie node | |
152 */ | |
51 | 153 static int Cookie_node_cmp(const void *v1, const void *v2) |
0 | 154 { |
155 const CookieNode *n1 = v1, *n2 = v2; | |
156 | |
1484
29d892265da0
domain comparison not case-sensitive
corvid <corvid@lavabit.com>
parents:
1483
diff
changeset
|
157 return dStrcasecmp(n1->domain, n2->domain); |
0 | 158 } |
159 | |
160 /* | |
161 * Compare function for searching a cookie node by domain | |
162 */ | |
51 | 163 static int Cookie_node_by_domain_cmp(const void *v1, const void *v2) |
0 | 164 { |
165 const CookieNode *node = v1; | |
166 const char *domain = v2; | |
167 | |
1484
29d892265da0
domain comparison not case-sensitive
corvid <corvid@lavabit.com>
parents:
1483
diff
changeset
|
168 return dStrcasecmp(node->domain, domain); |
0 | 169 } |
170 | |
171 /* | |
172 * Return a file pointer. If the file doesn't exist, try to create it, | |
173 * with the optional 'init_str' as its content. | |
174 */ | |
219 | 175 static FILE *Cookies_fopen(const char *filename, const char *mode, |
1503 | 176 const char *init_str) |
0 | 177 { |
178 FILE *F_in; | |
1200
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
179 int fd, rc; |
0 | 180 |
219 | 181 if ((F_in = fopen(filename, mode)) == NULL) { |
0 | 182 /* Create the file */ |
183 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); | |
184 if (fd != -1) { | |
1200
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
185 if (init_str) { |
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
186 rc = write(fd, init_str, strlen(init_str)); |
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
187 if (rc == -1) { |
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
188 MSG("Cookies: Could not write initial string to file %s: %s\n", |
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
189 filename, dStrerror(errno)); |
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
190 } |
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
191 } |
0 | 192 close(fd); |
193 | |
194 MSG("Created file: %s\n", filename); | |
219 | 195 F_in = fopen(filename, mode); |
0 | 196 } else { |
197 MSG("Could not create file: %s!\n", filename); | |
198 } | |
199 } | |
200 | |
174
67e98a1211f0
- Fixed a cookies-related dillo freeze bug happening at:
jcid
parents:
159
diff
changeset
|
201 if (F_in) { |
67e98a1211f0
- Fixed a cookies-related dillo freeze bug happening at:
jcid
parents:
159
diff
changeset
|
202 /* set close on exec */ |
67e98a1211f0
- Fixed a cookies-related dillo freeze bug happening at:
jcid
parents:
159
diff
changeset
|
203 fcntl(fileno(F_in), F_SETFD, FD_CLOEXEC | fcntl(fileno(F_in), F_GETFD)); |
67e98a1211f0
- Fixed a cookies-related dillo freeze bug happening at:
jcid
parents:
159
diff
changeset
|
204 } |
0 | 205 |
206 return F_in; | |
207 } | |
208 | |
209 static void Cookies_free_cookie(CookieData_t *cookie) | |
210 { | |
211 dFree(cookie->name); | |
212 dFree(cookie->value); | |
213 dFree(cookie->domain); | |
214 dFree(cookie->path); | |
215 dFree(cookie); | |
216 } | |
217 | |
218 /* | |
219 * Initialize the cookies module | |
1503 | 220 * (The 'disabled' variable is writeable only within Cookies_init) |
0 | 221 */ |
51 | 222 static void Cookies_init() |
0 | 223 { |
224 CookieData_t *cookie; | |
1200
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
225 char *filename, *rc = NULL; |
0 | 226 char line[LINE_MAXLEN]; |
227 #ifndef HAVE_LOCKF | |
228 struct flock lck; | |
229 #endif | |
230 | |
231 /* Default setting */ | |
232 disabled = TRUE; | |
233 | |
234 /* Read and parse the cookie control file (cookiesrc) */ | |
235 if (Cookie_control_init() != 0) { | |
236 MSG("Disabling cookies.\n"); | |
237 return; | |
238 } | |
239 | |
240 /* Get a stream for the cookies file */ | |
241 filename = dStrconcat(dGethomedir(), "/.dillo/cookies.txt", NULL); | |
219 | 242 file_stream = Cookies_fopen(filename, "r+", cookies_txt_header_str); |
0 | 243 |
244 dFree(filename); | |
245 | |
246 if (!file_stream) { | |
1495
a83b066cbcb3
rm support for ancient ~/.dillo/cookies file
corvid <corvid@lavabit.com>
parents:
1491
diff
changeset
|
247 MSG("ERROR: Can't open ~/.dillo/cookies.txt; disabling cookies\n"); |
0 | 248 return; |
249 } | |
250 | |
251 /* Try to get a lock from the file descriptor */ | |
252 #ifdef HAVE_LOCKF | |
253 disabled = (lockf(fileno(file_stream), F_TLOCK, 0) == -1); | |
254 #else /* POSIX lock */ | |
255 lck.l_start = 0; /* start at beginning of file */ | |
256 lck.l_len = 0; /* lock entire file */ | |
257 lck.l_type = F_WRLCK; | |
258 lck.l_whence = SEEK_SET; /* absolute offset */ | |
259 | |
260 disabled = (fcntl(fileno(file_stream), F_SETLK, &lck) == -1); | |
261 #endif | |
262 if (disabled) { | |
1495
a83b066cbcb3
rm support for ancient ~/.dillo/cookies file
corvid <corvid@lavabit.com>
parents:
1491
diff
changeset
|
263 MSG("The cookies file has a file lock; disabling cookies!\n"); |
0 | 264 fclose(file_stream); |
265 return; | |
266 } | |
267 | |
1495
a83b066cbcb3
rm support for ancient ~/.dillo/cookies file
corvid <corvid@lavabit.com>
parents:
1491
diff
changeset
|
268 MSG("Enabling cookies as per cookiesrc...\n"); |
0 | 269 |
270 cookies = dList_new(32); | |
271 | |
272 /* Get all lines in the file */ | |
273 while (!feof(file_stream)) { | |
274 line[0] = '\0'; | |
1200
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
275 rc = fgets(line, LINE_MAXLEN, file_stream); |
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
276 if (!rc && ferror(file_stream)) { |
1503 | 277 MSG("Error while reading from cookies.txt: %s\n", dStrerror(errno)); |
1200
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
278 break; /* bail out */ |
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
279 } |
0 | 280 |
281 /* Remove leading and trailing whitespaces */ | |
282 dStrstrip(line); | |
283 | |
284 if ((line[0] != '\0') && (line[0] != '#')) { | |
285 /* | |
286 * Split the row into pieces using a tab as the delimiter. | |
287 * pieces[0] The domain name | |
288 * pieces[1] TRUE/FALSE: is the domain a suffix, or a full domain? | |
289 * pieces[2] The path | |
1495
a83b066cbcb3
rm support for ancient ~/.dillo/cookies file
corvid <corvid@lavabit.com>
parents:
1491
diff
changeset
|
290 * pieces[3] TRUE/FALSE: is the cookie for secure use only? |
0 | 291 * pieces[4] Timestamp of expire date |
292 * pieces[5] Name of the cookie | |
293 * pieces[6] Value of the cookie | |
294 */ | |
295 CookieControlAction action; | |
296 char *piece; | |
297 char *line_marker = line; | |
298 | |
299 cookie = dNew0(CookieData_t, 1); | |
300 | |
301 cookie->session_only = FALSE; | |
302 cookie->domain = dStrdup(dStrsep(&line_marker, "\t")); | |
303 dStrsep(&line_marker, "\t"); /* we use domain always as sufix */ | |
304 cookie->path = dStrdup(dStrsep(&line_marker, "\t")); | |
305 piece = dStrsep(&line_marker, "\t"); | |
306 if (piece != NULL && piece[0] == 'T') | |
307 cookie->secure = TRUE; | |
308 piece = dStrsep(&line_marker, "\t"); | |
309 if (piece != NULL) | |
310 cookie->expires_at = (time_t) strtol(piece, NULL, 10); | |
311 cookie->name = dStrdup(dStrsep(&line_marker, "\t")); | |
1518
deccee022a42
handle nameless/valueless cookies in cookies.txt
corvid <corvid@lavabit.com>
parents:
1517
diff
changeset
|
312 cookie->value = dStrdup(line_marker ? line_marker : ""); |
0 | 313 |
314 if (!cookie->domain || cookie->domain[0] == '\0' || | |
315 !cookie->path || cookie->path[0] != '/' || | |
1518
deccee022a42
handle nameless/valueless cookies in cookies.txt
corvid <corvid@lavabit.com>
parents:
1517
diff
changeset
|
316 !cookie->name || !cookie->value) { |
0 | 317 MSG("Malformed line in cookies.txt file!\n"); |
318 Cookies_free_cookie(cookie); | |
319 continue; | |
320 } | |
321 | |
322 action = Cookies_control_check_domain(cookie->domain); | |
323 if (action == COOKIE_DENY) { | |
324 Cookies_free_cookie(cookie); | |
325 continue; | |
326 } else if (action == COOKIE_ACCEPT_SESSION) { | |
327 cookie->session_only = TRUE; | |
328 } | |
329 | |
330 /* Save cookie in memory */ | |
331 Cookies_add_cookie(cookie); | |
332 } | |
333 } | |
334 } | |
335 | |
336 /* | |
337 * Flush cookies to disk and free all the memory allocated. | |
338 */ | |
51 | 339 static void Cookies_save_and_free() |
0 | 340 { |
341 int i, fd; | |
342 CookieNode *node; | |
343 CookieData_t *cookie; | |
1512
bd36920f32d4
don't bother to save expired cookies
corvid <corvid@lavabit.com>
parents:
1510
diff
changeset
|
344 time_t now; |
0 | 345 |
346 #ifndef HAVE_LOCKF | |
347 struct flock lck; | |
348 #endif | |
349 | |
350 if (disabled) | |
351 return; | |
352 | |
1512
bd36920f32d4
don't bother to save expired cookies
corvid <corvid@lavabit.com>
parents:
1510
diff
changeset
|
353 now = time(NULL); |
bd36920f32d4
don't bother to save expired cookies
corvid <corvid@lavabit.com>
parents:
1510
diff
changeset
|
354 |
0 | 355 rewind(file_stream); |
356 fd = fileno(file_stream); | |
1200
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
357 if (ftruncate(fd, 0) == -1) |
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
358 MSG("Cookies: Truncate file stream failed: %s\n", dStrerror(errno)); |
454 | 359 fprintf(file_stream, "%s", cookies_txt_header_str); |
0 | 360 |
361 /* Iterate cookies per domain, saving and freeing */ | |
362 while ((node = dList_nth_data(cookies, 0))) { | |
363 for (i = 0; (cookie = dList_nth_data(node->dlist, i)); ++i) { | |
1512
bd36920f32d4
don't bother to save expired cookies
corvid <corvid@lavabit.com>
parents:
1510
diff
changeset
|
364 if (!cookie->session_only && (cookie->expires_at > now)) { |
0 | 365 fprintf(file_stream, "%s\tTRUE\t%s\t%s\t%ld\t%s\t%s\n", |
366 cookie->domain, | |
367 cookie->path, | |
368 cookie->secure ? "TRUE" : "FALSE", | |
369 (long)cookie->expires_at, | |
370 cookie->name, | |
371 cookie->value); | |
372 } | |
373 | |
374 Cookies_free_cookie(cookie); | |
375 } | |
376 dList_remove(cookies, node); | |
377 dFree(node->domain); | |
378 dList_free(node->dlist); | |
379 dFree(node); | |
380 } | |
381 | |
382 #ifdef HAVE_LOCKF | |
383 lockf(fd, F_ULOCK, 0); | |
384 #else /* POSIX file lock */ | |
385 lck.l_start = 0; /* start at beginning of file */ | |
386 lck.l_len = 0; /* lock entire file */ | |
387 lck.l_type = F_UNLCK; | |
388 lck.l_whence = SEEK_SET; /* absolute offset */ | |
389 | |
390 fcntl(fileno(file_stream), F_SETLKW, &lck); | |
391 #endif | |
392 fclose(file_stream); | |
393 } | |
394 | |
395 /* | |
396 * Take a months name and return a number between 1-12. | |
397 * E.g. 'April' -> 4 | |
398 */ | |
399 static int Cookies_get_month(const char *month_name) | |
400 { | |
1500
335f1b3692c9
timestamps a little less strict
corvid <corvid@lavabit.com>
parents:
1499
diff
changeset
|
401 static const char *const months[] = |
335f1b3692c9
timestamps a little less strict
corvid <corvid@lavabit.com>
parents:
1499
diff
changeset
|
402 { "", |
335f1b3692c9
timestamps a little less strict
corvid <corvid@lavabit.com>
parents:
1499
diff
changeset
|
403 "Jan", "Feb", "Mar", |
335f1b3692c9
timestamps a little less strict
corvid <corvid@lavabit.com>
parents:
1499
diff
changeset
|
404 "Apr", "May", "Jun", |
335f1b3692c9
timestamps a little less strict
corvid <corvid@lavabit.com>
parents:
1499
diff
changeset
|
405 "Jul", "Aug", "Sep", |
335f1b3692c9
timestamps a little less strict
corvid <corvid@lavabit.com>
parents:
1499
diff
changeset
|
406 "Oct", "Nov", "Dec" |
335f1b3692c9
timestamps a little less strict
corvid <corvid@lavabit.com>
parents:
1499
diff
changeset
|
407 }; |
0 | 408 int i; |
409 | |
410 for (i = 1; i <= 12; i++) { | |
411 if (!dStrncasecmp(months[i], month_name, 3)) | |
412 return i; | |
413 } | |
414 return 0; | |
415 } | |
416 | |
417 /* | |
418 * Return a local timestamp from a GMT date string | |
419 * Accept: RFC-1123 | RFC-850 | ANSI asctime | Old Netscape format. | |
420 * | |
421 * Wdy, DD-Mon-YY HH:MM:SS GMT | |
422 * Wdy, DD-Mon-YYYY HH:MM:SS GMT | |
423 * Weekday, DD-Mon-YY HH:MM:SS GMT | |
424 * Weekday, DD-Mon-YYYY HH:MM:SS GMT | |
425 * Tue May 21 13:46:22 1991\n | |
426 * Tue May 21 13:46:22 1991 | |
427 * | |
1500
335f1b3692c9
timestamps a little less strict
corvid <corvid@lavabit.com>
parents:
1499
diff
changeset
|
428 * Let's add: |
335f1b3692c9
timestamps a little less strict
corvid <corvid@lavabit.com>
parents:
1499
diff
changeset
|
429 * Mon Jan 11 08:00:00 2010 GMT |
335f1b3692c9
timestamps a little less strict
corvid <corvid@lavabit.com>
parents:
1499
diff
changeset
|
430 * |
0 | 431 * (return 0 on malformed date string syntax) |
1500
335f1b3692c9
timestamps a little less strict
corvid <corvid@lavabit.com>
parents:
1499
diff
changeset
|
432 * |
335f1b3692c9
timestamps a little less strict
corvid <corvid@lavabit.com>
parents:
1499
diff
changeset
|
433 * NOTE that the draft spec wants user agents to be more flexible in what |
335f1b3692c9
timestamps a little less strict
corvid <corvid@lavabit.com>
parents:
1499
diff
changeset
|
434 * they accept. For now, let's hack in special cases when they're encountered. |
335f1b3692c9
timestamps a little less strict
corvid <corvid@lavabit.com>
parents:
1499
diff
changeset
|
435 * Why? Because this function is currently understandable, and I don't want to |
335f1b3692c9
timestamps a little less strict
corvid <corvid@lavabit.com>
parents:
1499
diff
changeset
|
436 * abandon that (or at best decrease that -- see section 5.1.1) until there |
335f1b3692c9
timestamps a little less strict
corvid <corvid@lavabit.com>
parents:
1499
diff
changeset
|
437 * is known to be good reason. |
0 | 438 */ |
439 static time_t Cookies_create_timestamp(const char *expires) | |
440 { | |
441 time_t ret; | |
442 int day, month, year, hour, minutes, seconds; | |
443 char *cp; | |
1500
335f1b3692c9
timestamps a little less strict
corvid <corvid@lavabit.com>
parents:
1499
diff
changeset
|
444 const char *const E_msg = |
0 | 445 "Expire date is malformed!\n" |
446 " (should be RFC-1123 | RFC-850 | ANSI asctime)\n" | |
1500
335f1b3692c9
timestamps a little less strict
corvid <corvid@lavabit.com>
parents:
1499
diff
changeset
|
447 " Discarding cookie: "; |
0 | 448 |
449 cp = strchr(expires, ','); | |
1500
335f1b3692c9
timestamps a little less strict
corvid <corvid@lavabit.com>
parents:
1499
diff
changeset
|
450 if (!cp && strlen(expires)>20 && expires[13] == ':' && expires[16] == ':') { |
0 | 451 /* Looks like ANSI asctime format... */ |
452 cp = (char *)expires; | |
453 day = strtol(cp + 8, NULL, 10); /* day */ | |
454 month = Cookies_get_month(cp + 4); /* month */ | |
455 year = strtol(cp + 20, NULL, 10); /* year */ | |
456 hour = strtol(cp + 11, NULL, 10); /* hour */ | |
457 minutes = strtol(cp + 14, NULL, 10); /* minutes */ | |
458 seconds = strtol(cp + 17, NULL, 10); /* seconds */ | |
459 | |
460 } else if (cp && (cp - expires == 3 || cp - expires > 5) && | |
461 (strlen(cp) == 24 || strlen(cp) == 26)) { | |
462 /* RFC-1123 | RFC-850 format | Old Netscape format */ | |
463 day = strtol(cp + 2, NULL, 10); | |
464 month = Cookies_get_month(cp + 5); | |
465 year = strtol(cp + 9, &cp, 10); | |
368 | 466 /* TODO: tricky, because two digits for year IS ambiguous! */ |
0 | 467 year += (year < 70) ? 2000 : ((year < 100) ? 1900 : 0); |
468 hour = strtol(cp + 1, NULL, 10); | |
469 minutes = strtol(cp + 4, NULL, 10); | |
470 seconds = strtol(cp + 7, NULL, 10); | |
471 | |
472 } else { | |
473 MSG("%s%s\n", E_msg, expires); | |
474 return (time_t) 0; | |
475 } | |
476 | |
477 /* Error checks --this may be overkill */ | |
1127 | 478 if (!(day > 0 && day < 32 && month > 0 && month < 13 && year >= 1970 && |
0 | 479 hour >= 0 && hour < 24 && minutes >= 0 && minutes < 60 && |
480 seconds >= 0 && seconds < 60)) { | |
481 MSG("%s%s\n", E_msg, expires); | |
482 return (time_t) 0; | |
483 } | |
484 | |
485 /* Calculate local timestamp. | |
486 * [stolen from Lynx... (http://lynx.browser.org)] */ | |
487 month -= 3; | |
488 if (month < 0) { | |
489 month += 12; | |
490 year--; | |
491 } | |
492 | |
493 day += (year - 1968) * 1461 / 4; | |
494 day += ((((month * 153) + 2) / 5) - 672); | |
495 ret = (time_t)((day * 60 * 60 * 24) + | |
496 (hour * 60 * 60) + | |
497 (minutes * 60) + | |
498 seconds); | |
499 | |
1508 | 500 /* handle overflow */ |
501 if (year >= 1970 && ret < 0) | |
502 ret = DILLO_TIME_MAX; | |
503 | |
0 | 504 return ret; |
505 } | |
506 | |
1504
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
507 /* |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
508 * Remove the least recently used cookie in the list. |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
509 */ |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
510 static void Cookies_remove_LRU(Dlist *cookies) |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
511 { |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
512 int n = dList_length(cookies); |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
513 |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
514 if (n > 0) { |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
515 int i; |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
516 CookieData_t *lru = dList_nth_data(cookies, 0); |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
517 |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
518 for (i = 1; i < n; i++) { |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
519 CookieData_t *curr = dList_nth_data(cookies, i); |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
520 |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
521 if (curr->last_used < lru->last_used) |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
522 lru = curr; |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
523 } |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
524 dList_remove(cookies, lru); |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
525 MSG("removed LRU cookie \'%s=%s\'\n", lru->name, lru->value); |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
526 Cookies_free_cookie(lru); |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
527 } |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
528 } |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
529 |
0 | 530 static void Cookies_add_cookie(CookieData_t *cookie) |
531 { | |
532 Dlist *domain_cookies; | |
533 CookieData_t *c; | |
534 CookieNode *node; | |
535 | |
536 node = dList_find_sorted(cookies, cookie->domain,Cookie_node_by_domain_cmp); | |
537 domain_cookies = (node) ? node->dlist : NULL; | |
538 | |
539 if (domain_cookies) { | |
1482
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset
|
540 /* Remove any cookies with the same name and path */ |
1519
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
541 while ((c = dList_find_custom(domain_cookies, cookie, Cookies_cmp))) { |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
542 dList_remove(domain_cookies, c); |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
543 Cookies_free_cookie(c); |
1482
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset
|
544 } |
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset
|
545 |
0 | 546 /* Respect the limit of 20 cookies per domain */ |
547 if (dList_length(domain_cookies) >= 20) { | |
548 MSG("There are too many cookies for this domain (%s)\n", | |
549 cookie->domain); | |
1504
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
550 Cookies_remove_LRU(domain_cookies); |
0 | 551 } |
1482
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset
|
552 } |
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset
|
553 |
1503 | 554 /* Don't add an expired cookie. Whether expiring now == expired, exactly, |
555 * is arguable, but we definitely do not want to add a Max-Age=0 cookie. | |
556 */ | |
1482
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset
|
557 if (cookie->expires_at <= time(NULL)) { |
1503 | 558 MSG("Goodbye, expired cookie %s=%s d:%s p:%s\n", cookie->name, |
559 cookie->value, cookie->domain, cookie->path); | |
1482
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset
|
560 Cookies_free_cookie(cookie); |
0 | 561 } else { |
1519
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
562 cookie->last_used = cookies_use_counter++; |
0 | 563 |
1519
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
564 /* add cookie to domain list */ |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
565 if (!domain_cookies) { |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
566 domain_cookies = dList_new(5); |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
567 dList_append(domain_cookies, cookie); |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
568 node = dNew(CookieNode, 1); |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
569 node->domain = dStrdup(cookie->domain); |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
570 node->dlist = domain_cookies; |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
571 dList_insert_sorted(cookies, node, Cookie_node_cmp); |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
572 } else { |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
573 dList_append(domain_cookies, cookie); |
0 | 574 } |
575 } | |
1519
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
576 if (domain_cookies && (dList_length(domain_cookies) == 0)) { |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
577 dList_remove(cookies, node); |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
578 dFree(node->domain); |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
579 dList_free(domain_cookies); |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
580 dFree(node); |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
581 } |
0 | 582 } |
583 | |
584 /* | |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
585 * Return the attribute that is present at *cookie_str. |
0 | 586 */ |
587 static char *Cookies_parse_attr(char **cookie_str) | |
588 { | |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
589 char *str; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
590 uint_t len; |
0 | 591 |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
592 while (dIsspace(**cookie_str)) |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
593 (*cookie_str)++; |
0 | 594 |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
595 str = *cookie_str; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
596 /* find '=' at end of attr, ';' after attr/val pair, '\0' end of string */ |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
597 len = strcspn(str, "=;"); |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
598 *cookie_str += len; |
0 | 599 |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
600 while (len && (str[len - 1] == ' ' || str[len - 1] == '\t')) |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
601 len--; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
602 return dStrndup(str, len); |
0 | 603 } |
604 | |
605 /* | |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
606 * Get the value in *cookie_str. |
0 | 607 */ |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
608 static char *Cookies_parse_value(char **cookie_str) |
0 | 609 { |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
610 uint_t len; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
611 char *str; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
612 |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
613 if (**cookie_str == '=') { |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
614 (*cookie_str)++; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
615 while (dIsspace(**cookie_str)) |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
616 (*cookie_str)++; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
617 |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
618 str = *cookie_str; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
619 /* finds ';' after attr/val pair or '\0' at end of string */ |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
620 len = strcspn(str, ";"); |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
621 *cookie_str += len; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
622 |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
623 while (len && (str[len - 1] == ' ' || str[len - 1] == '\t')) |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
624 len--; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
625 } else { |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
626 str = *cookie_str; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
627 len = 0; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
628 } |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
629 return dStrndup(str, len); |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
630 } |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
631 |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
632 /* |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
633 * Advance past any value |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
634 */ |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
635 static void Cookies_eat_value(char **cookie_str) |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
636 { |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
637 if (**cookie_str == '=') |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
638 *cookie_str += strcspn(*cookie_str, ";"); |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
639 } |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
640 |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
641 /* |
1522
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
642 * Handle Expires attribute. |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
643 * Note that this CAN MODIFY the value string. |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
644 */ |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
645 static time_t Cookies_expires_attr(char *value, const char *server_date) |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
646 { |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
647 time_t exptime; |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
648 |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
649 if (*value == '"' && value[strlen(value) - 1] == '"') { |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
650 /* In this one case, pay attention to quotes */ |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
651 value[strlen(value) - 1] = '\0'; |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
652 value++; |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
653 } |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
654 exptime = Cookies_create_timestamp(value); |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
655 if (exptime && server_date) { |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
656 time_t server_time = Cookies_create_timestamp(server_date); |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
657 |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
658 if (server_time) { |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
659 time_t now = time(NULL); |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
660 time_t client_time = exptime + now - server_time; |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
661 |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
662 if (server_time == exptime) { |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
663 exptime = now; |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
664 } else if ((exptime > now) == (client_time > now)) { |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
665 exptime = client_time; |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
666 } else { |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
667 /* Don't want to wrap around at the extremes of representable |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
668 * values thanks to clock skew. |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
669 */ |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
670 MSG("At %ld, %ld was trying to turn into %ld\n", |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
671 (long)now, (long)exptime, |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
672 (long)client_time); |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
673 } |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
674 } |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
675 } |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
676 return exptime; |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
677 } |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
678 |
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
679 /* |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
680 * Parse cookie. A cookie might look something like: |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
681 * "Name=Val; Domain=example.com; Max-Age=3600; HttpOnly" |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
682 */ |
1501
6fd1c55d8022
cookies use server date to interpret Expires attr
corvid <corvid@lavabit.com>
parents:
1500
diff
changeset
|
683 static CookieData_t *Cookies_parse(char *cookie_str, const char *server_date) |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
684 { |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
685 CookieData_t *cookie = NULL; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
686 char *str = cookie_str; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
687 bool_t first_attr = TRUE; |
0 | 688 bool_t max_age = FALSE; |
1482
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset
|
689 bool_t expires = FALSE; |
0 | 690 |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
691 /* Iterate until there is nothing left of the string */ |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
692 while (*str) { |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
693 char *attr; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
694 char *value; |
0 | 695 |
696 /* Get attribute */ | |
697 attr = Cookies_parse_attr(&str); | |
698 | |
699 /* Get the value for the attribute and store it */ | |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
700 if (first_attr) { |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
701 if (!*str && !*attr) { |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
702 dFree(attr); |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
703 return NULL; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
704 } |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
705 cookie = dNew0(CookieData_t, 1); |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
706 /* let's arbitrarily choose a year for now */ |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
707 cookie->expires_at = time(NULL) + 60 * 60 * 24 * 365; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
708 |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
709 if (*str != '=') { |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
710 /* NOTE it seems possible that the Working Group will decide |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
711 * against allowing nameless cookies. |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
712 */ |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
713 cookie->name = dStrdup(""); |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
714 cookie->value = attr; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
715 } else { |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
716 cookie->name = dStrdup(attr); |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
717 cookie->value = Cookies_parse_value(&str); |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
718 } |
0 | 719 } else if (dStrcasecmp(attr, "Path") == 0) { |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
720 value = Cookies_parse_value(&str); |
1491
a10148c0bcab
cookies don't leak extra domain/path attrs
corvid <corvid@lavabit.com>
parents:
1490
diff
changeset
|
721 dFree(cookie->path); |
0 | 722 cookie->path = value; |
723 } else if (dStrcasecmp(attr, "Domain") == 0) { | |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
724 value = Cookies_parse_value(&str); |
1491
a10148c0bcab
cookies don't leak extra domain/path attrs
corvid <corvid@lavabit.com>
parents:
1490
diff
changeset
|
725 dFree(cookie->domain); |
0 | 726 cookie->domain = value; |
727 } else if (dStrcasecmp(attr, "Max-Age") == 0) { | |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
728 value = Cookies_parse_value(&str); |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
729 if (isdigit(*value) || *value == '-') { |
1508 | 730 time_t now = time(NULL); |
731 long age = strtol(value, NULL, 10); | |
732 | |
733 cookie->expires_at = now + age; | |
734 if (age > 0 && cookie->expires_at < 0) { | |
735 /* handle overflow */ | |
736 cookie->expires_at = DILLO_TIME_MAX; | |
737 } | |
1482
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset
|
738 expires = max_age = TRUE; |
0 | 739 } |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
740 dFree(value); |
0 | 741 } else if (dStrcasecmp(attr, "Expires") == 0) { |
1482
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset
|
742 if (!max_age) { |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
743 value = Cookies_parse_value(&str); |
1522
85062b64ae9d
cookies allow Expires attr's value to be quoted.
corvid <corvid@lavabit.com>
parents:
1519
diff
changeset
|
744 cookie->expires_at = Cookies_expires_attr(value, server_date); |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
745 expires = TRUE; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
746 dFree(value); |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
747 MSG("Expires in %ld seconds, at %s", |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
748 (long)cookie->expires_at - time(NULL), |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
749 ctime(&cookie->expires_at)); |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
750 |
0 | 751 } |
752 } else if (dStrcasecmp(attr, "Secure") == 0) { | |
753 cookie->secure = TRUE; | |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
754 Cookies_eat_value(&str); |
418
b7265ec32e33
- Allow login to wikipedia by ignoring the HttpOnly attribute (cookies)
jcid
parents:
379
diff
changeset
|
755 } else if (dStrcasecmp(attr, "HttpOnly") == 0) { |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
756 Cookies_eat_value(&str); |
0 | 757 } else { |
379 | 758 MSG("Cookie contains unknown attribute: '%s'\n", attr); |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
759 Cookies_eat_value(&str); |
0 | 760 } |
761 | |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
762 if (first_attr) |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
763 first_attr = FALSE; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
764 else |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
765 dFree(attr); |
0 | 766 |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
767 if (*str == ';') |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
768 str++; |
159
70da40b41e3a
- Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset
|
769 } |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
770 cookie->session_only = expires == FALSE; |
159
70da40b41e3a
- Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset
|
771 return cookie; |
0 | 772 } |
773 | |
774 /* | |
775 * Compare cookies by name and path (return 0 if equal) | |
776 */ | |
777 static int Cookies_cmp(const void *a, const void *b) | |
778 { | |
779 const CookieData_t *ca = a, *cb = b; | |
780 int ret; | |
781 | |
782 if (!(ret = strcmp(ca->name, cb->name))) | |
783 ret = strcmp(ca->path, cb->path); | |
784 return ret; | |
785 } | |
786 | |
787 /* | |
1517
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
788 * Is the domain an IP address? |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
789 */ |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
790 static bool_t Cookies_domain_is_ip(const char *domain) |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
791 { |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
792 uint_t len; |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
793 |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
794 if (!domain) |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
795 return FALSE; |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
796 |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
797 len = strlen(domain); |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
798 |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
799 if (len == strspn(domain, "0123456789.")) { |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
800 MSG("an IPv4 address\n"); |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
801 return TRUE; |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
802 } |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
803 if (*domain == '[' && |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
804 (len == strspn(domain, "0123456789abcdefABCDEF:.[]"))) { |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
805 /* The precise format is shown in section 3.2.2 of rfc 3986 */ |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
806 MSG("an IPv6 address\n"); |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
807 return TRUE; |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
808 } |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
809 return FALSE; |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
810 } |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
811 |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
812 /* |
1497
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
813 * Check whether url_path path-matches cookie_path |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
814 * |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
815 * Note different user agents apparently vary in path-matching behaviour, |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
816 * but this is the recommended method at the moment. |
1486 | 817 */ |
1497
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
818 static bool_t Cookies_path_matches(const char *url_path, |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
819 const char *cookie_path) |
1486 | 820 { |
821 bool_t ret = TRUE; | |
822 | |
1497
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
823 if (!url_path || !cookie_path) { |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
824 ret = FALSE; |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
825 } else { |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
826 uint_t c_len = strlen(cookie_path); |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
827 uint_t u_len = strlen(url_path); |
1486 | 828 |
1497
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
829 ret = (!strncmp(cookie_path, url_path, c_len) && |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
830 ((c_len == u_len) || |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
831 (c_len > 0 && cookie_path[c_len - 1] == '/') || |
1505 | 832 (url_path[c_len] == '/'))); |
1497
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
833 } |
1486 | 834 return ret; |
835 } | |
836 | |
837 /* | |
1497
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
838 * If cookie path is not properly set, remedy that. |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
839 */ |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
840 static void Cookies_validate_path(CookieData_t *cookie, const char *url_path) |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
841 { |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
842 if (!cookie->path || cookie->path[0] != '/') { |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
843 dFree(cookie->path); |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
844 |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
845 if (url_path) { |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
846 uint_t len = strlen(url_path); |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
847 |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
848 while (len && url_path[len] != '/') |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
849 len--; |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
850 cookie->path = dStrndup(url_path, len ? len : 1); |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
851 } else { |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
852 cookie->path = dStrdup("/"); |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
853 } |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
854 } |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
855 } |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
856 |
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
857 /* |
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
858 * Check whether host name A domain-matches host name B. |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
859 */ |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
860 static bool_t Cookies_domain_matches(char *A, char *B) |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
861 { |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
862 int diff; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
863 |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
864 if (!A || !*A || !B || !*B) |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
865 return FALSE; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
866 |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
867 if (*B == '.') |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
868 B++; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
869 |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
870 /* Should we concern ourselves with trailing dots in matching (here or |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
871 * elsewhere)? The HTTP State people have found that most user agents |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
872 * don't, so: No. |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
873 */ |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
874 |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
875 if (!dStrcasecmp(A, B)) |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
876 return TRUE; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
877 |
1517
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
878 if (Cookies_domain_is_ip(B)) |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
879 return FALSE; |
773b44547931
cookies: be more robust in rejecting IP addr partial matches
corvid <corvid@lavabit.com>
parents:
1516
diff
changeset
|
880 |
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
881 diff = strlen(A) - strlen(B); |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
882 |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
883 if (diff > 0) { |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
884 /* B is the tail of A, and the match is preceded by a '.' */ |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
885 return (dStrcasecmp(A + diff, B) == 0 && A[diff - 1] == '.'); |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
886 } else { |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
887 return FALSE; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
888 } |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
889 } |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
890 |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
891 /* |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
892 * Based on the host, how many internal dots do we need in a cookie domain |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
893 * to make it valid? e.g., "org" is not on the list, so dillo.org is a safe |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
894 * cookie domain, but "uk" is on the list, so ac.uk is not safe. |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
895 * |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
896 * This is imperfect, but it's something. Specifically, checking for these |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
897 * TLDs is the solution that Konqueror used once upon a time, according to |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
898 * reports. |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
899 */ |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
900 static uint_t Cookies_internal_dots_required(const char *host) |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
901 { |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
902 uint_t ret = 1; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
903 |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
904 if (host) { |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
905 int start, after, tld_len; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
906 |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
907 /* We may be able to trust the format of the host string more than |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
908 * I am here. Trailing dots and no dots are real possibilities, though. |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
909 */ |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
910 after = strlen(host); |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
911 if (after > 0 && host[after - 1] == '.') |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
912 after--; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
913 start = after; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
914 while (start > 0 && host[start - 1] != '.') |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
915 start--; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
916 tld_len = after - start; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
917 |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
918 if (tld_len > 0) { |
1510 | 919 /* These TLDs were chosen by examining the current publicsuffix list |
920 * in January 2010 and picking out those where it was simplest for | |
921 * them to describe the situation by beginning with a "*.[tld]" rule. | |
922 */ | |
923 const char *const tlds[] = {"ar","au","bd","bn","bt","ck","cy","do", | |
924 "eg","er","et","fj","fk","gt","gu","id", | |
925 "il","jm","ke","kh","kw","ml","mm","mt", | |
926 "mz","ni","np","nz","om","pg","py","qa", | |
927 "sv","tr","uk","uy","ve","ye","yu","za", | |
928 "zm","zw"}; | |
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
929 uint_t i, tld_num = sizeof(tlds) / sizeof(tlds[0]); |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
930 |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
931 for (i = 0; i < tld_num; i++) { |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
932 if (strlen(tlds[i]) == (uint_t) tld_len && |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
933 !dStrncasecmp(tlds[i], host + start, tld_len)) { |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
934 MSG("TLD code matched %s\n", tlds[i]); |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
935 ret++; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
936 break; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
937 } |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
938 } |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
939 } |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
940 } |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
941 return ret; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
942 } |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
943 |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
944 /* |
0 | 945 * Validate cookies domain against some security checks. |
946 */ | |
1497
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
947 static bool_t Cookies_validate_domain(CookieData_t *cookie, char *host) |
0 | 948 { |
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
949 uint_t i, internal_dots; |
0 | 950 |
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
951 if (!cookie->domain) { |
0 | 952 cookie->domain = dStrdup(host); |
953 return TRUE; | |
954 } | |
955 | |
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
956 if (cookie->domain[0] != '.' && !Cookies_domain_is_ip(cookie->domain)) { |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
957 char *d = dStrconcat(".", cookie->domain, NULL); |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
958 dFree(cookie->domain); |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
959 cookie->domain = d; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
960 } |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
961 |
1488 | 962 if (!Cookies_domain_matches(host, cookie->domain)) |
963 return FALSE; | |
964 | |
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
965 internal_dots = 0; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
966 for (i = 1; i < strlen(cookie->domain) - 1; i++) { |
0 | 967 if (cookie->domain[i] == '.') |
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
968 internal_dots++; |
0 | 969 } |
970 | |
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
971 /* All of this dots business is a weak hack. |
1488 | 972 * TODO: accept the publicsuffix.org list as an optional external file. |
973 */ | |
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
974 if (internal_dots < Cookies_internal_dots_required(host)) { |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
975 MSG("not enough dots in %s\n", cookie->domain); |
0 | 976 return FALSE; |
977 } | |
978 | |
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
979 MSG("host %s and domain %s is all right\n", host, cookie->domain); |
0 | 980 return TRUE; |
981 } | |
982 | |
983 /* | |
984 * Set the value corresponding to the cookie string | |
985 */ | |
51 | 986 static void Cookies_set(char *cookie_string, char *url_host, |
1501
6fd1c55d8022
cookies use server date to interpret Expires attr
corvid <corvid@lavabit.com>
parents:
1500
diff
changeset
|
987 char *url_path, char *server_date) |
0 | 988 { |
989 CookieControlAction action; | |
990 CookieData_t *cookie; | |
991 | |
992 if (disabled) | |
993 return; | |
994 | |
995 action = Cookies_control_check_domain(url_host); | |
996 if (action == COOKIE_DENY) { | |
997 MSG("denied SET for %s\n", url_host); | |
998 return; | |
999 } | |
1000 | |
1506
408f86fed820
make cookies very chatty for now
corvid <corvid@lavabit.com>
parents:
1505
diff
changeset
|
1001 MSG("%s SETTING: %s\n", url_host, cookie_string); |
1482
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset
|
1002 |
1501
6fd1c55d8022
cookies use server date to interpret Expires attr
corvid <corvid@lavabit.com>
parents:
1500
diff
changeset
|
1003 if ((cookie = Cookies_parse(cookie_string, server_date))) { |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
1004 if (Cookies_validate_domain(cookie, url_host)) { |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
1005 Cookies_validate_path(cookie, url_path); |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
1006 if (action == COOKIE_ACCEPT_SESSION) |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
1007 cookie->session_only = TRUE; |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
1008 Cookies_add_cookie(cookie); |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
1009 } else { |
1503 | 1010 MSG("Rejecting cookie for domain %s from host %s path %s\n", |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
1011 cookie->domain, url_host, url_path); |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
1012 Cookies_free_cookie(cookie); |
0 | 1013 } |
1014 } | |
1015 } | |
1016 | |
1017 /* | |
1503 | 1018 * Compare the cookie with the supplied data to see whether it matches |
0 | 1019 */ |
1497
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
1020 static bool_t Cookies_match(CookieData_t *cookie, const char *url_path, |
1496
5bec8ce33a42
cookies: rm version, comment, comment url, port, Cookie2
corvid <corvid@lavabit.com>
parents:
1495
diff
changeset
|
1021 bool_t is_ssl) |
0 | 1022 { |
1023 /* Insecure cookies matches both secure and insecure urls, secure | |
1024 cookies matches only secure urls */ | |
1025 if (cookie->secure && !is_ssl) | |
1026 return FALSE; | |
1027 | |
1497
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset
|
1028 if (!Cookies_path_matches(url_path, cookie->path)) |
0 | 1029 return FALSE; |
1030 | |
1031 /* It's a match */ | |
1032 return TRUE; | |
1033 } | |
1034 | |
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1035 static void Cookies_add_matching_cookies(const char *domain, |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1036 const char *url_path, |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1037 Dlist *matching_cookies, |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1038 bool_t is_ssl) |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1039 { |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1040 CookieNode *node = dList_find_sorted(cookies, domain, |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1041 Cookie_node_by_domain_cmp); |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1042 if (node) { |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1043 int i; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1044 CookieData_t *cookie; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1045 Dlist *domain_cookies = node->dlist; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1046 |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1047 for (i = 0; (cookie = dList_nth_data(domain_cookies, i)); ++i) { |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1048 /* Remove expired cookie. */ |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1049 if (cookie->expires_at < time(NULL)) { |
1503 | 1050 MSG("Goodbye, expired cookie %s=%s d:%s p:%s\n", cookie->name, |
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1051 cookie->value, cookie->domain, cookie->path); |
1519
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
1052 dList_remove(domain_cookies, cookie); |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
1053 Cookies_free_cookie(cookie); |
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1054 --i; continue; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1055 } |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1056 /* Check if the cookie matches the requesting URL */ |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1057 if (Cookies_match(cookie, url_path, is_ssl)) { |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1058 int j; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1059 CookieData_t *curr; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1060 uint_t path_length = strlen(cookie->path); |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1061 |
1504
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
1062 cookie->last_used = cookies_use_counter; |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
1063 |
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1064 /* Longest cookies go first */ |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1065 for (j = 0; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1066 (curr = dList_nth_data(matching_cookies, j)) && |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1067 strlen(curr->path) >= path_length; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1068 j++) ; |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1069 dList_insert_pos(matching_cookies, cookie, j); |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1070 } |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1071 } |
1519
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
1072 |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
1073 if (dList_length(domain_cookies) == 0) { |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
1074 dList_remove(cookies, node); |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
1075 dFree(node->domain); |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
1076 dList_free(domain_cookies); |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
1077 dFree(node); |
6fcb13a8b680
Be careful not to delete domain_cookies while still using it.
corvid <corvid@lavabit.com>
parents:
1518
diff
changeset
|
1078 } |
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1079 } |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1080 } |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1081 |
0 | 1082 /* |
1083 * Return a string that contains all relevant cookies as headers. | |
1084 */ | |
51 | 1085 static char *Cookies_get(char *url_host, char *url_path, |
1496
5bec8ce33a42
cookies: rm version, comment, comment url, port, Cookie2
corvid <corvid@lavabit.com>
parents:
1495
diff
changeset
|
1086 char *url_scheme) |
0 | 1087 { |
1496
5bec8ce33a42
cookies: rm version, comment, comment url, port, Cookie2
corvid <corvid@lavabit.com>
parents:
1495
diff
changeset
|
1088 char *domain_str, *str; |
0 | 1089 CookieData_t *cookie; |
1090 Dlist *matching_cookies; | |
1091 bool_t is_ssl; | |
1092 Dstr *cookie_dstring; | |
1093 int i; | |
1094 | |
1095 if (disabled) | |
1096 return dStrdup(""); | |
1097 | |
1098 matching_cookies = dList_new(8); | |
1099 | |
1100 /* Check if the protocol is secure or not */ | |
1101 is_ssl = (!dStrcasecmp(url_scheme, "https")); | |
1102 | |
1103 for (domain_str = (char *) url_host; | |
1104 domain_str != NULL && *domain_str; | |
1105 domain_str = strchr(domain_str+1, '.')) { | |
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1106 Cookies_add_matching_cookies(domain_str, url_path, matching_cookies, |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1107 is_ssl); |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1108 } |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1109 if (!Cookies_domain_is_ip(url_host)) { |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1110 domain_str = dStrconcat(".", url_host, NULL); |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1111 Cookies_add_matching_cookies(domain_str, url_path, matching_cookies, |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1112 is_ssl); |
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset
|
1113 dFree(domain_str); |
0 | 1114 } |
1115 | |
1116 /* Found the cookies, now make the string */ | |
1117 cookie_dstring = dStr_new(""); | |
1118 if (dList_length(matching_cookies) > 0) { | |
1119 | |
1120 dStr_sprintfa(cookie_dstring, "Cookie: "); | |
1121 | |
1122 for (i = 0; (cookie = dList_nth_data(matching_cookies, i)); ++i) { | |
1123 dStr_sprintfa(cookie_dstring, | |
1499
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
1124 "%s%s%s", |
1803fe44871e
cookies follow draft spec's simple parsing
corvid <corvid@lavabit.com>
parents:
1498
diff
changeset
|
1125 cookie->name, *cookie->name ? "=" : "", cookie->value); |
0 | 1126 dStr_append(cookie_dstring, |
1127 dList_length(matching_cookies) > i + 1 ? "; " : "\r\n"); | |
1128 } | |
1129 } | |
1130 | |
1131 dList_free(matching_cookies); | |
1132 str = cookie_dstring->str; | |
1133 dStr_free(cookie_dstring, FALSE); | |
1504
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
1134 |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
1135 if (*str) |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
1136 cookies_use_counter++; |
d10adebe95fb
when too many cookies for domain, rm least recently used
corvid <corvid@lavabit.com>
parents:
1503
diff
changeset
|
1137 |
1506
408f86fed820
make cookies very chatty for now
corvid <corvid@lavabit.com>
parents:
1505
diff
changeset
|
1138 MSG("%s GETTING: %s\n", url_host, str); |
0 | 1139 return str; |
1140 } | |
1141 | |
1142 /* ------------------------------------------------------------- | |
1143 * Access control routines | |
1144 * ------------------------------------------------------------- */ | |
1145 | |
1146 | |
1147 /* | |
1148 * Get the cookie control rules (from cookiesrc). | |
1149 * Return value: | |
1150 * 0 = Parsed OK, with cookies enabled | |
1151 * 1 = Parsed OK, with cookies disabled | |
1152 * 2 = Can't open the control file | |
1153 */ | |
1154 static int Cookie_control_init(void) | |
1155 { | |
1156 CookieControl cc; | |
1157 FILE *stream; | |
1200
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
1158 char *filename, *rc; |
0 | 1159 char line[LINE_MAXLEN]; |
1160 char domain[LINE_MAXLEN]; | |
1161 char rule[LINE_MAXLEN]; | |
1162 int i, j; | |
1163 bool_t enabled = FALSE; | |
1164 | |
1165 /* Get a file pointer */ | |
1166 filename = dStrconcat(dGethomedir(), "/.dillo/cookiesrc", NULL); | |
219 | 1167 stream = Cookies_fopen(filename, "r", "DEFAULT DENY\n"); |
0 | 1168 dFree(filename); |
1169 | |
1170 if (!stream) | |
1171 return 2; | |
1172 | |
1173 /* Get all lines in the file */ | |
1174 while (!feof(stream)) { | |
1175 line[0] = '\0'; | |
1200
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
1176 rc = fgets(line, LINE_MAXLEN, stream); |
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
1177 if (!rc && ferror(stream)) { |
1503 | 1178 MSG("Error while reading rule from cookiesrc: %s\n", |
1200
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
1179 dStrerror(errno)); |
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
1180 break; /* bail out */ |
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset
|
1181 } |
0 | 1182 |
1183 /* Remove leading and trailing whitespaces */ | |
1184 dStrstrip(line); | |
1185 | |
1186 if (line[0] != '\0' && line[0] != '#') { | |
1187 i = 0; | |
1188 j = 0; | |
1189 | |
1190 /* Get the domain */ | |
1221
f34b803b8639
Handle signed chars. Aadded dIsspace() and dIsalnum() to dlib
Jorge Arellano Cid <jcid@dillo.org>
parents:
1201
diff
changeset
|
1191 while (line[i] != '\0' && !dIsspace(line[i])) |
0 | 1192 domain[j++] = line[i++]; |
1193 domain[j] = '\0'; | |
1194 | |
1195 /* Skip past whitespaces */ | |
1221
f34b803b8639
Handle signed chars. Aadded dIsspace() and dIsalnum() to dlib
Jorge Arellano Cid <jcid@dillo.org>
parents:
1201
diff
changeset
|
1196 while (dIsspace(line[i])) |
0 | 1197 i++; |
1198 | |
1199 /* Get the rule */ | |
1200 j = 0; | |
1221
f34b803b8639
Handle signed chars. Aadded dIsspace() and dIsalnum() to dlib
Jorge Arellano Cid <jcid@dillo.org>
parents:
1201
diff
changeset
|
1201 while (line[i] != '\0' && !dIsspace(line[i])) |
0 | 1202 rule[j++] = line[i++]; |
1203 rule[j] = '\0'; | |
1204 | |
1205 if (dStrcasecmp(rule, "ACCEPT") == 0) | |
1206 cc.action = COOKIE_ACCEPT; | |
1207 else if (dStrcasecmp(rule, "ACCEPT_SESSION") == 0) | |
1208 cc.action = COOKIE_ACCEPT_SESSION; | |
1209 else if (dStrcasecmp(rule, "DENY") == 0) | |
1210 cc.action = COOKIE_DENY; | |
1211 else { | |
1212 MSG("Cookies: rule '%s' for domain '%s' is not recognised.\n", | |
1213 rule, domain); | |
1214 continue; | |
1215 } | |
1216 | |
1217 cc.domain = dStrdup(domain); | |
1218 if (dStrcasecmp(cc.domain, "DEFAULT") == 0) { | |
1219 /* Set the default action */ | |
1220 default_action = cc.action; | |
1221 dFree(cc.domain); | |
1222 } else { | |
1223 a_List_add(ccontrol, num_ccontrol, num_ccontrol_max); | |
1224 ccontrol[num_ccontrol++] = cc; | |
1225 } | |
1226 | |
1227 if (cc.action != COOKIE_DENY) | |
1228 enabled = TRUE; | |
1229 } | |
1230 } | |
1231 | |
1232 fclose(stream); | |
1233 | |
1234 return (enabled ? 0 : 1); | |
1235 } | |
1236 | |
1237 /* | |
1238 * Check the rules for an appropriate action for this domain | |
1239 */ | |
1240 static CookieControlAction Cookies_control_check_domain(const char *domain) | |
1241 { | |
1242 int i, diff; | |
1243 | |
1244 for (i = 0; i < num_ccontrol; i++) { | |
1245 if (ccontrol[i].domain[0] == '.') { | |
1246 diff = strlen(domain) - strlen(ccontrol[i].domain); | |
1247 if (diff >= 0) { | |
1248 if (dStrcasecmp(domain + diff, ccontrol[i].domain) != 0) | |
1249 continue; | |
1250 } else { | |
1251 continue; | |
1252 } | |
1253 } else { | |
1254 if (dStrcasecmp(domain, ccontrol[i].domain) != 0) | |
1255 continue; | |
1256 } | |
1257 | |
1258 /* If we got here we have a match */ | |
1259 return( ccontrol[i].action ); | |
1260 } | |
1261 | |
1262 return default_action; | |
1263 } | |
1264 | |
1265 /* -- Dpi parser ----------------------------------------------------------- */ | |
1266 | |
1267 /* | |
1268 * Parse a data stream (dpi protocol) | |
1269 * Note: Buf is a zero terminated string | |
1270 * Return code: { 0:OK, 1:Abort, 2:Close } | |
1271 */ | |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1272 static int srv_parse_tok(Dsh *sh, ClientInfo *client, char *Buf) |
0 | 1273 { |
1496
5bec8ce33a42
cookies: rm version, comment, comment url, port, Cookie2
corvid <corvid@lavabit.com>
parents:
1495
diff
changeset
|
1274 char *cmd, *cookie, *host, *path, *scheme; |
5bec8ce33a42
cookies: rm version, comment, comment url, port, Cookie2
corvid <corvid@lavabit.com>
parents:
1495
diff
changeset
|
1275 int ret = 1; |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1276 size_t BufSize = strlen(Buf); |
0 | 1277 |
1236
b912173aecd1
Added a_Dpip_get_attr_l() to DPIP's API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1221
diff
changeset
|
1278 cmd = a_Dpip_get_attr_l(Buf, BufSize, "cmd"); |
0 | 1279 |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1280 if (!cmd) { |
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1281 /* abort */ |
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1282 } else if (client->status == 0) { |
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1283 /* authenticate */ |
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1284 if (a_Dpip_check_auth(Buf) == 1) { |
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1285 client->status = 1; |
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1286 ret = 0; |
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1287 } |
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1288 } else if (strcmp(cmd, "DpiBye") == 0) { |
0 | 1289 dFree(cmd); |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1290 MSG("(pid %d): Got DpiBye.\n", (int)getpid()); |
0 | 1291 exit(0); |
1292 | |
1293 } else if (cmd && strcmp(cmd, "set_cookie") == 0) { | |
1501
6fd1c55d8022
cookies use server date to interpret Expires attr
corvid <corvid@lavabit.com>
parents:
1500
diff
changeset
|
1294 char *date; |
6fd1c55d8022
cookies use server date to interpret Expires attr
corvid <corvid@lavabit.com>
parents:
1500
diff
changeset
|
1295 |
0 | 1296 dFree(cmd); |
1236
b912173aecd1
Added a_Dpip_get_attr_l() to DPIP's API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1221
diff
changeset
|
1297 cookie = a_Dpip_get_attr_l(Buf, BufSize, "cookie"); |
b912173aecd1
Added a_Dpip_get_attr_l() to DPIP's API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1221
diff
changeset
|
1298 host = a_Dpip_get_attr_l(Buf, BufSize, "host"); |
b912173aecd1
Added a_Dpip_get_attr_l() to DPIP's API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1221
diff
changeset
|
1299 path = a_Dpip_get_attr_l(Buf, BufSize, "path"); |
1501
6fd1c55d8022
cookies use server date to interpret Expires attr
corvid <corvid@lavabit.com>
parents:
1500
diff
changeset
|
1300 date = a_Dpip_get_attr_l(Buf, BufSize, "date"); |
0 | 1301 |
1501
6fd1c55d8022
cookies use server date to interpret Expires attr
corvid <corvid@lavabit.com>
parents:
1500
diff
changeset
|
1302 Cookies_set(cookie, host, path, date); |
0 | 1303 |
1501
6fd1c55d8022
cookies use server date to interpret Expires attr
corvid <corvid@lavabit.com>
parents:
1500
diff
changeset
|
1304 dFree(date); |
0 | 1305 dFree(path); |
1306 dFree(host); | |
1307 dFree(cookie); | |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1308 ret = 2; |
0 | 1309 |
1310 } else if (cmd && strcmp(cmd, "get_cookie") == 0) { | |
1311 dFree(cmd); | |
1236
b912173aecd1
Added a_Dpip_get_attr_l() to DPIP's API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1221
diff
changeset
|
1312 scheme = a_Dpip_get_attr_l(Buf, BufSize, "scheme"); |
b912173aecd1
Added a_Dpip_get_attr_l() to DPIP's API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1221
diff
changeset
|
1313 host = a_Dpip_get_attr_l(Buf, BufSize, "host"); |
b912173aecd1
Added a_Dpip_get_attr_l() to DPIP's API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1221
diff
changeset
|
1314 path = a_Dpip_get_attr_l(Buf, BufSize, "path"); |
0 | 1315 |
1496
5bec8ce33a42
cookies: rm version, comment, comment url, port, Cookie2
corvid <corvid@lavabit.com>
parents:
1495
diff
changeset
|
1316 cookie = Cookies_get(host, path, scheme); |
0 | 1317 dFree(scheme); |
1318 dFree(path); | |
1319 dFree(host); | |
1320 | |
1321 cmd = a_Dpip_build_cmd("cmd=%s cookie=%s", "get_cookie_answer", cookie); | |
1322 | |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1323 if (a_Dpip_dsh_write_str(sh, 1, cmd)) { |
174
67e98a1211f0
- Fixed a cookies-related dillo freeze bug happening at:
jcid
parents:
159
diff
changeset
|
1324 ret = 1; |
67e98a1211f0
- Fixed a cookies-related dillo freeze bug happening at:
jcid
parents:
159
diff
changeset
|
1325 } else { |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1326 _MSG("a_Dpip_dsh_write_str: SUCCESS cmd={%s}\n", cmd); |
174
67e98a1211f0
- Fixed a cookies-related dillo freeze bug happening at:
jcid
parents:
159
diff
changeset
|
1327 ret = 2; |
0 | 1328 } |
1329 dFree(cookie); | |
1330 dFree(cmd); | |
1331 } | |
1332 | |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1333 return ret; |
0 | 1334 } |
1335 | |
1336 /* -- Termination handlers ----------------------------------------------- */ | |
1337 /* | |
1338 * (was to delete the local namespace socket), | |
1339 * but this is handled by 'dpid' now. | |
1340 */ | |
1341 static void cleanup(void) | |
1342 { | |
1343 Cookies_save_and_free(); | |
1344 MSG("cleanup\n"); | |
1345 /* no more cleanup required */ | |
1346 } | |
1347 | |
1348 /* | |
1349 * Perform any necessary cleanups upon abnormal termination | |
1350 */ | |
1351 static void termination_handler(int signum) | |
1352 { | |
1353 exit(signum); | |
1354 } | |
1355 | |
1356 | |
1357 /* | |
1358 * -- MAIN ------------------------------------------------------------------- | |
1359 */ | |
1385
eb98997886ec
Introduced the new tokenizing dsh API to DPIP
Jorge Arellano Cid <jcid@dillo.org>
parents:
1236
diff
changeset
|
1360 int main(void) { |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1361 struct sockaddr_in sin; |
0 | 1362 socklen_t address_size; |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1363 ClientInfo *client; |
1439
79fcf67eeea0
Fixed bookmarks "cancel" link (Add/Mod URL, Add Sec). Also s/tmp_fd/sock_fd.
Jorge Arellano Cid <jcid@dillo.org>
parents:
1388
diff
changeset
|
1364 int sock_fd, code; |
0 | 1365 char *buf; |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1366 Dsh *sh; |
0 | 1367 |
1368 /* Arrange the cleanup function for terminations via exit() */ | |
1369 atexit(cleanup); | |
1370 | |
1371 /* Arrange the cleanup function for abnormal terminations */ | |
1372 if (signal (SIGINT, termination_handler) == SIG_IGN) | |
1373 signal (SIGINT, SIG_IGN); | |
1374 if (signal (SIGHUP, termination_handler) == SIG_IGN) | |
1375 signal (SIGHUP, SIG_IGN); | |
1376 if (signal (SIGTERM, termination_handler) == SIG_IGN) | |
1377 signal (SIGTERM, SIG_IGN); | |
1378 | |
1379 Cookies_init(); | |
1380 MSG("(v.1) accepting connections...\n"); | |
1381 | |
1382 if (disabled) | |
1383 exit(1); | |
1384 | |
1385 /* some OSes may need this... */ | |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1386 address_size = sizeof(struct sockaddr_in); |
0 | 1387 |
1388 while (1) { | |
1439
79fcf67eeea0
Fixed bookmarks "cancel" link (Add/Mod URL, Add Sec). Also s/tmp_fd/sock_fd.
Jorge Arellano Cid <jcid@dillo.org>
parents:
1388
diff
changeset
|
1389 sock_fd = accept(STDIN_FILENO, (struct sockaddr *)&sin, &address_size); |
79fcf67eeea0
Fixed bookmarks "cancel" link (Add/Mod URL, Add Sec). Also s/tmp_fd/sock_fd.
Jorge Arellano Cid <jcid@dillo.org>
parents:
1388
diff
changeset
|
1390 if (sock_fd == -1) { |
0 | 1391 perror("[accept]"); |
1392 exit(1); | |
1393 } | |
1394 | |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1395 /* create the Dsh structure */ |
1439
79fcf67eeea0
Fixed bookmarks "cancel" link (Add/Mod URL, Add Sec). Also s/tmp_fd/sock_fd.
Jorge Arellano Cid <jcid@dillo.org>
parents:
1388
diff
changeset
|
1396 sh = a_Dpip_dsh_new(sock_fd, sock_fd, 8*1024); |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1397 client = dNew(ClientInfo,1); |
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1398 client->sh = sh; |
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1399 client->status = 0; |
0 | 1400 |
1401 while (1) { | |
1402 code = 1; | |
1388
eb35203124e4
Implemented the file dpi based on select() (removed its pthreads dependency)
Jorge Arellano Cid <jcid@dillo.org>
parents:
1387
diff
changeset
|
1403 if ((buf = a_Dpip_dsh_read_token(sh, 1)) != NULL) { |
0 | 1404 /* Let's see what we fished... */ |
174
67e98a1211f0
- Fixed a cookies-related dillo freeze bug happening at:
jcid
parents:
159
diff
changeset
|
1405 _MSG(" buf = {%s}\n", buf); |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1406 code = srv_parse_tok(sh, client, buf); |
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1407 dFree(buf); |
0 | 1408 } |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1409 |
174
67e98a1211f0
- Fixed a cookies-related dillo freeze bug happening at:
jcid
parents:
159
diff
changeset
|
1410 _MSG(" code = %d %s\n", code, code == 1 ? "EXIT" : "BREAK"); |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1411 if (code == 1) { |
0 | 1412 exit(1); |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1413 } else if (code == 2) { |
0 | 1414 break; |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1415 } |
0 | 1416 } |
1417 | |
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1418 _MSG("Closing Dsh\n"); |
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1419 a_Dpip_dsh_close(sh); |
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1420 a_Dpip_dsh_free(sh); |
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset
|
1421 dFree(client); |
0 | 1422 |
1423 }/*while*/ | |
174
67e98a1211f0
- Fixed a cookies-related dillo freeze bug happening at:
jcid
parents:
159
diff
changeset
|
1424 |
67e98a1211f0
- Fixed a cookies-related dillo freeze bug happening at:
jcid
parents:
159
diff
changeset
|
1425 return 0; |
0 | 1426 } |
1427 | |
1428 #endif /* !DISABLE_COOKIES */ |