Annotation of src/usr.bin/ftp/cookie.c, Revision 1.7
1.7 ! krw 1: /* $OpenBSD: cookie.c,v 1.6 2016/12/28 17:48:04 deraadt 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: size_t len;
62: time_t date;
63: char *line;
64: char *lbuf;
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);
78: lbuf = NULL;
79: while ((line = fgetln(fp, &len)) != NULL) {
80: if (line[len - 1] == '\n') {
81: line[len - 1] = '\0';
82: --len;
83: } else {
84: if ((lbuf = malloc(len + 1)) == NULL)
85: err(1, NULL);
86: memcpy(lbuf, line, len);
87: lbuf[len] = '\0';
88: line = lbuf;
89: }
1.2 pyr 90: line[strcspn(line, "\r")] = '\0';
1.1 pyr 91:
92: line += strspn(line, " \t");
93: if ((*line == '#') || (*line == '\0')) {
94: continue;
95: }
96: field = DOMAIN;
97: ck = calloc(1, sizeof(*ck));
98: if (ck == NULL)
99: err(1, NULL);
100: while ((param = strsep(&line, "\t")) != NULL) {
101: switch (field) {
102: case DOMAIN:
103: if (*param == '.') {
104: if (asprintf(&ck->domain,
105: "*%s", param) == -1)
106: err(1, NULL);
107: } else {
108: ck->domain = strdup(param);
109: if (ck->domain == NULL)
110: err(1, NULL);
111: }
112: break;
113: case TAILMATCH:
114: if (strcasecmp(param, "TRUE") == 0) {
115: ck->flags |= F_TAILMATCH;
116: } else if (strcasecmp(param, "FALSE") != 0) {
117: errx(1, "invalid cookie file");
118: }
119: break;
120: case PATH:
121: if (strcmp(param, "/") != 0) {
122: ck->flags |= F_MATCHPATH;
123: if (asprintf(&ck->path,
124: "%s*", param) == -1)
125: err(1, NULL);
126: }
127: break;
128: case SECURE:
129: if (strcasecmp(param, "TRUE") == 0) {
130: ck->flags |= F_SECURE;
131: } else if (strcasecmp(param, "FALSE") != 0) {
132: errx(1, "invalid cookie file");
133: }
134: break;
135: case EXPIRES:
136: /*
137: * rely on sizeof(time_t) being 4
138: */
139: ck->expires = strtonum(param, 0,
1.4 cloder 140: INT_MAX, &estr);
1.1 pyr 141: if (estr) {
142: if (errno == ERANGE)
143: ck->flags |= F_NOEXPIRY;
144: else
145: errx(1, "invalid cookie file");
146: }
147: break;
148: case NAME:
149: ck->key = strdup(param);
150: if (ck->key == NULL)
151: err(1, NULL);
152: break;
153: case VALUE:
154: ck->val = strdup(param);
155: if (ck->val == NULL)
156: err(1, NULL);
157: break;
158: case DONE:
159: errx(1, "invalid cookie file");
160: break;
161: }
162: field++;
163: }
164: if (field != DONE)
165: errx(1, "invalid cookie file");
166: if (ck->expires < date && !(ck->flags & F_NOEXPIRY)) {
167: free(ck->val);
168: free(ck->key);
169: free(ck->path);
170: free(ck->domain);
171: free(ck);
172: } else
173: TAILQ_INSERT_TAIL(&jar, ck, entry);
1.7 ! krw 174: }
1.1 pyr 175: free(lbuf);
176: fclose(fp);
177: }
178:
179: void
180: cookie_get(const char *domain, const char *path, int secure, char **pstr)
181: {
182: size_t len;
183: size_t headlen;
184: char *head;
185: char *str;
186: struct cookie *ck;
187: struct cookiejar tempjar;
188:
189: *pstr = NULL;
190:
191: if (cookiefile == NULL)
192: return;
193:
194: TAILQ_INIT(&tempjar);
195: len = strlen("Cookie\r\n");
196:
197: TAILQ_FOREACH(ck, &jar, entry) {
198: if (fnmatch(ck->domain, domain, 0) == 0 &&
199: (secure || !(ck->flags & F_SECURE))) {
200:
201: if (ck->flags & F_MATCHPATH &&
202: fnmatch(ck->path, path, 0) != 0)
203: continue;
204:
205: len += strlen(ck->key) + strlen(ck->val) +
206: strlen("; =");
207: TAILQ_INSERT_TAIL(&tempjar, ck, tempentry);
208: }
209: }
210: if (TAILQ_EMPTY(&tempjar))
211: return;
212: len += 1;
213: str = malloc(len);
214: if (str == NULL)
215: err(1, NULL);
216:
217: (void)strlcpy(str, "Cookie:", len);
218: TAILQ_FOREACH(ck, &tempjar, tempentry) {
219: head = str + strlen(str);
220: headlen = len - strlen(str);
221:
222: snprintf(head, headlen, "%s %s=%s",
223: (ck == TAILQ_FIRST(&tempjar))? "" : ";", ck->key, ck->val);
224: }
225: if (strlcat(str, "\r\n", len) >= len)
226: errx(1, "cookie header truncated");
227: *pstr = str;
228: }
229:
1.3 martynas 230: #endif /* !SMALL */
1.5 martynas 231: