GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/smtpd/smtpctl/../aliases.c Lines: 0 106 0.0 %
Date: 2017-11-07 Branches: 0 64 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: aliases.c,v 1.71 2016/08/31 10:18:08 gilles Exp $	*/
2
3
/*
4
 * Copyright (c) 2008 Gilles Chehade <gilles@poolp.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
#include <sys/types.h>
20
#include <sys/queue.h>
21
#include <sys/tree.h>
22
#include <sys/socket.h>
23
24
#include <ctype.h>
25
#include <errno.h>
26
#include <event.h>
27
#include <imsg.h>
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include <string.h>
31
#include <limits.h>
32
#include <util.h>
33
34
#include "smtpd.h"
35
#include "log.h"
36
37
static int aliases_expand_include(struct expand *, const char *);
38
39
int
40
aliases_get(struct expand *expand, const char *username)
41
{
42
	struct expandnode      *xn;
43
	char			buf[SMTPD_MAXLOCALPARTSIZE];
44
	size_t			nbaliases;
45
	int			ret;
46
	union lookup		lk;
47
	struct table	       *mapping = NULL;
48
	struct table	       *userbase = NULL;
49
	char		       *pbuf;
50
51
	mapping = expand->rule->r_mapping;
52
	userbase = expand->rule->r_userbase;
53
54
	xlowercase(buf, username, sizeof(buf));
55
56
	/* first, check if entry has a user-part tag */
57
	pbuf = strchr(buf, *env->sc_subaddressing_delim);
58
	if (pbuf) {
59
		ret = table_lookup(mapping, NULL, buf, K_ALIAS, &lk);
60
		if (ret < 0)
61
			return (-1);
62
		if (ret)
63
			goto expand;
64
		*pbuf = '\0';
65
	}
66
67
	/* no user-part tag, try looking up user */
68
	ret = table_lookup(mapping, NULL, buf, K_ALIAS, &lk);
69
	if (ret <= 0)
70
		return ret;
71
72
expand:
73
	/* foreach node in table_alias expandtree, we merge */
74
	nbaliases = 0;
75
	RB_FOREACH(xn, expandtree, &lk.expand->tree) {
76
		if (xn->type == EXPAND_INCLUDE)
77
			nbaliases += aliases_expand_include(expand,
78
			    xn->u.buffer);
79
		else {
80
			xn->mapping = mapping;
81
			xn->userbase = userbase;
82
			expand_insert(expand, xn);
83
			nbaliases++;
84
		}
85
	}
86
87
	expand_free(lk.expand);
88
89
	log_debug("debug: aliases_get: returned %zd aliases", nbaliases);
90
	return nbaliases;
91
}
92
93
int
94
aliases_virtual_get(struct expand *expand, const struct mailaddr *maddr)
95
{
96
	struct expandnode      *xn;
97
	union lookup		lk;
98
	char			buf[LINE_MAX];
99
	char			user[LINE_MAX];
100
	char			tag[LINE_MAX];
101
	char			domain[LINE_MAX];
102
	char		       *pbuf;
103
	int			nbaliases;
104
	int			ret;
105
	struct table	       *mapping = NULL;
106
	struct table	       *userbase = NULL;
107
108
	mapping = expand->rule->r_mapping;
109
	userbase = expand->rule->r_userbase;
110
111
	if (!bsnprintf(user, sizeof(user), "%s", maddr->user))
112
		return 0;
113
	if (!bsnprintf(domain, sizeof(domain), "%s", maddr->domain))
114
		return 0;
115
	xlowercase(user, user, sizeof(user));
116
	xlowercase(domain, domain, sizeof(domain));
117
118
	memset(tag, '\0', sizeof tag);
119
	pbuf = strchr(user, *env->sc_subaddressing_delim);
120
	if (pbuf) {
121
		if (!bsnprintf(tag, sizeof(tag), "%s", pbuf + 1))
122
			return 0;
123
		xlowercase(tag, tag, sizeof(tag));
124
		*pbuf = '\0';
125
	}
126
127
	/* first, check if entry has a user-part tag */
128
	if (tag[0]) {
129
		if (!bsnprintf(buf, sizeof(buf), "%s%c%s@%s",
130
			user, *env->sc_subaddressing_delim, tag, domain))
131
			return 0;
132
		ret = table_lookup(mapping, NULL, buf, K_ALIAS, &lk);
133
		if (ret < 0)
134
			return (-1);
135
		if (ret)
136
			goto expand;
137
	}
138
139
	/* then, check if entry exists without user-part tag */
140
	if (!bsnprintf(buf, sizeof(buf), "%s@%s", user, domain))
141
		return 0;
142
	ret = table_lookup(mapping, NULL, buf, K_ALIAS, &lk);
143
	if (ret < 0)
144
		return (-1);
145
	if (ret)
146
		goto expand;
147
148
	if (tag[0]) {
149
		/* Failed ? We lookup for username + user-part tag */
150
		if (!bsnprintf(buf, sizeof(buf), "%s%c%s",
151
			user, *env->sc_subaddressing_delim, tag))
152
			return 0;
153
		ret = table_lookup(mapping, NULL, buf, K_ALIAS, &lk);
154
		if (ret < 0)
155
			return (-1);
156
		if (ret)
157
			goto expand;
158
	}
159
160
	/* Failed ? We lookup for username only */
161
	if (!bsnprintf(buf, sizeof(buf), "%s", user))
162
		return 0;
163
	ret = table_lookup(mapping, NULL, buf, K_ALIAS, &lk);
164
	if (ret < 0)
165
		return (-1);
166
	if (ret)
167
		goto expand;
168
169
	if (!bsnprintf(buf, sizeof(buf), "@%s", domain))
170
		return 0;
171
	/* Failed ? We lookup for catch all for virtual domain */
172
	ret = table_lookup(mapping, NULL, buf, K_ALIAS, &lk);
173
	if (ret < 0)
174
		return (-1);
175
	if (ret)
176
		goto expand;
177
178
	/* Failed ? We lookup for a *global* catch all */
179
	ret = table_lookup(mapping, NULL, "@", K_ALIAS, &lk);
180
	if (ret <= 0)
181
		return (ret);
182
183
expand:
184
	/* foreach node in table_virtual expand, we merge */
185
	nbaliases = 0;
186
	RB_FOREACH(xn, expandtree, &lk.expand->tree) {
187
		if (xn->type == EXPAND_INCLUDE)
188
			nbaliases += aliases_expand_include(expand,
189
			    xn->u.buffer);
190
		else {
191
			xn->mapping = mapping;
192
			xn->userbase = userbase;
193
			expand_insert(expand, xn);
194
			nbaliases++;
195
		}
196
	}
197
198
	expand_free(lk.expand);
199
200
	log_debug("debug: aliases_virtual_get: '%s' resolved to %d nodes",
201
	    buf, nbaliases);
202
203
	return nbaliases;
204
}
205
206
static int
207
aliases_expand_include(struct expand *expand, const char *filename)
208
{
209
	FILE *fp;
210
	char *line;
211
	size_t len, lineno = 0;
212
	char delim[3] = { '\\', '#', '\0' };
213
214
	fp = fopen(filename, "r");
215
	if (fp == NULL) {
216
		log_warn("warn: failed to open include file \"%s\".", filename);
217
		return 0;
218
	}
219
220
	while ((line = fparseln(fp, &len, &lineno, delim, 0)) != NULL) {
221
		expand_line(expand, line, 0);
222
		free(line);
223
	}
224
225
	fclose(fp);
226
	return 1;
227
}