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 866e5e0e 2025-02-03 martijn enum osmtpd_session_status {
45 866e5e0e 2025-02-03 martijn SESSION_OK = 0,
46 866e5e0e 2025-02-03 martijn SESSION_ERROR,
47 866e5e0e 2025-02-03 martijn SESSION_DISCONNECTED
50 866e5e0e 2025-02-03 martijn struct osmtpd_session {
51 866e5e0e 2025-02-03 martijn struct osmtpd_ctx ctx; /* Must remain first element */
52 866e5e0e 2025-02-03 martijn enum osmtpd_session_status status;
53 866e5e0e 2025-02-03 martijn RB_ENTRY(osmtpd_session) entry;
56 d229c123 2019-08-22 martijn struct osmtpd_callback {
57 d229c123 2019-08-22 martijn enum osmtpd_type type;
58 d229c123 2019-08-22 martijn enum osmtpd_phase phase;
59 d229c123 2019-08-22 martijn int incoming;
60 866e5e0e 2025-02-03 martijn void (*osmtpd_cb)(struct osmtpd_callback *, struct osmtpd_session *,
61 866e5e0e 2025-02-03 martijn char *, char *);
62 d229c123 2019-08-22 martijn void *cb;
63 d229c123 2019-08-22 martijn int doregister;
64 d229c123 2019-08-22 martijn int storereport;
67 d229c123 2019-08-22 martijn static void osmtpd_register(enum osmtpd_type, enum osmtpd_phase, int, int,
69 d229c123 2019-08-22 martijn static const char *osmtpd_typetostr(enum osmtpd_type);
70 d229c123 2019-08-22 martijn static const char *osmtpd_phasetostr(enum osmtpd_phase);
71 d229c123 2019-08-22 martijn static enum osmtpd_phase osmtpd_strtophase(const char *, const char *);
72 d229c123 2019-08-22 martijn static void osmtpd_newline(struct io *, int, void *);
73 d229c123 2019-08-22 martijn static void osmtpd_outevt(struct io *, int, void *);
74 866e5e0e 2025-02-03 martijn static void osmtpd_noargs(struct osmtpd_callback *, struct osmtpd_session *,
75 d229c123 2019-08-22 martijn char *, char *);
76 866e5e0e 2025-02-03 martijn static void osmtpd_onearg(struct osmtpd_callback *, struct osmtpd_session *,
77 d229c123 2019-08-22 martijn char *, char *);
78 866e5e0e 2025-02-03 martijn static void osmtpd_connect(struct osmtpd_callback *, struct osmtpd_session *,
79 d229c123 2019-08-22 martijn char *, char *);
80 866e5e0e 2025-02-03 martijn static void osmtpd_identify(struct osmtpd_callback *, struct osmtpd_session *,
81 421c9a86 2019-09-06 martijn char *, char *);
82 866e5e0e 2025-02-03 martijn static void osmtpd_link_connect(struct osmtpd_callback *, struct osmtpd_session *,
83 d229c123 2019-08-22 martijn char *, char *);
84 d229c123 2019-08-22 martijn static void osmtpd_link_disconnect(struct osmtpd_callback *,
85 866e5e0e 2025-02-03 martijn struct osmtpd_session *, char *, char *);
86 866e5e0e 2025-02-03 martijn static void osmtpd_link_greeting(struct osmtpd_callback *, struct osmtpd_session *,
87 a05d5c54 2019-08-28 martijn char *, char *);
88 866e5e0e 2025-02-03 martijn static void osmtpd_link_identify(struct osmtpd_callback *, struct osmtpd_session *,
89 d229c123 2019-08-22 martijn char *, char *);
90 866e5e0e 2025-02-03 martijn static void osmtpd_link_tls(struct osmtpd_callback *, struct osmtpd_session *,
91 d229c123 2019-08-22 martijn char *, char *);
92 866e5e0e 2025-02-03 martijn static void osmtpd_link_auth(struct osmtpd_callback *, struct osmtpd_session *,
93 58a6bc69 2022-12-05 martijn char *, char *);
94 d308c531 2025-02-03 martijn static void osmtpd_tx_reset(struct osmtpd_callback *, struct osmtpd_session *,
95 d308c531 2025-02-03 martijn char *, char *);
96 866e5e0e 2025-02-03 martijn static void osmtpd_tx_begin(struct osmtpd_callback *, struct osmtpd_session *,
97 d229c123 2019-08-22 martijn char *, char *);
98 866e5e0e 2025-02-03 martijn static void osmtpd_tx_mail(struct osmtpd_callback *, struct osmtpd_session *,
99 d229c123 2019-08-22 martijn char *, char *);
100 866e5e0e 2025-02-03 martijn static void osmtpd_tx_rcpt(struct osmtpd_callback *, struct osmtpd_session *,
101 d229c123 2019-08-22 martijn char *, char *);
102 866e5e0e 2025-02-03 martijn static void osmtpd_tx_envelope(struct osmtpd_callback *, struct osmtpd_session *,
103 d229c123 2019-08-22 martijn char *, char *);
104 866e5e0e 2025-02-03 martijn static void osmtpd_tx_data(struct osmtpd_callback *, struct osmtpd_session *,
105 d229c123 2019-08-22 martijn char *, char *);
106 866e5e0e 2025-02-03 martijn static void osmtpd_tx_commit(struct osmtpd_callback *, struct osmtpd_session *,
107 d229c123 2019-08-22 martijn char *, char *);
108 866e5e0e 2025-02-03 martijn static void osmtpd_tx_rollback(struct osmtpd_callback *, struct osmtpd_session *,
109 d229c123 2019-08-22 martijn char *, char *);
110 d229c123 2019-08-22 martijn static void osmtpd_addrtoss(char *, struct sockaddr_storage *, int, char *);
111 d229c123 2019-08-22 martijn static enum osmtpd_status osmtpd_strtostatus(const char *, char *);
112 d229c123 2019-08-22 martijn static int osmtpd_session_cmp(struct osmtpd_session *, struct osmtpd_session *);
113 912d0ff2 2019-08-22 martijn static void *(*oncreatecb_session)(struct osmtpd_ctx *) = NULL;
114 912d0ff2 2019-08-22 martijn static void (*ondeletecb_session)(struct osmtpd_ctx *, void *) = NULL;
115 912d0ff2 2019-08-22 martijn static void *(*oncreatecb_message)(struct osmtpd_ctx *) = NULL;
116 912d0ff2 2019-08-22 martijn static void (*ondeletecb_message)(struct osmtpd_ctx *, void *) = NULL;
117 2029083f 2020-10-15 martijn static void (*conf_cb)(const char *, const char *);
119 d229c123 2019-08-22 martijn static struct osmtpd_callback osmtpd_callbacks[] = {
121 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
122 d229c123 2019-08-22 martijn OSMTPD_PHASE_CONNECT,
124 d229c123 2019-08-22 martijn osmtpd_connect,
130 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
131 d229c123 2019-08-22 martijn OSMTPD_PHASE_HELO,
133 421c9a86 2019-09-06 martijn osmtpd_identify,
139 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
140 d229c123 2019-08-22 martijn OSMTPD_PHASE_EHLO,
142 421c9a86 2019-09-06 martijn osmtpd_identify,
148 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
149 d229c123 2019-08-22 martijn OSMTPD_PHASE_STARTTLS,
151 d229c123 2019-08-22 martijn osmtpd_noargs,
157 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
158 d229c123 2019-08-22 martijn OSMTPD_PHASE_AUTH,
160 d229c123 2019-08-22 martijn osmtpd_onearg,
166 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
167 d229c123 2019-08-22 martijn OSMTPD_PHASE_MAIL_FROM,
169 d229c123 2019-08-22 martijn osmtpd_onearg,
175 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
176 d229c123 2019-08-22 martijn OSMTPD_PHASE_RCPT_TO,
178 d229c123 2019-08-22 martijn osmtpd_onearg,
184 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
185 d229c123 2019-08-22 martijn OSMTPD_PHASE_DATA,
187 d229c123 2019-08-22 martijn osmtpd_noargs,
193 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
194 d229c123 2019-08-22 martijn OSMTPD_PHASE_DATA_LINE,
196 d229c123 2019-08-22 martijn osmtpd_onearg,
202 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
203 d229c123 2019-08-22 martijn OSMTPD_PHASE_RSET,
205 d229c123 2019-08-22 martijn osmtpd_noargs,
211 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
212 d229c123 2019-08-22 martijn OSMTPD_PHASE_QUIT,
214 d229c123 2019-08-22 martijn osmtpd_noargs,
220 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
221 d229c123 2019-08-22 martijn OSMTPD_PHASE_NOOP,
223 d229c123 2019-08-22 martijn osmtpd_noargs,
229 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
230 d229c123 2019-08-22 martijn OSMTPD_PHASE_HELP,
232 d229c123 2019-08-22 martijn osmtpd_noargs,
238 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
239 d229c123 2019-08-22 martijn OSMTPD_PHASE_WIZ,
241 d229c123 2019-08-22 martijn osmtpd_noargs,
247 d229c123 2019-08-22 martijn OSMTPD_TYPE_FILTER,
248 d229c123 2019-08-22 martijn OSMTPD_PHASE_COMMIT,
250 d229c123 2019-08-22 martijn osmtpd_noargs,
256 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
257 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_CONNECT,
259 d229c123 2019-08-22 martijn osmtpd_link_connect,
265 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
266 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_DISCONNECT,
268 d229c123 2019-08-22 martijn osmtpd_link_disconnect,
274 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
275 a05d5c54 2019-08-28 martijn OSMTPD_PHASE_LINK_GREETING,
277 a05d5c54 2019-08-28 martijn osmtpd_link_greeting,
283 a05d5c54 2019-08-28 martijn OSMTPD_TYPE_REPORT,
284 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_IDENTIFY,
286 d229c123 2019-08-22 martijn osmtpd_link_identify,
292 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
293 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_TLS,
295 d229c123 2019-08-22 martijn osmtpd_link_tls,
301 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
302 58a6bc69 2022-12-05 martijn OSMTPD_PHASE_LINK_AUTH,
304 58a6bc69 2022-12-05 martijn osmtpd_link_auth,
310 58a6bc69 2022-12-05 martijn OSMTPD_TYPE_REPORT,
311 d308c531 2025-02-03 martijn OSMTPD_PHASE_TX_RESET,
313 d308c531 2025-02-03 martijn osmtpd_tx_reset,
319 d308c531 2025-02-03 martijn OSMTPD_TYPE_REPORT,
320 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_BEGIN,
322 d229c123 2019-08-22 martijn osmtpd_tx_begin,
328 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
329 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_MAIL,
331 d229c123 2019-08-22 martijn osmtpd_tx_mail,
337 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
338 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_RCPT,
340 d229c123 2019-08-22 martijn osmtpd_tx_rcpt,
346 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
347 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_ENVELOPE,
349 d229c123 2019-08-22 martijn osmtpd_tx_envelope,
355 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
356 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_DATA,
358 d229c123 2019-08-22 martijn osmtpd_tx_data,
364 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
365 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_COMMIT,
367 d229c123 2019-08-22 martijn osmtpd_tx_commit,
373 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
374 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_ROLLBACK,
376 d229c123 2019-08-22 martijn osmtpd_tx_rollback,
382 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
383 d229c123 2019-08-22 martijn OSMTPD_PHASE_PROTOCOL_CLIENT,
385 d229c123 2019-08-22 martijn osmtpd_onearg,
391 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
392 d229c123 2019-08-22 martijn OSMTPD_PHASE_PROTOCOL_SERVER,
394 d229c123 2019-08-22 martijn osmtpd_onearg,
400 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
401 d229c123 2019-08-22 martijn OSMTPD_PHASE_FILTER_RESPONSE,
403 d229c123 2019-08-22 martijn osmtpd_onearg,
409 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
410 d229c123 2019-08-22 martijn OSMTPD_PHASE_TIMEOUT,
412 d229c123 2019-08-22 martijn osmtpd_noargs,
418 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
419 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_CONNECT,
421 d229c123 2019-08-22 martijn osmtpd_link_connect,
427 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
428 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_DISCONNECT,
430 d229c123 2019-08-22 martijn osmtpd_link_disconnect,
436 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
437 a05d5c54 2019-08-28 martijn OSMTPD_PHASE_LINK_GREETING,
439 a05d5c54 2019-08-28 martijn osmtpd_link_greeting,
445 a05d5c54 2019-08-28 martijn OSMTPD_TYPE_REPORT,
446 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_IDENTIFY,
448 d229c123 2019-08-22 martijn osmtpd_link_identify,
454 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
455 d229c123 2019-08-22 martijn OSMTPD_PHASE_LINK_TLS,
457 d229c123 2019-08-22 martijn osmtpd_link_tls,
463 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
464 58a6bc69 2022-12-05 martijn OSMTPD_PHASE_LINK_AUTH,
466 58a6bc69 2022-12-05 martijn osmtpd_link_auth,
472 58a6bc69 2022-12-05 martijn OSMTPD_TYPE_REPORT,
473 d308c531 2025-02-03 martijn OSMTPD_PHASE_TX_RESET,
475 d308c531 2025-02-03 martijn osmtpd_tx_reset,
481 d308c531 2025-02-03 martijn OSMTPD_TYPE_REPORT,
482 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_BEGIN,
484 d229c123 2019-08-22 martijn osmtpd_tx_begin,
490 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
491 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_MAIL,
493 d229c123 2019-08-22 martijn osmtpd_tx_mail,
499 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
500 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_RCPT,
502 d229c123 2019-08-22 martijn osmtpd_tx_rcpt,
508 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
509 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_ENVELOPE,
511 d229c123 2019-08-22 martijn osmtpd_tx_envelope,
517 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
518 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_DATA,
520 d229c123 2019-08-22 martijn osmtpd_tx_data,
526 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
527 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_COMMIT,
529 d229c123 2019-08-22 martijn osmtpd_tx_commit,
535 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
536 d229c123 2019-08-22 martijn OSMTPD_PHASE_TX_ROLLBACK,
538 d229c123 2019-08-22 martijn osmtpd_tx_rollback,
544 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
545 d229c123 2019-08-22 martijn OSMTPD_PHASE_PROTOCOL_CLIENT,
547 d229c123 2019-08-22 martijn osmtpd_onearg,
553 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
554 d229c123 2019-08-22 martijn OSMTPD_PHASE_PROTOCOL_SERVER,
556 d229c123 2019-08-22 martijn osmtpd_onearg,
562 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
563 d229c123 2019-08-22 martijn OSMTPD_PHASE_FILTER_RESPONSE,
565 d229c123 2019-08-22 martijn osmtpd_onearg,
571 d229c123 2019-08-22 martijn OSMTPD_TYPE_REPORT,
572 d229c123 2019-08-22 martijn OSMTPD_PHASE_TIMEOUT,
574 d229c123 2019-08-22 martijn osmtpd_noargs,
581 ce062d50 2019-08-21 martijn static struct io *io_stdout;
582 09816288 2019-08-22 martijn static int needs;
583 ce062d50 2019-08-21 martijn static int ready = 0;
584 ce062d50 2019-08-21 martijn /* Default from smtpd */
585 ce062d50 2019-08-21 martijn static int session_timeout = 300;
587 d229c123 2019-08-22 martijn RB_HEAD(osmtpd_sessions, osmtpd_session) osmtpd_sessions = RB_INITIALIZER(NULL);
588 9e3e8410 2019-08-22 martijn RB_PROTOTYPE_STATIC(osmtpd_sessions, osmtpd_session, entry, osmtpd_session_cmp);
591 2029083f 2020-10-15 martijn osmtpd_register_conf(void (*cb)(const char *, const char *))
593 2029083f 2020-10-15 martijn conf_cb = cb;
597 5129e9c0 2025-04-10 kirill osmtpd_register_filter_connect(int (*cb)(struct osmtpd_ctx *, const char *,
598 ce062d50 2019-08-21 martijn struct sockaddr_storage *))
600 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_CONNECT, 1, 0,
601 ce062d50 2019-08-21 martijn (void *)cb);
602 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
607 5129e9c0 2025-04-10 kirill osmtpd_register_filter_helo(int (*cb)(struct osmtpd_ctx *, const char *))
609 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_HELO, 1, 0,
610 ce062d50 2019-08-21 martijn (void *)cb);
611 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
616 5129e9c0 2025-04-10 kirill osmtpd_register_filter_ehlo(int (*cb)(struct osmtpd_ctx *, const char *))
618 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_EHLO, 1, 0,
619 ce062d50 2019-08-21 martijn (void *)cb);
620 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
625 5129e9c0 2025-04-10 kirill osmtpd_register_filter_starttls(int (*cb)(struct osmtpd_ctx *))
627 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_STARTTLS, 1, 0,
628 ce062d50 2019-08-21 martijn (void *)cb);
629 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
634 5129e9c0 2025-04-10 kirill osmtpd_register_filter_auth(int (*cb)(struct osmtpd_ctx *, const char *))
636 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_AUTH, 1, 0,
637 ce062d50 2019-08-21 martijn (void *)cb);
638 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
643 5129e9c0 2025-04-10 kirill osmtpd_register_filter_mailfrom(int (*cb)(struct osmtpd_ctx *, const char *))
645 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_MAIL_FROM, 1, 0,
646 ce062d50 2019-08-21 martijn (void *)cb);
647 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
652 5129e9c0 2025-04-10 kirill osmtpd_register_filter_rcptto(int (*cb)(struct osmtpd_ctx *, const char *))
654 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_RCPT_TO, 1, 0,
655 ce062d50 2019-08-21 martijn (void *)cb);
656 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
661 5129e9c0 2025-04-10 kirill osmtpd_register_filter_data(int (*cb)(struct osmtpd_ctx *))
663 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_DATA, 1, 0,
664 ce062d50 2019-08-21 martijn (void *)cb);
665 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
670 5129e9c0 2025-04-10 kirill osmtpd_register_filter_dataline(int (*cb)(struct osmtpd_ctx *, const char *))
672 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_DATA_LINE, 1, 0,
673 ce062d50 2019-08-21 martijn (void *)cb);
674 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
679 5129e9c0 2025-04-10 kirill osmtpd_register_filter_rset(int (*cb)(struct osmtpd_ctx *))
681 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_RSET, 1, 0,
682 ce062d50 2019-08-21 martijn (void *)cb);
683 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
688 5129e9c0 2025-04-10 kirill osmtpd_register_filter_quit(int (*cb)(struct osmtpd_ctx *))
690 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_QUIT, 1, 0,
691 ce062d50 2019-08-21 martijn (void *)cb);
692 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
697 5129e9c0 2025-04-10 kirill osmtpd_register_filter_noop(int (*cb)(struct osmtpd_ctx *))
699 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_NOOP, 1, 0,
700 ce062d50 2019-08-21 martijn (void *)cb);
701 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
706 5129e9c0 2025-04-10 kirill osmtpd_register_filter_help(int (*cb)(struct osmtpd_ctx *))
708 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_HELP, 1, 0,
709 ce062d50 2019-08-21 martijn (void *)cb);
710 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
715 5129e9c0 2025-04-10 kirill osmtpd_register_filter_wiz(int (*cb)(struct osmtpd_ctx *))
717 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_WIZ, 1, 0,
718 ce062d50 2019-08-21 martijn (void *)cb);
719 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
724 5129e9c0 2025-04-10 kirill osmtpd_register_filter_commit(int (*cb)(struct osmtpd_ctx *))
726 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_FILTER, OSMTPD_PHASE_COMMIT, 1, 0,
727 ce062d50 2019-08-21 martijn (void *)cb);
728 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, 1, 0,
733 5129e9c0 2025-04-10 kirill osmtpd_register_report_connect(int incoming, int (*cb)(struct osmtpd_ctx *,
734 30f1cbac 2019-08-22 martijn const char *, enum osmtpd_status, struct sockaddr_storage *,
735 ce062d50 2019-08-21 martijn struct sockaddr_storage *))
737 3fd8a04a 2021-04-18 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_CONNECT, incoming,
738 ce062d50 2019-08-21 martijn 0, (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 5129e9c0 2025-04-10 kirill osmtpd_register_report_disconnect(int incoming, int (*cb)(struct osmtpd_ctx *))
746 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
747 ce062d50 2019-08-21 martijn incoming, 0, (void *)cb);
751 5129e9c0 2025-04-10 kirill osmtpd_register_report_identify(int incoming, int (*cb)(struct osmtpd_ctx *,
752 ce062d50 2019-08-21 martijn const char *))
754 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_IDENTIFY,
755 ce062d50 2019-08-21 martijn incoming, 0, (void *)cb);
756 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
757 ce062d50 2019-08-21 martijn incoming, 0, NULL);
761 5129e9c0 2025-04-10 kirill osmtpd_register_report_tls(int incoming, int (*cb)(struct osmtpd_ctx *,
762 ce062d50 2019-08-21 martijn const char *))
764 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_TLS, incoming, 0,
765 ce062d50 2019-08-21 martijn (void *)cb);
766 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
767 ce062d50 2019-08-21 martijn incoming, 0, NULL);
771 5129e9c0 2025-04-10 kirill osmtpd_register_report_auth(int incoming, int (*cb)(struct osmtpd_ctx *,
772 58a6bc69 2022-12-05 martijn const char *, enum osmtpd_auth_status))
774 58a6bc69 2022-12-05 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_AUTH, incoming, 0,
775 58a6bc69 2022-12-05 martijn (void *)cb);
776 58a6bc69 2022-12-05 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
777 58a6bc69 2022-12-05 martijn incoming, 0, NULL);
781 5129e9c0 2025-04-10 kirill osmtpd_register_report_reset(int incoming, int (*cb)(struct osmtpd_ctx *,
782 d308c531 2025-02-03 martijn uint32_t))
784 d308c531 2025-02-03 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_RESET, incoming, 0,
785 d308c531 2025-02-03 martijn (void *)cb);
786 d308c531 2025-02-03 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
787 d308c531 2025-02-03 martijn incoming, 0, NULL);
791 5129e9c0 2025-04-10 kirill osmtpd_register_report_begin(int incoming, int (*cb)(struct osmtpd_ctx *,
792 ce062d50 2019-08-21 martijn uint32_t))
794 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_BEGIN, incoming, 0,
795 ce062d50 2019-08-21 martijn (void *)cb);
796 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
797 ce062d50 2019-08-21 martijn incoming, 0, NULL);
801 5129e9c0 2025-04-10 kirill osmtpd_register_report_mail(int incoming, int (*cb)(struct osmtpd_ctx *,
802 ce062d50 2019-08-21 martijn uint32_t, const char *, enum osmtpd_status))
804 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_MAIL, incoming, 0,
805 ce062d50 2019-08-21 martijn (void *)cb);
806 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
807 ce062d50 2019-08-21 martijn incoming, 0, NULL);
811 5129e9c0 2025-04-10 kirill osmtpd_register_report_rcpt(int incoming, int (*cb)(struct osmtpd_ctx *,
812 ce062d50 2019-08-21 martijn uint32_t, const char *, enum osmtpd_status))
814 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_RCPT, incoming, 0,
815 ce062d50 2019-08-21 martijn (void *)cb);
816 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
817 ce062d50 2019-08-21 martijn incoming, 0, NULL);
821 5129e9c0 2025-04-10 kirill osmtpd_register_report_envelope(int incoming, int (*cb)(struct osmtpd_ctx *,
822 ce062d50 2019-08-21 martijn uint32_t, uint64_t))
824 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ENVELOPE, incoming,
825 ce062d50 2019-08-21 martijn 0, (void *)cb);
826 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
827 ce062d50 2019-08-21 martijn incoming, 0, NULL);
831 5129e9c0 2025-04-10 kirill osmtpd_register_report_data(int incoming, int (*cb)(struct osmtpd_ctx *,
832 ce062d50 2019-08-21 martijn uint32_t, enum osmtpd_status))
834 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_DATA, incoming, 0,
835 ce062d50 2019-08-21 martijn (void *)cb);
836 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
837 ce062d50 2019-08-21 martijn incoming, 0, NULL);
841 5129e9c0 2025-04-10 kirill osmtpd_register_report_commit(int incoming, int (*cb)(struct osmtpd_ctx *,
842 ce062d50 2019-08-21 martijn uint32_t, size_t))
844 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_COMMIT, incoming, 0,
845 ce062d50 2019-08-21 martijn (void *)cb);
846 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
847 ce062d50 2019-08-21 martijn incoming, 0, NULL);
851 5129e9c0 2025-04-10 kirill osmtpd_register_report_rollback(int incoming, int (*cb)(struct osmtpd_ctx *,
852 ce062d50 2019-08-21 martijn uint32_t))
854 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ROLLBACK, incoming,
855 ce062d50 2019-08-21 martijn 0, (void *)cb);
856 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
857 ce062d50 2019-08-21 martijn incoming, 0, NULL);
861 5129e9c0 2025-04-10 kirill osmtpd_register_report_client(int incoming, int (*cb)(struct osmtpd_ctx *,
862 ce062d50 2019-08-21 martijn const char *))
864 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_PROTOCOL_CLIENT,
865 ce062d50 2019-08-21 martijn incoming, 0, (void *)cb);
866 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
867 ce062d50 2019-08-21 martijn incoming, 0, NULL);
871 5129e9c0 2025-04-10 kirill osmtpd_register_report_server(int incoming, int (*cb)(struct osmtpd_ctx *,
872 ce062d50 2019-08-21 martijn const char *))
874 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_PROTOCOL_SERVER,
875 ce062d50 2019-08-21 martijn incoming, 0, (void *)cb);
876 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
877 ce062d50 2019-08-21 martijn incoming, 0, NULL);
881 5129e9c0 2025-04-10 kirill osmtpd_register_report_response(int incoming, int (*cb)(struct osmtpd_ctx *,
882 ce062d50 2019-08-21 martijn const char *))
884 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_FILTER_RESPONSE,
885 ce062d50 2019-08-21 martijn incoming, 0, (void *)cb);
886 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
887 ce062d50 2019-08-21 martijn incoming, 0, NULL);
891 5129e9c0 2025-04-10 kirill osmtpd_register_report_timeout(int incoming, int (*cb)(struct osmtpd_ctx *))
893 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TIMEOUT, incoming, 0,
894 ce062d50 2019-08-21 martijn (void *)cb);
895 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
896 ce062d50 2019-08-21 martijn incoming, 0, NULL);
900 912d0ff2 2019-08-22 martijn osmtpd_local_session(void *(*oncreate)(struct osmtpd_ctx *),
901 ce062d50 2019-08-21 martijn void (*ondelete)(struct osmtpd_ctx *, void *))
903 912d0ff2 2019-08-22 martijn oncreatecb_session = oncreate;
904 912d0ff2 2019-08-22 martijn ondeletecb_session = ondelete;
908 912d0ff2 2019-08-22 martijn osmtpd_local_message(void *(*oncreate)(struct osmtpd_ctx *),
909 912d0ff2 2019-08-22 martijn void (*ondelete)(struct osmtpd_ctx *, void *))
911 912d0ff2 2019-08-22 martijn oncreatecb_message = oncreate;
912 912d0ff2 2019-08-22 martijn ondeletecb_message = ondelete;
916 09816288 2019-08-22 martijn osmtpd_need(int lneeds)
918 09816288 2019-08-22 martijn needs |= lneeds;
921 09816288 2019-08-22 martijn static void
922 09816288 2019-08-22 martijn osmtpd_register_need(int incoming)
924 ce062d50 2019-08-21 martijn if (needs & (OSMTPD_NEED_SRC | OSMTPD_NEED_DST | OSMTPD_NEED_RDNS |
925 09816288 2019-08-22 martijn OSMTPD_NEED_FCRDNS))
926 705cd566 2019-08-23 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_CONNECT,
927 ce062d50 2019-08-21 martijn incoming, 1, NULL);
928 0fb4c799 2019-09-05 martijn if (needs & OSMTPD_NEED_GREETING)
929 a05d5c54 2019-08-28 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_GREETING,
930 a05d5c54 2019-08-28 martijn incoming, 1, NULL);
931 0fb4c799 2019-09-05 martijn if (needs & OSMTPD_NEED_IDENTITY)
932 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_IDENTIFY,
933 ce062d50 2019-08-21 martijn incoming, 1, NULL);
934 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_CIPHERS)
935 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_TLS,
936 ce062d50 2019-08-21 martijn incoming, 1, NULL);
937 58a6bc69 2022-12-05 martijn if (needs & OSMTPD_NEED_USERNAME)
938 58a6bc69 2022-12-05 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_AUTH,
939 58a6bc69 2022-12-05 martijn incoming, 1, NULL);
940 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_MSGID) {
941 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_BEGIN,
942 ce062d50 2019-08-21 martijn incoming, 1, NULL);
943 d308c531 2025-02-03 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_RESET,
944 ce062d50 2019-08-21 martijn incoming, 0, NULL);
946 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_MAILFROM) {
947 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_MAIL,
948 ce062d50 2019-08-21 martijn incoming, 1, NULL);
949 d308c531 2025-02-03 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_RESET,
950 ce062d50 2019-08-21 martijn incoming, 0, NULL);
952 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_RCPTTO) {
953 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_RCPT,
954 ce062d50 2019-08-21 martijn incoming, 1, NULL);
955 d308c531 2025-02-03 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_RESET,
956 ce062d50 2019-08-21 martijn incoming, 0, NULL);
958 ce062d50 2019-08-21 martijn if (needs & OSMTPD_NEED_EVPID) {
959 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_ENVELOPE,
960 ce062d50 2019-08-21 martijn incoming, 1, NULL);
961 d308c531 2025-02-03 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_TX_RESET,
962 ce062d50 2019-08-21 martijn incoming, 0, NULL);
965 ce062d50 2019-08-21 martijn osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT,
966 ce062d50 2019-08-21 martijn incoming, 0, NULL);
970 ce062d50 2019-08-21 martijn osmtpd_run(void)
972 ce062d50 2019-08-21 martijn size_t i = 0;
973 ce062d50 2019-08-21 martijn int registered = 0;
974 adebfe7c 2021-03-21 martijn struct event_base *evbase;
975 ce062d50 2019-08-21 martijn struct io *io_stdin;
976 a37af028 2019-09-17 martijn struct osmtpd_callback *hidenity = NULL, *eidentity = NULL;
977 a37af028 2019-09-17 martijn struct osmtpd_callback *ridentity = NULL;
979 adebfe7c 2021-03-21 martijn evbase = event_init();
981 ce062d50 2019-08-21 martijn if ((io_stdin = io_new()) == NULL ||
982 ce062d50 2019-08-21 martijn (io_stdout = io_new()) == NULL)
983 27dd1f3b 2019-08-22 martijn osmtpd_err(1, "io_new");
984 ce062d50 2019-08-21 martijn io_set_nonblocking(STDIN_FILENO);
985 ce062d50 2019-08-21 martijn io_set_fd(io_stdin, STDIN_FILENO);
986 ce062d50 2019-08-21 martijn io_set_callback(io_stdin, osmtpd_newline, NULL);
987 ce062d50 2019-08-21 martijn io_set_read(io_stdin);
988 ce062d50 2019-08-21 martijn io_set_nonblocking(STDOUT_FILENO);
989 ce062d50 2019-08-21 martijn io_set_fd(io_stdout, STDOUT_FILENO);
990 ce062d50 2019-08-21 martijn io_set_callback(io_stdout, osmtpd_outevt, NULL);
991 ce062d50 2019-08-21 martijn io_set_write(io_stdout);
993 ce062d50 2019-08-21 martijn for (i = 0; i < NITEMS(osmtpd_callbacks); i++) {
994 912d0ff2 2019-08-22 martijn if (osmtpd_callbacks[i].doregister) {
995 09816288 2019-08-22 martijn osmtpd_register_need(osmtpd_callbacks[i].incoming);
996 912d0ff2 2019-08-22 martijn if (oncreatecb_message != NULL) {
997 912d0ff2 2019-08-22 martijn osmtpd_register(OSMTPD_TYPE_REPORT,
998 912d0ff2 2019-08-22 martijn OSMTPD_PHASE_TX_BEGIN,
999 912d0ff2 2019-08-22 martijn osmtpd_callbacks[i].incoming, 0, NULL);
1000 912d0ff2 2019-08-22 martijn osmtpd_register(OSMTPD_TYPE_REPORT,
1001 d308c531 2025-02-03 martijn OSMTPD_PHASE_TX_RESET,
1002 912d0ff2 2019-08-22 martijn osmtpd_callbacks[i].incoming, 0, NULL);
1004 421c9a86 2019-09-06 martijn if (osmtpd_callbacks[i].type == OSMTPD_TYPE_FILTER &&
1005 421c9a86 2019-09-06 martijn osmtpd_callbacks[i].phase == OSMTPD_PHASE_HELO)
1006 421c9a86 2019-09-06 martijn hidenity = &(osmtpd_callbacks[i]);
1007 421c9a86 2019-09-06 martijn if (osmtpd_callbacks[i].type == OSMTPD_TYPE_FILTER &&
1008 421c9a86 2019-09-06 martijn osmtpd_callbacks[i].phase == OSMTPD_PHASE_EHLO)
1009 421c9a86 2019-09-06 martijn eidentity = &(osmtpd_callbacks[i]);
1010 421c9a86 2019-09-06 martijn if (osmtpd_callbacks[i].type == OSMTPD_TYPE_REPORT &&
1011 421c9a86 2019-09-06 martijn osmtpd_callbacks[i].phase ==
1012 421c9a86 2019-09-06 martijn OSMTPD_PHASE_LINK_IDENTIFY &&
1013 421c9a86 2019-09-06 martijn osmtpd_callbacks[i].incoming == 1)
1014 421c9a86 2019-09-06 martijn ridentity = &(osmtpd_callbacks[i]);
1017 a37af028 2019-09-17 martijn if (ridentity != NULL && ridentity->storereport) {
1018 a37af028 2019-09-17 martijn if (hidenity != NULL && hidenity->doregister)
1019 421c9a86 2019-09-06 martijn hidenity->storereport = 1;
1020 a37af028 2019-09-17 martijn if (eidentity != NULL && eidentity->doregister)
1021 421c9a86 2019-09-06 martijn eidentity->storereport = 1;
1023 09816288 2019-08-22 martijn for (i = 0; i < NITEMS(osmtpd_callbacks); i++) {
1024 ce062d50 2019-08-21 martijn if (osmtpd_callbacks[i].doregister) {
1025 ce062d50 2019-08-21 martijn if (osmtpd_callbacks[i].cb != NULL)
1026 ce062d50 2019-08-21 martijn registered = 1;
1027 ce062d50 2019-08-21 martijn io_printf(io_stdout, "register|%s|smtp-%s|%s\n",
1028 ce062d50 2019-08-21 martijn osmtpd_typetostr(osmtpd_callbacks[i].type),
1029 ce062d50 2019-08-21 martijn osmtpd_callbacks[i].incoming ? "in" : "out",
1030 ce062d50 2019-08-21 martijn osmtpd_phasetostr(osmtpd_callbacks[i].phase));
1034 ce062d50 2019-08-21 martijn if (!registered)
1035 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "No events registered");
1036 ce062d50 2019-08-21 martijn io_printf(io_stdout, "register|ready\n");
1037 ce062d50 2019-08-21 martijn ready = 1;
1039 ce062d50 2019-08-21 martijn event_dispatch();
1040 adebfe7c 2021-03-21 martijn io_free(io_stdin);
1041 adebfe7c 2021-03-21 martijn io_free(io_stdout);
1042 adebfe7c 2021-03-21 martijn event_base_free(evbase);
1046 8b9e9928 2025-01-30 kirill osmtpd_warn(struct osmtpd_ctx *ctx, const char *fmt, ...)
1048 8b9e9928 2025-01-30 kirill va_list ap;
1050 8b9e9928 2025-01-30 kirill if (ctx)
1051 8b9e9928 2025-01-30 kirill fprintf(stderr, "%016"PRIx64, ctx->reqid);
1052 8b9e9928 2025-01-30 kirill va_start(ap, fmt);
1053 8b9e9928 2025-01-30 kirill vfprintf(stderr, fmt, ap);
1054 8b9e9928 2025-01-30 kirill va_end(ap);
1055 8b9e9928 2025-01-30 kirill fprintf(stderr, ": %s\n", strerror(errno));
1059 8b9e9928 2025-01-30 kirill osmtpd_warnx(struct osmtpd_ctx *ctx, const char *fmt, ...)
1061 8b9e9928 2025-01-30 kirill va_list ap;
1063 8b9e9928 2025-01-30 kirill if (ctx)
1064 8b9e9928 2025-01-30 kirill fprintf(stderr, "%016"PRIx64, ctx->reqid);
1065 8b9e9928 2025-01-30 kirill va_start(ap, fmt);
1066 8b9e9928 2025-01-30 kirill vfprintf(stderr, fmt, ap);
1067 8b9e9928 2025-01-30 kirill va_end(ap);
1068 8b9e9928 2025-01-30 kirill fprintf(stderr, "\n");
1071 27dd1f3b 2019-08-22 martijn __dead void
1072 27dd1f3b 2019-08-22 martijn osmtpd_err(int eval, const char *fmt, ...)
1074 27dd1f3b 2019-08-22 martijn va_list ap;
1076 27dd1f3b 2019-08-22 martijn va_start(ap, fmt);
1077 27dd1f3b 2019-08-22 martijn vfprintf(stderr, fmt, ap);
1078 27dd1f3b 2019-08-22 martijn va_end(ap);
1079 67cd1323 2019-08-22 martijn fprintf(stderr, ": %s\n", strerror(errno));
1080 27dd1f3b 2019-08-22 martijn exit(eval);
1083 27dd1f3b 2019-08-22 martijn __dead void
1084 27dd1f3b 2019-08-22 martijn osmtpd_errx(int eval, const char *fmt, ...)
1086 27dd1f3b 2019-08-22 martijn va_list ap;
1088 27dd1f3b 2019-08-22 martijn va_start(ap, fmt);
1089 27dd1f3b 2019-08-22 martijn vfprintf(stderr, fmt, ap);
1090 27dd1f3b 2019-08-22 martijn va_end(ap);
1091 27dd1f3b 2019-08-22 martijn fprintf(stderr, "\n");
1092 27dd1f3b 2019-08-22 martijn exit(eval);
1095 ce062d50 2019-08-21 martijn static void
1096 6258daeb 2019-11-14 martijn osmtpd_newline(struct io *io, int ev, __unused void *arg)
1098 ce062d50 2019-08-21 martijn static char *linedup = NULL;
1099 ce062d50 2019-08-21 martijn static size_t dupsize = 0;
1100 ce062d50 2019-08-21 martijn struct osmtpd_session *ctx, search;
1101 ce062d50 2019-08-21 martijn enum osmtpd_type type;
1102 ce062d50 2019-08-21 martijn enum osmtpd_phase phase;
1103 ce062d50 2019-08-21 martijn int version_major, version_minor, incoming;
1104 ce062d50 2019-08-21 martijn struct timespec tm;
1105 ce062d50 2019-08-21 martijn char *line = NULL;
1106 ce062d50 2019-08-21 martijn const char *errstr = NULL;
1107 ce062d50 2019-08-21 martijn size_t linelen;
1108 ce062d50 2019-08-21 martijn char *end;
1109 ce062d50 2019-08-21 martijn size_t i;
1111 adebfe7c 2021-03-21 martijn if (ev == IO_DISCONNECTED) {
1112 adebfe7c 2021-03-21 martijn event_loopexit(0);
1113 adebfe7c 2021-03-21 martijn return;
1115 ce062d50 2019-08-21 martijn if (ev != IO_DATAIN)
1116 ce062d50 2019-08-21 martijn return;
1118 5f7c62fa 2022-03-28 martijn * Multiple calls to io_printf (through osmtpd_filter_dataline) can
1119 5f7c62fa 2022-03-28 martijn * cause a build-up of kevents, because of event_add/event_del loop.
1121 5f7c62fa 2022-03-28 martijn io_pause(io_stdout, IO_OUT);
1122 24d62a97 2019-08-23 martijn while ((line = io_getline(io, &linelen)) != NULL) {
1123 ce062d50 2019-08-21 martijn if (dupsize < linelen) {
1124 ce062d50 2019-08-21 martijn if ((linedup = realloc(linedup, linelen + 1)) == NULL)
1125 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1126 ce062d50 2019-08-21 martijn dupsize = linelen + 1;
1128 ce062d50 2019-08-21 martijn strlcpy(linedup, line, dupsize);
1129 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
1130 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing "
1131 c6cb29f3 2019-08-22 martijn "version: %s", linedup);
1132 ce062d50 2019-08-21 martijn end++[0] = '\0';
1133 ce062d50 2019-08-21 martijn if (strcmp(line, "filter") == 0)
1134 ce062d50 2019-08-21 martijn type = OSMTPD_TYPE_FILTER;
1135 ce062d50 2019-08-21 martijn else if (strcmp(line, "report") == 0)
1136 ce062d50 2019-08-21 martijn type = OSMTPD_TYPE_REPORT;
1137 ce062d50 2019-08-21 martijn else if (strcmp(line, "config") == 0) {
1138 ce062d50 2019-08-21 martijn line = end;
1139 2029083f 2020-10-15 martijn if (strcmp(line, "ready") == 0) {
1140 34f87d66 2020-12-20 martijn if (conf_cb != NULL)
1141 34f87d66 2020-12-20 martijn conf_cb(NULL, NULL);
1142 ce062d50 2019-08-21 martijn continue;
1144 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
1145 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing "
1146 c6cb29f3 2019-08-22 martijn "key: %s", linedup);
1147 ce062d50 2019-08-21 martijn end++[0] = '\0';
1148 34f87d66 2020-12-20 martijn if (conf_cb != NULL)
1149 34f87d66 2020-12-20 martijn conf_cb(line, end);
1150 ce062d50 2019-08-21 martijn if (strcmp(line, "smtp-session-timeout") == 0) {
1151 ce062d50 2019-08-21 martijn session_timeout = strtonum(end, 0, INT_MAX,
1152 ce062d50 2019-08-21 martijn &errstr);
1153 ce062d50 2019-08-21 martijn if (errstr != NULL)
1154 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: "
1155 ce062d50 2019-08-21 martijn "invalid smtp-sesion-timeout: %s",
1156 ce062d50 2019-08-21 martijn linedup);
1158 ce062d50 2019-08-21 martijn continue;
1161 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: unknown message "
1162 c6cb29f3 2019-08-22 martijn "type: %s", linedup);
1163 ce062d50 2019-08-21 martijn line = end;
1164 183acf20 2019-08-28 martijn version_major = strtoul(line, &end, 10);
1165 183acf20 2019-08-28 martijn if (line == end || end[0] != '.')
1166 183acf20 2019-08-28 martijn osmtpd_errx(1, "Invalid protocol received: %s",
1167 183acf20 2019-08-28 martijn linedup);
1168 183acf20 2019-08-28 martijn line = end + 1;
1169 183acf20 2019-08-28 martijn version_minor = strtoul(line, &end, 10);
1170 183acf20 2019-08-28 martijn if (end[0] == '\0')
1171 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing time: "
1172 c6cb29f3 2019-08-22 martijn "%s", linedup);
1173 183acf20 2019-08-28 martijn if (line == end || end[0] != '|')
1174 183acf20 2019-08-28 martijn osmtpd_errx(1, "Invalid protocol received: %s",
1175 183acf20 2019-08-28 martijn linedup);
1176 183acf20 2019-08-28 martijn if (version_major != 0)
1177 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Unsupported protocol received: %s",
1178 c6cb29f3 2019-08-22 martijn linedup);
1179 183acf20 2019-08-28 martijn line = end + 1;
1180 ce062d50 2019-08-21 martijn if ((end = strchr(line, '.')) == NULL)
1181 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
1182 c6cb29f3 2019-08-22 martijn "timestamp: %s", linedup);
1183 ce062d50 2019-08-21 martijn end++[0] = '\0';
1184 ce062d50 2019-08-21 martijn tm.tv_sec = (time_t) strtonum(line, 0, INT64_MAX, &errstr);
1185 ce062d50 2019-08-21 martijn if (errstr != NULL)
1186 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
1187 c6cb29f3 2019-08-22 martijn "timestamp: %s", linedup);
1188 ce062d50 2019-08-21 martijn line = end;
1189 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
1190 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing "
1191 c6cb29f3 2019-08-22 martijn "direction: %s", linedup);
1192 ce062d50 2019-08-21 martijn end++[0] = '\0';
1193 ce062d50 2019-08-21 martijn tm.tv_nsec = (long) strtonum(line, 0, LONG_MAX, &errstr);
1194 ce062d50 2019-08-21 martijn if (errstr != NULL)
1195 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
1196 c6cb29f3 2019-08-22 martijn "timestamp: %s", linedup);
1197 ce062d50 2019-08-21 martijn tm.tv_nsec *= 10 * (9 - (end - line));
1198 ce062d50 2019-08-21 martijn line = end;
1199 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
1200 e5f09156 2021-06-01 martijn osmtpd_errx(1, "Invalid line received: missing "
1201 c6cb29f3 2019-08-22 martijn "phase: %s", linedup);
1202 ce062d50 2019-08-21 martijn end++[0] = '\0';
1203 ce062d50 2019-08-21 martijn if (strcmp(line, "smtp-in") == 0)
1204 ce062d50 2019-08-21 martijn incoming = 1;
1205 ce062d50 2019-08-21 martijn else if (strcmp(line, "smtp-out") == 0)
1206 ce062d50 2019-08-21 martijn incoming = 0;
1208 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line: invalid direction: %s",
1209 c6cb29f3 2019-08-22 martijn linedup);
1210 ce062d50 2019-08-21 martijn line = end;
1211 ce062d50 2019-08-21 martijn if ((end = strchr(line, '|')) == NULL)
1212 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing reqid: "
1213 c6cb29f3 2019-08-22 martijn "%s", linedup);
1214 ce062d50 2019-08-21 martijn end++[0] = '\0';
1215 ce062d50 2019-08-21 martijn phase = osmtpd_strtophase(line, linedup);
1216 ce062d50 2019-08-21 martijn line = end;
1217 ce062d50 2019-08-21 martijn errno = 0;
1218 ce062d50 2019-08-21 martijn search.ctx.reqid = strtoull(line, &end, 16);
1219 ce062d50 2019-08-21 martijn if ((search.ctx.reqid == ULLONG_MAX && errno != 0) ||
1220 ce062d50 2019-08-21 martijn (end[0] != '|' && end[0] != '\0'))
1221 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid reqid: "
1222 c6cb29f3 2019-08-22 martijn "%s", linedup);
1223 ce062d50 2019-08-21 martijn line = end + 1;
1224 ce062d50 2019-08-21 martijn ctx = RB_FIND(osmtpd_sessions, &osmtpd_sessions, &search);
1225 ce062d50 2019-08-21 martijn if (ctx == NULL) {
1226 ce062d50 2019-08-21 martijn if ((ctx = malloc(sizeof(*ctx))) == NULL)
1227 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1228 d308c531 2025-02-03 martijn ctx->status = SESSION_OK;
1229 ce062d50 2019-08-21 martijn ctx->ctx.reqid = search.ctx.reqid;
1230 ce062d50 2019-08-21 martijn ctx->ctx.rdns = NULL;
1231 30f1cbac 2019-08-22 martijn ctx->ctx.fcrdns = OSMTPD_STATUS_TEMPFAIL;
1232 0fb4c799 2019-09-05 martijn ctx->ctx.identity = NULL;
1233 0fb4c799 2019-09-05 martijn ctx->ctx.greeting.identity = NULL;
1234 ce062d50 2019-08-21 martijn ctx->ctx.ciphers = NULL;
1235 ce062d50 2019-08-21 martijn ctx->ctx.msgid = 0;
1236 58a6bc69 2022-12-05 martijn ctx->ctx.username = NULL;
1237 ce062d50 2019-08-21 martijn ctx->ctx.mailfrom = NULL;
1238 ce062d50 2019-08-21 martijn ctx->ctx.rcptto = malloc(sizeof(*(ctx->ctx.rcptto)));
1239 ce062d50 2019-08-21 martijn if (ctx->ctx.rcptto == NULL)
1240 27dd1f3b 2019-08-22 martijn osmtpd_err(1, "malloc");
1241 ce062d50 2019-08-21 martijn ctx->ctx.rcptto[0] = NULL;
1242 ce062d50 2019-08-21 martijn memset(&(ctx->ctx.src), 0, sizeof(ctx->ctx.src));
1243 ce062d50 2019-08-21 martijn ctx->ctx.src.ss_family = AF_UNSPEC;
1244 ce062d50 2019-08-21 martijn memset(&(ctx->ctx.dst), 0, sizeof(ctx->ctx.dst));
1245 ce062d50 2019-08-21 martijn ctx->ctx.dst.ss_family = AF_UNSPEC;
1246 ce062d50 2019-08-21 martijn RB_INSERT(osmtpd_sessions, &osmtpd_sessions, ctx);
1247 ce062d50 2019-08-21 martijn ctx->ctx.evpid = 0;
1248 912d0ff2 2019-08-22 martijn ctx->ctx.local_session = NULL;
1249 912d0ff2 2019-08-22 martijn ctx->ctx.local_message = NULL;
1250 912d0ff2 2019-08-22 martijn if (oncreatecb_session != NULL)
1251 866e5e0e 2025-02-03 martijn if ((ctx->ctx.local_session =
1252 866e5e0e 2025-02-03 martijn oncreatecb_session(&ctx->ctx)) == NULL)
1253 866e5e0e 2025-02-03 martijn ctx->status = SESSION_ERROR;
1255 ce062d50 2019-08-21 martijn ctx->ctx.type = type;
1256 ce062d50 2019-08-21 martijn ctx->ctx.phase = phase;
1257 ce062d50 2019-08-21 martijn ctx->ctx.version_major = version_major;
1258 ce062d50 2019-08-21 martijn ctx->ctx.version_minor = version_minor;
1259 ce062d50 2019-08-21 martijn ctx->ctx.incoming = incoming;
1260 ce062d50 2019-08-21 martijn ctx->ctx.tm.tv_sec = tm.tv_sec;
1261 ce062d50 2019-08-21 martijn ctx->ctx.tm.tv_nsec = tm.tv_nsec;
1262 ce062d50 2019-08-21 martijn ctx->ctx.token = 0;
1264 ce062d50 2019-08-21 martijn for (i = 0; i < NITEMS(osmtpd_callbacks); i++) {
1265 ce062d50 2019-08-21 martijn if (ctx->ctx.type == osmtpd_callbacks[i].type &&
1266 ce062d50 2019-08-21 martijn ctx->ctx.phase == osmtpd_callbacks[i].phase &&
1267 ce062d50 2019-08-21 martijn ctx->ctx.incoming == osmtpd_callbacks[i].incoming)
1270 ce062d50 2019-08-21 martijn if (i == NITEMS(osmtpd_callbacks)) {
1271 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: received "
1272 c6cb29f3 2019-08-22 martijn "unregistered line: %s", linedup);
1274 ce062d50 2019-08-21 martijn if (ctx->ctx.type == OSMTPD_TYPE_FILTER) {
1275 ce062d50 2019-08-21 martijn ctx->ctx.token = strtoull(line, &end, 16);
1276 c6cb29f3 2019-08-22 martijn if ((ctx->ctx.token == ULLONG_MAX && errno != 0) ||
1277 ce062d50 2019-08-21 martijn end[0] != '|')
1278 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
1279 c6cb29f3 2019-08-22 martijn "token: %s", linedup);
1280 ce062d50 2019-08-21 martijn line = end + 1;
1281 866e5e0e 2025-02-03 martijn if (ctx->status == SESSION_ERROR)
1282 866e5e0e 2025-02-03 martijn osmtpd_filter_disconnect(&ctx->ctx,
1283 866e5e0e 2025-02-03 martijn "internal server error");
1285 ce062d50 2019-08-21 martijn osmtpd_callbacks[i].osmtpd_cb(&(osmtpd_callbacks[i]),
1286 866e5e0e 2025-02-03 martijn ctx, line, linedup);
1288 5f7c62fa 2022-03-28 martijn io_resume(io_stdout, IO_OUT);
1291 ce062d50 2019-08-21 martijn static void
1292 6258daeb 2019-11-14 martijn osmtpd_outevt(__unused struct io *io, int evt, __unused void *arg)
1294 ce062d50 2019-08-21 martijn switch (evt) {
1295 ce062d50 2019-08-21 martijn case IO_LOWAT:
1296 ce062d50 2019-08-21 martijn return;
1297 ce062d50 2019-08-21 martijn case IO_DISCONNECTED:
1298 ce062d50 2019-08-21 martijn exit(0);
1299 ce062d50 2019-08-21 martijn default:
1300 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Unexpectd event");
1304 ce062d50 2019-08-21 martijn static void
1305 866e5e0e 2025-02-03 martijn osmtpd_noargs(struct osmtpd_callback *cb, struct osmtpd_session *session,
1306 6258daeb 2019-11-14 martijn __unused char *params, __unused char *linedup)
1308 5129e9c0 2025-04-10 kirill int (*f)(struct osmtpd_ctx *);
1310 866e5e0e 2025-02-03 martijn if ((f = cb->cb) != NULL && session->status == SESSION_OK)
1311 5129e9c0 2025-04-10 kirill if (f(&session->ctx))
1312 5129e9c0 2025-04-10 kirill session->status = SESSION_ERROR;
1315 ce062d50 2019-08-21 martijn static void
1316 866e5e0e 2025-02-03 martijn osmtpd_onearg(struct osmtpd_callback *cb, struct osmtpd_session *session,
1317 866e5e0e 2025-02-03 martijn char *line, __unused char *linedup)
1319 5129e9c0 2025-04-10 kirill int (*f)(struct osmtpd_ctx *, const char *);
1321 866e5e0e 2025-02-03 martijn if ((f = cb->cb) != NULL && session->status == SESSION_OK)
1322 5129e9c0 2025-04-10 kirill if (f(&session->ctx, line))
1323 5129e9c0 2025-04-10 kirill session->status = SESSION_ERROR;
1326 ce062d50 2019-08-21 martijn static void
1327 866e5e0e 2025-02-03 martijn osmtpd_connect(struct osmtpd_callback *cb, struct osmtpd_session *session,
1328 866e5e0e 2025-02-03 martijn char *params, char *linedup)
1330 ce062d50 2019-08-21 martijn struct sockaddr_storage ss;
1331 ce062d50 2019-08-21 martijn char *hostname;
1332 ce062d50 2019-08-21 martijn char *address;
1333 5129e9c0 2025-04-10 kirill int (*f)(struct osmtpd_ctx *, const char *, struct sockaddr_storage *);
1335 ce062d50 2019-08-21 martijn hostname = params;
1336 ce062d50 2019-08-21 martijn if ((address = strchr(params, '|')) == NULL)
1337 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1338 c6cb29f3 2019-08-22 martijn linedup);
1339 ce062d50 2019-08-21 martijn address++[0] = '\0';
1341 ce062d50 2019-08-21 martijn osmtpd_addrtoss(address, &ss, 0, linedup);
1343 866e5e0e 2025-02-03 martijn if ((f = cb->cb) != NULL && session->status == SESSION_OK)
1344 5129e9c0 2025-04-10 kirill if (f(&session->ctx, hostname, &ss))
1345 5129e9c0 2025-04-10 kirill session->status = SESSION_ERROR;
1348 ce062d50 2019-08-21 martijn static void
1349 866e5e0e 2025-02-03 martijn osmtpd_identify(struct osmtpd_callback *cb, struct osmtpd_session *session,
1350 6258daeb 2019-11-14 martijn char *identity, __unused char *linedup)
1352 5129e9c0 2025-04-10 kirill int (*f)(struct osmtpd_ctx *, const char *);
1354 421c9a86 2019-09-06 martijn if (cb->storereport) {
1355 866e5e0e 2025-02-03 martijn free(session->ctx.identity);
1356 866e5e0e 2025-02-03 martijn if ((session->ctx.identity = strdup(identity)) == NULL)
1357 421c9a86 2019-09-06 martijn osmtpd_err(1, "strdup");
1360 866e5e0e 2025-02-03 martijn if ((f = cb->cb) != NULL && session->status == SESSION_OK)
1361 5129e9c0 2025-04-10 kirill if (f(&session->ctx, identity))
1362 5129e9c0 2025-04-10 kirill session->status = SESSION_ERROR;
1365 421c9a86 2019-09-06 martijn static void
1366 866e5e0e 2025-02-03 martijn osmtpd_link_connect(struct osmtpd_callback *cb, struct osmtpd_session *session,
1367 ce062d50 2019-08-21 martijn char *params, char *linedup)
1369 30f1cbac 2019-08-22 martijn char *end, *rdns;
1370 30f1cbac 2019-08-22 martijn enum osmtpd_status fcrdns;
1371 ce062d50 2019-08-21 martijn struct sockaddr_storage src, dst;
1372 5129e9c0 2025-04-10 kirill int (*f)(struct osmtpd_ctx *, const char *, enum osmtpd_status,
1373 c6cb29f3 2019-08-22 martijn struct sockaddr_storage *, struct sockaddr_storage *);
1375 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1376 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing fcrdns: %s",
1377 c6cb29f3 2019-08-22 martijn linedup);
1378 ce062d50 2019-08-21 martijn end++[0] = '\0';
1379 ce062d50 2019-08-21 martijn rdns = params;
1380 ce062d50 2019-08-21 martijn params = end;
1381 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1382 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing src: %s",
1383 c6cb29f3 2019-08-22 martijn linedup);
1384 ce062d50 2019-08-21 martijn end++[0] = '\0';
1385 30f1cbac 2019-08-22 martijn if (strcmp(params, "pass") == 0)
1386 30f1cbac 2019-08-22 martijn fcrdns = OSMTPD_STATUS_OK;
1387 30f1cbac 2019-08-22 martijn else if (strcmp(params, "fail") == 0)
1388 30f1cbac 2019-08-22 martijn fcrdns = OSMTPD_STATUS_PERMFAIL;
1389 30f1cbac 2019-08-22 martijn else if (strcmp(params, "error") == 0)
1390 30f1cbac 2019-08-22 martijn fcrdns = OSMTPD_STATUS_TEMPFAIL;
1392 30f1cbac 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid fcrdns: %s",
1393 30f1cbac 2019-08-22 martijn linedup);
1394 ce062d50 2019-08-21 martijn params = end;
1395 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1396 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing dst: %s",
1397 c6cb29f3 2019-08-22 martijn linedup);
1398 ce062d50 2019-08-21 martijn end++[0] = '\0';
1399 ce062d50 2019-08-21 martijn osmtpd_addrtoss(params, &src, 1, linedup);
1400 ce062d50 2019-08-21 martijn params = end;
1401 ce062d50 2019-08-21 martijn osmtpd_addrtoss(params, &dst, 1, linedup);
1402 ce062d50 2019-08-21 martijn if (cb->storereport) {
1403 866e5e0e 2025-02-03 martijn if ((session->ctx.rdns = strdup(rdns)) == NULL)
1404 30f1cbac 2019-08-22 martijn osmtpd_err(1, "strdup");
1405 866e5e0e 2025-02-03 martijn session->ctx.fcrdns = fcrdns;
1406 866e5e0e 2025-02-03 martijn memcpy(&session->ctx.src, &src, sizeof(session->ctx.src));
1407 866e5e0e 2025-02-03 martijn memcpy(&session->ctx.dst, &dst, sizeof(session->ctx.dst));
1409 866e5e0e 2025-02-03 martijn if ((f = cb->cb) != NULL && session->status == SESSION_OK)
1410 5129e9c0 2025-04-10 kirill if (f(&session->ctx, rdns, fcrdns, &src, &dst))
1411 5129e9c0 2025-04-10 kirill session->status = SESSION_ERROR;
1414 ce062d50 2019-08-21 martijn static void
1415 866e5e0e 2025-02-03 martijn osmtpd_link_disconnect(struct osmtpd_callback *cb,
1416 866e5e0e 2025-02-03 martijn struct osmtpd_session *session, __unused char *param,
1417 866e5e0e 2025-02-03 martijn __unused char *linedup)
1419 5129e9c0 2025-04-10 kirill int (*f)(struct osmtpd_ctx *);
1420 ce062d50 2019-08-21 martijn size_t i;
1422 866e5e0e 2025-02-03 martijn if ((f = cb->cb) != NULL && session->status == SESSION_OK)
1423 5129e9c0 2025-04-10 kirill if (f(&session->ctx))
1424 5129e9c0 2025-04-10 kirill session->status = SESSION_ERROR;
1426 866e5e0e 2025-02-03 martijn RB_REMOVE(osmtpd_sessions, &osmtpd_sessions, session);
1427 866e5e0e 2025-02-03 martijn if (ondeletecb_session != NULL && session->ctx.local_session != NULL)
1428 866e5e0e 2025-02-03 martijn ondeletecb_session(&session->ctx, session->ctx.local_session);
1429 866e5e0e 2025-02-03 martijn free(session->ctx.rdns);
1430 866e5e0e 2025-02-03 martijn free(session->ctx.identity);
1431 866e5e0e 2025-02-03 martijn free(session->ctx.greeting.identity);
1432 866e5e0e 2025-02-03 martijn free(session->ctx.ciphers);
1433 866e5e0e 2025-02-03 martijn free(session->ctx.username);
1434 866e5e0e 2025-02-03 martijn free(session->ctx.mailfrom);
1435 866e5e0e 2025-02-03 martijn for (i = 0; session->ctx.rcptto[i] != NULL; i++)
1436 866e5e0e 2025-02-03 martijn free(session->ctx.rcptto[i]);
1437 866e5e0e 2025-02-03 martijn free(session->ctx.rcptto);
1438 866e5e0e 2025-02-03 martijn free(session);
1441 866e5e0e 2025-02-03 martijn static void
1442 866e5e0e 2025-02-03 martijn osmtpd_link_greeting(struct osmtpd_callback *cb, struct osmtpd_session *session,
1443 866e5e0e 2025-02-03 martijn char *identity, __unused char *linedup)
1445 5129e9c0 2025-04-10 kirill int (*f)(struct osmtpd_ctx *, const char *);
1447 866e5e0e 2025-02-03 martijn if (cb->storereport) {
1448 0fb4c799 2019-09-05 martijn free(session->ctx.greeting.identity);
1449 866e5e0e 2025-02-03 martijn if ((session->ctx.greeting.identity = strdup(identity)) == NULL)
1450 a05d5c54 2019-08-28 martijn osmtpd_err(1, NULL);
1453 866e5e0e 2025-02-03 martijn if ((f = cb->cb) != NULL && session->status == SESSION_OK)
1454 5129e9c0 2025-04-10 kirill if (f(&session->ctx, identity))
1455 5129e9c0 2025-04-10 kirill session->status = SESSION_ERROR;
1458 a05d5c54 2019-08-28 martijn static void
1459 866e5e0e 2025-02-03 martijn osmtpd_link_identify(struct osmtpd_callback *cb, struct osmtpd_session *session,
1460 6258daeb 2019-11-14 martijn char *identity, __unused char *linedup)
1462 5129e9c0 2025-04-10 kirill int (*f)(struct osmtpd_ctx *, const char *);
1464 ce062d50 2019-08-21 martijn if (cb->storereport) {
1465 866e5e0e 2025-02-03 martijn free(session->ctx.identity);
1466 866e5e0e 2025-02-03 martijn if ((session->ctx.identity = strdup(identity)) == NULL)
1467 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1470 866e5e0e 2025-02-03 martijn if ((f = cb->cb) != NULL && session->status == SESSION_OK)
1471 5129e9c0 2025-04-10 kirill if (f(&session->ctx, identity))
1472 5129e9c0 2025-04-10 kirill session->status = SESSION_ERROR;
1475 ce062d50 2019-08-21 martijn static void
1476 866e5e0e 2025-02-03 martijn osmtpd_link_tls(struct osmtpd_callback *cb, struct osmtpd_session *session,
1477 6258daeb 2019-11-14 martijn char *ciphers, __unused char *linedup)
1479 5129e9c0 2025-04-10 kirill int (*f)(struct osmtpd_ctx *, const char *);
1481 ce062d50 2019-08-21 martijn if (cb->storereport) {
1482 866e5e0e 2025-02-03 martijn if ((session->ctx.ciphers = strdup(ciphers)) == NULL)
1483 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1486 866e5e0e 2025-02-03 martijn if ((f = cb->cb) != NULL && session->status == SESSION_OK)
1487 5129e9c0 2025-04-10 kirill if (f(&session->ctx, ciphers))
1488 5129e9c0 2025-04-10 kirill session->status = SESSION_ERROR;
1491 ce062d50 2019-08-21 martijn static void
1492 866e5e0e 2025-02-03 martijn osmtpd_link_auth(struct osmtpd_callback *cb, struct osmtpd_session *session,
1493 58a6bc69 2022-12-05 martijn char *username, char *linedup)
1495 5129e9c0 2025-04-10 kirill int (*f)(struct osmtpd_ctx *, const char *, enum osmtpd_auth_status);
1496 58a6bc69 2022-12-05 martijn char *status;
1497 58a6bc69 2022-12-05 martijn enum osmtpd_auth_status s;
1499 58a6bc69 2022-12-05 martijn if ((status = strrchr(username, '|')) == NULL)
1500 58a6bc69 2022-12-05 martijn osmtpd_errx(1, "Invalid auth received: %s", linedup);
1501 58a6bc69 2022-12-05 martijn status[0] = '\0';
1502 58a6bc69 2022-12-05 martijn status++;
1503 58a6bc69 2022-12-05 martijn if (strcmp(status, "pass") == 0)
1504 58a6bc69 2022-12-05 martijn s = OSMTPD_AUTH_PASS;
1505 58a6bc69 2022-12-05 martijn else if (strcmp(status, "fail") == 0)
1506 58a6bc69 2022-12-05 martijn s = OSMTPD_AUTH_FAIL;
1507 58a6bc69 2022-12-05 martijn else if (strcmp(status, "error") == 0)
1508 58a6bc69 2022-12-05 martijn s = OSMTPD_AUTH_ERROR;
1510 58a6bc69 2022-12-05 martijn osmtpd_errx(1, "Invalid auth status received: %s", linedup);
1512 58a6bc69 2022-12-05 martijn if (cb->storereport && s == OSMTPD_AUTH_PASS) {
1513 866e5e0e 2025-02-03 martijn if ((session->ctx.username = strdup(username)) == NULL)
1514 58a6bc69 2022-12-05 martijn osmtpd_err(1, NULL);
1517 866e5e0e 2025-02-03 martijn if ((f = cb->cb) != NULL && session->status == SESSION_OK)
1518 5129e9c0 2025-04-10 kirill if (f(&session->ctx, username, s))
1519 5129e9c0 2025-04-10 kirill session->status = SESSION_ERROR;
1522 58a6bc69 2022-12-05 martijn static void
1523 d308c531 2025-02-03 martijn osmtpd_tx_reset(struct osmtpd_callback *cb, struct osmtpd_session *session,
1524 d308c531 2025-02-03 martijn char *params, char *linedup)
1526 d308c531 2025-02-03 martijn char *end;
1527 d308c531 2025-02-03 martijn unsigned long imsgid;
1528 d308c531 2025-02-03 martijn uint32_t msgid;
1529 d308c531 2025-02-03 martijn size_t i;
1530 5129e9c0 2025-04-10 kirill int (*f)(struct osmtpd_ctx *, uint32_t);
1532 d308c531 2025-02-03 martijn errno = 0;
1533 d308c531 2025-02-03 martijn imsgid = strtoul(params, &end, 16);
1534 d308c531 2025-02-03 martijn if ((imsgid == ULONG_MAX && errno != 0))
1535 d308c531 2025-02-03 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1536 d308c531 2025-02-03 martijn linedup);
1537 d308c531 2025-02-03 martijn if (end[0] != '\0')
1538 d308c531 2025-02-03 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1539 d308c531 2025-02-03 martijn linedup);
1540 d308c531 2025-02-03 martijn msgid = imsgid;
1541 d308c531 2025-02-03 martijn if ((unsigned long) msgid != imsgid)
1542 d308c531 2025-02-03 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1543 d308c531 2025-02-03 martijn linedup);
1545 d308c531 2025-02-03 martijn if ((f = cb->cb) != NULL && session->status == SESSION_OK)
1546 5129e9c0 2025-04-10 kirill if (f(&session->ctx, msgid))
1547 5129e9c0 2025-04-10 kirill session->status = SESSION_ERROR;
1549 d308c531 2025-02-03 martijn if (ondeletecb_message != NULL && session->ctx.local_message != NULL) {
1550 d308c531 2025-02-03 martijn ondeletecb_message(&session->ctx, session->ctx.local_message);
1551 d308c531 2025-02-03 martijn session->ctx.local_message = NULL;
1554 d308c531 2025-02-03 martijn free(session->ctx.mailfrom);
1555 d308c531 2025-02-03 martijn session->ctx.mailfrom = NULL;
1557 d308c531 2025-02-03 martijn for (i = 0; session->ctx.rcptto[i] != NULL; i++)
1558 d308c531 2025-02-03 martijn free(session->ctx.rcptto[i]);
1559 d308c531 2025-02-03 martijn session->ctx.rcptto[0] = NULL;
1560 d308c531 2025-02-03 martijn session->ctx.evpid = 0;
1561 d308c531 2025-02-03 martijn session->ctx.msgid = 0;
1564 d308c531 2025-02-03 martijn static void
1565 866e5e0e 2025-02-03 martijn osmtpd_tx_begin(struct osmtpd_callback *cb, struct osmtpd_session *session,
1566 ce062d50 2019-08-21 martijn char *msgid, char *linedup)
1568 ce062d50 2019-08-21 martijn unsigned long imsgid;
1569 ce062d50 2019-08-21 martijn char *endptr;
1570 5129e9c0 2025-04-10 kirill int (*f)(struct osmtpd_ctx *, uint32_t);
1572 ce062d50 2019-08-21 martijn errno = 0;
1573 ce062d50 2019-08-21 martijn imsgid = strtoul(msgid, &endptr, 16);
1574 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0) || endptr[0] != '\0')
1575 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1576 c6cb29f3 2019-08-22 martijn linedup);
1577 866e5e0e 2025-02-03 martijn session->ctx.msgid = imsgid;
1578 ce062d50 2019-08-21 martijn /* Check if we're in range */
1579 866e5e0e 2025-02-03 martijn if ((unsigned long) session->ctx.msgid != imsgid)
1580 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1581 c6cb29f3 2019-08-22 martijn linedup);
1583 ce062d50 2019-08-21 martijn if (!cb->storereport)
1584 866e5e0e 2025-02-03 martijn session->ctx.msgid = 0;
1586 866e5e0e 2025-02-03 martijn if (oncreatecb_message != NULL) {
1587 866e5e0e 2025-02-03 martijn session->ctx.local_message = oncreatecb_message(&session->ctx);
1588 866e5e0e 2025-02-03 martijn if (session->ctx.local_message == NULL)
1589 866e5e0e 2025-02-03 martijn session->status = SESSION_ERROR;
1592 866e5e0e 2025-02-03 martijn if ((f = cb->cb) != NULL && session->status == SESSION_OK)
1593 5129e9c0 2025-04-10 kirill if (f(&session->ctx, imsgid))
1594 5129e9c0 2025-04-10 kirill session->status = SESSION_ERROR;
1597 ce062d50 2019-08-21 martijn static void
1598 866e5e0e 2025-02-03 martijn osmtpd_tx_mail(struct osmtpd_callback *cb, struct osmtpd_session *session,
1599 ce062d50 2019-08-21 martijn char *params, char *linedup)
1601 ce062d50 2019-08-21 martijn char *end, *mailfrom;
1602 53b354a9 2020-04-12 martijn enum osmtpd_status status;
1603 ce062d50 2019-08-21 martijn unsigned long imsgid;
1604 ce062d50 2019-08-21 martijn uint32_t msgid;
1605 5129e9c0 2025-04-10 kirill int (*f)(struct osmtpd_ctx *, uint32_t, const char *,
1606 ce062d50 2019-08-21 martijn enum osmtpd_status);
1608 ce062d50 2019-08-21 martijn errno = 0;
1609 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1610 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1611 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1612 c6cb29f3 2019-08-22 martijn linedup);
1613 ce062d50 2019-08-21 martijn if (end[0] != '|')
1614 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1615 c6cb29f3 2019-08-22 martijn linedup);
1616 ce062d50 2019-08-21 martijn msgid = imsgid;
1617 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1618 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1619 c6cb29f3 2019-08-22 martijn linedup);
1620 ce062d50 2019-08-21 martijn params = end + 1;
1622 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1623 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing status: %s",
1624 c6cb29f3 2019-08-22 martijn linedup);
1625 ce062d50 2019-08-21 martijn end++[0] = '\0';
1626 866e5e0e 2025-02-03 martijn if (session->ctx.version_major == 0 && session->ctx.version_minor < 6) {
1627 53b354a9 2020-04-12 martijn mailfrom = params;
1628 53b354a9 2020-04-12 martijn status = osmtpd_strtostatus(end, linedup);
1629 53b354a9 2020-04-12 martijn } else {
1630 53b354a9 2020-04-12 martijn mailfrom = end;
1631 53b354a9 2020-04-12 martijn status = osmtpd_strtostatus(params, linedup);
1633 ce062d50 2019-08-21 martijn if (cb->storereport) {
1634 866e5e0e 2025-02-03 martijn if ((session->ctx.mailfrom = strdup(mailfrom)) == NULL)
1635 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1638 866e5e0e 2025-02-03 martijn if ((f = cb->cb) != NULL && session->status == SESSION_OK)
1639 5129e9c0 2025-04-10 kirill if (f(&session->ctx, msgid, mailfrom, status))
1640 5129e9c0 2025-04-10 kirill session->status = SESSION_ERROR;
1643 ce062d50 2019-08-21 martijn static void
1644 866e5e0e 2025-02-03 martijn osmtpd_tx_rcpt(struct osmtpd_callback *cb, struct osmtpd_session *session,
1645 ce062d50 2019-08-21 martijn char *params, char *linedup)
1647 ce062d50 2019-08-21 martijn char *end, *rcptto;
1648 53b354a9 2020-04-12 martijn enum osmtpd_status status;
1649 ce062d50 2019-08-21 martijn unsigned long imsgid;
1650 ce062d50 2019-08-21 martijn uint32_t msgid;
1651 ce062d50 2019-08-21 martijn size_t i;
1652 5129e9c0 2025-04-10 kirill int (*f)(struct osmtpd_ctx *, uint32_t, const char *,
1653 ce062d50 2019-08-21 martijn enum osmtpd_status);
1655 ce062d50 2019-08-21 martijn errno = 0;
1656 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1657 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1658 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1659 c6cb29f3 2019-08-22 martijn linedup);
1660 ce062d50 2019-08-21 martijn if (end[0] != '|')
1661 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1662 c6cb29f3 2019-08-22 martijn linedup);
1663 ce062d50 2019-08-21 martijn msgid = imsgid;
1664 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1665 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1666 c6cb29f3 2019-08-22 martijn linedup);
1667 ce062d50 2019-08-21 martijn params = end + 1;
1669 ce062d50 2019-08-21 martijn if ((end = strchr(params, '|')) == NULL)
1670 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing status: %s",
1671 c6cb29f3 2019-08-22 martijn linedup);
1672 ce062d50 2019-08-21 martijn end++[0] = '\0';
1674 866e5e0e 2025-02-03 martijn if (session->ctx.version_major == 0 && session->ctx.version_minor < 6) {
1675 53b354a9 2020-04-12 martijn rcptto = params;
1676 53b354a9 2020-04-12 martijn status = osmtpd_strtostatus(end, linedup);
1677 53b354a9 2020-04-12 martijn } else {
1678 53b354a9 2020-04-12 martijn rcptto = end;
1679 53b354a9 2020-04-12 martijn status = osmtpd_strtostatus(params, linedup);
1682 ce062d50 2019-08-21 martijn if (cb->storereport) {
1683 866e5e0e 2025-02-03 martijn for (i = 0; session->ctx.rcptto[i] != NULL; i++)
1685 866e5e0e 2025-02-03 martijn session->ctx.rcptto = reallocarray(session->ctx.rcptto, i + 2,
1686 866e5e0e 2025-02-03 martijn sizeof(*session->ctx.rcptto));
1687 866e5e0e 2025-02-03 martijn if (session->ctx.rcptto == NULL)
1688 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1690 866e5e0e 2025-02-03 martijn if ((session->ctx.rcptto[i] = strdup(rcptto)) == NULL)
1691 27dd1f3b 2019-08-22 martijn osmtpd_err(1, NULL);
1692 866e5e0e 2025-02-03 martijn session->ctx.rcptto[i + 1] = NULL;
1695 866e5e0e 2025-02-03 martijn if ((f = cb->cb) != NULL && session->status == SESSION_OK)
1696 5129e9c0 2025-04-10 kirill if (f(&session->ctx, msgid, rcptto, status))
1697 5129e9c0 2025-04-10 kirill session->status = SESSION_ERROR;
1700 ce062d50 2019-08-21 martijn static void
1701 866e5e0e 2025-02-03 martijn osmtpd_tx_envelope(struct osmtpd_callback *cb, struct osmtpd_session *session,
1702 ce062d50 2019-08-21 martijn char *params, char *linedup)
1704 ce062d50 2019-08-21 martijn unsigned long imsgid;
1705 ce062d50 2019-08-21 martijn uint32_t msgid;
1706 ce062d50 2019-08-21 martijn uint64_t evpid;
1707 ce062d50 2019-08-21 martijn char *end;
1708 5129e9c0 2025-04-10 kirill int (*f)(struct osmtpd_ctx *, uint32_t, uint64_t);
1710 ce062d50 2019-08-21 martijn errno = 0;
1711 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1712 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1713 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1714 c6cb29f3 2019-08-22 martijn linedup);
1715 ce062d50 2019-08-21 martijn if (end[0] != '|')
1716 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1717 c6cb29f3 2019-08-22 martijn linedup);
1718 ce062d50 2019-08-21 martijn msgid = imsgid;
1719 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1720 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1721 c6cb29f3 2019-08-22 martijn linedup);
1722 ce062d50 2019-08-21 martijn params = end + 1;
1724 ce062d50 2019-08-21 martijn evpid = strtoull(params, &end, 16);
1725 866e5e0e 2025-02-03 martijn if ((session->ctx.evpid == ULLONG_MAX && errno != 0) || end[0] != '\0')
1726 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid evpid: %s",
1727 c6cb29f3 2019-08-22 martijn linedup);
1728 ce062d50 2019-08-21 martijn if (cb->storereport)
1729 866e5e0e 2025-02-03 martijn session->ctx.evpid = evpid;
1731 866e5e0e 2025-02-03 martijn if ((f = cb->cb) != NULL && session->status == SESSION_OK)
1732 5129e9c0 2025-04-10 kirill if (f(&session->ctx, msgid, evpid))
1733 5129e9c0 2025-04-10 kirill session->status = SESSION_ERROR;
1736 ce062d50 2019-08-21 martijn static void
1737 866e5e0e 2025-02-03 martijn osmtpd_tx_data(struct osmtpd_callback *cb, struct osmtpd_session *session,
1738 ce062d50 2019-08-21 martijn char *params, char *linedup)
1740 ce062d50 2019-08-21 martijn char *end;
1741 ce062d50 2019-08-21 martijn unsigned long imsgid;
1742 ce062d50 2019-08-21 martijn uint32_t msgid;
1743 5129e9c0 2025-04-10 kirill int (*f)(struct osmtpd_ctx *, uint32_t, enum osmtpd_status);
1745 ce062d50 2019-08-21 martijn errno = 0;
1746 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1747 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1748 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1749 c6cb29f3 2019-08-22 martijn linedup);
1750 ce062d50 2019-08-21 martijn if (end[0] != '|')
1751 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1752 c6cb29f3 2019-08-22 martijn linedup);
1753 ce062d50 2019-08-21 martijn msgid = imsgid;
1754 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1755 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1756 c6cb29f3 2019-08-22 martijn linedup);
1757 ce062d50 2019-08-21 martijn params = end + 1;
1759 866e5e0e 2025-02-03 martijn if ((f = cb->cb) != NULL && session->status == SESSION_OK)
1760 5129e9c0 2025-04-10 kirill if (f(&session->ctx, msgid, osmtpd_strtostatus(params, linedup)))
1761 5129e9c0 2025-04-10 kirill session->status = SESSION_ERROR;
1764 ce062d50 2019-08-21 martijn static void
1765 866e5e0e 2025-02-03 martijn osmtpd_tx_commit(struct osmtpd_callback *cb, struct osmtpd_session *session,
1766 ce062d50 2019-08-21 martijn char *params, char *linedup)
1768 ce062d50 2019-08-21 martijn char *end;
1769 332b3141 2019-08-22 martijn const char *errstr = NULL;
1770 ce062d50 2019-08-21 martijn unsigned long imsgid;
1771 ce062d50 2019-08-21 martijn uint32_t msgid;
1772 d308c531 2025-02-03 martijn size_t msgsz;
1773 5129e9c0 2025-04-10 kirill int (*f)(struct osmtpd_ctx *, uint32_t, size_t);
1775 ce062d50 2019-08-21 martijn errno = 0;
1776 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1777 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1778 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1779 c6cb29f3 2019-08-22 martijn linedup);
1780 ce062d50 2019-08-21 martijn if (end[0] != '|')
1781 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1782 c6cb29f3 2019-08-22 martijn linedup);
1783 ce062d50 2019-08-21 martijn msgid = imsgid;
1784 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1785 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1786 c6cb29f3 2019-08-22 martijn linedup);
1787 ce062d50 2019-08-21 martijn params = end + 1;
1789 332b3141 2019-08-22 martijn msgsz = strtonum(params, 0, UINT32_MAX, &errstr);
1790 ce062d50 2019-08-21 martijn if (errstr != NULL)
1791 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msg size: %s",
1792 c6cb29f3 2019-08-22 martijn linedup);
1794 866e5e0e 2025-02-03 martijn if ((f = cb->cb) != NULL && session->status == SESSION_OK)
1795 5129e9c0 2025-04-10 kirill if (f(&session->ctx, msgid, msgsz))
1796 5129e9c0 2025-04-10 kirill session->status = SESSION_ERROR;
1799 ce062d50 2019-08-21 martijn static void
1800 866e5e0e 2025-02-03 martijn osmtpd_tx_rollback(struct osmtpd_callback *cb, struct osmtpd_session *session,
1801 ce062d50 2019-08-21 martijn char *params, char *linedup)
1803 ce062d50 2019-08-21 martijn char *end;
1804 ce062d50 2019-08-21 martijn unsigned long imsgid;
1805 ce062d50 2019-08-21 martijn uint32_t msgid;
1806 5129e9c0 2025-04-10 kirill int (*f)(struct osmtpd_ctx *, uint32_t);
1808 ce062d50 2019-08-21 martijn errno = 0;
1809 ce062d50 2019-08-21 martijn imsgid = strtoul(params, &end, 16);
1810 ce062d50 2019-08-21 martijn if ((imsgid == ULONG_MAX && errno != 0))
1811 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1812 c6cb29f3 2019-08-22 martijn linedup);
1813 ce062d50 2019-08-21 martijn if (end[0] != '\0')
1814 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: missing address: %s",
1815 c6cb29f3 2019-08-22 martijn linedup);
1816 ce062d50 2019-08-21 martijn msgid = imsgid;
1817 ce062d50 2019-08-21 martijn if ((unsigned long) msgid != imsgid)
1818 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid msgid: %s",
1819 c6cb29f3 2019-08-22 martijn linedup);
1821 866e5e0e 2025-02-03 martijn if ((f = cb->cb) != NULL && session->status == SESSION_OK)
1822 5129e9c0 2025-04-10 kirill if (f(&session->ctx, msgid))
1823 5129e9c0 2025-04-10 kirill session->status = SESSION_ERROR;
1827 ce062d50 2019-08-21 martijn osmtpd_filter_proceed(struct osmtpd_ctx *ctx)
1829 866e5e0e 2025-02-03 martijn struct osmtpd_session *session = (struct osmtpd_session *)ctx;
1831 866e5e0e 2025-02-03 martijn if (session->status == SESSION_DISCONNECTED)
1832 866e5e0e 2025-02-03 martijn return;
1834 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1835 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1836 06220a70 2019-12-06 martijn "proceed\n", ctx->token, ctx->reqid);
1838 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1839 06220a70 2019-12-06 martijn "proceed\n", ctx->reqid, ctx->token);
1843 ce062d50 2019-08-21 martijn osmtpd_filter_reject(struct osmtpd_ctx *ctx, int code, const char *reason, ...)
1845 866e5e0e 2025-02-03 martijn struct osmtpd_session *session = (struct osmtpd_session *)ctx;
1846 ce062d50 2019-08-21 martijn va_list ap;
1848 866e5e0e 2025-02-03 martijn if (session->status == SESSION_DISCONNECTED)
1849 866e5e0e 2025-02-03 martijn return;
1851 ce062d50 2019-08-21 martijn if (code < 200 || code > 599)
1852 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid reject code");
1854 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1855 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1856 06220a70 2019-12-06 martijn "reject|%d ", ctx->token, ctx->reqid, code);
1858 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1859 06220a70 2019-12-06 martijn "reject|%d ", ctx->reqid, ctx->token, code);
1860 ce062d50 2019-08-21 martijn va_start(ap, reason);
1861 ce062d50 2019-08-21 martijn io_vprintf(io_stdout, reason, ap);
1862 ce062d50 2019-08-21 martijn va_end(ap);
1863 ce062d50 2019-08-21 martijn io_printf(io_stdout, "\n");
1867 000aebbc 2019-08-23 martijn osmtpd_filter_reject_enh(struct osmtpd_ctx *ctx, int code, int class,
1868 000aebbc 2019-08-23 martijn int subject, int detail, const char *reason, ...)
1870 866e5e0e 2025-02-03 martijn struct osmtpd_session *session = (struct osmtpd_session *)ctx;
1871 000aebbc 2019-08-23 martijn va_list ap;
1873 866e5e0e 2025-02-03 martijn if (session->status == SESSION_DISCONNECTED)
1874 866e5e0e 2025-02-03 martijn return;
1876 000aebbc 2019-08-23 martijn if (code < 200 || code > 599)
1877 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid reject code");
1878 2a3d7bdf 2019-08-27 martijn if (class < 2 || class > 5)
1879 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid enhanced status class");
1880 000aebbc 2019-08-23 martijn if (subject < 0 || subject > 999)
1881 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid enhanced status subject");
1882 000aebbc 2019-08-23 martijn if (detail < 0 || detail > 999)
1883 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid enhanced status detail");
1885 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1886 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1887 06220a70 2019-12-06 martijn "reject|%d %d.%d.%d ", ctx->token, ctx->reqid, code, class,
1888 06220a70 2019-12-06 martijn subject, detail);
1890 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1891 06220a70 2019-12-06 martijn "reject|%d %d.%d.%d ", ctx->reqid, ctx->token, code, class,
1892 06220a70 2019-12-06 martijn subject, detail);
1893 000aebbc 2019-08-23 martijn va_start(ap, reason);
1894 000aebbc 2019-08-23 martijn io_vprintf(io_stdout, reason, ap);
1895 000aebbc 2019-08-23 martijn va_end(ap);
1896 000aebbc 2019-08-23 martijn io_printf(io_stdout, "\n");
1900 ce062d50 2019-08-21 martijn osmtpd_filter_disconnect(struct osmtpd_ctx *ctx, const char *reason, ...)
1902 866e5e0e 2025-02-03 martijn struct osmtpd_session *session = (struct osmtpd_session *)ctx;
1903 ce062d50 2019-08-21 martijn va_list ap;
1905 866e5e0e 2025-02-03 martijn if (session->status == SESSION_DISCONNECTED)
1906 866e5e0e 2025-02-03 martijn return;
1908 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1909 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1910 06220a70 2019-12-06 martijn "disconnect|421 ", ctx->token, ctx->reqid);
1912 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1913 06220a70 2019-12-06 martijn "disconnect|421 ", ctx->reqid, ctx->token);
1914 ce062d50 2019-08-21 martijn va_start(ap, reason);
1915 ce062d50 2019-08-21 martijn io_vprintf(io_stdout, reason, ap);
1916 ce062d50 2019-08-21 martijn va_end(ap);
1917 ce062d50 2019-08-21 martijn io_printf(io_stdout, "\n");
1918 866e5e0e 2025-02-03 martijn session->status = SESSION_DISCONNECTED;
1922 000aebbc 2019-08-23 martijn osmtpd_filter_disconnect_enh(struct osmtpd_ctx *ctx, int class, int subject,
1923 000aebbc 2019-08-23 martijn int detail, const char *reason, ...)
1925 866e5e0e 2025-02-03 martijn struct osmtpd_session *session = (struct osmtpd_session *)ctx;
1926 000aebbc 2019-08-23 martijn va_list ap;
1928 866e5e0e 2025-02-03 martijn if (session->status == SESSION_DISCONNECTED)
1929 866e5e0e 2025-02-03 martijn return;
1931 000aebbc 2019-08-23 martijn if (class <= 2 || class >= 5)
1932 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid enhanced status class");
1933 000aebbc 2019-08-23 martijn if (subject < 0 || subject > 999)
1934 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid enhanced status subject");
1935 000aebbc 2019-08-23 martijn if (detail < 0 || detail > 999)
1936 000aebbc 2019-08-23 martijn osmtpd_errx(1, "Invalid enhanced status detail");
1937 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1938 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1939 06220a70 2019-12-06 martijn "disconnect|421 %d.%d.%d ", ctx->token, ctx->reqid, class,
1940 06220a70 2019-12-06 martijn subject, detail);
1942 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1943 06220a70 2019-12-06 martijn "disconnect|421 %d.%d.%d ", ctx->reqid, ctx->token, class,
1944 06220a70 2019-12-06 martijn subject, detail);
1945 000aebbc 2019-08-23 martijn va_start(ap, reason);
1946 000aebbc 2019-08-23 martijn io_vprintf(io_stdout, reason, ap);
1947 000aebbc 2019-08-23 martijn va_end(ap);
1948 000aebbc 2019-08-23 martijn io_printf(io_stdout, "\n");
1949 866e5e0e 2025-02-03 martijn session->status = SESSION_DISCONNECTED;
1953 4fb72612 2019-08-21 martijn osmtpd_filter_rewrite(struct osmtpd_ctx *ctx, const char *value, ...)
1955 866e5e0e 2025-02-03 martijn struct osmtpd_session *session = (struct osmtpd_session *)ctx;
1956 4fb72612 2019-08-21 martijn va_list ap;
1958 866e5e0e 2025-02-03 martijn if (session->status == SESSION_DISCONNECTED)
1959 866e5e0e 2025-02-03 martijn return;
1961 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1962 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1963 06220a70 2019-12-06 martijn "rewrite|", ctx->token, ctx->reqid);
1965 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-result|%016"PRIx64"|%016"PRIx64"|"
1966 06220a70 2019-12-06 martijn "rewrite|", ctx->reqid, ctx->token);
1967 4fb72612 2019-08-21 martijn va_start(ap, value);
1968 4fb72612 2019-08-21 martijn io_vprintf(io_stdout, value, ap);
1969 4fb72612 2019-08-21 martijn va_end(ap);
1970 4fb72612 2019-08-21 martijn io_printf(io_stdout, "\n");
1974 ce062d50 2019-08-21 martijn osmtpd_filter_dataline(struct osmtpd_ctx *ctx, const char *line, ...)
1976 866e5e0e 2025-02-03 martijn struct osmtpd_session *session = (struct osmtpd_session *)ctx;
1977 ce062d50 2019-08-21 martijn va_list ap;
1979 866e5e0e 2025-02-03 martijn if (session->status == SESSION_DISCONNECTED)
1980 866e5e0e 2025-02-03 martijn return;
1982 06220a70 2019-12-06 martijn if (ctx->version_major == 0 && ctx->version_minor < 5)
1983 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-dataline|%016"PRIx64"|%016"PRIx64"|",
1984 06220a70 2019-12-06 martijn ctx->token, ctx->reqid);
1986 06220a70 2019-12-06 martijn io_printf(io_stdout, "filter-dataline|%016"PRIx64"|%016"PRIx64"|",
1987 06220a70 2019-12-06 martijn ctx->reqid, ctx->token);
1988 ce062d50 2019-08-21 martijn va_start(ap, line);
1989 ce062d50 2019-08-21 martijn io_vprintf(io_stdout, line, ap);
1990 ce062d50 2019-08-21 martijn va_end(ap);
1991 ce062d50 2019-08-21 martijn io_printf(io_stdout, "\n");
1994 ce062d50 2019-08-21 martijn static void
1995 ce062d50 2019-08-21 martijn osmtpd_register(enum osmtpd_type type, enum osmtpd_phase phase, int incoming,
1996 ce062d50 2019-08-21 martijn int storereport, void *cb)
1998 ce062d50 2019-08-21 martijn size_t i;
2000 ce062d50 2019-08-21 martijn if (ready)
2001 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Can't register when proc is running");
2003 ce062d50 2019-08-21 martijn for (i = 0; i < NITEMS(osmtpd_callbacks); i++) {
2004 ce062d50 2019-08-21 martijn if (type == osmtpd_callbacks[i].type &&
2005 ce062d50 2019-08-21 martijn phase == osmtpd_callbacks[i].phase &&
2006 ce062d50 2019-08-21 martijn incoming == osmtpd_callbacks[i].incoming) {
2007 ce062d50 2019-08-21 martijn if (osmtpd_callbacks[i].cb != NULL && cb != NULL)
2008 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Event already registered");
2009 912d0ff2 2019-08-22 martijn if (cb != NULL)
2010 912d0ff2 2019-08-22 martijn osmtpd_callbacks[i].cb = cb;
2011 ce062d50 2019-08-21 martijn osmtpd_callbacks[i].doregister = 1;
2012 ce062d50 2019-08-21 martijn if (storereport)
2013 ce062d50 2019-08-21 martijn osmtpd_callbacks[i].storereport = 1;
2014 ce062d50 2019-08-21 martijn return;
2017 ce062d50 2019-08-21 martijn /* NOT REACHED */
2018 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Trying to register unknown event");
2021 ce062d50 2019-08-21 martijn static enum osmtpd_phase
2022 ce062d50 2019-08-21 martijn osmtpd_strtophase(const char *phase, const char *linedup)
2024 ce062d50 2019-08-21 martijn if (strcmp(phase, "connect") == 0)
2025 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_CONNECT;
2026 ce062d50 2019-08-21 martijn if (strcmp(phase, "helo") == 0)
2027 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_HELO;
2028 ce062d50 2019-08-21 martijn if (strcmp(phase, "ehlo") == 0)
2029 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_EHLO;
2030 ce062d50 2019-08-21 martijn if (strcmp(phase, "starttls") == 0)
2031 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_STARTTLS;
2032 ce062d50 2019-08-21 martijn if (strcmp(phase, "auth") == 0)
2033 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_AUTH;
2034 ce062d50 2019-08-21 martijn if (strcmp(phase, "mail-from") == 0)
2035 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_MAIL_FROM;
2036 ce062d50 2019-08-21 martijn if (strcmp(phase, "rcpt-to") == 0)
2037 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_RCPT_TO;
2038 ce062d50 2019-08-21 martijn if (strcmp(phase, "data") == 0)
2039 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_DATA;
2040 ce062d50 2019-08-21 martijn if (strcmp(phase, "data-line") == 0)
2041 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_DATA_LINE;
2042 ce062d50 2019-08-21 martijn if (strcmp(phase, "rset") == 0)
2043 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_RSET;
2044 ce062d50 2019-08-21 martijn if (strcmp(phase, "quit") == 0)
2045 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_QUIT;
2046 ce062d50 2019-08-21 martijn if (strcmp(phase, "noop") == 0)
2047 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_NOOP;
2048 ce062d50 2019-08-21 martijn if (strcmp(phase, "help") == 0)
2049 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_HELP;
2050 ce062d50 2019-08-21 martijn if (strcmp(phase, "wiz") == 0)
2051 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_WIZ;
2052 ce062d50 2019-08-21 martijn if (strcmp(phase, "commit") == 0)
2053 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_COMMIT;
2054 ce062d50 2019-08-21 martijn if (strcmp(phase, "link-connect") == 0)
2055 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_LINK_CONNECT;
2056 ce062d50 2019-08-21 martijn if (strcmp(phase, "link-disconnect") == 0)
2057 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_LINK_DISCONNECT;
2058 b52f2785 2019-09-06 martijn if (strcmp(phase, "link-greeting") == 0)
2059 b52f2785 2019-09-06 martijn return OSMTPD_PHASE_LINK_GREETING;
2060 ce062d50 2019-08-21 martijn if (strcmp(phase, "link-identify") == 0)
2061 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_LINK_IDENTIFY;
2062 ce062d50 2019-08-21 martijn if (strcmp(phase, "link-tls") == 0)
2063 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_LINK_TLS;
2064 58a6bc69 2022-12-05 martijn if (strcmp(phase, "link-auth") == 0)
2065 58a6bc69 2022-12-05 martijn return OSMTPD_PHASE_LINK_AUTH;
2066 d308c531 2025-02-03 martijn if (strcmp(phase, "tx-reset") == 0)
2067 d308c531 2025-02-03 martijn return OSMTPD_PHASE_TX_RESET;
2068 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-begin") == 0)
2069 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_BEGIN;
2070 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-mail") == 0)
2071 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_MAIL;
2072 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-rcpt") == 0)
2073 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_RCPT;
2074 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-envelope") == 0)
2075 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_ENVELOPE;
2076 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-data") == 0)
2077 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_DATA;
2078 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-commit") == 0)
2079 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_COMMIT;
2080 ce062d50 2019-08-21 martijn if (strcmp(phase, "tx-rollback") == 0)
2081 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TX_ROLLBACK;
2082 ce062d50 2019-08-21 martijn if (strcmp(phase, "protocol-client") == 0)
2083 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_PROTOCOL_CLIENT;
2084 ce062d50 2019-08-21 martijn if (strcmp(phase, "protocol-server") == 0)
2085 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_PROTOCOL_SERVER;
2086 ce062d50 2019-08-21 martijn if (strcmp(phase, "filter-response") == 0)
2087 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_FILTER_RESPONSE;
2088 ce062d50 2019-08-21 martijn if (strcmp(phase, "timeout") == 0)
2089 ce062d50 2019-08-21 martijn return OSMTPD_PHASE_TIMEOUT;
2090 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid phase: %s", linedup);
2093 ce062d50 2019-08-21 martijn static const char *
2094 ce062d50 2019-08-21 martijn osmtpd_typetostr(enum osmtpd_type type)
2096 ce062d50 2019-08-21 martijn switch (type) {
2097 ce062d50 2019-08-21 martijn case OSMTPD_TYPE_FILTER:
2098 ce062d50 2019-08-21 martijn return "filter";
2099 ce062d50 2019-08-21 martijn case OSMTPD_TYPE_REPORT:
2100 ce062d50 2019-08-21 martijn return "report";
2102 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "In valid type: %d\n", type);
2105 ce062d50 2019-08-21 martijn static const char *
2106 ce062d50 2019-08-21 martijn osmtpd_phasetostr(enum osmtpd_phase phase)
2108 ce062d50 2019-08-21 martijn switch (phase) {
2109 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_CONNECT:
2110 ce062d50 2019-08-21 martijn return "connect";
2111 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_HELO:
2112 ce062d50 2019-08-21 martijn return "helo";
2113 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_EHLO:
2114 ce062d50 2019-08-21 martijn return "ehlo";
2115 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_STARTTLS:
2116 ce062d50 2019-08-21 martijn return "starttls";
2117 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_AUTH:
2118 ce062d50 2019-08-21 martijn return "auth";
2119 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_MAIL_FROM:
2120 ce062d50 2019-08-21 martijn return "mail-from";
2121 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_RCPT_TO:
2122 ce062d50 2019-08-21 martijn return "rcpt-to";
2123 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_DATA:
2124 ce062d50 2019-08-21 martijn return "data";
2125 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_DATA_LINE:
2126 ce062d50 2019-08-21 martijn return "data-line";
2127 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_RSET:
2128 ce062d50 2019-08-21 martijn return "rset";
2129 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_QUIT:
2130 ce062d50 2019-08-21 martijn return "quit";
2131 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_NOOP:
2132 ce062d50 2019-08-21 martijn return "noop";
2133 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_HELP:
2134 ce062d50 2019-08-21 martijn return "help";
2135 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_WIZ:
2136 ce062d50 2019-08-21 martijn return "wiz";
2137 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_COMMIT:
2138 ce062d50 2019-08-21 martijn return "commit";
2139 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_LINK_CONNECT:
2140 ce062d50 2019-08-21 martijn return "link-connect";
2141 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_LINK_DISCONNECT:
2142 ce062d50 2019-08-21 martijn return "link-disconnect";
2143 a05d5c54 2019-08-28 martijn case OSMTPD_PHASE_LINK_GREETING:
2144 a05d5c54 2019-08-28 martijn return "link-greeting";
2145 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_LINK_IDENTIFY:
2146 ce062d50 2019-08-21 martijn return "link-identify";
2147 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_LINK_TLS:
2148 ce062d50 2019-08-21 martijn return "link-tls";
2149 58a6bc69 2022-12-05 martijn case OSMTPD_PHASE_LINK_AUTH:
2150 58a6bc69 2022-12-05 martijn return "link-auth";
2151 d308c531 2025-02-03 martijn case OSMTPD_PHASE_TX_RESET:
2152 d308c531 2025-02-03 martijn return "tx-reset";
2153 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_BEGIN:
2154 ce062d50 2019-08-21 martijn return "tx-begin";
2155 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_MAIL:
2156 ce062d50 2019-08-21 martijn return "tx-mail";
2157 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_RCPT:
2158 ce062d50 2019-08-21 martijn return "tx-rcpt";
2159 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_ENVELOPE:
2160 ce062d50 2019-08-21 martijn return "tx-envelope";
2161 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_DATA:
2162 ce062d50 2019-08-21 martijn return "tx-data";
2163 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_COMMIT:
2164 ce062d50 2019-08-21 martijn return "tx-commit";
2165 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TX_ROLLBACK:
2166 ce062d50 2019-08-21 martijn return "tx-rollback";
2167 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_PROTOCOL_CLIENT:
2168 ce062d50 2019-08-21 martijn return "protocol-client";
2169 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_PROTOCOL_SERVER:
2170 ce062d50 2019-08-21 martijn return "protocol-server";
2171 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_FILTER_RESPONSE:
2172 ce062d50 2019-08-21 martijn return "filter-response";
2173 ce062d50 2019-08-21 martijn case OSMTPD_PHASE_TIMEOUT:
2174 ce062d50 2019-08-21 martijn return "timeout";
2176 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "In valid phase: %d\n", phase);
2179 53b354a9 2020-04-12 martijn static enum osmtpd_status
2180 53b354a9 2020-04-12 martijn osmtpd_strtostatus(const char *status, char *linedup)
2182 ce062d50 2019-08-21 martijn if (strcmp(status, "ok") == 0)
2183 ce062d50 2019-08-21 martijn return OSMTPD_STATUS_OK;
2184 ce062d50 2019-08-21 martijn else if (strcmp(status, "tempfail") == 0)
2185 ce062d50 2019-08-21 martijn return OSMTPD_STATUS_TEMPFAIL;
2186 ce062d50 2019-08-21 martijn else if (strcmp(status, "permfail") == 0)
2187 ce062d50 2019-08-21 martijn return OSMTPD_STATUS_PERMFAIL;
2188 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid status: %s\n", linedup);
2191 ce062d50 2019-08-21 martijn static void
2192 ce062d50 2019-08-21 martijn osmtpd_addrtoss(char *addr, struct sockaddr_storage *ss, int hasport,
2193 ce062d50 2019-08-21 martijn char *linedup)
2195 a37af028 2019-09-17 martijn char *port = NULL;
2196 ce062d50 2019-08-21 martijn const char *errstr = NULL;
2197 ce062d50 2019-08-21 martijn struct sockaddr_in *sin;
2198 ce062d50 2019-08-21 martijn struct sockaddr_in6 *sin6;
2199 ce062d50 2019-08-21 martijn struct sockaddr_un *sun;
2200 4574fbd0 2019-09-26 martijn size_t n;
2202 4574fbd0 2019-09-26 martijn if (addr[0] == '[') {
2203 ce062d50 2019-08-21 martijn sin6 = (struct sockaddr_in6 *)ss;
2204 ce062d50 2019-08-21 martijn sin6->sin6_family = AF_INET6;
2205 ce062d50 2019-08-21 martijn sin6->sin6_port = 0;
2206 ce062d50 2019-08-21 martijn if (hasport) {
2207 ce062d50 2019-08-21 martijn if ((port = strrchr(addr, ':')) == NULL)
2208 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
2209 ce062d50 2019-08-21 martijn "address (%s): %s", addr, linedup);
2210 4574fbd0 2019-09-26 martijn if (port[-1] != ']')
2211 4574fbd0 2019-09-26 martijn osmtpd_errx(1, "Invalid line received: invalid "
2212 4574fbd0 2019-09-26 martijn "address (%s): %s", addr, linedup);
2213 ce062d50 2019-08-21 martijn port++;
2214 ce062d50 2019-08-21 martijn sin6->sin6_port = htons(strtonum(port, 0, UINT16_MAX,
2215 ce062d50 2019-08-21 martijn &errstr));
2216 ce062d50 2019-08-21 martijn if (errstr != NULL)
2217 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
2218 ce062d50 2019-08-21 martijn "address (%s): %s", addr, linedup);
2219 4574fbd0 2019-09-26 martijn port[-2] = '\0';
2220 4574fbd0 2019-09-26 martijn } else {
2221 4574fbd0 2019-09-26 martijn n = strlen(addr);
2222 4574fbd0 2019-09-26 martijn if (addr[n - 1] != ']')
2223 4574fbd0 2019-09-26 martijn osmtpd_errx(1, "Invalid line received: invalid "
2224 4574fbd0 2019-09-26 martijn "address (%s): %s", addr, linedup);
2225 4574fbd0 2019-09-26 martijn addr[n - 1] = '\0';
2227 4574fbd0 2019-09-26 martijn switch (inet_pton(AF_INET6, addr + 1, &(sin6->sin6_addr))) {
2228 ce062d50 2019-08-21 martijn case 1:
2230 ce062d50 2019-08-21 martijn case 0:
2231 a37af028 2019-09-17 martijn if (hasport)
2232 4574fbd0 2019-09-26 martijn port[-2] = ']';
2234 4574fbd0 2019-09-26 martijn addr[n - 1] = ']';
2235 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid address "
2236 ce062d50 2019-08-21 martijn "(%s): %s", addr, linedup);
2237 ce062d50 2019-08-21 martijn default:
2238 a37af028 2019-09-17 martijn if (hasport)
2239 4574fbd0 2019-09-26 martijn port[-2] = ']';
2241 4574fbd0 2019-09-26 martijn addr[n - 1] = ']';
2242 c6cb29f3 2019-08-22 martijn osmtpd_err(1, "Can't parse address (%s): %s", addr,
2243 c6cb29f3 2019-08-22 martijn linedup);
2245 ce062d50 2019-08-21 martijn } else if (strncasecmp(addr, "unix:", 5) == 0) {
2246 ce062d50 2019-08-21 martijn sun = (struct sockaddr_un *)ss;
2247 ce062d50 2019-08-21 martijn sun->sun_family = AF_UNIX;
2248 ce062d50 2019-08-21 martijn if (strlcpy(sun->sun_path, addr,
2249 ce062d50 2019-08-21 martijn sizeof(sun->sun_path)) >= sizeof(sun->sun_path)) {
2250 c6cb29f3 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: address too "
2251 c6cb29f3 2019-08-22 martijn "long (%s): %s", addr, linedup);
2253 ce062d50 2019-08-21 martijn } else {
2254 ce062d50 2019-08-21 martijn sin = (struct sockaddr_in *)ss;
2255 ce062d50 2019-08-21 martijn sin->sin_family = AF_INET;
2256 ce062d50 2019-08-21 martijn sin->sin_port = 0;
2257 ce062d50 2019-08-21 martijn if (hasport) {
2258 ce062d50 2019-08-21 martijn if ((port = strrchr(addr, ':')) == NULL)
2259 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
2260 ce062d50 2019-08-21 martijn "address (%s): %s", addr, linedup);
2261 ce062d50 2019-08-21 martijn port++;
2262 ce062d50 2019-08-21 martijn sin->sin_port = htons(strtonum(port, 0, UINT16_MAX,
2263 ce062d50 2019-08-21 martijn &errstr));
2264 ce062d50 2019-08-21 martijn if (errstr != NULL)
2265 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid "
2266 ce062d50 2019-08-21 martijn "address (%s): %s", addr, linedup);
2267 ce062d50 2019-08-21 martijn port[-1] = '\0';
2269 ce062d50 2019-08-21 martijn switch (inet_pton(AF_INET, addr, &(sin->sin_addr))) {
2270 ce062d50 2019-08-21 martijn case 1:
2272 ce062d50 2019-08-21 martijn case 0:
2273 a37af028 2019-09-17 martijn if (hasport)
2274 a37af028 2019-09-17 martijn port[-1] = ':';
2275 27dd1f3b 2019-08-22 martijn osmtpd_errx(1, "Invalid line received: invalid address "
2276 ce062d50 2019-08-21 martijn "(%s): %s", addr, linedup);
2277 ce062d50 2019-08-21 martijn default:
2278 a37af028 2019-09-17 martijn if (hasport)
2279 a37af028 2019-09-17 martijn port[-1] = ':';
2280 c6cb29f3 2019-08-22 martijn osmtpd_err(1, "Can't parse address (%s): %s", addr,
2281 c6cb29f3 2019-08-22 martijn linedup);
2286 ce062d50 2019-08-21 martijn static int
2287 ce062d50 2019-08-21 martijn osmtpd_session_cmp(struct osmtpd_session *a, struct osmtpd_session *b)
2289 ce062d50 2019-08-21 martijn return a->ctx.reqid < b->ctx.reqid ? -1 : a->ctx.reqid > b->ctx.reqid;
2292 9e3e8410 2019-08-22 martijn RB_GENERATE_STATIC(osmtpd_sessions, osmtpd_session, entry, osmtpd_session_cmp);