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 957c2372 2019-11-14 martijn #define _GNU_SOURCE 1
17 957c2372 2019-11-14 martijn
18 ce062d50 2019-08-21 martijn #include <sys/time.h>
19 ce062d50 2019-08-21 martijn #include <sys/tree.h>
20 ce062d50 2019-08-21 martijn #include <sys/socket.h>
21 ce062d50 2019-08-21 martijn #include <sys/un.h>
22 ce062d50 2019-08-21 martijn
23 ce062d50 2019-08-21 martijn #include <arpa/inet.h>
24 078ff8cf 2019-08-21 martijn #include <netinet/in.h>
25 078ff8cf 2019-08-21 martijn
26 ce062d50 2019-08-21 martijn #include <errno.h>
27 ce062d50 2019-08-21 martijn #include <event.h>
28 ce062d50 2019-08-21 martijn #include <fcntl.h>
29 ce062d50 2019-08-21 martijn #include <inttypes.h>
30 ce062d50 2019-08-21 martijn #include <limits.h>
31 ce062d50 2019-08-21 martijn #include <stdarg.h>
32 ce062d50 2019-08-21 martijn #include <stdio.h>
33 ce062d50 2019-08-21 martijn #include <stdlib.h>
34 ce062d50 2019-08-21 martijn #include <string.h>
35 ce062d50 2019-08-21 martijn #include <syslog.h>
36 ce062d50 2019-08-21 martijn #include <unistd.h>
37 ce062d50 2019-08-21 martijn
38 957c2372 2019-11-14 martijn #include "openbsd-compat.h"
39 ce062d50 2019-08-21 martijn #include "opensmtpd.h"
40 ce062d50 2019-08-21 martijn #include "ioev.h"
41 ce062d50 2019-08-21 martijn
42 ce062d50 2019-08-21 martijn #define NITEMS(x) (sizeof(x) / sizeof(*x))
43 ce062d50 2019-08-21 martijn
44 d229c123 2019-08-22 martijn struct osmtpd_callback {
45 d229c123 2019-08-22 martijn enum osmtpd_type type;
46 d229c123 2019-08-22 martijn enum osmtpd_phase phase;
47 d229c123 2019-08-22 martijn int incoming;
48 d229c123 2019-08-22 martijn void (*osmtpd_cb)(struct osmtpd_callback *, struct osmtpd_ctx *, char *,
49 d229c123 2019-08-22 martijn char *);
50 d229c123 2019-08-22 martijn void *cb;
51 d229c123 2019-08-22 martijn int doregister;
52 d229c123 2019-08-22 martijn int storereport;
53 d229c123 2019-08-22 martijn };
54 d229c123 2019-08-22 martijn
55 d229c123 2019-08-22 martijn struct osmtpd_session {
56 d229c123 2019-08-22 martijn struct osmtpd_ctx ctx;
57 d229c123 2019-08-22 martijn RB_ENTRY(osmtpd_session) entry;
58 d229c123 2019-08-22 martijn };
59 d229c123 2019-08-22 martijn
60 d229c123 2019-08-22 martijn static void osmtpd_register(enum osmtpd_type, enum osmtpd_phase, int, int,
61 d229c123 2019-08-22 martijn void *);
62 d229c123 2019-08-22 martijn static const char *osmtpd_typetostr(enum osmtpd_type);
63 d229c123 2019-08-22 martijn static const char *osmtpd_phasetostr(enum osmtpd_phase);
64 d229c123 2019-08-22 martijn static enum osmtpd_phase osmtpd_strtophase(const char *, const char *);
65 d229c123 2019-08-22 martijn static void osmtpd_newline(struct io *, int, void *);
66 d229c123 2019-08-22 martijn static void osmtpd_outevt(struct io *, int, void *);
67 d229c123 2019-08-22 martijn static void osmtpd_noargs(struct osmtpd_callback *, struct osmtpd_ctx *,
68 d229c123 2019-08-22 martijn char *, char *);
69 d229c123 2019-08-22 martijn static void osmtpd_onearg(struct osmtpd_callback *, struct osmtpd_ctx *,
70 d229c123 2019-08-22 martijn char *, char *);
71 d229c123 2019-08-22 martijn static void osmtpd_connect(struct osmtpd_callback *, struct osmtpd_ctx *,
72 d229c123 2019-08-22 martijn char *, char *);
73 421c9a86 2019-09-06 martijn static void osmtpd_identify(struct osmtpd_callback *, struct osmtpd_ctx *,
74 421c9a86 2019-09-06 martijn char *, char *);
75 d229c123 2019-08-22 martijn static void osmtpd_link_connect(struct osmtpd_callback *, struct osmtpd_ctx *,
76 d229c123 2019-08-22 martijn char *, char *);
77 d229c123 2019-08-22 martijn static void osmtpd_link_disconnect(struct osmtpd_callback *,
78 d229c123 2019-08-22 martijn struct osmtpd_ctx *, char *, char *);
79 a05d5c54 2019-08-28 martijn static void osmtpd_link_greeting(struct osmtpd_callback *, struct osmtpd_ctx *,
80 a05d5c54 2019-08-28 martijn char *, char *);
81 d229c123 2019-08-22 martijn static void osmtpd_link_identify(struct osmtpd_callback *, struct osmtpd_ctx *,
82 d229c123 2019-08-22 martijn char *, char *);
83 d229c123 2019-08-22 martijn static void osmtpd_link_tls(struct osmtpd_callback *, struct osmtpd_ctx *,
84 d229c123 2019-08-22 martijn char *, char *);
85 58a6bc69 2022-12-05 martijn static void osmtpd_link_auth(struct osmtpd_callback *, struct osmtpd_ctx *,
86 58a6bc69 2022-12-05 martijn char *, char *);
87 d229c123 2019-08-22 martijn static void osmtpd_tx_begin(struct osmtpd_callback *, struct osmtpd_ctx *,
88 d229c123 2019-08-22 martijn char *, char *);
89 d229c123 2019-08-22 martijn static void osmtpd_tx_mail(struct osmtpd_callback *, struct osmtpd_ctx *,
90 d229c123 2019-08-22 martijn char *, char *);
91 d229c123 2019-08-22 martijn static void osmtpd_tx_rcpt(struct osmtpd_callback *, struct osmtpd_ctx *,
92 d229c123 2019-08-22 martijn char *, char *);
93 d229c123 2019-08-22 martijn static void osmtpd_tx_envelope(struct osmtpd_callback *, struct osmtpd_ctx *,
94 d229c123 2019-08-22 martijn char *, char *);
95 d229c123 2019-08-22 martijn static void osmtpd_tx_data(struct osmtpd_callback *, struct osmtpd_ctx *,
96 d229c123 2019-08-22 martijn char *, char *);
97 d229c123 2019-08-22 martijn static void osmtpd_tx_commit(struct osmtpd_callback *, struct osmtpd_ctx *,
98 d229c123 2019-08-22 martijn char *, char *);
99 d229c123 2019-08-22 martijn static void osmtpd_tx_rollback(struct osmtpd_callback *, struct osmtpd_ctx *,
100 d229c123 2019-08-22 martijn char *, char *);
101 d229c123 2019-08-22 martijn static void osmtpd_addrtoss(char *, struct sockaddr_storage *, int, char *);
102 d229c123 2019-08-22 martijn static enum osmtpd_status osmtpd_strtostatus(const char *, char *);
103 d229c123 2019-08-22 martijn static int osmtpd_session_cmp(struct osmtpd_session *, struct osmtpd_session *);
104 912d0ff2 2019-08-22 martijn static void *(*oncreatecb_session)(struct osmtpd_ctx *) = NULL;
105 912d0ff2 2019-08-22 martijn static void (*ondeletecb_session)(struct osmtpd_ctx *, void *) = NULL;
106 912d0ff2 2019-08-22 martijn static void *(*oncreatecb_message)(struct osmtpd_ctx *) = NULL;
107 912d0ff2 2019-08-22 martijn static void (*ondeletecb_message)(struct osmtpd_ctx *, void *) = NULL;
108 2029083f 2020-10-15 martijn static void (*conf_cb)(const char *, const char *);
109 d229c123 2019-08-22 martijn
110 d229c123 2019-08-22 martijn static struct osmtpd_callback osmtpd_callbacks[] = {
111 d229c123 2019-08-22 martijn {
112 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
113 d229c123 2019-08-22 martijn OSMTPD_PHASE_CONNECT,
114 d229c123 2019-08-22 martijn 1,
115 d229c123 2019-08-22 martijn osmtpd_connect,
116 d229c123 2019-08-22 martijn NULL,
117 d229c123 2019-08-22 martijn 0,
118 d229c123 2019-08-22 martijn 0
119 d229c123 2019-08-22 martijn },
120 d229c123 2019-08-22 martijn {
121 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
122 d229c123 2019-08-22 martijn OSMTPD_PHASE_HELO,
123 d229c123 2019-08-22 martijn 1,
124 421c9a86 2019-09-06 martijn osmtpd_identify,
125 d229c123 2019-08-22 martijn NULL,
126 d229c123 2019-08-22 martijn 0,
127 d229c123 2019-08-22 martijn 0
128 d229c123 2019-08-22 martijn },
129 d229c123 2019-08-22 martijn {
130 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
131 d229c123 2019-08-22 martijn OSMTPD_PHASE_EHLO,
132 d229c123 2019-08-22 martijn 1,
133 421c9a86 2019-09-06 martijn osmtpd_identify,
134 d229c123 2019-08-22 martijn NULL,
135 d229c123 2019-08-22 martijn 0,
136 d229c123 2019-08-22 martijn 0
137 d229c123 2019-08-22 martijn },
138 d229c123 2019-08-22 martijn {
139 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
140 d229c123 2019-08-22 martijn OSMTPD_PHASE_STARTTLS,
141 d229c123 2019-08-22 martijn 1,
142 d229c123 2019-08-22 martijn osmtpd_noargs,
143 d229c123 2019-08-22 martijn NULL,
144 d229c123 2019-08-22 martijn 0,
145 d229c123 2019-08-22 martijn 0
146 d229c123 2019-08-22 martijn },
147 d229c123 2019-08-22 martijn {
148 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
149 d229c123 2019-08-22 martijn OSMTPD_PHASE_AUTH,
150 d229c123 2019-08-22 martijn 1,
151 d229c123 2019-08-22 martijn osmtpd_onearg,
152 d229c123 2019-08-22 martijn NULL,
153 d229c123 2019-08-22 martijn 0,
154 d229c123 2019-08-22 martijn 0
155 d229c123 2019-08-22 martijn },
156 d229c123 2019-08-22 martijn {
157 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
158 d229c123 2019-08-22 martijn OSMTPD_PHASE_MAIL_FROM,
159 d229c123 2019-08-22 martijn 1,
160 d229c123 2019-08-22 martijn osmtpd_onearg,
161 d229c123 2019-08-22 martijn NULL,
162 d229c123 2019-08-22 martijn 0,
163 d229c123 2019-08-22 martijn 0
164 d229c123 2019-08-22 martijn },
165 d229c123 2019-08-22 martijn {
166 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
167 d229c123 2019-08-22 martijn OSMTPD_PHASE_RCPT_TO,
168 d229c123 2019-08-22 martijn 1,
169 d229c123 2019-08-22 martijn osmtpd_onearg,
170 d229c123 2019-08-22 martijn NULL,
171 d229c123 2019-08-22 martijn 0,
172 d229c123 2019-08-22 martijn 0
173 d229c123 2019-08-22 martijn },
174 d229c123 2019-08-22 martijn {
175 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
176 d229c123 2019-08-22 martijn OSMTPD_PHASE_DATA,
177 d229c123 2019-08-22 martijn 1,
178 d229c123 2019-08-22 martijn osmtpd_noargs,
179 d229c123 2019-08-22 martijn NULL,
180 d229c123 2019-08-22 martijn 0,
181 d229c123 2019-08-22 martijn 0
182 d229c123 2019-08-22 martijn },
183 d229c123 2019-08-22 martijn {
184 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
185 d229c123 2019-08-22 martijn OSMTPD_PHASE_DATA_LINE,
186 d229c123 2019-08-22 martijn 1,
187 d229c123 2019-08-22 martijn osmtpd_onearg,
188 d229c123 2019-08-22 martijn NULL,
189 d229c123 2019-08-22 martijn 0,
190 d229c123 2019-08-22 martijn 0
191 d229c123 2019-08-22 martijn },
192 d229c123 2019-08-22 martijn {
193 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
194 d229c123 2019-08-22 martijn OSMTPD_PHASE_RSET,
195 d229c123 2019-08-22 martijn 1,
196 d229c123 2019-08-22 martijn osmtpd_noargs,
197 d229c123 2019-08-22 martijn NULL,
198 d229c123 2019-08-22 martijn 0,
199 d229c123 2019-08-22 martijn 0
200 d229c123 2019-08-22 martijn },
201 d229c123 2019-08-22 martijn {
202 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
203 d229c123 2019-08-22 martijn OSMTPD_PHASE_QUIT,
204 d229c123 2019-08-22 martijn 1,
205 d229c123 2019-08-22 martijn osmtpd_noargs,
206 d229c123 2019-08-22 martijn NULL,
207 d229c123 2019-08-22 martijn 0,
208 d229c123 2019-08-22 martijn 0
209 d229c123 2019-08-22 martijn },
210 d229c123 2019-08-22 martijn {
211 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
212 d229c123 2019-08-22 martijn OSMTPD_PHASE_NOOP,
213 d229c123 2019-08-22 martijn 1,
214 d229c123 2019-08-22 martijn osmtpd_noargs,
215 d229c123 2019-08-22 martijn NULL,
216 d229c123 2019-08-22 martijn 0,
217 d229c123 2019-08-22 martijn 0
218 d229c123 2019-08-22 martijn },
219 d229c123 2019-08-22 martijn {
220 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
221 d229c123 2019-08-22 martijn OSMTPD_PHASE_HELP,
222 d229c123 2019-08-22 martijn 1,
223 d229c123 2019-08-22 martijn osmtpd_noargs,
224 d229c123 2019-08-22 martijn NULL,
225 d229c123 2019-08-22 martijn 0,
226 d229c123 2019-08-22 martijn 0
227 d229c123 2019-08-22 martijn },
228 d229c123 2019-08-22 martijn {
229 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
230 d229c123 2019-08-22 martijn OSMTPD_PHASE_WIZ,
231 d229c123 2019-08-22 martijn 1,
232 d229c123 2019-08-22 martijn osmtpd_noargs,
233 d229c123 2019-08-22 martijn NULL,
234 d229c123 2019-08-22 martijn 0,
235 d229c123 2019-08-22 martijn 0
236 d229c123 2019-08-22 martijn },
237 d229c123 2019-08-22 martijn {
238 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
239 d229c123 2019-08-22 martijn OSMTPD_PHASE_COMMIT,
240 d229c123 2019-08-22 martijn 1,
241 d229c123 2019-08-22 martijn osmtpd_noargs,
242 d229c123 2019-08-22 martijn NULL,
243 d229c123 2019-08-22 martijn 0,
244 d229c123 2019-08-22 martijn 0
245 d229c123 2019-08-22 martijn },
246 d229c123 2019-08-22 martijn {
247 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
248 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_CONNECT,
249 d229c123 2019-08-22 martijn 1,
250 d229c123 2019-08-22 martijn osmtpd_link_connect,
251 d229c123 2019-08-22 martijn NULL,
252 d229c123 2019-08-22 martijn 0,
253 d229c123 2019-08-22 martijn 0
254 d229c123 2019-08-22 martijn },
255 d229c123 2019-08-22 martijn {
256 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
257 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_DISCONNECT,
258 d229c123 2019-08-22 martijn 1,
259 d229c123 2019-08-22 martijn osmtpd_link_disconnect,
260 d229c123 2019-08-22 martijn NULL,
261 d229c123 2019-08-22 martijn 0,
262 d229c123 2019-08-22 martijn 0
263 d229c123 2019-08-22 martijn },
264 d229c123 2019-08-22 martijn {
265 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
266 a05d5c54 2019-08-28 martijn OSMTPD_PHASE_LINK_GREETING,
267 a05d5c54 2019-08-28 martijn 1,
268 a05d5c54 2019-08-28 martijn osmtpd_link_greeting,
269 a05d5c54 2019-08-28 martijn NULL,
270 a05d5c54 2019-08-28 martijn 0,
271 a05d5c54 2019-08-28 martijn 0
272 a05d5c54 2019-08-28 martijn },
273 a05d5c54 2019-08-28 martijn {
274 a05d5c54 2019-08-28 martijn OSMTPD_TYPE_REPORT,
275 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_IDENTIFY,
276 d229c123 2019-08-22 martijn 1,
277 d229c123 2019-08-22 martijn osmtpd_link_identify,
278 d229c123 2019-08-22 martijn NULL,
279 d229c123 2019-08-22 martijn 0,
280 d229c123 2019-08-22 martijn 0
281 d229c123 2019-08-22 martijn },
282 d229c123 2019-08-22 martijn {
283 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
284 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_TLS,
285 d229c123 2019-08-22 martijn 1,
286 d229c123 2019-08-22 martijn osmtpd_link_tls,
287 d229c123 2019-08-22 martijn NULL,
288 d229c123 2019-08-22 martijn 0,
289 d229c123 2019-08-22 martijn 0
290 d229c123 2019-08-22 martijn },
291 d229c123 2019-08-22 martijn {
292 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
293 58a6bc69 2022-12-05 martijn OSMTPD_PHASE_LINK_AUTH,
294 58a6bc69 2022-12-05 martijn 1,
295 58a6bc69 2022-12-05 martijn osmtpd_link_auth,
296 58a6bc69 2022-12-05 martijn NULL,
297 58a6bc69 2022-12-05 martijn 0,
298 58a6bc69 2022-12-05 martijn 0
299 58a6bc69 2022-12-05 martijn },
300 58a6bc69 2022-12-05 martijn {
301 58a6bc69 2022-12-05 martijn OSMTPD_TYPE_REPORT,
302 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_BEGIN,
303 d229c123 2019-08-22 martijn 1,
304 d229c123 2019-08-22 martijn osmtpd_tx_begin,
305 d229c123 2019-08-22 martijn NULL,
306 d229c123 2019-08-22 martijn 0,
307 d229c123 2019-08-22 martijn 0
308 d229c123 2019-08-22 martijn },
309 d229c123 2019-08-22 martijn {
310 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
311 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_MAIL,
312 d229c123 2019-08-22 martijn 1,
313 d229c123 2019-08-22 martijn osmtpd_tx_mail,
314 d229c123 2019-08-22 martijn NULL,
315 d229c123 2019-08-22 martijn 0,
316 d229c123 2019-08-22 martijn 0
317 d229c123 2019-08-22 martijn },
318 d229c123 2019-08-22 martijn {
319 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
320 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_RCPT,
321 d229c123 2019-08-22 martijn 1,
322 d229c123 2019-08-22 martijn osmtpd_tx_rcpt,
323 d229c123 2019-08-22 martijn NULL,
324 d229c123 2019-08-22 martijn 0,
325 d229c123 2019-08-22 martijn 0
326 d229c123 2019-08-22 martijn },
327 d229c123 2019-08-22 martijn {
328 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
329 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_ENVELOPE,
330 d229c123 2019-08-22 martijn 1,
331 d229c123 2019-08-22 martijn osmtpd_tx_envelope,
332 d229c123 2019-08-22 martijn NULL,
333 d229c123 2019-08-22 martijn 0,
334 d229c123 2019-08-22 martijn 0
335 d229c123 2019-08-22 martijn },
336 d229c123 2019-08-22 martijn {
337 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
338 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_DATA,
339 d229c123 2019-08-22 martijn 1,
340 d229c123 2019-08-22 martijn osmtpd_tx_data,
341 d229c123 2019-08-22 martijn NULL,
342 d229c123 2019-08-22 martijn 0,
343 d229c123 2019-08-22 martijn 0
344 d229c123 2019-08-22 martijn },
345 d229c123 2019-08-22 martijn {
346 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
347 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_COMMIT,
348 d229c123 2019-08-22 martijn 1,
349 d229c123 2019-08-22 martijn osmtpd_tx_commit,
350 d229c123 2019-08-22 martijn NULL,
351 d229c123 2019-08-22 martijn 0,
352 d229c123 2019-08-22 martijn 0
353 d229c123 2019-08-22 martijn },
354 d229c123 2019-08-22 martijn {
355 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
356 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_ROLLBACK,
357 d229c123 2019-08-22 martijn 1,
358 d229c123 2019-08-22 martijn osmtpd_tx_rollback,
359 d229c123 2019-08-22 martijn NULL,
360 d229c123 2019-08-22 martijn 0,
361 d229c123 2019-08-22 martijn 0
362 d229c123 2019-08-22 martijn },
363 d229c123 2019-08-22 martijn {
364 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
365 d229c123 2019-08-22 martijn OSMTPD_PHASE_PROTOCOL_CLIENT,
366 d229c123 2019-08-22 martijn 1,
367 d229c123 2019-08-22 martijn osmtpd_onearg,
368 d229c123 2019-08-22 martijn NULL,
369 d229c123 2019-08-22 martijn 0,
370 d229c123 2019-08-22 martijn 0
371 d229c123 2019-08-22 martijn },
372 d229c123 2019-08-22 martijn {
373 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
374 d229c123 2019-08-22 martijn OSMTPD_PHASE_PROTOCOL_SERVER,
375 d229c123 2019-08-22 martijn 1,
376 d229c123 2019-08-22 martijn osmtpd_onearg,
377 d229c123 2019-08-22 martijn NULL,
378 d229c123 2019-08-22 martijn 0,
379 d229c123 2019-08-22 martijn 0
380 d229c123 2019-08-22 martijn },
381 d229c123 2019-08-22 martijn {
382 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
383 d229c123 2019-08-22 martijn OSMTPD_PHASE_FILTER_RESPONSE,
384 d229c123 2019-08-22 martijn 1,
385 d229c123 2019-08-22 martijn osmtpd_onearg,
386 d229c123 2019-08-22 martijn NULL,
387 d229c123 2019-08-22 martijn 0,
388 d229c123 2019-08-22 martijn 0
389 d229c123 2019-08-22 martijn },
390 d229c123 2019-08-22 martijn {
391 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
392 d229c123 2019-08-22 martijn OSMTPD_PHASE_TIMEOUT,
393 d229c123 2019-08-22 martijn 1,
394 d229c123 2019-08-22 martijn osmtpd_noargs,
395 d229c123 2019-08-22 martijn NULL,
396 d229c123 2019-08-22 martijn 0,
397 d229c123 2019-08-22 martijn 0
398 d229c123 2019-08-22 martijn },
399 d229c123 2019-08-22 martijn {
400 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
401 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_CONNECT,
402 d229c123 2019-08-22 martijn 0,
403 d229c123 2019-08-22 martijn osmtpd_link_connect,
404 d229c123 2019-08-22 martijn NULL,
405 d229c123 2019-08-22 martijn 0,
406 d229c123 2019-08-22 martijn 0
407 d229c123 2019-08-22 martijn },
408 d229c123 2019-08-22 martijn {
409 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
410 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_DISCONNECT,
411 d229c123 2019-08-22 martijn 0,
412 d229c123 2019-08-22 martijn osmtpd_link_disconnect,
413 d229c123 2019-08-22 martijn NULL,
414 d229c123 2019-08-22 martijn 0,
415 d229c123 2019-08-22 martijn 0
416 d229c123 2019-08-22 martijn },
417 d229c123 2019-08-22 martijn {
418 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
419 a05d5c54 2019-08-28 martijn OSMTPD_PHASE_LINK_GREETING,
420 a05d5c54 2019-08-28 martijn 0,
421 a05d5c54 2019-08-28 martijn osmtpd_link_greeting,
422 a05d5c54 2019-08-28 martijn NULL,
423 a05d5c54 2019-08-28 martijn 0,
424 a05d5c54 2019-08-28 martijn 0
425 a05d5c54 2019-08-28 martijn },
426 a05d5c54 2019-08-28 martijn {
427 a05d5c54 2019-08-28 martijn OSMTPD_TYPE_REPORT,
428 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_IDENTIFY,
429 d229c123 2019-08-22 martijn 0,
430 d229c123 2019-08-22 martijn osmtpd_link_identify,
431 d229c123 2019-08-22 martijn NULL,
432 d229c123 2019-08-22 martijn 0,
433 d229c123 2019-08-22 martijn 0
434 d229c123 2019-08-22 martijn },
435 d229c123 2019-08-22 martijn {
436 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
437 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_TLS,
438 d229c123 2019-08-22 martijn 0,
439 d229c123 2019-08-22 martijn osmtpd_link_tls,
440 d229c123 2019-08-22 martijn NULL,
441 d229c123 2019-08-22 martijn 0,
442 d229c123 2019-08-22 martijn 0
443 d229c123 2019-08-22 martijn },
444 d229c123 2019-08-22 martijn {
445 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
446 58a6bc69 2022-12-05 martijn OSMTPD_PHASE_LINK_AUTH,
447 58a6bc69 2022-12-05 martijn 0,
448 58a6bc69 2022-12-05 martijn osmtpd_link_auth,
449 58a6bc69 2022-12-05 martijn NULL,
450 58a6bc69 2022-12-05 martijn 0,
451 58a6bc69 2022-12-05 martijn 0
452 58a6bc69 2022-12-05 martijn },
453 58a6bc69 2022-12-05 martijn {
454 58a6bc69 2022-12-05 martijn OSMTPD_TYPE_REPORT,
455 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_BEGIN,
456 d229c123 2019-08-22 martijn 0,
457 d229c123 2019-08-22 martijn osmtpd_tx_begin,
458 d229c123 2019-08-22 martijn NULL,
459 d229c123 2019-08-22 martijn 0,
460 d229c123 2019-08-22 martijn 0
461 d229c123 2019-08-22 martijn },
462 d229c123 2019-08-22 martijn {
463 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
464 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_MAIL,
465 d229c123 2019-08-22 martijn 0,
466 d229c123 2019-08-22 martijn osmtpd_tx_mail,
467 d229c123 2019-08-22 martijn NULL,
468 d229c123 2019-08-22 martijn 0,
469 d229c123 2019-08-22 martijn 0
470 d229c123 2019-08-22 martijn },
471 d229c123 2019-08-22 martijn {
472 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
473 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_RCPT,
474 d229c123 2019-08-22 martijn 0,
475 d229c123 2019-08-22 martijn osmtpd_tx_rcpt,
476 d229c123 2019-08-22 martijn NULL,
477 d229c123 2019-08-22 martijn 0,
478 d229c123 2019-08-22 martijn 0
479 d229c123 2019-08-22 martijn },
480 d229c123 2019-08-22 martijn {
481 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
482 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_ENVELOPE,
483 d229c123 2019-08-22 martijn 0,
484 d229c123 2019-08-22 martijn osmtpd_tx_envelope,
485 d229c123 2019-08-22 martijn NULL,
486 d229c123 2019-08-22 martijn 0,
487 d229c123 2019-08-22 martijn 0
488 d229c123 2019-08-22 martijn },
489 d229c123 2019-08-22 martijn {
490 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
491 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_DATA,
492 d229c123 2019-08-22 martijn 0,
493 d229c123 2019-08-22 martijn osmtpd_tx_data,
494 d229c123 2019-08-22 martijn NULL,
495 d229c123 2019-08-22 martijn 0,
496 d229c123 2019-08-22 martijn 0
497 d229c123 2019-08-22 martijn },
498 d229c123 2019-08-22 martijn {
499 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
500 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_COMMIT,
501 d229c123 2019-08-22 martijn 0,
502 d229c123 2019-08-22 martijn osmtpd_tx_commit,
503 d229c123 2019-08-22 martijn NULL,
504 d229c123 2019-08-22 martijn 0,
505 d229c123 2019-08-22 martijn 0
506 d229c123 2019-08-22 martijn },
507 d229c123 2019-08-22 martijn {
508 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
509 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_ROLLBACK,
510 d229c123 2019-08-22 martijn 0,
511 d229c123 2019-08-22 martijn osmtpd_tx_rollback,
512 d229c123 2019-08-22 martijn NULL,
513 d229c123 2019-08-22 martijn 0,
514 d229c123 2019-08-22 martijn 0
515 d229c123 2019-08-22 martijn },
516 d229c123 2019-08-22 martijn {
517 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
518 d229c123 2019-08-22 martijn OSMTPD_PHASE_PROTOCOL_CLIENT,
519 d229c123 2019-08-22 martijn 0,
520 d229c123 2019-08-22 martijn osmtpd_onearg,
521 d229c123 2019-08-22 martijn NULL,
522 d229c123 2019-08-22 martijn 0,
523 d229c123 2019-08-22 martijn 0
524 d229c123 2019-08-22 martijn },
525 d229c123 2019-08-22 martijn {
526 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
527 d229c123 2019-08-22 martijn OSMTPD_PHASE_PROTOCOL_SERVER,
528 d229c123 2019-08-22 martijn 0,
529 d229c123 2019-08-22 martijn osmtpd_onearg,
530 d229c123 2019-08-22 martijn NULL,
531 d229c123 2019-08-22 martijn 0,
532 d229c123 2019-08-22 martijn 0
533 d229c123 2019-08-22 martijn },
534 d229c123 2019-08-22 martijn {
535 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
536 d229c123 2019-08-22 martijn OSMTPD_PHASE_FILTER_RESPONSE,
537 d229c123 2019-08-22 martijn 0,
538 d229c123 2019-08-22 martijn osmtpd_onearg,
539 d229c123 2019-08-22 martijn NULL,
540 d229c123 2019-08-22 martijn 0,
541 d229c123 2019-08-22 martijn 0
542 d229c123 2019-08-22 martijn },
543 d229c123 2019-08-22 martijn {
544 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
545 d229c123 2019-08-22 martijn OSMTPD_PHASE_TIMEOUT,
546 d229c123 2019-08-22 martijn 0,
547 d229c123 2019-08-22 martijn osmtpd_noargs,
548 d229c123 2019-08-22 martijn NULL,
549 d229c123 2019-08-22 martijn 0,
550 d229c123 2019-08-22 martijn 0
551 d229c123 2019-08-22 martijn }
552 d229c123 2019-08-22 martijn };
553 d229c123 2019-08-22 martijn
554 ce062d50 2019-08-21 martijn static struct io *io_stdout;
555 09816288 2019-08-22 martijn static int needs;
556 ce062d50 2019-08-21 martijn static int ready = 0;
557 ce062d50 2019-08-21 martijn /* Default from smtpd */
558 ce062d50 2019-08-21 martijn static int session_timeout = 300;
559 ce062d50 2019-08-21 martijn
560 d229c123 2019-08-22 martijn RB_HEAD(osmtpd_sessions, osmtpd_session) osmtpd_sessions = RB_INITIALIZER(NULL);
561 9e3e8410 2019-08-22 martijn RB_PROTOTYPE_STATIC(osmtpd_sessions, osmtpd_session, entry, osmtpd_session_cmp);
562 d229c123 2019-08-22 martijn
563 ce062d50 2019-08-21 martijn void
564 2029083f 2020-10-15 martijn osmtpd_register_conf(void (*cb)(const char *, const char *))
565 2029083f 2020-10-15 martijn {
566 2029083f 2020-10-15 martijn conf_cb = cb;
567 2029083f 2020-10-15 martijn }
568 2029083f 2020-10-15 martijn
569 2029083f 2020-10-15 martijn void
570 ce062d50 2019-08-21 martijn osmtpd_register_filter_connect(void (*cb)(struct osmtpd_ctx *, const char *,
571 ce062d50 2019-08-21 martijn struct sockaddr_storage *))
572 ce062d50 2019-08-21 martijn {
573 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_CONNECT, 1, 0,
574 ce062d50 2019-08-21 martijn (void *)cb);
575 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
576 ce062d50 2019-08-21 martijn NULL);
577 ce062d50 2019-08-21 martijn }
578 ce062d50 2019-08-21 martijn
579 ce062d50 2019-08-21 martijn void
580 ce062d50 2019-08-21 martijn osmtpd_register_filter_helo(void (*cb)(struct osmtpd_ctx *, const char *))
581 ce062d50 2019-08-21 martijn {
582 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_HELO, 1, 0,
583 ce062d50 2019-08-21 martijn (void *)cb);
584 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
585 ce062d50 2019-08-21 martijn NULL);
586 ce062d50 2019-08-21 martijn }
587 ce062d50 2019-08-21 martijn
588 ce062d50 2019-08-21 martijn void
589 ce062d50 2019-08-21 martijn osmtpd_register_filter_ehlo(void (*cb)(struct osmtpd_ctx *, const char *))
590 ce062d50 2019-08-21 martijn {
591 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_EHLO, 1, 0,
592 ce062d50 2019-08-21 martijn (void *)cb);
593 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
594 ce062d50 2019-08-21 martijn NULL);
595 ce062d50 2019-08-21 martijn }
596 ce062d50 2019-08-21 martijn
597 ce062d50 2019-08-21 martijn void
598 ce062d50 2019-08-21 martijn osmtpd_register_filter_starttls(void (*cb)(struct osmtpd_ctx *))
599 ce062d50 2019-08-21 martijn {
600 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_STARTTLS, 1, 0,
601 ce062d50 2019-08-21 martijn (void *)cb);
602 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
603 ce062d50 2019-08-21 martijn NULL);
604 ce062d50 2019-08-21 martijn }
605 ce062d50 2019-08-21 martijn
606 ce062d50 2019-08-21 martijn void
607 ce062d50 2019-08-21 martijn osmtpd_register_filter_auth(void (*cb)(struct osmtpd_ctx *, const char *))
608 ce062d50 2019-08-21 martijn {
609 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_AUTH, 1, 0,
610 ce062d50 2019-08-21 martijn (void *)cb);
611 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
612 ce062d50 2019-08-21 martijn NULL);
613 ce062d50 2019-08-21 martijn }
614 ce062d50 2019-08-21 martijn
615 ce062d50 2019-08-21 martijn void
616 ce062d50 2019-08-21 martijn osmtpd_register_filter_mailfrom(void (*cb)(struct osmtpd_ctx *, const char *))
617 ce062d50 2019-08-21 martijn {
618 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_MAIL_FROM, 1, 0,
619 ce062d50 2019-08-21 martijn (void *)cb);
620 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
621 ce062d50 2019-08-21 martijn NULL);
622 ce062d50 2019-08-21 martijn }
623 ce062d50 2019-08-21 martijn
624 ce062d50 2019-08-21 martijn void
625 ce062d50 2019-08-21 martijn osmtpd_register_filter_rcptto(void (*cb)(struct osmtpd_ctx *, const char *))
626 ce062d50 2019-08-21 martijn {
627 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_RCPT_TO, 1, 0,
628 ce062d50 2019-08-21 martijn (void *)cb);
629 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
630 ce062d50 2019-08-21 martijn NULL);
631 ce062d50 2019-08-21 martijn }
632 ce062d50 2019-08-21 martijn
633 ce062d50 2019-08-21 martijn void
634 ce062d50 2019-08-21 martijn osmtpd_register_filter_data(void (*cb)(struct osmtpd_ctx *))
635 ce062d50 2019-08-21 martijn {
636 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_DATA, 1, 0,
637 ce062d50 2019-08-21 martijn (void *)cb);
638 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
639 ce062d50 2019-08-21 martijn NULL);
640 ce062d50 2019-08-21 martijn }
641 ce062d50 2019-08-21 martijn
642 ce062d50 2019-08-21 martijn void
643 ce062d50 2019-08-21 martijn osmtpd_register_filter_dataline(void (*cb)(struct osmtpd_ctx *, const char *))
644 ce062d50 2019-08-21 martijn {
645 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_DATA_LINE, 1, 0,
646 ce062d50 2019-08-21 martijn (void *)cb);
647 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
648 ce062d50 2019-08-21 martijn NULL);
649 ce062d50 2019-08-21 martijn }
650 ce062d50 2019-08-21 martijn
651 ce062d50 2019-08-21 martijn void
652 ce062d50 2019-08-21 martijn osmtpd_register_filter_rset(void (*cb)(struct osmtpd_ctx *))
653 ce062d50 2019-08-21 martijn {
654 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_RSET, 1, 0,
655 ce062d50 2019-08-21 martijn (void *)cb);
656 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
657 ce062d50 2019-08-21 martijn NULL);
658 ce062d50 2019-08-21 martijn }
659 ce062d50 2019-08-21 martijn
660 ce062d50 2019-08-21 martijn void
661 ce062d50 2019-08-21 martijn osmtpd_register_filter_quit(void (*cb)(struct osmtpd_ctx *))
662 ce062d50 2019-08-21 martijn {
663 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_QUIT, 1, 0,
664 ce062d50 2019-08-21 martijn (void *)cb);
665 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
666 ce062d50 2019-08-21 martijn NULL);
667 ce062d50 2019-08-21 martijn }
668 ce062d50 2019-08-21 martijn
669 ce062d50 2019-08-21 martijn void
670 ce062d50 2019-08-21 martijn osmtpd_register_filter_noop(void (*cb)(struct osmtpd_ctx *))
671 ce062d50 2019-08-21 martijn {
672 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_NOOP, 1, 0,
673 ce062d50 2019-08-21 martijn (void *)cb);
674 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
675 ce062d50 2019-08-21 martijn NULL);
676 ce062d50 2019-08-21 martijn }
677 ce062d50 2019-08-21 martijn
678 ce062d50 2019-08-21 martijn void
679 ce062d50 2019-08-21 martijn osmtpd_register_filter_help(void (*cb)(struct osmtpd_ctx *))
680 ce062d50 2019-08-21 martijn {
681 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_HELP, 1, 0,
682 ce062d50 2019-08-21 martijn (void *)cb);
683 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
684 ce062d50 2019-08-21 martijn NULL);
685 ce062d50 2019-08-21 martijn }
686 ce062d50 2019-08-21 martijn
687 ce062d50 2019-08-21 martijn void
688 ce062d50 2019-08-21 martijn osmtpd_register_filter_wiz(void (*cb)(struct osmtpd_ctx *))
689 ce062d50 2019-08-21 martijn {
690 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_WIZ, 1, 0,
691 ce062d50 2019-08-21 martijn (void *)cb);
692 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
693 ce062d50 2019-08-21 martijn NULL);
694 ce062d50 2019-08-21 martijn }
695 ce062d50 2019-08-21 martijn
696 ce062d50 2019-08-21 martijn void
697 ce062d50 2019-08-21 martijn osmtpd_register_filter_commit(void (*cb)(struct osmtpd_ctx *))
698 ce062d50 2019-08-21 martijn {
699 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_COMMIT, 1, 0,
700 ce062d50 2019-08-21 martijn (void *)cb);
701 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
702 ce062d50 2019-08-21 martijn NULL);
703 ce062d50 2019-08-21 martijn }
704 ce062d50 2019-08-21 martijn
705 ce062d50 2019-08-21 martijn void
706 ce062d50 2019-08-21 martijn osmtpd_register_report_connect(int incoming, void (*cb)(struct osmtpd_ctx *,
707 30f1cbac 2019-08-22 martijn const char *, enum osmtpd_status, struct sockaddr_storage *,
708 ce062d50 2019-08-21 martijn struct sockaddr_storage *))
709 ce062d50 2019-08-21 martijn {
710 3fd8a04a 2021-04-18 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_CONNECT, incoming,
711 ce062d50 2019-08-21 martijn 0, (void *)cb);
712 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
713 ce062d50 2019-08-21 martijn incoming, 0, NULL);
714 ce062d50 2019-08-21 martijn }
715 ce062d50 2019-08-21 martijn
716 ce062d50 2019-08-21 martijn void
717 ce062d50 2019-08-21 martijn osmtpd_register_report_disconnect(int incoming, void (*cb)(struct osmtpd_ctx *))
718 ce062d50 2019-08-21 martijn {
719 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
720 ce062d50 2019-08-21 martijn incoming, 0, (void *)cb);
721 ce062d50 2019-08-21 martijn }
722 ce062d50 2019-08-21 martijn
723 ce062d50 2019-08-21 martijn void
724 ce062d50 2019-08-21 martijn osmtpd_register_report_identify(int incoming, void (*cb)(struct osmtpd_ctx *,
725 ce062d50 2019-08-21 martijn const char *))
726 ce062d50 2019-08-21 martijn {
727 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_IDENTIFY,
728 ce062d50 2019-08-21 martijn incoming, 0, (void *)cb);
729 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
730 ce062d50 2019-08-21 martijn incoming, 0, NULL);
731 ce062d50 2019-08-21 martijn }
732 ce062d50 2019-08-21 martijn
733 ce062d50 2019-08-21 martijn void
734 ce062d50 2019-08-21 martijn osmtpd_register_report_tls(int incoming, void (*cb)(struct osmtpd_ctx *,
735 ce062d50 2019-08-21 martijn const char *))
736 ce062d50 2019-08-21 martijn {
737 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_TLS, incoming, 0,
738 ce062d50 2019-08-21 martijn (void *)cb);
739 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
740 ce062d50 2019-08-21 martijn incoming, 0, NULL);
741 ce062d50 2019-08-21 martijn }
742 ce062d50 2019-08-21 martijn
743 ce062d50 2019-08-21 martijn void
744 58a6bc69 2022-12-05 martijn osmtpd_register_report_auth(int incoming, void (*cb)(struct osmtpd_ctx *,
745 58a6bc69 2022-12-05 martijn const char *, enum osmtpd_auth_status))
746 58a6bc69 2022-12-05 martijn {
747 58a6bc69 2022-12-05 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_AUTH, incoming, 0,
748 58a6bc69 2022-12-05 martijn (void *)cb);
749 58a6bc69 2022-12-05 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
750 58a6bc69 2022-12-05 martijn incoming, 0, NULL);
751 58a6bc69 2022-12-05 martijn }
752 58a6bc69 2022-12-05 martijn
753 58a6bc69 2022-12-05 martijn void
754 ce062d50 2019-08-21 martijn osmtpd_register_report_begin(int incoming, void (*cb)(struct osmtpd_ctx *,
755 ce062d50 2019-08-21 martijn uint32_t))
756 ce062d50 2019-08-21 martijn {
757 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_BEGIN, incoming, 0,
758 ce062d50 2019-08-21 martijn (void *)cb);
759 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
760 ce062d50 2019-08-21 martijn incoming, 0, NULL);
761 ce062d50 2019-08-21 martijn }
762 ce062d50 2019-08-21 martijn
763 ce062d50 2019-08-21 martijn void
764 ce062d50 2019-08-21 martijn osmtpd_register_report_mail(int incoming, void (*cb)(struct osmtpd_ctx *,
765 ce062d50 2019-08-21 martijn uint32_t, const char *, enum osmtpd_status))
766 ce062d50 2019-08-21 martijn {
767 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_MAIL, incoming, 0,
768 ce062d50 2019-08-21 martijn (void *)cb);
769 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
770 ce062d50 2019-08-21 martijn incoming, 0, NULL);
771 ce062d50 2019-08-21 martijn }
772 ce062d50 2019-08-21 martijn
773 ce062d50 2019-08-21 martijn void
774 ce062d50 2019-08-21 martijn osmtpd_register_report_rcpt(int incoming, void (*cb)(struct osmtpd_ctx *,
775 ce062d50 2019-08-21 martijn uint32_t, const char *, enum osmtpd_status))
776 ce062d50 2019-08-21 martijn {
777 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_RCPT, incoming, 0,
778 ce062d50 2019-08-21 martijn (void *)cb);
779 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
780 ce062d50 2019-08-21 martijn incoming, 0, NULL);
781 ce062d50 2019-08-21 martijn }
782 ce062d50 2019-08-21 martijn
783 ce062d50 2019-08-21 martijn void
784 ce062d50 2019-08-21 martijn osmtpd_register_report_envelope(int incoming, void (*cb)(struct osmtpd_ctx *,
785 ce062d50 2019-08-21 martijn uint32_t, uint64_t))
786 ce062d50 2019-08-21 martijn {
787 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ENVELOPE, incoming,
788 ce062d50 2019-08-21 martijn 0, (void *)cb);
789 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
790 ce062d50 2019-08-21 martijn incoming, 0, NULL);
791 ce062d50 2019-08-21 martijn }
792 ce062d50 2019-08-21 martijn
793 ce062d50 2019-08-21 martijn void
794 ce062d50 2019-08-21 martijn osmtpd_register_report_data(int incoming, void (*cb)(struct osmtpd_ctx *,
795 ce062d50 2019-08-21 martijn uint32_t, enum osmtpd_status))
796 ce062d50 2019-08-21 martijn {
797 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_DATA, incoming, 0,
798 ce062d50 2019-08-21 martijn (void *)cb);
799 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
800 ce062d50 2019-08-21 martijn incoming, 0, NULL);
801 ce062d50 2019-08-21 martijn }
802 ce062d50 2019-08-21 martijn
803 ce062d50 2019-08-21 martijn void
804 ce062d50 2019-08-21 martijn osmtpd_register_report_commit(int incoming, void (*cb)(struct osmtpd_ctx *,
805 ce062d50 2019-08-21 martijn uint32_t, size_t))
806 ce062d50 2019-08-21 martijn {
807 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_COMMIT, incoming, 0,
808 ce062d50 2019-08-21 martijn (void *)cb);
809 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
810 ce062d50 2019-08-21 martijn incoming, 0, NULL);
811 ce062d50 2019-08-21 martijn }
812 ce062d50 2019-08-21 martijn
813 ce062d50 2019-08-21 martijn void
814 ce062d50 2019-08-21 martijn osmtpd_register_report_rollback(int incoming, void (*cb)(struct osmtpd_ctx *,
815 ce062d50 2019-08-21 martijn uint32_t))
816 ce062d50 2019-08-21 martijn {
817 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ROLLBACK, incoming,
818 ce062d50 2019-08-21 martijn 0, (void *)cb);
819 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
820 ce062d50 2019-08-21 martijn incoming, 0, NULL);
821 ce062d50 2019-08-21 martijn }
822 ce062d50 2019-08-21 martijn
823 ce062d50 2019-08-21 martijn void
824 ce062d50 2019-08-21 martijn osmtpd_register_report_client(int incoming, void (*cb)(struct osmtpd_ctx *,
825 ce062d50 2019-08-21 martijn const char *))
826 ce062d50 2019-08-21 martijn {
827 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_PROTOCOL_CLIENT,
828 ce062d50 2019-08-21 martijn incoming, 0, (void *)cb);
829 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
830 ce062d50 2019-08-21 martijn incoming, 0, NULL);
831 ce062d50 2019-08-21 martijn }
832 ce062d50 2019-08-21 martijn
833 ce062d50 2019-08-21 martijn void
834 ce062d50 2019-08-21 martijn osmtpd_register_report_server(int incoming, void (*cb)(struct osmtpd_ctx *,
835 ce062d50 2019-08-21 martijn const char *))
836 ce062d50 2019-08-21 martijn {
837 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_PROTOCOL_SERVER,
838 ce062d50 2019-08-21 martijn incoming, 0, (void *)cb);
839 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
840 ce062d50 2019-08-21 martijn incoming, 0, NULL);
841 ce062d50 2019-08-21 martijn }
842 ce062d50 2019-08-21 martijn
843 ce062d50 2019-08-21 martijn void
844 ce062d50 2019-08-21 martijn osmtpd_register_report_response(int incoming, void (*cb)(struct osmtpd_ctx *,
845 ce062d50 2019-08-21 martijn const char *))
846 ce062d50 2019-08-21 martijn {
847 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_FILTER_RESPONSE,
848 ce062d50 2019-08-21 martijn incoming, 0, (void *)cb);
849 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
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 void
854 ce062d50 2019-08-21 martijn osmtpd_register_report_timeout(int incoming, void (*cb)(struct osmtpd_ctx *))
855 ce062d50 2019-08-21 martijn {
856 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TIMEOUT, incoming, 0,
857 ce062d50 2019-08-21 martijn (void *)cb);
858 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
859 ce062d50 2019-08-21 martijn incoming, 0, NULL);
860 ce062d50 2019-08-21 martijn }
861 ce062d50 2019-08-21 martijn
862 ce062d50 2019-08-21 martijn void
863 912d0ff2 2019-08-22 martijn osmtpd_local_session(void *(*oncreate)(struct osmtpd_ctx *),
864 ce062d50 2019-08-21 martijn void (*ondelete)(struct osmtpd_ctx *, void *))
865 ce062d50 2019-08-21 martijn {
866 912d0ff2 2019-08-22 martijn oncreatecb_session = oncreate;
867 912d0ff2 2019-08-22 martijn ondeletecb_session = ondelete;
868 ce062d50 2019-08-21 martijn }
869 ce062d50 2019-08-21 martijn
870 ce062d50 2019-08-21 martijn void
871 912d0ff2 2019-08-22 martijn osmtpd_local_message(void *(*oncreate)(struct osmtpd_ctx *),
872 912d0ff2 2019-08-22 martijn void (*ondelete)(struct osmtpd_ctx *, void *))
873 912d0ff2 2019-08-22 martijn {
874 912d0ff2 2019-08-22 martijn oncreatecb_message = oncreate;
875 912d0ff2 2019-08-22 martijn ondeletecb_message = ondelete;
876 912d0ff2 2019-08-22 martijn }
877 912d0ff2 2019-08-22 martijn
878 912d0ff2 2019-08-22 martijn void
879 09816288 2019-08-22 martijn osmtpd_need(int lneeds)
880 ce062d50 2019-08-21 martijn {
881 09816288 2019-08-22 martijn needs |= lneeds;
882 09816288 2019-08-22 martijn }
883 09816288 2019-08-22 martijn
884 09816288 2019-08-22 martijn static void
885 09816288 2019-08-22 martijn osmtpd_register_need(int incoming)
886 09816288 2019-08-22 martijn {
887 ce062d50 2019-08-21 martijn if (needs & (OSMTPD_NEED_SRC | OSMTPD_NEED_DST | OSMTPD_NEED_RDNS |
888 09816288 2019-08-22 martijn OSMTPD_NEED_FCRDNS))
889 705cd566 2019-08-23 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_CONNECT,
890 ce062d50 2019-08-21 martijn incoming, 1, NULL);
891 0fb4c799 2019-09-05 martijn if (needs & OSMTPD_NEED_GREETING)
892 a05d5c54 2019-08-28 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_GREETING,
893 a05d5c54 2019-08-28 martijn incoming, 1, NULL);
894 0fb4c799 2019-09-05 martijn if (needs & OSMTPD_NEED_IDENTITY)
895 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_IDENTIFY,
896 ce062d50 2019-08-21 martijn incoming, 1, NULL);
897 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_CIPHERS)
898 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_TLS,
899 ce062d50 2019-08-21 martijn incoming, 1, NULL);
900 58a6bc69 2022-12-05 martijn if (needs & OSMTPD_NEED_USERNAME)
901 58a6bc69 2022-12-05 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_AUTH,
902 58a6bc69 2022-12-05 martijn incoming, 1, NULL);
903 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_MSGID) {
904 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_BEGIN,
905 ce062d50 2019-08-21 martijn incoming, 1, NULL);
906 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ROLLBACK,
907 ce062d50 2019-08-21 martijn incoming, 0, NULL);
908 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_COMMIT,
909 ce062d50 2019-08-21 martijn incoming, 0, NULL);
910 ce062d50 2019-08-21 martijn }
911 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_MAILFROM) {
912 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_MAIL,
913 ce062d50 2019-08-21 martijn incoming, 1, NULL);
914 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ROLLBACK,
915 ce062d50 2019-08-21 martijn incoming, 0, NULL);
916 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_COMMIT,
917 ce062d50 2019-08-21 martijn incoming, 0, NULL);
918 ce062d50 2019-08-21 martijn }
919 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_RCPTTO) {
920 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_RCPT,
921 ce062d50 2019-08-21 martijn incoming, 1, NULL);
922 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ROLLBACK,
923 ce062d50 2019-08-21 martijn incoming, 0, NULL);
924 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_COMMIT,
925 ce062d50 2019-08-21 martijn incoming, 0, NULL);
926 ce062d50 2019-08-21 martijn }
927 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_EVPID) {
928 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ENVELOPE,
929 ce062d50 2019-08-21 martijn incoming, 1, NULL);
930 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ROLLBACK,
931 ce062d50 2019-08-21 martijn incoming, 0, NULL);
932 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_COMMIT,
933 ce062d50 2019-08-21 martijn incoming, 0, NULL);
934 ce062d50 2019-08-21 martijn }
935 ce062d50 2019-08-21 martijn
936 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
937 ce062d50 2019-08-21 martijn incoming, 0, NULL);
938 ce062d50 2019-08-21 martijn }
939 ce062d50 2019-08-21 martijn
940 ce062d50 2019-08-21 martijn void
941 ce062d50 2019-08-21 martijn osmtpd_run(void)
942 ce062d50 2019-08-21 martijn {
943 ce062d50 2019-08-21 martijn size_t i = 0;
944 ce062d50 2019-08-21 martijn int registered = 0;
945 adebfe7c 2021-03-21 martijn struct event_base *evbase;
946 ce062d50 2019-08-21 martijn struct io *io_stdin;
947 a37af028 2019-09-17 martijn struct osmtpd_callback *hidenity = NULL, *eidentity = NULL;
948 a37af028 2019-09-17 martijn struct osmtpd_callback *ridentity = NULL;
949 ce062d50 2019-08-21 martijn
950 adebfe7c 2021-03-21 martijn evbase = event_init();
951 ce062d50 2019-08-21 martijn
952 ce062d50 2019-08-21 martijn if ((io_stdin = io_new()) == NULL ||
953 ce062d50 2019-08-21 martijn (io_stdout = io_new()) == NULL)
954 27dd1f3b 2019-08-22 martijn osmtpd_err(1, "io_new");
955 ce062d50 2019-08-21 martijn io_set_nonblocking(STDIN_FILENO);
956 ce062d50 2019-08-21 martijn io_set_fd(io_stdin, STDIN_FILENO);
957 ce062d50 2019-08-21 martijn io_set_callback(io_stdin, osmtpd_newline, NULL);
958 ce062d50 2019-08-21 martijn io_set_read(io_stdin);
959 ce062d50 2019-08-21 martijn io_set_nonblocking(STDOUT_FILENO);
960 ce062d50 2019-08-21 martijn io_set_fd(io_stdout, STDOUT_FILENO);
961 ce062d50 2019-08-21 martijn io_set_callback(io_stdout, osmtpd_outevt, NULL);
962 ce062d50 2019-08-21 martijn io_set_write(io_stdout);
963 ce062d50 2019-08-21 martijn
964 ce062d50 2019-08-21 martijn for (i = 0; i < NITEMS(osmtpd_callbacks); i++) {
965 912d0ff2 2019-08-22 martijn if (osmtpd_callbacks[i].doregister) {
966 09816288 2019-08-22 martijn osmtpd_register_need(osmtpd_callbacks[i].incoming);
967 912d0ff2 2019-08-22 martijn if (oncreatecb_message != NULL) {
968 912d0ff2 2019-08-22 martijn osmtpd_register(OSMTPD_TYPE_REPORT,
969 912d0ff2 2019-08-22 martijn OSMTPD_PHASE_TX_BEGIN,
970 912d0ff2 2019-08-22 martijn osmtpd_callbacks[i].incoming, 0, NULL);
971 912d0ff2 2019-08-22 martijn osmtpd_register(OSMTPD_TYPE_REPORT,
972 912d0ff2 2019-08-22 martijn OSMTPD_PHASE_TX_ROLLBACK,
973 912d0ff2 2019-08-22 martijn osmtpd_callbacks[i].incoming, 0, NULL);
974 912d0ff2 2019-08-22 martijn osmtpd_register(OSMTPD_TYPE_REPORT,
975 912d0ff2 2019-08-22 martijn OSMTPD_PHASE_TX_COMMIT,
976 912d0ff2 2019-08-22 martijn osmtpd_callbacks[i].incoming, 0, NULL);
977 912d0ff2 2019-08-22 martijn }
978 421c9a86 2019-09-06 martijn if (osmtpd_callbacks[i].type == OSMTPD_TYPE_FILTER &&
979 421c9a86 2019-09-06 martijn osmtpd_callbacks[i].phase == OSMTPD_PHASE_HELO)
980 421c9a86 2019-09-06 martijn hidenity = &(osmtpd_callbacks[i]);
981 421c9a86 2019-09-06 martijn if (osmtpd_callbacks[i].type == OSMTPD_TYPE_FILTER &&
982 421c9a86 2019-09-06 martijn osmtpd_callbacks[i].phase == OSMTPD_PHASE_EHLO)
983 421c9a86 2019-09-06 martijn eidentity = &(osmtpd_callbacks[i]);
984 421c9a86 2019-09-06 martijn if (osmtpd_callbacks[i].type == OSMTPD_TYPE_REPORT &&
985 421c9a86 2019-09-06 martijn osmtpd_callbacks[i].phase ==
986 421c9a86 2019-09-06 martijn OSMTPD_PHASE_LINK_IDENTIFY &&
987 421c9a86 2019-09-06 martijn osmtpd_callbacks[i].incoming == 1)
988 421c9a86 2019-09-06 martijn ridentity = &(osmtpd_callbacks[i]);
989 912d0ff2 2019-08-22 martijn }
990 09816288 2019-08-22 martijn }
991 a37af028 2019-09-17 martijn if (ridentity != NULL && ridentity->storereport) {
992 a37af028 2019-09-17 martijn if (hidenity != NULL && hidenity->doregister)
993 421c9a86 2019-09-06 martijn hidenity->storereport = 1;
994 a37af028 2019-09-17 martijn if (eidentity != NULL && eidentity->doregister)
995 421c9a86 2019-09-06 martijn eidentity->storereport = 1;
996 421c9a86 2019-09-06 martijn }
997 09816288 2019-08-22 martijn for (i = 0; i < NITEMS(osmtpd_callbacks); i++) {
998 ce062d50 2019-08-21 martijn if (osmtpd_callbacks[i].doregister) {
999 ce062d50 2019-08-21 martijn if (osmtpd_callbacks[i].cb != NULL)
1000 ce062d50 2019-08-21 martijn registered = 1;
1001 ce062d50 2019-08-21 martijn io_printf(io_stdout, "register|%s|smtp-%s|%s\n",
1002 ce062d50 2019-08-21 martijn osmtpd_typetostr(osmtpd_callbacks[i].type),
1003 ce062d50 2019-08-21 martijn osmtpd_callbacks[i].incoming ? "in" : "out",
1004 ce062d50 2019-08-21 martijn osmtpd_phasetostr(osmtpd_callbacks[i].phase));
1005 ce062d50 2019-08-21 martijn }
1006 ce062d50 2019-08-21 martijn }
1007 ce062d50 2019-08-21 martijn
1008 ce062d50 2019-08-21 martijn if (!registered)
1009 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "No events registered");
1010 ce062d50 2019-08-21 martijn io_printf(io_stdout, "register|ready\n");
1011 ce062d50 2019-08-21 martijn ready = 1;
1012 ce062d50 2019-08-21 martijn
1013 ce062d50 2019-08-21 martijn event_dispatch();
1014 adebfe7c 2021-03-21 martijn io_free(io_stdin);
1015 adebfe7c 2021-03-21 martijn io_free(io_stdout);
1016 adebfe7c 2021-03-21 martijn event_base_free(evbase);
1017 ce062d50 2019-08-21 martijn }
1018 ce062d50 2019-08-21 martijn
1019 27dd1f3b 2019-08-22 martijn __dead void
1020 27dd1f3b 2019-08-22 martijn osmtpd_err(int eval, const char *fmt, ...)
1021 27dd1f3b 2019-08-22 martijn {
1022 27dd1f3b 2019-08-22 martijn va_list ap;
1023 27dd1f3b 2019-08-22 martijn
1024 27dd1f3b 2019-08-22 martijn va_start(ap, fmt);
1025 27dd1f3b 2019-08-22 martijn vfprintf(stderr, fmt, ap);
1026 27dd1f3b 2019-08-22 martijn va_end(ap);
1027 67cd1323 2019-08-22 martijn fprintf(stderr, ": %s\n", strerror(errno));
1028 27dd1f3b 2019-08-22 martijn exit(eval);
1029 27dd1f3b 2019-08-22 martijn }
1030 27dd1f3b 2019-08-22 martijn
1031 27dd1f3b 2019-08-22 martijn __dead void
1032 27dd1f3b 2019-08-22 martijn osmtpd_errx(int eval, const char *fmt, ...)
1033 27dd1f3b 2019-08-22 martijn {
1034 27dd1f3b 2019-08-22 martijn va_list ap;
1035 27dd1f3b 2019-08-22 martijn
1036 27dd1f3b 2019-08-22 martijn va_start(ap, fmt);
1037 27dd1f3b 2019-08-22 martijn vfprintf(stderr, fmt, ap);
1038 27dd1f3b 2019-08-22 martijn va_end(ap);
1039 27dd1f3b 2019-08-22 martijn fprintf(stderr, "\n");
1040 27dd1f3b 2019-08-22 martijn exit(eval);
1041 27dd1f3b 2019-08-22 martijn }
1042 27dd1f3b 2019-08-22 martijn
1043 ce062d50 2019-08-21 martijn static void
1044 6258daeb 2019-11-14 martijn osmtpd_newline(struct io *io, int ev, __unused void *arg)
1045 ce062d50 2019-08-21 martijn {
1046 ce062d50 2019-08-21 martijn static char *linedup = NULL;
1047 ce062d50 2019-08-21 martijn static size_t dupsize = 0;
1048 ce062d50 2019-08-21 martijn struct osmtpd_session *ctx, search;
1049 ce062d50 2019-08-21 martijn enum osmtpd_type type;
1050 ce062d50 2019-08-21 martijn enum osmtpd_phase phase;
1051 ce062d50 2019-08-21 martijn int version_major, version_minor, incoming;
1052 ce062d50 2019-08-21 martijn struct timespec tm;
1053 ce062d50 2019-08-21 martijn char *line = NULL;
1054 ce062d50 2019-08-21 martijn const char *errstr = NULL;
1055 ce062d50 2019-08-21 martijn size_t linelen;
1056 ce062d50 2019-08-21 martijn char *end;
1057 ce062d50 2019-08-21 martijn size_t i;
1058 ce062d50 2019-08-21 martijn
1059 adebfe7c 2021-03-21 martijn if (ev == IO_DISCONNECTED) {
1060 adebfe7c 2021-03-21 martijn event_loopexit(0);
1061 adebfe7c 2021-03-21 martijn return;
1062 adebfe7c 2021-03-21 martijn }
1063 ce062d50 2019-08-21 martijn if (ev != IO_DATAIN)
1064 ce062d50 2019-08-21 martijn return;
1065 5f7c62fa 2022-03-28 martijn /*
1066 5f7c62fa 2022-03-28 martijn * Multiple calls to io_printf (through osmtpd_filter_dataline) can
1067 5f7c62fa 2022-03-28 martijn * cause a build-up of kevents, because of event_add/event_del loop.
1068 5f7c62fa 2022-03-28 martijn */
1069 5f7c62fa 2022-03-28 martijn io_pause(io_stdout, IO_OUT);
1070 24d62a97 2019-08-23 martijn while ((line = io_getline(io, &linelen)) != NULL) {
1071 ce062d50 2019-08-21 martijn if (dupsize < linelen) {
1072 ce062d50 2019-08-21 martijn if ((linedup = realloc(linedup, linelen + 1)) == NULL)
1073 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1074 ce062d50 2019-08-21 martijn dupsize = linelen + 1;
1075 ce062d50 2019-08-21 martijn }
1076 ce062d50 2019-08-21 martijn strlcpy(linedup, line, dupsize);
1077 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
1078 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing "
1079 c6cb29f3 2019-08-22 martijn "version: %s", linedup);
1080 ce062d50 2019-08-21 martijn end++[0] = '\0';
1081 ce062d50 2019-08-21 martijn if (strcmp(line, "filter") == 0)
1082 ce062d50 2019-08-21 martijn type = OSMTPD_TYPE_FILTER;
1083 ce062d50 2019-08-21 martijn else if (strcmp(line, "report") == 0)
1084 ce062d50 2019-08-21 martijn type = OSMTPD_TYPE_REPORT;
1085 ce062d50 2019-08-21 martijn else if (strcmp(line, "config") == 0) {
1086 ce062d50 2019-08-21 martijn line = end;
1087 2029083f 2020-10-15 martijn if (strcmp(line, "ready") == 0) {
1088 34f87d66 2020-12-20 martijn if (conf_cb != NULL)
1089 34f87d66 2020-12-20 martijn conf_cb(NULL, NULL);
1090 ce062d50 2019-08-21 martijn continue;
1091 2029083f 2020-10-15 martijn }
1092 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
1093 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing "
1094 c6cb29f3 2019-08-22 martijn "key: %s", linedup);
1095 ce062d50 2019-08-21 martijn end++[0] = '\0';
1096 34f87d66 2020-12-20 martijn if (conf_cb != NULL)
1097 34f87d66 2020-12-20 martijn conf_cb(line, end);
1098 ce062d50 2019-08-21 martijn if (strcmp(line, "smtp-session-timeout") == 0) {
1099 ce062d50 2019-08-21 martijn session_timeout = strtonum(end, 0, INT_MAX,
1100 ce062d50 2019-08-21 martijn &errstr);
1101 ce062d50 2019-08-21 martijn if (errstr != NULL)
1102 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: "
1103 ce062d50 2019-08-21 martijn "invalid smtp-sesion-timeout: %s",
1104 ce062d50 2019-08-21 martijn linedup);
1105 ce062d50 2019-08-21 martijn }
1106 ce062d50 2019-08-21 martijn continue;
1107 ce062d50 2019-08-21 martijn }
1108 ce062d50 2019-08-21 martijn else
1109 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: unknown message "
1110 c6cb29f3 2019-08-22 martijn "type: %s", linedup);
1111 ce062d50 2019-08-21 martijn line = end;
1112 183acf20 2019-08-28 martijn version_major = strtoul(line, &end, 10);
1113 183acf20 2019-08-28 martijn if (line == end || end[0] != '.')
1114 183acf20 2019-08-28 martijn osmtpd_errx(1, "Invalid protocol received: %s",
1115 183acf20 2019-08-28 martijn linedup);
1116 183acf20 2019-08-28 martijn line = end + 1;
1117 183acf20 2019-08-28 martijn version_minor = strtoul(line, &end, 10);
1118 183acf20 2019-08-28 martijn if (end[0] == '\0')
1119 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing time: "
1120 c6cb29f3 2019-08-22 martijn "%s", linedup);
1121 183acf20 2019-08-28 martijn if (line == end || end[0] != '|')
1122 183acf20 2019-08-28 martijn osmtpd_errx(1, "Invalid protocol received: %s",
1123 183acf20 2019-08-28 martijn linedup);
1124 183acf20 2019-08-28 martijn if (version_major != 0)
1125 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Unsupported protocol received: %s",
1126 c6cb29f3 2019-08-22 martijn linedup);
1127 183acf20 2019-08-28 martijn line = end + 1;
1128 ce062d50 2019-08-21 martijn if ((end = strchr(line, '.')) == NULL)
1129 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
1130 c6cb29f3 2019-08-22 martijn "timestamp: %s", linedup);
1131 ce062d50 2019-08-21 martijn end++[0] = '\0';
1132 ce062d50 2019-08-21 martijn tm.tv_sec = (time_t) strtonum(line, 0, INT64_MAX, &errstr);
1133 ce062d50 2019-08-21 martijn if (errstr != NULL)
1134 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
1135 c6cb29f3 2019-08-22 martijn "timestamp: %s", linedup);
1136 ce062d50 2019-08-21 martijn line = end;
1137 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
1138 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing "
1139 c6cb29f3 2019-08-22 martijn "direction: %s", linedup);
1140 ce062d50 2019-08-21 martijn end++[0] = '\0';
1141 ce062d50 2019-08-21 martijn tm.tv_nsec = (long) strtonum(line, 0, LONG_MAX, &errstr);
1142 ce062d50 2019-08-21 martijn if (errstr != NULL)
1143 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
1144 c6cb29f3 2019-08-22 martijn "timestamp: %s", linedup);
1145 ce062d50 2019-08-21 martijn tm.tv_nsec *= 10 * (9 - (end - line));
1146 ce062d50 2019-08-21 martijn line = end;
1147 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
1148 e5f09156 2021-06-01 martijn osmtpd_errx(1, "Invalid line received: missing "
1149 c6cb29f3 2019-08-22 martijn "phase: %s", linedup);
1150 ce062d50 2019-08-21 martijn end++[0] = '\0';
1151 ce062d50 2019-08-21 martijn if (strcmp(line, "smtp-in") == 0)
1152 ce062d50 2019-08-21 martijn incoming = 1;
1153 ce062d50 2019-08-21 martijn else if (strcmp(line, "smtp-out") == 0)
1154 ce062d50 2019-08-21 martijn incoming = 0;
1155 ce062d50 2019-08-21 martijn else
1156 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line: invalid direction: %s",
1157 c6cb29f3 2019-08-22 martijn linedup);
1158 ce062d50 2019-08-21 martijn line = end;
1159 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
1160 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing reqid: "
1161 c6cb29f3 2019-08-22 martijn "%s", linedup);
1162 ce062d50 2019-08-21 martijn end++[0] = '\0';
1163 ce062d50 2019-08-21 martijn phase = osmtpd_strtophase(line, linedup);
1164 ce062d50 2019-08-21 martijn line = end;
1165 ce062d50 2019-08-21 martijn errno = 0;
1166 ce062d50 2019-08-21 martijn search.ctx.reqid = strtoull(line, &end, 16);
1167 ce062d50 2019-08-21 martijn if ((search.ctx.reqid == ULLONG_MAX && errno != 0) ||
1168 ce062d50 2019-08-21 martijn (end[0] != '|' && end[0] != '\0'))
1169 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid reqid: "
1170 c6cb29f3 2019-08-22 martijn "%s", linedup);
1171 ce062d50 2019-08-21 martijn line = end + 1;
1172 ce062d50 2019-08-21 martijn ctx = RB_FIND(osmtpd_sessions, &osmtpd_sessions, &search);
1173 ce062d50 2019-08-21 martijn if (ctx == NULL) {
1174 ce062d50 2019-08-21 martijn if ((ctx = malloc(sizeof(*ctx))) == NULL)
1175 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1176 ce062d50 2019-08-21 martijn ctx->ctx.reqid = search.ctx.reqid;
1177 ce062d50 2019-08-21 martijn ctx->ctx.rdns = NULL;
1178 30f1cbac 2019-08-22 martijn ctx->ctx.fcrdns = OSMTPD_STATUS_TEMPFAIL;
1179 0fb4c799 2019-09-05 martijn ctx->ctx.identity = NULL;
1180 0fb4c799 2019-09-05 martijn ctx->ctx.greeting.identity = NULL;
1181 ce062d50 2019-08-21 martijn ctx->ctx.ciphers = NULL;
1182 ce062d50 2019-08-21 martijn ctx->ctx.msgid = 0;
1183 58a6bc69 2022-12-05 martijn ctx->ctx.username = NULL;
1184 ce062d50 2019-08-21 martijn ctx->ctx.mailfrom = NULL;
1185 ce062d50 2019-08-21 martijn ctx->ctx.rcptto = malloc(sizeof(*(ctx->ctx.rcptto)));
1186 ce062d50 2019-08-21 martijn if (ctx->ctx.rcptto == NULL)
1187 27dd1f3b 2019-08-22 martijn osmtpd_err(1, "malloc");
1188 ce062d50 2019-08-21 martijn ctx->ctx.rcptto[0] = NULL;
1189 ce062d50 2019-08-21 martijn memset(&(ctx->ctx.src), 0, sizeof(ctx->ctx.src));
1190 ce062d50 2019-08-21 martijn ctx->ctx.src.ss_family = AF_UNSPEC;
1191 ce062d50 2019-08-21 martijn memset(&(ctx->ctx.dst), 0, sizeof(ctx->ctx.dst));
1192 ce062d50 2019-08-21 martijn ctx->ctx.dst.ss_family = AF_UNSPEC;
1193 ce062d50 2019-08-21 martijn RB_INSERT(osmtpd_sessions, &osmtpd_sessions, ctx);
1194 ce062d50 2019-08-21 martijn ctx->ctx.evpid = 0;
1195 912d0ff2 2019-08-22 martijn ctx->ctx.local_session = NULL;
1196 912d0ff2 2019-08-22 martijn ctx->ctx.local_message = NULL;
1197 912d0ff2 2019-08-22 martijn if (oncreatecb_session != NULL)
1198 912d0ff2 2019-08-22 martijn ctx->ctx.local_session =
1199 912d0ff2 2019-08-22 martijn oncreatecb_session(&ctx->ctx);
1200 ce062d50 2019-08-21 martijn }
1201 ce062d50 2019-08-21 martijn ctx->ctx.type = type;
1202 ce062d50 2019-08-21 martijn ctx->ctx.phase = phase;
1203 ce062d50 2019-08-21 martijn ctx->ctx.version_major = version_major;
1204 ce062d50 2019-08-21 martijn ctx->ctx.version_minor = version_minor;
1205 ce062d50 2019-08-21 martijn ctx->ctx.incoming = incoming;
1206 ce062d50 2019-08-21 martijn ctx->ctx.tm.tv_sec = tm.tv_sec;
1207 ce062d50 2019-08-21 martijn ctx->ctx.tm.tv_nsec = tm.tv_nsec;
1208 ce062d50 2019-08-21 martijn ctx->ctx.token = 0;
1209 ce062d50 2019-08-21 martijn
1210 ce062d50 2019-08-21 martijn for (i = 0; i < NITEMS(osmtpd_callbacks); i++) {
1211 ce062d50 2019-08-21 martijn if (ctx->ctx.type == osmtpd_callbacks[i].type &&
1212 ce062d50 2019-08-21 martijn ctx->ctx.phase == osmtpd_callbacks[i].phase &&
1213 ce062d50 2019-08-21 martijn ctx->ctx.incoming == osmtpd_callbacks[i].incoming)
1214 ce062d50 2019-08-21 martijn break;
1215 ce062d50 2019-08-21 martijn }
1216 ce062d50 2019-08-21 martijn if (i == NITEMS(osmtpd_callbacks)) {
1217 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: received "
1218 c6cb29f3 2019-08-22 martijn "unregistered line: %s", linedup);
1219 ce062d50 2019-08-21 martijn }
1220 ce062d50 2019-08-21 martijn if (ctx->ctx.type == OSMTPD_TYPE_FILTER) {
1221 ce062d50 2019-08-21 martijn ctx->ctx.token = strtoull(line, &end, 16);
1222 c6cb29f3 2019-08-22 martijn if ((ctx->ctx.token == ULLONG_MAX && errno != 0) ||
1223 ce062d50 2019-08-21 martijn end[0] != '|')
1224 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
1225 c6cb29f3 2019-08-22 martijn "token: %s", linedup);
1226 ce062d50 2019-08-21 martijn line = end + 1;
1227 ce062d50 2019-08-21 martijn }
1228 ce062d50 2019-08-21 martijn osmtpd_callbacks[i].osmtpd_cb(&(osmtpd_callbacks[i]),
1229 ce062d50 2019-08-21 martijn &(ctx->ctx), line, linedup);
1230 ce062d50 2019-08-21 martijn }
1231 5f7c62fa 2022-03-28 martijn io_resume(io_stdout, IO_OUT);
1232 ce062d50 2019-08-21 martijn }
1233 ce062d50 2019-08-21 martijn
1234 ce062d50 2019-08-21 martijn static void
1235 6258daeb 2019-11-14 martijn osmtpd_outevt(__unused struct io *io, int evt, __unused void *arg)
1236 ce062d50 2019-08-21 martijn {
1237 ce062d50 2019-08-21 martijn switch (evt) {
1238 ce062d50 2019-08-21 martijn case IO_LOWAT:
1239 ce062d50 2019-08-21 martijn return;
1240 ce062d50 2019-08-21 martijn case IO_DISCONNECTED:
1241 ce062d50 2019-08-21 martijn exit(0);
1242 ce062d50 2019-08-21 martijn default:
1243 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Unexpectd event");
1244 ce062d50 2019-08-21 martijn }
1245 ce062d50 2019-08-21 martijn }
1246 ce062d50 2019-08-21 martijn
1247 ce062d50 2019-08-21 martijn static void
1248 6258daeb 2019-11-14 martijn osmtpd_noargs(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1249 6258daeb 2019-11-14 martijn __unused char *params, __unused char *linedup)
1250 ce062d50 2019-08-21 martijn {
1251 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *);
1252 ce062d50 2019-08-21 martijn
1253 ce062d50 2019-08-21 martijn f = cb->cb;
1254 ce062d50 2019-08-21 martijn f(ctx);
1255 ce062d50 2019-08-21 martijn }
1256 ce062d50 2019-08-21 martijn
1257 ce062d50 2019-08-21 martijn static void
1258 ce062d50 2019-08-21 martijn osmtpd_onearg(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx, char *line,
1259 6258daeb 2019-11-14 martijn __unused char *linedup)
1260 ce062d50 2019-08-21 martijn {
1261 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, const char *);
1262 ce062d50 2019-08-21 martijn
1263 ce062d50 2019-08-21 martijn f = cb->cb;
1264 ce062d50 2019-08-21 martijn f(ctx, line);
1265 ce062d50 2019-08-21 martijn }
1266 ce062d50 2019-08-21 martijn
1267 ce062d50 2019-08-21 martijn static void
1268 ce062d50 2019-08-21 martijn osmtpd_connect(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx, char *params,
1269 ce062d50 2019-08-21 martijn char *linedup)
1270 ce062d50 2019-08-21 martijn {
1271 ce062d50 2019-08-21 martijn struct sockaddr_storage ss;
1272 ce062d50 2019-08-21 martijn char *hostname;
1273 ce062d50 2019-08-21 martijn char *address;
1274 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, const char *, struct sockaddr_storage *);
1275 ce062d50 2019-08-21 martijn
1276 ce062d50 2019-08-21 martijn hostname = params;
1277 ce062d50 2019-08-21 martijn if ((address = strchr(params, '|')) == NULL)
1278 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1279 c6cb29f3 2019-08-22 martijn linedup);
1280 ce062d50 2019-08-21 martijn address++[0] = '\0';
1281 ce062d50 2019-08-21 martijn
1282 ce062d50 2019-08-21 martijn osmtpd_addrtoss(address, &ss, 0, linedup);
1283 ce062d50 2019-08-21 martijn
1284 ce062d50 2019-08-21 martijn f = cb->cb;
1285 ce062d50 2019-08-21 martijn f(ctx, hostname, &ss);
1286 ce062d50 2019-08-21 martijn }
1287 ce062d50 2019-08-21 martijn
1288 ce062d50 2019-08-21 martijn static void
1289 421c9a86 2019-09-06 martijn osmtpd_identify(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1290 6258daeb 2019-11-14 martijn char *identity, __unused char *linedup)
1291 421c9a86 2019-09-06 martijn {
1292 421c9a86 2019-09-06 martijn void (*f)(struct osmtpd_ctx *, const char *);
1293 421c9a86 2019-09-06 martijn
1294 421c9a86 2019-09-06 martijn if (cb->storereport) {
1295 421c9a86 2019-09-06 martijn free(ctx->identity);
1296 421c9a86 2019-09-06 martijn if ((ctx->identity = strdup(identity)) == NULL)
1297 421c9a86 2019-09-06 martijn osmtpd_err(1, "strdup");
1298 421c9a86 2019-09-06 martijn }
1299 421c9a86 2019-09-06 martijn
1300 421c9a86 2019-09-06 martijn f = cb->cb;
1301 421c9a86 2019-09-06 martijn f(ctx, identity);
1302 421c9a86 2019-09-06 martijn }
1303 421c9a86 2019-09-06 martijn
1304 421c9a86 2019-09-06 martijn static void
1305 ce062d50 2019-08-21 martijn osmtpd_link_connect(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1306 ce062d50 2019-08-21 martijn char *params, char *linedup)
1307 ce062d50 2019-08-21 martijn {
1308 30f1cbac 2019-08-22 martijn char *end, *rdns;
1309 30f1cbac 2019-08-22 martijn enum osmtpd_status fcrdns;
1310 ce062d50 2019-08-21 martijn struct sockaddr_storage src, dst;
1311 30f1cbac 2019-08-22 martijn void (*f)(struct osmtpd_ctx *, const char *, enum osmtpd_status,
1312 c6cb29f3 2019-08-22 martijn struct sockaddr_storage *, struct sockaddr_storage *);
1313 ce062d50 2019-08-21 martijn
1314 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1315 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing fcrdns: %s",
1316 c6cb29f3 2019-08-22 martijn linedup);
1317 ce062d50 2019-08-21 martijn end++[0] = '\0';
1318 ce062d50 2019-08-21 martijn rdns = params;
1319 ce062d50 2019-08-21 martijn params = end;
1320 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1321 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing src: %s",
1322 c6cb29f3 2019-08-22 martijn linedup);
1323 ce062d50 2019-08-21 martijn end++[0] = '\0';
1324 30f1cbac 2019-08-22 martijn if (strcmp(params, "pass") == 0)
1325 30f1cbac 2019-08-22 martijn fcrdns = OSMTPD_STATUS_OK;
1326 30f1cbac 2019-08-22 martijn else if (strcmp(params, "fail") == 0)
1327 30f1cbac 2019-08-22 martijn fcrdns = OSMTPD_STATUS_PERMFAIL;
1328 30f1cbac 2019-08-22 martijn else if (strcmp(params, "error") == 0)
1329 30f1cbac 2019-08-22 martijn fcrdns = OSMTPD_STATUS_TEMPFAIL;
1330 30f1cbac 2019-08-22 martijn else
1331 30f1cbac 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid fcrdns: %s",
1332 30f1cbac 2019-08-22 martijn linedup);
1333 ce062d50 2019-08-21 martijn params = end;
1334 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1335 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing dst: %s",
1336 c6cb29f3 2019-08-22 martijn linedup);
1337 ce062d50 2019-08-21 martijn end++[0] = '\0';
1338 ce062d50 2019-08-21 martijn osmtpd_addrtoss(params, &src, 1, linedup);
1339 ce062d50 2019-08-21 martijn params = end;
1340 ce062d50 2019-08-21 martijn osmtpd_addrtoss(params, &dst, 1, linedup);
1341 ce062d50 2019-08-21 martijn if (cb->storereport) {
1342 30f1cbac 2019-08-22 martijn if ((ctx->rdns = strdup(rdns)) == NULL)
1343 30f1cbac 2019-08-22 martijn osmtpd_err(1, "strdup");
1344 30f1cbac 2019-08-22 martijn ctx->fcrdns = fcrdns;
1345 ce062d50 2019-08-21 martijn memcpy(&(ctx->src), &src, sizeof(ctx->src));
1346 ce062d50 2019-08-21 martijn memcpy(&(ctx->dst), &dst, sizeof(ctx->dst));
1347 ce062d50 2019-08-21 martijn }
1348 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1349 ce062d50 2019-08-21 martijn f(ctx, rdns, fcrdns, &src, &dst);
1350 ce062d50 2019-08-21 martijn }
1351 ce062d50 2019-08-21 martijn
1352 ce062d50 2019-08-21 martijn static void
1353 ce062d50 2019-08-21 martijn osmtpd_link_disconnect(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1354 6258daeb 2019-11-14 martijn __unused char *param, __unused char *linedup)
1355 ce062d50 2019-08-21 martijn {
1356 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *);
1357 ce062d50 2019-08-21 martijn size_t i;
1358 ce062d50 2019-08-21 martijn struct osmtpd_session *session, search;
1359 ce062d50 2019-08-21 martijn
1360 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1361 ce062d50 2019-08-21 martijn f(ctx);
1362 ce062d50 2019-08-21 martijn
1363 ce062d50 2019-08-21 martijn search.ctx.reqid = ctx->reqid;
1364 ce062d50 2019-08-21 martijn session = RB_FIND(osmtpd_sessions, &osmtpd_sessions, &search);
1365 ce062d50 2019-08-21 martijn if (session != NULL) {
1366 ce062d50 2019-08-21 martijn RB_REMOVE(osmtpd_sessions, &osmtpd_sessions, session);
1367 912d0ff2 2019-08-22 martijn if (ondeletecb_session != NULL)
1368 912d0ff2 2019-08-22 martijn ondeletecb_session(ctx, session->ctx.local_session);
1369 ce062d50 2019-08-21 martijn free(session->ctx.rdns);
1370 0fb4c799 2019-09-05 martijn free(session->ctx.identity);
1371 0fb4c799 2019-09-05 martijn free(session->ctx.greeting.identity);
1372 ce062d50 2019-08-21 martijn free(session->ctx.ciphers);
1373 58a6bc69 2022-12-05 martijn free(session->ctx.username);
1374 ce062d50 2019-08-21 martijn free(session->ctx.mailfrom);
1375 ce062d50 2019-08-21 martijn for (i = 0; session->ctx.rcptto[i] != NULL; i++)
1376 ce062d50 2019-08-21 martijn free(session->ctx.rcptto[i]);
1377 ce062d50 2019-08-21 martijn free(session->ctx.rcptto);
1378 ce062d50 2019-08-21 martijn free(session);
1379 ce062d50 2019-08-21 martijn }
1380 ce062d50 2019-08-21 martijn }
1381 ce062d50 2019-08-21 martijn
1382 ce062d50 2019-08-21 martijn static void
1383 a05d5c54 2019-08-28 martijn osmtpd_link_greeting(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1384 6258daeb 2019-11-14 martijn char *identity, __unused char *linedup)
1385 a05d5c54 2019-08-28 martijn {
1386 a05d5c54 2019-08-28 martijn void (*f)(struct osmtpd_ctx *, const char *);
1387 a05d5c54 2019-08-28 martijn
1388 a05d5c54 2019-08-28 martijn if (cb->storereport) {
1389 421c9a86 2019-09-06 martijn free(ctx->greeting.identity);
1390 0fb4c799 2019-09-05 martijn if ((ctx->greeting.identity = strdup(identity)) == NULL)
1391 a05d5c54 2019-08-28 martijn osmtpd_err(1, NULL);
1392 a05d5c54 2019-08-28 martijn }
1393 a05d5c54 2019-08-28 martijn
1394 a05d5c54 2019-08-28 martijn if ((f = cb->cb) != NULL)
1395 a05d5c54 2019-08-28 martijn f(ctx, identity);
1396 a05d5c54 2019-08-28 martijn }
1397 a05d5c54 2019-08-28 martijn
1398 a05d5c54 2019-08-28 martijn static void
1399 ce062d50 2019-08-21 martijn osmtpd_link_identify(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1400 6258daeb 2019-11-14 martijn char *identity, __unused char *linedup)
1401 ce062d50 2019-08-21 martijn {
1402 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, const char *);
1403 ce062d50 2019-08-21 martijn
1404 ce062d50 2019-08-21 martijn if (cb->storereport) {
1405 421c9a86 2019-09-06 martijn free(ctx->identity);
1406 0fb4c799 2019-09-05 martijn if ((ctx->identity = strdup(identity)) == NULL)
1407 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1408 ce062d50 2019-08-21 martijn }
1409 ce062d50 2019-08-21 martijn
1410 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1411 ce062d50 2019-08-21 martijn f(ctx, identity);
1412 ce062d50 2019-08-21 martijn }
1413 ce062d50 2019-08-21 martijn
1414 ce062d50 2019-08-21 martijn static void
1415 ce062d50 2019-08-21 martijn osmtpd_link_tls(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1416 6258daeb 2019-11-14 martijn char *ciphers, __unused char *linedup)
1417 ce062d50 2019-08-21 martijn {
1418 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, const char *);
1419 ce062d50 2019-08-21 martijn
1420 ce062d50 2019-08-21 martijn if (cb->storereport) {
1421 ce062d50 2019-08-21 martijn if ((ctx->ciphers = strdup(ciphers)) == NULL)
1422 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1423 ce062d50 2019-08-21 martijn }
1424 ce062d50 2019-08-21 martijn
1425 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1426 ce062d50 2019-08-21 martijn f(ctx, ciphers);
1427 ce062d50 2019-08-21 martijn }
1428 ce062d50 2019-08-21 martijn
1429 ce062d50 2019-08-21 martijn static void
1430 58a6bc69 2022-12-05 martijn osmtpd_link_auth(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1431 58a6bc69 2022-12-05 martijn char *username, char *linedup)
1432 58a6bc69 2022-12-05 martijn {
1433 58a6bc69 2022-12-05 martijn void (*f)(struct osmtpd_ctx *, const char *, enum osmtpd_auth_status);
1434 58a6bc69 2022-12-05 martijn char *status;
1435 58a6bc69 2022-12-05 martijn enum osmtpd_auth_status s;
1436 58a6bc69 2022-12-05 martijn
1437 58a6bc69 2022-12-05 martijn if ((status = strrchr(username, '|')) == NULL)
1438 58a6bc69 2022-12-05 martijn osmtpd_errx(1, "Invalid auth received: %s", linedup);
1439 58a6bc69 2022-12-05 martijn status[0] = '\0';
1440 58a6bc69 2022-12-05 martijn status++;
1441 58a6bc69 2022-12-05 martijn if (strcmp(status, "pass") == 0)
1442 58a6bc69 2022-12-05 martijn s = OSMTPD_AUTH_PASS;
1443 58a6bc69 2022-12-05 martijn else if (strcmp(status, "fail") == 0)
1444 58a6bc69 2022-12-05 martijn s = OSMTPD_AUTH_FAIL;
1445 58a6bc69 2022-12-05 martijn else if (strcmp(status, "error") == 0)
1446 58a6bc69 2022-12-05 martijn s = OSMTPD_AUTH_ERROR;
1447 58a6bc69 2022-12-05 martijn else
1448 58a6bc69 2022-12-05 martijn osmtpd_errx(1, "Invalid auth status received: %s", linedup);
1449 58a6bc69 2022-12-05 martijn
1450 58a6bc69 2022-12-05 martijn if (cb->storereport && s == OSMTPD_AUTH_PASS) {
1451 58a6bc69 2022-12-05 martijn if ((ctx->username = strdup(username)) == NULL)
1452 58a6bc69 2022-12-05 martijn osmtpd_err(1, NULL);
1453 58a6bc69 2022-12-05 martijn }
1454 58a6bc69 2022-12-05 martijn
1455 58a6bc69 2022-12-05 martijn if ((f = cb->cb) != NULL)
1456 58a6bc69 2022-12-05 martijn f(ctx, username, s);
1457 58a6bc69 2022-12-05 martijn }
1458 58a6bc69 2022-12-05 martijn
1459 58a6bc69 2022-12-05 martijn static void
1460 ce062d50 2019-08-21 martijn osmtpd_tx_begin(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1461 ce062d50 2019-08-21 martijn char *msgid, char *linedup)
1462 ce062d50 2019-08-21 martijn {
1463 ce062d50 2019-08-21 martijn unsigned long imsgid;
1464 ce062d50 2019-08-21 martijn char *endptr;
1465 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t);
1466 ce062d50 2019-08-21 martijn
1467 ce062d50 2019-08-21 martijn errno = 0;
1468 ce062d50 2019-08-21 martijn imsgid = strtoul(msgid, &endptr, 16);
1469 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0) || endptr[0] != '\0')
1470 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1471 c6cb29f3 2019-08-22 martijn linedup);
1472 ce062d50 2019-08-21 martijn ctx->msgid = imsgid;
1473 ce062d50 2019-08-21 martijn /* Check if we're in range */
1474 ce062d50 2019-08-21 martijn if ((unsigned long) ctx->msgid != imsgid)
1475 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1476 c6cb29f3 2019-08-22 martijn linedup);
1477 ce062d50 2019-08-21 martijn
1478 ce062d50 2019-08-21 martijn if (!cb->storereport)
1479 ce062d50 2019-08-21 martijn ctx->msgid = 0;
1480 ce062d50 2019-08-21 martijn
1481 912d0ff2 2019-08-22 martijn if (oncreatecb_message != NULL)
1482 912d0ff2 2019-08-22 martijn ctx->local_message = oncreatecb_message(ctx);
1483 912d0ff2 2019-08-22 martijn
1484 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1485 ce062d50 2019-08-21 martijn f(ctx, imsgid);
1486 ce062d50 2019-08-21 martijn }
1487 ce062d50 2019-08-21 martijn
1488 ce062d50 2019-08-21 martijn static void
1489 ce062d50 2019-08-21 martijn osmtpd_tx_mail(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1490 ce062d50 2019-08-21 martijn char *params, char *linedup)
1491 ce062d50 2019-08-21 martijn {
1492 ce062d50 2019-08-21 martijn char *end, *mailfrom;
1493 53b354a9 2020-04-12 martijn enum osmtpd_status status;
1494 ce062d50 2019-08-21 martijn unsigned long imsgid;
1495 ce062d50 2019-08-21 martijn uint32_t msgid;
1496 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t, const char *,
1497 ce062d50 2019-08-21 martijn enum osmtpd_status);
1498 ce062d50 2019-08-21 martijn
1499 ce062d50 2019-08-21 martijn errno = 0;
1500 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1501 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1502 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1503 c6cb29f3 2019-08-22 martijn linedup);
1504 ce062d50 2019-08-21 martijn if (end[0] != '|')
1505 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1506 c6cb29f3 2019-08-22 martijn linedup);
1507 ce062d50 2019-08-21 martijn msgid = imsgid;
1508 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1509 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1510 c6cb29f3 2019-08-22 martijn linedup);
1511 ce062d50 2019-08-21 martijn params = end + 1;
1512 ce062d50 2019-08-21 martijn
1513 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1514 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing status: %s",
1515 c6cb29f3 2019-08-22 martijn linedup);
1516 ce062d50 2019-08-21 martijn end++[0] = '\0';
1517 53b354a9 2020-04-12 martijn if (ctx->version_major == 0 && ctx->version_minor < 6) {
1518 53b354a9 2020-04-12 martijn mailfrom = params;
1519 53b354a9 2020-04-12 martijn status = osmtpd_strtostatus(end, linedup);
1520 53b354a9 2020-04-12 martijn } else {
1521 53b354a9 2020-04-12 martijn mailfrom = end;
1522 53b354a9 2020-04-12 martijn status = osmtpd_strtostatus(params, linedup);
1523 53b354a9 2020-04-12 martijn }
1524 ce062d50 2019-08-21 martijn if (cb->storereport) {
1525 ce062d50 2019-08-21 martijn if ((ctx->mailfrom = strdup(mailfrom)) == NULL)
1526 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1527 ce062d50 2019-08-21 martijn }
1528 ce062d50 2019-08-21 martijn
1529 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1530 53b354a9 2020-04-12 martijn f(ctx, msgid, mailfrom, status);
1531 ce062d50 2019-08-21 martijn }
1532 ce062d50 2019-08-21 martijn
1533 ce062d50 2019-08-21 martijn static void
1534 ce062d50 2019-08-21 martijn osmtpd_tx_rcpt(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1535 ce062d50 2019-08-21 martijn char *params, char *linedup)
1536 ce062d50 2019-08-21 martijn {
1537 ce062d50 2019-08-21 martijn char *end, *rcptto;
1538 53b354a9 2020-04-12 martijn enum osmtpd_status status;
1539 ce062d50 2019-08-21 martijn unsigned long imsgid;
1540 ce062d50 2019-08-21 martijn uint32_t msgid;
1541 ce062d50 2019-08-21 martijn size_t i;
1542 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t, const char *,
1543 ce062d50 2019-08-21 martijn enum osmtpd_status);
1544 ce062d50 2019-08-21 martijn
1545 ce062d50 2019-08-21 martijn errno = 0;
1546 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1547 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1548 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1549 c6cb29f3 2019-08-22 martijn linedup);
1550 ce062d50 2019-08-21 martijn if (end[0] != '|')
1551 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1552 c6cb29f3 2019-08-22 martijn linedup);
1553 ce062d50 2019-08-21 martijn msgid = imsgid;
1554 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1555 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1556 c6cb29f3 2019-08-22 martijn linedup);
1557 ce062d50 2019-08-21 martijn params = end + 1;
1558 ce062d50 2019-08-21 martijn
1559 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1560 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing status: %s",
1561 c6cb29f3 2019-08-22 martijn linedup);
1562 ce062d50 2019-08-21 martijn end++[0] = '\0';
1563 ce062d50 2019-08-21 martijn
1564 53b354a9 2020-04-12 martijn if (ctx->version_major == 0 && ctx->version_minor < 6) {
1565 53b354a9 2020-04-12 martijn rcptto = params;
1566 53b354a9 2020-04-12 martijn status = osmtpd_strtostatus(end, linedup);
1567 53b354a9 2020-04-12 martijn } else {
1568 53b354a9 2020-04-12 martijn rcptto = end;
1569 53b354a9 2020-04-12 martijn status = osmtpd_strtostatus(params, linedup);
1570 53b354a9 2020-04-12 martijn }
1571 ce062d50 2019-08-21 martijn
1572 ce062d50 2019-08-21 martijn if (cb->storereport) {
1573 ce062d50 2019-08-21 martijn for (i = 0; ctx->rcptto[i] != NULL; i++)
1574 ce062d50 2019-08-21 martijn ;
1575 ce062d50 2019-08-21 martijn ctx->rcptto = reallocarray(ctx->rcptto, i + 2,
1576 ce062d50 2019-08-21 martijn sizeof(*(ctx->rcptto)));
1577 ce062d50 2019-08-21 martijn if (ctx->rcptto == NULL)
1578 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1579 ce062d50 2019-08-21 martijn
1580 ce062d50 2019-08-21 martijn if ((ctx->rcptto[i] = strdup(rcptto)) == NULL)
1581 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1582 ce062d50 2019-08-21 martijn ctx->rcptto[i + 1] = NULL;
1583 ce062d50 2019-08-21 martijn }
1584 ce062d50 2019-08-21 martijn
1585 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1586 53b354a9 2020-04-12 martijn f(ctx, msgid, rcptto, status);
1587 ce062d50 2019-08-21 martijn }
1588 ce062d50 2019-08-21 martijn
1589 ce062d50 2019-08-21 martijn static void
1590 ce062d50 2019-08-21 martijn osmtpd_tx_envelope(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1591 ce062d50 2019-08-21 martijn char *params, char *linedup)
1592 ce062d50 2019-08-21 martijn {
1593 ce062d50 2019-08-21 martijn unsigned long imsgid;
1594 ce062d50 2019-08-21 martijn uint32_t msgid;
1595 ce062d50 2019-08-21 martijn uint64_t evpid;
1596 ce062d50 2019-08-21 martijn char *end;
1597 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t, uint64_t);
1598 ce062d50 2019-08-21 martijn
1599 ce062d50 2019-08-21 martijn errno = 0;
1600 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1601 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1602 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1603 c6cb29f3 2019-08-22 martijn linedup);
1604 ce062d50 2019-08-21 martijn if (end[0] != '|')
1605 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1606 c6cb29f3 2019-08-22 martijn linedup);
1607 ce062d50 2019-08-21 martijn msgid = imsgid;
1608 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1609 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1610 c6cb29f3 2019-08-22 martijn linedup);
1611 ce062d50 2019-08-21 martijn params = end + 1;
1612 ce062d50 2019-08-21 martijn
1613 ce062d50 2019-08-21 martijn evpid = strtoull(params, &end, 16);
1614 c6cb29f3 2019-08-22 martijn if ((ctx->evpid == ULLONG_MAX && errno != 0) ||
1615 ce062d50 2019-08-21 martijn end[0] != '\0')
1616 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid evpid: %s",
1617 c6cb29f3 2019-08-22 martijn linedup);
1618 ce062d50 2019-08-21 martijn if (cb->storereport)
1619 ce062d50 2019-08-21 martijn ctx->evpid = evpid;
1620 ce062d50 2019-08-21 martijn
1621 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1622 ce062d50 2019-08-21 martijn f(ctx, msgid, evpid);
1623 ce062d50 2019-08-21 martijn }
1624 ce062d50 2019-08-21 martijn
1625 ce062d50 2019-08-21 martijn static void
1626 ce062d50 2019-08-21 martijn osmtpd_tx_data(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1627 ce062d50 2019-08-21 martijn char *params, char *linedup)
1628 ce062d50 2019-08-21 martijn {
1629 ce062d50 2019-08-21 martijn char *end;
1630 ce062d50 2019-08-21 martijn unsigned long imsgid;
1631 ce062d50 2019-08-21 martijn uint32_t msgid;
1632 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t, enum osmtpd_status);
1633 ce062d50 2019-08-21 martijn
1634 ce062d50 2019-08-21 martijn errno = 0;
1635 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1636 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1637 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1638 c6cb29f3 2019-08-22 martijn linedup);
1639 ce062d50 2019-08-21 martijn if (end[0] != '|')
1640 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1641 c6cb29f3 2019-08-22 martijn linedup);
1642 ce062d50 2019-08-21 martijn msgid = imsgid;
1643 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1644 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1645 c6cb29f3 2019-08-22 martijn linedup);
1646 ce062d50 2019-08-21 martijn params = end + 1;
1647 ce062d50 2019-08-21 martijn
1648 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1649 ce062d50 2019-08-21 martijn f(ctx, msgid, osmtpd_strtostatus(params, linedup));
1650 ce062d50 2019-08-21 martijn }
1651 ce062d50 2019-08-21 martijn
1652 ce062d50 2019-08-21 martijn static void
1653 ce062d50 2019-08-21 martijn osmtpd_tx_commit(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1654 ce062d50 2019-08-21 martijn char *params, char *linedup)
1655 ce062d50 2019-08-21 martijn {
1656 ce062d50 2019-08-21 martijn char *end;
1657 332b3141 2019-08-22 martijn const char *errstr = NULL;
1658 ce062d50 2019-08-21 martijn unsigned long imsgid;
1659 ce062d50 2019-08-21 martijn uint32_t msgid;
1660 ce062d50 2019-08-21 martijn size_t i, msgsz;
1661 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t, size_t);
1662 ce062d50 2019-08-21 martijn
1663 ce062d50 2019-08-21 martijn errno = 0;
1664 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1665 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1666 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1667 c6cb29f3 2019-08-22 martijn linedup);
1668 ce062d50 2019-08-21 martijn if (end[0] != '|')
1669 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1670 c6cb29f3 2019-08-22 martijn linedup);
1671 ce062d50 2019-08-21 martijn msgid = imsgid;
1672 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1673 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1674 c6cb29f3 2019-08-22 martijn linedup);
1675 ce062d50 2019-08-21 martijn params = end + 1;
1676 ce062d50 2019-08-21 martijn
1677 332b3141 2019-08-22 martijn msgsz = strtonum(params, 0, UINT32_MAX, &errstr);
1678 ce062d50 2019-08-21 martijn if (errstr != NULL)
1679 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msg size: %s",
1680 c6cb29f3 2019-08-22 martijn linedup);
1681 ce062d50 2019-08-21 martijn
1682 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1683 ce062d50 2019-08-21 martijn f(ctx, msgid, msgsz);
1684 912d0ff2 2019-08-22 martijn
1685 912d0ff2 2019-08-22 martijn if (ondeletecb_message != NULL) {
1686 912d0ff2 2019-08-22 martijn ondeletecb_message(ctx, ctx->local_message);
1687 912d0ff2 2019-08-22 martijn ctx->local_message = NULL;
1688 912d0ff2 2019-08-22 martijn }
1689 912d0ff2 2019-08-22 martijn
1690 912d0ff2 2019-08-22 martijn free(ctx->mailfrom);
1691 912d0ff2 2019-08-22 martijn ctx->mailfrom = NULL;
1692 912d0ff2 2019-08-22 martijn
1693 912d0ff2 2019-08-22 martijn for (i = 0; ctx->rcptto[i] != NULL; i++)
1694 912d0ff2 2019-08-22 martijn free(ctx->rcptto[i]);
1695 912d0ff2 2019-08-22 martijn ctx->rcptto[0] = NULL;
1696 912d0ff2 2019-08-22 martijn ctx->evpid = 0;
1697 912d0ff2 2019-08-22 martijn ctx->msgid = 0;
1698 ce062d50 2019-08-21 martijn }
1699 ce062d50 2019-08-21 martijn
1700 ce062d50 2019-08-21 martijn static void
1701 ce062d50 2019-08-21 martijn osmtpd_tx_rollback(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1702 ce062d50 2019-08-21 martijn char *params, char *linedup)
1703 ce062d50 2019-08-21 martijn {
1704 ce062d50 2019-08-21 martijn char *end;
1705 ce062d50 2019-08-21 martijn unsigned long imsgid;
1706 ce062d50 2019-08-21 martijn uint32_t msgid;
1707 ce062d50 2019-08-21 martijn size_t i;
1708 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t);
1709 ce062d50 2019-08-21 martijn
1710 ce062d50 2019-08-21 martijn errno = 0;
1711 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1712 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1713 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1714 c6cb29f3 2019-08-22 martijn linedup);
1715 ce062d50 2019-08-21 martijn if (end[0] != '\0')
1716 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1717 c6cb29f3 2019-08-22 martijn linedup);
1718 ce062d50 2019-08-21 martijn msgid = imsgid;
1719 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1720 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1721 c6cb29f3 2019-08-22 martijn linedup);
1722 ce062d50 2019-08-21 martijn
1723 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1724 ce062d50 2019-08-21 martijn f(ctx, msgid);
1725 ce062d50 2019-08-21 martijn
1726 912d0ff2 2019-08-22 martijn if (ondeletecb_message != NULL) {
1727 912d0ff2 2019-08-22 martijn ondeletecb_message(ctx, ctx->local_message);
1728 912d0ff2 2019-08-22 martijn ctx->local_message = NULL;
1729 912d0ff2 2019-08-22 martijn }
1730 912d0ff2 2019-08-22 martijn
1731 ce062d50 2019-08-21 martijn free(ctx->mailfrom);
1732 ce062d50 2019-08-21 martijn ctx->mailfrom = NULL;
1733 ce062d50 2019-08-21 martijn
1734 ce062d50 2019-08-21 martijn for (i = 0; ctx->rcptto[i] != NULL; i++)
1735 ce062d50 2019-08-21 martijn free(ctx->rcptto[i]);
1736 ce062d50 2019-08-21 martijn ctx->rcptto[0] = NULL;
1737 ce062d50 2019-08-21 martijn ctx->evpid = 0;
1738 ce062d50 2019-08-21 martijn ctx->msgid = 0;
1739 ce062d50 2019-08-21 martijn }
1740 ce062d50 2019-08-21 martijn
1741 ce062d50 2019-08-21 martijn void
1742 ce062d50 2019-08-21 martijn osmtpd_filter_proceed(struct osmtpd_ctx *ctx)
1743 ce062d50 2019-08-21 martijn {
1744 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1745 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1746 06220a70 2019-12-06 martijn "proceed\n", ctx->token, ctx->reqid);
1747 06220a70 2019-12-06 martijn else
1748 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1749 06220a70 2019-12-06 martijn "proceed\n", ctx->reqid, ctx->token);
1750 ce062d50 2019-08-21 martijn }
1751 ce062d50 2019-08-21 martijn
1752 ce062d50 2019-08-21 martijn void
1753 ce062d50 2019-08-21 martijn osmtpd_filter_reject(struct osmtpd_ctx *ctx, int code, const char *reason, ...)
1754 ce062d50 2019-08-21 martijn {
1755 ce062d50 2019-08-21 martijn va_list ap;
1756 ce062d50 2019-08-21 martijn
1757 ce062d50 2019-08-21 martijn if (code < 200 || code > 599)
1758 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid reject code");
1759 ce062d50 2019-08-21 martijn
1760 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1761 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1762 06220a70 2019-12-06 martijn "reject|%d ", ctx->token, ctx->reqid, code);
1763 06220a70 2019-12-06 martijn else
1764 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1765 06220a70 2019-12-06 martijn "reject|%d ", ctx->reqid, ctx->token, code);
1766 ce062d50 2019-08-21 martijn va_start(ap, reason);
1767 ce062d50 2019-08-21 martijn io_vprintf(io_stdout, reason, ap);
1768 ce062d50 2019-08-21 martijn va_end(ap);
1769 ce062d50 2019-08-21 martijn io_printf(io_stdout, "\n");
1770 ce062d50 2019-08-21 martijn }
1771 ce062d50 2019-08-21 martijn
1772 ce062d50 2019-08-21 martijn void
1773 000aebbc 2019-08-23 martijn osmtpd_filter_reject_enh(struct osmtpd_ctx *ctx, int code, int class,
1774 000aebbc 2019-08-23 martijn int subject, int detail, const char *reason, ...)
1775 000aebbc 2019-08-23 martijn {
1776 000aebbc 2019-08-23 martijn va_list ap;
1777 000aebbc 2019-08-23 martijn
1778 000aebbc 2019-08-23 martijn if (code < 200 || code > 599)
1779 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid reject code");
1780 2a3d7bdf 2019-08-27 martijn if (class < 2 || class > 5)
1781 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid enhanced status class");
1782 000aebbc 2019-08-23 martijn if (subject < 0 || subject > 999)
1783 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid enhanced status subject");
1784 000aebbc 2019-08-23 martijn if (detail < 0 || detail > 999)
1785 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid enhanced status detail");
1786 000aebbc 2019-08-23 martijn
1787 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1788 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1789 06220a70 2019-12-06 martijn "reject|%d %d.%d.%d ", ctx->token, ctx->reqid, code, class,
1790 06220a70 2019-12-06 martijn subject, detail);
1791 06220a70 2019-12-06 martijn else
1792 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1793 06220a70 2019-12-06 martijn "reject|%d %d.%d.%d ", ctx->reqid, ctx->token, code, class,
1794 06220a70 2019-12-06 martijn subject, detail);
1795 000aebbc 2019-08-23 martijn va_start(ap, reason);
1796 000aebbc 2019-08-23 martijn io_vprintf(io_stdout, reason, ap);
1797 000aebbc 2019-08-23 martijn va_end(ap);
1798 000aebbc 2019-08-23 martijn io_printf(io_stdout, "\n");
1799 000aebbc 2019-08-23 martijn }
1800 000aebbc 2019-08-23 martijn
1801 000aebbc 2019-08-23 martijn void
1802 ce062d50 2019-08-21 martijn osmtpd_filter_disconnect(struct osmtpd_ctx *ctx, const char *reason, ...)
1803 ce062d50 2019-08-21 martijn {
1804 ce062d50 2019-08-21 martijn va_list ap;
1805 ce062d50 2019-08-21 martijn
1806 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1807 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1808 06220a70 2019-12-06 martijn "disconnect|421 ", ctx->token, ctx->reqid);
1809 06220a70 2019-12-06 martijn else
1810 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1811 06220a70 2019-12-06 martijn "disconnect|421 ", ctx->reqid, ctx->token);
1812 ce062d50 2019-08-21 martijn va_start(ap, reason);
1813 ce062d50 2019-08-21 martijn io_vprintf(io_stdout, reason, ap);
1814 ce062d50 2019-08-21 martijn va_end(ap);
1815 ce062d50 2019-08-21 martijn io_printf(io_stdout, "\n");
1816 ce062d50 2019-08-21 martijn }
1817 ce062d50 2019-08-21 martijn
1818 ce062d50 2019-08-21 martijn void
1819 000aebbc 2019-08-23 martijn osmtpd_filter_disconnect_enh(struct osmtpd_ctx *ctx, int class, int subject,
1820 000aebbc 2019-08-23 martijn int detail, const char *reason, ...)
1821 000aebbc 2019-08-23 martijn {
1822 000aebbc 2019-08-23 martijn va_list ap;
1823 000aebbc 2019-08-23 martijn
1824 000aebbc 2019-08-23 martijn if (class <= 2 || class >= 5)
1825 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid enhanced status class");
1826 000aebbc 2019-08-23 martijn if (subject < 0 || subject > 999)
1827 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid enhanced status subject");
1828 000aebbc 2019-08-23 martijn if (detail < 0 || detail > 999)
1829 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid enhanced status detail");
1830 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1831 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1832 06220a70 2019-12-06 martijn "disconnect|421 %d.%d.%d ", ctx->token, ctx->reqid, class,
1833 06220a70 2019-12-06 martijn subject, detail);
1834 06220a70 2019-12-06 martijn else
1835 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1836 06220a70 2019-12-06 martijn "disconnect|421 %d.%d.%d ", ctx->reqid, ctx->token, class,
1837 06220a70 2019-12-06 martijn subject, detail);
1838 000aebbc 2019-08-23 martijn va_start(ap, reason);
1839 000aebbc 2019-08-23 martijn io_vprintf(io_stdout, reason, ap);
1840 000aebbc 2019-08-23 martijn va_end(ap);
1841 000aebbc 2019-08-23 martijn io_printf(io_stdout, "\n");
1842 000aebbc 2019-08-23 martijn }
1843 000aebbc 2019-08-23 martijn
1844 000aebbc 2019-08-23 martijn void
1845 4fb72612 2019-08-21 martijn osmtpd_filter_rewrite(struct osmtpd_ctx *ctx, const char *value, ...)
1846 4fb72612 2019-08-21 martijn {
1847 4fb72612 2019-08-21 martijn va_list ap;
1848 4fb72612 2019-08-21 martijn
1849 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1850 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1851 06220a70 2019-12-06 martijn "rewrite|", ctx->token, ctx->reqid);
1852 06220a70 2019-12-06 martijn else
1853 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1854 06220a70 2019-12-06 martijn "rewrite|", ctx->reqid, ctx->token);
1855 4fb72612 2019-08-21 martijn va_start(ap, value);
1856 4fb72612 2019-08-21 martijn io_vprintf(io_stdout, value, ap);
1857 4fb72612 2019-08-21 martijn va_end(ap);
1858 4fb72612 2019-08-21 martijn io_printf(io_stdout, "\n");
1859 4fb72612 2019-08-21 martijn }
1860 4fb72612 2019-08-21 martijn
1861 4fb72612 2019-08-21 martijn void
1862 ce062d50 2019-08-21 martijn osmtpd_filter_dataline(struct osmtpd_ctx *ctx, const char *line, ...)
1863 ce062d50 2019-08-21 martijn {
1864 ce062d50 2019-08-21 martijn va_list ap;
1865 ce062d50 2019-08-21 martijn
1866 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1867 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-dataline|%016"PRIx64"|%016"PRIx64"|",
1868 06220a70 2019-12-06 martijn ctx->token, ctx->reqid);
1869 06220a70 2019-12-06 martijn else
1870 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-dataline|%016"PRIx64"|%016"PRIx64"|",
1871 06220a70 2019-12-06 martijn ctx->reqid, ctx->token);
1872 ce062d50 2019-08-21 martijn va_start(ap, line);
1873 ce062d50 2019-08-21 martijn io_vprintf(io_stdout, line, ap);
1874 ce062d50 2019-08-21 martijn va_end(ap);
1875 ce062d50 2019-08-21 martijn io_printf(io_stdout, "\n");
1876 ce062d50 2019-08-21 martijn }
1877 ce062d50 2019-08-21 martijn
1878 ce062d50 2019-08-21 martijn static void
1879 ce062d50 2019-08-21 martijn osmtpd_register(enum osmtpd_type type, enum osmtpd_phase phase, int incoming,
1880 ce062d50 2019-08-21 martijn int storereport, void *cb)
1881 ce062d50 2019-08-21 martijn {
1882 ce062d50 2019-08-21 martijn size_t i;
1883 ce062d50 2019-08-21 martijn
1884 ce062d50 2019-08-21 martijn if (ready)
1885 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Can't register when proc is running");
1886 ce062d50 2019-08-21 martijn
1887 ce062d50 2019-08-21 martijn for (i = 0; i < NITEMS(osmtpd_callbacks); i++) {
1888 ce062d50 2019-08-21 martijn if (type == osmtpd_callbacks[i].type &&
1889 ce062d50 2019-08-21 martijn phase == osmtpd_callbacks[i].phase &&
1890 ce062d50 2019-08-21 martijn incoming == osmtpd_callbacks[i].incoming) {
1891 ce062d50 2019-08-21 martijn if (osmtpd_callbacks[i].cb != NULL && cb != NULL)
1892 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Event already registered");
1893 912d0ff2 2019-08-22 martijn if (cb != NULL)
1894 912d0ff2 2019-08-22 martijn osmtpd_callbacks[i].cb = cb;
1895 ce062d50 2019-08-21 martijn osmtpd_callbacks[i].doregister = 1;
1896 ce062d50 2019-08-21 martijn if (storereport)
1897 ce062d50 2019-08-21 martijn osmtpd_callbacks[i].storereport = 1;
1898 ce062d50 2019-08-21 martijn return;
1899 ce062d50 2019-08-21 martijn }
1900 ce062d50 2019-08-21 martijn }
1901 ce062d50 2019-08-21 martijn /* NOT REACHED */
1902 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Trying to register unknown event");
1903 ce062d50 2019-08-21 martijn }
1904 ce062d50 2019-08-21 martijn
1905 ce062d50 2019-08-21 martijn static enum osmtpd_phase
1906 ce062d50 2019-08-21 martijn osmtpd_strtophase(const char *phase, const char *linedup)
1907 ce062d50 2019-08-21 martijn {
1908 ce062d50 2019-08-21 martijn if (strcmp(phase, "connect") == 0)
1909 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_CONNECT;
1910 ce062d50 2019-08-21 martijn if (strcmp(phase, "helo") == 0)
1911 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_HELO;
1912 ce062d50 2019-08-21 martijn if (strcmp(phase, "ehlo") == 0)
1913 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_EHLO;
1914 ce062d50 2019-08-21 martijn if (strcmp(phase, "starttls") == 0)
1915 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_STARTTLS;
1916 ce062d50 2019-08-21 martijn if (strcmp(phase, "auth") == 0)
1917 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_AUTH;
1918 ce062d50 2019-08-21 martijn if (strcmp(phase, "mail-from") == 0)
1919 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_MAIL_FROM;
1920 ce062d50 2019-08-21 martijn if (strcmp(phase, "rcpt-to") == 0)
1921 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_RCPT_TO;
1922 ce062d50 2019-08-21 martijn if (strcmp(phase, "data") == 0)
1923 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_DATA;
1924 ce062d50 2019-08-21 martijn if (strcmp(phase, "data-line") == 0)
1925 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_DATA_LINE;
1926 ce062d50 2019-08-21 martijn if (strcmp(phase, "rset") == 0)
1927 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_RSET;
1928 ce062d50 2019-08-21 martijn if (strcmp(phase, "quit") == 0)
1929 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_QUIT;
1930 ce062d50 2019-08-21 martijn if (strcmp(phase, "noop") == 0)
1931 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_NOOP;
1932 ce062d50 2019-08-21 martijn if (strcmp(phase, "help") == 0)
1933 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_HELP;
1934 ce062d50 2019-08-21 martijn if (strcmp(phase, "wiz") == 0)
1935 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_WIZ;
1936 ce062d50 2019-08-21 martijn if (strcmp(phase, "commit") == 0)
1937 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_COMMIT;
1938 ce062d50 2019-08-21 martijn if (strcmp(phase, "link-connect") == 0)
1939 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_LINK_CONNECT;
1940 ce062d50 2019-08-21 martijn if (strcmp(phase, "link-disconnect") == 0)
1941 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_LINK_DISCONNECT;
1942 b52f2785 2019-09-06 martijn if (strcmp(phase, "link-greeting") == 0)
1943 b52f2785 2019-09-06 martijn return OSMTPD_PHASE_LINK_GREETING;
1944 ce062d50 2019-08-21 martijn if (strcmp(phase, "link-identify") == 0)
1945 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_LINK_IDENTIFY;
1946 ce062d50 2019-08-21 martijn if (strcmp(phase, "link-tls") == 0)
1947 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_LINK_TLS;
1948 58a6bc69 2022-12-05 martijn if (strcmp(phase, "link-auth") == 0)
1949 58a6bc69 2022-12-05 martijn return OSMTPD_PHASE_LINK_AUTH;
1950 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-begin") == 0)
1951 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_BEGIN;
1952 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-mail") == 0)
1953 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_MAIL;
1954 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-rcpt") == 0)
1955 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_RCPT;
1956 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-envelope") == 0)
1957 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_ENVELOPE;
1958 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-data") == 0)
1959 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_DATA;
1960 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-commit") == 0)
1961 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_COMMIT;
1962 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-rollback") == 0)
1963 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_ROLLBACK;
1964 ce062d50 2019-08-21 martijn if (strcmp(phase, "protocol-client") == 0)
1965 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_PROTOCOL_CLIENT;
1966 ce062d50 2019-08-21 martijn if (strcmp(phase, "protocol-server") == 0)
1967 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_PROTOCOL_SERVER;
1968 ce062d50 2019-08-21 martijn if (strcmp(phase, "filter-response") == 0)
1969 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_FILTER_RESPONSE;
1970 ce062d50 2019-08-21 martijn if (strcmp(phase, "timeout") == 0)
1971 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TIMEOUT;
1972 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid phase: %s", linedup);
1973 ce062d50 2019-08-21 martijn }
1974 ce062d50 2019-08-21 martijn
1975 ce062d50 2019-08-21 martijn static const char *
1976 ce062d50 2019-08-21 martijn osmtpd_typetostr(enum osmtpd_type type)
1977 ce062d50 2019-08-21 martijn {
1978 ce062d50 2019-08-21 martijn switch (type) {
1979 ce062d50 2019-08-21 martijn case OSMTPD_TYPE_FILTER:
1980 ce062d50 2019-08-21 martijn return "filter";
1981 ce062d50 2019-08-21 martijn case OSMTPD_TYPE_REPORT:
1982 ce062d50 2019-08-21 martijn return "report";
1983 ce062d50 2019-08-21 martijn }
1984 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "In valid type: %d\n", type);
1985 ce062d50 2019-08-21 martijn }
1986 ce062d50 2019-08-21 martijn
1987 ce062d50 2019-08-21 martijn static const char *
1988 ce062d50 2019-08-21 martijn osmtpd_phasetostr(enum osmtpd_phase phase)
1989 ce062d50 2019-08-21 martijn {
1990 ce062d50 2019-08-21 martijn switch (phase) {
1991 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_CONNECT:
1992 ce062d50 2019-08-21 martijn return "connect";
1993 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_HELO:
1994 ce062d50 2019-08-21 martijn return "helo";
1995 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_EHLO:
1996 ce062d50 2019-08-21 martijn return "ehlo";
1997 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_STARTTLS:
1998 ce062d50 2019-08-21 martijn return "starttls";
1999 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_AUTH:
2000 ce062d50 2019-08-21 martijn return "auth";
2001 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_MAIL_FROM:
2002 ce062d50 2019-08-21 martijn return "mail-from";
2003 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_RCPT_TO:
2004 ce062d50 2019-08-21 martijn return "rcpt-to";
2005 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_DATA:
2006 ce062d50 2019-08-21 martijn return "data";
2007 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_DATA_LINE:
2008 ce062d50 2019-08-21 martijn return "data-line";
2009 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_RSET:
2010 ce062d50 2019-08-21 martijn return "rset";
2011 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_QUIT:
2012 ce062d50 2019-08-21 martijn return "quit";
2013 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_NOOP:
2014 ce062d50 2019-08-21 martijn return "noop";
2015 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_HELP:
2016 ce062d50 2019-08-21 martijn return "help";
2017 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_WIZ:
2018 ce062d50 2019-08-21 martijn return "wiz";
2019 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_COMMIT:
2020 ce062d50 2019-08-21 martijn return "commit";
2021 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_LINK_CONNECT:
2022 ce062d50 2019-08-21 martijn return "link-connect";
2023 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_LINK_DISCONNECT:
2024 ce062d50 2019-08-21 martijn return "link-disconnect";
2025 a05d5c54 2019-08-28 martijn case OSMTPD_PHASE_LINK_GREETING:
2026 a05d5c54 2019-08-28 martijn return "link-greeting";
2027 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_LINK_IDENTIFY:
2028 ce062d50 2019-08-21 martijn return "link-identify";
2029 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_LINK_TLS:
2030 ce062d50 2019-08-21 martijn return "link-tls";
2031 58a6bc69 2022-12-05 martijn case OSMTPD_PHASE_LINK_AUTH:
2032 58a6bc69 2022-12-05 martijn return "link-auth";
2033 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_BEGIN:
2034 ce062d50 2019-08-21 martijn return "tx-begin";
2035 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_MAIL:
2036 ce062d50 2019-08-21 martijn return "tx-mail";
2037 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_RCPT:
2038 ce062d50 2019-08-21 martijn return "tx-rcpt";
2039 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_ENVELOPE:
2040 ce062d50 2019-08-21 martijn return "tx-envelope";
2041 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_DATA:
2042 ce062d50 2019-08-21 martijn return "tx-data";
2043 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_COMMIT:
2044 ce062d50 2019-08-21 martijn return "tx-commit";
2045 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_ROLLBACK:
2046 ce062d50 2019-08-21 martijn return "tx-rollback";
2047 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_PROTOCOL_CLIENT:
2048 ce062d50 2019-08-21 martijn return "protocol-client";
2049 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_PROTOCOL_SERVER:
2050 ce062d50 2019-08-21 martijn return "protocol-server";
2051 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_FILTER_RESPONSE:
2052 ce062d50 2019-08-21 martijn return "filter-response";
2053 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TIMEOUT:
2054 ce062d50 2019-08-21 martijn return "timeout";
2055 ce062d50 2019-08-21 martijn }
2056 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "In valid phase: %d\n", phase);
2057 ce062d50 2019-08-21 martijn }
2058 ce062d50 2019-08-21 martijn
2059 53b354a9 2020-04-12 martijn static enum osmtpd_status
2060 53b354a9 2020-04-12 martijn osmtpd_strtostatus(const char *status, char *linedup)
2061 ce062d50 2019-08-21 martijn {
2062 ce062d50 2019-08-21 martijn if (strcmp(status, "ok") == 0)
2063 ce062d50 2019-08-21 martijn return OSMTPD_STATUS_OK;
2064 ce062d50 2019-08-21 martijn else if (strcmp(status, "tempfail") == 0)
2065 ce062d50 2019-08-21 martijn return OSMTPD_STATUS_TEMPFAIL;
2066 ce062d50 2019-08-21 martijn else if (strcmp(status, "permfail") == 0)
2067 ce062d50 2019-08-21 martijn return OSMTPD_STATUS_PERMFAIL;
2068 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid status: %s\n", linedup);
2069 ce062d50 2019-08-21 martijn }
2070 ce062d50 2019-08-21 martijn
2071 ce062d50 2019-08-21 martijn static void
2072 ce062d50 2019-08-21 martijn osmtpd_addrtoss(char *addr, struct sockaddr_storage *ss, int hasport,
2073 ce062d50 2019-08-21 martijn char *linedup)
2074 ce062d50 2019-08-21 martijn {
2075 a37af028 2019-09-17 martijn char *port = NULL;
2076 ce062d50 2019-08-21 martijn const char *errstr = NULL;
2077 ce062d50 2019-08-21 martijn struct sockaddr_in *sin;
2078 ce062d50 2019-08-21 martijn struct sockaddr_in6 *sin6;
2079 ce062d50 2019-08-21 martijn struct sockaddr_un *sun;
2080 4574fbd0 2019-09-26 martijn size_t n;
2081 ce062d50 2019-08-21 martijn
2082 4574fbd0 2019-09-26 martijn if (addr[0] == '[') {
2083 ce062d50 2019-08-21 martijn sin6 = (struct sockaddr_in6 *)ss;
2084 ce062d50 2019-08-21 martijn sin6->sin6_family = AF_INET6;
2085 ce062d50 2019-08-21 martijn sin6->sin6_port = 0;
2086 ce062d50 2019-08-21 martijn if (hasport) {
2087 ce062d50 2019-08-21 martijn if ((port = strrchr(addr, ':')) == NULL)
2088 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
2089 ce062d50 2019-08-21 martijn "address (%s): %s", addr, linedup);
2090 4574fbd0 2019-09-26 martijn if (port[-1] != ']')
2091 4574fbd0 2019-09-26 martijn osmtpd_errx(1, "Invalid line received: invalid "
2092 4574fbd0 2019-09-26 martijn "address (%s): %s", addr, linedup);
2093 ce062d50 2019-08-21 martijn port++;
2094 ce062d50 2019-08-21 martijn sin6->sin6_port = htons(strtonum(port, 0, UINT16_MAX,
2095 ce062d50 2019-08-21 martijn &errstr));
2096 ce062d50 2019-08-21 martijn if (errstr != NULL)
2097 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
2098 ce062d50 2019-08-21 martijn "address (%s): %s", addr, linedup);
2099 4574fbd0 2019-09-26 martijn port[-2] = '\0';
2100 4574fbd0 2019-09-26 martijn } else {
2101 4574fbd0 2019-09-26 martijn n = strlen(addr);
2102 4574fbd0 2019-09-26 martijn if (addr[n - 1] != ']')
2103 4574fbd0 2019-09-26 martijn osmtpd_errx(1, "Invalid line received: invalid "
2104 4574fbd0 2019-09-26 martijn "address (%s): %s", addr, linedup);
2105 4574fbd0 2019-09-26 martijn addr[n - 1] = '\0';
2106 ce062d50 2019-08-21 martijn }
2107 4574fbd0 2019-09-26 martijn switch (inet_pton(AF_INET6, addr + 1, &(sin6->sin6_addr))) {
2108 ce062d50 2019-08-21 martijn case 1:
2109 ce062d50 2019-08-21 martijn break;
2110 ce062d50 2019-08-21 martijn case 0:
2111 a37af028 2019-09-17 martijn if (hasport)
2112 4574fbd0 2019-09-26 martijn port[-2] = ']';
2113 4574fbd0 2019-09-26 martijn else
2114 4574fbd0 2019-09-26 martijn addr[n - 1] = ']';
2115 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid address "
2116 ce062d50 2019-08-21 martijn "(%s): %s", addr, linedup);
2117 ce062d50 2019-08-21 martijn default:
2118 a37af028 2019-09-17 martijn if (hasport)
2119 4574fbd0 2019-09-26 martijn port[-2] = ']';
2120 4574fbd0 2019-09-26 martijn else
2121 4574fbd0 2019-09-26 martijn addr[n - 1] = ']';
2122 c6cb29f3 2019-08-22 martijn osmtpd_err(1, "Can't parse address (%s): %s", addr,
2123 c6cb29f3 2019-08-22 martijn linedup);
2124 ce062d50 2019-08-21 martijn }
2125 ce062d50 2019-08-21 martijn } else if (strncasecmp(addr, "unix:", 5) == 0) {
2126 ce062d50 2019-08-21 martijn sun = (struct sockaddr_un *)ss;
2127 ce062d50 2019-08-21 martijn sun->sun_family = AF_UNIX;
2128 ce062d50 2019-08-21 martijn if (strlcpy(sun->sun_path, addr,
2129 ce062d50 2019-08-21 martijn sizeof(sun->sun_path)) >= sizeof(sun->sun_path)) {
2130 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: address too "
2131 c6cb29f3 2019-08-22 martijn "long (%s): %s", addr, linedup);
2132 ce062d50 2019-08-21 martijn }
2133 ce062d50 2019-08-21 martijn } else {
2134 ce062d50 2019-08-21 martijn sin = (struct sockaddr_in *)ss;
2135 ce062d50 2019-08-21 martijn sin->sin_family = AF_INET;
2136 ce062d50 2019-08-21 martijn sin->sin_port = 0;
2137 ce062d50 2019-08-21 martijn if (hasport) {
2138 ce062d50 2019-08-21 martijn if ((port = strrchr(addr, ':')) == NULL)
2139 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
2140 ce062d50 2019-08-21 martijn "address (%s): %s", addr, linedup);
2141 ce062d50 2019-08-21 martijn port++;
2142 ce062d50 2019-08-21 martijn sin->sin_port = htons(strtonum(port, 0, UINT16_MAX,
2143 ce062d50 2019-08-21 martijn &errstr));
2144 ce062d50 2019-08-21 martijn if (errstr != NULL)
2145 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
2146 ce062d50 2019-08-21 martijn "address (%s): %s", addr, linedup);
2147 ce062d50 2019-08-21 martijn port[-1] = '\0';
2148 ce062d50 2019-08-21 martijn }
2149 ce062d50 2019-08-21 martijn switch (inet_pton(AF_INET, addr, &(sin->sin_addr))) {
2150 ce062d50 2019-08-21 martijn case 1:
2151 ce062d50 2019-08-21 martijn break;
2152 ce062d50 2019-08-21 martijn case 0:
2153 a37af028 2019-09-17 martijn if (hasport)
2154 a37af028 2019-09-17 martijn port[-1] = ':';
2155 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid address "
2156 ce062d50 2019-08-21 martijn "(%s): %s", addr, linedup);
2157 ce062d50 2019-08-21 martijn default:
2158 a37af028 2019-09-17 martijn if (hasport)
2159 a37af028 2019-09-17 martijn port[-1] = ':';
2160 c6cb29f3 2019-08-22 martijn osmtpd_err(1, "Can't parse address (%s): %s", addr,
2161 c6cb29f3 2019-08-22 martijn linedup);
2162 ce062d50 2019-08-21 martijn }
2163 ce062d50 2019-08-21 martijn }
2164 ce062d50 2019-08-21 martijn }
2165 ce062d50 2019-08-21 martijn
2166 ce062d50 2019-08-21 martijn static int
2167 ce062d50 2019-08-21 martijn osmtpd_session_cmp(struct osmtpd_session *a, struct osmtpd_session *b)
2168 ce062d50 2019-08-21 martijn {
2169 ce062d50 2019-08-21 martijn return a->ctx.reqid < b->ctx.reqid ? -1 : a->ctx.reqid > b->ctx.reqid;
2170 ce062d50 2019-08-21 martijn }
2171 ce062d50 2019-08-21 martijn
2172 9e3e8410 2019-08-22 martijn RB_GENERATE_STATIC(osmtpd_sessions, osmtpd_session, entry, osmtpd_session_cmp);