GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/smtpd/smtpd/../table_static.c Lines: 0 105 0.0 %
Date: 2017-11-13 Branches: 0 90 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: table_static.c,v 1.17 2017/08/29 07:37:11 eric Exp $	*/
2
3
/*
4
 * Copyright (c) 2013 Eric Faurot <eric@openbsd.org>
5
 * Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <sys/types.h>
21
#include <sys/queue.h>
22
#include <sys/tree.h>
23
#include <sys/socket.h>
24
25
#include <netinet/in.h>
26
#include <arpa/inet.h>
27
28
#include <ctype.h>
29
#include <err.h>
30
#include <event.h>
31
#include <fcntl.h>
32
#include <imsg.h>
33
#include <stdio.h>
34
#include <stdlib.h>
35
#include <limits.h>
36
#include <string.h>
37
38
#include "smtpd.h"
39
#include "log.h"
40
41
/* static backend */
42
static int table_static_config(struct table *);
43
static int table_static_update(struct table *);
44
static void *table_static_open(struct table *);
45
static int table_static_lookup(void *, struct dict *, const char *,
46
    enum table_service, union lookup *);
47
static int table_static_fetch(void *, struct dict *, enum table_service,
48
    union lookup *);
49
static void  table_static_close(void *);
50
51
struct table_backend table_backend_static = {
52
	K_ALIAS|K_CREDENTIALS|K_DOMAIN|K_NETADDR|K_USERINFO|
53
	K_SOURCE|K_MAILADDR|K_ADDRNAME|K_MAILADDRMAP,
54
	table_static_config,
55
	table_static_open,
56
	table_static_update,
57
	table_static_close,
58
	table_static_lookup,
59
	table_static_fetch
60
};
61
62
static struct keycmp {
63
	enum table_service	service;
64
	int		       (*func)(const char *, const char *);
65
} keycmp[] = {
66
	{ K_DOMAIN, table_domain_match },
67
	{ K_NETADDR, table_netaddr_match },
68
	{ K_MAILADDR, table_mailaddr_match }
69
};
70
71
72
static int
73
table_static_config(struct table *t)
74
{
75
	FILE	*fp;
76
	char	*buf = NULL, *p;
77
	int	 lineno = 0;
78
	size_t	 sz = 0;
79
	ssize_t	 flen;
80
	char	*keyp;
81
	char	*valp;
82
	size_t	 ret = 0;
83
84
	/* no config ? ok */
85
	if (*t->t_config == '\0')
86
		return 1;
87
88
	if ((fp = fopen(t->t_config, "r")) == NULL) {
89
		log_warn("warn: Table \"%s\"", t->t_config);
90
		return 0;
91
	}
92
93
	while ((flen = getline(&buf, &sz, fp)) != -1) {
94
		lineno++;
95
		if (buf[flen - 1] == '\n')
96
			buf[--flen] = '\0';
97
98
		keyp = buf;
99
		while (isspace((unsigned char)*keyp)) {
100
			++keyp;
101
			--flen;
102
		}
103
		if (*keyp == '\0')
104
			continue;
105
		while (isspace((unsigned char)keyp[flen - 1]))
106
			keyp[--flen] = '\0';
107
		if (*keyp == '#') {
108
			if (t->t_type == T_NONE) {
109
				keyp++;
110
				while (isspace((unsigned char)*keyp))
111
					++keyp;
112
				if (!strcmp(keyp, "@list"))
113
					t->t_type = T_LIST;
114
			}
115
			continue;
116
		}
117
118
		if (t->t_type == T_NONE) {
119
			for (p = keyp; *p; p++) {
120
				if (*p == ' ' || *p == '\t' || *p == ':') {
121
					t->t_type = T_HASH;
122
					break;
123
				}
124
			}
125
			if (t->t_type == T_NONE)
126
				t->t_type = T_LIST;
127
		}
128
129
		if (t->t_type == T_LIST) {
130
			table_add(t, keyp, NULL);
131
			continue;
132
		}
133
134
		/* T_HASH */
135
		valp = keyp;
136
		strsep(&valp, " \t:");
137
		if (valp) {
138
			while (*valp) {
139
				if (!isspace((unsigned char)*valp) &&
140
				    !(*valp == ':' &&
141
				    isspace((unsigned char)*(valp + 1))))
142
					break;
143
				++valp;
144
			}
145
			if (*valp == '\0')
146
				valp = NULL;
147
		}
148
		if (valp == NULL) {
149
			log_warnx("%s: invalid map entry line %d", t->t_config,
150
			    lineno);
151
			goto end;
152
		}
153
154
		table_add(t, keyp, valp);
155
	}
156
157
	if (ferror(fp)) {
158
		log_warn("%s: getline", t->t_config);
159
		goto end;
160
	}
161
162
	/* Accept empty alias files; treat them as hashes */
163
	if (t->t_type == T_NONE && t->t_backend->services & K_ALIAS)
164
	    t->t_type = T_HASH;
165
166
	ret = 1;
167
end:
168
	free(buf);
169
	fclose(fp);
170
	return ret;
171
}
172
173
static int
174
table_static_update(struct table *table)
175
{
176
	struct table	*t;
177
	void		*p = NULL;
178
179
	/* no config ? ok */
180
	if (table->t_config[0] == '\0')
181
		goto ok;
182
183
	t = table_create("static", table->t_name, "update", table->t_config);
184
	if (!table_config(t))
185
		goto err;
186
187
	/* replace former table, frees t */
188
	while (dict_poproot(&table->t_dict, (void **)&p))
189
		free(p);
190
	dict_merge(&table->t_dict, &t->t_dict);
191
	table_destroy(t);
192
193
ok:
194
	log_info("info: Table \"%s\" successfully updated", table->t_name);
195
	return 1;
196
197
err:
198
	table_destroy(t);
199
	log_info("info: Failed to update table \"%s\"", table->t_name);
200
	return 0;
201
}
202
203
static void *
204
table_static_open(struct table *table)
205
{
206
	return table;
207
}
208
209
static void
210
table_static_close(void *hdl)
211
{
212
	return;
213
}
214
215
static int
216
table_static_lookup(void *hdl, struct dict *params, const char *key,
217
    enum table_service service, union lookup *lk)
218
{
219
	struct table   *m  = hdl;
220
	char	       *line;
221
	int		ret;
222
	int	       (*match)(const char *, const char *) = NULL;
223
	size_t		i;
224
	void	       *iter;
225
	const char     *k;
226
	char	       *v;
227
228
	for (i = 0; i < nitems(keycmp); ++i)
229
		if (keycmp[i].service == service)
230
			match = keycmp[i].func;
231
232
	line = NULL;
233
	iter = NULL;
234
	ret = 0;
235
	while (dict_iter(&m->t_dict, &iter, &k, (void **)&v)) {
236
		if (match) {
237
			if (match(key, k)) {
238
				line = v;
239
				ret = 1;
240
			}
241
		}
242
		else {
243
			if (strcmp(key, k) == 0) {
244
				line = v;
245
				ret = 1;
246
			}
247
		}
248
		if (ret)
249
			break;
250
	}
251
252
	if (lk == NULL)
253
		return ret ? 1 : 0;
254
255
	if (ret == 0)
256
		return 0;
257
258
	return table_parse_lookup(service, key, line, lk);
259
}
260
261
static int
262
table_static_fetch(void *hdl, struct dict *params,
263
    enum table_service service, union lookup *lk)
264
{
265
	struct table   *t = hdl;
266
	const char     *k;
267
268
	if (!dict_iter(&t->t_dict, &t->t_iter, &k, (void **)NULL)) {
269
		t->t_iter = NULL;
270
		if (!dict_iter(&t->t_dict, &t->t_iter, &k, (void **)NULL))
271
			return 0;
272
	}
273
274
	if (lk == NULL)
275
		return 1;
276
277
	return table_parse_lookup(service, NULL, k, lk);
278
}