Dillo v3.2.0-151-g90488cbf
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 <errno.h>
41
42#include "IO/Url.h"
43#include "list.h"
44#include "cookies.h"
45#include "capi.h"
46#include "../dpip/dpip.h"
47
48
50#define LINE_MAXLEN 4096
51
57
58typedef struct {
60 char *domain;
61} CookieControl;
62
63/* Variables for access control */
64static CookieControl *ccontrol = NULL;
65static int num_ccontrol = 0;
66static int num_ccontrol_max = 1;
68
70
71static FILE *Cookies_fopen(const char *file, char *init_str);
73static CookieControlAction Cookies_control_check_domain(const char *domain);
74static int Cookie_control_init(void);
75
80static FILE *Cookies_fopen(const char *filename, char *init_str)
81{
82 FILE *F_in;
83 int fd, rc;
84
85 if ((F_in = fopen(filename, "r")) == NULL) {
86 /* Create the file */
87 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
88 if (fd != -1) {
89 if (init_str) {
90 rc = write(fd, init_str, strlen(init_str));
91 if (rc == -1) {
92 MSG("Cookies: Could not write initial string to file %s: %s\n",
93 filename, dStrerror(errno));
94 }
95 }
96 dClose(fd);
97
98 MSG("Cookies: Created file: %s\n", filename);
99 F_in = fopen(filename, "r");
100 } else {
101 MSG("Cookies: Could not create file: %s!\n", filename);
102 }
103 }
104
105 if (F_in) {
106 /* set close on exec */
107 fcntl(fileno(F_in), F_SETFD, FD_CLOEXEC | fcntl(fileno(F_in), F_GETFD));
108 }
109
110 return F_in;
111}
112
118{
119 /* Default setting */
120 disabled = TRUE;
121
122 /* Read and parse the cookie control file (cookiesrc) */
123 if (Cookie_control_init() != 0) {
124 MSG("Disabling cookies.\n");
125 return;
126 }
127
128 MSG("Enabling cookies as from cookiesrc...\n");
129 disabled = FALSE;
130}
131
136{
137}
138
142void a_Cookies_set(Dlist *cookie_strings, const DilloUrl *set_url,
143 const char *date)
144{
145 CookieControlAction action;
146 char *cmd, *cookie_string, *dpip_tag;
147 const char *path;
148 int i;
149
150 if (disabled)
151 return;
152
153 action = Cookies_control_check(set_url);
154 if (action == COOKIE_DENY) {
155 _MSG("Cookies: denied SET for %s\n", URL_HOST_(set_url));
156 return;
157 }
158
159 for (i = 0; (cookie_string = dList_nth_data(cookie_strings, i)); ++i) {
160 path = URL_PATH_(set_url);
161 if (date)
162 cmd = a_Dpip_build_cmd("cmd=%s cookie=%s host=%s path=%s date=%s",
163 "set_cookie", cookie_string,
164 URL_HOST_(set_url), path ? path : "/", date);
165 else
166 cmd = a_Dpip_build_cmd("cmd=%s cookie=%s host=%s path=%s",
167 "set_cookie", cookie_string,
168 URL_HOST_(set_url), path ? path : "/");
169
170 _MSG("Cookies.c: a_Cookies_set \n\t \"%s\" \n",cmd );
171 /* This call is commented because it doesn't guarantee the order
172 * in which cookies are set and got. (It may deadlock too) */
173 //a_Capi_dpi_send_cmd(NULL, NULL, cmd, "cookies", 1);
174
175 dpip_tag = a_Dpi_send_blocking_cmd("cookies", cmd);
176 _MSG("a_Cookies_set: dpip_tag = {%s}\n", dpip_tag);
177 dFree(dpip_tag);
178 dFree(cmd);
179 }
180}
181
185char *a_Cookies_get_query(const DilloUrl *query_url, const DilloUrl *requester,
186 int is_root_url)
187{
188 char *cmd, *dpip_tag, *query;
189 const char *path;
190 CookieControlAction action;
191
192 if (disabled)
193 return dStrdup("");
194
195 action = Cookies_control_check(query_url);
196 if (action == COOKIE_DENY) {
197 _MSG("Cookies: denied GET for %s\n", URL_HOST_(query_url));
198 return dStrdup("");
199 }
200
201 if (requester == NULL) {
202 /* request made by user */
203 } else if (!is_root_url && !a_Url_same_organization(query_url, requester)) {
204 MSG("Cookies: not sent for non-root request by '%s' for '%s'\n",
205 URL_HOST(requester), URL_HOST(query_url));
206 return dStrdup("");
207 }
208
209 path = URL_PATH_(query_url);
210
211 cmd = a_Dpip_build_cmd("cmd=%s scheme=%s host=%s path=%s",
212 "get_cookie", URL_SCHEME(query_url),
213 URL_HOST(query_url), path ? path : "/");
214
215 /* Get the answer from cookies.dpi */
216 _MSG("cookies.c: a_Dpi_send_blocking_cmd cmd = {%s}\n", cmd);
217 dpip_tag = a_Dpi_send_blocking_cmd("cookies", cmd);
218 _MSG("cookies.c: after a_Dpi_send_blocking_cmd resp={%s}\n", dpip_tag);
219 dFree(cmd);
220
221 if (dpip_tag != NULL) {
222 query = a_Dpip_get_attr(dpip_tag, "cookie");
223 dFree(dpip_tag);
224 } else {
225 query = dStrdup("");
226 }
227 return query;
228}
229
230/* -------------------------------------------------------------
231 * Access control routines
232 * ------------------------------------------------------------- */
233
234
242static int Cookie_control_init(void)
243{
244 CookieControl cc;
245 FILE *stream;
246 char *filename, *rc;
247 char line[LINE_MAXLEN];
248 char domain[LINE_MAXLEN];
249 char rule[LINE_MAXLEN];
250 bool_t enabled = FALSE;
251
252 /* Get a file pointer */
253 filename = dStrconcat(dGethomedir(), "/.dillo/cookiesrc", NULL);
254 stream = Cookies_fopen(filename, "DEFAULT DENY\n");
255 dFree(filename);
256
257 if (!stream)
258 return 2;
259
260 /* Get all lines in the file */
261 while (!feof(stream)) {
262 line[0] = '\0';
263 rc = fgets(line, LINE_MAXLEN, stream);
264 if (!rc && ferror(stream)) {
265 MSG("Cookies1: Error while reading rule from cookiesrc: %s\n",
266 dStrerror(errno));
267 fclose(stream);
268 return 2; /* bail out */
269 }
270
271 /* Remove leading and trailing whitespaces */
272 dStrstrip(line);
273
274 if (line[0] != '\0' && line[0] != '#') {
275 int i = 0, j = 0;
276
277 /* Get the domain */
278 while (line[i] != '\0' && !dIsspace(line[i]))
279 domain[j++] = line[i++];
280 domain[j] = '\0';
281
282 /* Skip past whitespaces */
283 while (dIsspace(line[i]))
284 i++;
285
286 /* Get the rule */
287 j = 0;
288 while (line[i] != '\0' && !dIsspace(line[i]))
289 rule[j++] = line[i++];
290 rule[j] = '\0';
291
292 if (dStrAsciiCasecmp(rule, "ACCEPT") == 0)
293 cc.action = COOKIE_ACCEPT;
294 else if (dStrAsciiCasecmp(rule, "ACCEPT_SESSION") == 0)
295 cc.action = COOKIE_ACCEPT_SESSION;
296 else if (dStrAsciiCasecmp(rule, "DENY") == 0)
297 cc.action = COOKIE_DENY;
298 else {
299 MSG("Cookies: rule '%s' for domain '%s' is not recognised.\n",
300 rule, domain);
301 continue;
302 }
303
304 cc.domain = dStrdup(domain);
305 if (dStrAsciiCasecmp(cc.domain, "DEFAULT") == 0) {
306 /* Set the default action */
307 default_action = cc.action;
308 dFree(cc.domain);
309 } else {
310 int i;
311 uint_t len = strlen(cc.domain);
312
313 /* Insert into list such that longest rules come first. */
315 for (i = num_ccontrol++;
316 i > 0 && (len > strlen(ccontrol[i-1].domain));
317 i--) {
318 ccontrol[i] = ccontrol[i-1];
319 }
320 ccontrol[i] = cc;
321 }
322
323 if (cc.action != COOKIE_DENY)
324 enabled = TRUE;
325 }
326 }
327
328 fclose(stream);
329
330 return (enabled ? 0 : 1);
331}
332
339{
340 int i, diff;
341
342 for (i = 0; i < num_ccontrol; i++) {
343 if (ccontrol[i].domain[0] == '.') {
344 diff = strlen(domain) - strlen(ccontrol[i].domain);
345 if (diff >= 0) {
346 if (dStrAsciiCasecmp(domain + diff, ccontrol[i].domain) != 0)
347 continue;
348 } else {
349 continue;
350 }
351 } else {
352 if (dStrAsciiCasecmp(domain, ccontrol[i].domain) != 0)
353 continue;
354 }
355
356 /* If we got here we have a match */
357 return( ccontrol[i].action );
358 }
359
360 return default_action;
361}
362
370
371#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:101
void dFree(void *mem)
Definition dlib.c:67
int dStrAsciiCasecmp(const char *s1, const char *s2)
Definition dlib.c:202
char * dStrstrip(char *s)
Remove leading and trailing whitespace.
Definition dlib.c:121
char * dStrdup(const char *s)
Definition dlib.c:76
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:689
int dClose(int fd)
Close a FD handling EINTR.
Definition dlib.c:978
char * dGethomedir(void)
Return the home directory in a static string (don't free)
Definition dlib.c:933
#define dStrerror
Definition dlib.h:124
static int dIsspace(unsigned char c)
Definition dlib.h:53
#define TRUE
Definition dlib.h:36
#define FALSE
Definition dlib.h:32
static int num_ccontrol
Definition cookies.c:127
#define _MSG(...)
Definition cookies.c:57
#define MSG(...)
Definition cookies.c:58
static int num_ccontrol_max
Definition cookies.c:128
static CookieControl * ccontrol
Definition cookies.c:126
static int Cookie_control_init(void)
Definition cookies.c:1417
#define a_List_add(list, num_items, alloc_step)
Definition cookies.c:67
static CookieControlAction default_action
Definition cookies.c:129
CookieControlAction
Definition cookies.c:83
@ COOKIE_ACCEPT_SESSION
Definition cookies.c:85
@ COOKIE_ACCEPT
Definition cookies.c:84
@ COOKIE_DENY
Definition cookies.c:86
static CookieControlAction Cookies_control_check_domain(const char *domain)
Definition cookies.c:1512
static bool_t disabled
Definition cookies.c:132
static FILE * Cookies_fopen(const char *filename, const char *mode, const char *init_str)
Definition cookies.c:190
#define LINE_MAXLEN
Definition cookies.c:78
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:773
void a_Cookies_init(void)
Initialize the cookies module (The 'disabled' variable is writable only within a_Cookies_init)
Definition cookies.c:117
static CookieControlAction Cookies_control_check(const DilloUrl *url)
Same as Cookies_control_check_domain except it takes an URL.
Definition cookies.c:366
void a_Cookies_freeall(void)
Flush cookies to disk and free all the memory allocated.
Definition cookies.c:135
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:142
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:185
Definition url.h:88
Definition dlib.h:161
static void path()
Definition cookies.c:858
bool_t a_Url_same_organization(const DilloUrl *u1, const DilloUrl *u2)
Definition url.c:797
#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