GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/smtpd/smtpd/../ruleset.c Lines: 0 55 0.0 %
Date: 2017-11-07 Branches: 0 80 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: ruleset.c,v 1.34 2017/02/13 12:23:47 gilles Exp $ */
2
3
/*
4
 * Copyright (c) 2009 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 <netinet/in.h>
25
26
#include <errno.h>
27
#include <event.h>
28
#include <imsg.h>
29
#include <stdio.h>
30
#include <string.h>
31
#include <limits.h>
32
33
#include "smtpd.h"
34
#include "log.h"
35
36
37
static int ruleset_check_source(struct table *,
38
    const struct sockaddr_storage *, int);
39
static int ruleset_check_mailaddr(struct table *, const struct mailaddr *);
40
41
struct rule *
42
ruleset_match(const struct envelope *evp)
43
{
44
	const struct mailaddr		*maddr = &evp->dest;
45
	const struct sockaddr_storage	*ss = &evp->ss;
46
	struct rule			*r;
47
	int				 ret;
48
49
	TAILQ_FOREACH(r, env->sc_rules, r_entry) {
50
51
		if (r->r_tag[0] != '\0') {
52
			ret = strcmp(r->r_tag, evp->tag);
53
			if (ret != 0 && !r->r_nottag)
54
				continue;
55
			if (ret == 0 && r->r_nottag)
56
				continue;
57
		}
58
59
		if ((r->r_wantauth && !r->r_negwantauth) && !(evp->flags & EF_AUTHENTICATED))
60
			continue;
61
		if ((r->r_wantauth && r->r_negwantauth) && (evp->flags & EF_AUTHENTICATED))
62
			continue;
63
64
		ret = ruleset_check_source(r->r_sources, ss, evp->flags);
65
		if (ret == -1) {
66
			errno = EAGAIN;
67
			return (NULL);
68
		}
69
		if ((ret == 0 && !r->r_notsources) || (ret != 0 && r->r_notsources))
70
			continue;
71
72
		if (r->r_senders) {
73
			ret = ruleset_check_mailaddr(r->r_senders, &evp->sender);
74
			if (ret == -1) {
75
				errno = EAGAIN;
76
				return (NULL);
77
			}
78
			if ((ret == 0 && !r->r_notsenders) || (ret != 0 && r->r_notsenders))
79
				continue;
80
		}
81
82
		if (r->r_recipients) {
83
			ret = ruleset_check_mailaddr(r->r_recipients, &evp->dest);
84
			if (ret == -1) {
85
				errno = EAGAIN;
86
				return (NULL);
87
			}
88
			if ((ret == 0 && !r->r_notrecipients) || (ret != 0 && r->r_notrecipients))
89
				continue;
90
		}
91
92
		ret = r->r_destination == NULL ? 1 :
93
		    table_lookup(r->r_destination, NULL, maddr->domain, K_DOMAIN,
94
			NULL);
95
		if (ret == -1) {
96
			errno = EAGAIN;
97
			return NULL;
98
		}
99
		if ((ret == 0 && !r->r_notdestination) || (ret != 0 && r->r_notdestination))
100
			continue;
101
102
		goto matched;
103
	}
104
105
	errno = 0;
106
	log_trace(TRACE_RULES, "no rule matched");
107
	return (NULL);
108
109
matched:
110
	log_trace(TRACE_RULES, "rule matched: %s", rule_to_text(r));
111
	return r;
112
}
113
114
static int
115
ruleset_check_source(struct table *table, const struct sockaddr_storage *ss,
116
    int evpflags)
117
{
118
	const char   *key;
119
120
	if (evpflags & (EF_AUTHENTICATED | EF_INTERNAL))
121
		key = "local";
122
	else
123
		key = ss_to_text(ss);
124
	switch (table_lookup(table, NULL, key, K_NETADDR, NULL)) {
125
	case 1:
126
		return 1;
127
	case -1:
128
		log_warnx("warn: failure to perform a table lookup on table %s",
129
		    table->t_name);
130
		return -1;
131
	default:
132
		break;
133
	}
134
135
	return 0;
136
}
137
138
static int
139
ruleset_check_mailaddr(struct table *table, const struct mailaddr *maddr)
140
{
141
	const char	*key;
142
143
	key = mailaddr_to_text(maddr);
144
	if (key == NULL)
145
		return -1;
146
147
	switch (table_lookup(table, NULL, key, K_MAILADDR, NULL)) {
148
	case 1:
149
		return 1;
150
	case -1:
151
		log_warnx("warn: failure to perform a table lookup on table %s",
152
		    table->t_name);
153
		return -1;
154
	default:
155
		break;
156
	}
157
	return 0;
158
}