Blame


1 ce062d50 2019-08-21 martijn /*
2 ce062d50 2019-08-21 martijn * Copyright (c) 2019 Martijn van Duren <martijn@openbsd.org>
3 ce062d50 2019-08-21 martijn *
4 ce062d50 2019-08-21 martijn * Permission to use, copy, modify, and distribute this software for any
5 ce062d50 2019-08-21 martijn * purpose with or without fee is hereby granted, provided that the above
6 ce062d50 2019-08-21 martijn * copyright notice and this permission notice appear in all copies.
7 ce062d50 2019-08-21 martijn *
8 ce062d50 2019-08-21 martijn * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 ce062d50 2019-08-21 martijn * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 ce062d50 2019-08-21 martijn * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 ce062d50 2019-08-21 martijn * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 ce062d50 2019-08-21 martijn * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 ce062d50 2019-08-21 martijn * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 ce062d50 2019-08-21 martijn * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 ce062d50 2019-08-21 martijn */
16 ce062d50 2019-08-21 martijn #include <sys/time.h>
17 ce062d50 2019-08-21 martijn #include <sys/tree.h>
18 ce062d50 2019-08-21 martijn #include <sys/socket.h>
19 ce062d50 2019-08-21 martijn #include <sys/un.h>
20 ce062d50 2019-08-21 martijn
21 ce062d50 2019-08-21 martijn #include <arpa/inet.h>
22 078ff8cf 2019-08-21 martijn #include <netinet/in.h>
23 078ff8cf 2019-08-21 martijn
24 ce062d50 2019-08-21 martijn #include <err.h>
25 ce062d50 2019-08-21 martijn #include <errno.h>
26 ce062d50 2019-08-21 martijn #include <event.h>
27 ce062d50 2019-08-21 martijn #include <fcntl.h>
28 ce062d50 2019-08-21 martijn #include <inttypes.h>
29 ce062d50 2019-08-21 martijn #include <limits.h>
30 ce062d50 2019-08-21 martijn #include <stdarg.h>
31 ce062d50 2019-08-21 martijn #include <stdio.h>
32 ce062d50 2019-08-21 martijn #include <stdlib.h>
33 ce062d50 2019-08-21 martijn #include <string.h>
34 ce062d50 2019-08-21 martijn #include <syslog.h>
35 ce062d50 2019-08-21 martijn #include <unistd.h>
36 ce062d50 2019-08-21 martijn
37 ce062d50 2019-08-21 martijn #include "opensmtpd.h"
38 ce062d50 2019-08-21 martijn #include "ioev.h"
39 ce062d50 2019-08-21 martijn
40 ce062d50 2019-08-21 martijn #define NITEMS(x) (sizeof(x) / sizeof(*x))
41 ce062d50 2019-08-21 martijn
42 d229c123 2019-08-22 martijn struct osmtpd_callback {
43 d229c123 2019-08-22 martijn enum osmtpd_type type;
44 d229c123 2019-08-22 martijn enum osmtpd_phase phase;
45 d229c123 2019-08-22 martijn int incoming;
46 d229c123 2019-08-22 martijn void (*osmtpd_cb)(struct osmtpd_callback *, struct osmtpd_ctx *, char *,
47 d229c123 2019-08-22 martijn char *);
48 d229c123 2019-08-22 martijn void *cb;
49 d229c123 2019-08-22 martijn int doregister;
50 d229c123 2019-08-22 martijn int storereport;
51 d229c123 2019-08-22 martijn };
52 d229c123 2019-08-22 martijn
53 d229c123 2019-08-22 martijn struct osmtpd_session {
54 d229c123 2019-08-22 martijn struct osmtpd_ctx ctx;
55 d229c123 2019-08-22 martijn RB_ENTRY(osmtpd_session) entry;
56 d229c123 2019-08-22 martijn };
57 d229c123 2019-08-22 martijn
58 d229c123 2019-08-22 martijn static void osmtpd_register(enum osmtpd_type, enum osmtpd_phase, int, int,
59 d229c123 2019-08-22 martijn void *);
60 d229c123 2019-08-22 martijn static const char *osmtpd_typetostr(enum osmtpd_type);
61 d229c123 2019-08-22 martijn static const char *osmtpd_phasetostr(enum osmtpd_phase);
62 d229c123 2019-08-22 martijn static enum osmtpd_phase osmtpd_strtophase(const char *, const char *);
63 d229c123 2019-08-22 martijn static void osmtpd_newline(struct io *, int, void *);
64 d229c123 2019-08-22 martijn static void osmtpd_outevt(struct io *, int, void *);
65 d229c123 2019-08-22 martijn static void osmtpd_noargs(struct osmtpd_callback *, struct osmtpd_ctx *,
66 d229c123 2019-08-22 martijn char *, char *);
67 d229c123 2019-08-22 martijn static void osmtpd_onearg(struct osmtpd_callback *, struct osmtpd_ctx *,
68 d229c123 2019-08-22 martijn char *, char *);
69 d229c123 2019-08-22 martijn static void osmtpd_connect(struct osmtpd_callback *, struct osmtpd_ctx *,
70 d229c123 2019-08-22 martijn char *, char *);
71 d229c123 2019-08-22 martijn static void osmtpd_link_connect(struct osmtpd_callback *, struct osmtpd_ctx *,
72 d229c123 2019-08-22 martijn char *, char *);
73 d229c123 2019-08-22 martijn static void osmtpd_link_disconnect(struct osmtpd_callback *,
74 d229c123 2019-08-22 martijn struct osmtpd_ctx *, char *, char *);
75 d229c123 2019-08-22 martijn static void osmtpd_link_identify(struct osmtpd_callback *, struct osmtpd_ctx *,
76 d229c123 2019-08-22 martijn char *, char *);
77 d229c123 2019-08-22 martijn static void osmtpd_link_tls(struct osmtpd_callback *, struct osmtpd_ctx *,
78 d229c123 2019-08-22 martijn char *, char *);
79 d229c123 2019-08-22 martijn static void osmtpd_tx_begin(struct osmtpd_callback *, struct osmtpd_ctx *,
80 d229c123 2019-08-22 martijn char *, char *);
81 d229c123 2019-08-22 martijn static void osmtpd_tx_mail(struct osmtpd_callback *, struct osmtpd_ctx *,
82 d229c123 2019-08-22 martijn char *, char *);
83 d229c123 2019-08-22 martijn static void osmtpd_tx_rcpt(struct osmtpd_callback *, struct osmtpd_ctx *,
84 d229c123 2019-08-22 martijn char *, char *);
85 d229c123 2019-08-22 martijn static void osmtpd_tx_envelope(struct osmtpd_callback *, struct osmtpd_ctx *,
86 d229c123 2019-08-22 martijn char *, char *);
87 d229c123 2019-08-22 martijn static void osmtpd_tx_data(struct osmtpd_callback *, struct osmtpd_ctx *,
88 d229c123 2019-08-22 martijn char *, char *);
89 d229c123 2019-08-22 martijn static void osmtpd_tx_commit(struct osmtpd_callback *, struct osmtpd_ctx *,
90 d229c123 2019-08-22 martijn char *, char *);
91 d229c123 2019-08-22 martijn static void osmtpd_tx_rollback(struct osmtpd_callback *, struct osmtpd_ctx *,
92 d229c123 2019-08-22 martijn char *, char *);
93 d229c123 2019-08-22 martijn static void osmtpd_addrtoss(char *, struct sockaddr_storage *, int, char *);
94 d229c123 2019-08-22 martijn static enum osmtpd_status osmtpd_strtostatus(const char *, char *);
95 d229c123 2019-08-22 martijn static int osmtpd_session_cmp(struct osmtpd_session *, struct osmtpd_session *);
96 d229c123 2019-08-22 martijn static void *(*oncreatecb)(struct osmtpd_ctx *) = NULL;
97 d229c123 2019-08-22 martijn static void (*ondeletecb)(struct osmtpd_ctx *, void *) = NULL;
98 d229c123 2019-08-22 martijn
99 d229c123 2019-08-22 martijn
100 d229c123 2019-08-22 martijn static struct osmtpd_callback osmtpd_callbacks[] = {
101 d229c123 2019-08-22 martijn {
102 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
103 d229c123 2019-08-22 martijn OSMTPD_PHASE_CONNECT,
104 d229c123 2019-08-22 martijn 1,
105 d229c123 2019-08-22 martijn osmtpd_connect,
106 d229c123 2019-08-22 martijn NULL,
107 d229c123 2019-08-22 martijn 0,
108 d229c123 2019-08-22 martijn 0
109 d229c123 2019-08-22 martijn },
110 d229c123 2019-08-22 martijn {
111 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
112 d229c123 2019-08-22 martijn OSMTPD_PHASE_HELO,
113 d229c123 2019-08-22 martijn 1,
114 d229c123 2019-08-22 martijn osmtpd_onearg,
115 d229c123 2019-08-22 martijn NULL,
116 d229c123 2019-08-22 martijn 0,
117 d229c123 2019-08-22 martijn 0
118 d229c123 2019-08-22 martijn },
119 d229c123 2019-08-22 martijn {
120 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
121 d229c123 2019-08-22 martijn OSMTPD_PHASE_EHLO,
122 d229c123 2019-08-22 martijn 1,
123 d229c123 2019-08-22 martijn osmtpd_onearg,
124 d229c123 2019-08-22 martijn NULL,
125 d229c123 2019-08-22 martijn 0,
126 d229c123 2019-08-22 martijn 0
127 d229c123 2019-08-22 martijn },
128 d229c123 2019-08-22 martijn {
129 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
130 d229c123 2019-08-22 martijn OSMTPD_PHASE_STARTTLS,
131 d229c123 2019-08-22 martijn 1,
132 d229c123 2019-08-22 martijn osmtpd_noargs,
133 d229c123 2019-08-22 martijn NULL,
134 d229c123 2019-08-22 martijn 0,
135 d229c123 2019-08-22 martijn 0
136 d229c123 2019-08-22 martijn },
137 d229c123 2019-08-22 martijn {
138 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
139 d229c123 2019-08-22 martijn OSMTPD_PHASE_AUTH,
140 d229c123 2019-08-22 martijn 1,
141 d229c123 2019-08-22 martijn osmtpd_onearg,
142 d229c123 2019-08-22 martijn NULL,
143 d229c123 2019-08-22 martijn 0,
144 d229c123 2019-08-22 martijn 0
145 d229c123 2019-08-22 martijn },
146 d229c123 2019-08-22 martijn {
147 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
148 d229c123 2019-08-22 martijn OSMTPD_PHASE_MAIL_FROM,
149 d229c123 2019-08-22 martijn 1,
150 d229c123 2019-08-22 martijn osmtpd_onearg,
151 d229c123 2019-08-22 martijn NULL,
152 d229c123 2019-08-22 martijn 0,
153 d229c123 2019-08-22 martijn 0
154 d229c123 2019-08-22 martijn },
155 d229c123 2019-08-22 martijn {
156 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
157 d229c123 2019-08-22 martijn OSMTPD_PHASE_RCPT_TO,
158 d229c123 2019-08-22 martijn 1,
159 d229c123 2019-08-22 martijn osmtpd_onearg,
160 d229c123 2019-08-22 martijn NULL,
161 d229c123 2019-08-22 martijn 0,
162 d229c123 2019-08-22 martijn 0
163 d229c123 2019-08-22 martijn },
164 d229c123 2019-08-22 martijn {
165 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
166 d229c123 2019-08-22 martijn OSMTPD_PHASE_DATA,
167 d229c123 2019-08-22 martijn 1,
168 d229c123 2019-08-22 martijn osmtpd_noargs,
169 d229c123 2019-08-22 martijn NULL,
170 d229c123 2019-08-22 martijn 0,
171 d229c123 2019-08-22 martijn 0
172 d229c123 2019-08-22 martijn },
173 d229c123 2019-08-22 martijn {
174 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
175 d229c123 2019-08-22 martijn OSMTPD_PHASE_DATA_LINE,
176 d229c123 2019-08-22 martijn 1,
177 d229c123 2019-08-22 martijn osmtpd_onearg,
178 d229c123 2019-08-22 martijn NULL,
179 d229c123 2019-08-22 martijn 0,
180 d229c123 2019-08-22 martijn 0
181 d229c123 2019-08-22 martijn },
182 d229c123 2019-08-22 martijn {
183 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
184 d229c123 2019-08-22 martijn OSMTPD_PHASE_RSET,
185 d229c123 2019-08-22 martijn 1,
186 d229c123 2019-08-22 martijn osmtpd_noargs,
187 d229c123 2019-08-22 martijn NULL,
188 d229c123 2019-08-22 martijn 0,
189 d229c123 2019-08-22 martijn 0
190 d229c123 2019-08-22 martijn },
191 d229c123 2019-08-22 martijn {
192 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
193 d229c123 2019-08-22 martijn OSMTPD_PHASE_QUIT,
194 d229c123 2019-08-22 martijn 1,
195 d229c123 2019-08-22 martijn osmtpd_noargs,
196 d229c123 2019-08-22 martijn NULL,
197 d229c123 2019-08-22 martijn 0,
198 d229c123 2019-08-22 martijn 0
199 d229c123 2019-08-22 martijn },
200 d229c123 2019-08-22 martijn {
201 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
202 d229c123 2019-08-22 martijn OSMTPD_PHASE_NOOP,
203 d229c123 2019-08-22 martijn 1,
204 d229c123 2019-08-22 martijn osmtpd_noargs,
205 d229c123 2019-08-22 martijn NULL,
206 d229c123 2019-08-22 martijn 0,
207 d229c123 2019-08-22 martijn 0
208 d229c123 2019-08-22 martijn },
209 d229c123 2019-08-22 martijn {
210 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
211 d229c123 2019-08-22 martijn OSMTPD_PHASE_HELP,
212 d229c123 2019-08-22 martijn 1,
213 d229c123 2019-08-22 martijn osmtpd_noargs,
214 d229c123 2019-08-22 martijn NULL,
215 d229c123 2019-08-22 martijn 0,
216 d229c123 2019-08-22 martijn 0
217 d229c123 2019-08-22 martijn },
218 d229c123 2019-08-22 martijn {
219 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
220 d229c123 2019-08-22 martijn OSMTPD_PHASE_WIZ,
221 d229c123 2019-08-22 martijn 1,
222 d229c123 2019-08-22 martijn osmtpd_noargs,
223 d229c123 2019-08-22 martijn NULL,
224 d229c123 2019-08-22 martijn 0,
225 d229c123 2019-08-22 martijn 0
226 d229c123 2019-08-22 martijn },
227 d229c123 2019-08-22 martijn {
228 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
229 d229c123 2019-08-22 martijn OSMTPD_PHASE_COMMIT,
230 d229c123 2019-08-22 martijn 1,
231 d229c123 2019-08-22 martijn osmtpd_noargs,
232 d229c123 2019-08-22 martijn NULL,
233 d229c123 2019-08-22 martijn 0,
234 d229c123 2019-08-22 martijn 0
235 d229c123 2019-08-22 martijn },
236 d229c123 2019-08-22 martijn {
237 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
238 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_CONNECT,
239 d229c123 2019-08-22 martijn 1,
240 d229c123 2019-08-22 martijn osmtpd_link_connect,
241 d229c123 2019-08-22 martijn NULL,
242 d229c123 2019-08-22 martijn 0,
243 d229c123 2019-08-22 martijn 0
244 d229c123 2019-08-22 martijn },
245 d229c123 2019-08-22 martijn {
246 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
247 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_DISCONNECT,
248 d229c123 2019-08-22 martijn 1,
249 d229c123 2019-08-22 martijn osmtpd_link_disconnect,
250 d229c123 2019-08-22 martijn NULL,
251 d229c123 2019-08-22 martijn 0,
252 d229c123 2019-08-22 martijn 0
253 d229c123 2019-08-22 martijn },
254 d229c123 2019-08-22 martijn {
255 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
256 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_IDENTIFY,
257 d229c123 2019-08-22 martijn 1,
258 d229c123 2019-08-22 martijn osmtpd_link_identify,
259 d229c123 2019-08-22 martijn NULL,
260 d229c123 2019-08-22 martijn 0,
261 d229c123 2019-08-22 martijn 0
262 d229c123 2019-08-22 martijn },
263 d229c123 2019-08-22 martijn {
264 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
265 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_TLS,
266 d229c123 2019-08-22 martijn 1,
267 d229c123 2019-08-22 martijn osmtpd_link_tls,
268 d229c123 2019-08-22 martijn NULL,
269 d229c123 2019-08-22 martijn 0,
270 d229c123 2019-08-22 martijn 0
271 d229c123 2019-08-22 martijn },
272 d229c123 2019-08-22 martijn {
273 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
274 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_BEGIN,
275 d229c123 2019-08-22 martijn 1,
276 d229c123 2019-08-22 martijn osmtpd_tx_begin,
277 d229c123 2019-08-22 martijn NULL,
278 d229c123 2019-08-22 martijn 0,
279 d229c123 2019-08-22 martijn 0
280 d229c123 2019-08-22 martijn },
281 d229c123 2019-08-22 martijn {
282 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
283 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_MAIL,
284 d229c123 2019-08-22 martijn 1,
285 d229c123 2019-08-22 martijn osmtpd_tx_mail,
286 d229c123 2019-08-22 martijn NULL,
287 d229c123 2019-08-22 martijn 0,
288 d229c123 2019-08-22 martijn 0
289 d229c123 2019-08-22 martijn },
290 d229c123 2019-08-22 martijn {
291 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
292 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_RCPT,
293 d229c123 2019-08-22 martijn 1,
294 d229c123 2019-08-22 martijn osmtpd_tx_rcpt,
295 d229c123 2019-08-22 martijn NULL,
296 d229c123 2019-08-22 martijn 0,
297 d229c123 2019-08-22 martijn 0
298 d229c123 2019-08-22 martijn },
299 d229c123 2019-08-22 martijn {
300 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
301 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_ENVELOPE,
302 d229c123 2019-08-22 martijn 1,
303 d229c123 2019-08-22 martijn osmtpd_tx_envelope,
304 d229c123 2019-08-22 martijn NULL,
305 d229c123 2019-08-22 martijn 0,
306 d229c123 2019-08-22 martijn 0
307 d229c123 2019-08-22 martijn },
308 d229c123 2019-08-22 martijn {
309 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
310 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_DATA,
311 d229c123 2019-08-22 martijn 1,
312 d229c123 2019-08-22 martijn osmtpd_tx_data,
313 d229c123 2019-08-22 martijn NULL,
314 d229c123 2019-08-22 martijn 0,
315 d229c123 2019-08-22 martijn 0
316 d229c123 2019-08-22 martijn },
317 d229c123 2019-08-22 martijn {
318 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
319 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_COMMIT,
320 d229c123 2019-08-22 martijn 1,
321 d229c123 2019-08-22 martijn osmtpd_tx_commit,
322 d229c123 2019-08-22 martijn NULL,
323 d229c123 2019-08-22 martijn 0,
324 d229c123 2019-08-22 martijn 0
325 d229c123 2019-08-22 martijn },
326 d229c123 2019-08-22 martijn {
327 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
328 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_ROLLBACK,
329 d229c123 2019-08-22 martijn 1,
330 d229c123 2019-08-22 martijn osmtpd_tx_rollback,
331 d229c123 2019-08-22 martijn NULL,
332 d229c123 2019-08-22 martijn 0,
333 d229c123 2019-08-22 martijn 0
334 d229c123 2019-08-22 martijn },
335 d229c123 2019-08-22 martijn {
336 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
337 d229c123 2019-08-22 martijn OSMTPD_PHASE_PROTOCOL_CLIENT,
338 d229c123 2019-08-22 martijn 1,
339 d229c123 2019-08-22 martijn osmtpd_onearg,
340 d229c123 2019-08-22 martijn NULL,
341 d229c123 2019-08-22 martijn 0,
342 d229c123 2019-08-22 martijn 0
343 d229c123 2019-08-22 martijn },
344 d229c123 2019-08-22 martijn {
345 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
346 d229c123 2019-08-22 martijn OSMTPD_PHASE_PROTOCOL_SERVER,
347 d229c123 2019-08-22 martijn 1,
348 d229c123 2019-08-22 martijn osmtpd_onearg,
349 d229c123 2019-08-22 martijn NULL,
350 d229c123 2019-08-22 martijn 0,
351 d229c123 2019-08-22 martijn 0
352 d229c123 2019-08-22 martijn },
353 d229c123 2019-08-22 martijn {
354 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
355 d229c123 2019-08-22 martijn OSMTPD_PHASE_FILTER_RESPONSE,
356 d229c123 2019-08-22 martijn 1,
357 d229c123 2019-08-22 martijn osmtpd_onearg,
358 d229c123 2019-08-22 martijn NULL,
359 d229c123 2019-08-22 martijn 0,
360 d229c123 2019-08-22 martijn 0
361 d229c123 2019-08-22 martijn },
362 d229c123 2019-08-22 martijn {
363 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
364 d229c123 2019-08-22 martijn OSMTPD_PHASE_TIMEOUT,
365 d229c123 2019-08-22 martijn 1,
366 d229c123 2019-08-22 martijn osmtpd_noargs,
367 d229c123 2019-08-22 martijn NULL,
368 d229c123 2019-08-22 martijn 0,
369 d229c123 2019-08-22 martijn 0
370 d229c123 2019-08-22 martijn },
371 d229c123 2019-08-22 martijn {
372 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
373 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_CONNECT,
374 d229c123 2019-08-22 martijn 0,
375 d229c123 2019-08-22 martijn osmtpd_link_connect,
376 d229c123 2019-08-22 martijn NULL,
377 d229c123 2019-08-22 martijn 0,
378 d229c123 2019-08-22 martijn 0
379 d229c123 2019-08-22 martijn },
380 d229c123 2019-08-22 martijn {
381 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
382 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_DISCONNECT,
383 d229c123 2019-08-22 martijn 0,
384 d229c123 2019-08-22 martijn osmtpd_link_disconnect,
385 d229c123 2019-08-22 martijn NULL,
386 d229c123 2019-08-22 martijn 0,
387 d229c123 2019-08-22 martijn 0
388 d229c123 2019-08-22 martijn },
389 d229c123 2019-08-22 martijn {
390 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
391 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_IDENTIFY,
392 d229c123 2019-08-22 martijn 0,
393 d229c123 2019-08-22 martijn osmtpd_link_identify,
394 d229c123 2019-08-22 martijn NULL,
395 d229c123 2019-08-22 martijn 0,
396 d229c123 2019-08-22 martijn 0
397 d229c123 2019-08-22 martijn },
398 d229c123 2019-08-22 martijn {
399 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
400 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_TLS,
401 d229c123 2019-08-22 martijn 0,
402 d229c123 2019-08-22 martijn osmtpd_link_tls,
403 d229c123 2019-08-22 martijn NULL,
404 d229c123 2019-08-22 martijn 0,
405 d229c123 2019-08-22 martijn 0
406 d229c123 2019-08-22 martijn },
407 d229c123 2019-08-22 martijn {
408 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
409 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_BEGIN,
410 d229c123 2019-08-22 martijn 0,
411 d229c123 2019-08-22 martijn osmtpd_tx_begin,
412 d229c123 2019-08-22 martijn NULL,
413 d229c123 2019-08-22 martijn 0,
414 d229c123 2019-08-22 martijn 0
415 d229c123 2019-08-22 martijn },
416 d229c123 2019-08-22 martijn {
417 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
418 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_MAIL,
419 d229c123 2019-08-22 martijn 0,
420 d229c123 2019-08-22 martijn osmtpd_tx_mail,
421 d229c123 2019-08-22 martijn NULL,
422 d229c123 2019-08-22 martijn 0,
423 d229c123 2019-08-22 martijn 0
424 d229c123 2019-08-22 martijn },
425 d229c123 2019-08-22 martijn {
426 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
427 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_RCPT,
428 d229c123 2019-08-22 martijn 0,
429 d229c123 2019-08-22 martijn osmtpd_tx_rcpt,
430 d229c123 2019-08-22 martijn NULL,
431 d229c123 2019-08-22 martijn 0,
432 d229c123 2019-08-22 martijn 0
433 d229c123 2019-08-22 martijn },
434 d229c123 2019-08-22 martijn {
435 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
436 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_ENVELOPE,
437 d229c123 2019-08-22 martijn 0,
438 d229c123 2019-08-22 martijn osmtpd_tx_envelope,
439 d229c123 2019-08-22 martijn NULL,
440 d229c123 2019-08-22 martijn 0,
441 d229c123 2019-08-22 martijn 0
442 d229c123 2019-08-22 martijn },
443 d229c123 2019-08-22 martijn {
444 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
445 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_DATA,
446 d229c123 2019-08-22 martijn 0,
447 d229c123 2019-08-22 martijn osmtpd_tx_data,
448 d229c123 2019-08-22 martijn NULL,
449 d229c123 2019-08-22 martijn 0,
450 d229c123 2019-08-22 martijn 0
451 d229c123 2019-08-22 martijn },
452 d229c123 2019-08-22 martijn {
453 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
454 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_COMMIT,
455 d229c123 2019-08-22 martijn 0,
456 d229c123 2019-08-22 martijn osmtpd_tx_commit,
457 d229c123 2019-08-22 martijn NULL,
458 d229c123 2019-08-22 martijn 0,
459 d229c123 2019-08-22 martijn 0
460 d229c123 2019-08-22 martijn },
461 d229c123 2019-08-22 martijn {
462 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
463 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_ROLLBACK,
464 d229c123 2019-08-22 martijn 0,
465 d229c123 2019-08-22 martijn osmtpd_tx_rollback,
466 d229c123 2019-08-22 martijn NULL,
467 d229c123 2019-08-22 martijn 0,
468 d229c123 2019-08-22 martijn 0
469 d229c123 2019-08-22 martijn },
470 d229c123 2019-08-22 martijn {
471 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
472 d229c123 2019-08-22 martijn OSMTPD_PHASE_PROTOCOL_CLIENT,
473 d229c123 2019-08-22 martijn 0,
474 d229c123 2019-08-22 martijn osmtpd_onearg,
475 d229c123 2019-08-22 martijn NULL,
476 d229c123 2019-08-22 martijn 0,
477 d229c123 2019-08-22 martijn 0
478 d229c123 2019-08-22 martijn },
479 d229c123 2019-08-22 martijn {
480 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
481 d229c123 2019-08-22 martijn OSMTPD_PHASE_PROTOCOL_SERVER,
482 d229c123 2019-08-22 martijn 0,
483 d229c123 2019-08-22 martijn osmtpd_onearg,
484 d229c123 2019-08-22 martijn NULL,
485 d229c123 2019-08-22 martijn 0,
486 d229c123 2019-08-22 martijn 0
487 d229c123 2019-08-22 martijn },
488 d229c123 2019-08-22 martijn {
489 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
490 d229c123 2019-08-22 martijn OSMTPD_PHASE_FILTER_RESPONSE,
491 d229c123 2019-08-22 martijn 0,
492 d229c123 2019-08-22 martijn osmtpd_onearg,
493 d229c123 2019-08-22 martijn NULL,
494 d229c123 2019-08-22 martijn 0,
495 d229c123 2019-08-22 martijn 0
496 d229c123 2019-08-22 martijn },
497 d229c123 2019-08-22 martijn {
498 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
499 d229c123 2019-08-22 martijn OSMTPD_PHASE_TIMEOUT,
500 d229c123 2019-08-22 martijn 0,
501 d229c123 2019-08-22 martijn osmtpd_noargs,
502 d229c123 2019-08-22 martijn NULL,
503 d229c123 2019-08-22 martijn 0,
504 d229c123 2019-08-22 martijn 0
505 d229c123 2019-08-22 martijn }
506 d229c123 2019-08-22 martijn };
507 d229c123 2019-08-22 martijn
508 ce062d50 2019-08-21 martijn static struct io *io_stdout;
509 ce062d50 2019-08-21 martijn static int ready = 0;
510 ce062d50 2019-08-21 martijn /* Default from smtpd */
511 ce062d50 2019-08-21 martijn static int session_timeout = 300;
512 ce062d50 2019-08-21 martijn
513 d229c123 2019-08-22 martijn RB_HEAD(osmtpd_sessions, osmtpd_session) osmtpd_sessions = RB_INITIALIZER(NULL);
514 9e3e8410 2019-08-22 martijn RB_PROTOTYPE_STATIC(osmtpd_sessions, osmtpd_session, entry, osmtpd_session_cmp);
515 d229c123 2019-08-22 martijn
516 ce062d50 2019-08-21 martijn void
517 ce062d50 2019-08-21 martijn osmtpd_register_filter_connect(void (*cb)(struct osmtpd_ctx *, const char *,
518 ce062d50 2019-08-21 martijn struct sockaddr_storage *))
519 ce062d50 2019-08-21 martijn {
520 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_CONNECT, 1, 0,
521 ce062d50 2019-08-21 martijn (void *)cb);
522 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
523 ce062d50 2019-08-21 martijn NULL);
524 ce062d50 2019-08-21 martijn }
525 ce062d50 2019-08-21 martijn
526 ce062d50 2019-08-21 martijn void
527 ce062d50 2019-08-21 martijn osmtpd_register_filter_helo(void (*cb)(struct osmtpd_ctx *, const char *))
528 ce062d50 2019-08-21 martijn {
529 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_HELO, 1, 0,
530 ce062d50 2019-08-21 martijn (void *)cb);
531 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
532 ce062d50 2019-08-21 martijn NULL);
533 ce062d50 2019-08-21 martijn }
534 ce062d50 2019-08-21 martijn
535 ce062d50 2019-08-21 martijn void
536 ce062d50 2019-08-21 martijn osmtpd_register_filter_ehlo(void (*cb)(struct osmtpd_ctx *, const char *))
537 ce062d50 2019-08-21 martijn {
538 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_EHLO, 1, 0,
539 ce062d50 2019-08-21 martijn (void *)cb);
540 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
541 ce062d50 2019-08-21 martijn NULL);
542 ce062d50 2019-08-21 martijn }
543 ce062d50 2019-08-21 martijn
544 ce062d50 2019-08-21 martijn void
545 ce062d50 2019-08-21 martijn osmtpd_register_filter_starttls(void (*cb)(struct osmtpd_ctx *))
546 ce062d50 2019-08-21 martijn {
547 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_STARTTLS, 1, 0,
548 ce062d50 2019-08-21 martijn (void *)cb);
549 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
550 ce062d50 2019-08-21 martijn NULL);
551 ce062d50 2019-08-21 martijn }
552 ce062d50 2019-08-21 martijn
553 ce062d50 2019-08-21 martijn void
554 ce062d50 2019-08-21 martijn osmtpd_register_filter_auth(void (*cb)(struct osmtpd_ctx *, const char *))
555 ce062d50 2019-08-21 martijn {
556 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_AUTH, 1, 0,
557 ce062d50 2019-08-21 martijn (void *)cb);
558 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
559 ce062d50 2019-08-21 martijn NULL);
560 ce062d50 2019-08-21 martijn }
561 ce062d50 2019-08-21 martijn
562 ce062d50 2019-08-21 martijn void
563 ce062d50 2019-08-21 martijn osmtpd_register_filter_mailfrom(void (*cb)(struct osmtpd_ctx *, const char *))
564 ce062d50 2019-08-21 martijn {
565 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_MAIL_FROM, 1, 0,
566 ce062d50 2019-08-21 martijn (void *)cb);
567 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
568 ce062d50 2019-08-21 martijn NULL);
569 ce062d50 2019-08-21 martijn }
570 ce062d50 2019-08-21 martijn
571 ce062d50 2019-08-21 martijn void
572 ce062d50 2019-08-21 martijn osmtpd_register_filter_rcptto(void (*cb)(struct osmtpd_ctx *, const char *))
573 ce062d50 2019-08-21 martijn {
574 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_RCPT_TO, 1, 0,
575 ce062d50 2019-08-21 martijn (void *)cb);
576 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
577 ce062d50 2019-08-21 martijn NULL);
578 ce062d50 2019-08-21 martijn }
579 ce062d50 2019-08-21 martijn
580 ce062d50 2019-08-21 martijn void
581 ce062d50 2019-08-21 martijn osmtpd_register_filter_data(void (*cb)(struct osmtpd_ctx *))
582 ce062d50 2019-08-21 martijn {
583 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_DATA, 1, 0,
584 ce062d50 2019-08-21 martijn (void *)cb);
585 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
586 ce062d50 2019-08-21 martijn NULL);
587 ce062d50 2019-08-21 martijn }
588 ce062d50 2019-08-21 martijn
589 ce062d50 2019-08-21 martijn void
590 ce062d50 2019-08-21 martijn osmtpd_register_filter_dataline(void (*cb)(struct osmtpd_ctx *, const char *))
591 ce062d50 2019-08-21 martijn {
592 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_DATA_LINE, 1, 0,
593 ce062d50 2019-08-21 martijn (void *)cb);
594 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
595 ce062d50 2019-08-21 martijn NULL);
596 ce062d50 2019-08-21 martijn }
597 ce062d50 2019-08-21 martijn
598 ce062d50 2019-08-21 martijn void
599 ce062d50 2019-08-21 martijn osmtpd_register_filter_rset(void (*cb)(struct osmtpd_ctx *))
600 ce062d50 2019-08-21 martijn {
601 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_RSET, 1, 0,
602 ce062d50 2019-08-21 martijn (void *)cb);
603 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
604 ce062d50 2019-08-21 martijn NULL);
605 ce062d50 2019-08-21 martijn }
606 ce062d50 2019-08-21 martijn
607 ce062d50 2019-08-21 martijn void
608 ce062d50 2019-08-21 martijn osmtpd_register_filter_quit(void (*cb)(struct osmtpd_ctx *))
609 ce062d50 2019-08-21 martijn {
610 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_QUIT, 1, 0,
611 ce062d50 2019-08-21 martijn (void *)cb);
612 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
613 ce062d50 2019-08-21 martijn NULL);
614 ce062d50 2019-08-21 martijn }
615 ce062d50 2019-08-21 martijn
616 ce062d50 2019-08-21 martijn void
617 ce062d50 2019-08-21 martijn osmtpd_register_filter_noop(void (*cb)(struct osmtpd_ctx *))
618 ce062d50 2019-08-21 martijn {
619 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_NOOP, 1, 0,
620 ce062d50 2019-08-21 martijn (void *)cb);
621 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
622 ce062d50 2019-08-21 martijn NULL);
623 ce062d50 2019-08-21 martijn }
624 ce062d50 2019-08-21 martijn
625 ce062d50 2019-08-21 martijn void
626 ce062d50 2019-08-21 martijn osmtpd_register_filter_help(void (*cb)(struct osmtpd_ctx *))
627 ce062d50 2019-08-21 martijn {
628 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_HELP, 1, 0,
629 ce062d50 2019-08-21 martijn (void *)cb);
630 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
631 ce062d50 2019-08-21 martijn NULL);
632 ce062d50 2019-08-21 martijn }
633 ce062d50 2019-08-21 martijn
634 ce062d50 2019-08-21 martijn void
635 ce062d50 2019-08-21 martijn osmtpd_register_filter_wiz(void (*cb)(struct osmtpd_ctx *))
636 ce062d50 2019-08-21 martijn {
637 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_WIZ, 1, 0,
638 ce062d50 2019-08-21 martijn (void *)cb);
639 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
640 ce062d50 2019-08-21 martijn NULL);
641 ce062d50 2019-08-21 martijn }
642 ce062d50 2019-08-21 martijn
643 ce062d50 2019-08-21 martijn void
644 ce062d50 2019-08-21 martijn osmtpd_register_filter_commit(void (*cb)(struct osmtpd_ctx *))
645 ce062d50 2019-08-21 martijn {
646 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_COMMIT, 1, 0,
647 ce062d50 2019-08-21 martijn (void *)cb);
648 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
649 ce062d50 2019-08-21 martijn NULL);
650 ce062d50 2019-08-21 martijn }
651 ce062d50 2019-08-21 martijn
652 ce062d50 2019-08-21 martijn void
653 ce062d50 2019-08-21 martijn osmtpd_register_report_connect(int incoming, void (*cb)(struct osmtpd_ctx *,
654 ce062d50 2019-08-21 martijn const char *, const char *, struct sockaddr_storage *,
655 ce062d50 2019-08-21 martijn struct sockaddr_storage *))
656 ce062d50 2019-08-21 martijn {
657 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_LINK_CONNECT, incoming,
658 ce062d50 2019-08-21 martijn 0, (void *)cb);
659 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
660 ce062d50 2019-08-21 martijn incoming, 0, NULL);
661 ce062d50 2019-08-21 martijn }
662 ce062d50 2019-08-21 martijn
663 ce062d50 2019-08-21 martijn void
664 ce062d50 2019-08-21 martijn osmtpd_register_report_disconnect(int incoming, void (*cb)(struct osmtpd_ctx *))
665 ce062d50 2019-08-21 martijn {
666 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
667 ce062d50 2019-08-21 martijn incoming, 0, (void *)cb);
668 ce062d50 2019-08-21 martijn }
669 ce062d50 2019-08-21 martijn
670 ce062d50 2019-08-21 martijn void
671 ce062d50 2019-08-21 martijn osmtpd_register_report_identify(int incoming, void (*cb)(struct osmtpd_ctx *,
672 ce062d50 2019-08-21 martijn const char *))
673 ce062d50 2019-08-21 martijn {
674 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_IDENTIFY,
675 ce062d50 2019-08-21 martijn incoming, 0, (void *)cb);
676 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
677 ce062d50 2019-08-21 martijn incoming, 0, NULL);
678 ce062d50 2019-08-21 martijn }
679 ce062d50 2019-08-21 martijn
680 ce062d50 2019-08-21 martijn void
681 ce062d50 2019-08-21 martijn osmtpd_register_report_tls(int incoming, void (*cb)(struct osmtpd_ctx *,
682 ce062d50 2019-08-21 martijn const char *))
683 ce062d50 2019-08-21 martijn {
684 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_TLS, incoming, 0,
685 ce062d50 2019-08-21 martijn (void *)cb);
686 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
687 ce062d50 2019-08-21 martijn incoming, 0, NULL);
688 ce062d50 2019-08-21 martijn }
689 ce062d50 2019-08-21 martijn
690 ce062d50 2019-08-21 martijn void
691 ce062d50 2019-08-21 martijn osmtpd_register_report_begin(int incoming, void (*cb)(struct osmtpd_ctx *,
692 ce062d50 2019-08-21 martijn uint32_t))
693 ce062d50 2019-08-21 martijn {
694 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_BEGIN, incoming, 0,
695 ce062d50 2019-08-21 martijn (void *)cb);
696 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
697 ce062d50 2019-08-21 martijn incoming, 0, NULL);
698 ce062d50 2019-08-21 martijn }
699 ce062d50 2019-08-21 martijn
700 ce062d50 2019-08-21 martijn void
701 ce062d50 2019-08-21 martijn osmtpd_register_report_mail(int incoming, void (*cb)(struct osmtpd_ctx *,
702 ce062d50 2019-08-21 martijn uint32_t, const char *, enum osmtpd_status))
703 ce062d50 2019-08-21 martijn {
704 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_MAIL, incoming, 0,
705 ce062d50 2019-08-21 martijn (void *)cb);
706 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
707 ce062d50 2019-08-21 martijn incoming, 0, NULL);
708 ce062d50 2019-08-21 martijn }
709 ce062d50 2019-08-21 martijn
710 ce062d50 2019-08-21 martijn void
711 ce062d50 2019-08-21 martijn osmtpd_register_report_rcpt(int incoming, void (*cb)(struct osmtpd_ctx *,
712 ce062d50 2019-08-21 martijn uint32_t, const char *, enum osmtpd_status))
713 ce062d50 2019-08-21 martijn {
714 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_RCPT, incoming, 0,
715 ce062d50 2019-08-21 martijn (void *)cb);
716 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
717 ce062d50 2019-08-21 martijn incoming, 0, NULL);
718 ce062d50 2019-08-21 martijn }
719 ce062d50 2019-08-21 martijn
720 ce062d50 2019-08-21 martijn void
721 ce062d50 2019-08-21 martijn osmtpd_register_report_envelope(int incoming, void (*cb)(struct osmtpd_ctx *,
722 ce062d50 2019-08-21 martijn uint32_t, uint64_t))
723 ce062d50 2019-08-21 martijn {
724 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ENVELOPE, incoming,
725 ce062d50 2019-08-21 martijn 0, (void *)cb);
726 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
727 ce062d50 2019-08-21 martijn incoming, 0, NULL);
728 ce062d50 2019-08-21 martijn }
729 ce062d50 2019-08-21 martijn
730 ce062d50 2019-08-21 martijn void
731 ce062d50 2019-08-21 martijn osmtpd_register_report_data(int incoming, void (*cb)(struct osmtpd_ctx *,
732 ce062d50 2019-08-21 martijn uint32_t, enum osmtpd_status))
733 ce062d50 2019-08-21 martijn {
734 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_DATA, incoming, 0,
735 ce062d50 2019-08-21 martijn (void *)cb);
736 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
737 ce062d50 2019-08-21 martijn incoming, 0, NULL);
738 ce062d50 2019-08-21 martijn }
739 ce062d50 2019-08-21 martijn
740 ce062d50 2019-08-21 martijn void
741 ce062d50 2019-08-21 martijn osmtpd_register_report_commit(int incoming, void (*cb)(struct osmtpd_ctx *,
742 ce062d50 2019-08-21 martijn uint32_t, size_t))
743 ce062d50 2019-08-21 martijn {
744 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_COMMIT, incoming, 0,
745 ce062d50 2019-08-21 martijn (void *)cb);
746 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
747 ce062d50 2019-08-21 martijn incoming, 0, NULL);
748 ce062d50 2019-08-21 martijn }
749 ce062d50 2019-08-21 martijn
750 ce062d50 2019-08-21 martijn void
751 ce062d50 2019-08-21 martijn osmtpd_register_report_rollback(int incoming, void (*cb)(struct osmtpd_ctx *,
752 ce062d50 2019-08-21 martijn uint32_t))
753 ce062d50 2019-08-21 martijn {
754 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ROLLBACK, incoming,
755 ce062d50 2019-08-21 martijn 0, (void *)cb);
756 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
757 ce062d50 2019-08-21 martijn incoming, 0, NULL);
758 ce062d50 2019-08-21 martijn }
759 ce062d50 2019-08-21 martijn
760 ce062d50 2019-08-21 martijn void
761 ce062d50 2019-08-21 martijn osmtpd_register_report_client(int incoming, void (*cb)(struct osmtpd_ctx *,
762 ce062d50 2019-08-21 martijn const char *))
763 ce062d50 2019-08-21 martijn {
764 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_PROTOCOL_CLIENT,
765 ce062d50 2019-08-21 martijn incoming, 0, (void *)cb);
766 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
767 ce062d50 2019-08-21 martijn incoming, 0, NULL);
768 ce062d50 2019-08-21 martijn }
769 ce062d50 2019-08-21 martijn
770 ce062d50 2019-08-21 martijn void
771 ce062d50 2019-08-21 martijn osmtpd_register_report_server(int incoming, void (*cb)(struct osmtpd_ctx *,
772 ce062d50 2019-08-21 martijn const char *))
773 ce062d50 2019-08-21 martijn {
774 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_PROTOCOL_SERVER,
775 ce062d50 2019-08-21 martijn incoming, 0, (void *)cb);
776 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
777 ce062d50 2019-08-21 martijn incoming, 0, NULL);
778 ce062d50 2019-08-21 martijn }
779 ce062d50 2019-08-21 martijn
780 ce062d50 2019-08-21 martijn void
781 ce062d50 2019-08-21 martijn osmtpd_register_report_response(int incoming, void (*cb)(struct osmtpd_ctx *,
782 ce062d50 2019-08-21 martijn const char *))
783 ce062d50 2019-08-21 martijn {
784 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_FILTER_RESPONSE,
785 ce062d50 2019-08-21 martijn incoming, 0, (void *)cb);
786 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
787 ce062d50 2019-08-21 martijn incoming, 0, NULL);
788 ce062d50 2019-08-21 martijn }
789 ce062d50 2019-08-21 martijn
790 ce062d50 2019-08-21 martijn void
791 ce062d50 2019-08-21 martijn osmtpd_register_report_timeout(int incoming, void (*cb)(struct osmtpd_ctx *))
792 ce062d50 2019-08-21 martijn {
793 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TIMEOUT, incoming, 0,
794 ce062d50 2019-08-21 martijn (void *)cb);
795 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
796 ce062d50 2019-08-21 martijn incoming, 0, NULL);
797 ce062d50 2019-08-21 martijn }
798 ce062d50 2019-08-21 martijn
799 ce062d50 2019-08-21 martijn void
800 ce062d50 2019-08-21 martijn osmtpd_localdata(void *(*oncreate)(struct osmtpd_ctx *),
801 ce062d50 2019-08-21 martijn void (*ondelete)(struct osmtpd_ctx *, void *))
802 ce062d50 2019-08-21 martijn {
803 ce062d50 2019-08-21 martijn oncreatecb = oncreate;
804 ce062d50 2019-08-21 martijn ondeletecb = ondelete;
805 ce062d50 2019-08-21 martijn }
806 ce062d50 2019-08-21 martijn
807 ce062d50 2019-08-21 martijn void
808 ce062d50 2019-08-21 martijn osmtpd_need(int incoming, int needs)
809 ce062d50 2019-08-21 martijn {
810 ce062d50 2019-08-21 martijn if (needs & (OSMTPD_NEED_SRC | OSMTPD_NEED_DST | OSMTPD_NEED_RDNS |
811 ce062d50 2019-08-21 martijn OSMTPD_NEED_FRDNS))
812 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_LINK_CONNECT,
813 ce062d50 2019-08-21 martijn incoming, 1, NULL);
814 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_IDENTITY)
815 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_IDENTIFY,
816 ce062d50 2019-08-21 martijn incoming, 1, NULL);
817 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_CIPHERS)
818 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_TLS,
819 ce062d50 2019-08-21 martijn incoming, 1, NULL);
820 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_MSGID) {
821 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_BEGIN,
822 ce062d50 2019-08-21 martijn incoming, 1, NULL);
823 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ROLLBACK,
824 ce062d50 2019-08-21 martijn incoming, 0, NULL);
825 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_COMMIT,
826 ce062d50 2019-08-21 martijn incoming, 0, NULL);
827 ce062d50 2019-08-21 martijn }
828 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_MAILFROM) {
829 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_MAIL,
830 ce062d50 2019-08-21 martijn incoming, 1, NULL);
831 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ROLLBACK,
832 ce062d50 2019-08-21 martijn incoming, 0, NULL);
833 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_COMMIT,
834 ce062d50 2019-08-21 martijn incoming, 0, NULL);
835 ce062d50 2019-08-21 martijn }
836 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_RCPTTO) {
837 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_RCPT,
838 ce062d50 2019-08-21 martijn incoming, 1, NULL);
839 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ROLLBACK,
840 ce062d50 2019-08-21 martijn incoming, 0, NULL);
841 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_COMMIT,
842 ce062d50 2019-08-21 martijn incoming, 0, NULL);
843 ce062d50 2019-08-21 martijn }
844 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_EVPID) {
845 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ENVELOPE,
846 ce062d50 2019-08-21 martijn incoming, 1, NULL);
847 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ROLLBACK,
848 ce062d50 2019-08-21 martijn incoming, 0, NULL);
849 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_COMMIT,
850 ce062d50 2019-08-21 martijn incoming, 0, NULL);
851 ce062d50 2019-08-21 martijn }
852 ce062d50 2019-08-21 martijn
853 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
854 ce062d50 2019-08-21 martijn incoming, 0, NULL);
855 ce062d50 2019-08-21 martijn }
856 ce062d50 2019-08-21 martijn
857 ce062d50 2019-08-21 martijn void
858 ce062d50 2019-08-21 martijn osmtpd_run(void)
859 ce062d50 2019-08-21 martijn {
860 ce062d50 2019-08-21 martijn size_t i = 0;
861 ce062d50 2019-08-21 martijn int registered = 0;
862 ce062d50 2019-08-21 martijn /* Doesn't leak, since it needs to exists until the application ends. */
863 ce062d50 2019-08-21 martijn struct io *io_stdin;
864 ce062d50 2019-08-21 martijn
865 ce062d50 2019-08-21 martijn event_init();
866 ce062d50 2019-08-21 martijn
867 ce062d50 2019-08-21 martijn if ((io_stdin = io_new()) == NULL ||
868 ce062d50 2019-08-21 martijn (io_stdout = io_new()) == NULL)
869 ce062d50 2019-08-21 martijn err(1, "io_new");
870 ce062d50 2019-08-21 martijn io_set_nonblocking(STDIN_FILENO);
871 ce062d50 2019-08-21 martijn io_set_fd(io_stdin, STDIN_FILENO);
872 ce062d50 2019-08-21 martijn io_set_callback(io_stdin, osmtpd_newline, NULL);
873 ce062d50 2019-08-21 martijn io_set_read(io_stdin);
874 ce062d50 2019-08-21 martijn io_set_nonblocking(STDOUT_FILENO);
875 ce062d50 2019-08-21 martijn io_set_fd(io_stdout, STDOUT_FILENO);
876 ce062d50 2019-08-21 martijn io_set_callback(io_stdout, osmtpd_outevt, NULL);
877 ce062d50 2019-08-21 martijn io_set_write(io_stdout);
878 ce062d50 2019-08-21 martijn
879 ce062d50 2019-08-21 martijn for (i = 0; i < NITEMS(osmtpd_callbacks); i++) {
880 ce062d50 2019-08-21 martijn if (osmtpd_callbacks[i].doregister) {
881 ce062d50 2019-08-21 martijn if (osmtpd_callbacks[i].cb != NULL)
882 ce062d50 2019-08-21 martijn registered = 1;
883 ce062d50 2019-08-21 martijn io_printf(io_stdout, "register|%s|smtp-%s|%s\n",
884 ce062d50 2019-08-21 martijn osmtpd_typetostr(osmtpd_callbacks[i].type),
885 ce062d50 2019-08-21 martijn osmtpd_callbacks[i].incoming ? "in" : "out",
886 ce062d50 2019-08-21 martijn osmtpd_phasetostr(osmtpd_callbacks[i].phase));
887 ce062d50 2019-08-21 martijn }
888 ce062d50 2019-08-21 martijn }
889 ce062d50 2019-08-21 martijn
890 ce062d50 2019-08-21 martijn if (!registered)
891 ce062d50 2019-08-21 martijn errx(1, "No events registered");
892 ce062d50 2019-08-21 martijn io_printf(io_stdout, "register|ready\n");
893 ce062d50 2019-08-21 martijn ready = 1;
894 ce062d50 2019-08-21 martijn
895 ce062d50 2019-08-21 martijn event_dispatch();
896 ce062d50 2019-08-21 martijn }
897 ce062d50 2019-08-21 martijn
898 ce062d50 2019-08-21 martijn static void
899 ce062d50 2019-08-21 martijn osmtpd_newline(struct io *io, int ev, void *arg)
900 ce062d50 2019-08-21 martijn {
901 ce062d50 2019-08-21 martijn static char *linedup = NULL;
902 ce062d50 2019-08-21 martijn static size_t dupsize = 0;
903 ce062d50 2019-08-21 martijn struct osmtpd_session *ctx, search;
904 ce062d50 2019-08-21 martijn enum osmtpd_type type;
905 ce062d50 2019-08-21 martijn enum osmtpd_phase phase;
906 ce062d50 2019-08-21 martijn int version_major, version_minor, incoming;
907 ce062d50 2019-08-21 martijn struct timespec tm;
908 ce062d50 2019-08-21 martijn char *line = NULL;
909 ce062d50 2019-08-21 martijn const char *errstr = NULL;
910 ce062d50 2019-08-21 martijn size_t linelen;
911 ce062d50 2019-08-21 martijn char *end;
912 ce062d50 2019-08-21 martijn size_t i;
913 ce062d50 2019-08-21 martijn
914 ce062d50 2019-08-21 martijn if (ev == IO_DISCONNECTED)
915 ce062d50 2019-08-21 martijn exit(0);
916 ce062d50 2019-08-21 martijn if (ev != IO_DATAIN)
917 ce062d50 2019-08-21 martijn return;
918 ce062d50 2019-08-21 martijn while ((line = io_getline(io, &linelen)) > 0) {
919 ce062d50 2019-08-21 martijn if (dupsize < linelen) {
920 ce062d50 2019-08-21 martijn if ((linedup = realloc(linedup, linelen + 1)) == NULL)
921 ce062d50 2019-08-21 martijn err(1, NULL);
922 ce062d50 2019-08-21 martijn dupsize = linelen + 1;
923 ce062d50 2019-08-21 martijn }
924 ce062d50 2019-08-21 martijn strlcpy(linedup, line, dupsize);
925 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
926 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: missing version: %s", linedup);
927 ce062d50 2019-08-21 martijn end++[0] = '\0';
928 ce062d50 2019-08-21 martijn if (strcmp(line, "filter") == 0)
929 ce062d50 2019-08-21 martijn type = OSMTPD_TYPE_FILTER;
930 ce062d50 2019-08-21 martijn else if (strcmp(line, "report") == 0)
931 ce062d50 2019-08-21 martijn type = OSMTPD_TYPE_REPORT;
932 ce062d50 2019-08-21 martijn else if (strcmp(line, "config") == 0) {
933 ce062d50 2019-08-21 martijn line = end;
934 ce062d50 2019-08-21 martijn if (strcmp(line, "ready") == 0)
935 ce062d50 2019-08-21 martijn continue;
936 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
937 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: missing key: %s", linedup);
938 ce062d50 2019-08-21 martijn end++[0] = '\0';
939 ce062d50 2019-08-21 martijn if (strcmp(line, "smtp-session-timeout") == 0) {
940 ce062d50 2019-08-21 martijn session_timeout = strtonum(end, 0, INT_MAX,
941 ce062d50 2019-08-21 martijn &errstr);
942 ce062d50 2019-08-21 martijn if (errstr != NULL)
943 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: "
944 ce062d50 2019-08-21 martijn "invalid smtp-sesion-timeout: %s",
945 ce062d50 2019-08-21 martijn linedup);
946 ce062d50 2019-08-21 martijn }
947 ce062d50 2019-08-21 martijn continue;
948 ce062d50 2019-08-21 martijn }
949 ce062d50 2019-08-21 martijn else
950 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: unknown message type: %s", linedup);
951 ce062d50 2019-08-21 martijn line = end;
952 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
953 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: missing time: %s", linedup);
954 ce062d50 2019-08-21 martijn end++[0] = '\0';
955 ce062d50 2019-08-21 martijn if (strcmp(line, "0.1") != 0)
956 ce062d50 2019-08-21 martijn errx(1, "Unsupported protocol received: %s", linedup);
957 ce062d50 2019-08-21 martijn version_major = 0;
958 ce062d50 2019-08-21 martijn version_minor = 1;
959 ce062d50 2019-08-21 martijn line = end;
960 ce062d50 2019-08-21 martijn if ((end = strchr(line, '.')) == NULL)
961 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid timestamp: %s", linedup);
962 ce062d50 2019-08-21 martijn end++[0] = '\0';
963 ce062d50 2019-08-21 martijn tm.tv_sec = (time_t) strtonum(line, 0, INT64_MAX, &errstr);
964 ce062d50 2019-08-21 martijn if (errstr != NULL)
965 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid timestamp: %s", linedup);
966 ce062d50 2019-08-21 martijn line = end;
967 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
968 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: missing direction: %s", linedup);
969 ce062d50 2019-08-21 martijn end++[0] = '\0';
970 ce062d50 2019-08-21 martijn tm.tv_nsec = (long) strtonum(line, 0, LONG_MAX, &errstr);
971 ce062d50 2019-08-21 martijn if (errstr != NULL)
972 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid timestamp: %s",
973 ce062d50 2019-08-21 martijn linedup);
974 ce062d50 2019-08-21 martijn tm.tv_nsec *= 10 * (9 - (end - line));
975 ce062d50 2019-08-21 martijn line = end;
976 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
977 ce062d50 2019-08-21 martijn errx(1, "Invalid line receieved: missing phase: %s",
978 ce062d50 2019-08-21 martijn linedup);
979 ce062d50 2019-08-21 martijn end++[0] = '\0';
980 ce062d50 2019-08-21 martijn if (strcmp(line, "smtp-in") == 0)
981 ce062d50 2019-08-21 martijn incoming = 1;
982 ce062d50 2019-08-21 martijn else if (strcmp(line, "smtp-out") == 0)
983 ce062d50 2019-08-21 martijn incoming = 0;
984 ce062d50 2019-08-21 martijn else
985 ce062d50 2019-08-21 martijn errx(1, "Invalid line: invalid direction: %s", linedup);
986 ce062d50 2019-08-21 martijn line = end;
987 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
988 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: missing reqid: %s",
989 ce062d50 2019-08-21 martijn linedup);
990 ce062d50 2019-08-21 martijn end++[0] = '\0';
991 ce062d50 2019-08-21 martijn phase = osmtpd_strtophase(line, linedup);
992 ce062d50 2019-08-21 martijn line = end;
993 ce062d50 2019-08-21 martijn errno = 0;
994 ce062d50 2019-08-21 martijn search.ctx.reqid = strtoull(line, &end, 16);
995 ce062d50 2019-08-21 martijn if ((search.ctx.reqid == ULLONG_MAX && errno != 0) ||
996 ce062d50 2019-08-21 martijn (end[0] != '|' && end[0] != '\0'))
997 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid reqid: %s",
998 ce062d50 2019-08-21 martijn linedup);
999 ce062d50 2019-08-21 martijn line = end + 1;
1000 ce062d50 2019-08-21 martijn ctx = RB_FIND(osmtpd_sessions, &osmtpd_sessions, &search);
1001 ce062d50 2019-08-21 martijn if (ctx == NULL) {
1002 ce062d50 2019-08-21 martijn if ((ctx = malloc(sizeof(*ctx))) == NULL)
1003 ce062d50 2019-08-21 martijn err(1, NULL);
1004 ce062d50 2019-08-21 martijn ctx->ctx.reqid = search.ctx.reqid;
1005 ce062d50 2019-08-21 martijn ctx->ctx.rdns = NULL;
1006 ce062d50 2019-08-21 martijn ctx->ctx.fcrdns = NULL;
1007 ce062d50 2019-08-21 martijn ctx->ctx.identity = NULL;
1008 ce062d50 2019-08-21 martijn ctx->ctx.ciphers = NULL;
1009 ce062d50 2019-08-21 martijn ctx->ctx.msgid = 0;
1010 ce062d50 2019-08-21 martijn ctx->ctx.mailfrom = NULL;
1011 ce062d50 2019-08-21 martijn ctx->ctx.rcptto = malloc(sizeof(*(ctx->ctx.rcptto)));
1012 ce062d50 2019-08-21 martijn if (ctx->ctx.rcptto == NULL)
1013 ce062d50 2019-08-21 martijn err(1, "malloc");
1014 ce062d50 2019-08-21 martijn ctx->ctx.rcptto[0] = NULL;
1015 ce062d50 2019-08-21 martijn memset(&(ctx->ctx.src), 0, sizeof(ctx->ctx.src));
1016 ce062d50 2019-08-21 martijn ctx->ctx.src.ss_family = AF_UNSPEC;
1017 ce062d50 2019-08-21 martijn memset(&(ctx->ctx.dst), 0, sizeof(ctx->ctx.dst));
1018 ce062d50 2019-08-21 martijn ctx->ctx.dst.ss_family = AF_UNSPEC;
1019 ce062d50 2019-08-21 martijn RB_INSERT(osmtpd_sessions, &osmtpd_sessions, ctx);
1020 ce062d50 2019-08-21 martijn ctx->ctx.evpid = 0;
1021 ce062d50 2019-08-21 martijn ctx->ctx.local = NULL;
1022 ce062d50 2019-08-21 martijn if (oncreatecb != NULL)
1023 ce062d50 2019-08-21 martijn ctx->ctx.local = oncreatecb(&ctx->ctx);
1024 ce062d50 2019-08-21 martijn }
1025 ce062d50 2019-08-21 martijn ctx->ctx.type = type;
1026 ce062d50 2019-08-21 martijn ctx->ctx.phase = phase;
1027 ce062d50 2019-08-21 martijn ctx->ctx.version_major = version_major;
1028 ce062d50 2019-08-21 martijn ctx->ctx.version_minor = version_minor;
1029 ce062d50 2019-08-21 martijn ctx->ctx.incoming = incoming;
1030 ce062d50 2019-08-21 martijn ctx->ctx.tm.tv_sec = tm.tv_sec;
1031 ce062d50 2019-08-21 martijn ctx->ctx.tm.tv_nsec = tm.tv_nsec;
1032 ce062d50 2019-08-21 martijn ctx->ctx.token = 0;
1033 ce062d50 2019-08-21 martijn
1034 ce062d50 2019-08-21 martijn for (i = 0; i < NITEMS(osmtpd_callbacks); i++) {
1035 ce062d50 2019-08-21 martijn if (ctx->ctx.type == osmtpd_callbacks[i].type &&
1036 ce062d50 2019-08-21 martijn ctx->ctx.phase == osmtpd_callbacks[i].phase &&
1037 ce062d50 2019-08-21 martijn ctx->ctx.incoming == osmtpd_callbacks[i].incoming)
1038 ce062d50 2019-08-21 martijn break;
1039 ce062d50 2019-08-21 martijn }
1040 ce062d50 2019-08-21 martijn if (i == NITEMS(osmtpd_callbacks)) {
1041 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: received unregistered "
1042 ce062d50 2019-08-21 martijn "line: %s", linedup);
1043 ce062d50 2019-08-21 martijn }
1044 ce062d50 2019-08-21 martijn if (ctx->ctx.type == OSMTPD_TYPE_FILTER) {
1045 ce062d50 2019-08-21 martijn ctx->ctx.token = strtoull(line, &end, 16);
1046 ce062d50 2019-08-21 martijn if ((ctx->ctx.token == ULLONG_MAX && errno != 0) ||
1047 ce062d50 2019-08-21 martijn end[0] != '|')
1048 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid token: %s", linedup);
1049 ce062d50 2019-08-21 martijn line = end + 1;
1050 ce062d50 2019-08-21 martijn }
1051 ce062d50 2019-08-21 martijn osmtpd_callbacks[i].osmtpd_cb(&(osmtpd_callbacks[i]),
1052 ce062d50 2019-08-21 martijn &(ctx->ctx), line, linedup);
1053 ce062d50 2019-08-21 martijn }
1054 ce062d50 2019-08-21 martijn }
1055 ce062d50 2019-08-21 martijn
1056 ce062d50 2019-08-21 martijn static void
1057 ce062d50 2019-08-21 martijn osmtpd_outevt(struct io *io, int evt, void *arg)
1058 ce062d50 2019-08-21 martijn {
1059 ce062d50 2019-08-21 martijn switch (evt) {
1060 ce062d50 2019-08-21 martijn case IO_LOWAT:
1061 ce062d50 2019-08-21 martijn return;
1062 ce062d50 2019-08-21 martijn case IO_DISCONNECTED:
1063 ce062d50 2019-08-21 martijn exit(0);
1064 ce062d50 2019-08-21 martijn default:
1065 ce062d50 2019-08-21 martijn errx(1, "Unexpectd event");
1066 ce062d50 2019-08-21 martijn }
1067 ce062d50 2019-08-21 martijn }
1068 ce062d50 2019-08-21 martijn
1069 ce062d50 2019-08-21 martijn static void
1070 ce062d50 2019-08-21 martijn osmtpd_noargs(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx, char *params,
1071 ce062d50 2019-08-21 martijn char *linedup)
1072 ce062d50 2019-08-21 martijn {
1073 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *);
1074 ce062d50 2019-08-21 martijn
1075 ce062d50 2019-08-21 martijn f = cb->cb;
1076 ce062d50 2019-08-21 martijn f(ctx);
1077 ce062d50 2019-08-21 martijn }
1078 ce062d50 2019-08-21 martijn
1079 ce062d50 2019-08-21 martijn static void
1080 ce062d50 2019-08-21 martijn osmtpd_onearg(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx, char *line,
1081 ce062d50 2019-08-21 martijn char *linedup)
1082 ce062d50 2019-08-21 martijn {
1083 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, const char *);
1084 ce062d50 2019-08-21 martijn
1085 ce062d50 2019-08-21 martijn f = cb->cb;
1086 ce062d50 2019-08-21 martijn f(ctx, line);
1087 ce062d50 2019-08-21 martijn }
1088 ce062d50 2019-08-21 martijn
1089 ce062d50 2019-08-21 martijn static void
1090 ce062d50 2019-08-21 martijn osmtpd_connect(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx, char *params,
1091 ce062d50 2019-08-21 martijn char *linedup)
1092 ce062d50 2019-08-21 martijn {
1093 ce062d50 2019-08-21 martijn struct sockaddr_storage ss;
1094 ce062d50 2019-08-21 martijn char *hostname;
1095 ce062d50 2019-08-21 martijn char *address;
1096 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, const char *, struct sockaddr_storage *);
1097 ce062d50 2019-08-21 martijn
1098 ce062d50 2019-08-21 martijn hostname = params;
1099 ce062d50 2019-08-21 martijn if ((address = strchr(params, '|')) == NULL)
1100 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: missing address: %s", linedup);
1101 ce062d50 2019-08-21 martijn address++[0] = '\0';
1102 ce062d50 2019-08-21 martijn
1103 ce062d50 2019-08-21 martijn osmtpd_addrtoss(address, &ss, 0, linedup);
1104 ce062d50 2019-08-21 martijn
1105 ce062d50 2019-08-21 martijn f = cb->cb;
1106 ce062d50 2019-08-21 martijn f(ctx, hostname, &ss);
1107 ce062d50 2019-08-21 martijn }
1108 ce062d50 2019-08-21 martijn
1109 ce062d50 2019-08-21 martijn static void
1110 ce062d50 2019-08-21 martijn osmtpd_link_connect(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1111 ce062d50 2019-08-21 martijn char *params, char *linedup)
1112 ce062d50 2019-08-21 martijn {
1113 ce062d50 2019-08-21 martijn char *end, *rdns, *fcrdns;
1114 ce062d50 2019-08-21 martijn struct sockaddr_storage src, dst;
1115 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, const char *, const char *,
1116 ce062d50 2019-08-21 martijn struct sockaddr_storage *, struct sockaddr_storage *);
1117 ce062d50 2019-08-21 martijn
1118 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1119 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: missing fcrdns: %s", linedup);
1120 ce062d50 2019-08-21 martijn end++[0] = '\0';
1121 ce062d50 2019-08-21 martijn rdns = params;
1122 ce062d50 2019-08-21 martijn params = end;
1123 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1124 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: missing src: %s", linedup);
1125 ce062d50 2019-08-21 martijn end++[0] = '\0';
1126 ce062d50 2019-08-21 martijn fcrdns = params;
1127 ce062d50 2019-08-21 martijn params = end;
1128 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1129 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: missing dst: %s", linedup);
1130 ce062d50 2019-08-21 martijn end++[0] = '\0';
1131 ce062d50 2019-08-21 martijn osmtpd_addrtoss(params, &src, 1, linedup);
1132 ce062d50 2019-08-21 martijn params = end;
1133 ce062d50 2019-08-21 martijn osmtpd_addrtoss(params, &dst, 1, linedup);
1134 ce062d50 2019-08-21 martijn if (cb->storereport) {
1135 ce062d50 2019-08-21 martijn if ((ctx->rdns = strdup(params)) == NULL)
1136 ce062d50 2019-08-21 martijn err(1, NULL);
1137 ce062d50 2019-08-21 martijn if ((ctx->fcrdns = strdup(params)) == NULL)
1138 ce062d50 2019-08-21 martijn err(1, NULL);
1139 ce062d50 2019-08-21 martijn memcpy(&(ctx->src), &src, sizeof(ctx->src));
1140 ce062d50 2019-08-21 martijn memcpy(&(ctx->dst), &dst, sizeof(ctx->dst));
1141 ce062d50 2019-08-21 martijn }
1142 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1143 ce062d50 2019-08-21 martijn f(ctx, rdns, fcrdns, &src, &dst);
1144 ce062d50 2019-08-21 martijn }
1145 ce062d50 2019-08-21 martijn
1146 ce062d50 2019-08-21 martijn static void
1147 ce062d50 2019-08-21 martijn osmtpd_link_disconnect(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1148 ce062d50 2019-08-21 martijn char *param, char *linedup)
1149 ce062d50 2019-08-21 martijn {
1150 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *);
1151 ce062d50 2019-08-21 martijn size_t i;
1152 ce062d50 2019-08-21 martijn struct osmtpd_session *session, search;
1153 ce062d50 2019-08-21 martijn
1154 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1155 ce062d50 2019-08-21 martijn f(ctx);
1156 ce062d50 2019-08-21 martijn
1157 ce062d50 2019-08-21 martijn search.ctx.reqid = ctx->reqid;
1158 ce062d50 2019-08-21 martijn session = RB_FIND(osmtpd_sessions, &osmtpd_sessions, &search);
1159 ce062d50 2019-08-21 martijn if (session != NULL) {
1160 ce062d50 2019-08-21 martijn RB_REMOVE(osmtpd_sessions, &osmtpd_sessions, session);
1161 ce062d50 2019-08-21 martijn if (ondeletecb != NULL)
1162 ce062d50 2019-08-21 martijn ondeletecb(ctx, session->ctx.local);
1163 ce062d50 2019-08-21 martijn free(session->ctx.rdns);
1164 ce062d50 2019-08-21 martijn free(session->ctx.fcrdns);
1165 ce062d50 2019-08-21 martijn free(session->ctx.identity);
1166 ce062d50 2019-08-21 martijn free(session->ctx.ciphers);
1167 ce062d50 2019-08-21 martijn free(session->ctx.mailfrom);
1168 ce062d50 2019-08-21 martijn for (i = 0; session->ctx.rcptto[i] != NULL; i++)
1169 ce062d50 2019-08-21 martijn free(session->ctx.rcptto[i]);
1170 ce062d50 2019-08-21 martijn free(session->ctx.rcptto);
1171 ce062d50 2019-08-21 martijn free(session);
1172 ce062d50 2019-08-21 martijn }
1173 ce062d50 2019-08-21 martijn }
1174 ce062d50 2019-08-21 martijn
1175 ce062d50 2019-08-21 martijn static void
1176 ce062d50 2019-08-21 martijn osmtpd_link_identify(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1177 ce062d50 2019-08-21 martijn char *identity, char *linedup)
1178 ce062d50 2019-08-21 martijn {
1179 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, const char *);
1180 ce062d50 2019-08-21 martijn
1181 ce062d50 2019-08-21 martijn if (cb->storereport) {
1182 ce062d50 2019-08-21 martijn if ((ctx->identity = strdup(identity)) == NULL)
1183 ce062d50 2019-08-21 martijn err(1, NULL);
1184 ce062d50 2019-08-21 martijn }
1185 ce062d50 2019-08-21 martijn
1186 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1187 ce062d50 2019-08-21 martijn f(ctx, identity);
1188 ce062d50 2019-08-21 martijn }
1189 ce062d50 2019-08-21 martijn
1190 ce062d50 2019-08-21 martijn static void
1191 ce062d50 2019-08-21 martijn osmtpd_link_tls(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1192 ce062d50 2019-08-21 martijn char *ciphers, char *linedup)
1193 ce062d50 2019-08-21 martijn {
1194 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, const char *);
1195 ce062d50 2019-08-21 martijn
1196 ce062d50 2019-08-21 martijn if (cb->storereport) {
1197 ce062d50 2019-08-21 martijn if ((ctx->ciphers = strdup(ciphers)) == NULL)
1198 ce062d50 2019-08-21 martijn err(1, NULL);
1199 ce062d50 2019-08-21 martijn }
1200 ce062d50 2019-08-21 martijn
1201 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1202 ce062d50 2019-08-21 martijn f(ctx, ciphers);
1203 ce062d50 2019-08-21 martijn }
1204 ce062d50 2019-08-21 martijn
1205 ce062d50 2019-08-21 martijn static void
1206 ce062d50 2019-08-21 martijn osmtpd_tx_begin(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1207 ce062d50 2019-08-21 martijn char *msgid, char *linedup)
1208 ce062d50 2019-08-21 martijn {
1209 ce062d50 2019-08-21 martijn unsigned long imsgid;
1210 ce062d50 2019-08-21 martijn char *endptr;
1211 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t);
1212 ce062d50 2019-08-21 martijn
1213 ce062d50 2019-08-21 martijn errno = 0;
1214 ce062d50 2019-08-21 martijn imsgid = strtoul(msgid, &endptr, 16);
1215 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0) || endptr[0] != '\0')
1216 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid msgid: %s", linedup);
1217 ce062d50 2019-08-21 martijn ctx->msgid = imsgid;
1218 ce062d50 2019-08-21 martijn /* Check if we're in range */
1219 ce062d50 2019-08-21 martijn if ((unsigned long) ctx->msgid != imsgid)
1220 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid msgid: %s", linedup);
1221 ce062d50 2019-08-21 martijn
1222 ce062d50 2019-08-21 martijn if (!cb->storereport)
1223 ce062d50 2019-08-21 martijn ctx->msgid = 0;
1224 ce062d50 2019-08-21 martijn
1225 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1226 ce062d50 2019-08-21 martijn f(ctx, imsgid);
1227 ce062d50 2019-08-21 martijn }
1228 ce062d50 2019-08-21 martijn
1229 ce062d50 2019-08-21 martijn static void
1230 ce062d50 2019-08-21 martijn osmtpd_tx_mail(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1231 ce062d50 2019-08-21 martijn char *params, char *linedup)
1232 ce062d50 2019-08-21 martijn {
1233 ce062d50 2019-08-21 martijn char *end, *mailfrom;
1234 ce062d50 2019-08-21 martijn unsigned long imsgid;
1235 ce062d50 2019-08-21 martijn uint32_t msgid;
1236 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t, const char *,
1237 ce062d50 2019-08-21 martijn enum osmtpd_status);
1238 ce062d50 2019-08-21 martijn
1239 ce062d50 2019-08-21 martijn errno = 0;
1240 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1241 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1242 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid msgid: %s", linedup);
1243 ce062d50 2019-08-21 martijn if (end[0] != '|')
1244 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: missing address: %s", linedup);
1245 ce062d50 2019-08-21 martijn msgid = imsgid;
1246 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1247 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid msgid: %s", linedup);
1248 ce062d50 2019-08-21 martijn params = end + 1;
1249 ce062d50 2019-08-21 martijn
1250 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1251 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: missing status: %s", linedup);
1252 ce062d50 2019-08-21 martijn end++[0] = '\0';
1253 ce062d50 2019-08-21 martijn mailfrom = params;
1254 ce062d50 2019-08-21 martijn if (cb->storereport) {
1255 ce062d50 2019-08-21 martijn if ((ctx->mailfrom = strdup(mailfrom)) == NULL)
1256 ce062d50 2019-08-21 martijn err(1, NULL);
1257 ce062d50 2019-08-21 martijn }
1258 ce062d50 2019-08-21 martijn params = end;
1259 ce062d50 2019-08-21 martijn
1260 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1261 996ed925 2019-08-21 martijn f(ctx, msgid, mailfrom, osmtpd_strtostatus(params, linedup));
1262 ce062d50 2019-08-21 martijn }
1263 ce062d50 2019-08-21 martijn
1264 ce062d50 2019-08-21 martijn static void
1265 ce062d50 2019-08-21 martijn osmtpd_tx_rcpt(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1266 ce062d50 2019-08-21 martijn char *params, char *linedup)
1267 ce062d50 2019-08-21 martijn {
1268 ce062d50 2019-08-21 martijn char *end, *rcptto;
1269 ce062d50 2019-08-21 martijn unsigned long imsgid;
1270 ce062d50 2019-08-21 martijn uint32_t msgid;
1271 ce062d50 2019-08-21 martijn size_t i;
1272 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t, const char *,
1273 ce062d50 2019-08-21 martijn enum osmtpd_status);
1274 ce062d50 2019-08-21 martijn
1275 ce062d50 2019-08-21 martijn errno = 0;
1276 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1277 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1278 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid msgid: %s", linedup);
1279 ce062d50 2019-08-21 martijn if (end[0] != '|')
1280 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: missing address: %s", linedup);
1281 ce062d50 2019-08-21 martijn msgid = imsgid;
1282 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1283 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid msgid: %s", linedup);
1284 ce062d50 2019-08-21 martijn params = end + 1;
1285 ce062d50 2019-08-21 martijn
1286 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1287 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: missing status: %s", linedup);
1288 ce062d50 2019-08-21 martijn end++[0] = '\0';
1289 ce062d50 2019-08-21 martijn
1290 ce062d50 2019-08-21 martijn rcptto = params;
1291 ce062d50 2019-08-21 martijn params = end;
1292 ce062d50 2019-08-21 martijn
1293 ce062d50 2019-08-21 martijn if (cb->storereport) {
1294 ce062d50 2019-08-21 martijn for (i = 0; ctx->rcptto[i] != NULL; i++)
1295 ce062d50 2019-08-21 martijn ;
1296 ce062d50 2019-08-21 martijn ctx->rcptto = reallocarray(ctx->rcptto, i + 2,
1297 ce062d50 2019-08-21 martijn sizeof(*(ctx->rcptto)));
1298 ce062d50 2019-08-21 martijn if (ctx->rcptto == NULL)
1299 ce062d50 2019-08-21 martijn err(1, NULL);
1300 ce062d50 2019-08-21 martijn
1301 ce062d50 2019-08-21 martijn if ((ctx->rcptto[i] = strdup(rcptto)) == NULL)
1302 ce062d50 2019-08-21 martijn err(1, NULL);
1303 ce062d50 2019-08-21 martijn ctx->rcptto[i + 1] = NULL;
1304 ce062d50 2019-08-21 martijn }
1305 ce062d50 2019-08-21 martijn
1306 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1307 ce062d50 2019-08-21 martijn f(ctx, msgid, rcptto,
1308 ce062d50 2019-08-21 martijn osmtpd_strtostatus(params, linedup));
1309 ce062d50 2019-08-21 martijn }
1310 ce062d50 2019-08-21 martijn
1311 ce062d50 2019-08-21 martijn static void
1312 ce062d50 2019-08-21 martijn osmtpd_tx_envelope(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1313 ce062d50 2019-08-21 martijn char *params, char *linedup)
1314 ce062d50 2019-08-21 martijn {
1315 ce062d50 2019-08-21 martijn unsigned long imsgid;
1316 ce062d50 2019-08-21 martijn uint32_t msgid;
1317 ce062d50 2019-08-21 martijn uint64_t evpid;
1318 ce062d50 2019-08-21 martijn char *end;
1319 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t, uint64_t);
1320 ce062d50 2019-08-21 martijn
1321 ce062d50 2019-08-21 martijn errno = 0;
1322 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1323 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1324 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid msgid: %s", linedup);
1325 ce062d50 2019-08-21 martijn if (end[0] != '|')
1326 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: missing address: %s", linedup);
1327 ce062d50 2019-08-21 martijn msgid = imsgid;
1328 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1329 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid msgid: %s", linedup);
1330 ce062d50 2019-08-21 martijn params = end + 1;
1331 ce062d50 2019-08-21 martijn
1332 ce062d50 2019-08-21 martijn evpid = strtoull(params, &end, 16);
1333 ce062d50 2019-08-21 martijn if ((ctx->evpid == ULLONG_MAX && errno != 0) ||
1334 ce062d50 2019-08-21 martijn end[0] != '\0')
1335 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid evpid: %s", linedup);
1336 ce062d50 2019-08-21 martijn if (cb->storereport)
1337 ce062d50 2019-08-21 martijn ctx->evpid = evpid;
1338 ce062d50 2019-08-21 martijn
1339 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1340 ce062d50 2019-08-21 martijn f(ctx, msgid, evpid);
1341 ce062d50 2019-08-21 martijn }
1342 ce062d50 2019-08-21 martijn
1343 ce062d50 2019-08-21 martijn static void
1344 ce062d50 2019-08-21 martijn osmtpd_tx_data(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1345 ce062d50 2019-08-21 martijn char *params, char *linedup)
1346 ce062d50 2019-08-21 martijn {
1347 ce062d50 2019-08-21 martijn char *end;
1348 ce062d50 2019-08-21 martijn unsigned long imsgid;
1349 ce062d50 2019-08-21 martijn uint32_t msgid;
1350 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t, enum osmtpd_status);
1351 ce062d50 2019-08-21 martijn
1352 ce062d50 2019-08-21 martijn errno = 0;
1353 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1354 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1355 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid msgid: %s", linedup);
1356 ce062d50 2019-08-21 martijn if (end[0] != '|')
1357 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: missing address: %s", linedup);
1358 ce062d50 2019-08-21 martijn msgid = imsgid;
1359 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1360 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid msgid: %s", linedup);
1361 ce062d50 2019-08-21 martijn params = end + 1;
1362 ce062d50 2019-08-21 martijn
1363 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1364 ce062d50 2019-08-21 martijn f(ctx, msgid, osmtpd_strtostatus(params, linedup));
1365 ce062d50 2019-08-21 martijn }
1366 ce062d50 2019-08-21 martijn
1367 ce062d50 2019-08-21 martijn static void
1368 ce062d50 2019-08-21 martijn osmtpd_tx_commit(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1369 ce062d50 2019-08-21 martijn char *params, char *linedup)
1370 ce062d50 2019-08-21 martijn {
1371 ce062d50 2019-08-21 martijn char *end;
1372 ce062d50 2019-08-21 martijn const char *errstr;
1373 ce062d50 2019-08-21 martijn unsigned long imsgid;
1374 ce062d50 2019-08-21 martijn uint32_t msgid;
1375 ce062d50 2019-08-21 martijn size_t i, msgsz;
1376 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t, size_t);
1377 ce062d50 2019-08-21 martijn
1378 ce062d50 2019-08-21 martijn errno = 0;
1379 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1380 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1381 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid msgid: %s", linedup);
1382 ce062d50 2019-08-21 martijn if (end[0] != '|')
1383 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: missing address: %s", linedup);
1384 ce062d50 2019-08-21 martijn msgid = imsgid;
1385 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1386 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid msgid: %s", linedup);
1387 ce062d50 2019-08-21 martijn params = end + 1;
1388 ce062d50 2019-08-21 martijn
1389 ce062d50 2019-08-21 martijn msgsz = strtonum(params, 0, SIZE_MAX, &errstr);
1390 ce062d50 2019-08-21 martijn if (errstr != NULL)
1391 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid msg size: %s", linedup);
1392 ce062d50 2019-08-21 martijn
1393 ce062d50 2019-08-21 martijn free(ctx->mailfrom);
1394 ce062d50 2019-08-21 martijn ctx->mailfrom = NULL;
1395 ce062d50 2019-08-21 martijn
1396 ce062d50 2019-08-21 martijn for (i = 0; ctx->rcptto[i] != NULL; i++)
1397 ce062d50 2019-08-21 martijn free(ctx->rcptto[i]);
1398 ce062d50 2019-08-21 martijn ctx->rcptto[0] = NULL;
1399 ce062d50 2019-08-21 martijn ctx->evpid = 0;
1400 ce062d50 2019-08-21 martijn ctx->msgid = 0;
1401 ce062d50 2019-08-21 martijn
1402 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1403 ce062d50 2019-08-21 martijn f(ctx, msgid, msgsz);
1404 ce062d50 2019-08-21 martijn }
1405 ce062d50 2019-08-21 martijn
1406 ce062d50 2019-08-21 martijn static void
1407 ce062d50 2019-08-21 martijn osmtpd_tx_rollback(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1408 ce062d50 2019-08-21 martijn char *params, char *linedup)
1409 ce062d50 2019-08-21 martijn {
1410 ce062d50 2019-08-21 martijn char *end;
1411 ce062d50 2019-08-21 martijn unsigned long imsgid;
1412 ce062d50 2019-08-21 martijn uint32_t msgid;
1413 ce062d50 2019-08-21 martijn size_t i;
1414 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t);
1415 ce062d50 2019-08-21 martijn
1416 ce062d50 2019-08-21 martijn errno = 0;
1417 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1418 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1419 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid msgid: %s", linedup);
1420 ce062d50 2019-08-21 martijn if (end[0] != '\0')
1421 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: missing address: %s", linedup);
1422 ce062d50 2019-08-21 martijn msgid = imsgid;
1423 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1424 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid msgid: %s", linedup);
1425 ce062d50 2019-08-21 martijn
1426 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1427 ce062d50 2019-08-21 martijn f(ctx, msgid);
1428 ce062d50 2019-08-21 martijn
1429 ce062d50 2019-08-21 martijn free(ctx->mailfrom);
1430 ce062d50 2019-08-21 martijn ctx->mailfrom = NULL;
1431 ce062d50 2019-08-21 martijn
1432 ce062d50 2019-08-21 martijn for (i = 0; ctx->rcptto[i] != NULL; i++)
1433 ce062d50 2019-08-21 martijn free(ctx->rcptto[i]);
1434 ce062d50 2019-08-21 martijn ctx->rcptto[0] = NULL;
1435 ce062d50 2019-08-21 martijn ctx->evpid = 0;
1436 ce062d50 2019-08-21 martijn ctx->msgid = 0;
1437 ce062d50 2019-08-21 martijn }
1438 ce062d50 2019-08-21 martijn
1439 ce062d50 2019-08-21 martijn void
1440 ce062d50 2019-08-21 martijn osmtpd_filter_proceed(struct osmtpd_ctx *ctx)
1441 ce062d50 2019-08-21 martijn {
1442 ce062d50 2019-08-21 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1443 ce062d50 2019-08-21 martijn "proceed\n", ctx->token, ctx->reqid);
1444 ce062d50 2019-08-21 martijn }
1445 ce062d50 2019-08-21 martijn
1446 ce062d50 2019-08-21 martijn void
1447 ce062d50 2019-08-21 martijn osmtpd_filter_reject(struct osmtpd_ctx *ctx, int code, const char *reason, ...)
1448 ce062d50 2019-08-21 martijn {
1449 ce062d50 2019-08-21 martijn va_list ap;
1450 ce062d50 2019-08-21 martijn
1451 ce062d50 2019-08-21 martijn if (code < 200 || code > 599)
1452 ce062d50 2019-08-21 martijn errx(1, "Invalid reject code");
1453 ce062d50 2019-08-21 martijn
1454 ce062d50 2019-08-21 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|reject|"
1455 ce062d50 2019-08-21 martijn "%d ", ctx->token, ctx->reqid, code);
1456 ce062d50 2019-08-21 martijn va_start(ap, reason);
1457 ce062d50 2019-08-21 martijn io_vprintf(io_stdout, reason, ap);
1458 ce062d50 2019-08-21 martijn va_end(ap);
1459 ce062d50 2019-08-21 martijn io_printf(io_stdout, "\n");
1460 ce062d50 2019-08-21 martijn }
1461 ce062d50 2019-08-21 martijn
1462 ce062d50 2019-08-21 martijn void
1463 ce062d50 2019-08-21 martijn osmtpd_filter_disconnect(struct osmtpd_ctx *ctx, const char *reason, ...)
1464 ce062d50 2019-08-21 martijn {
1465 ce062d50 2019-08-21 martijn va_list ap;
1466 ce062d50 2019-08-21 martijn
1467 ce062d50 2019-08-21 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1468 ce062d50 2019-08-21 martijn "disconnect|421 ", ctx->token, ctx->reqid);
1469 ce062d50 2019-08-21 martijn va_start(ap, reason);
1470 ce062d50 2019-08-21 martijn io_vprintf(io_stdout, reason, ap);
1471 ce062d50 2019-08-21 martijn va_end(ap);
1472 ce062d50 2019-08-21 martijn io_printf(io_stdout, "\n");
1473 ce062d50 2019-08-21 martijn }
1474 ce062d50 2019-08-21 martijn
1475 ce062d50 2019-08-21 martijn void
1476 4fb72612 2019-08-21 martijn osmtpd_filter_rewrite(struct osmtpd_ctx *ctx, const char *value, ...)
1477 4fb72612 2019-08-21 martijn {
1478 4fb72612 2019-08-21 martijn va_list ap;
1479 4fb72612 2019-08-21 martijn
1480 4fb72612 2019-08-21 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1481 4fb72612 2019-08-21 martijn "rewrite|", ctx->token, ctx->reqid);
1482 4fb72612 2019-08-21 martijn va_start(ap, value);
1483 4fb72612 2019-08-21 martijn io_vprintf(io_stdout, value, ap);
1484 4fb72612 2019-08-21 martijn va_end(ap);
1485 4fb72612 2019-08-21 martijn io_printf(io_stdout, "\n");
1486 4fb72612 2019-08-21 martijn }
1487 4fb72612 2019-08-21 martijn
1488 4fb72612 2019-08-21 martijn void
1489 ce062d50 2019-08-21 martijn osmtpd_filter_dataline(struct osmtpd_ctx *ctx, const char *line, ...)
1490 ce062d50 2019-08-21 martijn {
1491 ce062d50 2019-08-21 martijn va_list ap;
1492 ce062d50 2019-08-21 martijn
1493 ce062d50 2019-08-21 martijn io_printf(io_stdout, "filter-dataline|%016"PRIx64"|%016"PRIx64"|",
1494 ce062d50 2019-08-21 martijn ctx->token, ctx->reqid);
1495 ce062d50 2019-08-21 martijn va_start(ap, line);
1496 ce062d50 2019-08-21 martijn io_vprintf(io_stdout, line, ap);
1497 ce062d50 2019-08-21 martijn va_end(ap);
1498 ce062d50 2019-08-21 martijn io_printf(io_stdout, "\n");
1499 ce062d50 2019-08-21 martijn }
1500 ce062d50 2019-08-21 martijn
1501 ce062d50 2019-08-21 martijn static void
1502 ce062d50 2019-08-21 martijn osmtpd_register(enum osmtpd_type type, enum osmtpd_phase phase, int incoming,
1503 ce062d50 2019-08-21 martijn int storereport, void *cb)
1504 ce062d50 2019-08-21 martijn {
1505 ce062d50 2019-08-21 martijn size_t i;
1506 ce062d50 2019-08-21 martijn
1507 ce062d50 2019-08-21 martijn if (ready)
1508 ce062d50 2019-08-21 martijn errx(1, "Can't register when proc is running");
1509 ce062d50 2019-08-21 martijn
1510 ce062d50 2019-08-21 martijn for (i = 0; i < NITEMS(osmtpd_callbacks); i++) {
1511 ce062d50 2019-08-21 martijn if (type == osmtpd_callbacks[i].type &&
1512 ce062d50 2019-08-21 martijn phase == osmtpd_callbacks[i].phase &&
1513 ce062d50 2019-08-21 martijn incoming == osmtpd_callbacks[i].incoming) {
1514 ce062d50 2019-08-21 martijn if (osmtpd_callbacks[i].cb != NULL && cb != NULL)
1515 ce062d50 2019-08-21 martijn errx(1, "Event already registered");
1516 ce062d50 2019-08-21 martijn osmtpd_callbacks[i].cb = cb;
1517 ce062d50 2019-08-21 martijn osmtpd_callbacks[i].doregister = 1;
1518 ce062d50 2019-08-21 martijn if (storereport)
1519 ce062d50 2019-08-21 martijn osmtpd_callbacks[i].storereport = 1;
1520 ce062d50 2019-08-21 martijn return;
1521 ce062d50 2019-08-21 martijn }
1522 ce062d50 2019-08-21 martijn }
1523 ce062d50 2019-08-21 martijn /* NOT REACHED */
1524 ce062d50 2019-08-21 martijn errx(1, "Trying to register unknown event");
1525 ce062d50 2019-08-21 martijn }
1526 ce062d50 2019-08-21 martijn
1527 ce062d50 2019-08-21 martijn static enum osmtpd_phase
1528 ce062d50 2019-08-21 martijn osmtpd_strtophase(const char *phase, const char *linedup)
1529 ce062d50 2019-08-21 martijn {
1530 ce062d50 2019-08-21 martijn if (strcmp(phase, "connect") == 0)
1531 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_CONNECT;
1532 ce062d50 2019-08-21 martijn if (strcmp(phase, "helo") == 0)
1533 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_HELO;
1534 ce062d50 2019-08-21 martijn if (strcmp(phase, "ehlo") == 0)
1535 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_EHLO;
1536 ce062d50 2019-08-21 martijn if (strcmp(phase, "starttls") == 0)
1537 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_STARTTLS;
1538 ce062d50 2019-08-21 martijn if (strcmp(phase, "auth") == 0)
1539 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_AUTH;
1540 ce062d50 2019-08-21 martijn if (strcmp(phase, "mail-from") == 0)
1541 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_MAIL_FROM;
1542 ce062d50 2019-08-21 martijn if (strcmp(phase, "rcpt-to") == 0)
1543 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_RCPT_TO;
1544 ce062d50 2019-08-21 martijn if (strcmp(phase, "data") == 0)
1545 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_DATA;
1546 ce062d50 2019-08-21 martijn if (strcmp(phase, "data-line") == 0)
1547 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_DATA_LINE;
1548 ce062d50 2019-08-21 martijn if (strcmp(phase, "rset") == 0)
1549 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_RSET;
1550 ce062d50 2019-08-21 martijn if (strcmp(phase, "quit") == 0)
1551 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_QUIT;
1552 ce062d50 2019-08-21 martijn if (strcmp(phase, "noop") == 0)
1553 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_NOOP;
1554 ce062d50 2019-08-21 martijn if (strcmp(phase, "help") == 0)
1555 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_HELP;
1556 ce062d50 2019-08-21 martijn if (strcmp(phase, "wiz") == 0)
1557 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_WIZ;
1558 ce062d50 2019-08-21 martijn if (strcmp(phase, "commit") == 0)
1559 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_COMMIT;
1560 ce062d50 2019-08-21 martijn if (strcmp(phase, "link-connect") == 0)
1561 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_LINK_CONNECT;
1562 ce062d50 2019-08-21 martijn if (strcmp(phase, "link-disconnect") == 0)
1563 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_LINK_DISCONNECT;
1564 ce062d50 2019-08-21 martijn if (strcmp(phase, "link-identify") == 0)
1565 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_LINK_IDENTIFY;
1566 ce062d50 2019-08-21 martijn if (strcmp(phase, "link-tls") == 0)
1567 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_LINK_TLS;
1568 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-begin") == 0)
1569 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_BEGIN;
1570 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-mail") == 0)
1571 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_MAIL;
1572 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-rcpt") == 0)
1573 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_RCPT;
1574 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-envelope") == 0)
1575 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_ENVELOPE;
1576 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-data") == 0)
1577 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_DATA;
1578 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-commit") == 0)
1579 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_COMMIT;
1580 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-rollback") == 0)
1581 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_ROLLBACK;
1582 ce062d50 2019-08-21 martijn if (strcmp(phase, "protocol-client") == 0)
1583 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_PROTOCOL_CLIENT;
1584 ce062d50 2019-08-21 martijn if (strcmp(phase, "protocol-server") == 0)
1585 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_PROTOCOL_SERVER;
1586 ce062d50 2019-08-21 martijn if (strcmp(phase, "filter-response") == 0)
1587 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_FILTER_RESPONSE;
1588 ce062d50 2019-08-21 martijn if (strcmp(phase, "timeout") == 0)
1589 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TIMEOUT;
1590 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid phase: %s", linedup);
1591 ce062d50 2019-08-21 martijn }
1592 ce062d50 2019-08-21 martijn
1593 ce062d50 2019-08-21 martijn static const char *
1594 ce062d50 2019-08-21 martijn osmtpd_typetostr(enum osmtpd_type type)
1595 ce062d50 2019-08-21 martijn {
1596 ce062d50 2019-08-21 martijn switch (type) {
1597 ce062d50 2019-08-21 martijn case OSMTPD_TYPE_FILTER:
1598 ce062d50 2019-08-21 martijn return "filter";
1599 ce062d50 2019-08-21 martijn case OSMTPD_TYPE_REPORT:
1600 ce062d50 2019-08-21 martijn return "report";
1601 ce062d50 2019-08-21 martijn }
1602 ce062d50 2019-08-21 martijn errx(1, "In valid type: %d\n", type);
1603 ce062d50 2019-08-21 martijn }
1604 ce062d50 2019-08-21 martijn
1605 ce062d50 2019-08-21 martijn static const char *
1606 ce062d50 2019-08-21 martijn osmtpd_phasetostr(enum osmtpd_phase phase)
1607 ce062d50 2019-08-21 martijn {
1608 ce062d50 2019-08-21 martijn switch (phase) {
1609 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_CONNECT:
1610 ce062d50 2019-08-21 martijn return "connect";
1611 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_HELO:
1612 ce062d50 2019-08-21 martijn return "helo";
1613 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_EHLO:
1614 ce062d50 2019-08-21 martijn return "ehlo";
1615 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_STARTTLS:
1616 ce062d50 2019-08-21 martijn return "starttls";
1617 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_AUTH:
1618 ce062d50 2019-08-21 martijn return "auth";
1619 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_MAIL_FROM:
1620 ce062d50 2019-08-21 martijn return "mail-from";
1621 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_RCPT_TO:
1622 ce062d50 2019-08-21 martijn return "rcpt-to";
1623 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_DATA:
1624 ce062d50 2019-08-21 martijn return "data";
1625 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_DATA_LINE:
1626 ce062d50 2019-08-21 martijn return "data-line";
1627 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_RSET:
1628 ce062d50 2019-08-21 martijn return "rset";
1629 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_QUIT:
1630 ce062d50 2019-08-21 martijn return "quit";
1631 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_NOOP:
1632 ce062d50 2019-08-21 martijn return "noop";
1633 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_HELP:
1634 ce062d50 2019-08-21 martijn return "help";
1635 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_WIZ:
1636 ce062d50 2019-08-21 martijn return "wiz";
1637 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_COMMIT:
1638 ce062d50 2019-08-21 martijn return "commit";
1639 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_LINK_CONNECT:
1640 ce062d50 2019-08-21 martijn return "link-connect";
1641 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_LINK_DISCONNECT:
1642 ce062d50 2019-08-21 martijn return "link-disconnect";
1643 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_LINK_IDENTIFY:
1644 ce062d50 2019-08-21 martijn return "link-identify";
1645 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_LINK_TLS:
1646 ce062d50 2019-08-21 martijn return "link-tls";
1647 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_BEGIN:
1648 ce062d50 2019-08-21 martijn return "tx-begin";
1649 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_MAIL:
1650 ce062d50 2019-08-21 martijn return "tx-mail";
1651 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_RCPT:
1652 ce062d50 2019-08-21 martijn return "tx-rcpt";
1653 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_ENVELOPE:
1654 ce062d50 2019-08-21 martijn return "tx-envelope";
1655 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_DATA:
1656 ce062d50 2019-08-21 martijn return "tx-data";
1657 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_COMMIT:
1658 ce062d50 2019-08-21 martijn return "tx-commit";
1659 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_ROLLBACK:
1660 ce062d50 2019-08-21 martijn return "tx-rollback";
1661 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_PROTOCOL_CLIENT:
1662 ce062d50 2019-08-21 martijn return "protocol-client";
1663 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_PROTOCOL_SERVER:
1664 ce062d50 2019-08-21 martijn return "protocol-server";
1665 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_FILTER_RESPONSE:
1666 ce062d50 2019-08-21 martijn return "filter-response";
1667 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TIMEOUT:
1668 ce062d50 2019-08-21 martijn return "timeout";
1669 ce062d50 2019-08-21 martijn }
1670 ce062d50 2019-08-21 martijn errx(1, "In valid phase: %d\n", phase);
1671 ce062d50 2019-08-21 martijn }
1672 ce062d50 2019-08-21 martijn
1673 ce062d50 2019-08-21 martijn static enum
1674 ce062d50 2019-08-21 martijn osmtpd_status osmtpd_strtostatus(const char *status, char *linedup)
1675 ce062d50 2019-08-21 martijn {
1676 ce062d50 2019-08-21 martijn if (strcmp(status, "ok") == 0)
1677 ce062d50 2019-08-21 martijn return OSMTPD_STATUS_OK;
1678 ce062d50 2019-08-21 martijn else if (strcmp(status, "tempfail") == 0)
1679 ce062d50 2019-08-21 martijn return OSMTPD_STATUS_TEMPFAIL;
1680 ce062d50 2019-08-21 martijn else if (strcmp(status, "permfail") == 0)
1681 ce062d50 2019-08-21 martijn return OSMTPD_STATUS_PERMFAIL;
1682 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid status: %s\n", linedup);
1683 ce062d50 2019-08-21 martijn }
1684 ce062d50 2019-08-21 martijn
1685 ce062d50 2019-08-21 martijn static void
1686 ce062d50 2019-08-21 martijn osmtpd_addrtoss(char *addr, struct sockaddr_storage *ss, int hasport,
1687 ce062d50 2019-08-21 martijn char *linedup)
1688 ce062d50 2019-08-21 martijn {
1689 ce062d50 2019-08-21 martijn char *port;
1690 ce062d50 2019-08-21 martijn const char *errstr = NULL;
1691 ce062d50 2019-08-21 martijn struct sockaddr_in *sin;
1692 ce062d50 2019-08-21 martijn struct sockaddr_in6 *sin6;
1693 ce062d50 2019-08-21 martijn struct sockaddr_un *sun;
1694 ce062d50 2019-08-21 martijn
1695 ce062d50 2019-08-21 martijn if (strncasecmp(addr, "ipv6:", 5) == 0) {
1696 ce062d50 2019-08-21 martijn sin6 = (struct sockaddr_in6 *)ss;
1697 ce062d50 2019-08-21 martijn sin6->sin6_len = sizeof(*sin6);
1698 ce062d50 2019-08-21 martijn sin6->sin6_family = AF_INET6;
1699 ce062d50 2019-08-21 martijn sin6->sin6_port = 0;
1700 ce062d50 2019-08-21 martijn if (hasport) {
1701 ce062d50 2019-08-21 martijn if ((port = strrchr(addr, ':')) == NULL)
1702 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid "
1703 ce062d50 2019-08-21 martijn "address (%s): %s", addr, linedup);
1704 ce062d50 2019-08-21 martijn port++;
1705 ce062d50 2019-08-21 martijn sin6->sin6_port = htons(strtonum(port, 0, UINT16_MAX,
1706 ce062d50 2019-08-21 martijn &errstr));
1707 ce062d50 2019-08-21 martijn if (errstr != NULL)
1708 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid "
1709 ce062d50 2019-08-21 martijn "address (%s): %s", addr, linedup);
1710 ce062d50 2019-08-21 martijn port[-1] = '\0';
1711 ce062d50 2019-08-21 martijn }
1712 ce062d50 2019-08-21 martijn switch (inet_pton(AF_INET6, addr + 5, &(sin6->sin6_addr))) {
1713 ce062d50 2019-08-21 martijn case 1:
1714 ce062d50 2019-08-21 martijn break;
1715 ce062d50 2019-08-21 martijn case 0:
1716 ce062d50 2019-08-21 martijn port[-1] = ':';
1717 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid address "
1718 ce062d50 2019-08-21 martijn "(%s): %s", addr, linedup);
1719 ce062d50 2019-08-21 martijn default:
1720 ce062d50 2019-08-21 martijn port[-1] = ':';
1721 ce062d50 2019-08-21 martijn err(1, "Can't parse address (%s): %s", addr, linedup);
1722 ce062d50 2019-08-21 martijn }
1723 ce062d50 2019-08-21 martijn } else if (strncasecmp(addr, "unix:", 5) == 0) {
1724 ce062d50 2019-08-21 martijn sun = (struct sockaddr_un *)ss;
1725 ce062d50 2019-08-21 martijn sun->sun_len = sizeof(*sun);
1726 ce062d50 2019-08-21 martijn sun->sun_family = AF_UNIX;
1727 ce062d50 2019-08-21 martijn if (strlcpy(sun->sun_path, addr,
1728 ce062d50 2019-08-21 martijn sizeof(sun->sun_path)) >= sizeof(sun->sun_path)) {
1729 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: address too long (%s): "
1730 ce062d50 2019-08-21 martijn "%s", addr, linedup);
1731 ce062d50 2019-08-21 martijn }
1732 ce062d50 2019-08-21 martijn } else {
1733 ce062d50 2019-08-21 martijn sin = (struct sockaddr_in *)ss;
1734 ce062d50 2019-08-21 martijn sin->sin_len = sizeof(*sin);
1735 ce062d50 2019-08-21 martijn sin->sin_family = AF_INET;
1736 ce062d50 2019-08-21 martijn sin->sin_port = 0;
1737 ce062d50 2019-08-21 martijn if (hasport) {
1738 ce062d50 2019-08-21 martijn if ((port = strrchr(addr, ':')) == NULL)
1739 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid "
1740 ce062d50 2019-08-21 martijn "address (%s): %s", addr, linedup);
1741 ce062d50 2019-08-21 martijn port++;
1742 ce062d50 2019-08-21 martijn sin->sin_port = htons(strtonum(port, 0, UINT16_MAX,
1743 ce062d50 2019-08-21 martijn &errstr));
1744 ce062d50 2019-08-21 martijn if (errstr != NULL)
1745 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid "
1746 ce062d50 2019-08-21 martijn "address (%s): %s", addr, linedup);
1747 ce062d50 2019-08-21 martijn port[-1] = '\0';
1748 ce062d50 2019-08-21 martijn }
1749 ce062d50 2019-08-21 martijn switch (inet_pton(AF_INET, addr, &(sin->sin_addr))) {
1750 ce062d50 2019-08-21 martijn case 1:
1751 ce062d50 2019-08-21 martijn break;
1752 ce062d50 2019-08-21 martijn case 0:
1753 ce062d50 2019-08-21 martijn port[-1] = ':';
1754 ce062d50 2019-08-21 martijn errx(1, "Invalid line received: invalid address "
1755 ce062d50 2019-08-21 martijn "(%s): %s", addr, linedup);
1756 ce062d50 2019-08-21 martijn default:
1757 ce062d50 2019-08-21 martijn port[-1] = ':';
1758 ce062d50 2019-08-21 martijn err(1, "Can't parse address (%s): %s", addr, linedup);
1759 ce062d50 2019-08-21 martijn }
1760 ce062d50 2019-08-21 martijn }
1761 ce062d50 2019-08-21 martijn }
1762 ce062d50 2019-08-21 martijn
1763 ce062d50 2019-08-21 martijn static int
1764 ce062d50 2019-08-21 martijn osmtpd_session_cmp(struct osmtpd_session *a, struct osmtpd_session *b)
1765 ce062d50 2019-08-21 martijn {
1766 ce062d50 2019-08-21 martijn return a->ctx.reqid < b->ctx.reqid ? -1 : a->ctx.reqid > b->ctx.reqid;
1767 ce062d50 2019-08-21 martijn }
1768 ce062d50 2019-08-21 martijn
1769 9e3e8410 2019-08-22 martijn RB_GENERATE_STATIC(osmtpd_sessions, osmtpd_session, entry, osmtpd_session_cmp);