GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/ftp/cookie.c Lines: 11 102 10.8 %
Date: 2017-11-07 Branches: 2 81 2.5 %

Line Branch Exec Source
1
/*	$OpenBSD: cookie.c,v 1.7 2017/01/21 08:33:07 krw Exp $	*/
2
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
19
#ifndef NOSSL
20
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,
52
	EXPIRES = 4, NAME = 5, VALUE = 6, DONE = 7
53
} field_t;
54
55
static struct cookiejar jar;
56
57
void
58
cookie_load(void)
59
{
60
	field_t		 field;
61
30
	size_t		 len;
62
	time_t		 date;
63
15
	char		*line;
64
	char		*lbuf;
65
	char		*param;
66
15
	const char	*estr;
67
	FILE		*fp;
68
	struct cookie	*ck;
69
70
15
	if (cookiefile == NULL)
71
15
		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
		}
90
		line[strcspn(line, "\r")] = '\0';
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,
140
				    INT_MAX, &estr);
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);
174
	}
175
	free(lbuf);
176
	fclose(fp);
177
15
}
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
32
	struct cookiejar tempjar;
188
189
16
	*pstr = NULL;
190
191
16
	if (cookiefile == NULL)
192
16
		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
16
}
229
230
#endif /* !SMALL */
231