2 ce062d50 2019-08-21 martijn * Copyright (c) 2019 Martijn van Duren <martijn@openbsd.org>
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.
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.
16 957c2372 2019-11-14 martijn #define _GNU_SOURCE 1
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>
23 ce062d50 2019-08-21 martijn #include <arpa/inet.h>
24 078ff8cf 2019-08-21 martijn #include <netinet/in.h>
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>
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"
42 ce062d50 2019-08-21 martijn #define NITEMS(x) (sizeof(x) / sizeof(*x))
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 *,
50 d229c123 2019-08-22 martijn void *cb;
51 d229c123 2019-08-22 martijn int doregister;
52 d229c123 2019-08-22 martijn int storereport;
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;
60 d229c123 2019-08-22 martijn static void osmtpd_register(enum osmtpd_type, enum osmtpd_phase, int, int,
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 d229c123 2019-08-22 martijn static void osmtpd_tx_begin(struct osmtpd_callback *, struct osmtpd_ctx *,
86 d229c123 2019-08-22 martijn char *, char *);
87 d229c123 2019-08-22 martijn static void osmtpd_tx_mail(struct osmtpd_callback *, struct osmtpd_ctx *,
88 d229c123 2019-08-22 martijn char *, char *);
89 d229c123 2019-08-22 martijn static void osmtpd_tx_rcpt(struct osmtpd_callback *, struct osmtpd_ctx *,
90 d229c123 2019-08-22 martijn char *, char *);
91 d229c123 2019-08-22 martijn static void osmtpd_tx_envelope(struct osmtpd_callback *, struct osmtpd_ctx *,
92 d229c123 2019-08-22 martijn char *, char *);
93 d229c123 2019-08-22 martijn static void osmtpd_tx_data(struct osmtpd_callback *, struct osmtpd_ctx *,
94 d229c123 2019-08-22 martijn char *, char *);
95 d229c123 2019-08-22 martijn static void osmtpd_tx_commit(struct osmtpd_callback *, struct osmtpd_ctx *,
96 d229c123 2019-08-22 martijn char *, char *);
97 d229c123 2019-08-22 martijn static void osmtpd_tx_rollback(struct osmtpd_callback *, struct osmtpd_ctx *,
98 d229c123 2019-08-22 martijn char *, char *);
99 d229c123 2019-08-22 martijn static void osmtpd_addrtoss(char *, struct sockaddr_storage *, int, char *);
100 d229c123 2019-08-22 martijn static enum osmtpd_status osmtpd_strtostatus(const char *, char *);
101 d229c123 2019-08-22 martijn static int osmtpd_session_cmp(struct osmtpd_session *, struct osmtpd_session *);
102 912d0ff2 2019-08-22 martijn static void *(*oncreatecb_session)(struct osmtpd_ctx *) = NULL;
103 912d0ff2 2019-08-22 martijn static void (*ondeletecb_session)(struct osmtpd_ctx *, void *) = NULL;
104 912d0ff2 2019-08-22 martijn static void *(*oncreatecb_message)(struct osmtpd_ctx *) = NULL;
105 912d0ff2 2019-08-22 martijn static void (*ondeletecb_message)(struct osmtpd_ctx *, void *) = NULL;
106 2029083f 2020-10-15 martijn static void (*conf_cb)(const char *, const char *);
108 d229c123 2019-08-22 martijn static struct osmtpd_callback osmtpd_callbacks[] = {
110 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
111 d229c123 2019-08-22 martijn OSMTPD_PHASE_CONNECT,
113 d229c123 2019-08-22 martijn osmtpd_connect,
119 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
120 d229c123 2019-08-22 martijn OSMTPD_PHASE_HELO,
122 421c9a86 2019-09-06 martijn osmtpd_identify,
128 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
129 d229c123 2019-08-22 martijn OSMTPD_PHASE_EHLO,
131 421c9a86 2019-09-06 martijn osmtpd_identify,
137 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
138 d229c123 2019-08-22 martijn OSMTPD_PHASE_STARTTLS,
140 d229c123 2019-08-22 martijn osmtpd_noargs,
146 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
147 d229c123 2019-08-22 martijn OSMTPD_PHASE_AUTH,
149 d229c123 2019-08-22 martijn osmtpd_onearg,
155 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
156 d229c123 2019-08-22 martijn OSMTPD_PHASE_MAIL_FROM,
158 d229c123 2019-08-22 martijn osmtpd_onearg,
164 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
165 d229c123 2019-08-22 martijn OSMTPD_PHASE_RCPT_TO,
167 d229c123 2019-08-22 martijn osmtpd_onearg,
173 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
174 d229c123 2019-08-22 martijn OSMTPD_PHASE_DATA,
176 d229c123 2019-08-22 martijn osmtpd_noargs,
182 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
183 d229c123 2019-08-22 martijn OSMTPD_PHASE_DATA_LINE,
185 d229c123 2019-08-22 martijn osmtpd_onearg,
191 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
192 d229c123 2019-08-22 martijn OSMTPD_PHASE_RSET,
194 d229c123 2019-08-22 martijn osmtpd_noargs,
200 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
201 d229c123 2019-08-22 martijn OSMTPD_PHASE_QUIT,
203 d229c123 2019-08-22 martijn osmtpd_noargs,
209 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
210 d229c123 2019-08-22 martijn OSMTPD_PHASE_NOOP,
212 d229c123 2019-08-22 martijn osmtpd_noargs,
218 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
219 d229c123 2019-08-22 martijn OSMTPD_PHASE_HELP,
221 d229c123 2019-08-22 martijn osmtpd_noargs,
227 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
228 d229c123 2019-08-22 martijn OSMTPD_PHASE_WIZ,
230 d229c123 2019-08-22 martijn osmtpd_noargs,
236 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
237 d229c123 2019-08-22 martijn OSMTPD_PHASE_COMMIT,
239 d229c123 2019-08-22 martijn osmtpd_noargs,
245 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
246 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_CONNECT,
248 d229c123 2019-08-22 martijn osmtpd_link_connect,
254 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
255 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_DISCONNECT,
257 d229c123 2019-08-22 martijn osmtpd_link_disconnect,
263 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
264 a05d5c54 2019-08-28 martijn OSMTPD_PHASE_LINK_GREETING,
266 a05d5c54 2019-08-28 martijn osmtpd_link_greeting,
272 a05d5c54 2019-08-28 martijn OSMTPD_TYPE_REPORT,
273 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_IDENTIFY,
275 d229c123 2019-08-22 martijn osmtpd_link_identify,
281 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
282 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_TLS,
284 d229c123 2019-08-22 martijn osmtpd_link_tls,
290 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
291 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_BEGIN,
293 d229c123 2019-08-22 martijn osmtpd_tx_begin,
299 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
300 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_MAIL,
302 d229c123 2019-08-22 martijn osmtpd_tx_mail,
308 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
309 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_RCPT,
311 d229c123 2019-08-22 martijn osmtpd_tx_rcpt,
317 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
318 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_ENVELOPE,
320 d229c123 2019-08-22 martijn osmtpd_tx_envelope,
326 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
327 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_DATA,
329 d229c123 2019-08-22 martijn osmtpd_tx_data,
335 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
336 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_COMMIT,
338 d229c123 2019-08-22 martijn osmtpd_tx_commit,
344 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
345 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_ROLLBACK,
347 d229c123 2019-08-22 martijn osmtpd_tx_rollback,
353 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
354 d229c123 2019-08-22 martijn OSMTPD_PHASE_PROTOCOL_CLIENT,
356 d229c123 2019-08-22 martijn osmtpd_onearg,
362 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
363 d229c123 2019-08-22 martijn OSMTPD_PHASE_PROTOCOL_SERVER,
365 d229c123 2019-08-22 martijn osmtpd_onearg,
371 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
372 d229c123 2019-08-22 martijn OSMTPD_PHASE_FILTER_RESPONSE,
374 d229c123 2019-08-22 martijn osmtpd_onearg,
380 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
381 d229c123 2019-08-22 martijn OSMTPD_PHASE_TIMEOUT,
383 d229c123 2019-08-22 martijn osmtpd_noargs,
389 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
390 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_CONNECT,
392 d229c123 2019-08-22 martijn osmtpd_link_connect,
398 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
399 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_DISCONNECT,
401 d229c123 2019-08-22 martijn osmtpd_link_disconnect,
407 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
408 a05d5c54 2019-08-28 martijn OSMTPD_PHASE_LINK_GREETING,
410 a05d5c54 2019-08-28 martijn osmtpd_link_greeting,
416 a05d5c54 2019-08-28 martijn OSMTPD_TYPE_REPORT,
417 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_IDENTIFY,
419 d229c123 2019-08-22 martijn osmtpd_link_identify,
425 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
426 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_TLS,
428 d229c123 2019-08-22 martijn osmtpd_link_tls,
434 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
435 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_BEGIN,
437 d229c123 2019-08-22 martijn osmtpd_tx_begin,
443 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
444 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_MAIL,
446 d229c123 2019-08-22 martijn osmtpd_tx_mail,
452 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
453 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_RCPT,
455 d229c123 2019-08-22 martijn osmtpd_tx_rcpt,
461 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
462 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_ENVELOPE,
464 d229c123 2019-08-22 martijn osmtpd_tx_envelope,
470 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
471 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_DATA,
473 d229c123 2019-08-22 martijn osmtpd_tx_data,
479 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
480 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_COMMIT,
482 d229c123 2019-08-22 martijn osmtpd_tx_commit,
488 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
489 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_ROLLBACK,
491 d229c123 2019-08-22 martijn osmtpd_tx_rollback,
497 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
498 d229c123 2019-08-22 martijn OSMTPD_PHASE_PROTOCOL_CLIENT,
500 d229c123 2019-08-22 martijn osmtpd_onearg,
506 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
507 d229c123 2019-08-22 martijn OSMTPD_PHASE_PROTOCOL_SERVER,
509 d229c123 2019-08-22 martijn osmtpd_onearg,
515 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
516 d229c123 2019-08-22 martijn OSMTPD_PHASE_FILTER_RESPONSE,
518 d229c123 2019-08-22 martijn osmtpd_onearg,
524 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
525 d229c123 2019-08-22 martijn OSMTPD_PHASE_TIMEOUT,
527 d229c123 2019-08-22 martijn osmtpd_noargs,
534 ce062d50 2019-08-21 martijn static struct io *io_stdout;
535 09816288 2019-08-22 martijn static int needs;
536 ce062d50 2019-08-21 martijn static int ready = 0;
537 ce062d50 2019-08-21 martijn /* Default from smtpd */
538 ce062d50 2019-08-21 martijn static int session_timeout = 300;
540 d229c123 2019-08-22 martijn RB_HEAD(osmtpd_sessions, osmtpd_session) osmtpd_sessions = RB_INITIALIZER(NULL);
541 9e3e8410 2019-08-22 martijn RB_PROTOTYPE_STATIC(osmtpd_sessions, osmtpd_session, entry, osmtpd_session_cmp);
544 2029083f 2020-10-15 martijn osmtpd_register_conf(void (*cb)(const char *, const char *))
546 2029083f 2020-10-15 martijn conf_cb = cb;
550 ce062d50 2019-08-21 martijn osmtpd_register_filter_connect(void (*cb)(struct osmtpd_ctx *, const char *,
551 ce062d50 2019-08-21 martijn struct sockaddr_storage *))
553 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_CONNECT, 1, 0,
554 ce062d50 2019-08-21 martijn (void *)cb);
555 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
560 ce062d50 2019-08-21 martijn osmtpd_register_filter_helo(void (*cb)(struct osmtpd_ctx *, const char *))
562 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_HELO, 1, 0,
563 ce062d50 2019-08-21 martijn (void *)cb);
564 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
569 ce062d50 2019-08-21 martijn osmtpd_register_filter_ehlo(void (*cb)(struct osmtpd_ctx *, const char *))
571 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_EHLO, 1, 0,
572 ce062d50 2019-08-21 martijn (void *)cb);
573 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
578 ce062d50 2019-08-21 martijn osmtpd_register_filter_starttls(void (*cb)(struct osmtpd_ctx *))
580 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_STARTTLS, 1, 0,
581 ce062d50 2019-08-21 martijn (void *)cb);
582 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
587 ce062d50 2019-08-21 martijn osmtpd_register_filter_auth(void (*cb)(struct osmtpd_ctx *, const char *))
589 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_AUTH, 1, 0,
590 ce062d50 2019-08-21 martijn (void *)cb);
591 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
596 ce062d50 2019-08-21 martijn osmtpd_register_filter_mailfrom(void (*cb)(struct osmtpd_ctx *, const char *))
598 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_MAIL_FROM, 1, 0,
599 ce062d50 2019-08-21 martijn (void *)cb);
600 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
605 ce062d50 2019-08-21 martijn osmtpd_register_filter_rcptto(void (*cb)(struct osmtpd_ctx *, const char *))
607 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_RCPT_TO, 1, 0,
608 ce062d50 2019-08-21 martijn (void *)cb);
609 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
614 ce062d50 2019-08-21 martijn osmtpd_register_filter_data(void (*cb)(struct osmtpd_ctx *))
616 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_DATA, 1, 0,
617 ce062d50 2019-08-21 martijn (void *)cb);
618 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
623 ce062d50 2019-08-21 martijn osmtpd_register_filter_dataline(void (*cb)(struct osmtpd_ctx *, const char *))
625 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_DATA_LINE, 1, 0,
626 ce062d50 2019-08-21 martijn (void *)cb);
627 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
632 ce062d50 2019-08-21 martijn osmtpd_register_filter_rset(void (*cb)(struct osmtpd_ctx *))
634 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_RSET, 1, 0,
635 ce062d50 2019-08-21 martijn (void *)cb);
636 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
641 ce062d50 2019-08-21 martijn osmtpd_register_filter_quit(void (*cb)(struct osmtpd_ctx *))
643 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_QUIT, 1, 0,
644 ce062d50 2019-08-21 martijn (void *)cb);
645 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
650 ce062d50 2019-08-21 martijn osmtpd_register_filter_noop(void (*cb)(struct osmtpd_ctx *))
652 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_NOOP, 1, 0,
653 ce062d50 2019-08-21 martijn (void *)cb);
654 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
659 ce062d50 2019-08-21 martijn osmtpd_register_filter_help(void (*cb)(struct osmtpd_ctx *))
661 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_HELP, 1, 0,
662 ce062d50 2019-08-21 martijn (void *)cb);
663 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
668 ce062d50 2019-08-21 martijn osmtpd_register_filter_wiz(void (*cb)(struct osmtpd_ctx *))
670 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_WIZ, 1, 0,
671 ce062d50 2019-08-21 martijn (void *)cb);
672 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
677 ce062d50 2019-08-21 martijn osmtpd_register_filter_commit(void (*cb)(struct osmtpd_ctx *))
679 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_COMMIT, 1, 0,
680 ce062d50 2019-08-21 martijn (void *)cb);
681 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
686 ce062d50 2019-08-21 martijn osmtpd_register_report_connect(int incoming, void (*cb)(struct osmtpd_ctx *,
687 30f1cbac 2019-08-22 martijn const char *, enum osmtpd_status, struct sockaddr_storage *,
688 ce062d50 2019-08-21 martijn struct sockaddr_storage *))
690 3fd8a04a 2021-04-18 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_CONNECT, incoming,
691 ce062d50 2019-08-21 martijn 0, (void *)cb);
692 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
693 ce062d50 2019-08-21 martijn incoming, 0, NULL);
697 ce062d50 2019-08-21 martijn osmtpd_register_report_disconnect(int incoming, void (*cb)(struct osmtpd_ctx *))
699 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
700 ce062d50 2019-08-21 martijn incoming, 0, (void *)cb);
704 ce062d50 2019-08-21 martijn osmtpd_register_report_identify(int incoming, void (*cb)(struct osmtpd_ctx *,
705 ce062d50 2019-08-21 martijn const char *))
707 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_IDENTIFY,
708 ce062d50 2019-08-21 martijn incoming, 0, (void *)cb);
709 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
710 ce062d50 2019-08-21 martijn incoming, 0, NULL);
714 ce062d50 2019-08-21 martijn osmtpd_register_report_tls(int incoming, void (*cb)(struct osmtpd_ctx *,
715 ce062d50 2019-08-21 martijn const char *))
717 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_TLS, incoming, 0,
718 ce062d50 2019-08-21 martijn (void *)cb);
719 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
720 ce062d50 2019-08-21 martijn incoming, 0, NULL);
724 ce062d50 2019-08-21 martijn osmtpd_register_report_begin(int incoming, void (*cb)(struct osmtpd_ctx *,
725 ce062d50 2019-08-21 martijn uint32_t))
727 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_BEGIN, incoming, 0,
728 ce062d50 2019-08-21 martijn (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);
734 ce062d50 2019-08-21 martijn osmtpd_register_report_mail(int incoming, void (*cb)(struct osmtpd_ctx *,
735 ce062d50 2019-08-21 martijn uint32_t, const char *, enum osmtpd_status))
737 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_MAIL, 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);
744 ce062d50 2019-08-21 martijn osmtpd_register_report_rcpt(int incoming, void (*cb)(struct osmtpd_ctx *,
745 ce062d50 2019-08-21 martijn uint32_t, const char *, enum osmtpd_status))
747 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_RCPT, incoming, 0,
748 ce062d50 2019-08-21 martijn (void *)cb);
749 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
750 ce062d50 2019-08-21 martijn incoming, 0, NULL);
754 ce062d50 2019-08-21 martijn osmtpd_register_report_envelope(int incoming, void (*cb)(struct osmtpd_ctx *,
755 ce062d50 2019-08-21 martijn uint32_t, uint64_t))
757 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ENVELOPE, incoming,
758 ce062d50 2019-08-21 martijn 0, (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);
764 ce062d50 2019-08-21 martijn osmtpd_register_report_data(int incoming, void (*cb)(struct osmtpd_ctx *,
765 ce062d50 2019-08-21 martijn uint32_t, enum osmtpd_status))
767 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_DATA, 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);
774 ce062d50 2019-08-21 martijn osmtpd_register_report_commit(int incoming, void (*cb)(struct osmtpd_ctx *,
775 ce062d50 2019-08-21 martijn uint32_t, size_t))
777 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_COMMIT, 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);
784 ce062d50 2019-08-21 martijn osmtpd_register_report_rollback(int incoming, void (*cb)(struct osmtpd_ctx *,
785 ce062d50 2019-08-21 martijn uint32_t))
787 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ROLLBACK, 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);
794 ce062d50 2019-08-21 martijn osmtpd_register_report_client(int incoming, void (*cb)(struct osmtpd_ctx *,
795 ce062d50 2019-08-21 martijn const char *))
797 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_PROTOCOL_CLIENT,
798 ce062d50 2019-08-21 martijn incoming, 0, (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);
804 ce062d50 2019-08-21 martijn osmtpd_register_report_server(int incoming, void (*cb)(struct osmtpd_ctx *,
805 ce062d50 2019-08-21 martijn const char *))
807 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_PROTOCOL_SERVER,
808 ce062d50 2019-08-21 martijn incoming, 0, (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);
814 ce062d50 2019-08-21 martijn osmtpd_register_report_response(int incoming, void (*cb)(struct osmtpd_ctx *,
815 ce062d50 2019-08-21 martijn const char *))
817 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_FILTER_RESPONSE,
818 ce062d50 2019-08-21 martijn incoming, 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);
824 ce062d50 2019-08-21 martijn osmtpd_register_report_timeout(int incoming, void (*cb)(struct osmtpd_ctx *))
826 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TIMEOUT, incoming, 0,
827 ce062d50 2019-08-21 martijn (void *)cb);
828 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
829 ce062d50 2019-08-21 martijn incoming, 0, NULL);
833 912d0ff2 2019-08-22 martijn osmtpd_local_session(void *(*oncreate)(struct osmtpd_ctx *),
834 ce062d50 2019-08-21 martijn void (*ondelete)(struct osmtpd_ctx *, void *))
836 912d0ff2 2019-08-22 martijn oncreatecb_session = oncreate;
837 912d0ff2 2019-08-22 martijn ondeletecb_session = ondelete;
841 912d0ff2 2019-08-22 martijn osmtpd_local_message(void *(*oncreate)(struct osmtpd_ctx *),
842 912d0ff2 2019-08-22 martijn void (*ondelete)(struct osmtpd_ctx *, void *))
844 912d0ff2 2019-08-22 martijn oncreatecb_message = oncreate;
845 912d0ff2 2019-08-22 martijn ondeletecb_message = ondelete;
849 09816288 2019-08-22 martijn osmtpd_need(int lneeds)
851 09816288 2019-08-22 martijn needs |= lneeds;
854 09816288 2019-08-22 martijn static void
855 09816288 2019-08-22 martijn osmtpd_register_need(int incoming)
857 ce062d50 2019-08-21 martijn if (needs & (OSMTPD_NEED_SRC | OSMTPD_NEED_DST | OSMTPD_NEED_RDNS |
858 09816288 2019-08-22 martijn OSMTPD_NEED_FCRDNS))
859 705cd566 2019-08-23 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_CONNECT,
860 ce062d50 2019-08-21 martijn incoming, 1, NULL);
861 0fb4c799 2019-09-05 martijn if (needs & OSMTPD_NEED_GREETING)
862 a05d5c54 2019-08-28 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_GREETING,
863 a05d5c54 2019-08-28 martijn incoming, 1, NULL);
864 0fb4c799 2019-09-05 martijn if (needs & OSMTPD_NEED_IDENTITY)
865 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_IDENTIFY,
866 ce062d50 2019-08-21 martijn incoming, 1, NULL);
867 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_CIPHERS)
868 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_TLS,
869 ce062d50 2019-08-21 martijn incoming, 1, NULL);
870 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_MSGID) {
871 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_BEGIN,
872 ce062d50 2019-08-21 martijn incoming, 1, NULL);
873 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ROLLBACK,
874 ce062d50 2019-08-21 martijn incoming, 0, NULL);
875 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_COMMIT,
876 ce062d50 2019-08-21 martijn incoming, 0, NULL);
878 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_MAILFROM) {
879 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_MAIL,
880 ce062d50 2019-08-21 martijn incoming, 1, NULL);
881 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ROLLBACK,
882 ce062d50 2019-08-21 martijn incoming, 0, NULL);
883 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_COMMIT,
884 ce062d50 2019-08-21 martijn incoming, 0, NULL);
886 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_RCPTTO) {
887 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_RCPT,
888 ce062d50 2019-08-21 martijn incoming, 1, NULL);
889 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ROLLBACK,
890 ce062d50 2019-08-21 martijn incoming, 0, NULL);
891 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_COMMIT,
892 ce062d50 2019-08-21 martijn incoming, 0, NULL);
894 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_EVPID) {
895 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ENVELOPE,
896 ce062d50 2019-08-21 martijn incoming, 1, NULL);
897 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ROLLBACK,
898 ce062d50 2019-08-21 martijn incoming, 0, NULL);
899 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_COMMIT,
900 ce062d50 2019-08-21 martijn incoming, 0, NULL);
903 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
904 ce062d50 2019-08-21 martijn incoming, 0, NULL);
908 ce062d50 2019-08-21 martijn osmtpd_run(void)
910 ce062d50 2019-08-21 martijn size_t i = 0;
911 ce062d50 2019-08-21 martijn int registered = 0;
912 adebfe7c 2021-03-21 martijn struct event_base *evbase;
913 ce062d50 2019-08-21 martijn struct io *io_stdin;
914 a37af028 2019-09-17 martijn struct osmtpd_callback *hidenity = NULL, *eidentity = NULL;
915 a37af028 2019-09-17 martijn struct osmtpd_callback *ridentity = NULL;
917 adebfe7c 2021-03-21 martijn evbase = event_init();
919 ce062d50 2019-08-21 martijn if ((io_stdin = io_new()) == NULL ||
920 ce062d50 2019-08-21 martijn (io_stdout = io_new()) == NULL)
921 27dd1f3b 2019-08-22 martijn osmtpd_err(1, "io_new");
922 ce062d50 2019-08-21 martijn io_set_nonblocking(STDIN_FILENO);
923 ce062d50 2019-08-21 martijn io_set_fd(io_stdin, STDIN_FILENO);
924 ce062d50 2019-08-21 martijn io_set_callback(io_stdin, osmtpd_newline, NULL);
925 ce062d50 2019-08-21 martijn io_set_read(io_stdin);
926 ce062d50 2019-08-21 martijn io_set_nonblocking(STDOUT_FILENO);
927 ce062d50 2019-08-21 martijn io_set_fd(io_stdout, STDOUT_FILENO);
928 ce062d50 2019-08-21 martijn io_set_callback(io_stdout, osmtpd_outevt, NULL);
929 ce062d50 2019-08-21 martijn io_set_write(io_stdout);
931 ce062d50 2019-08-21 martijn for (i = 0; i < NITEMS(osmtpd_callbacks); i++) {
932 912d0ff2 2019-08-22 martijn if (osmtpd_callbacks[i].doregister) {
933 09816288 2019-08-22 martijn osmtpd_register_need(osmtpd_callbacks[i].incoming);
934 912d0ff2 2019-08-22 martijn if (oncreatecb_message != NULL) {
935 912d0ff2 2019-08-22 martijn osmtpd_register(OSMTPD_TYPE_REPORT,
936 912d0ff2 2019-08-22 martijn OSMTPD_PHASE_TX_BEGIN,
937 912d0ff2 2019-08-22 martijn osmtpd_callbacks[i].incoming, 0, NULL);
938 912d0ff2 2019-08-22 martijn osmtpd_register(OSMTPD_TYPE_REPORT,
939 912d0ff2 2019-08-22 martijn OSMTPD_PHASE_TX_ROLLBACK,
940 912d0ff2 2019-08-22 martijn osmtpd_callbacks[i].incoming, 0, NULL);
941 912d0ff2 2019-08-22 martijn osmtpd_register(OSMTPD_TYPE_REPORT,
942 912d0ff2 2019-08-22 martijn OSMTPD_PHASE_TX_COMMIT,
943 912d0ff2 2019-08-22 martijn osmtpd_callbacks[i].incoming, 0, NULL);
945 421c9a86 2019-09-06 martijn if (osmtpd_callbacks[i].type == OSMTPD_TYPE_FILTER &&
946 421c9a86 2019-09-06 martijn osmtpd_callbacks[i].phase == OSMTPD_PHASE_HELO)
947 421c9a86 2019-09-06 martijn hidenity = &(osmtpd_callbacks[i]);
948 421c9a86 2019-09-06 martijn if (osmtpd_callbacks[i].type == OSMTPD_TYPE_FILTER &&
949 421c9a86 2019-09-06 martijn osmtpd_callbacks[i].phase == OSMTPD_PHASE_EHLO)
950 421c9a86 2019-09-06 martijn eidentity = &(osmtpd_callbacks[i]);
951 421c9a86 2019-09-06 martijn if (osmtpd_callbacks[i].type == OSMTPD_TYPE_REPORT &&
952 421c9a86 2019-09-06 martijn osmtpd_callbacks[i].phase ==
953 421c9a86 2019-09-06 martijn OSMTPD_PHASE_LINK_IDENTIFY &&
954 421c9a86 2019-09-06 martijn osmtpd_callbacks[i].incoming == 1)
955 421c9a86 2019-09-06 martijn ridentity = &(osmtpd_callbacks[i]);
958 a37af028 2019-09-17 martijn if (ridentity != NULL && ridentity->storereport) {
959 a37af028 2019-09-17 martijn if (hidenity != NULL && hidenity->doregister)
960 421c9a86 2019-09-06 martijn hidenity->storereport = 1;
961 a37af028 2019-09-17 martijn if (eidentity != NULL && eidentity->doregister)
962 421c9a86 2019-09-06 martijn eidentity->storereport = 1;
964 09816288 2019-08-22 martijn for (i = 0; i < NITEMS(osmtpd_callbacks); i++) {
965 ce062d50 2019-08-21 martijn if (osmtpd_callbacks[i].doregister) {
966 ce062d50 2019-08-21 martijn if (osmtpd_callbacks[i].cb != NULL)
967 ce062d50 2019-08-21 martijn registered = 1;
968 ce062d50 2019-08-21 martijn io_printf(io_stdout, "register|%s|smtp-%s|%s\n",
969 ce062d50 2019-08-21 martijn osmtpd_typetostr(osmtpd_callbacks[i].type),
970 ce062d50 2019-08-21 martijn osmtpd_callbacks[i].incoming ? "in" : "out",
971 ce062d50 2019-08-21 martijn osmtpd_phasetostr(osmtpd_callbacks[i].phase));
975 ce062d50 2019-08-21 martijn if (!registered)
976 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "No events registered");
977 ce062d50 2019-08-21 martijn io_printf(io_stdout, "register|ready\n");
978 ce062d50 2019-08-21 martijn ready = 1;
980 ce062d50 2019-08-21 martijn event_dispatch();
981 adebfe7c 2021-03-21 martijn io_free(io_stdin);
982 adebfe7c 2021-03-21 martijn io_free(io_stdout);
983 adebfe7c 2021-03-21 martijn event_base_free(evbase);
986 27dd1f3b 2019-08-22 martijn __dead void
987 27dd1f3b 2019-08-22 martijn osmtpd_err(int eval, const char *fmt, ...)
989 27dd1f3b 2019-08-22 martijn va_list ap;
991 27dd1f3b 2019-08-22 martijn va_start(ap, fmt);
992 27dd1f3b 2019-08-22 martijn vfprintf(stderr, fmt, ap);
993 27dd1f3b 2019-08-22 martijn va_end(ap);
994 67cd1323 2019-08-22 martijn fprintf(stderr, ": %s\n", strerror(errno));
995 27dd1f3b 2019-08-22 martijn exit(eval);
998 27dd1f3b 2019-08-22 martijn __dead void
999 27dd1f3b 2019-08-22 martijn osmtpd_errx(int eval, const char *fmt, ...)
1001 27dd1f3b 2019-08-22 martijn va_list ap;
1003 27dd1f3b 2019-08-22 martijn va_start(ap, fmt);
1004 27dd1f3b 2019-08-22 martijn vfprintf(stderr, fmt, ap);
1005 27dd1f3b 2019-08-22 martijn va_end(ap);
1006 27dd1f3b 2019-08-22 martijn fprintf(stderr, "\n");
1007 27dd1f3b 2019-08-22 martijn exit(eval);
1010 ce062d50 2019-08-21 martijn static void
1011 6258daeb 2019-11-14 martijn osmtpd_newline(struct io *io, int ev, __unused void *arg)
1013 ce062d50 2019-08-21 martijn static char *linedup = NULL;
1014 ce062d50 2019-08-21 martijn static size_t dupsize = 0;
1015 ce062d50 2019-08-21 martijn struct osmtpd_session *ctx, search;
1016 ce062d50 2019-08-21 martijn enum osmtpd_type type;
1017 ce062d50 2019-08-21 martijn enum osmtpd_phase phase;
1018 ce062d50 2019-08-21 martijn int version_major, version_minor, incoming;
1019 ce062d50 2019-08-21 martijn struct timespec tm;
1020 ce062d50 2019-08-21 martijn char *line = NULL;
1021 ce062d50 2019-08-21 martijn const char *errstr = NULL;
1022 ce062d50 2019-08-21 martijn size_t linelen;
1023 ce062d50 2019-08-21 martijn char *end;
1024 ce062d50 2019-08-21 martijn size_t i;
1026 adebfe7c 2021-03-21 martijn if (ev == IO_DISCONNECTED) {
1027 adebfe7c 2021-03-21 martijn event_loopexit(0);
1028 adebfe7c 2021-03-21 martijn return;
1030 ce062d50 2019-08-21 martijn if (ev != IO_DATAIN)
1031 ce062d50 2019-08-21 martijn return;
1032 24d62a97 2019-08-23 martijn while ((line = io_getline(io, &linelen)) != NULL) {
1033 ce062d50 2019-08-21 martijn if (dupsize < linelen) {
1034 ce062d50 2019-08-21 martijn if ((linedup = realloc(linedup, linelen + 1)) == NULL)
1035 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1036 ce062d50 2019-08-21 martijn dupsize = linelen + 1;
1038 ce062d50 2019-08-21 martijn strlcpy(linedup, line, dupsize);
1039 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
1040 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing "
1041 c6cb29f3 2019-08-22 martijn "version: %s", linedup);
1042 ce062d50 2019-08-21 martijn end++[0] = '\0';
1043 ce062d50 2019-08-21 martijn if (strcmp(line, "filter") == 0)
1044 ce062d50 2019-08-21 martijn type = OSMTPD_TYPE_FILTER;
1045 ce062d50 2019-08-21 martijn else if (strcmp(line, "report") == 0)
1046 ce062d50 2019-08-21 martijn type = OSMTPD_TYPE_REPORT;
1047 ce062d50 2019-08-21 martijn else if (strcmp(line, "config") == 0) {
1048 ce062d50 2019-08-21 martijn line = end;
1049 2029083f 2020-10-15 martijn if (strcmp(line, "ready") == 0) {
1050 34f87d66 2020-12-20 martijn if (conf_cb != NULL)
1051 34f87d66 2020-12-20 martijn conf_cb(NULL, NULL);
1052 ce062d50 2019-08-21 martijn continue;
1054 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
1055 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing "
1056 c6cb29f3 2019-08-22 martijn "key: %s", linedup);
1057 ce062d50 2019-08-21 martijn end++[0] = '\0';
1058 34f87d66 2020-12-20 martijn if (conf_cb != NULL)
1059 34f87d66 2020-12-20 martijn conf_cb(line, end);
1060 ce062d50 2019-08-21 martijn if (strcmp(line, "smtp-session-timeout") == 0) {
1061 ce062d50 2019-08-21 martijn session_timeout = strtonum(end, 0, INT_MAX,
1062 ce062d50 2019-08-21 martijn &errstr);
1063 ce062d50 2019-08-21 martijn if (errstr != NULL)
1064 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: "
1065 ce062d50 2019-08-21 martijn "invalid smtp-sesion-timeout: %s",
1066 ce062d50 2019-08-21 martijn linedup);
1068 ce062d50 2019-08-21 martijn continue;
1071 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: unknown message "
1072 c6cb29f3 2019-08-22 martijn "type: %s", linedup);
1073 ce062d50 2019-08-21 martijn line = end;
1074 183acf20 2019-08-28 martijn version_major = strtoul(line, &end, 10);
1075 183acf20 2019-08-28 martijn if (line == end || end[0] != '.')
1076 183acf20 2019-08-28 martijn osmtpd_errx(1, "Invalid protocol received: %s",
1077 183acf20 2019-08-28 martijn linedup);
1078 183acf20 2019-08-28 martijn line = end + 1;
1079 183acf20 2019-08-28 martijn version_minor = strtoul(line, &end, 10);
1080 183acf20 2019-08-28 martijn if (end[0] == '\0')
1081 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing time: "
1082 c6cb29f3 2019-08-22 martijn "%s", linedup);
1083 183acf20 2019-08-28 martijn if (line == end || end[0] != '|')
1084 183acf20 2019-08-28 martijn osmtpd_errx(1, "Invalid protocol received: %s",
1085 183acf20 2019-08-28 martijn linedup);
1086 183acf20 2019-08-28 martijn if (version_major != 0)
1087 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Unsupported protocol received: %s",
1088 c6cb29f3 2019-08-22 martijn linedup);
1089 183acf20 2019-08-28 martijn line = end + 1;
1090 ce062d50 2019-08-21 martijn if ((end = strchr(line, '.')) == NULL)
1091 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
1092 c6cb29f3 2019-08-22 martijn "timestamp: %s", linedup);
1093 ce062d50 2019-08-21 martijn end++[0] = '\0';
1094 ce062d50 2019-08-21 martijn tm.tv_sec = (time_t) strtonum(line, 0, INT64_MAX, &errstr);
1095 ce062d50 2019-08-21 martijn if (errstr != NULL)
1096 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
1097 c6cb29f3 2019-08-22 martijn "timestamp: %s", linedup);
1098 ce062d50 2019-08-21 martijn line = end;
1099 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
1100 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing "
1101 c6cb29f3 2019-08-22 martijn "direction: %s", linedup);
1102 ce062d50 2019-08-21 martijn end++[0] = '\0';
1103 ce062d50 2019-08-21 martijn tm.tv_nsec = (long) strtonum(line, 0, LONG_MAX, &errstr);
1104 ce062d50 2019-08-21 martijn if (errstr != NULL)
1105 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
1106 c6cb29f3 2019-08-22 martijn "timestamp: %s", linedup);
1107 ce062d50 2019-08-21 martijn tm.tv_nsec *= 10 * (9 - (end - line));
1108 ce062d50 2019-08-21 martijn line = end;
1109 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
1110 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line receieved: missing "
1111 c6cb29f3 2019-08-22 martijn "phase: %s", linedup);
1112 ce062d50 2019-08-21 martijn end++[0] = '\0';
1113 ce062d50 2019-08-21 martijn if (strcmp(line, "smtp-in") == 0)
1114 ce062d50 2019-08-21 martijn incoming = 1;
1115 ce062d50 2019-08-21 martijn else if (strcmp(line, "smtp-out") == 0)
1116 ce062d50 2019-08-21 martijn incoming = 0;
1118 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line: invalid direction: %s",
1119 c6cb29f3 2019-08-22 martijn linedup);
1120 ce062d50 2019-08-21 martijn line = end;
1121 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
1122 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing reqid: "
1123 c6cb29f3 2019-08-22 martijn "%s", linedup);
1124 ce062d50 2019-08-21 martijn end++[0] = '\0';
1125 ce062d50 2019-08-21 martijn phase = osmtpd_strtophase(line, linedup);
1126 ce062d50 2019-08-21 martijn line = end;
1127 ce062d50 2019-08-21 martijn errno = 0;
1128 ce062d50 2019-08-21 martijn search.ctx.reqid = strtoull(line, &end, 16);
1129 ce062d50 2019-08-21 martijn if ((search.ctx.reqid == ULLONG_MAX && errno != 0) ||
1130 ce062d50 2019-08-21 martijn (end[0] != '|' && end[0] != '\0'))
1131 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid reqid: "
1132 c6cb29f3 2019-08-22 martijn "%s", linedup);
1133 ce062d50 2019-08-21 martijn line = end + 1;
1134 ce062d50 2019-08-21 martijn ctx = RB_FIND(osmtpd_sessions, &osmtpd_sessions, &search);
1135 ce062d50 2019-08-21 martijn if (ctx == NULL) {
1136 ce062d50 2019-08-21 martijn if ((ctx = malloc(sizeof(*ctx))) == NULL)
1137 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1138 ce062d50 2019-08-21 martijn ctx->ctx.reqid = search.ctx.reqid;
1139 ce062d50 2019-08-21 martijn ctx->ctx.rdns = NULL;
1140 30f1cbac 2019-08-22 martijn ctx->ctx.fcrdns = OSMTPD_STATUS_TEMPFAIL;
1141 0fb4c799 2019-09-05 martijn ctx->ctx.identity = NULL;
1142 0fb4c799 2019-09-05 martijn ctx->ctx.greeting.identity = NULL;
1143 ce062d50 2019-08-21 martijn ctx->ctx.ciphers = NULL;
1144 ce062d50 2019-08-21 martijn ctx->ctx.msgid = 0;
1145 ce062d50 2019-08-21 martijn ctx->ctx.mailfrom = NULL;
1146 ce062d50 2019-08-21 martijn ctx->ctx.rcptto = malloc(sizeof(*(ctx->ctx.rcptto)));
1147 ce062d50 2019-08-21 martijn if (ctx->ctx.rcptto == NULL)
1148 27dd1f3b 2019-08-22 martijn osmtpd_err(1, "malloc");
1149 ce062d50 2019-08-21 martijn ctx->ctx.rcptto[0] = NULL;
1150 ce062d50 2019-08-21 martijn memset(&(ctx->ctx.src), 0, sizeof(ctx->ctx.src));
1151 ce062d50 2019-08-21 martijn ctx->ctx.src.ss_family = AF_UNSPEC;
1152 ce062d50 2019-08-21 martijn memset(&(ctx->ctx.dst), 0, sizeof(ctx->ctx.dst));
1153 ce062d50 2019-08-21 martijn ctx->ctx.dst.ss_family = AF_UNSPEC;
1154 ce062d50 2019-08-21 martijn RB_INSERT(osmtpd_sessions, &osmtpd_sessions, ctx);
1155 ce062d50 2019-08-21 martijn ctx->ctx.evpid = 0;
1156 912d0ff2 2019-08-22 martijn ctx->ctx.local_session = NULL;
1157 912d0ff2 2019-08-22 martijn ctx->ctx.local_message = NULL;
1158 912d0ff2 2019-08-22 martijn if (oncreatecb_session != NULL)
1159 912d0ff2 2019-08-22 martijn ctx->ctx.local_session =
1160 912d0ff2 2019-08-22 martijn oncreatecb_session(&ctx->ctx);
1162 ce062d50 2019-08-21 martijn ctx->ctx.type = type;
1163 ce062d50 2019-08-21 martijn ctx->ctx.phase = phase;
1164 ce062d50 2019-08-21 martijn ctx->ctx.version_major = version_major;
1165 ce062d50 2019-08-21 martijn ctx->ctx.version_minor = version_minor;
1166 ce062d50 2019-08-21 martijn ctx->ctx.incoming = incoming;
1167 ce062d50 2019-08-21 martijn ctx->ctx.tm.tv_sec = tm.tv_sec;
1168 ce062d50 2019-08-21 martijn ctx->ctx.tm.tv_nsec = tm.tv_nsec;
1169 ce062d50 2019-08-21 martijn ctx->ctx.token = 0;
1171 ce062d50 2019-08-21 martijn for (i = 0; i < NITEMS(osmtpd_callbacks); i++) {
1172 ce062d50 2019-08-21 martijn if (ctx->ctx.type == osmtpd_callbacks[i].type &&
1173 ce062d50 2019-08-21 martijn ctx->ctx.phase == osmtpd_callbacks[i].phase &&
1174 ce062d50 2019-08-21 martijn ctx->ctx.incoming == osmtpd_callbacks[i].incoming)
1177 ce062d50 2019-08-21 martijn if (i == NITEMS(osmtpd_callbacks)) {
1178 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: received "
1179 c6cb29f3 2019-08-22 martijn "unregistered line: %s", linedup);
1181 ce062d50 2019-08-21 martijn if (ctx->ctx.type == OSMTPD_TYPE_FILTER) {
1182 ce062d50 2019-08-21 martijn ctx->ctx.token = strtoull(line, &end, 16);
1183 c6cb29f3 2019-08-22 martijn if ((ctx->ctx.token == ULLONG_MAX && errno != 0) ||
1184 ce062d50 2019-08-21 martijn end[0] != '|')
1185 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
1186 c6cb29f3 2019-08-22 martijn "token: %s", linedup);
1187 ce062d50 2019-08-21 martijn line = end + 1;
1189 ce062d50 2019-08-21 martijn osmtpd_callbacks[i].osmtpd_cb(&(osmtpd_callbacks[i]),
1190 ce062d50 2019-08-21 martijn &(ctx->ctx), line, linedup);
1194 ce062d50 2019-08-21 martijn static void
1195 6258daeb 2019-11-14 martijn osmtpd_outevt(__unused struct io *io, int evt, __unused void *arg)
1197 ce062d50 2019-08-21 martijn switch (evt) {
1198 ce062d50 2019-08-21 martijn case IO_LOWAT:
1199 ce062d50 2019-08-21 martijn return;
1200 ce062d50 2019-08-21 martijn case IO_DISCONNECTED:
1201 ce062d50 2019-08-21 martijn exit(0);
1202 ce062d50 2019-08-21 martijn default:
1203 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Unexpectd event");
1207 ce062d50 2019-08-21 martijn static void
1208 6258daeb 2019-11-14 martijn osmtpd_noargs(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1209 6258daeb 2019-11-14 martijn __unused char *params, __unused char *linedup)
1211 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *);
1213 ce062d50 2019-08-21 martijn f = cb->cb;
1214 ce062d50 2019-08-21 martijn f(ctx);
1217 ce062d50 2019-08-21 martijn static void
1218 ce062d50 2019-08-21 martijn osmtpd_onearg(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx, char *line,
1219 6258daeb 2019-11-14 martijn __unused char *linedup)
1221 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, const char *);
1223 ce062d50 2019-08-21 martijn f = cb->cb;
1224 ce062d50 2019-08-21 martijn f(ctx, line);
1227 ce062d50 2019-08-21 martijn static void
1228 ce062d50 2019-08-21 martijn osmtpd_connect(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx, char *params,
1229 ce062d50 2019-08-21 martijn char *linedup)
1231 ce062d50 2019-08-21 martijn struct sockaddr_storage ss;
1232 ce062d50 2019-08-21 martijn char *hostname;
1233 ce062d50 2019-08-21 martijn char *address;
1234 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, const char *, struct sockaddr_storage *);
1236 ce062d50 2019-08-21 martijn hostname = params;
1237 ce062d50 2019-08-21 martijn if ((address = strchr(params, '|')) == NULL)
1238 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1239 c6cb29f3 2019-08-22 martijn linedup);
1240 ce062d50 2019-08-21 martijn address++[0] = '\0';
1242 ce062d50 2019-08-21 martijn osmtpd_addrtoss(address, &ss, 0, linedup);
1244 ce062d50 2019-08-21 martijn f = cb->cb;
1245 ce062d50 2019-08-21 martijn f(ctx, hostname, &ss);
1248 ce062d50 2019-08-21 martijn static void
1249 421c9a86 2019-09-06 martijn osmtpd_identify(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1250 6258daeb 2019-11-14 martijn char *identity, __unused char *linedup)
1252 421c9a86 2019-09-06 martijn void (*f)(struct osmtpd_ctx *, const char *);
1254 421c9a86 2019-09-06 martijn if (cb->storereport) {
1255 421c9a86 2019-09-06 martijn free(ctx->identity);
1256 421c9a86 2019-09-06 martijn if ((ctx->identity = strdup(identity)) == NULL)
1257 421c9a86 2019-09-06 martijn osmtpd_err(1, "strdup");
1260 421c9a86 2019-09-06 martijn f = cb->cb;
1261 421c9a86 2019-09-06 martijn f(ctx, identity);
1264 421c9a86 2019-09-06 martijn static void
1265 ce062d50 2019-08-21 martijn osmtpd_link_connect(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1266 ce062d50 2019-08-21 martijn char *params, char *linedup)
1268 30f1cbac 2019-08-22 martijn char *end, *rdns;
1269 30f1cbac 2019-08-22 martijn enum osmtpd_status fcrdns;
1270 ce062d50 2019-08-21 martijn struct sockaddr_storage src, dst;
1271 30f1cbac 2019-08-22 martijn void (*f)(struct osmtpd_ctx *, const char *, enum osmtpd_status,
1272 c6cb29f3 2019-08-22 martijn struct sockaddr_storage *, struct sockaddr_storage *);
1274 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1275 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing fcrdns: %s",
1276 c6cb29f3 2019-08-22 martijn linedup);
1277 ce062d50 2019-08-21 martijn end++[0] = '\0';
1278 ce062d50 2019-08-21 martijn rdns = params;
1279 ce062d50 2019-08-21 martijn params = end;
1280 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1281 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing src: %s",
1282 c6cb29f3 2019-08-22 martijn linedup);
1283 ce062d50 2019-08-21 martijn end++[0] = '\0';
1284 30f1cbac 2019-08-22 martijn if (strcmp(params, "pass") == 0)
1285 30f1cbac 2019-08-22 martijn fcrdns = OSMTPD_STATUS_OK;
1286 30f1cbac 2019-08-22 martijn else if (strcmp(params, "fail") == 0)
1287 30f1cbac 2019-08-22 martijn fcrdns = OSMTPD_STATUS_PERMFAIL;
1288 30f1cbac 2019-08-22 martijn else if (strcmp(params, "error") == 0)
1289 30f1cbac 2019-08-22 martijn fcrdns = OSMTPD_STATUS_TEMPFAIL;
1291 30f1cbac 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid fcrdns: %s",
1292 30f1cbac 2019-08-22 martijn linedup);
1293 ce062d50 2019-08-21 martijn params = end;
1294 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1295 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing dst: %s",
1296 c6cb29f3 2019-08-22 martijn linedup);
1297 ce062d50 2019-08-21 martijn end++[0] = '\0';
1298 ce062d50 2019-08-21 martijn osmtpd_addrtoss(params, &src, 1, linedup);
1299 ce062d50 2019-08-21 martijn params = end;
1300 ce062d50 2019-08-21 martijn osmtpd_addrtoss(params, &dst, 1, linedup);
1301 ce062d50 2019-08-21 martijn if (cb->storereport) {
1302 30f1cbac 2019-08-22 martijn if ((ctx->rdns = strdup(rdns)) == NULL)
1303 30f1cbac 2019-08-22 martijn osmtpd_err(1, "strdup");
1304 30f1cbac 2019-08-22 martijn ctx->fcrdns = fcrdns;
1305 ce062d50 2019-08-21 martijn memcpy(&(ctx->src), &src, sizeof(ctx->src));
1306 ce062d50 2019-08-21 martijn memcpy(&(ctx->dst), &dst, sizeof(ctx->dst));
1308 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1309 ce062d50 2019-08-21 martijn f(ctx, rdns, fcrdns, &src, &dst);
1312 ce062d50 2019-08-21 martijn static void
1313 ce062d50 2019-08-21 martijn osmtpd_link_disconnect(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1314 6258daeb 2019-11-14 martijn __unused char *param, __unused char *linedup)
1316 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *);
1317 ce062d50 2019-08-21 martijn size_t i;
1318 ce062d50 2019-08-21 martijn struct osmtpd_session *session, search;
1320 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1321 ce062d50 2019-08-21 martijn f(ctx);
1323 ce062d50 2019-08-21 martijn search.ctx.reqid = ctx->reqid;
1324 ce062d50 2019-08-21 martijn session = RB_FIND(osmtpd_sessions, &osmtpd_sessions, &search);
1325 ce062d50 2019-08-21 martijn if (session != NULL) {
1326 ce062d50 2019-08-21 martijn RB_REMOVE(osmtpd_sessions, &osmtpd_sessions, session);
1327 912d0ff2 2019-08-22 martijn if (ondeletecb_session != NULL)
1328 912d0ff2 2019-08-22 martijn ondeletecb_session(ctx, session->ctx.local_session);
1329 ce062d50 2019-08-21 martijn free(session->ctx.rdns);
1330 0fb4c799 2019-09-05 martijn free(session->ctx.identity);
1331 0fb4c799 2019-09-05 martijn free(session->ctx.greeting.identity);
1332 ce062d50 2019-08-21 martijn free(session->ctx.ciphers);
1333 ce062d50 2019-08-21 martijn free(session->ctx.mailfrom);
1334 ce062d50 2019-08-21 martijn for (i = 0; session->ctx.rcptto[i] != NULL; i++)
1335 ce062d50 2019-08-21 martijn free(session->ctx.rcptto[i]);
1336 ce062d50 2019-08-21 martijn free(session->ctx.rcptto);
1337 ce062d50 2019-08-21 martijn free(session);
1341 ce062d50 2019-08-21 martijn static void
1342 a05d5c54 2019-08-28 martijn osmtpd_link_greeting(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1343 6258daeb 2019-11-14 martijn char *identity, __unused char *linedup)
1345 a05d5c54 2019-08-28 martijn void (*f)(struct osmtpd_ctx *, const char *);
1347 a05d5c54 2019-08-28 martijn if (cb->storereport) {
1348 421c9a86 2019-09-06 martijn free(ctx->greeting.identity);
1349 0fb4c799 2019-09-05 martijn if ((ctx->greeting.identity = strdup(identity)) == NULL)
1350 a05d5c54 2019-08-28 martijn osmtpd_err(1, NULL);
1353 a05d5c54 2019-08-28 martijn if ((f = cb->cb) != NULL)
1354 a05d5c54 2019-08-28 martijn f(ctx, identity);
1357 a05d5c54 2019-08-28 martijn static void
1358 ce062d50 2019-08-21 martijn osmtpd_link_identify(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1359 6258daeb 2019-11-14 martijn char *identity, __unused char *linedup)
1361 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, const char *);
1363 ce062d50 2019-08-21 martijn if (cb->storereport) {
1364 421c9a86 2019-09-06 martijn free(ctx->identity);
1365 0fb4c799 2019-09-05 martijn if ((ctx->identity = strdup(identity)) == NULL)
1366 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1369 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1370 ce062d50 2019-08-21 martijn f(ctx, identity);
1373 ce062d50 2019-08-21 martijn static void
1374 ce062d50 2019-08-21 martijn osmtpd_link_tls(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1375 6258daeb 2019-11-14 martijn char *ciphers, __unused char *linedup)
1377 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, const char *);
1379 ce062d50 2019-08-21 martijn if (cb->storereport) {
1380 ce062d50 2019-08-21 martijn if ((ctx->ciphers = strdup(ciphers)) == NULL)
1381 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1384 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1385 ce062d50 2019-08-21 martijn f(ctx, ciphers);
1388 ce062d50 2019-08-21 martijn static void
1389 ce062d50 2019-08-21 martijn osmtpd_tx_begin(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1390 ce062d50 2019-08-21 martijn char *msgid, char *linedup)
1392 ce062d50 2019-08-21 martijn unsigned long imsgid;
1393 ce062d50 2019-08-21 martijn char *endptr;
1394 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t);
1396 ce062d50 2019-08-21 martijn errno = 0;
1397 ce062d50 2019-08-21 martijn imsgid = strtoul(msgid, &endptr, 16);
1398 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0) || endptr[0] != '\0')
1399 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1400 c6cb29f3 2019-08-22 martijn linedup);
1401 ce062d50 2019-08-21 martijn ctx->msgid = imsgid;
1402 ce062d50 2019-08-21 martijn /* Check if we're in range */
1403 ce062d50 2019-08-21 martijn if ((unsigned long) ctx->msgid != imsgid)
1404 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1405 c6cb29f3 2019-08-22 martijn linedup);
1407 ce062d50 2019-08-21 martijn if (!cb->storereport)
1408 ce062d50 2019-08-21 martijn ctx->msgid = 0;
1410 912d0ff2 2019-08-22 martijn if (oncreatecb_message != NULL)
1411 912d0ff2 2019-08-22 martijn ctx->local_message = oncreatecb_message(ctx);
1413 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1414 ce062d50 2019-08-21 martijn f(ctx, imsgid);
1417 ce062d50 2019-08-21 martijn static void
1418 ce062d50 2019-08-21 martijn osmtpd_tx_mail(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1419 ce062d50 2019-08-21 martijn char *params, char *linedup)
1421 ce062d50 2019-08-21 martijn char *end, *mailfrom;
1422 53b354a9 2020-04-12 martijn enum osmtpd_status status;
1423 ce062d50 2019-08-21 martijn unsigned long imsgid;
1424 ce062d50 2019-08-21 martijn uint32_t msgid;
1425 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t, const char *,
1426 ce062d50 2019-08-21 martijn enum osmtpd_status);
1428 ce062d50 2019-08-21 martijn errno = 0;
1429 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1430 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1431 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1432 c6cb29f3 2019-08-22 martijn linedup);
1433 ce062d50 2019-08-21 martijn if (end[0] != '|')
1434 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1435 c6cb29f3 2019-08-22 martijn linedup);
1436 ce062d50 2019-08-21 martijn msgid = imsgid;
1437 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1438 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1439 c6cb29f3 2019-08-22 martijn linedup);
1440 ce062d50 2019-08-21 martijn params = end + 1;
1442 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1443 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing status: %s",
1444 c6cb29f3 2019-08-22 martijn linedup);
1445 ce062d50 2019-08-21 martijn end++[0] = '\0';
1446 53b354a9 2020-04-12 martijn if (ctx->version_major == 0 && ctx->version_minor < 6) {
1447 53b354a9 2020-04-12 martijn mailfrom = params;
1448 53b354a9 2020-04-12 martijn status = osmtpd_strtostatus(end, linedup);
1449 53b354a9 2020-04-12 martijn } else {
1450 53b354a9 2020-04-12 martijn mailfrom = end;
1451 53b354a9 2020-04-12 martijn status = osmtpd_strtostatus(params, linedup);
1453 ce062d50 2019-08-21 martijn if (cb->storereport) {
1454 ce062d50 2019-08-21 martijn if ((ctx->mailfrom = strdup(mailfrom)) == NULL)
1455 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1458 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1459 53b354a9 2020-04-12 martijn f(ctx, msgid, mailfrom, status);
1462 ce062d50 2019-08-21 martijn static void
1463 ce062d50 2019-08-21 martijn osmtpd_tx_rcpt(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1464 ce062d50 2019-08-21 martijn char *params, char *linedup)
1466 ce062d50 2019-08-21 martijn char *end, *rcptto;
1467 53b354a9 2020-04-12 martijn enum osmtpd_status status;
1468 ce062d50 2019-08-21 martijn unsigned long imsgid;
1469 ce062d50 2019-08-21 martijn uint32_t msgid;
1470 ce062d50 2019-08-21 martijn size_t i;
1471 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t, const char *,
1472 ce062d50 2019-08-21 martijn enum osmtpd_status);
1474 ce062d50 2019-08-21 martijn errno = 0;
1475 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1476 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1477 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1478 c6cb29f3 2019-08-22 martijn linedup);
1479 ce062d50 2019-08-21 martijn if (end[0] != '|')
1480 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1481 c6cb29f3 2019-08-22 martijn linedup);
1482 ce062d50 2019-08-21 martijn msgid = imsgid;
1483 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1484 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1485 c6cb29f3 2019-08-22 martijn linedup);
1486 ce062d50 2019-08-21 martijn params = end + 1;
1488 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1489 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing status: %s",
1490 c6cb29f3 2019-08-22 martijn linedup);
1491 ce062d50 2019-08-21 martijn end++[0] = '\0';
1493 53b354a9 2020-04-12 martijn if (ctx->version_major == 0 && ctx->version_minor < 6) {
1494 53b354a9 2020-04-12 martijn rcptto = params;
1495 53b354a9 2020-04-12 martijn status = osmtpd_strtostatus(end, linedup);
1496 53b354a9 2020-04-12 martijn } else {
1497 53b354a9 2020-04-12 martijn rcptto = end;
1498 53b354a9 2020-04-12 martijn status = osmtpd_strtostatus(params, linedup);
1501 ce062d50 2019-08-21 martijn if (cb->storereport) {
1502 ce062d50 2019-08-21 martijn for (i = 0; ctx->rcptto[i] != NULL; i++)
1504 ce062d50 2019-08-21 martijn ctx->rcptto = reallocarray(ctx->rcptto, i + 2,
1505 ce062d50 2019-08-21 martijn sizeof(*(ctx->rcptto)));
1506 ce062d50 2019-08-21 martijn if (ctx->rcptto == NULL)
1507 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1509 ce062d50 2019-08-21 martijn if ((ctx->rcptto[i] = strdup(rcptto)) == NULL)
1510 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1511 ce062d50 2019-08-21 martijn ctx->rcptto[i + 1] = NULL;
1514 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1515 53b354a9 2020-04-12 martijn f(ctx, msgid, rcptto, status);
1518 ce062d50 2019-08-21 martijn static void
1519 ce062d50 2019-08-21 martijn osmtpd_tx_envelope(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1520 ce062d50 2019-08-21 martijn char *params, char *linedup)
1522 ce062d50 2019-08-21 martijn unsigned long imsgid;
1523 ce062d50 2019-08-21 martijn uint32_t msgid;
1524 ce062d50 2019-08-21 martijn uint64_t evpid;
1525 ce062d50 2019-08-21 martijn char *end;
1526 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t, uint64_t);
1528 ce062d50 2019-08-21 martijn errno = 0;
1529 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1530 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1531 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1532 c6cb29f3 2019-08-22 martijn linedup);
1533 ce062d50 2019-08-21 martijn if (end[0] != '|')
1534 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1535 c6cb29f3 2019-08-22 martijn linedup);
1536 ce062d50 2019-08-21 martijn msgid = imsgid;
1537 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1538 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1539 c6cb29f3 2019-08-22 martijn linedup);
1540 ce062d50 2019-08-21 martijn params = end + 1;
1542 ce062d50 2019-08-21 martijn evpid = strtoull(params, &end, 16);
1543 c6cb29f3 2019-08-22 martijn if ((ctx->evpid == ULLONG_MAX && errno != 0) ||
1544 ce062d50 2019-08-21 martijn end[0] != '\0')
1545 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid evpid: %s",
1546 c6cb29f3 2019-08-22 martijn linedup);
1547 ce062d50 2019-08-21 martijn if (cb->storereport)
1548 ce062d50 2019-08-21 martijn ctx->evpid = evpid;
1550 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1551 ce062d50 2019-08-21 martijn f(ctx, msgid, evpid);
1554 ce062d50 2019-08-21 martijn static void
1555 ce062d50 2019-08-21 martijn osmtpd_tx_data(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1556 ce062d50 2019-08-21 martijn char *params, char *linedup)
1558 ce062d50 2019-08-21 martijn char *end;
1559 ce062d50 2019-08-21 martijn unsigned long imsgid;
1560 ce062d50 2019-08-21 martijn uint32_t msgid;
1561 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t, enum osmtpd_status);
1563 ce062d50 2019-08-21 martijn errno = 0;
1564 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1565 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1566 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1567 c6cb29f3 2019-08-22 martijn linedup);
1568 ce062d50 2019-08-21 martijn if (end[0] != '|')
1569 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1570 c6cb29f3 2019-08-22 martijn linedup);
1571 ce062d50 2019-08-21 martijn msgid = imsgid;
1572 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1573 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1574 c6cb29f3 2019-08-22 martijn linedup);
1575 ce062d50 2019-08-21 martijn params = end + 1;
1577 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1578 ce062d50 2019-08-21 martijn f(ctx, msgid, osmtpd_strtostatus(params, linedup));
1581 ce062d50 2019-08-21 martijn static void
1582 ce062d50 2019-08-21 martijn osmtpd_tx_commit(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1583 ce062d50 2019-08-21 martijn char *params, char *linedup)
1585 ce062d50 2019-08-21 martijn char *end;
1586 332b3141 2019-08-22 martijn const char *errstr = NULL;
1587 ce062d50 2019-08-21 martijn unsigned long imsgid;
1588 ce062d50 2019-08-21 martijn uint32_t msgid;
1589 ce062d50 2019-08-21 martijn size_t i, msgsz;
1590 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t, size_t);
1592 ce062d50 2019-08-21 martijn errno = 0;
1593 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1594 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1595 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1596 c6cb29f3 2019-08-22 martijn linedup);
1597 ce062d50 2019-08-21 martijn if (end[0] != '|')
1598 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1599 c6cb29f3 2019-08-22 martijn linedup);
1600 ce062d50 2019-08-21 martijn msgid = imsgid;
1601 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
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 params = end + 1;
1606 332b3141 2019-08-22 martijn msgsz = strtonum(params, 0, UINT32_MAX, &errstr);
1607 ce062d50 2019-08-21 martijn if (errstr != NULL)
1608 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msg size: %s",
1609 c6cb29f3 2019-08-22 martijn linedup);
1611 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1612 ce062d50 2019-08-21 martijn f(ctx, msgid, msgsz);
1614 912d0ff2 2019-08-22 martijn if (ondeletecb_message != NULL) {
1615 912d0ff2 2019-08-22 martijn ondeletecb_message(ctx, ctx->local_message);
1616 912d0ff2 2019-08-22 martijn ctx->local_message = NULL;
1619 912d0ff2 2019-08-22 martijn free(ctx->mailfrom);
1620 912d0ff2 2019-08-22 martijn ctx->mailfrom = NULL;
1622 912d0ff2 2019-08-22 martijn for (i = 0; ctx->rcptto[i] != NULL; i++)
1623 912d0ff2 2019-08-22 martijn free(ctx->rcptto[i]);
1624 912d0ff2 2019-08-22 martijn ctx->rcptto[0] = NULL;
1625 912d0ff2 2019-08-22 martijn ctx->evpid = 0;
1626 912d0ff2 2019-08-22 martijn ctx->msgid = 0;
1629 ce062d50 2019-08-21 martijn static void
1630 ce062d50 2019-08-21 martijn osmtpd_tx_rollback(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx,
1631 ce062d50 2019-08-21 martijn char *params, char *linedup)
1633 ce062d50 2019-08-21 martijn char *end;
1634 ce062d50 2019-08-21 martijn unsigned long imsgid;
1635 ce062d50 2019-08-21 martijn uint32_t msgid;
1636 ce062d50 2019-08-21 martijn size_t i;
1637 ce062d50 2019-08-21 martijn void (*f)(struct osmtpd_ctx *, uint32_t);
1639 ce062d50 2019-08-21 martijn errno = 0;
1640 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1641 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1642 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1643 c6cb29f3 2019-08-22 martijn linedup);
1644 ce062d50 2019-08-21 martijn if (end[0] != '\0')
1645 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1646 c6cb29f3 2019-08-22 martijn linedup);
1647 ce062d50 2019-08-21 martijn msgid = imsgid;
1648 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1649 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1650 c6cb29f3 2019-08-22 martijn linedup);
1652 ce062d50 2019-08-21 martijn if ((f = cb->cb) != NULL)
1653 ce062d50 2019-08-21 martijn f(ctx, msgid);
1655 912d0ff2 2019-08-22 martijn if (ondeletecb_message != NULL) {
1656 912d0ff2 2019-08-22 martijn ondeletecb_message(ctx, ctx->local_message);
1657 912d0ff2 2019-08-22 martijn ctx->local_message = NULL;
1660 ce062d50 2019-08-21 martijn free(ctx->mailfrom);
1661 ce062d50 2019-08-21 martijn ctx->mailfrom = NULL;
1663 ce062d50 2019-08-21 martijn for (i = 0; ctx->rcptto[i] != NULL; i++)
1664 ce062d50 2019-08-21 martijn free(ctx->rcptto[i]);
1665 ce062d50 2019-08-21 martijn ctx->rcptto[0] = NULL;
1666 ce062d50 2019-08-21 martijn ctx->evpid = 0;
1667 ce062d50 2019-08-21 martijn ctx->msgid = 0;
1671 ce062d50 2019-08-21 martijn osmtpd_filter_proceed(struct osmtpd_ctx *ctx)
1673 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1674 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1675 06220a70 2019-12-06 martijn "proceed\n", ctx->token, ctx->reqid);
1677 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1678 06220a70 2019-12-06 martijn "proceed\n", ctx->reqid, ctx->token);
1682 ce062d50 2019-08-21 martijn osmtpd_filter_reject(struct osmtpd_ctx *ctx, int code, const char *reason, ...)
1684 ce062d50 2019-08-21 martijn va_list ap;
1686 ce062d50 2019-08-21 martijn if (code < 200 || code > 599)
1687 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid reject code");
1689 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1690 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1691 06220a70 2019-12-06 martijn "reject|%d ", ctx->token, ctx->reqid, code);
1693 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1694 06220a70 2019-12-06 martijn "reject|%d ", ctx->reqid, ctx->token, code);
1695 ce062d50 2019-08-21 martijn va_start(ap, reason);
1696 ce062d50 2019-08-21 martijn io_vprintf(io_stdout, reason, ap);
1697 ce062d50 2019-08-21 martijn va_end(ap);
1698 ce062d50 2019-08-21 martijn io_printf(io_stdout, "\n");
1702 000aebbc 2019-08-23 martijn osmtpd_filter_reject_enh(struct osmtpd_ctx *ctx, int code, int class,
1703 000aebbc 2019-08-23 martijn int subject, int detail, const char *reason, ...)
1705 000aebbc 2019-08-23 martijn va_list ap;
1707 000aebbc 2019-08-23 martijn if (code < 200 || code > 599)
1708 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid reject code");
1709 2a3d7bdf 2019-08-27 martijn if (class < 2 || class > 5)
1710 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid enhanced status class");
1711 000aebbc 2019-08-23 martijn if (subject < 0 || subject > 999)
1712 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid enhanced status subject");
1713 000aebbc 2019-08-23 martijn if (detail < 0 || detail > 999)
1714 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid enhanced status detail");
1716 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1717 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1718 06220a70 2019-12-06 martijn "reject|%d %d.%d.%d ", ctx->token, ctx->reqid, code, class,
1719 06220a70 2019-12-06 martijn subject, detail);
1721 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1722 06220a70 2019-12-06 martijn "reject|%d %d.%d.%d ", ctx->reqid, ctx->token, code, class,
1723 06220a70 2019-12-06 martijn subject, detail);
1724 000aebbc 2019-08-23 martijn va_start(ap, reason);
1725 000aebbc 2019-08-23 martijn io_vprintf(io_stdout, reason, ap);
1726 000aebbc 2019-08-23 martijn va_end(ap);
1727 000aebbc 2019-08-23 martijn io_printf(io_stdout, "\n");
1731 ce062d50 2019-08-21 martijn osmtpd_filter_disconnect(struct osmtpd_ctx *ctx, const char *reason, ...)
1733 ce062d50 2019-08-21 martijn va_list ap;
1735 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1736 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1737 06220a70 2019-12-06 martijn "disconnect|421 ", ctx->token, ctx->reqid);
1739 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1740 06220a70 2019-12-06 martijn "disconnect|421 ", ctx->reqid, ctx->token);
1741 ce062d50 2019-08-21 martijn va_start(ap, reason);
1742 ce062d50 2019-08-21 martijn io_vprintf(io_stdout, reason, ap);
1743 ce062d50 2019-08-21 martijn va_end(ap);
1744 ce062d50 2019-08-21 martijn io_printf(io_stdout, "\n");
1748 000aebbc 2019-08-23 martijn osmtpd_filter_disconnect_enh(struct osmtpd_ctx *ctx, int class, int subject,
1749 000aebbc 2019-08-23 martijn int detail, const char *reason, ...)
1751 000aebbc 2019-08-23 martijn va_list ap;
1753 000aebbc 2019-08-23 martijn if (class <= 2 || class >= 5)
1754 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid enhanced status class");
1755 000aebbc 2019-08-23 martijn if (subject < 0 || subject > 999)
1756 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid enhanced status subject");
1757 000aebbc 2019-08-23 martijn if (detail < 0 || detail > 999)
1758 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid enhanced status detail");
1759 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1760 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1761 06220a70 2019-12-06 martijn "disconnect|421 %d.%d.%d ", ctx->token, ctx->reqid, class,
1762 06220a70 2019-12-06 martijn subject, detail);
1764 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1765 06220a70 2019-12-06 martijn "disconnect|421 %d.%d.%d ", ctx->reqid, ctx->token, class,
1766 06220a70 2019-12-06 martijn subject, detail);
1767 000aebbc 2019-08-23 martijn va_start(ap, reason);
1768 000aebbc 2019-08-23 martijn io_vprintf(io_stdout, reason, ap);
1769 000aebbc 2019-08-23 martijn va_end(ap);
1770 000aebbc 2019-08-23 martijn io_printf(io_stdout, "\n");
1774 4fb72612 2019-08-21 martijn osmtpd_filter_rewrite(struct osmtpd_ctx *ctx, const char *value, ...)
1776 4fb72612 2019-08-21 martijn va_list ap;
1778 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1779 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1780 06220a70 2019-12-06 martijn "rewrite|", ctx->token, ctx->reqid);
1782 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1783 06220a70 2019-12-06 martijn "rewrite|", ctx->reqid, ctx->token);
1784 4fb72612 2019-08-21 martijn va_start(ap, value);
1785 4fb72612 2019-08-21 martijn io_vprintf(io_stdout, value, ap);
1786 4fb72612 2019-08-21 martijn va_end(ap);
1787 4fb72612 2019-08-21 martijn io_printf(io_stdout, "\n");
1791 ce062d50 2019-08-21 martijn osmtpd_filter_dataline(struct osmtpd_ctx *ctx, const char *line, ...)
1793 ce062d50 2019-08-21 martijn va_list ap;
1795 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1796 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-dataline|%016"PRIx64"|%016"PRIx64"|",
1797 06220a70 2019-12-06 martijn ctx->token, ctx->reqid);
1799 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-dataline|%016"PRIx64"|%016"PRIx64"|",
1800 06220a70 2019-12-06 martijn ctx->reqid, ctx->token);
1801 ce062d50 2019-08-21 martijn va_start(ap, line);
1802 ce062d50 2019-08-21 martijn io_vprintf(io_stdout, line, ap);
1803 ce062d50 2019-08-21 martijn va_end(ap);
1804 ce062d50 2019-08-21 martijn io_printf(io_stdout, "\n");
1807 ce062d50 2019-08-21 martijn static void
1808 ce062d50 2019-08-21 martijn osmtpd_register(enum osmtpd_type type, enum osmtpd_phase phase, int incoming,
1809 ce062d50 2019-08-21 martijn int storereport, void *cb)
1811 ce062d50 2019-08-21 martijn size_t i;
1813 ce062d50 2019-08-21 martijn if (ready)
1814 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Can't register when proc is running");
1816 ce062d50 2019-08-21 martijn for (i = 0; i < NITEMS(osmtpd_callbacks); i++) {
1817 ce062d50 2019-08-21 martijn if (type == osmtpd_callbacks[i].type &&
1818 ce062d50 2019-08-21 martijn phase == osmtpd_callbacks[i].phase &&
1819 ce062d50 2019-08-21 martijn incoming == osmtpd_callbacks[i].incoming) {
1820 ce062d50 2019-08-21 martijn if (osmtpd_callbacks[i].cb != NULL && cb != NULL)
1821 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Event already registered");
1822 912d0ff2 2019-08-22 martijn if (cb != NULL)
1823 912d0ff2 2019-08-22 martijn osmtpd_callbacks[i].cb = cb;
1824 ce062d50 2019-08-21 martijn osmtpd_callbacks[i].doregister = 1;
1825 ce062d50 2019-08-21 martijn if (storereport)
1826 ce062d50 2019-08-21 martijn osmtpd_callbacks[i].storereport = 1;
1827 ce062d50 2019-08-21 martijn return;
1830 ce062d50 2019-08-21 martijn /* NOT REACHED */
1831 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Trying to register unknown event");
1834 ce062d50 2019-08-21 martijn static enum osmtpd_phase
1835 ce062d50 2019-08-21 martijn osmtpd_strtophase(const char *phase, const char *linedup)
1837 ce062d50 2019-08-21 martijn if (strcmp(phase, "connect") == 0)
1838 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_CONNECT;
1839 ce062d50 2019-08-21 martijn if (strcmp(phase, "helo") == 0)
1840 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_HELO;
1841 ce062d50 2019-08-21 martijn if (strcmp(phase, "ehlo") == 0)
1842 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_EHLO;
1843 ce062d50 2019-08-21 martijn if (strcmp(phase, "starttls") == 0)
1844 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_STARTTLS;
1845 ce062d50 2019-08-21 martijn if (strcmp(phase, "auth") == 0)
1846 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_AUTH;
1847 ce062d50 2019-08-21 martijn if (strcmp(phase, "mail-from") == 0)
1848 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_MAIL_FROM;
1849 ce062d50 2019-08-21 martijn if (strcmp(phase, "rcpt-to") == 0)
1850 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_RCPT_TO;
1851 ce062d50 2019-08-21 martijn if (strcmp(phase, "data") == 0)
1852 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_DATA;
1853 ce062d50 2019-08-21 martijn if (strcmp(phase, "data-line") == 0)
1854 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_DATA_LINE;
1855 ce062d50 2019-08-21 martijn if (strcmp(phase, "rset") == 0)
1856 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_RSET;
1857 ce062d50 2019-08-21 martijn if (strcmp(phase, "quit") == 0)
1858 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_QUIT;
1859 ce062d50 2019-08-21 martijn if (strcmp(phase, "noop") == 0)
1860 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_NOOP;
1861 ce062d50 2019-08-21 martijn if (strcmp(phase, "help") == 0)
1862 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_HELP;
1863 ce062d50 2019-08-21 martijn if (strcmp(phase, "wiz") == 0)
1864 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_WIZ;
1865 ce062d50 2019-08-21 martijn if (strcmp(phase, "commit") == 0)
1866 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_COMMIT;
1867 ce062d50 2019-08-21 martijn if (strcmp(phase, "link-connect") == 0)
1868 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_LINK_CONNECT;
1869 ce062d50 2019-08-21 martijn if (strcmp(phase, "link-disconnect") == 0)
1870 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_LINK_DISCONNECT;
1871 b52f2785 2019-09-06 martijn if (strcmp(phase, "link-greeting") == 0)
1872 b52f2785 2019-09-06 martijn return OSMTPD_PHASE_LINK_GREETING;
1873 ce062d50 2019-08-21 martijn if (strcmp(phase, "link-identify") == 0)
1874 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_LINK_IDENTIFY;
1875 ce062d50 2019-08-21 martijn if (strcmp(phase, "link-tls") == 0)
1876 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_LINK_TLS;
1877 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-begin") == 0)
1878 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_BEGIN;
1879 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-mail") == 0)
1880 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_MAIL;
1881 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-rcpt") == 0)
1882 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_RCPT;
1883 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-envelope") == 0)
1884 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_ENVELOPE;
1885 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-data") == 0)
1886 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_DATA;
1887 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-commit") == 0)
1888 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_COMMIT;
1889 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-rollback") == 0)
1890 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_ROLLBACK;
1891 ce062d50 2019-08-21 martijn if (strcmp(phase, "protocol-client") == 0)
1892 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_PROTOCOL_CLIENT;
1893 ce062d50 2019-08-21 martijn if (strcmp(phase, "protocol-server") == 0)
1894 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_PROTOCOL_SERVER;
1895 ce062d50 2019-08-21 martijn if (strcmp(phase, "filter-response") == 0)
1896 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_FILTER_RESPONSE;
1897 ce062d50 2019-08-21 martijn if (strcmp(phase, "timeout") == 0)
1898 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TIMEOUT;
1899 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid phase: %s", linedup);
1902 ce062d50 2019-08-21 martijn static const char *
1903 ce062d50 2019-08-21 martijn osmtpd_typetostr(enum osmtpd_type type)
1905 ce062d50 2019-08-21 martijn switch (type) {
1906 ce062d50 2019-08-21 martijn case OSMTPD_TYPE_FILTER:
1907 ce062d50 2019-08-21 martijn return "filter";
1908 ce062d50 2019-08-21 martijn case OSMTPD_TYPE_REPORT:
1909 ce062d50 2019-08-21 martijn return "report";
1911 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "In valid type: %d\n", type);
1914 ce062d50 2019-08-21 martijn static const char *
1915 ce062d50 2019-08-21 martijn osmtpd_phasetostr(enum osmtpd_phase phase)
1917 ce062d50 2019-08-21 martijn switch (phase) {
1918 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_CONNECT:
1919 ce062d50 2019-08-21 martijn return "connect";
1920 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_HELO:
1921 ce062d50 2019-08-21 martijn return "helo";
1922 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_EHLO:
1923 ce062d50 2019-08-21 martijn return "ehlo";
1924 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_STARTTLS:
1925 ce062d50 2019-08-21 martijn return "starttls";
1926 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_AUTH:
1927 ce062d50 2019-08-21 martijn return "auth";
1928 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_MAIL_FROM:
1929 ce062d50 2019-08-21 martijn return "mail-from";
1930 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_RCPT_TO:
1931 ce062d50 2019-08-21 martijn return "rcpt-to";
1932 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_DATA:
1933 ce062d50 2019-08-21 martijn return "data";
1934 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_DATA_LINE:
1935 ce062d50 2019-08-21 martijn return "data-line";
1936 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_RSET:
1937 ce062d50 2019-08-21 martijn return "rset";
1938 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_QUIT:
1939 ce062d50 2019-08-21 martijn return "quit";
1940 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_NOOP:
1941 ce062d50 2019-08-21 martijn return "noop";
1942 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_HELP:
1943 ce062d50 2019-08-21 martijn return "help";
1944 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_WIZ:
1945 ce062d50 2019-08-21 martijn return "wiz";
1946 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_COMMIT:
1947 ce062d50 2019-08-21 martijn return "commit";
1948 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_LINK_CONNECT:
1949 ce062d50 2019-08-21 martijn return "link-connect";
1950 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_LINK_DISCONNECT:
1951 ce062d50 2019-08-21 martijn return "link-disconnect";
1952 a05d5c54 2019-08-28 martijn case OSMTPD_PHASE_LINK_GREETING:
1953 a05d5c54 2019-08-28 martijn return "link-greeting";
1954 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_LINK_IDENTIFY:
1955 ce062d50 2019-08-21 martijn return "link-identify";
1956 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_LINK_TLS:
1957 ce062d50 2019-08-21 martijn return "link-tls";
1958 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_BEGIN:
1959 ce062d50 2019-08-21 martijn return "tx-begin";
1960 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_MAIL:
1961 ce062d50 2019-08-21 martijn return "tx-mail";
1962 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_RCPT:
1963 ce062d50 2019-08-21 martijn return "tx-rcpt";
1964 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_ENVELOPE:
1965 ce062d50 2019-08-21 martijn return "tx-envelope";
1966 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_DATA:
1967 ce062d50 2019-08-21 martijn return "tx-data";
1968 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_COMMIT:
1969 ce062d50 2019-08-21 martijn return "tx-commit";
1970 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_ROLLBACK:
1971 ce062d50 2019-08-21 martijn return "tx-rollback";
1972 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_PROTOCOL_CLIENT:
1973 ce062d50 2019-08-21 martijn return "protocol-client";
1974 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_PROTOCOL_SERVER:
1975 ce062d50 2019-08-21 martijn return "protocol-server";
1976 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_FILTER_RESPONSE:
1977 ce062d50 2019-08-21 martijn return "filter-response";
1978 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TIMEOUT:
1979 ce062d50 2019-08-21 martijn return "timeout";
1981 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "In valid phase: %d\n", phase);
1984 53b354a9 2020-04-12 martijn static enum osmtpd_status
1985 53b354a9 2020-04-12 martijn osmtpd_strtostatus(const char *status, char *linedup)
1987 ce062d50 2019-08-21 martijn if (strcmp(status, "ok") == 0)
1988 ce062d50 2019-08-21 martijn return OSMTPD_STATUS_OK;
1989 ce062d50 2019-08-21 martijn else if (strcmp(status, "tempfail") == 0)
1990 ce062d50 2019-08-21 martijn return OSMTPD_STATUS_TEMPFAIL;
1991 ce062d50 2019-08-21 martijn else if (strcmp(status, "permfail") == 0)
1992 ce062d50 2019-08-21 martijn return OSMTPD_STATUS_PERMFAIL;
1993 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid status: %s\n", linedup);
1996 ce062d50 2019-08-21 martijn static void
1997 ce062d50 2019-08-21 martijn osmtpd_addrtoss(char *addr, struct sockaddr_storage *ss, int hasport,
1998 ce062d50 2019-08-21 martijn char *linedup)
2000 a37af028 2019-09-17 martijn char *port = NULL;
2001 ce062d50 2019-08-21 martijn const char *errstr = NULL;
2002 ce062d50 2019-08-21 martijn struct sockaddr_in *sin;
2003 ce062d50 2019-08-21 martijn struct sockaddr_in6 *sin6;
2004 ce062d50 2019-08-21 martijn struct sockaddr_un *sun;
2005 4574fbd0 2019-09-26 martijn size_t n;
2007 4574fbd0 2019-09-26 martijn if (addr[0] == '[') {
2008 ce062d50 2019-08-21 martijn sin6 = (struct sockaddr_in6 *)ss;
2009 ce062d50 2019-08-21 martijn sin6->sin6_family = AF_INET6;
2010 ce062d50 2019-08-21 martijn sin6->sin6_port = 0;
2011 ce062d50 2019-08-21 martijn if (hasport) {
2012 ce062d50 2019-08-21 martijn if ((port = strrchr(addr, ':')) == NULL)
2013 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
2014 ce062d50 2019-08-21 martijn "address (%s): %s", addr, linedup);
2015 4574fbd0 2019-09-26 martijn if (port[-1] != ']')
2016 4574fbd0 2019-09-26 martijn osmtpd_errx(1, "Invalid line received: invalid "
2017 4574fbd0 2019-09-26 martijn "address (%s): %s", addr, linedup);
2018 ce062d50 2019-08-21 martijn port++;
2019 ce062d50 2019-08-21 martijn sin6->sin6_port = htons(strtonum(port, 0, UINT16_MAX,
2020 ce062d50 2019-08-21 martijn &errstr));
2021 ce062d50 2019-08-21 martijn if (errstr != NULL)
2022 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
2023 ce062d50 2019-08-21 martijn "address (%s): %s", addr, linedup);
2024 4574fbd0 2019-09-26 martijn port[-2] = '\0';
2025 4574fbd0 2019-09-26 martijn } else {
2026 4574fbd0 2019-09-26 martijn n = strlen(addr);
2027 4574fbd0 2019-09-26 martijn if (addr[n - 1] != ']')
2028 4574fbd0 2019-09-26 martijn osmtpd_errx(1, "Invalid line received: invalid "
2029 4574fbd0 2019-09-26 martijn "address (%s): %s", addr, linedup);
2030 4574fbd0 2019-09-26 martijn addr[n - 1] = '\0';
2032 4574fbd0 2019-09-26 martijn switch (inet_pton(AF_INET6, addr + 1, &(sin6->sin6_addr))) {
2033 ce062d50 2019-08-21 martijn case 1:
2035 ce062d50 2019-08-21 martijn case 0:
2036 a37af028 2019-09-17 martijn if (hasport)
2037 4574fbd0 2019-09-26 martijn port[-2] = ']';
2039 4574fbd0 2019-09-26 martijn addr[n - 1] = ']';
2040 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid address "
2041 ce062d50 2019-08-21 martijn "(%s): %s", addr, linedup);
2042 ce062d50 2019-08-21 martijn default:
2043 a37af028 2019-09-17 martijn if (hasport)
2044 4574fbd0 2019-09-26 martijn port[-2] = ']';
2046 4574fbd0 2019-09-26 martijn addr[n - 1] = ']';
2047 c6cb29f3 2019-08-22 martijn osmtpd_err(1, "Can't parse address (%s): %s", addr,
2048 c6cb29f3 2019-08-22 martijn linedup);
2050 ce062d50 2019-08-21 martijn } else if (strncasecmp(addr, "unix:", 5) == 0) {
2051 ce062d50 2019-08-21 martijn sun = (struct sockaddr_un *)ss;
2052 ce062d50 2019-08-21 martijn sun->sun_family = AF_UNIX;
2053 ce062d50 2019-08-21 martijn if (strlcpy(sun->sun_path, addr,
2054 ce062d50 2019-08-21 martijn sizeof(sun->sun_path)) >= sizeof(sun->sun_path)) {
2055 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: address too "
2056 c6cb29f3 2019-08-22 martijn "long (%s): %s", addr, linedup);
2058 ce062d50 2019-08-21 martijn } else {
2059 ce062d50 2019-08-21 martijn sin = (struct sockaddr_in *)ss;
2060 ce062d50 2019-08-21 martijn sin->sin_family = AF_INET;
2061 ce062d50 2019-08-21 martijn sin->sin_port = 0;
2062 ce062d50 2019-08-21 martijn if (hasport) {
2063 ce062d50 2019-08-21 martijn if ((port = strrchr(addr, ':')) == NULL)
2064 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
2065 ce062d50 2019-08-21 martijn "address (%s): %s", addr, linedup);
2066 ce062d50 2019-08-21 martijn port++;
2067 ce062d50 2019-08-21 martijn sin->sin_port = htons(strtonum(port, 0, UINT16_MAX,
2068 ce062d50 2019-08-21 martijn &errstr));
2069 ce062d50 2019-08-21 martijn if (errstr != NULL)
2070 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
2071 ce062d50 2019-08-21 martijn "address (%s): %s", addr, linedup);
2072 ce062d50 2019-08-21 martijn port[-1] = '\0';
2074 ce062d50 2019-08-21 martijn switch (inet_pton(AF_INET, addr, &(sin->sin_addr))) {
2075 ce062d50 2019-08-21 martijn case 1:
2077 ce062d50 2019-08-21 martijn case 0:
2078 a37af028 2019-09-17 martijn if (hasport)
2079 a37af028 2019-09-17 martijn port[-1] = ':';
2080 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid address "
2081 ce062d50 2019-08-21 martijn "(%s): %s", addr, linedup);
2082 ce062d50 2019-08-21 martijn default:
2083 a37af028 2019-09-17 martijn if (hasport)
2084 a37af028 2019-09-17 martijn port[-1] = ':';
2085 c6cb29f3 2019-08-22 martijn osmtpd_err(1, "Can't parse address (%s): %s", addr,
2086 c6cb29f3 2019-08-22 martijn linedup);
2091 ce062d50 2019-08-21 martijn static int
2092 ce062d50 2019-08-21 martijn osmtpd_session_cmp(struct osmtpd_session *a, struct osmtpd_session *b)
2094 ce062d50 2019-08-21 martijn return a->ctx.reqid < b->ctx.reqid ? -1 : a->ctx.reqid > b->ctx.reqid;
2097 9e3e8410 2019-08-22 martijn RB_GENERATE_STATIC(osmtpd_sessions, osmtpd_session, entry, osmtpd_session_cmp);