Mercurial > dillo_port1.3
annotate dpi/cookies.c @ 1498:c04b0de69b00
cookies follow draft spec for domains
author  corvid <corvid@lavabit.com> 

date  Sat, 09 Jan 2010 20:05:22 +0000 
parents  4ecebf934b44 
children  1803fe44871e 
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 20022007 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 * draftietfhttpstatecookie01.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 hostonly 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/mailarchive/web/httpstate/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/mailarchive/web/httpstate/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  
65  
66 /*  
67 * a_List_add()  
68 *  
69 * Make sure there's space for 'num_items' items within the list  
70 * (First, allocate an 'alloc_step' sized chunk, after that, double the  
71 * list size to make it faster)  
72 */  
73 #define a_List_add(list,num_items,alloc_step) \  
74 if (!list) { \  
75 list = dMalloc(alloc_step * sizeof((*list))); \  
76 } \  
77 if (num_items >= alloc_step){ \  
78 while ( num_items >= alloc_step ) \  
79 alloc_step <<= 1; \  
80 list = dRealloc(list, alloc_step * sizeof((*list))); \  
81 }  
82  
83 /* The maximum length of a line in the cookie file */  
84 #define LINE_MAXLEN 4096  
85  
86 typedef enum {  
87 COOKIE_ACCEPT,  
88 COOKIE_ACCEPT_SESSION,  
89 COOKIE_DENY  
90 } CookieControlAction;  
91  
92 typedef struct {  
93 char *domain;  
94 CookieControlAction action;  
95 } CookieControl;  
96  
97 typedef struct {  
98 char *domain;  
99 Dlist *dlist;  
100 } CookieNode;  
101  
102 typedef struct {  
103 char *name;  
104 char *value;  
105 char *domain;  
106 char *path;  
107 time_t expires_at;  
108 bool_t secure;  
109 bool_t session_only;  
110 } CookieData_t;  
111  
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

112 typedef struct { 
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

113 Dsh *sh; 
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

114 int status; 
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

115 } ClientInfo; 
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

116 
0  117 /* 
118 * Local data  
119 */  
120  
121 /* List of CookieNode. Each node holds a domain and its list of cookies */  
122 static Dlist *cookies;  
123  
124 /* Variables for access control */  
125 static CookieControl *ccontrol = NULL;  
126 static int num_ccontrol = 0;  
127 static int num_ccontrol_max = 1;  
128 static CookieControlAction default_action = COOKIE_DENY;  
129  
130 static bool_t disabled;  
131 static FILE *file_stream;  
132 static char *cookies_txt_header_str =  
133 "# HTTP Cookie File\n"  
235  134 "# http://wp.netscape.com/newsref/std/cookie_spec.html\n" 
0  135 "# This is a generated file! Do not edit.\n\n"; 
136  
137  
138 /*  
139 * Forward declarations  
140 */  
141  
142 static CookieControlAction Cookies_control_check_domain(const char *domain);  
143 static int Cookie_control_init(void);  
144 static void Cookies_add_cookie(CookieData_t *cookie);  
145 static void Cookies_remove_cookie(CookieData_t *cookie);  
146 static int Cookies_cmp(const void *a, const void *b);  
147  
148 /*  
149 * Compare function for searching a cookie node  
150 */  
51  151 static int Cookie_node_cmp(const void *v1, const void *v2) 
0  152 { 
153 const CookieNode *n1 = v1, *n2 = v2;  
154  
1484
29d892265da0
domain comparison not casesensitive
corvid <corvid@lavabit.com>
parents:
1483
diff
changeset

155 return dStrcasecmp(n1>domain, n2>domain); 
0  156 } 
157  
158 /*  
159 * Compare function for searching a cookie node by domain  
160 */  
51  161 static int Cookie_node_by_domain_cmp(const void *v1, const void *v2) 
0  162 { 
163 const CookieNode *node = v1;  
164 const char *domain = v2;  
165  
1484
29d892265da0
domain comparison not casesensitive
corvid <corvid@lavabit.com>
parents:
1483
diff
changeset

166 return dStrcasecmp(node>domain, domain); 
0  167 } 
168  
169 /*  
170 * Return a file pointer. If the file doesn't exist, try to create it,  
171 * with the optional 'init_str' as its content.  
172 */  
219  173 static FILE *Cookies_fopen(const char *filename, const char *mode, 
174 char *init_str)  
0  175 { 
176 FILE *F_in;  
1200
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

177 int fd, rc; 
0  178 
219  179 if ((F_in = fopen(filename, mode)) == NULL) { 
0  180 /* Create the file */ 
181 fd = open(filename, O_WRONLY  O_CREAT  O_TRUNC, S_IRUSR  S_IWUSR);  
182 if (fd != 1) {  
1200
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

183 if (init_str) { 
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

184 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

185 if (rc == 1) { 
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

186 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

187 filename, dStrerror(errno)); 
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

188 } 
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

189 } 
0  190 close(fd); 
191  
192 MSG("Created file: %s\n", filename);  
219  193 F_in = fopen(filename, mode); 
0  194 } else { 
195 MSG("Could not create file: %s!\n", filename);  
196 }  
197 }  
198  
174
67e98a1211f0
 Fixed a cookiesrelated dillo freeze bug happening at:
jcid
parents:
159
diff
changeset

199 if (F_in) { 
67e98a1211f0
 Fixed a cookiesrelated dillo freeze bug happening at:
jcid
parents:
159
diff
changeset

200 /* set close on exec */ 
67e98a1211f0
 Fixed a cookiesrelated dillo freeze bug happening at:
jcid
parents:
159
diff
changeset

201 fcntl(fileno(F_in), F_SETFD, FD_CLOEXEC  fcntl(fileno(F_in), F_GETFD)); 
67e98a1211f0
 Fixed a cookiesrelated dillo freeze bug happening at:
jcid
parents:
159
diff
changeset

202 } 
0  203 
204 return F_in;  
205 }  
206  
207 static void Cookies_free_cookie(CookieData_t *cookie)  
208 {  
209 dFree(cookie>name);  
210 dFree(cookie>value);  
211 dFree(cookie>domain);  
212 dFree(cookie>path);  
213 dFree(cookie);  
214 }  
215  
216 /*  
217 * Initialize the cookies module  
218 * (The 'disabled' variable is writable only within Cookies_init)  
219 */  
51  220 static void Cookies_init() 
0  221 { 
222 CookieData_t *cookie;  
1200
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

223 char *filename, *rc = NULL; 
0  224 char line[LINE_MAXLEN]; 
225 #ifndef HAVE_LOCKF  
226 struct flock lck;  
227 #endif  
228  
229 /* Default setting */  
230 disabled = TRUE;  
231  
232 /* Read and parse the cookie control file (cookiesrc) */  
233 if (Cookie_control_init() != 0) {  
234 MSG("Disabling cookies.\n");  
235 return;  
236 }  
237  
238 /* Get a stream for the cookies file */  
239 filename = dStrconcat(dGethomedir(), "/.dillo/cookies.txt", NULL);  
219  240 file_stream = Cookies_fopen(filename, "r+", cookies_txt_header_str); 
0  241 
242 dFree(filename);  
243  
244 if (!file_stream) {  
1495
a83b066cbcb3
rm support for ancient ~/.dillo/cookies file
corvid <corvid@lavabit.com>
parents:
1491
diff
changeset

245 MSG("ERROR: Can't open ~/.dillo/cookies.txt; disabling cookies\n"); 
0  246 return; 
247 }  
248  
249 /* Try to get a lock from the file descriptor */  
250 #ifdef HAVE_LOCKF  
251 disabled = (lockf(fileno(file_stream), F_TLOCK, 0) == 1);  
252 #else /* POSIX lock */  
253 lck.l_start = 0; /* start at beginning of file */  
254 lck.l_len = 0; /* lock entire file */  
255 lck.l_type = F_WRLCK;  
256 lck.l_whence = SEEK_SET; /* absolute offset */  
257  
258 disabled = (fcntl(fileno(file_stream), F_SETLK, &lck) == 1);  
259 #endif  
260 if (disabled) {  
1495
a83b066cbcb3
rm support for ancient ~/.dillo/cookies file
corvid <corvid@lavabit.com>
parents:
1491
diff
changeset

261 MSG("The cookies file has a file lock; disabling cookies!\n"); 
0  262 fclose(file_stream); 
263 return;  
264 }  
265  
1495
a83b066cbcb3
rm support for ancient ~/.dillo/cookies file
corvid <corvid@lavabit.com>
parents:
1491
diff
changeset

266 MSG("Enabling cookies as per cookiesrc...\n"); 
0  267 
268 cookies = dList_new(32);  
269  
270 /* Get all lines in the file */  
271 while (!feof(file_stream)) {  
272 line[0] = '\0';  
1200
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

273 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

274 if (!rc && ferror(file_stream)) { 
1201  275 MSG("Cookies1: Error while reading from cookies.txt: %s\n", 
1200
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

276 dStrerror(errno)); 
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

277 break; /* bail out */ 
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

278 } 
0  279 
280 /* Remove leading and trailing whitespaces */  
281 dStrstrip(line);  
282  
283 if ((line[0] != '\0') && (line[0] != '#')) {  
284 /*  
285 * Split the row into pieces using a tab as the delimiter.  
286 * pieces[0] The domain name  
287 * pieces[1] TRUE/FALSE: is the domain a suffix, or a full domain?  
288 * pieces[2] The path  
1495
a83b066cbcb3
rm support for ancient ~/.dillo/cookies file
corvid <corvid@lavabit.com>
parents:
1491
diff
changeset

289 * pieces[3] TRUE/FALSE: is the cookie for secure use only? 
0  290 * pieces[4] Timestamp of expire date 
291 * pieces[5] Name of the cookie  
292 * pieces[6] Value of the cookie  
293 */  
294 CookieControlAction action;  
295 char *piece;  
296 char *line_marker = line;  
297  
298 cookie = dNew0(CookieData_t, 1);  
299  
300 cookie>session_only = FALSE;  
301 cookie>domain = dStrdup(dStrsep(&line_marker, "\t"));  
302 dStrsep(&line_marker, "\t"); /* we use domain always as sufix */  
303 cookie>path = dStrdup(dStrsep(&line_marker, "\t"));  
304 piece = dStrsep(&line_marker, "\t");  
305 if (piece != NULL && piece[0] == 'T')  
306 cookie>secure = TRUE;  
307 piece = dStrsep(&line_marker, "\t");  
308 if (piece != NULL)  
309 cookie>expires_at = (time_t) strtol(piece, NULL, 10);  
310 cookie>name = dStrdup(dStrsep(&line_marker, "\t"));  
311 cookie>value = dStrdup(dStrsep(&line_marker, "\t"));  
312  
313 if (!cookie>domain  cookie>domain[0] == '\0'   
314 !cookie>path  cookie>path[0] != '/'   
315 !cookie>name  cookie>name[0] == '\0'   
316 !cookie>value) {  
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;  
344  
345 #ifndef HAVE_LOCKF  
346 struct flock lck;  
347 #endif  
348  
349 if (disabled)  
350 return;  
351  
352 rewind(file_stream);  
353 fd = fileno(file_stream);  
1200
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

354 if (ftruncate(fd, 0) == 1) 
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

355 MSG("Cookies: Truncate file stream failed: %s\n", dStrerror(errno)); 
454  356 fprintf(file_stream, "%s", cookies_txt_header_str); 
0  357 
358 /* Iterate cookies per domain, saving and freeing */  
359 while ((node = dList_nth_data(cookies, 0))) {  
360 for (i = 0; (cookie = dList_nth_data(node>dlist, i)); ++i) {  
361 if (!cookie>session_only) {  
362 fprintf(file_stream, "%s\tTRUE\t%s\t%s\t%ld\t%s\t%s\n",  
363 cookie>domain,  
364 cookie>path,  
365 cookie>secure ? "TRUE" : "FALSE",  
366 (long)cookie>expires_at,  
367 cookie>name,  
368 cookie>value);  
369 }  
370  
371 Cookies_free_cookie(cookie);  
372 }  
373 dList_remove(cookies, node);  
374 dFree(node>domain);  
375 dList_free(node>dlist);  
376 dFree(node);  
377 }  
378  
379 #ifdef HAVE_LOCKF  
380 lockf(fd, F_ULOCK, 0);  
381 #else /* POSIX file lock */  
382 lck.l_start = 0; /* start at beginning of file */  
383 lck.l_len = 0; /* lock entire file */  
384 lck.l_type = F_UNLCK;  
385 lck.l_whence = SEEK_SET; /* absolute offset */  
386  
387 fcntl(fileno(file_stream), F_SETLKW, &lck);  
388 #endif  
389 fclose(file_stream);  
390 }  
391  
392 static char *months[] =  
393 { "",  
394 "Jan", "Feb", "Mar",  
395 "Apr", "May", "Jun",  
396 "Jul", "Aug", "Sep",  
397 "Oct", "Nov", "Dec"  
398 };  
399  
400 /*  
401 * Take a months name and return a number between 112.  
402 * E.g. 'April' > 4  
403 */  
404 static int Cookies_get_month(const char *month_name)  
405 {  
406 int i;  
407  
408 for (i = 1; i <= 12; i++) {  
409 if (!dStrncasecmp(months[i], month_name, 3))  
410 return i;  
411 }  
412 return 0;  
413 }  
414  
415 /*  
416 * Return a local timestamp from a GMT date string  
417 * Accept: RFC1123  RFC850  ANSI asctime  Old Netscape format.  
418 *  
419 * Wdy, DDMonYY HH:MM:SS GMT  
420 * Wdy, DDMonYYYY HH:MM:SS GMT  
421 * Weekday, DDMonYY HH:MM:SS GMT  
422 * Weekday, DDMonYYYY HH:MM:SS GMT  
423 * Tue May 21 13:46:22 1991\n  
424 * Tue May 21 13:46:22 1991  
425 *  
426 * (return 0 on malformed date string syntax)  
427 */  
428 static time_t Cookies_create_timestamp(const char *expires)  
429 {  
430 time_t ret;  
431 int day, month, year, hour, minutes, seconds;  
432 char *cp;  
433 char *E_msg =  
434 "Expire date is malformed!\n"  
435 " (should be RFC1123  RFC850  ANSI asctime)\n"  
436 " Ignoring cookie: ";  
437  
438 cp = strchr(expires, ',');  
439 if (!cp && (strlen(expires) == 24  strlen(expires) == 25)) {  
440 /* Looks like ANSI asctime format... */  
441 cp = (char *)expires;  
442 day = strtol(cp + 8, NULL, 10); /* day */  
443 month = Cookies_get_month(cp + 4); /* month */  
444 year = strtol(cp + 20, NULL, 10); /* year */  
445 hour = strtol(cp + 11, NULL, 10); /* hour */  
446 minutes = strtol(cp + 14, NULL, 10); /* minutes */  
447 seconds = strtol(cp + 17, NULL, 10); /* seconds */  
448  
449 } else if (cp && (cp  expires == 3  cp  expires > 5) &&  
450 (strlen(cp) == 24  strlen(cp) == 26)) {  
451 /* RFC1123  RFC850 format  Old Netscape format */  
452 day = strtol(cp + 2, NULL, 10);  
453 month = Cookies_get_month(cp + 5);  
454 year = strtol(cp + 9, &cp, 10);  
368  455 /* TODO: tricky, because two digits for year IS ambiguous! */ 
0  456 year += (year < 70) ? 2000 : ((year < 100) ? 1900 : 0); 
457 hour = strtol(cp + 1, NULL, 10);  
458 minutes = strtol(cp + 4, NULL, 10);  
459 seconds = strtol(cp + 7, NULL, 10);  
460  
461 } else {  
462 MSG("%s%s\n", E_msg, expires);  
463 return (time_t) 0;  
464 }  
465  
466 /* Error checks this may be overkill */  
1127  467 if (!(day > 0 && day < 32 && month > 0 && month < 13 && year >= 1970 && 
0  468 hour >= 0 && hour < 24 && minutes >= 0 && minutes < 60 && 
469 seconds >= 0 && seconds < 60)) {  
470 MSG("%s%s\n", E_msg, expires);  
471 return (time_t) 0;  
472 }  
473  
474 /* Calculate local timestamp.  
475 * [stolen from Lynx... (http://lynx.browser.org)] */  
476 month = 3;  
477 if (month < 0) {  
478 month += 12;  
479 year;  
480 }  
481  
482 day += (year  1968) * 1461 / 4;  
483 day += ((((month * 153) + 2) / 5)  672);  
484 ret = (time_t)((day * 60 * 60 * 24) +  
485 (hour * 60 * 60) +  
486 (minutes * 60) +  
487 seconds);  
488  
489 MSG("Expires in %ld seconds, at %s",  
490 (long)ret  time(NULL), ctime(&ret));  
491  
492 return ret;  
493 }  
494  
495 static void Cookies_add_cookie(CookieData_t *cookie)  
496 {  
497 Dlist *domain_cookies;  
498 CookieData_t *c;  
499 CookieNode *node;  
500  
501 node = dList_find_sorted(cookies, cookie>domain,Cookie_node_by_domain_cmp);  
502 domain_cookies = (node) ? node>dlist : NULL;  
503  
504 if (domain_cookies) {  
1482
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

505 /* Remove any cookies with the same name and path */ 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

506 while ((c = dList_find_custom(domain_cookies, cookie, Cookies_cmp))){ 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

507 Cookies_remove_cookie(c); 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

508 } 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

509 
0  510 /* Respect the limit of 20 cookies per domain */ 
511 if (dList_length(domain_cookies) >= 20) {  
512 MSG("There are too many cookies for this domain (%s)\n",  
513 cookie>domain);  
514 Cookies_free_cookie(cookie);  
515 return;  
516 }  
517  
1482
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

518 } 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

519 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

520 /* Don't add an expired cookie. Strictly speaking, maxage cookies should 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

521 * only be discarded when "the age is _greater_ than deltaseconds seconds" 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

522 * (my emphasis), but "A value of zero means the cookie SHOULD be discarded 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

523 * immediately", and there's no compelling reason to distinguish between 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

524 * these cases. */ 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

525 if (cookie>expires_at <= time(NULL)) { 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

526 Cookies_free_cookie(cookie); 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

527 return; 
0  528 } 
529  
530 /* add the cookie into the respective domain list */  
531 node = dList_find_sorted(cookies, cookie>domain,Cookie_node_by_domain_cmp);  
532 domain_cookies = (node) ? node>dlist : NULL;  
533 if (!domain_cookies) {  
534 domain_cookies = dList_new(5);  
535 dList_append(domain_cookies, cookie);  
536 node = dNew(CookieNode, 1);  
537 node>domain = dStrdup(cookie>domain);  
538 node>dlist = domain_cookies;  
539 dList_insert_sorted(cookies, node, Cookie_node_cmp);  
540 } else {  
541 dList_append(domain_cookies, cookie);  
542 }  
543 }  
544  
545 /*  
546 * Remove the cookie from the domain list.  
547 * If the domain list is empty, remove the node too.  
548 * Free the cookie.  
549 */  
550 static void Cookies_remove_cookie(CookieData_t *cookie)  
551 {  
552 CookieNode *node;  
553  
554 node = dList_find_sorted(cookies, cookie>domain,Cookie_node_by_domain_cmp);  
555 if (node) {  
556 dList_remove(node>dlist, cookie);  
557 if (dList_length(node>dlist) == 0) {  
558 dList_remove(cookies, node);  
559 dFree(node>domain);  
560 dList_free(node>dlist);  
561 }  
562 } else {  
563 MSG("Attempting to remove a cookie that doesn't exist!\n");  
564 }  
565  
566 Cookies_free_cookie(cookie);  
567 }  
568  
569 /*  
570 * Return the attribute that is present at *cookie_str. This function  
571 * will also attempt to advance cookie_str past any equalsign.  
572 */  
573 static char *Cookies_parse_attr(char **cookie_str)  
574 {  
575 char *str = *cookie_str;  
576 uint_t i, end = 0;  
577 bool_t got_attr = FALSE;  
578  
579 for (i = 0; ; i++) {  
580 switch (str[i]) {  
581 case ' ':  
582 case '\t':  
583 case '=':  
584 case ';':  
585 got_attr = TRUE;  
586 if (end == 0)  
587 end = i;  
588 break;  
589 case ',':  
590 *cookie_str = str + i;  
591 return dStrndup(str, i);  
592 break;  
593 case '\0':  
594 if (!got_attr) {  
595 end = i;  
596 got_attr = TRUE;  
597 }  
598 /* fall through! */  
599 default:  
600 if (got_attr) {  
601 *cookie_str = str + i;  
602 return dStrndup(str, end);  
603 }  
604 break;  
605 }  
606 }  
607  
608 return NULL;  
609 }  
610  
611 /*  
612 * Get the value starting at *cookie_str.  
613 * broken_syntax: watch out for stupid syntax (comma in unquoted string...)  
614 */  
615 static char *Cookies_parse_value(char **cookie_str,  
616 bool_t broken_syntax,  
617 bool_t keep_quotes)  
618 {  
619 uint_t i, end;  
620 char *str = *cookie_str;  
621  
622 for (i = end = 0; !end; ++i) {  
623 switch (str[i]) {  
624 case ' ':  
625 case '\t':  
626 if (!broken_syntax && str[0] != '\'' && str[0] != '"') {  
1481
4a6917683a2d
handle whitespace following cookie attribute value
corvid <corvid@lavabit.com>
parents:
1439
diff
changeset

627 end = 1; 
0  628 *cookie_str = str + i + 1; 
1481
4a6917683a2d
handle whitespace following cookie attribute value
corvid <corvid@lavabit.com>
parents:
1439
diff
changeset

629 while (**cookie_str == ' '  **cookie_str == '\t') 
4a6917683a2d
handle whitespace following cookie attribute value
corvid <corvid@lavabit.com>
parents:
1439
diff
changeset

630 *cookie_str += 1; 
4a6917683a2d
handle whitespace following cookie attribute value
corvid <corvid@lavabit.com>
parents:
1439
diff
changeset

631 if (**cookie_str == ';') 
4a6917683a2d
handle whitespace following cookie attribute value
corvid <corvid@lavabit.com>
parents:
1439
diff
changeset

632 *cookie_str += 1; 
0  633 } 
634 break;  
635 case '\'':  
636 case '"':  
637 if (i != 0 && str[i] == str[0]) {  
638 char *tmp = str + i;  
639  
640 while (*tmp != '\0' && *tmp != ';' && *tmp != ',')  
641 tmp++;  
642  
643 *cookie_str = (*tmp == ';') ? tmp + 1 : tmp;  
644  
645 if (keep_quotes)  
646 i++;  
647 end = 1;  
648 }  
649 break;  
650 case '\0':  
651 *cookie_str = str + i;  
652 end = 1;  
653 break;  
654 case ',':  
655 if (str[0] != '\'' && str[0] != '"' && !broken_syntax) {  
656 /* A new cookie starts here! */  
657 *cookie_str = str + i;  
658 end = 1;  
659 }  
660 break;  
661 case ';':  
662 if (str[0] != '\'' && str[0] != '"') {  
663 *cookie_str = str + i + 1;  
664 end = 1;  
665 }  
666 break;  
667 default:  
668 break;  
669 }  
670 }  
671 /* keep i as an index to the last char */  
672 i;  
673  
674 if ((str[0] == '\''  str[0] == '"') && !keep_quotes) {  
675 return i > 1 ? dStrndup(str + 1, i  1) : NULL;  
676 } else {  
677 return dStrndup(str, i);  
678 }  
679 }  
680  
681 /*  
682 * Parse one cookie...  
683 */  
1496
5bec8ce33a42
cookies: rm version, comment, comment url, port, Cookie2
corvid <corvid@lavabit.com>
parents:
1495
diff
changeset

684 static CookieData_t *Cookies_parse_one(char **cookie_str) 
0  685 { 
686 CookieData_t *cookie;  
687 char *str = *cookie_str;  
688 char *attr;  
689 char *value;  
690 int num_attr = 0;  
691 bool_t max_age = FALSE;  
1482
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

692 bool_t expires = FALSE; 
0  693 bool_t discard = FALSE; 
159
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

694 bool_t error = FALSE; 
0  695 
696 cookie = dNew0(CookieData_t, 1);  
1482
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

697 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

698 /* let's arbitrarily choose a year for now */ 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

699 cookie>expires_at = time(NULL) + 60 * 60 * 24 * 365; 
0  700 
701 /* Iterate until there is nothing left of the string OR we come  
702 * across a comma representing the start of another cookie */  
703 while (*str != '\0' && *str != ',') {  
159
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

704 if (error) { 
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

705 str++; 
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

706 continue; 
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

707 } 
0  708 /* Skip whitespace */ 
1221
f34b803b8639
Handle signed chars. Aadded dIsspace() and dIsalnum() to dlib
Jorge Arellano Cid <jcid@dillo.org>
parents:
1201
diff
changeset

709 while (dIsspace(*str)) 
0  710 str++; 
711  
712 /* Get attribute */  
713 attr = Cookies_parse_attr(&str);  
714 if (!attr) {  
159
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

715 MSG("Cannot parse cookie attribute!\n"); 
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

716 error = TRUE; 
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

717 continue; 
0  718 } 
719  
720 /* Get the value for the attribute and store it */  
721 if (num_attr == 0) {  
722 /* The first attr, which always is the user supplied attr, may  
723 * have the same name as an ordinary attr. Hence this workaround. */  
724 cookie>name = dStrdup(attr);  
725 cookie>value = Cookies_parse_value(&str, FALSE, TRUE);  
726 } else if (dStrcasecmp(attr, "Path") == 0) {  
727 value = Cookies_parse_value(&str, FALSE, FALSE);  
1491
a10148c0bcab
cookies don't leak extra domain/path attrs
corvid <corvid@lavabit.com>
parents:
1490
diff
changeset

728 dFree(cookie>path); 
0  729 cookie>path = value; 
730 } else if (dStrcasecmp(attr, "Domain") == 0) {  
731 value = Cookies_parse_value(&str, FALSE, FALSE);  
1491
a10148c0bcab
cookies don't leak extra domain/path attrs
corvid <corvid@lavabit.com>
parents:
1490
diff
changeset

732 dFree(cookie>domain); 
0  733 cookie>domain = value; 
734 } else if (dStrcasecmp(attr, "Discard") == 0) {  
735 discard = TRUE;  
736 } else if (dStrcasecmp(attr, "MaxAge") == 0) {  
1482
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

737 value = Cookies_parse_value(&str, FALSE, FALSE); 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

738 if (value) { 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

739 cookie>expires_at = time(NULL) + strtol(value, NULL, 10); 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

740 expires = max_age = TRUE; 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

741 dFree(value); 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

742 } else { 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

743 MSG("Cannot parse cookie MaxAge value!\n"); 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

744 dFree(attr); 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

745 error = TRUE; 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

746 continue; 
0  747 } 
748 } else if (dStrcasecmp(attr, "Expires") == 0) {  
1482
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

749 if (!max_age) { 
1489  750 _MSG("Old Netscapestyle cookie...\n"); 
0  751 value = Cookies_parse_value(&str, TRUE, FALSE); 
752 if (value) {  
753 cookie>expires_at = Cookies_create_timestamp(value);  
1482
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

754 expires = TRUE; 
0  755 dFree(value); 
756 } else {  
159
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

757 MSG("Cannot parse cookie Expires value!\n"); 
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

758 dFree(attr); 
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

759 error = TRUE; 
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

760 continue; 
0  761 } 
1483
d6776d51675d
handle maxage + expires error case
corvid <corvid@lavabit.com>
parents:
1482
diff
changeset

762 } else { 
d6776d51675d
handle maxage + expires error case
corvid <corvid@lavabit.com>
parents:
1482
diff
changeset

763 MSG("Cookie cannot contain MaxAge and Expires.\n"); 
d6776d51675d
handle maxage + expires error case
corvid <corvid@lavabit.com>
parents:
1482
diff
changeset

764 dFree(attr); 
d6776d51675d
handle maxage + expires error case
corvid <corvid@lavabit.com>
parents:
1482
diff
changeset

765 error = TRUE; 
d6776d51675d
handle maxage + expires error case
corvid <corvid@lavabit.com>
parents:
1482
diff
changeset

766 continue; 
0  767 } 
768 } else if (dStrcasecmp(attr, "Secure") == 0) {  
769 cookie>secure = TRUE;  
418
b7265ec32e33
 Allow login to wikipedia by ignoring the HttpOnly attribute (cookies)
jcid
parents:
379
diff
changeset

770 } else if (dStrcasecmp(attr, "HttpOnly") == 0) { 
419  771 // this case is intentionally left blank, because we do not 
772 // do clientside scripting (yet).  
0  773 } else { 
774 /* Oops! this can't be good... */  
379  775 MSG("Cookie contains unknown attribute: '%s'\n", attr); 
0  776 dFree(attr); 
159
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

777 error = TRUE; 
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

778 continue; 
0  779 } 
780  
781 dFree(attr);  
782 num_attr++;  
783 }  
784  
1482
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

785 /* 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

786 * Netscape cookie spec: "expires is an optional attribute. If not 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

787 * specified, the cookie will expire when the user's session ends." 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

788 * rfc 2965: (in the absence of) "MaxAge The default behavior is to 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

789 * discard the cookie when the user agent exits." 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

790 * "The Discard attribute instructs the user agent to discard the 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

791 * cookie unconditionally when the user agent terminates." 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

792 */ 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

793 cookie>session_only = discard == TRUE  expires == FALSE; 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

794 
0  795 *cookie_str = (*str == ',') ? str + 1 : str; 
796  
159
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

797 if (!error && (!cookie>name  !cookie>value)) { 
0  798 MSG("Cookie missing name and/or value!\n"); 
159
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

799 error = TRUE; 
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

800 } 
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

801 if (error) { 
0  802 Cookies_free_cookie(cookie); 
159
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

803 cookie = NULL; 
0  804 } 
159
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

805 return cookie; 
0  806 } 
807  
808 /*  
809 * Iterate the cookie string until we catch all cookies.  
810 * Return Value: a list with all the cookies! (or NULL upon error)  
811 */  
1496
5bec8ce33a42
cookies: rm version, comment, comment url, port, Cookie2
corvid <corvid@lavabit.com>
parents:
1495
diff
changeset

812 static Dlist *Cookies_parse_string(char *cookie_string) 
0  813 { 
814 CookieData_t *cookie;  
815 Dlist *ret = NULL;  
816 char *str = cookie_string;  
817  
818 /* The string may contain several cookies separated by comma.  
159
70da40b41e3a
 Fixed a bug in Cookies_parse_one. Set it to a single return potint too!
jcid
parents:
154
diff
changeset

819 * We'll iterate until we've caught them all */ 
0  820 while (*str) { 
1496
5bec8ce33a42
cookies: rm version, comment, comment url, port, Cookie2
corvid <corvid@lavabit.com>
parents:
1495
diff
changeset

821 cookie = Cookies_parse_one(&str); 
0  822 
823 if (cookie) {  
824 if (!ret)  
825 ret = dList_new(4);  
826 dList_append(ret, cookie);  
827 } else {  
828 MSG("Malformed cookie field, ignoring cookie: %s\n", cookie_string);  
829 }  
830 }  
831  
832 return ret;  
833 }  
834  
835 /*  
836 * Compare cookies by name and path (return 0 if equal)  
837 */  
838 static int Cookies_cmp(const void *a, const void *b)  
839 {  
840 const CookieData_t *ca = a, *cb = b;  
841 int ret;  
842  
843 if (!(ret = strcmp(ca>name, cb>name)))  
844 ret = strcmp(ca>path, cb>path);  
845 return ret;  
846 }  
847  
848 /*  
1497
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

849 * Check whether url_path pathmatches cookie_path 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

850 * 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

851 * Note different user agents apparently vary in pathmatching behaviour, 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

852 * but this is the recommended method at the moment. 
1486  853 */ 
1497
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

854 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

855 const char *cookie_path) 
1486  856 { 
857 bool_t ret = TRUE;  
858  
1497
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

859 if (!url_path  !cookie_path) { 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

860 ret = FALSE; 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

861 } else { 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

862 uint_t c_len = strlen(cookie_path); 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

863 uint_t u_len = strlen(url_path); 
1486  864 
1497
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

865 ret = (!strncmp(cookie_path, url_path, c_len) && 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

866 ((c_len == u_len)  
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

867 (c_len > 0 && cookie_path[c_len  1] == '/')  
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

868 (u_len > c_len && url_path[c_len] == '/'))); 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

869 } 
1486  870 return ret; 
871 }  
872  
873 /*  
1497
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

874 * If cookie path is not properly set, remedy that. 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

875 */ 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

876 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

877 { 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

878 if (!cookie>path  cookie>path[0] != '/') { 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

879 dFree(cookie>path); 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

880 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

881 if (url_path) { 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

882 uint_t len = strlen(url_path); 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

883 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

884 while (len && url_path[len] != '/') 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

885 len; 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

886 cookie>path = dStrndup(url_path, len ? len : 1); 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

887 } else { 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

888 cookie>path = dStrdup("/"); 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

889 } 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

890 } 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

891 } 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

892 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

893 /* 
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

894 * Check whether host name A domainmatches host name B. 
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 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

897 { 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

898 int diff; 
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 if (!A  !*A  !B  !*B) 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

901 return FALSE; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

902 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

903 if (*B == '.') 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

904 B++; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

905 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

906 /* 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

907 * 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

908 * don't, so: No. 
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 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

911 if (!dStrcasecmp(A, B)) 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

912 return TRUE; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

913 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

914 diff = strlen(A)  strlen(B); 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

915 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

916 if (diff > 0) { 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

917 /* 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

918 return (dStrcasecmp(A + diff, B) == 0 && A[diff  1] == '.'); 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

919 } else { 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

920 return FALSE; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

921 } 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

922 } 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

923 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

924 /* 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

925 * 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

926 * 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

927 * 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

928 * 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

929 * 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

930 * 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

931 * reports. 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

932 */ 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

933 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

934 { 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

935 uint_t ret = 1; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

936 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

937 if (host) { 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

938 int start, after, tld_len; 
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 /* 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

941 * 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

942 */ 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

943 after = strlen(host); 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

944 if (after > 0 && host[after  1] == '.') 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

945 after; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

946 start = after; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

947 while (start > 0 && host[start  1] != '.') 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

948 start; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

949 tld_len = after  start; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

950 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

951 if (tld_len > 0) { 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

952 const char *const tlds[] = {"ai","au","bd","bh","ck","eg","et","fk", 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

953 "il","in","kh","kr","mk","mt","na","np", 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

954 "nz","pg","pk","qa","sa","sb","sg","sv", 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

955 "ua","ug","uk","uy","vn","za","zw","name"}; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

956 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

957 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

958 for (i = 0; i < tld_num; i++) { 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

959 if (strlen(tlds[i]) == (uint_t) tld_len && 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

960 !dStrncasecmp(tlds[i], host + start, tld_len)) { 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

961 MSG("TLD code matched %s\n", tlds[i]); 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

962 ret++; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

963 break; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

964 } 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

965 } 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

966 } 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

967 } 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

968 return ret; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

969 } 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

970 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

971 /* 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

972 * Is the domain an IP address? 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

973 */ 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

974 static bool_t Cookies_domain_is_ip(const char *domain) 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

975 { 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

976 bool_t ipv4 = TRUE, ipv6 = TRUE; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

977 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

978 if (!domain) 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

979 return FALSE; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

980 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

981 while (*domain) { 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

982 if (*domain != '.' && !isdigit(*domain)) 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

983 ipv4 = FALSE; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

984 if (*domain != ':' && !isxdigit(*domain)) 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

985 ipv6 = FALSE; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

986 if (!(ipv4  ipv6)) 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

987 return FALSE; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

988 domain++; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

989 } 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

990 MSG("an IP address\n"); 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

991 return TRUE; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

992 } 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

993 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

994 /* 
0  995 * Validate cookies domain against some security checks. 
996 */  
1497
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

997 static bool_t Cookies_validate_domain(CookieData_t *cookie, char *host) 
0  998 { 
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

999 uint_t i, internal_dots; 
0  1000 
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1001 if (!cookie>domain) { 
0  1002 cookie>domain = dStrdup(host); 
1003 return TRUE;  
1004 }  
1005  
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1006 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

1007 char *d = dStrconcat(".", cookie>domain, NULL); 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1008 dFree(cookie>domain); 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1009 cookie>domain = d; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1010 } 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1011 
1488  1012 if (!Cookies_domain_matches(host, cookie>domain)) 
1013 return FALSE;  
1014  
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1015 internal_dots = 0; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1016 for (i = 1; i < strlen(cookie>domain)  1; i++) { 
0  1017 if (cookie>domain[i] == '.') 
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1018 internal_dots++; 
0  1019 } 
1020  
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1021 /* All of this dots business is a weak hack. 
1488  1022 * TODO: accept the publicsuffix.org list as an optional external file. 
1023 */  
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1024 if (internal_dots < Cookies_internal_dots_required(host)) { 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1025 MSG("not enough dots in %s\n", cookie>domain); 
0  1026 return FALSE; 
1027 }  
1028  
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1029 MSG("host %s and domain %s is all right\n", host, cookie>domain); 
0  1030 return TRUE; 
1031 }  
1032  
1033 /*  
1034 * Set the value corresponding to the cookie string  
1035 */  
51  1036 static void Cookies_set(char *cookie_string, char *url_host, 
1496
5bec8ce33a42
cookies: rm version, comment, comment url, port, Cookie2
corvid <corvid@lavabit.com>
parents:
1495
diff
changeset

1037 char *url_path) 
0  1038 { 
1039 CookieControlAction action;  
1040 CookieData_t *cookie;  
1041 Dlist *list;  
1042 int i;  
1043  
1044 if (disabled)  
1045 return;  
1046  
1047 action = Cookies_control_check_domain(url_host);  
1048 if (action == COOKIE_DENY) {  
1049 MSG("denied SET for %s\n", url_host);  
1050 return;  
1051 }  
1052  
1482
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

1053 _MSG("%s setting: %s\n", url_host, cookie_string); 
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

1054 
1496
5bec8ce33a42
cookies: rm version, comment, comment url, port, Cookie2
corvid <corvid@lavabit.com>
parents:
1495
diff
changeset

1055 if ((list = Cookies_parse_string(cookie_string))) { 
0  1056 for (i = 0; (cookie = dList_nth_data(list, i)); ++i) { 
1497
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

1057 if (Cookies_validate_domain(cookie, url_host)) { 
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

1058 Cookies_validate_path(cookie, url_path); 
0  1059 if (action == COOKIE_ACCEPT_SESSION) 
1060 cookie>session_only = TRUE;  
1061 Cookies_add_cookie(cookie);  
1062 } else {  
1063 MSG("Rejecting cookie for %s from host %s path %s\n",  
1064 cookie>domain, url_host, url_path);  
1065 Cookies_free_cookie(cookie);  
1066 }  
1067 }  
1068 dList_free(list);  
1069 }  
1070 }  
1071  
1072 /*  
1073 * Compare the cookie with the supplied data to see if it matches  
1074 */  
1497
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

1075 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

1076 bool_t is_ssl) 
0  1077 { 
1078 /* Insecure cookies matches both secure and insecure urls, secure  
1079 cookies matches only secure urls */  
1080 if (cookie>secure && !is_ssl)  
1081 return FALSE;  
1082  
1497
4ecebf934b44
cookies follow draft spec for paths
corvid <corvid@lavabit.com>
parents:
1496
diff
changeset

1083 if (!Cookies_path_matches(url_path, cookie>path)) 
0  1084 return FALSE; 
1085  
1086 /* It's a match */  
1087 return TRUE;  
1088 }  
1089  
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1090 static void Cookies_add_matching_cookies(const char *domain, 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1091 const char *url_path, 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1092 Dlist *matching_cookies, 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1093 bool_t is_ssl) 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1094 { 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1095 CookieNode *node = dList_find_sorted(cookies, domain, 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1096 Cookie_node_by_domain_cmp); 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1097 if (node) { 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1098 int i; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1099 CookieData_t *cookie; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1100 Dlist *domain_cookies = node>dlist; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1101 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1102 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

1103 /* Remove expired cookie. */ 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1104 if (cookie>expires_at < time(NULL)) { 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1105 MSG("goodbye, expired cookie %s=%s d:%s p:%s\n", cookie>name, 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1106 cookie>value, cookie>domain, cookie>path); 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1107 Cookies_remove_cookie(cookie); 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1108 i; continue; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1109 } 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1110 /* Check if the cookie matches the requesting URL */ 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1111 if (Cookies_match(cookie, url_path, is_ssl)) { 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1112 int j; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1113 CookieData_t *curr; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1114 uint_t path_length = strlen(cookie>path); 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1115 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1116 /* Longest cookies go first */ 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1117 for (j = 0; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1118 (curr = dList_nth_data(matching_cookies, j)) && 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1119 strlen(curr>path) >= path_length; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1120 j++) ; 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1121 dList_insert_pos(matching_cookies, cookie, j); 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1122 } 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1123 } 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1124 } 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1125 } 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1126 
0  1127 /* 
1128 * Return a string that contains all relevant cookies as headers.  
1129 */  
51  1130 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

1131 char *url_scheme) 
0  1132 { 
1496
5bec8ce33a42
cookies: rm version, comment, comment url, port, Cookie2
corvid <corvid@lavabit.com>
parents:
1495
diff
changeset

1133 char *domain_str, *str; 
0  1134 CookieData_t *cookie; 
1135 Dlist *matching_cookies;  
1136 bool_t is_ssl;  
1137 Dstr *cookie_dstring;  
1138 int i;  
1139  
1140 if (disabled)  
1141 return dStrdup("");  
1142  
1143 matching_cookies = dList_new(8);  
1144  
1145 /* Check if the protocol is secure or not */  
1146 is_ssl = (!dStrcasecmp(url_scheme, "https"));  
1147  
1148 for (domain_str = (char *) url_host;  
1149 domain_str != NULL && *domain_str;  
1150 domain_str = strchr(domain_str+1, '.')) {  
1498
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1151 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

1152 is_ssl); 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1153 } 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1154 if (!Cookies_domain_is_ip(url_host)) { 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1155 domain_str = dStrconcat(".", url_host, NULL); 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1156 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

1157 is_ssl); 
c04b0de69b00
cookies follow draft spec for domains
corvid <corvid@lavabit.com>
parents:
1497
diff
changeset

1158 dFree(domain_str); 
0  1159 } 
1160  
1161 /* Found the cookies, now make the string */  
1162 cookie_dstring = dStr_new("");  
1163 if (dList_length(matching_cookies) > 0) {  
1164  
1165 dStr_sprintfa(cookie_dstring, "Cookie: ");  
1166  
1167 for (i = 0; (cookie = dList_nth_data(matching_cookies, i)); ++i) {  
1168 dStr_sprintfa(cookie_dstring,  
1496
5bec8ce33a42
cookies: rm version, comment, comment url, port, Cookie2
corvid <corvid@lavabit.com>
parents:
1495
diff
changeset

1169 "%s=%s; $Path=%s; $Domain=%s", 
0  1170 cookie>name, cookie>value, 
1496
5bec8ce33a42
cookies: rm version, comment, comment url, port, Cookie2
corvid <corvid@lavabit.com>
parents:
1495
diff
changeset

1171 cookie>path, cookie>domain); 
0  1172 dStr_append(cookie_dstring, 
1173 dList_length(matching_cookies) > i + 1 ? "; " : "\r\n");  
1174 }  
1175 }  
1176  
1177 dList_free(matching_cookies);  
1178 str = cookie_dstring>str;  
1179 dStr_free(cookie_dstring, FALSE);  
1482
a749c1b10fbe
clean up cookie expiration/replacement and sessions
corvid <corvid@lavabit.com>
parents:
1481
diff
changeset

1180 _MSG("%s gets %s\n", url_host, str); 
0  1181 return str; 
1182 }  
1183  
1184 /*   
1185 * Access control routines  
1186 *  */  
1187  
1188  
1189 /*  
1190 * Get the cookie control rules (from cookiesrc).  
1191 * Return value:  
1192 * 0 = Parsed OK, with cookies enabled  
1193 * 1 = Parsed OK, with cookies disabled  
1194 * 2 = Can't open the control file  
1195 */  
1196 static int Cookie_control_init(void)  
1197 {  
1198 CookieControl cc;  
1199 FILE *stream;  
1200
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

1200 char *filename, *rc; 
0  1201 char line[LINE_MAXLEN]; 
1202 char domain[LINE_MAXLEN];  
1203 char rule[LINE_MAXLEN];  
1204 int i, j;  
1205 bool_t enabled = FALSE;  
1206  
1207 /* Get a file pointer */  
1208 filename = dStrconcat(dGethomedir(), "/.dillo/cookiesrc", NULL);  
219  1209 stream = Cookies_fopen(filename, "r", "DEFAULT DENY\n"); 
0  1210 dFree(filename); 
1211  
1212 if (!stream)  
1213 return 2;  
1214  
1215 /* Get all lines in the file */  
1216 while (!feof(stream)) {  
1217 line[0] = '\0';  
1200
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

1218 rc = fgets(line, LINE_MAXLEN, stream); 
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

1219 if (!rc && ferror(stream)) { 
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

1220 MSG("Cookies3: Error while reading rule from cookiesrc: %s\n", 
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

1221 dStrerror(errno)); 
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

1222 break; /* bail out */ 
6bdf6ea2637a
Removed compiler warnings for unused return values
Michal Nowak newman.x@gmail.com
parents:
1127
diff
changeset

1223 } 
0  1224 
1225 /* Remove leading and trailing whitespaces */  
1226 dStrstrip(line);  
1227  
1228 if (line[0] != '\0' && line[0] != '#') {  
1229 i = 0;  
1230 j = 0;  
1231  
1232 /* Get the domain */  
1221
f34b803b8639
Handle signed chars. Aadded dIsspace() and dIsalnum() to dlib
Jorge Arellano Cid <jcid@dillo.org>
parents:
1201
diff
changeset

1233 while (line[i] != '\0' && !dIsspace(line[i])) 
0  1234 domain[j++] = line[i++]; 
1235 domain[j] = '\0';  
1236  
1237 /* Skip past whitespaces */  
1221
f34b803b8639
Handle signed chars. Aadded dIsspace() and dIsalnum() to dlib
Jorge Arellano Cid <jcid@dillo.org>
parents:
1201
diff
changeset

1238 while (dIsspace(line[i])) 
0  1239 i++; 
1240  
1241 /* Get the rule */  
1242 j = 0;  
1221
f34b803b8639
Handle signed chars. Aadded dIsspace() and dIsalnum() to dlib
Jorge Arellano Cid <jcid@dillo.org>
parents:
1201
diff
changeset

1243 while (line[i] != '\0' && !dIsspace(line[i])) 
0  1244 rule[j++] = line[i++]; 
1245 rule[j] = '\0';  
1246  
1247 if (dStrcasecmp(rule, "ACCEPT") == 0)  
1248 cc.action = COOKIE_ACCEPT;  
1249 else if (dStrcasecmp(rule, "ACCEPT_SESSION") == 0)  
1250 cc.action = COOKIE_ACCEPT_SESSION;  
1251 else if (dStrcasecmp(rule, "DENY") == 0)  
1252 cc.action = COOKIE_DENY;  
1253 else {  
1254 MSG("Cookies: rule '%s' for domain '%s' is not recognised.\n",  
1255 rule, domain);  
1256 continue;  
1257 }  
1258  
1259 cc.domain = dStrdup(domain);  
1260 if (dStrcasecmp(cc.domain, "DEFAULT") == 0) {  
1261 /* Set the default action */  
1262 default_action = cc.action;  
1263 dFree(cc.domain);  
1264 } else {  
1265 a_List_add(ccontrol, num_ccontrol, num_ccontrol_max);  
1266 ccontrol[num_ccontrol++] = cc;  
1267 }  
1268  
1269 if (cc.action != COOKIE_DENY)  
1270 enabled = TRUE;  
1271 }  
1272 }  
1273  
1274 fclose(stream);  
1275  
1276 return (enabled ? 0 : 1);  
1277 }  
1278  
1279 /*  
1280 * Check the rules for an appropriate action for this domain  
1281 */  
1282 static CookieControlAction Cookies_control_check_domain(const char *domain)  
1283 {  
1284 int i, diff;  
1285  
1286 for (i = 0; i < num_ccontrol; i++) {  
1287 if (ccontrol[i].domain[0] == '.') {  
1288 diff = strlen(domain)  strlen(ccontrol[i].domain);  
1289 if (diff >= 0) {  
1290 if (dStrcasecmp(domain + diff, ccontrol[i].domain) != 0)  
1291 continue;  
1292 } else {  
1293 continue;  
1294 }  
1295 } else {  
1296 if (dStrcasecmp(domain, ccontrol[i].domain) != 0)  
1297 continue;  
1298 }  
1299  
1300 /* If we got here we have a match */  
1301 return( ccontrol[i].action );  
1302 }  
1303  
1304 return default_action;  
1305 }  
1306  
1307 /*  Dpi parser  */  
1308  
1309 /*  
1310 * Parse a data stream (dpi protocol)  
1311 * Note: Buf is a zero terminated string  
1312 * Return code: { 0:OK, 1:Abort, 2:Close }  
1313 */  
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1314 static int srv_parse_tok(Dsh *sh, ClientInfo *client, char *Buf) 
0  1315 { 
1496
5bec8ce33a42
cookies: rm version, comment, comment url, port, Cookie2
corvid <corvid@lavabit.com>
parents:
1495
diff
changeset

1316 char *cmd, *cookie, *host, *path, *scheme; 
5bec8ce33a42
cookies: rm version, comment, comment url, port, Cookie2
corvid <corvid@lavabit.com>
parents:
1495
diff
changeset

1317 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

1318 size_t BufSize = strlen(Buf); 
0  1319 
1236
b912173aecd1
Added a_Dpip_get_attr_l() to DPIP's API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1221
diff
changeset

1320 cmd = a_Dpip_get_attr_l(Buf, BufSize, "cmd"); 
0  1321 
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1322 if (!cmd) { 
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1323 /* abort */ 
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1324 } 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

1325 /* authenticate */ 
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1326 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

1327 client>status = 1; 
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1328 ret = 0; 
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1329 } 
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1330 } else if (strcmp(cmd, "DpiBye") == 0) { 
0  1331 dFree(cmd); 
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1332 MSG("(pid %d): Got DpiBye.\n", (int)getpid()); 
0  1333 exit(0); 
1334  
1335 } else if (cmd && strcmp(cmd, "set_cookie") == 0) {  
1336 dFree(cmd);  
1236
b912173aecd1
Added a_Dpip_get_attr_l() to DPIP's API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1221
diff
changeset

1337 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

1338 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

1339 path = a_Dpip_get_attr_l(Buf, BufSize, "path"); 
0  1340 
1496
5bec8ce33a42
cookies: rm version, comment, comment url, port, Cookie2
corvid <corvid@lavabit.com>
parents:
1495
diff
changeset

1341 Cookies_set(cookie, host, path); 
0  1342 
1343 dFree(path);  
1344 dFree(host);  
1345 dFree(cookie);  
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1346 ret = 2; 
0  1347 
1348 } else if (cmd && strcmp(cmd, "get_cookie") == 0) {  
1349 dFree(cmd);  
1236
b912173aecd1
Added a_Dpip_get_attr_l() to DPIP's API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1221
diff
changeset

1350 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

1351 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

1352 path = a_Dpip_get_attr_l(Buf, BufSize, "path"); 
0  1353 
1496
5bec8ce33a42
cookies: rm version, comment, comment url, port, Cookie2
corvid <corvid@lavabit.com>
parents:
1495
diff
changeset

1354 cookie = Cookies_get(host, path, scheme); 
0  1355 dFree(scheme); 
1356 dFree(path);  
1357 dFree(host);  
1358  
1359 cmd = a_Dpip_build_cmd("cmd=%s cookie=%s", "get_cookie_answer", cookie);  
1360  
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1361 if (a_Dpip_dsh_write_str(sh, 1, cmd)) { 
174
67e98a1211f0
 Fixed a cookiesrelated dillo freeze bug happening at:
jcid
parents:
159
diff
changeset

1362 ret = 1; 
67e98a1211f0
 Fixed a cookiesrelated dillo freeze bug happening at:
jcid
parents:
159
diff
changeset

1363 } else { 
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1364 _MSG("a_Dpip_dsh_write_str: SUCCESS cmd={%s}\n", cmd); 
174
67e98a1211f0
 Fixed a cookiesrelated dillo freeze bug happening at:
jcid
parents:
159
diff
changeset

1365 ret = 2; 
0  1366 } 
1367 dFree(cookie);  
1368 dFree(cmd);  
1369 }  
1370  
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1371 return ret; 
0  1372 } 
1373  
1374 /*  Termination handlers  */  
1375 /*  
1376 * (was to delete the local namespace socket),  
1377 * but this is handled by 'dpid' now.  
1378 */  
1379 static void cleanup(void)  
1380 {  
1381 Cookies_save_and_free();  
1382 MSG("cleanup\n");  
1383 /* no more cleanup required */  
1384 }  
1385  
1386 /*  
1387 * Perform any necessary cleanups upon abnormal termination  
1388 */  
1389 static void termination_handler(int signum)  
1390 {  
1391 exit(signum);  
1392 }  
1393  
1394  
1395 /*  
1396 *  MAIN   
1397 */  
1385
eb98997886ec
Introduced the new tokenizing dsh API to DPIP
Jorge Arellano Cid <jcid@dillo.org>
parents:
1236
diff
changeset

1398 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

1399 struct sockaddr_in sin; 
0  1400 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

1401 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

1402 int sock_fd, code; 
0  1403 char *buf; 
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1404 Dsh *sh; 
0  1405 
1406 /* Arrange the cleanup function for terminations via exit() */  
1407 atexit(cleanup);  
1408  
1409 /* Arrange the cleanup function for abnormal terminations */  
1410 if (signal (SIGINT, termination_handler) == SIG_IGN)  
1411 signal (SIGINT, SIG_IGN);  
1412 if (signal (SIGHUP, termination_handler) == SIG_IGN)  
1413 signal (SIGHUP, SIG_IGN);  
1414 if (signal (SIGTERM, termination_handler) == SIG_IGN)  
1415 signal (SIGTERM, SIG_IGN);  
1416  
1417 Cookies_init();  
1418 MSG("(v.1) accepting connections...\n");  
1419  
1420 if (disabled)  
1421 exit(1);  
1422  
1423 /* 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

1424 address_size = sizeof(struct sockaddr_in); 
0  1425 
1426 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

1427 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

1428 if (sock_fd == 1) { 
0  1429 perror("[accept]"); 
1430 exit(1);  
1431 }  
1432  
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1433 /* 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

1434 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

1435 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

1436 client>sh = sh; 
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1437 client>status = 0; 
0  1438 
1439 while (1) {  
1440 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

1441 if ((buf = a_Dpip_dsh_read_token(sh, 1)) != NULL) { 
0  1442 /* Let's see what we fished... */ 
174
67e98a1211f0
 Fixed a cookiesrelated dillo freeze bug happening at:
jcid
parents:
159
diff
changeset

1443 _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

1444 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

1445 dFree(buf); 
0  1446 } 
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1447 
174
67e98a1211f0
 Fixed a cookiesrelated dillo freeze bug happening at:
jcid
parents:
159
diff
changeset

1448 _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

1449 if (code == 1) { 
0  1450 exit(1); 
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1451 } else if (code == 2) { 
0  1452 break; 
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1453 } 
0  1454 } 
1455  
1387
16cf380cd04c
Convert dpid, file dpi and cookies dpi to dsh API
Jorge Arellano Cid <jcid@dillo.org>
parents:
1385
diff
changeset

1456 _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

1457 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

1458 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

1459 dFree(client); 
0  1460 
1461 }/*while*/  
174
67e98a1211f0
 Fixed a cookiesrelated dillo freeze bug happening at:
jcid
parents:
159
diff
changeset

1462 
67e98a1211f0
 Fixed a cookiesrelated dillo freeze bug happening at:
jcid
parents:
159
diff
changeset

1463 return 0; 
0  1464 } 
1465  
1466 #endif /* !DISABLE_COOKIES */ 