Dillo v3.2.0-93-g6a586845
Loading...
Searching...
No Matches
cookies.c
Go to the documentation of this file.
1/*
2 * File: cookies.c
3 *
4 * Copyright 2001 Lars Clausen <lrclause@cs.uiuc.edu>
5 * Jörgen Viksell <jorgen.viksell@telia.com>
6 * Copyright 2025 Rodrigo Arias Mallo <rodarima@gmail.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 */
13
19#include "msg.h"
20
21#ifdef DISABLE_COOKIES
22
26void a_Cookies_init(void)
27{
28 MSG("Cookies: absolutely disabled at compilation time.\n");
29}
30
31#else
32
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <sys/file.h>
36#include <fcntl.h>
37#include <unistd.h>
38#include <stdlib.h>
39#include <stdio.h>
40#include <ctype.h>
41#include <errno.h>
42
43#include "IO/Url.h"
44#include "list.h"
45#include "cookies.h"
46#include "capi.h"
47#include "../dpip/dpip.h"
48
49
51#define LINE_MAXLEN 4096
52
58
59typedef struct {
61 char *domain;
62} CookieControl;
63
64/* Variables for access control */
65static CookieControl *ccontrol = NULL;
66static int num_ccontrol = 0;
67static int num_ccontrol_max = 1;
69
71
72static FILE *Cookies_fopen(const char *file, char *init_str);
74static CookieControlAction Cookies_control_check_domain(const char *domain);
75static int Cookie_control_init(void);
76
81static FILE *Cookies_fopen(const char *filename, char *init_str)
82{
83 FILE *F_in;
84 int fd, rc;
85
86 if ((F_in = fopen(filename, "r")) == NULL) {
87 /* Create the file */
88 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
89 if (fd != -1) {
90 if (init_str) {
91 rc = write(fd, init_str, strlen(init_str));
92 if (rc == -1) {
93 MSG("Cookies: Could not write initial string to file %s: %s\n",
94 filename, dStrerror(errno));
95 }
96 }
97 dClose(fd);
98
99 MSG("Cookies: Created file: %s\n", filename);
100 F_in = fopen(filename, "r");
101 } else {
102 MSG("Cookies: Could not create file: %s!\n", filename);
103 }
104 }
105
106 if (F_in) {
107 /* set close on exec */
108 fcntl(fileno(F_in), F_SETFD, FD_CLOEXEC | fcntl(fileno(F_in), F_GETFD));
109 }
110
111 return F_in;
112}
113
119{
120 /* Default setting */
121 disabled = TRUE;
122
123 /* Read and parse the cookie control file (cookiesrc) */
124 if (Cookie_control_init() != 0) {
125 MSG("Disabling cookies.\n");
126 return;
127 }
128
129 MSG("Enabling cookies as from cookiesrc...\n");
130 disabled = FALSE;
131}
132
137{
138}
139
143void a_Cookies_set(Dlist *cookie_strings, const DilloUrl *set_url,
144 const char *date)
145{
146 CookieControlAction action;
147 char *cmd, *cookie_string, *dpip_tag;
148 const char *path;
149 int i;
150
151 if (disabled)
152 return;
153
154 action = Cookies_control_check(set_url);
155 if (action == COOKIE_DENY) {
156 _MSG("Cookies: denied SET for %s\n", URL_HOST_(set_url));
157 return;
158 }
159
160 for (i = 0; (cookie_string = dList_nth_data(cookie_strings, i)); ++i) {
161 path = URL_PATH_(set_url);
162 if (date)
163 cmd = a_Dpip_build_cmd("cmd=%s cookie=%s host=%s path=%s date=%s",
164 "set_cookie", cookie_string,
165 URL_HOST_(set_url), path ? path : "/", date);
166 else
167 cmd = a_Dpip_build_cmd("cmd=%s cookie=%s host=%s path=%s",
168 "set_cookie", cookie_string,
169 URL_HOST_(set_url), path ? path : "/");
170
171 _MSG("Cookies.c: a_Cookies_set \n\t \"%s\" \n",cmd );
172 /* This call is commented because it doesn't guarantee the order
173 * in which cookies are set and got. (It may deadlock too) */
174 //a_Capi_dpi_send_cmd(NULL, NULL, cmd, "cookies", 1);
175
176 dpip_tag = a_Dpi_send_blocking_cmd("cookies", cmd);
177 _MSG("a_Cookies_set: dpip_tag = {%s}\n", dpip_tag);
178 dFree(dpip_tag);
179 dFree(cmd);
180 }
181}
182
186char *a_Cookies_get_query(const DilloUrl *query_url, const DilloUrl *requester,
187 int is_root_url)
188{
189 char *cmd, *dpip_tag, *query;
190 const char *path;
191 CookieControlAction action;
192
193 if (disabled)
194 return dStrdup("");
195
196 action = Cookies_control_check(query_url);
197 if (action == COOKIE_DENY) {
198 _MSG("Cookies: denied GET for %s\n", URL_HOST_(query_url));
199 return dStrdup("");
200 }
201
202 if (requester == NULL) {
203 /* request made by user */
204 } else if (!is_root_url && !a_Url_same_organization(query_url, requester)) {
205 MSG("Cookies: not sent for non-root request by '%s' for '%s'\n",
206 URL_HOST(requester), URL_HOST(query_url));
207 return dStrdup("");
208 }
209
210 path = URL_PATH_(query_url);
211
212 cmd = a_Dpip_build_cmd("cmd=%s scheme=%s host=%s path=%s",
213 "get_cookie", URL_SCHEME(query_url),
214 URL_HOST(query_url), path ? path : "/");
215
216 /* Get the answer from cookies.dpi */
217 _MSG("cookies.c: a_Dpi_send_blocking_cmd cmd = {%s}\n", cmd);
218 dpip_tag = a_Dpi_send_blocking_cmd("cookies", cmd);
219 _MSG("cookies.c: after a_Dpi_send_blocking_cmd resp={%s}\n", dpip_tag);
220 dFree(cmd);
221
222 if (dpip_tag != NULL) {
223 query = a_Dpip_get_attr(dpip_tag, "cookie");
224 dFree(dpip_tag);
225 } else {
226 query = dStrdup("");
227 }
228 return query;
229}
230
231/* -------------------------------------------------------------
232 * Access control routines
233 * ------------------------------------------------------------- */
234
235
243static int Cookie_control_init(void)
244{
245 CookieControl cc;
246 FILE *stream;
247 char *filename, *rc;
248 char line[LINE_MAXLEN];
249 char domain[LINE_MAXLEN];
250 char rule[LINE_MAXLEN];
251 bool_t enabled = FALSE;
252
253 /* Get a file pointer */
254 filename = dStrconcat(dGethomedir(), "/.dillo/cookiesrc", NULL);
255 stream = Cookies_fopen(filename, "DEFAULT DENY\n");
256 dFree(filename);
257
258 if (!stream)
259 return 2;
260
261 /* Get all lines in the file */
262 while (!feof(stream)) {
263 line[0] = '\0';
264 rc = fgets(line, LINE_MAXLEN, stream);
265 if (!rc && ferror(stream)) {
266 MSG("Cookies1: Error while reading rule from cookiesrc: %s\n",
267 dStrerror(errno));
268 fclose(stream);
269 return 2; /* bail out */
270 }
271
272 /* Remove leading and trailing whitespaces */
273 dStrstrip(line);
274
275 if (line[0] != '\0' && line[0] != '#') {
276 int i = 0, j = 0;
277
278 /* Get the domain */
279 while (line[i] != '\0' && !dIsspace(line[i]))
280 domain[j++] = line[i++];
281 domain[j] = '\0';
282
283 /* Skip past whitespaces */
284 while (dIsspace(line[i]))
285 i++;
286
287 /* Get the rule */
288 j = 0;
289 while (line[i] != '\0' && !dIsspace(line[i]))
290 rule[j++] = line[i++];
291 rule[j] = '\0';
292
293 if (dStrAsciiCasecmp(rule, "ACCEPT") == 0)
294 cc.action = COOKIE_ACCEPT;
295 else if (dStrAsciiCasecmp(rule, "ACCEPT_SESSION") == 0)
296 cc.action = COOKIE_ACCEPT_SESSION;
297 else if (dStrAsciiCasecmp(rule, "DENY") == 0)
298 cc.action = COOKIE_DENY;
299 else {
300 MSG("Cookies: rule '%s' for domain '%s' is not recognised.\n",
301 rule, domain);
302 continue;
303 }
304
305 cc.domain = dStrdup(domain);
306 if (dStrAsciiCasecmp(cc.domain, "DEFAULT") == 0) {
307 /* Set the default action */
308 default_action = cc.action;
309 dFree(cc.domain);
310 } else {
311 int i;
312 uint_t len = strlen(cc.domain);
313
314 /* Insert into list such that longest rules come first. */
316 for (i = num_ccontrol++;
317 i > 0 && (len > strlen(ccontrol[i-1].domain));
318 i--) {
319 ccontrol[i] = ccontrol[i-1];
320 }
321 ccontrol[i] = cc;
322 }
323
324 if (cc.action != COOKIE_DENY)
325 enabled = TRUE;
326 }
327 }
328
329 fclose(stream);
330
331 return (enabled ? 0 : 1);
332}
333
340{
341 int i, diff;
342
343 for (i = 0; i < num_ccontrol; i++) {
344 if (ccontrol[i].domain[0] == '.') {
345 diff = strlen(domain) - strlen(ccontrol[i].domain);
346 if (diff >= 0) {
347 if (dStrAsciiCasecmp(domain + diff, ccontrol[i].domain) != 0)
348 continue;
349 } else {
350 continue;
351 }
352 } else {
353 if (dStrAsciiCasecmp(domain, ccontrol[i].domain) != 0)
354 continue;
355 }
356
357 /* If we got here we have a match */
358 return( ccontrol[i].action );
359 }
360
361 return default_action;
362}
363
371
372#endif /* !DISABLE_COOKIES */
unsigned int uint_t
Definition d_size.h:20
unsigned char bool_t
Definition d_size.h:21
char * dStrconcat(const char *s1,...)
Concatenate a NULL-terminated list of strings.
Definition dlib.c:102
void dFree(void *mem)
Definition dlib.c:68
int dStrAsciiCasecmp(const char *s1, const char *s2)
Definition dlib.c:203
char * dStrstrip(char *s)
Remove leading and trailing whitespace.
Definition dlib.c:122
char * dStrdup(const char *s)
Definition dlib.c:77
void * dList_nth_data(Dlist *lp, int n0)
Return the nth data item, NULL when not found or 'n0' is out of range.
Definition dlib.c:690
int dClose(int fd)
Close a FD handling EINTR.
Definition dlib.c:979
char * dGethomedir(void)
Return the home directory in a static string (don't free)
Definition dlib.c:934
#define dStrerror
Definition dlib.h:107
#define dIsspace(c)
Definition dlib.h:45
#define TRUE
Definition dlib.h:35
#define FALSE
Definition dlib.h:31
static int num_ccontrol
Definition cookies.c:128
#define _MSG(...)
Definition cookies.c:58
#define MSG(...)
Definition cookies.c:59
static int num_ccontrol_max
Definition cookies.c:129
static CookieControl * ccontrol
Definition cookies.c:127
static int Cookie_control_init(void)
Definition cookies.c:1418
#define a_List_add(list, num_items, alloc_step)
Definition cookies.c:68
static CookieControlAction default_action
Definition cookies.c:130
CookieControlAction
Definition cookies.c:84
@ COOKIE_ACCEPT_SESSION
Definition cookies.c:86
@ COOKIE_ACCEPT
Definition cookies.c:85
@ COOKIE_DENY
Definition cookies.c:87
static CookieControlAction Cookies_control_check_domain(const char *domain)
Definition cookies.c:1513
static bool_t disabled
Definition cookies.c:133
static FILE * Cookies_fopen(const char *filename, const char *mode, const char *init_str)
Definition cookies.c:191
#define LINE_MAXLEN
Definition cookies.c:79
char * a_Dpip_build_cmd(const char *format,...)
Printf like function for building dpip commands.
Definition dpip.c:83
char * a_Dpip_get_attr(const char *tag, const char *attrname)
Task: given a tag and an attribute name, return its value.
Definition dpip.c:192
Fast list methods.
char * a_Dpi_send_blocking_cmd(const char *server_name, const char *cmd)
Send a command to a dpi server, and block until the answer is got.
Definition dpi.c:774
void a_Cookies_init(void)
Initialize the cookies module (The 'disabled' variable is writable only within a_Cookies_init)
Definition cookies.c:118
static CookieControlAction Cookies_control_check(const DilloUrl *url)
Same as Cookies_control_check_domain except it takes an URL.
Definition cookies.c:367
void a_Cookies_freeall(void)
Flush cookies to disk and free all the memory allocated.
Definition cookies.c:136
void a_Cookies_set(Dlist *cookie_strings, const DilloUrl *set_url, const char *date)
Set the value corresponding to the cookie string.
Definition cookies.c:143
char * a_Cookies_get_query(const DilloUrl *query_url, const DilloUrl *requester, int is_root_url)
Return a string containing cookie data for an HTTP query.
Definition cookies.c:186
Definition url.h:88
Definition dlib.h:144
static void path()
Definition cookies.c:859
bool_t a_Url_same_organization(const DilloUrl *u1, const DilloUrl *u2)
Definition url.c:798
#define URL_HOST_(u)
Definition url.h:54
#define URL_SCHEME(u)
Definition url.h:70
#define URL_PATH_(u)
Definition url.h:51
#define URL_HOST(u)
Definition url.h:75