Annotation of src/usr.bin/ftp/cookie.c, Revision 1.10
1.10 ! naddy 1: /* $OpenBSD: cookie.c,v 1.9 2019/05/16 12:44:17 florian Exp $ */
1.5 martynas 2:
1.1 pyr 3: /*
4: * Copyright (c) 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
1.6 deraadt 19: #ifndef NOSSL
1.5 martynas 20:
1.1 pyr 21: #include <sys/types.h>
22: #include <sys/queue.h>
23:
24: #include <err.h>
25: #include <errno.h>
26: #include <fnmatch.h>
27: #include <stdio.h>
28: #include <string.h>
29: #include <stdlib.h>
30: #include <time.h>
31:
32: #include "ftp_var.h"
33:
34: struct cookie {
35: TAILQ_ENTRY(cookie) entry;
36: TAILQ_ENTRY(cookie) tempentry;
37: u_int8_t flags;
38: #define F_SECURE 0x01
39: #define F_TAILMATCH 0x02
40: #define F_NOEXPIRY 0x04
41: #define F_MATCHPATH 0x08
42: time_t expires;
43: char *domain;
44: char *path;
45: char *key;
46: char *val;
47: };
48: TAILQ_HEAD(cookiejar, cookie);
49:
50: typedef enum {
51: DOMAIN = 0, TAILMATCH = 1, PATH = 2, SECURE = 3,
1.7 krw 52: EXPIRES = 4, NAME = 5, VALUE = 6, DONE = 7
1.1 pyr 53: } field_t;
54:
55: static struct cookiejar jar;
56:
57: void
58: cookie_load(void)
59: {
60: field_t field;
61: time_t date;
62: char *line;
1.10 ! naddy 63: char *lbuf = NULL;
! 64: size_t lbufsize = 0;
1.1 pyr 65: char *param;
66: const char *estr;
67: FILE *fp;
68: struct cookie *ck;
69:
70: if (cookiefile == NULL)
71: return;
72:
73: TAILQ_INIT(&jar);
74: fp = fopen(cookiefile, "r");
75: if (fp == NULL)
76: err(1, "cannot open cookie file %s", cookiefile);
77: date = time(NULL);
1.10 ! naddy 78: while (getline(&lbuf, &lbufsize, fp) != -1) {
! 79: line = lbuf;
! 80: line[strcspn(line, "\r\n")] = '\0';
1.1 pyr 81:
82: line += strspn(line, " \t");
83: if ((*line == '#') || (*line == '\0')) {
84: continue;
85: }
86: field = DOMAIN;
87: ck = calloc(1, sizeof(*ck));
88: if (ck == NULL)
89: err(1, NULL);
90: while ((param = strsep(&line, "\t")) != NULL) {
91: switch (field) {
92: case DOMAIN:
93: if (*param == '.') {
94: if (asprintf(&ck->domain,
95: "*%s", param) == -1)
96: err(1, NULL);
97: } else {
98: ck->domain = strdup(param);
99: if (ck->domain == NULL)
100: err(1, NULL);
101: }
102: break;
103: case TAILMATCH:
104: if (strcasecmp(param, "TRUE") == 0) {
105: ck->flags |= F_TAILMATCH;
106: } else if (strcasecmp(param, "FALSE") != 0) {
107: errx(1, "invalid cookie file");
108: }
109: break;
110: case PATH:
111: if (strcmp(param, "/") != 0) {
112: ck->flags |= F_MATCHPATH;
113: if (asprintf(&ck->path,
114: "%s*", param) == -1)
115: err(1, NULL);
116: }
117: break;
118: case SECURE:
119: if (strcasecmp(param, "TRUE") == 0) {
120: ck->flags |= F_SECURE;
121: } else if (strcasecmp(param, "FALSE") != 0) {
122: errx(1, "invalid cookie file");
123: }
124: break;
125: case EXPIRES:
126: /*
127: * rely on sizeof(time_t) being 4
128: */
129: ck->expires = strtonum(param, 0,
1.4 cloder 130: INT_MAX, &estr);
1.1 pyr 131: if (estr) {
132: if (errno == ERANGE)
133: ck->flags |= F_NOEXPIRY;
134: else
135: errx(1, "invalid cookie file");
136: }
137: break;
138: case NAME:
139: ck->key = strdup(param);
140: if (ck->key == NULL)
141: err(1, NULL);
142: break;
143: case VALUE:
144: ck->val = strdup(param);
145: if (ck->val == NULL)
146: err(1, NULL);
147: break;
148: case DONE:
149: errx(1, "invalid cookie file");
150: break;
151: }
152: field++;
153: }
154: if (field != DONE)
155: errx(1, "invalid cookie file");
156: if (ck->expires < date && !(ck->flags & F_NOEXPIRY)) {
157: free(ck->val);
158: free(ck->key);
159: free(ck->path);
160: free(ck->domain);
161: free(ck);
162: } else
163: TAILQ_INSERT_TAIL(&jar, ck, entry);
1.7 krw 164: }
1.1 pyr 165: free(lbuf);
166: fclose(fp);
167: }
168:
169: void
170: cookie_get(const char *domain, const char *path, int secure, char **pstr)
171: {
172: size_t len;
173: size_t headlen;
174: char *head;
175: char *str;
176: struct cookie *ck;
177: struct cookiejar tempjar;
178:
179: *pstr = NULL;
180:
181: if (cookiefile == NULL)
182: return;
183:
184: TAILQ_INIT(&tempjar);
185: len = strlen("Cookie\r\n");
186:
187: TAILQ_FOREACH(ck, &jar, entry) {
188: if (fnmatch(ck->domain, domain, 0) == 0 &&
189: (secure || !(ck->flags & F_SECURE))) {
190:
191: if (ck->flags & F_MATCHPATH &&
192: fnmatch(ck->path, path, 0) != 0)
193: continue;
194:
195: len += strlen(ck->key) + strlen(ck->val) +
196: strlen("; =");
197: TAILQ_INSERT_TAIL(&tempjar, ck, tempentry);
198: }
199: }
200: if (TAILQ_EMPTY(&tempjar))
201: return;
202: len += 1;
203: str = malloc(len);
204: if (str == NULL)
205: err(1, NULL);
206:
207: (void)strlcpy(str, "Cookie:", len);
208: TAILQ_FOREACH(ck, &tempjar, tempentry) {
209: head = str + strlen(str);
210: headlen = len - strlen(str);
211:
212: snprintf(head, headlen, "%s %s=%s",
213: (ck == TAILQ_FIRST(&tempjar))? "" : ";", ck->key, ck->val);
214: }
215: if (strlcat(str, "\r\n", len) >= len)
216: errx(1, "cookie header truncated");
217: *pstr = str;
218: }
219:
1.3 martynas 220: #endif /* !SMALL */
1.5 martynas 221: