Bug Summary

File:src/usr.sbin/smtpd/smtpd/../smtpd.c
Warning:line 1835, column 3
The right operand of '-' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name smtpd.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/smtpd/smtpd/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/usr.sbin/smtpd/smtpd/.. -D IO_TLS -D QUEUE_PROFILING -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/smtpd/smtpd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.sbin/smtpd/smtpd/../smtpd.c
1/* $OpenBSD: smtpd.c,v 1.346 2023/06/18 17:28:42 op Exp $ */
2
3/*
4 * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
5 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
6 * Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net>
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */
20
21#include <sys/wait.h>
22#include <sys/stat.h>
23
24#include <bsd_auth.h>
25#include <dirent.h>
26#include <errno(*__errno()).h>
27#include <fcntl.h>
28#include <fts.h>
29#include <grp.h>
30#include <inttypes.h>
31#include <paths.h>
32#include <poll.h>
33#include <pwd.h>
34#include <signal.h>
35#include <syslog.h>
36#include <stdlib.h>
37#include <string.h>
38#include <sysexits.h>
39#include <time.h>
40#include <tls.h>
41#include <unistd.h>
42
43#include "smtpd.h"
44#include "log.h"
45#include "ssl.h"
46
47#define SMTPD_MAXARG32 32
48
49static void parent_imsg(struct mproc *, struct imsg *);
50static void usage(void);
51static int smtpd(void);
52static void parent_shutdown(void);
53static void parent_send_config(int, short, void *);
54static void parent_send_config_lka(void);
55static void parent_send_config_dispatcher(void);
56static void parent_send_config_ca(void);
57static void parent_sig_handler(int, short, void *);
58static void forkmda(struct mproc *, uint64_t, struct deliver *);
59static int parent_forward_open(char *, char *, uid_t, gid_t);
60static struct child *child_add(pid_t, int, const char *);
61static struct mproc *start_child(int, char **, char *);
62static struct mproc *setup_peer(enum smtp_proc_type, pid_t, int);
63static void setup_peers(struct mproc *, struct mproc *);
64static void setup_done(struct mproc *);
65static void setup_proc(void);
66static struct mproc *setup_peer(enum smtp_proc_type, pid_t, int);
67static int imsg_wait(struct imsgbuf *, struct imsg *, int);
68
69static void offline_scan(int, short, void *);
70static int offline_add(char *, uid_t, gid_t);
71static void offline_done(void);
72static int offline_enqueue(char *, uid_t, gid_t);
73
74static void purge_task(void);
75static int parent_auth_user(const char *, const char *);
76static void load_pki_tree(void);
77static void load_pki_keys(void);
78
79static void fork_filter_processes(void);
80static void fork_filter_process(const char *, const char *, const char *, const char *, const char *, uint32_t);
81
82enum child_type {
83 CHILD_DAEMON,
84 CHILD_MDA,
85 CHILD_PROCESSOR,
86 CHILD_ENQUEUE_OFFLINE,
87};
88
89struct child {
90 pid_t pid;
91 enum child_type type;
92 const char *title;
93 int mda_out;
94 uint64_t mda_id;
95 char *path;
96 char *cause;
97};
98
99struct offline {
100 TAILQ_ENTRY(offline)struct { struct offline *tqe_next; struct offline **tqe_prev;
}
entry;
101 uid_t uid;
102 gid_t gid;
103 char *path;
104};
105
106#define OFFLINE_READMAX20 20
107#define OFFLINE_QUEUEMAX5 5
108static size_t offline_running = 0;
109TAILQ_HEAD(, offline)struct { struct offline *tqh_first; struct offline **tqh_last
; }
offline_q;
110
111static struct event config_ev;
112static struct event offline_ev;
113static struct timeval offline_timeout;
114
115static pid_t purge_pid = -1;
116
117extern char **environ;
118void (*imsg_callback)(struct mproc *, struct imsg *);
119
120enum smtp_proc_type smtpd_process;
121
122struct smtpd *env = NULL((void *)0);
123
124struct mproc *p_control = NULL((void *)0);
125struct mproc *p_lka = NULL((void *)0);
126struct mproc *p_parent = NULL((void *)0);
127struct mproc *p_queue = NULL((void *)0);
128struct mproc *p_scheduler = NULL((void *)0);
129struct mproc *p_dispatcher = NULL((void *)0);
130struct mproc *p_ca = NULL((void *)0);
131
132const char *backend_queue = "fs";
133const char *backend_scheduler = "ramqueue";
134const char *backend_stat = "ram";
135
136int profiling = 0;
137int debug = 0;
138int foreground = 0;
139int control_socket = -1;
140
141struct tree children;
142
143static void
144parent_imsg(struct mproc *p, struct imsg *imsg)
145{
146 struct forward_req *fwreq;
147 struct filter_proc *processor;
148 struct deliver deliver;
149 struct child *c;
150 struct msg m;
151 const void *data;
152 const char *username, *password, *cause, *procname;
153 uint64_t reqid;
154 size_t sz;
155 void *i;
156 int fd, n, v, ret;
157
158 if (imsg == NULL((void *)0))
159 fatalx("process %s socket closed", p->name);
160
161 switch (imsg->hdr.type) {
162 case IMSG_LKA_OPEN_FORWARD:
163 CHECK_IMSG_DATA_SIZE(imsg, sizeof *fwreq)do { if ((imsg)->hdr.len - sizeof(struct imsg_hdr) != (sizeof
*fwreq)) fatalx("smtpd: imsg %d: data size expected %zd got %zd"
, (imsg)->hdr.type, (sizeof *fwreq), (imsg)->hdr.len - sizeof
(struct imsg_hdr)); } while (0)
;
164 fwreq = imsg->data;
165 fd = parent_forward_open(fwreq->user, fwreq->directory,
166 fwreq->uid, fwreq->gid);
167 fwreq->status = 0;
168 if (fd == -1 && errno(*__errno()) != ENOENT2) {
169 if (errno(*__errno()) == EAGAIN35)
170 fwreq->status = -1;
171 }
172 else
173 fwreq->status = 1;
174 m_compose(p, IMSG_LKA_OPEN_FORWARD, 0, 0, fd,
175 fwreq, sizeof *fwreq);
176 return;
177
178 case IMSG_LKA_AUTHENTICATE:
179 /*
180 * If we reached here, it means we want root to lookup
181 * system user.
182 */
183 m_msg(&m, imsg);
184 m_get_id(&m, &reqid);
185 m_get_string(&m, &username);
186 m_get_string(&m, &password);
187 m_end(&m);
188
189 ret = parent_auth_user(username, password);
190
191 m_create(p, IMSG_LKA_AUTHENTICATE, 0, 0, -1);
192 m_add_id(p, reqid);
193 m_add_int(p, ret);
194 m_close(p);
195 return;
196
197 case IMSG_MDA_FORK:
198 m_msg(&m, imsg);
199 m_get_id(&m, &reqid);
200 m_get_data(&m, &data, &sz);
201 m_end(&m);
202 if (sz != sizeof(deliver))
203 fatalx("expected deliver");
204 memmove(&deliver, data, sz);
205 forkmda(p, reqid, &deliver);
206 return;
207
208 case IMSG_MDA_KILL:
209 m_msg(&m, imsg);
210 m_get_id(&m, &reqid);
211 m_get_string(&m, &cause);
212 m_end(&m);
213
214 i = NULL((void *)0);
215 while ((n = tree_iter(&children, &i, NULL((void *)0), (void**)&c)))
216 if (c->type == CHILD_MDA &&
217 c->mda_id == reqid &&
218 c->cause == NULL((void *)0))
219 break;
220 if (!n) {
221 log_debug("debug: smtpd: "
222 "kill request: proc not found");
223 return;
224 }
225
226 c->cause = xstrdup(cause);
227 log_debug("debug: smtpd: kill requested for %u: %s",
228 c->pid, c->cause);
229 kill(c->pid, SIGTERM15);
230 return;
231
232 case IMSG_CTL_VERBOSE:
233 m_msg(&m, imsg);
234 m_get_int(&m, &v);
235 m_end(&m);
236 log_trace_verbose(v);
237 return;
238
239 case IMSG_CTL_PROFILE:
240 m_msg(&m, imsg);
241 m_get_int(&m, &v);
242 m_end(&m);
243 profiling = v;
244 return;
245
246 case IMSG_LKA_PROCESSOR_ERRFD:
247 m_msg(&m, imsg);
248 m_get_string(&m, &procname);
249 m_end(&m);
250
251 processor = dict_xget(env->sc_filter_processes_dict, procname);
252 m_create(p_lka, IMSG_LKA_PROCESSOR_ERRFD, 0, 0, processor->errfd);
253 m_add_string(p_lka, procname);
254 m_close(p_lka);
255 return;
256 }
257
258 fatalx("parent_imsg: unexpected %s imsg from %s",
259 imsg_to_str(imsg->hdr.type), proc_title(p->proc));
260}
261
262static void
263usage(void)
264{
265 extern char *__progname;
266
267 fprintf(stderr(&__sF[2]), "usage: %s [-dFhnv] [-D macro=value] "
268 "[-f file] [-P system] [-T trace]\n", __progname);
269 exit(1);
270}
271
272static void
273parent_shutdown(void)
274{
275 pid_t pid;
276
277 mproc_clear(p_ca);
278 mproc_clear(p_dispatcher);
279 mproc_clear(p_control);
280 mproc_clear(p_lka);
281 mproc_clear(p_scheduler);
282 mproc_clear(p_queue);
283
284 do {
285 pid = waitpid(WAIT_MYPGRP0, NULL((void *)0), 0);
286 } while (pid != -1 || (pid == -1 && errno(*__errno()) == EINTR4));
287
288 unlink(SMTPD_SOCKET"/var/run/smtpd.sock");
289
290 log_info("Exiting");
291 exit(0);
292}
293
294static void
295parent_send_config(int fd, short event, void *p)
296{
297 parent_send_config_lka();
298 parent_send_config_dispatcher();
299 parent_send_config_ca();
300 purge_config(PURGE_PKI0x08);
301}
302
303static void
304parent_send_config_dispatcher(void)
305{
306 log_debug("debug: parent_send_config: configuring dispatcher process");
307 m_compose(p_dispatcher, IMSG_CONF_START, 0, 0, -1, NULL((void *)0), 0);
308 m_compose(p_dispatcher, IMSG_CONF_END, 0, 0, -1, NULL((void *)0), 0);
309}
310
311void
312parent_send_config_lka(void)
313{
314 log_debug("debug: parent_send_config_ruleset: reloading");
315 m_compose(p_lka, IMSG_CONF_START, 0, 0, -1, NULL((void *)0), 0);
316 m_compose(p_lka, IMSG_CONF_END, 0, 0, -1, NULL((void *)0), 0);
317}
318
319static void
320parent_send_config_ca(void)
321{
322 log_debug("debug: parent_send_config: configuring ca process");
323 m_compose(p_ca, IMSG_CONF_START, 0, 0, -1, NULL((void *)0), 0);
324 m_compose(p_ca, IMSG_CONF_END, 0, 0, -1, NULL((void *)0), 0);
325}
326
327static void
328parent_sig_handler(int sig, short event, void *p)
329{
330 struct child *child;
331 int status, fail;
332 pid_t pid;
333 char *cause;
334
335 switch (sig) {
336 case SIGTERM15:
337 case SIGINT2:
338 log_debug("debug: got signal %d", sig);
339 parent_shutdown();
340 /* NOT REACHED */
341
342 case SIGCHLD20:
343 do {
344 int len;
345 enum mda_resp_status mda_status;
346 int mda_sysexit;
347
348 pid = waitpid(-1, &status, WNOHANG0x01);
349 if (pid <= 0)
350 continue;
351
352 fail = 0;
353 if (WIFSIGNALED(status)(((status) & 0177) != 0177 && ((status) & 0177
) != 0)
) {
354 fail = 1;
355 len = asprintf(&cause, "terminated; signal %d",
356 WTERMSIG(status)(((status) & 0177)));
357 mda_status = MDA_TEMPFAIL;
358 mda_sysexit = 0;
359 } else if (WIFEXITED(status)(((status) & 0177) == 0)) {
360 if (WEXITSTATUS(status)(int)(((unsigned)(status) >> 8) & 0xff) != 0) {
361 fail = 1;
362 len = asprintf(&cause,
363 "exited abnormally");
364 mda_sysexit = WEXITSTATUS(status)(int)(((unsigned)(status) >> 8) & 0xff);
365 if (mda_sysexit == EX_OSERR71 ||
366 mda_sysexit == EX_TEMPFAIL75)
367 mda_status = MDA_TEMPFAIL;
368 else
369 mda_status = MDA_PERMFAIL;
370 } else {
371 len = asprintf(&cause, "exited okay");
372 mda_status = MDA_OK;
373 mda_sysexit = 0;
374 }
375 } else
376 /* WIFSTOPPED or WIFCONTINUED */
377 continue;
378
379 if (len == -1)
380 fatal("asprintf");
381
382 if (pid == purge_pid)
383 purge_pid = -1;
384
385 child = tree_pop(&children, pid);
386 if (child == NULL((void *)0))
387 goto skip;
388
389 switch (child->type) {
390 case CHILD_PROCESSOR:
391 if (fail) {
392 log_warnx("warn: lost processor: %s %s",
393 child->title, cause);
394 parent_shutdown();
395 }
396 break;
397
398 case CHILD_DAEMON:
399 if (fail)
400 log_warnx("warn: lost child: %s %s",
401 child->title, cause);
402 break;
403
404 case CHILD_MDA:
405 if (WIFSIGNALED(status)(((status) & 0177) != 0177 && ((status) & 0177
) != 0)
&&
406 WTERMSIG(status)(((status) & 0177)) == SIGALRM14) {
407 char *tmp;
408 if (asprintf(&tmp,
409 "terminated; timeout") != -1) {
410 free(cause);
411 cause = tmp;
412 }
413 }
414 else if (child->cause &&
415 WIFSIGNALED(status)(((status) & 0177) != 0177 && ((status) & 0177
) != 0)
&&
416 WTERMSIG(status)(((status) & 0177)) == SIGTERM15) {
417 free(cause);
418 cause = child->cause;
419 child->cause = NULL((void *)0);
420 }
421 free(child->cause);
422 log_debug("debug: smtpd: mda process done "
423 "for session %016"PRIx64"llx" ": %s",
424 child->mda_id, cause);
425
426 m_create(p_dispatcher, IMSG_MDA_DONE, 0, 0,
427 child->mda_out);
428 m_add_id(p_dispatcher, child->mda_id);
429 m_add_int(p_dispatcher, mda_status);
430 m_add_int(p_dispatcher, mda_sysexit);
431 m_add_string(p_dispatcher, cause);
432 m_close(p_dispatcher);
433
434 break;
435
436 case CHILD_ENQUEUE_OFFLINE:
437 if (fail)
438 log_warnx("warn: smtpd: "
439 "couldn't enqueue offline "
440 "message %s; smtpctl %s",
441 child->path, cause);
442 else
443 unlink(child->path);
444 free(child->path);
445 offline_done();
446 break;
447
448 default:
449 fatalx("smtpd: unexpected child type");
450 }
451 free(child);
452 skip:
453 free(cause);
454 } while (pid > 0 || (pid == -1 && errno(*__errno()) == EINTR4));
455
456 break;
457 default:
458 fatalx("smtpd: unexpected signal");
459 }
460}
461
462int
463main(int argc, char *argv[])
464{
465 int c, i;
466 int opts, flags;
467 const char *conffile = CONF_FILE"/etc/mail/smtpd.conf";
468 int save_argc = argc;
469 char **save_argv = argv;
470 char *rexec = NULL((void *)0);
471 struct smtpd *conf;
472
473 flags = 0;
474 opts = 0;
475 debug = 0;
476 tracing = 0;
477
478 log_init(1, LOG_MAIL(2<<3));
479
480 if ((conf = config_default()) == NULL((void *)0))
481 fatal("config_default");
482 env = conf;
483
484 TAILQ_INIT(&offline_q)do { (&offline_q)->tqh_first = ((void *)0); (&offline_q
)->tqh_last = &(&offline_q)->tqh_first; } while
(0)
;
485
486 while ((c = getopt(argc, argv, "B:dD:hnP:f:FT:vx:")) != -1) {
487 switch (c) {
488 case 'B':
489 if (strstr(optarg, "queue=") == optarg)
490 backend_queue = strchr(optarg, '=') + 1;
491 else if (strstr(optarg, "scheduler=") == optarg)
492 backend_scheduler = strchr(optarg, '=') + 1;
493 else if (strstr(optarg, "stat=") == optarg)
494 backend_stat = strchr(optarg, '=') + 1;
495 else
496 log_warnx("warn: "
497 "invalid backend specifier %s",
498 optarg);
499 break;
500 case 'd':
501 foreground = 1;
502 foreground_log = 1;
503 break;
504 case 'D':
505 if (cmdline_symset(optarg) < 0)
506 log_warnx("warn: "
507 "could not parse macro definition %s",
508 optarg);
509 break;
510 case 'h':
511 log_info("version: " SMTPD_NAME"OpenSMTPD" " " SMTPD_VERSION"7.4.0");
512 usage();
513 break;
514 case 'n':
515 debug = 2;
516 opts |= SMTPD_OPT_NOACTION0x00000002;
517 break;
518 case 'f':
519 conffile = optarg;
520 break;
521 case 'F':
522 foreground = 1;
523 break;
524
525 case 'T':
526 if (!strcmp(optarg, "imsg"))
527 tracing |= TRACE_IMSG0x0002;
528 else if (!strcmp(optarg, "io"))
529 tracing |= TRACE_IO0x0004;
530 else if (!strcmp(optarg, "smtp"))
531 tracing |= TRACE_SMTP0x0008;
532 else if (!strcmp(optarg, "filters"))
533 tracing |= TRACE_FILTERS0x0010;
534 else if (!strcmp(optarg, "mta") ||
535 !strcmp(optarg, "transfer"))
536 tracing |= TRACE_MTA0x0020;
537 else if (!strcmp(optarg, "bounce") ||
538 !strcmp(optarg, "bounces"))
539 tracing |= TRACE_BOUNCE0x0040;
540 else if (!strcmp(optarg, "scheduler"))
541 tracing |= TRACE_SCHEDULER0x0080;
542 else if (!strcmp(optarg, "lookup"))
543 tracing |= TRACE_LOOKUP0x0100;
544 else if (!strcmp(optarg, "stat") ||
545 !strcmp(optarg, "stats"))
546 tracing |= TRACE_STAT0x0200;
547 else if (!strcmp(optarg, "rules"))
548 tracing |= TRACE_RULES0x0400;
549 else if (!strcmp(optarg, "mproc"))
550 tracing |= TRACE_MPROC0x0800;
551 else if (!strcmp(optarg, "expand"))
552 tracing |= TRACE_EXPAND0x1000;
553 else if (!strcmp(optarg, "table") ||
554 !strcmp(optarg, "tables"))
555 tracing |= TRACE_TABLES0x2000;
556 else if (!strcmp(optarg, "queue"))
557 tracing |= TRACE_QUEUE0x4000;
558 else if (!strcmp(optarg, "all"))
559 tracing |= ~TRACE_DEBUG0x0001;
560 else if (!strcmp(optarg, "profstat"))
561 profiling |= PROFILE_TOSTAT0x0001;
562 else if (!strcmp(optarg, "profile-imsg"))
563 profiling |= PROFILE_IMSG0x0002;
564 else if (!strcmp(optarg, "profile-queue"))
565 profiling |= PROFILE_QUEUE0x0004;
566 else
567 log_warnx("warn: unknown trace flag \"%s\"",
568 optarg);
569 break;
570 case 'P':
571 if (!strcmp(optarg, "smtp"))
572 flags |= SMTPD_SMTP_PAUSED0x00000008;
573 else if (!strcmp(optarg, "mta"))
574 flags |= SMTPD_MTA_PAUSED0x00000004;
575 else if (!strcmp(optarg, "mda"))
576 flags |= SMTPD_MDA_PAUSED0x00000002;
577 break;
578 case 'v':
579 tracing |= TRACE_DEBUG0x0001;
580 break;
581 case 'x':
582 rexec = optarg;
583 break;
584 default:
585 usage();
586 }
587 }
588
589 argv += optind;
590 argc -= optind;
591
592 if (argc || *argv)
593 usage();
594
595 env->sc_opts |= opts;
596
597 if (parse_config(conf, conffile, opts))
598 exit(1);
599
600 if (strlcpy(env->sc_conffile, conffile, PATH_MAX1024)
601 >= PATH_MAX1024)
602 fatalx("config file exceeds PATH_MAX");
603
604 if (env->sc_opts & SMTPD_OPT_NOACTION0x00000002) {
605 if (env->sc_queue_key &&
606 crypto_setup(env->sc_queue_key,
607 strlen(env->sc_queue_key)) == 0) {
608 fatalx("crypto_setup:"
609 "invalid key for queue encryption");
610 }
611 load_pki_tree();
612 load_pki_keys();
613 fprintf(stderr(&__sF[2]), "configuration OK\n");
614 exit(0);
615 }
616
617 env->sc_flags |= flags;
618
619 /* check for root privileges */
620 if (geteuid())
621 fatalx("need root privileges");
622
623 log_init(foreground_log, LOG_MAIL(2<<3));
624 log_trace_verbose(tracing);
625 load_pki_tree();
626 load_pki_keys();
627
628 log_debug("debug: using \"%s\" queue backend", backend_queue);
629 log_debug("debug: using \"%s\" scheduler backend", backend_scheduler);
630 log_debug("debug: using \"%s\" stat backend", backend_stat);
631
632 if (env->sc_hostname[0] == '\0')
633 fatalx("machine does not have a hostname set");
634 env->sc_uptime = time(NULL((void *)0));
635
636 if (rexec == NULL((void *)0)) {
637 smtpd_process = PROC_PARENT;
638
639 if (env->sc_queue_flags & QUEUE_ENCRYPTION0x00000002) {
640 if (env->sc_queue_key == NULL((void *)0)) {
641 char *password;
642
643 password = getpass("queue key: ");
644 if (password == NULL((void *)0))
645 fatal("getpass");
646
647 env->sc_queue_key = strdup(password);
648 explicit_bzero(password, strlen(password));
649 if (env->sc_queue_key == NULL((void *)0))
650 fatal("strdup");
651 }
652 else {
653 char *buf = NULL((void *)0);
654 size_t sz = 0;
655 ssize_t len;
656
657 if (strcasecmp(env->sc_queue_key, "stdin") == 0) {
658 if ((len = getline(&buf, &sz, stdin(&__sF[0]))) == -1)
659 fatal("getline");
660 if (buf[len - 1] == '\n')
661 buf[len - 1] = '\0';
662 env->sc_queue_key = buf;
663 }
664 }
665 }
666
667 log_info("info: %s %s starting", SMTPD_NAME"OpenSMTPD", SMTPD_VERSION"7.4.0");
668
669 if (!foreground)
670 if (daemon(0, 0) == -1)
671 fatal("failed to daemonize");
672
673 /* setup all processes */
674
675 p_ca = start_child(save_argc, save_argv, "ca");
676 p_ca->proc = PROC_CA;
677
678 p_control = start_child(save_argc, save_argv, "control");
679 p_control->proc = PROC_CONTROL;
680
681 p_lka = start_child(save_argc, save_argv, "lka");
682 p_lka->proc = PROC_LKA;
683
684 p_dispatcher = start_child(save_argc, save_argv, "dispatcher");
685 p_dispatcher->proc = PROC_DISPATCHER;
686
687 p_queue = start_child(save_argc, save_argv, "queue");
688 p_queue->proc = PROC_QUEUE;
689
690 p_scheduler = start_child(save_argc, save_argv, "scheduler");
691 p_scheduler->proc = PROC_SCHEDULER;
692
693 setup_peers(p_control, p_ca);
694 setup_peers(p_control, p_lka);
695 setup_peers(p_control, p_dispatcher);
696 setup_peers(p_control, p_queue);
697 setup_peers(p_control, p_scheduler);
698 setup_peers(p_dispatcher, p_ca);
699 setup_peers(p_dispatcher, p_lka);
700 setup_peers(p_dispatcher, p_queue);
701 setup_peers(p_queue, p_lka);
702 setup_peers(p_queue, p_scheduler);
703
704 if (env->sc_queue_key) {
705 if (imsg_compose(&p_queue->imsgbuf, IMSG_SETUP_KEY, 0,
706 0, -1, env->sc_queue_key, strlen(env->sc_queue_key)
707 + 1) == -1)
708 fatal("imsg_compose");
709 if (imsg_flush(&p_queue->imsgbuf) == -1)
710 fatal("imsg_flush");
711 }
712
713 setup_done(p_ca);
714 setup_done(p_control);
715 setup_done(p_lka);
716 setup_done(p_dispatcher);
717 setup_done(p_queue);
718 setup_done(p_scheduler);
719
720 log_debug("smtpd: setup done");
721
722 return smtpd();
723 }
724
725 if (!strcmp(rexec, "ca")) {
726 smtpd_process = PROC_CA;
727 setup_proc();
728
729 return ca();
730 }
731
732 else if (!strcmp(rexec, "control")) {
733 smtpd_process = PROC_CONTROL;
734 setup_proc();
735
736 /* the control socket ensures that only one smtpd instance is running */
737 control_socket = control_create_socket();
738
739 env->sc_stat = stat_backend_lookup(backend_stat);
740 if (env->sc_stat == NULL((void *)0))
741 fatalx("could not find stat backend \"%s\"", backend_stat);
742
743 return control();
744 }
745
746 else if (!strcmp(rexec, "lka")) {
747 smtpd_process = PROC_LKA;
748 setup_proc();
749
750 return lka();
751 }
752
753 else if (!strcmp(rexec, "dispatcher")) {
754 smtpd_process = PROC_DISPATCHER;
755 setup_proc();
756
757 return dispatcher();
758 }
759
760 else if (!strcmp(rexec, "queue")) {
761 smtpd_process = PROC_QUEUE;
762 setup_proc();
763
764 if (env->sc_queue_flags & QUEUE_COMPRESSION0x00000001)
765 env->sc_comp = compress_backend_lookup("gzip");
766
767 if (!queue_init(backend_queue, 1))
768 fatalx("could not initialize queue backend");
769
770 return queue();
771 }
772
773 else if (!strcmp(rexec, "scheduler")) {
774 smtpd_process = PROC_SCHEDULER;
775 setup_proc();
776
777 for (i = 0; i < MAX_BOUNCE_WARN4; i++) {
778 if (env->sc_bounce_warn[i] == 0)
779 break;
780 log_debug("debug: bounce warning after %s",
781 duration_to_text(env->sc_bounce_warn[i]));
782 }
783
784 return scheduler();
785 }
786
787 fatalx("bad rexec: %s", rexec);
788
789 return (1);
790}
791
792static struct mproc *
793start_child(int save_argc, char **save_argv, char *rexec)
794{
795 struct mproc *p;
796 char *argv[SMTPD_MAXARG32];
797 int sp[2], argc = 0;
798 pid_t pid;
799
800 if (save_argc >= SMTPD_MAXARG32 - 2)
801 fatalx("too many arguments");
802
803 if (socketpair(AF_UNIX1, SOCK_STREAM1, PF_UNSPEC0, sp) == -1)
804 fatal("socketpair");
805
806 io_set_nonblocking(sp[0]);
807 io_set_nonblocking(sp[1]);
808
809 switch (pid = fork()) {
810 case -1:
811 fatal("%s: fork", save_argv[0]);
812 case 0:
813 break;
814 default:
815 close(sp[0]);
816 p = calloc(1, sizeof(*p));
817 if (p == NULL((void *)0))
818 fatal("calloc");
819 if((p->name = strdup(rexec)) == NULL((void *)0))
820 fatal("strdup");
821 mproc_init(p, sp[1]);
822 p->pid = pid;
823 p->handler = parent_imsg;
824 return p;
825 }
826
827 if (sp[0] != 3) {
828 if (dup2(sp[0], 3) == -1)
829 fatal("%s: dup2", rexec);
830 } else if (fcntl(sp[0], F_SETFD2, 0) == -1)
831 fatal("%s: fcntl", rexec);
832
833 if (closefrom(4) == -1)
834 fatal("%s: closefrom", rexec);
835
836 for (argc = 0; argc < save_argc; argc++)
837 argv[argc] = save_argv[argc];
838 argv[argc++] = "-x";
839 argv[argc++] = rexec;
840 argv[argc++] = NULL((void *)0);
841
842 execvp(argv[0], argv);
843 fatal("%s: execvp", rexec);
844}
845
846static void
847setup_peers(struct mproc *a, struct mproc *b)
848{
849 int sp[2];
850
851 if (socketpair(AF_UNIX1, SOCK_STREAM1, PF_UNSPEC0, sp) == -1)
852 fatal("socketpair");
853
854 io_set_nonblocking(sp[0]);
855 io_set_nonblocking(sp[1]);
856
857 if (imsg_compose(&a->imsgbuf, IMSG_SETUP_PEER, b->proc, b->pid, sp[0],
858 NULL((void *)0), 0) == -1)
859 fatal("imsg_compose");
860 if (imsg_flush(&a->imsgbuf) == -1)
861 fatal("imsg_flush");
862
863 if (imsg_compose(&b->imsgbuf, IMSG_SETUP_PEER, a->proc, a->pid, sp[1],
864 NULL((void *)0), 0) == -1)
865 fatal("imsg_compose");
866 if (imsg_flush(&b->imsgbuf) == -1)
867 fatal("imsg_flush");
868}
869
870static void
871setup_done(struct mproc *p)
872{
873 struct imsg imsg;
874
875 if (imsg_compose(&p->imsgbuf, IMSG_SETUP_DONE, 0, 0, -1, NULL((void *)0), 0) == -1)
876 fatal("imsg_compose");
877 if (imsg_flush(&p->imsgbuf) == -1)
878 fatal("imsg_flush");
879
880 if (imsg_wait(&p->imsgbuf, &imsg, 10000) == -1)
881 fatal("imsg_wait");
882
883 if (imsg.hdr.type != IMSG_SETUP_DONE)
884 fatalx("expect IMSG_SETUP_DONE");
885
886 log_debug("setup_done: %s[%d] done", p->name, p->pid);
887
888 imsg_free(&imsg);
889}
890
891static void
892setup_proc(void)
893{
894 struct imsgbuf *ibuf;
895 struct imsg imsg;
896 int setup = 1;
897
898 log_procinit(proc_title(smtpd_process));
899
900 p_parent = calloc(1, sizeof(*p_parent));
901 if (p_parent == NULL((void *)0))
902 fatal("calloc");
903 if((p_parent->name = strdup("parent")) == NULL((void *)0))
904 fatal("strdup");
905 p_parent->proc = PROC_PARENT;
906 p_parent->handler = imsg_dispatch;
907 mproc_init(p_parent, 3);
908
909 ibuf = &p_parent->imsgbuf;
910
911 while (setup) {
912 if (imsg_wait(ibuf, &imsg, 10000) == -1)
913 fatal("imsg_wait");
914
915 switch (imsg.hdr.type) {
916 case IMSG_SETUP_KEY:
917 env->sc_queue_key = strdup(imsg.data);
918 break;
919 case IMSG_SETUP_PEER:
920 setup_peer(imsg.hdr.peerid, imsg.hdr.pid, imsg.fd);
921 break;
922 case IMSG_SETUP_DONE:
923 setup = 0;
924 break;
925 default:
926 fatal("bad imsg %d", imsg.hdr.type);
927 }
928 imsg_free(&imsg);
929 }
930
931 if (imsg_compose(ibuf, IMSG_SETUP_DONE, 0, 0, -1, NULL((void *)0), 0) == -1)
932 fatal("imsg_compose");
933
934 if (imsg_flush(ibuf) == -1)
935 fatal("imsg_flush");
936
937 log_debug("setup_proc: %s done", proc_title(smtpd_process));
938}
939
940static struct mproc *
941setup_peer(enum smtp_proc_type proc, pid_t pid, int sock)
942{
943 struct mproc *p, **pp;
944
945 log_debug("setup_peer: %s -> %s[%u] fd=%d", proc_title(smtpd_process),
946 proc_title(proc), pid, sock);
947
948 if (sock == -1)
949 fatalx("peer socket not received");
950
951 switch (proc) {
952 case PROC_LKA:
953 pp = &p_lka;
954 break;
955 case PROC_QUEUE:
956 pp = &p_queue;
957 break;
958 case PROC_CONTROL:
959 pp = &p_control;
960 break;
961 case PROC_SCHEDULER:
962 pp = &p_scheduler;
963 break;
964 case PROC_DISPATCHER:
965 pp = &p_dispatcher;
966 break;
967 case PROC_CA:
968 pp = &p_ca;
969 break;
970 default:
971 fatalx("unknown peer");
972 }
973
974 if (*pp)
975 fatalx("peer already set");
976
977 p = calloc(1, sizeof(*p));
978 if (p == NULL((void *)0))
979 fatal("calloc");
980 if((p->name = strdup(proc_title(proc))) == NULL((void *)0))
981 fatal("strdup");
982 mproc_init(p, sock);
983 p->pid = pid;
984 p->proc = proc;
985 p->handler = imsg_dispatch;
986
987 *pp = p;
988
989 return p;
990}
991
992static int
993imsg_wait(struct imsgbuf *ibuf, struct imsg *imsg, int timeout)
994{
995 struct pollfd pfd[1];
996 ssize_t n;
997
998 pfd[0].fd = ibuf->fd;
999 pfd[0].events = POLLIN0x0001;
1000
1001 while (1) {
1002 if ((n = imsg_get(ibuf, imsg)) == -1)
1003 return -1;
1004 if (n)
1005 return 1;
1006
1007 n = poll(pfd, 1, timeout);
1008 if (n == -1)
1009 return -1;
1010 if (n == 0) {
1011 errno(*__errno()) = ETIMEDOUT60;
1012 return -1;
1013 }
1014
1015 if (((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35) || n == 0)
1016 return -1;
1017 }
1018}
1019
1020int
1021smtpd(void) {
1022 struct event ev_sigint;
1023 struct event ev_sigterm;
1024 struct event ev_sigchld;
1025 struct event ev_sighup;
1026 struct timeval tv;
1027
1028 imsg_callback = parent_imsg;
1029
1030 tree_init(&children)do { do { (&((&children)->tree))->sph_root = ((
void *)0); } while (0); (&children)->count = 0; } while
(0)
;
1031
1032 child_add(p_queue->pid, CHILD_DAEMON, proc_title(PROC_QUEUE));
1033 child_add(p_control->pid, CHILD_DAEMON, proc_title(PROC_CONTROL));
1034 child_add(p_lka->pid, CHILD_DAEMON, proc_title(PROC_LKA));
1035 child_add(p_scheduler->pid, CHILD_DAEMON, proc_title(PROC_SCHEDULER));
1036 child_add(p_dispatcher->pid, CHILD_DAEMON, proc_title(PROC_DISPATCHER));
1037 child_add(p_ca->pid, CHILD_DAEMON, proc_title(PROC_CA));
1038
1039 event_init();
1040
1041 signal_set(&ev_sigint, SIGINT, parent_sig_handler, NULL)event_set(&ev_sigint, 2, 0x08|0x10, parent_sig_handler, (
(void *)0))
;
1042 signal_set(&ev_sigterm, SIGTERM, parent_sig_handler, NULL)event_set(&ev_sigterm, 15, 0x08|0x10, parent_sig_handler,
((void *)0))
;
1043 signal_set(&ev_sigchld, SIGCHLD, parent_sig_handler, NULL)event_set(&ev_sigchld, 20, 0x08|0x10, parent_sig_handler,
((void *)0))
;
1044 signal_set(&ev_sighup, SIGHUP, parent_sig_handler, NULL)event_set(&ev_sighup, 1, 0x08|0x10, parent_sig_handler, (
(void *)0))
;
1045 signal_add(&ev_sigint, NULL)event_add(&ev_sigint, ((void *)0));
1046 signal_add(&ev_sigterm, NULL)event_add(&ev_sigterm, ((void *)0));
1047 signal_add(&ev_sigchld, NULL)event_add(&ev_sigchld, ((void *)0));
1048 signal_add(&ev_sighup, NULL)event_add(&ev_sighup, ((void *)0));
1049 signal(SIGPIPE13, SIG_IGN(void (*)(int))1);
1050
1051 config_peer(PROC_CONTROL);
1052 config_peer(PROC_LKA);
1053 config_peer(PROC_QUEUE);
1054 config_peer(PROC_CA);
1055 config_peer(PROC_DISPATCHER);
1056
1057 evtimer_set(&config_ev, parent_send_config, NULL)event_set(&config_ev, -1, 0, parent_send_config, ((void *
)0))
;
1058 memset(&tv, 0, sizeof(tv));
1059 evtimer_add(&config_ev, &tv)event_add(&config_ev, &tv);
1060
1061 /* defer offline scanning for a second */
1062 evtimer_set(&offline_ev, offline_scan, NULL)event_set(&offline_ev, -1, 0, offline_scan, ((void *)0));
1063 offline_timeout.tv_sec = 1;
1064 offline_timeout.tv_usec = 0;
1065 evtimer_add(&offline_ev, &offline_timeout)event_add(&offline_ev, &offline_timeout);
1066
1067 fork_filter_processes();
1068
1069 purge_task();
1070
1071 if (pledge("stdio rpath wpath cpath fattr tmppath "
1072 "getpw sendfd proc exec id inet chown unix", NULL((void *)0)) == -1)
1073 fatal("pledge");
1074
1075 event_dispatch();
1076 fatalx("exited event loop");
1077
1078 return (0);
1079}
1080
1081static void
1082load_pki_tree(void)
1083{
1084 struct pki *pki;
1085 struct ca *sca;
1086 const char *k;
1087 void *iter_dict;
1088
1089 log_debug("debug: init ssl-tree");
1090 iter_dict = NULL((void *)0);
1091 while (dict_iter(env->sc_pki_dict, &iter_dict, &k, (void **)&pki)) {
1092 log_debug("info: loading pki information for %s", k);
1093 if (pki->pki_cert_file == NULL((void *)0))
1094 fatalx("load_pki_tree: missing certificate file");
1095 if (pki->pki_key_file == NULL((void *)0))
1096 fatalx("load_pki_tree: missing key file");
1097
1098 if (!ssl_load_certificate(pki, pki->pki_cert_file))
1099 fatalx("load_pki_tree: failed to load certificate file");
1100 }
1101
1102 log_debug("debug: init ca-tree");
1103 iter_dict = NULL((void *)0);
1104 while (dict_iter(env->sc_ca_dict, &iter_dict, &k, (void **)&sca)) {
1105 log_debug("info: loading CA information for %s", k);
1106 if (!ssl_load_cafile(sca, sca->ca_cert_file))
1107 fatalx("load_pki_tree: failed to load CA file");
1108 }
1109}
1110
1111void
1112load_pki_keys(void)
1113{
1114 struct pki *pki;
1115 const char *k;
1116 void *iter_dict;
1117
1118 log_debug("debug: init ssl-tree");
1119 iter_dict = NULL((void *)0);
1120 while (dict_iter(env->sc_pki_dict, &iter_dict, &k, (void **)&pki)) {
1121 log_debug("info: loading pki keys for %s", k);
1122
1123 if (!ssl_load_keyfile(pki, pki->pki_key_file, k))
1124 fatalx("load_pki_keys: failed to load key file");
1125 }
1126}
1127
1128int
1129fork_proc_backend(const char *key, const char *conf, const char *procname)
1130{
1131 pid_t pid;
1132 int sp[2];
1133 char path[PATH_MAX1024];
1134 char name[PATH_MAX1024];
1135 char *arg;
1136
1137 if (strlcpy(name, conf, sizeof(name)) >= sizeof(name)) {
1138 log_warnx("warn: %s-proc: conf too long", key);
1139 return (0);
1140 }
1141
1142 arg = strchr(name, ':');
1143 if (arg)
1144 *arg++ = '\0';
1145
1146 if (snprintf(path, sizeof(path), PATH_LIBEXEC"/usr/local/libexec/smtpd" "/%s-%s", key, name) >=
1147 (ssize_t)sizeof(path)) {
1148 log_warn("warn: %s-proc: exec path too long", key);
1149 return (-1);
1150 }
1151
1152 if (socketpair(AF_UNIX1, SOCK_STREAM1, PF_UNSPEC0, sp) == -1) {
1153 log_warn("warn: %s-proc: socketpair", key);
1154 return (-1);
1155 }
1156
1157 if ((pid = fork()) == -1) {
1158 log_warn("warn: %s-proc: fork", key);
1159 close(sp[0]);
1160 close(sp[1]);
1161 return (-1);
1162 }
1163
1164 if (pid == 0) {
1165 /* child process */
1166 dup2(sp[0], STDIN_FILENO0);
1167 if (closefrom(STDERR_FILENO2 + 1) == -1)
1168 exit(1);
1169
1170 if (procname == NULL((void *)0))
1171 procname = name;
1172
1173 execl(path, procname, arg, (char *)NULL((void *)0));
1174 fatal("execl: %s", path);
1175 }
1176
1177 /* parent process */
1178 close(sp[0]);
1179
1180 return (sp[1]);
1181}
1182
1183struct child *
1184child_add(pid_t pid, int type, const char *title)
1185{
1186 struct child *child;
1187
1188 if ((child = calloc(1, sizeof(*child))) == NULL((void *)0))
1189 fatal("smtpd: child_add: calloc");
1190
1191 child->pid = pid;
1192 child->type = type;
1193 child->title = title;
1194
1195 tree_xset(&children, pid, child);
1196
1197 return (child);
1198}
1199
1200static void
1201purge_task(void)
1202{
1203 struct passwd *pw;
1204 DIR *d;
1205 int n;
1206 uid_t uid;
1207 gid_t gid;
1208
1209 n = 0;
1210 if ((d = opendir(PATH_SPOOL"/var/spool/smtpd" PATH_PURGE"/purge"))) {
1211 while (readdir(d) != NULL((void *)0))
1212 n++;
1213 closedir(d);
1214 } else
1215 log_warn("warn: purge_task: opendir");
1216
1217 if (n > 2) {
1218 switch (purge_pid = fork()) {
1219 case -1:
1220 log_warn("warn: purge_task: fork");
1221 break;
1222 case 0:
1223 if ((pw = getpwnam(SMTPD_QUEUE_USER"_smtpq")) == NULL((void *)0))
1224 fatalx("unknown user " SMTPD_QUEUE_USER"_smtpq");
1225 if (chroot(PATH_SPOOL"/var/spool/smtpd" PATH_PURGE"/purge") == -1)
1226 fatal("smtpd: chroot");
1227 if (chdir("/") == -1)
1228 fatal("smtpd: chdir");
1229 uid = pw->pw_uid;
1230 gid = pw->pw_gid;
1231 if (setgroups(1, &gid) ||
1232 setresgid(gid, gid, gid) ||
1233 setresuid(uid, uid, uid))
1234 fatal("smtpd: cannot drop privileges");
1235 rmtree("/", 1);
1236 _exit(0);
1237 break;
1238 default:
1239 break;
1240 }
1241 }
1242}
1243
1244static void
1245fork_filter_processes(void)
1246{
1247 const char *name;
1248 void *iter;
1249 const char *fn;
1250 struct filter_config *fc;
1251 struct filter_config *fcs;
1252 struct filter_proc *fp;
1253 size_t i;
1254
1255 /* For each filter chain, assign the registered subsystem to subfilters */
1256 iter = NULL((void *)0);
1257 while (dict_iter(env->sc_filters_dict, &iter, (const char **)&fn, (void **)&fc)) {
1258 if (fc->chain) {
1259 for (i = 0; i < fc->chain_size; ++i) {
1260 fcs = dict_xget(env->sc_filters_dict, fc->chain[i]);
1261 fcs->filter_subsystem |= fc->filter_subsystem;
1262 }
1263 }
1264 }
1265
1266 /* For each filter, assign the registered subsystem to underlying proc */
1267 iter = NULL((void *)0);
1268 while (dict_iter(env->sc_filters_dict, &iter, (const char **)&fn, (void **)&fc)) {
1269 if (fc->proc) {
1270 fp = dict_xget(env->sc_filter_processes_dict, fc->proc);
1271 fp->filter_subsystem |= fc->filter_subsystem;
1272 }
1273 }
1274
1275 iter = NULL((void *)0);
1276 while (dict_iter(env->sc_filter_processes_dict, &iter, &name, (void **)&fp))
1277 fork_filter_process(name, fp->command, fp->user, fp->group, fp->chroot, fp->filter_subsystem);
1278}
1279
1280static void
1281fork_filter_process(const char *name, const char *command, const char *user, const char *group, const char *chroot_path, uint32_t subsystems)
1282{
1283 pid_t pid;
1284 struct filter_proc *processor;
1285 char buf;
1286 int sp[2], errfd[2];
1287 struct passwd *pw;
1288 struct group *gr;
1289 char exec[_POSIX_ARG_MAX4096];
1290 int execr;
1291
1292 if (user == NULL((void *)0))
1293 user = SMTPD_USER"_smtpd";
1294 if ((pw = getpwnam(user)) == NULL((void *)0))
1295 fatal("getpwnam");
1296
1297 if (group) {
1298 if ((gr = getgrnam(group)) == NULL((void *)0))
1299 fatal("getgrnam");
1300 }
1301 else {
1302 if ((gr = getgrgid(pw->pw_gid)) == NULL((void *)0))
1303 fatal("getgrgid");
1304 }
1305
1306 if (socketpair(AF_UNIX1, SOCK_STREAM1, PF_UNSPEC0, sp) == -1)
1307 fatal("socketpair");
1308 if (socketpair(AF_UNIX1, SOCK_STREAM1, PF_UNSPEC0, errfd) == -1)
1309 fatal("socketpair");
1310
1311 if ((pid = fork()) == -1)
1312 fatal("fork");
1313
1314 /* parent passes the child fd over to lka */
1315 if (pid > 0) {
1316 processor = dict_xget(env->sc_filter_processes_dict, name);
1317 processor->errfd = errfd[1];
1318 child_add(pid, CHILD_PROCESSOR, name);
1319 close(sp[0]);
1320 close(errfd[0]);
1321 m_create(p_lka, IMSG_LKA_PROCESSOR_FORK, 0, 0, sp[1]);
1322 m_add_string(p_lka, name);
1323 m_add_u32(p_lka, (uint32_t)subsystems);
1324 m_close(p_lka);
1325 return;
1326 }
1327
1328 close(sp[1]);
1329 close(errfd[1]);
1330 dup2(sp[0], STDIN_FILENO0);
1331 dup2(sp[0], STDOUT_FILENO1);
1332 dup2(errfd[0], STDERR_FILENO2);
1333
1334 if (chroot_path) {
1335 if (chroot(chroot_path) != 0 || chdir("/") != 0)
1336 fatal("chroot: %s", chroot_path);
1337 }
1338
1339 if (setgroups(1, &gr->gr_gid) ||
1340 setresgid(gr->gr_gid, gr->gr_gid, gr->gr_gid) ||
1341 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
1342 fatal("fork_filter_process: cannot drop privileges");
1343
1344 if (closefrom(STDERR_FILENO2 + 1) == -1)
1345 fatal("closefrom");
1346 if (setsid() == -1)
1347 fatal("setsid");
1348 if (signal(SIGPIPE13, SIG_DFL(void (*)(int))0) == SIG_ERR(void (*)(int))-1 ||
1349 signal(SIGINT2, SIG_DFL(void (*)(int))0) == SIG_ERR(void (*)(int))-1 ||
1350 signal(SIGTERM15, SIG_DFL(void (*)(int))0) == SIG_ERR(void (*)(int))-1 ||
1351 signal(SIGCHLD20, SIG_DFL(void (*)(int))0) == SIG_ERR(void (*)(int))-1 ||
1352 signal(SIGHUP1, SIG_DFL(void (*)(int))0) == SIG_ERR(void (*)(int))-1)
1353 fatal("signal");
1354
1355 if (command[0] == '/')
1356 execr = snprintf(exec, sizeof(exec), "exec %s", command);
1357 else
1358 execr = snprintf(exec, sizeof(exec), "exec %s/%s",
1359 PATH_LIBEXEC"/usr/local/libexec/smtpd", command);
1360 if (execr >= (int) sizeof(exec))
1361 fatalx("%s: exec path too long", name);
1362
1363 /*
1364 * Wait for lka to acknowledge that it received the fd.
1365 * This prevents a race condition between the filter sending an error
1366 * message, and exiting and lka not being able to log it because of
1367 * SIGCHLD.
1368 * (Ab)use read to determine if the fd is installed; since stderr is
1369 * never going to be read from we can shutdown(2) the write-end in lka.
1370 */
1371 if (read(STDERR_FILENO2, &buf, 1) != 0)
1372 fatalx("lka didn't properly close write end of error socket");
1373 if (system(exec) == -1)
1374 fatal("system");
1375
1376 /* there's no successful exit from a processor */
1377 _exit(1);
1378}
1379
1380static void
1381forkmda(struct mproc *p, uint64_t id, struct deliver *deliver)
1382{
1383 char ebuf[128], sfn[32];
1384 struct dispatcher *dsp;
1385 struct child *child;
1386 pid_t pid;
1387 int allout, pipefd[2];
1388 struct passwd *pw;
1389 const char *pw_name;
1390 uid_t pw_uid;
1391 gid_t pw_gid;
1392 const char *pw_dir;
1393
1394 dsp = dict_xget(env->sc_dispatchers, deliver->dispatcher);
1395 if (dsp->type != DISPATCHER_LOCAL)
1396 fatalx("non-local dispatcher called from forkmda()");
1397
1398 log_debug("debug: smtpd: forking mda for session %016"PRIx64"llx"
1399 ": %s as %s", id, deliver->userinfo.username,
1400 dsp->u.local.user ? dsp->u.local.user : deliver->userinfo.username);
1401
1402 if (dsp->u.local.user) {
1403 if ((pw = getpwnam(dsp->u.local.user)) == NULL((void *)0)) {
1404 (void)snprintf(ebuf, sizeof ebuf,
1405 "delivery user '%s' does not exist",
1406 dsp->u.local.user);
1407 m_create(p_dispatcher, IMSG_MDA_DONE, 0, 0, -1);
1408 m_add_id(p_dispatcher, id);
1409 m_add_int(p_dispatcher, MDA_PERMFAIL);
1410 m_add_int(p_dispatcher, EX_NOUSER67);
1411 m_add_string(p_dispatcher, ebuf);
1412 m_close(p_dispatcher);
1413 return;
1414 }
1415 pw_name = pw->pw_name;
1416 pw_uid = pw->pw_uid;
1417 pw_gid = pw->pw_gid;
1418 pw_dir = pw->pw_dir;
1419 }
1420 else {
1421 pw_name = deliver->userinfo.username;
1422 pw_uid = deliver->userinfo.uid;
1423 pw_gid = deliver->userinfo.gid;
1424 pw_dir = deliver->userinfo.directory;
1425 }
1426
1427 if (pw_uid == 0 && deliver->mda_exec[0]) {
1428 pw_name = deliver->userinfo.username;
1429 pw_uid = deliver->userinfo.uid;
1430 pw_gid = deliver->userinfo.gid;
1431 pw_dir = deliver->userinfo.directory;
1432 }
1433
1434 if (pw_uid == 0 && !dsp->u.local.is_mbox) {
1435 (void)snprintf(ebuf, sizeof ebuf, "not allowed to deliver to: %s",
1436 deliver->userinfo.username);
1437 m_create(p_dispatcher, IMSG_MDA_DONE, 0, 0, -1);
1438 m_add_id(p_dispatcher, id);
1439 m_add_int(p_dispatcher, MDA_PERMFAIL);
1440 m_add_int(p_dispatcher, EX_NOPERM77);
1441 m_add_string(p_dispatcher, ebuf);
1442 m_close(p_dispatcher);
1443 return;
1444 }
1445
1446 if (pipe(pipefd) == -1) {
1447 (void)snprintf(ebuf, sizeof ebuf, "pipe: %s", strerror(errno(*__errno())));
1448 m_create(p_dispatcher, IMSG_MDA_DONE, 0, 0, -1);
1449 m_add_id(p_dispatcher, id);
1450 m_add_int(p_dispatcher, MDA_TEMPFAIL);
1451 m_add_int(p_dispatcher, EX_OSERR71);
1452 m_add_string(p_dispatcher, ebuf);
1453 m_close(p_dispatcher);
1454 return;
1455 }
1456
1457 /* prepare file which captures stdout and stderr */
1458 (void)strlcpy(sfn, "/tmp/smtpd.out.XXXXXXXXXXX", sizeof(sfn));
1459 allout = mkstemp(sfn);
1460 if (allout == -1) {
1461 (void)snprintf(ebuf, sizeof ebuf, "mkstemp: %s", strerror(errno(*__errno())));
1462 m_create(p_dispatcher, IMSG_MDA_DONE, 0, 0, -1);
1463 m_add_id(p_dispatcher, id);
1464 m_add_int(p_dispatcher, MDA_TEMPFAIL);
1465 m_add_int(p_dispatcher, EX_OSERR71);
1466 m_add_string(p_dispatcher, ebuf);
1467 m_close(p_dispatcher);
1468 close(pipefd[0]);
1469 close(pipefd[1]);
1470 return;
1471 }
1472 unlink(sfn);
1473
1474 pid = fork();
1475 if (pid == -1) {
1476 (void)snprintf(ebuf, sizeof ebuf, "fork: %s", strerror(errno(*__errno())));
1477 m_create(p_dispatcher, IMSG_MDA_DONE, 0, 0, -1);
1478 m_add_id(p_dispatcher, id);
1479 m_add_int(p_dispatcher, MDA_TEMPFAIL);
1480 m_add_int(p_dispatcher, EX_OSERR71);
1481 m_add_string(p_dispatcher, ebuf);
1482 m_close(p_dispatcher);
1483 close(pipefd[0]);
1484 close(pipefd[1]);
1485 close(allout);
1486 return;
1487 }
1488
1489 /* parent passes the child fd over to mda */
1490 if (pid > 0) {
1491 child = child_add(pid, CHILD_MDA, NULL((void *)0));
1492 child->mda_out = allout;
1493 child->mda_id = id;
1494 close(pipefd[0]);
1495 m_create(p, IMSG_MDA_FORK, 0, 0, pipefd[1]);
1496 m_add_id(p, id);
1497 m_close(p);
1498 return;
1499 }
1500
1501 /* mbox helper, create mailbox before privdrop if it doesn't exist */
1502 if (dsp->u.local.is_mbox)
1503 mda_mbox_init(deliver);
1504
1505 if (chdir(pw_dir) == -1 && chdir("/") == -1)
1506 fatal("chdir");
1507 if (setgroups(1, &pw_gid) ||
1508 setresgid(pw_gid, pw_gid, pw_gid) ||
1509 setresuid(pw_uid, pw_uid, pw_uid))
1510 fatal("forkmda: cannot drop privileges");
1511 if (dup2(pipefd[0], STDIN_FILENO0) == -1 ||
1512 dup2(allout, STDOUT_FILENO1) == -1 ||
1513 dup2(allout, STDERR_FILENO2) == -1)
1514 fatal("forkmda: dup2");
1515 if (closefrom(STDERR_FILENO2 + 1) == -1)
1516 fatal("closefrom");
1517 if (setsid() == -1)
1518 fatal("setsid");
1519 if (signal(SIGPIPE13, SIG_DFL(void (*)(int))0) == SIG_ERR(void (*)(int))-1 ||
1520 signal(SIGINT2, SIG_DFL(void (*)(int))0) == SIG_ERR(void (*)(int))-1 ||
1521 signal(SIGTERM15, SIG_DFL(void (*)(int))0) == SIG_ERR(void (*)(int))-1 ||
1522 signal(SIGCHLD20, SIG_DFL(void (*)(int))0) == SIG_ERR(void (*)(int))-1 ||
1523 signal(SIGHUP1, SIG_DFL(void (*)(int))0) == SIG_ERR(void (*)(int))-1)
1524 fatal("signal");
1525
1526 /* avoid hangs by setting 5m timeout */
1527 alarm(300);
1528
1529 if (dsp->u.local.is_mbox &&
1530 dsp->u.local.mda_wrapper == NULL((void *)0) &&
1531 deliver->mda_exec[0] == '\0')
1532 mda_mbox(deliver);
1533 else
1534 mda_unpriv(dsp, deliver, pw_name, pw_dir);
1535}
1536
1537static void
1538offline_scan(int fd, short ev, void *arg)
1539{
1540 char *path_argv[2];
1541 FTS *fts = arg;
1542 FTSENT *e;
1543 int n = 0;
1544
1545 path_argv[0] = PATH_SPOOL"/var/spool/smtpd" PATH_OFFLINE"/offline";
1546 path_argv[1] = NULL((void *)0);
1547
1548 if (fts == NULL((void *)0)) {
1549 log_debug("debug: smtpd: scanning offline queue...");
1550 fts = fts_open(path_argv, FTS_PHYSICAL0x0010 | FTS_NOCHDIR0x0004, NULL((void *)0));
1551 if (fts == NULL((void *)0)) {
1552 log_warn("fts_open: %s", path_argv[0]);
1553 return;
1554 }
1555 }
1556
1557 while ((e = fts_read(fts)) != NULL((void *)0)) {
1558 if (e->fts_info != FTS_F8)
1559 continue;
1560
1561 /* offline files must be at depth 1 */
1562 if (e->fts_level != 1)
1563 continue;
1564
1565 /* offline file group must match parent directory group */
1566 if (e->fts_statp->st_gid != e->fts_parent->fts_statp->st_gid)
1567 continue;
1568
1569 if (e->fts_statp->st_size == 0) {
1570 if (unlink(e->fts_accpath) == -1)
1571 log_warnx("warn: smtpd: could not unlink %s", e->fts_accpath);
1572 continue;
1573 }
1574
1575 if (offline_add(e->fts_name, e->fts_statp->st_uid,
1576 e->fts_statp->st_gid)) {
1577 log_warnx("warn: smtpd: "
1578 "could not add offline message %s", e->fts_name);
1579 continue;
1580 }
1581
1582 if ((n++) == OFFLINE_READMAX20) {
1583 evtimer_set(&offline_ev, offline_scan, fts)event_set(&offline_ev, -1, 0, offline_scan, fts);
1584 offline_timeout.tv_sec = 0;
1585 offline_timeout.tv_usec = 100000;
1586 evtimer_add(&offline_ev, &offline_timeout)event_add(&offline_ev, &offline_timeout);
1587 return;
1588 }
1589 }
1590
1591 log_debug("debug: smtpd: offline scanning done");
1592 fts_close(fts);
1593}
1594
1595static int
1596offline_enqueue(char *name, uid_t uid, gid_t gid)
1597{
1598 char *path;
1599 struct stat sb;
1600 pid_t pid;
1601 struct child *child;
1602 struct passwd *pw;
1603 int pathlen;
1604
1605 pathlen = asprintf(&path, "%s/%s", PATH_SPOOL"/var/spool/smtpd" PATH_OFFLINE"/offline", name);
1606 if (pathlen == -1) {
1607 log_warnx("warn: smtpd: asprintf");
1608 return (-1);
1609 }
1610
1611 if (pathlen >= PATH_MAX1024) {
1612 log_warnx("warn: smtpd: pathname exceeds PATH_MAX");
1613 free(path);
1614 return (-1);
1615 }
1616
1617 log_debug("debug: smtpd: enqueueing offline message %s", path);
1618
1619 if ((pid = fork()) == -1) {
1620 log_warn("warn: smtpd: fork");
1621 free(path);
1622 return (-1);
1623 }
1624
1625 if (pid == 0) {
1626 char *envp[2], *p = NULL((void *)0), *tmp;
1627 int fd;
1628 FILE *fp;
1629 size_t sz = 0;
1630 ssize_t len;
1631 arglist args;
1632
1633 if (closefrom(STDERR_FILENO2 + 1) == -1)
1634 _exit(1);
1635
1636 memset(&args, 0, sizeof(args));
1637
1638 if ((fd = open(path, O_RDONLY0x0000|O_NOFOLLOW0x0100|O_NONBLOCK0x0004)) == -1) {
1639 log_warn("warn: smtpd: open: %s", path);
1640 _exit(1);
1641 }
1642
1643 if (fstat(fd, &sb) == -1) {
1644 log_warn("warn: smtpd: fstat: %s", path);
1645 _exit(1);
1646 }
1647
1648 if (!S_ISREG(sb.st_mode)((sb.st_mode & 0170000) == 0100000)) {
1649 log_warnx("warn: smtpd: file %s (uid %d) not regular",
1650 path, sb.st_uid);
1651 _exit(1);
1652 }
1653
1654 if (sb.st_nlink != 1) {
1655 log_warnx("warn: smtpd: file %s is hard-link", path);
1656 _exit(1);
1657 }
1658
1659 if (sb.st_uid != uid) {
1660 log_warnx("warn: smtpd: file %s has bad uid %d",
1661 path, sb.st_uid);
1662 _exit(1);
1663 }
1664
1665 if (sb.st_gid != gid) {
1666 log_warnx("warn: smtpd: file %s has bad gid %d",
1667 path, sb.st_gid);
1668 _exit(1);
1669 }
1670
1671 pw = getpwuid(sb.st_uid);
1672 if (pw == NULL((void *)0)) {
1673 log_warnx("warn: smtpd: getpwuid for uid %d failed",
1674 sb.st_uid);
1675 _exit(1);
1676 }
1677
1678 if (setgroups(1, &pw->pw_gid) ||
1679 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
1680 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
1681 _exit(1);
1682
1683 if ((fp = fdopen(fd, "r")) == NULL((void *)0))
1684 _exit(1);
1685
1686 if (chdir(pw->pw_dir) == -1 && chdir("/") == -1)
1687 _exit(1);
1688
1689 if (setsid() == -1 ||
1690 signal(SIGPIPE13, SIG_DFL(void (*)(int))0) == SIG_ERR(void (*)(int))-1 ||
1691 dup2(fileno(fp)(!__isthreaded ? ((fp)->_file) : (fileno)(fp)), STDIN_FILENO0) == -1)
1692 _exit(1);
1693
1694 if ((len = getline(&p, &sz, fp)) == -1)
1695 _exit(1);
1696
1697 if (p[len - 1] != '\n')
1698 _exit(1);
1699 p[len - 1] = '\0';
1700
1701 addargs(&args, "%s", "sendmail");
1702 addargs(&args, "%s", "-S");
1703
1704 while ((tmp = strsep(&p, "|")) != NULL((void *)0))
1705 addargs(&args, "%s", tmp);
1706
1707 free(p);
1708 if (lseek(fileno(fp)(!__isthreaded ? ((fp)->_file) : (fileno)(fp)), len, SEEK_SET0) == -1)
1709 _exit(1);
1710
1711 envp[0] = "PATH=" _PATH_DEFPATH"/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin";
1712 envp[1] = (char *)NULL((void *)0);
1713 environ = envp;
1714
1715 execvp(PATH_SMTPCTL"/usr/sbin/smtpctl", args.list);
1716 _exit(1);
1717 }
1718
1719 offline_running++;
1720 child = child_add(pid, CHILD_ENQUEUE_OFFLINE, NULL((void *)0));
1721 child->path = path;
1722
1723 return (0);
1724}
1725
1726static int
1727offline_add(char *path, uid_t uid, gid_t gid)
1728{
1729 struct offline *q;
1730
1731 if (offline_running < OFFLINE_QUEUEMAX5)
1732 /* skip queue */
1733 return offline_enqueue(path, uid, gid);
1734
1735 q = malloc(sizeof(*q) + strlen(path) + 1);
1736 if (q == NULL((void *)0))
1737 return (-1);
1738 q->uid = uid;
1739 q->gid = gid;
1740 q->path = (char *)q + sizeof(*q);
1741 memmove(q->path, path, strlen(path) + 1);
1742 TAILQ_INSERT_TAIL(&offline_q, q, entry)do { (q)->entry.tqe_next = ((void *)0); (q)->entry.tqe_prev
= (&offline_q)->tqh_last; *(&offline_q)->tqh_last
= (q); (&offline_q)->tqh_last = &(q)->entry.tqe_next
; } while (0)
;
1743
1744 return (0);
1745}
1746
1747static void
1748offline_done(void)
1749{
1750 struct offline *q;
1751
1752 offline_running--;
1753
1754 while (offline_running < OFFLINE_QUEUEMAX5) {
1755 if ((q = TAILQ_FIRST(&offline_q)((&offline_q)->tqh_first)) == NULL((void *)0))
1756 break; /* all done */
1757 TAILQ_REMOVE(&offline_q, q, entry)do { if (((q)->entry.tqe_next) != ((void *)0)) (q)->entry
.tqe_next->entry.tqe_prev = (q)->entry.tqe_prev; else (
&offline_q)->tqh_last = (q)->entry.tqe_prev; *(q)->
entry.tqe_prev = (q)->entry.tqe_next; ; ; } while (0)
;
1758 offline_enqueue(q->path, q->uid, q->gid);
1759 free(q);
1760 }
1761}
1762
1763static int
1764parent_forward_open(char *username, char *directory, uid_t uid, gid_t gid)
1765{
1766 char pathname[PATH_MAX1024];
1767 int fd;
1768 struct stat sb;
1769
1770 if (!bsnprintf(pathname, sizeof (pathname), "%s/.forward",
1771 directory)) {
1772 log_warnx("warn: smtpd: %s: pathname too large", pathname);
1773 return -1;
1774 }
1775
1776 if (stat(directory, &sb) == -1) {
1777 log_warn("warn: smtpd: parent_forward_open: %s", directory);
1778 return -1;
1779 }
1780 if (sb.st_mode & S_ISVTX0001000) {
1781 log_warnx("warn: smtpd: parent_forward_open: %s is sticky",
1782 directory);
1783 errno(*__errno()) = EAGAIN35;
1784 return -1;
1785 }
1786
1787 do {
1788 fd = open(pathname, O_RDONLY0x0000|O_NOFOLLOW0x0100|O_NONBLOCK0x0004);
1789 } while (fd == -1 && errno(*__errno()) == EINTR4);
1790 if (fd == -1) {
1791 if (errno(*__errno()) == ENOENT2)
1792 return -1;
1793 if (errno(*__errno()) == EMFILE24 || errno(*__errno()) == ENFILE23 || errno(*__errno()) == EIO5) {
1794 errno(*__errno()) = EAGAIN35;
1795 return -1;
1796 }
1797 if (errno(*__errno()) == ELOOP62)
1798 log_warnx("warn: smtpd: parent_forward_open: %s: "
1799 "cannot follow symbolic links", pathname);
1800 else
1801 log_warn("warn: smtpd: parent_forward_open: %s", pathname);
1802 return -1;
1803 }
1804
1805 if (!secure_file(fd, pathname, directory, uid, 1)) {
1806 log_warnx("warn: smtpd: %s: unsecure file", pathname);
1807 close(fd);
1808 return -1;
1809 }
1810
1811 return fd;
1812}
1813
1814void
1815imsg_dispatch(struct mproc *p, struct imsg *imsg)
1816{
1817 struct timespec t0, t1, dt;
1818 int msg;
1819
1820 if (imsg == NULL((void *)0)) {
1
Assuming 'imsg' is not equal to NULL
2
Taking false branch
1821 imsg_callback(p, imsg);
1822 return;
1823 }
1824
1825 log_imsg(smtpd_process, p->proc, imsg);
1826
1827 if (profiling & PROFILE_IMSG0x0002)
3
Assuming the condition is false
4
Taking false branch
1828 clock_gettime(CLOCK_MONOTONIC3, &t0);
1829
1830 msg = imsg->hdr.type;
1831 imsg_callback(p, imsg);
1832
1833 if (profiling & PROFILE_IMSG0x0002) {
5
Assuming the condition is true
6
Taking true branch
1834 clock_gettime(CLOCK_MONOTONIC3, &t1);
1835 timespecsub(&t1, &t0, &dt)do { (&dt)->tv_sec = (&t1)->tv_sec - (&t0)->
tv_sec; (&dt)->tv_nsec = (&t1)->tv_nsec - (&
t0)->tv_nsec; if ((&dt)->tv_nsec < 0) { (&dt
)->tv_sec--; (&dt)->tv_nsec += 1000000000L; } } while
(0)
;
7
The right operand of '-' is a garbage value
1836
1837 log_debug("profile-imsg: %s %s %s %d %lld.%09ld",
1838 proc_name(smtpd_process),
1839 proc_name(p->proc),
1840 imsg_to_str(msg),
1841 (int)imsg->hdr.len,
1842 (long long)dt.tv_sec,
1843 dt.tv_nsec);
1844
1845 if (profiling & PROFILE_TOSTAT0x0001) {
1846 char key[STAT_KEY_SIZE1024];
1847 /* can't profstat control process yet */
1848 if (smtpd_process == PROC_CONTROL)
1849 return;
1850
1851 if (!bsnprintf(key, sizeof key,
1852 "profiling.imsg.%s.%s.%s",
1853 proc_name(smtpd_process),
1854 proc_name(p->proc),
1855 imsg_to_str(msg)))
1856 return;
1857 stat_set(key, stat_timespec(&dt));
1858 }
1859 }
1860}
1861
1862void
1863log_imsg(int to, int from, struct imsg *imsg)
1864{
1865
1866 if (to == PROC_CONTROL && imsg->hdr.type == IMSG_STAT_SET)
1867 return;
1868
1869 if (imsg->fd != -1)
1870 log_trace(TRACE_IMSG, "imsg: %s <- %s: %s (len=%zu, fd=%d)",do { if (tracing & (0x0002)) log_trace0("imsg: %s <- %s: %s (len=%zu, fd=%d)"
, proc_name(to), proc_name(from), imsg_to_str(imsg->hdr.type
), imsg->hdr.len - sizeof(struct imsg_hdr), imsg->fd); }
while (0)
1871 proc_name(to),do { if (tracing & (0x0002)) log_trace0("imsg: %s <- %s: %s (len=%zu, fd=%d)"
, proc_name(to), proc_name(from), imsg_to_str(imsg->hdr.type
), imsg->hdr.len - sizeof(struct imsg_hdr), imsg->fd); }
while (0)
1872 proc_name(from),do { if (tracing & (0x0002)) log_trace0("imsg: %s <- %s: %s (len=%zu, fd=%d)"
, proc_name(to), proc_name(from), imsg_to_str(imsg->hdr.type
), imsg->hdr.len - sizeof(struct imsg_hdr), imsg->fd); }
while (0)
1873 imsg_to_str(imsg->hdr.type),do { if (tracing & (0x0002)) log_trace0("imsg: %s <- %s: %s (len=%zu, fd=%d)"
, proc_name(to), proc_name(from), imsg_to_str(imsg->hdr.type
), imsg->hdr.len - sizeof(struct imsg_hdr), imsg->fd); }
while (0)
1874 imsg->hdr.len - IMSG_HEADER_SIZE,do { if (tracing & (0x0002)) log_trace0("imsg: %s <- %s: %s (len=%zu, fd=%d)"
, proc_name(to), proc_name(from), imsg_to_str(imsg->hdr.type
), imsg->hdr.len - sizeof(struct imsg_hdr), imsg->fd); }
while (0)
1875 imsg->fd)do { if (tracing & (0x0002)) log_trace0("imsg: %s <- %s: %s (len=%zu, fd=%d)"
, proc_name(to), proc_name(from), imsg_to_str(imsg->hdr.type
), imsg->hdr.len - sizeof(struct imsg_hdr), imsg->fd); }
while (0)
;
1876 else
1877 log_trace(TRACE_IMSG, "imsg: %s <- %s: %s (len=%zu)",do { if (tracing & (0x0002)) log_trace0("imsg: %s <- %s: %s (len=%zu)"
, proc_name(to), proc_name(from), imsg_to_str(imsg->hdr.type
), imsg->hdr.len - sizeof(struct imsg_hdr)); } while (0)
1878 proc_name(to),do { if (tracing & (0x0002)) log_trace0("imsg: %s <- %s: %s (len=%zu)"
, proc_name(to), proc_name(from), imsg_to_str(imsg->hdr.type
), imsg->hdr.len - sizeof(struct imsg_hdr)); } while (0)
1879 proc_name(from),do { if (tracing & (0x0002)) log_trace0("imsg: %s <- %s: %s (len=%zu)"
, proc_name(to), proc_name(from), imsg_to_str(imsg->hdr.type
), imsg->hdr.len - sizeof(struct imsg_hdr)); } while (0)
1880 imsg_to_str(imsg->hdr.type),do { if (tracing & (0x0002)) log_trace0("imsg: %s <- %s: %s (len=%zu)"
, proc_name(to), proc_name(from), imsg_to_str(imsg->hdr.type
), imsg->hdr.len - sizeof(struct imsg_hdr)); } while (0)
1881 imsg->hdr.len - IMSG_HEADER_SIZE)do { if (tracing & (0x0002)) log_trace0("imsg: %s <- %s: %s (len=%zu)"
, proc_name(to), proc_name(from), imsg_to_str(imsg->hdr.type
), imsg->hdr.len - sizeof(struct imsg_hdr)); } while (0)
;
1882}
1883
1884const char *
1885proc_title(enum smtp_proc_type proc)
1886{
1887 switch (proc) {
1888 case PROC_PARENT:
1889 return "[priv]";
1890 case PROC_LKA:
1891 return "lookup";
1892 case PROC_QUEUE:
1893 return "queue";
1894 case PROC_CONTROL:
1895 return "control";
1896 case PROC_SCHEDULER:
1897 return "scheduler";
1898 case PROC_DISPATCHER:
1899 return "dispatcher";
1900 case PROC_CA:
1901 return "crypto";
1902 case PROC_CLIENT:
1903 return "client";
1904 case PROC_PROCESSOR:
1905 return "processor";
1906 }
1907 return "unknown";
1908}
1909
1910const char *
1911proc_name(enum smtp_proc_type proc)
1912{
1913 switch (proc) {
1914 case PROC_PARENT:
1915 return "parent";
1916 case PROC_LKA:
1917 return "lka";
1918 case PROC_QUEUE:
1919 return "queue";
1920 case PROC_CONTROL:
1921 return "control";
1922 case PROC_SCHEDULER:
1923 return "scheduler";
1924 case PROC_DISPATCHER:
1925 return "dispatcher";
1926 case PROC_CA:
1927 return "ca";
1928 case PROC_CLIENT:
1929 return "client-proc";
1930 default:
1931 return "unknown";
1932 }
1933}
1934
1935#define CASE(x)case x : return "x" case x : return #x
1936
1937const char *
1938imsg_to_str(int type)
1939{
1940 static char buf[32];
1941
1942 switch (type) {
1943 CASE(IMSG_NONE)case IMSG_NONE : return "IMSG_NONE";
1944
1945 CASE(IMSG_CTL_OK)case IMSG_CTL_OK : return "IMSG_CTL_OK";
1946 CASE(IMSG_CTL_FAIL)case IMSG_CTL_FAIL : return "IMSG_CTL_FAIL";
1947
1948 CASE(IMSG_CTL_GET_DIGEST)case IMSG_CTL_GET_DIGEST : return "IMSG_CTL_GET_DIGEST";
1949 CASE(IMSG_CTL_GET_STATS)case IMSG_CTL_GET_STATS : return "IMSG_CTL_GET_STATS";
1950 CASE(IMSG_CTL_LIST_MESSAGES)case IMSG_CTL_LIST_MESSAGES : return "IMSG_CTL_LIST_MESSAGES";
1951 CASE(IMSG_CTL_LIST_ENVELOPES)case IMSG_CTL_LIST_ENVELOPES : return "IMSG_CTL_LIST_ENVELOPES";
1952 CASE(IMSG_CTL_MTA_SHOW_HOSTS)case IMSG_CTL_MTA_SHOW_HOSTS : return "IMSG_CTL_MTA_SHOW_HOSTS";
1953 CASE(IMSG_CTL_MTA_SHOW_RELAYS)case IMSG_CTL_MTA_SHOW_RELAYS : return "IMSG_CTL_MTA_SHOW_RELAYS";
1954 CASE(IMSG_CTL_MTA_SHOW_ROUTES)case IMSG_CTL_MTA_SHOW_ROUTES : return "IMSG_CTL_MTA_SHOW_ROUTES";
1955 CASE(IMSG_CTL_MTA_SHOW_HOSTSTATS)case IMSG_CTL_MTA_SHOW_HOSTSTATS : return "IMSG_CTL_MTA_SHOW_HOSTSTATS";
1956 CASE(IMSG_CTL_MTA_BLOCK)case IMSG_CTL_MTA_BLOCK : return "IMSG_CTL_MTA_BLOCK";
1957 CASE(IMSG_CTL_MTA_UNBLOCK)case IMSG_CTL_MTA_UNBLOCK : return "IMSG_CTL_MTA_UNBLOCK";
1958 CASE(IMSG_CTL_MTA_SHOW_BLOCK)case IMSG_CTL_MTA_SHOW_BLOCK : return "IMSG_CTL_MTA_SHOW_BLOCK";
1959 CASE(IMSG_CTL_PAUSE_EVP)case IMSG_CTL_PAUSE_EVP : return "IMSG_CTL_PAUSE_EVP";
1960 CASE(IMSG_CTL_PAUSE_MDA)case IMSG_CTL_PAUSE_MDA : return "IMSG_CTL_PAUSE_MDA";
1961 CASE(IMSG_CTL_PAUSE_MTA)case IMSG_CTL_PAUSE_MTA : return "IMSG_CTL_PAUSE_MTA";
1962 CASE(IMSG_CTL_PAUSE_SMTP)case IMSG_CTL_PAUSE_SMTP : return "IMSG_CTL_PAUSE_SMTP";
1963 CASE(IMSG_CTL_PROFILE)case IMSG_CTL_PROFILE : return "IMSG_CTL_PROFILE";
1964 CASE(IMSG_CTL_PROFILE_DISABLE)case IMSG_CTL_PROFILE_DISABLE : return "IMSG_CTL_PROFILE_DISABLE";
1965 CASE(IMSG_CTL_PROFILE_ENABLE)case IMSG_CTL_PROFILE_ENABLE : return "IMSG_CTL_PROFILE_ENABLE";
1966 CASE(IMSG_CTL_RESUME_EVP)case IMSG_CTL_RESUME_EVP : return "IMSG_CTL_RESUME_EVP";
1967 CASE(IMSG_CTL_RESUME_MDA)case IMSG_CTL_RESUME_MDA : return "IMSG_CTL_RESUME_MDA";
1968 CASE(IMSG_CTL_RESUME_MTA)case IMSG_CTL_RESUME_MTA : return "IMSG_CTL_RESUME_MTA";
1969 CASE(IMSG_CTL_RESUME_SMTP)case IMSG_CTL_RESUME_SMTP : return "IMSG_CTL_RESUME_SMTP";
1970 CASE(IMSG_CTL_RESUME_ROUTE)case IMSG_CTL_RESUME_ROUTE : return "IMSG_CTL_RESUME_ROUTE";
1971 CASE(IMSG_CTL_REMOVE)case IMSG_CTL_REMOVE : return "IMSG_CTL_REMOVE";
1972 CASE(IMSG_CTL_SCHEDULE)case IMSG_CTL_SCHEDULE : return "IMSG_CTL_SCHEDULE";
1973 CASE(IMSG_CTL_SHOW_STATUS)case IMSG_CTL_SHOW_STATUS : return "IMSG_CTL_SHOW_STATUS";
1974 CASE(IMSG_CTL_TRACE_DISABLE)case IMSG_CTL_TRACE_DISABLE : return "IMSG_CTL_TRACE_DISABLE";
1975 CASE(IMSG_CTL_TRACE_ENABLE)case IMSG_CTL_TRACE_ENABLE : return "IMSG_CTL_TRACE_ENABLE";
1976 CASE(IMSG_CTL_UPDATE_TABLE)case IMSG_CTL_UPDATE_TABLE : return "IMSG_CTL_UPDATE_TABLE";
1977 CASE(IMSG_CTL_VERBOSE)case IMSG_CTL_VERBOSE : return "IMSG_CTL_VERBOSE";
1978 CASE(IMSG_CTL_DISCOVER_EVPID)case IMSG_CTL_DISCOVER_EVPID : return "IMSG_CTL_DISCOVER_EVPID";
1979 CASE(IMSG_CTL_DISCOVER_MSGID)case IMSG_CTL_DISCOVER_MSGID : return "IMSG_CTL_DISCOVER_MSGID";
1980
1981 CASE(IMSG_CTL_SMTP_SESSION)case IMSG_CTL_SMTP_SESSION : return "IMSG_CTL_SMTP_SESSION";
1982
1983 CASE(IMSG_GETADDRINFO)case IMSG_GETADDRINFO : return "IMSG_GETADDRINFO";
1984 CASE(IMSG_GETADDRINFO_END)case IMSG_GETADDRINFO_END : return "IMSG_GETADDRINFO_END";
1985 CASE(IMSG_GETNAMEINFO)case IMSG_GETNAMEINFO : return "IMSG_GETNAMEINFO";
1986 CASE(IMSG_RES_QUERY)case IMSG_RES_QUERY : return "IMSG_RES_QUERY";
1987
1988 CASE(IMSG_SETUP_KEY)case IMSG_SETUP_KEY : return "IMSG_SETUP_KEY";
1989 CASE(IMSG_SETUP_PEER)case IMSG_SETUP_PEER : return "IMSG_SETUP_PEER";
1990 CASE(IMSG_SETUP_DONE)case IMSG_SETUP_DONE : return "IMSG_SETUP_DONE";
1991
1992 CASE(IMSG_CONF_START)case IMSG_CONF_START : return "IMSG_CONF_START";
1993 CASE(IMSG_CONF_END)case IMSG_CONF_END : return "IMSG_CONF_END";
1994
1995 CASE(IMSG_STAT_INCREMENT)case IMSG_STAT_INCREMENT : return "IMSG_STAT_INCREMENT";
1996 CASE(IMSG_STAT_DECREMENT)case IMSG_STAT_DECREMENT : return "IMSG_STAT_DECREMENT";
1997 CASE(IMSG_STAT_SET)case IMSG_STAT_SET : return "IMSG_STAT_SET";
1998
1999 CASE(IMSG_LKA_AUTHENTICATE)case IMSG_LKA_AUTHENTICATE : return "IMSG_LKA_AUTHENTICATE";
2000 CASE(IMSG_LKA_OPEN_FORWARD)case IMSG_LKA_OPEN_FORWARD : return "IMSG_LKA_OPEN_FORWARD";
2001 CASE(IMSG_LKA_ENVELOPE_SUBMIT)case IMSG_LKA_ENVELOPE_SUBMIT : return "IMSG_LKA_ENVELOPE_SUBMIT";
2002 CASE(IMSG_LKA_ENVELOPE_COMMIT)case IMSG_LKA_ENVELOPE_COMMIT : return "IMSG_LKA_ENVELOPE_COMMIT";
2003
2004 CASE(IMSG_QUEUE_DELIVER)case IMSG_QUEUE_DELIVER : return "IMSG_QUEUE_DELIVER";
2005 CASE(IMSG_QUEUE_DELIVERY_OK)case IMSG_QUEUE_DELIVERY_OK : return "IMSG_QUEUE_DELIVERY_OK";
2006 CASE(IMSG_QUEUE_DELIVERY_TEMPFAIL)case IMSG_QUEUE_DELIVERY_TEMPFAIL : return "IMSG_QUEUE_DELIVERY_TEMPFAIL";
2007 CASE(IMSG_QUEUE_DELIVERY_PERMFAIL)case IMSG_QUEUE_DELIVERY_PERMFAIL : return "IMSG_QUEUE_DELIVERY_PERMFAIL";
2008 CASE(IMSG_QUEUE_DELIVERY_LOOP)case IMSG_QUEUE_DELIVERY_LOOP : return "IMSG_QUEUE_DELIVERY_LOOP";
2009 CASE(IMSG_QUEUE_DISCOVER_EVPID)case IMSG_QUEUE_DISCOVER_EVPID : return "IMSG_QUEUE_DISCOVER_EVPID";
2010 CASE(IMSG_QUEUE_DISCOVER_MSGID)case IMSG_QUEUE_DISCOVER_MSGID : return "IMSG_QUEUE_DISCOVER_MSGID";
2011 CASE(IMSG_QUEUE_ENVELOPE_ACK)case IMSG_QUEUE_ENVELOPE_ACK : return "IMSG_QUEUE_ENVELOPE_ACK";
2012 CASE(IMSG_QUEUE_ENVELOPE_COMMIT)case IMSG_QUEUE_ENVELOPE_COMMIT : return "IMSG_QUEUE_ENVELOPE_COMMIT";
2013 CASE(IMSG_QUEUE_ENVELOPE_REMOVE)case IMSG_QUEUE_ENVELOPE_REMOVE : return "IMSG_QUEUE_ENVELOPE_REMOVE";
2014 CASE(IMSG_QUEUE_ENVELOPE_SCHEDULE)case IMSG_QUEUE_ENVELOPE_SCHEDULE : return "IMSG_QUEUE_ENVELOPE_SCHEDULE";
2015 CASE(IMSG_QUEUE_ENVELOPE_SUBMIT)case IMSG_QUEUE_ENVELOPE_SUBMIT : return "IMSG_QUEUE_ENVELOPE_SUBMIT";
2016 CASE(IMSG_QUEUE_HOLDQ_HOLD)case IMSG_QUEUE_HOLDQ_HOLD : return "IMSG_QUEUE_HOLDQ_HOLD";
2017 CASE(IMSG_QUEUE_HOLDQ_RELEASE)case IMSG_QUEUE_HOLDQ_RELEASE : return "IMSG_QUEUE_HOLDQ_RELEASE";
2018 CASE(IMSG_QUEUE_MESSAGE_COMMIT)case IMSG_QUEUE_MESSAGE_COMMIT : return "IMSG_QUEUE_MESSAGE_COMMIT";
2019 CASE(IMSG_QUEUE_MESSAGE_ROLLBACK)case IMSG_QUEUE_MESSAGE_ROLLBACK : return "IMSG_QUEUE_MESSAGE_ROLLBACK";
2020 CASE(IMSG_QUEUE_SMTP_SESSION)case IMSG_QUEUE_SMTP_SESSION : return "IMSG_QUEUE_SMTP_SESSION";
2021 CASE(IMSG_QUEUE_TRANSFER)case IMSG_QUEUE_TRANSFER : return "IMSG_QUEUE_TRANSFER";
2022
2023 CASE(IMSG_MDA_DELIVERY_OK)case IMSG_MDA_DELIVERY_OK : return "IMSG_MDA_DELIVERY_OK";
2024 CASE(IMSG_MDA_DELIVERY_TEMPFAIL)case IMSG_MDA_DELIVERY_TEMPFAIL : return "IMSG_MDA_DELIVERY_TEMPFAIL";
2025 CASE(IMSG_MDA_DELIVERY_PERMFAIL)case IMSG_MDA_DELIVERY_PERMFAIL : return "IMSG_MDA_DELIVERY_PERMFAIL";
2026 CASE(IMSG_MDA_DELIVERY_LOOP)case IMSG_MDA_DELIVERY_LOOP : return "IMSG_MDA_DELIVERY_LOOP";
2027 CASE(IMSG_MDA_DELIVERY_HOLD)case IMSG_MDA_DELIVERY_HOLD : return "IMSG_MDA_DELIVERY_HOLD";
2028 CASE(IMSG_MDA_DONE)case IMSG_MDA_DONE : return "IMSG_MDA_DONE";
2029 CASE(IMSG_MDA_FORK)case IMSG_MDA_FORK : return "IMSG_MDA_FORK";
2030 CASE(IMSG_MDA_HOLDQ_RELEASE)case IMSG_MDA_HOLDQ_RELEASE : return "IMSG_MDA_HOLDQ_RELEASE";
2031 CASE(IMSG_MDA_LOOKUP_USERINFO)case IMSG_MDA_LOOKUP_USERINFO : return "IMSG_MDA_LOOKUP_USERINFO";
2032 CASE(IMSG_MDA_KILL)case IMSG_MDA_KILL : return "IMSG_MDA_KILL";
2033 CASE(IMSG_MDA_OPEN_MESSAGE)case IMSG_MDA_OPEN_MESSAGE : return "IMSG_MDA_OPEN_MESSAGE";
2034
2035 CASE(IMSG_MTA_DELIVERY_OK)case IMSG_MTA_DELIVERY_OK : return "IMSG_MTA_DELIVERY_OK";
2036 CASE(IMSG_MTA_DELIVERY_TEMPFAIL)case IMSG_MTA_DELIVERY_TEMPFAIL : return "IMSG_MTA_DELIVERY_TEMPFAIL";
2037 CASE(IMSG_MTA_DELIVERY_PERMFAIL)case IMSG_MTA_DELIVERY_PERMFAIL : return "IMSG_MTA_DELIVERY_PERMFAIL";
2038 CASE(IMSG_MTA_DELIVERY_LOOP)case IMSG_MTA_DELIVERY_LOOP : return "IMSG_MTA_DELIVERY_LOOP";
2039 CASE(IMSG_MTA_DELIVERY_HOLD)case IMSG_MTA_DELIVERY_HOLD : return "IMSG_MTA_DELIVERY_HOLD";
2040 CASE(IMSG_MTA_DNS_HOST)case IMSG_MTA_DNS_HOST : return "IMSG_MTA_DNS_HOST";
2041 CASE(IMSG_MTA_DNS_HOST_END)case IMSG_MTA_DNS_HOST_END : return "IMSG_MTA_DNS_HOST_END";
2042 CASE(IMSG_MTA_DNS_MX)case IMSG_MTA_DNS_MX : return "IMSG_MTA_DNS_MX";
2043 CASE(IMSG_MTA_DNS_MX_PREFERENCE)case IMSG_MTA_DNS_MX_PREFERENCE : return "IMSG_MTA_DNS_MX_PREFERENCE";
2044 CASE(IMSG_MTA_HOLDQ_RELEASE)case IMSG_MTA_HOLDQ_RELEASE : return "IMSG_MTA_HOLDQ_RELEASE";
2045 CASE(IMSG_MTA_LOOKUP_CREDENTIALS)case IMSG_MTA_LOOKUP_CREDENTIALS : return "IMSG_MTA_LOOKUP_CREDENTIALS";
2046 CASE(IMSG_MTA_LOOKUP_SOURCE)case IMSG_MTA_LOOKUP_SOURCE : return "IMSG_MTA_LOOKUP_SOURCE";
2047 CASE(IMSG_MTA_LOOKUP_HELO)case IMSG_MTA_LOOKUP_HELO : return "IMSG_MTA_LOOKUP_HELO";
2048 CASE(IMSG_MTA_LOOKUP_SMARTHOST)case IMSG_MTA_LOOKUP_SMARTHOST : return "IMSG_MTA_LOOKUP_SMARTHOST";
2049 CASE(IMSG_MTA_OPEN_MESSAGE)case IMSG_MTA_OPEN_MESSAGE : return "IMSG_MTA_OPEN_MESSAGE";
2050 CASE(IMSG_MTA_SCHEDULE)case IMSG_MTA_SCHEDULE : return "IMSG_MTA_SCHEDULE";
2051
2052 CASE(IMSG_SCHED_ENVELOPE_BOUNCE)case IMSG_SCHED_ENVELOPE_BOUNCE : return "IMSG_SCHED_ENVELOPE_BOUNCE";
2053 CASE(IMSG_SCHED_ENVELOPE_DELIVER)case IMSG_SCHED_ENVELOPE_DELIVER : return "IMSG_SCHED_ENVELOPE_DELIVER";
2054 CASE(IMSG_SCHED_ENVELOPE_EXPIRE)case IMSG_SCHED_ENVELOPE_EXPIRE : return "IMSG_SCHED_ENVELOPE_EXPIRE";
2055 CASE(IMSG_SCHED_ENVELOPE_INJECT)case IMSG_SCHED_ENVELOPE_INJECT : return "IMSG_SCHED_ENVELOPE_INJECT";
2056 CASE(IMSG_SCHED_ENVELOPE_REMOVE)case IMSG_SCHED_ENVELOPE_REMOVE : return "IMSG_SCHED_ENVELOPE_REMOVE";
2057 CASE(IMSG_SCHED_ENVELOPE_TRANSFER)case IMSG_SCHED_ENVELOPE_TRANSFER : return "IMSG_SCHED_ENVELOPE_TRANSFER";
2058
2059 CASE(IMSG_SMTP_AUTHENTICATE)case IMSG_SMTP_AUTHENTICATE : return "IMSG_SMTP_AUTHENTICATE";
2060 CASE(IMSG_SMTP_MESSAGE_COMMIT)case IMSG_SMTP_MESSAGE_COMMIT : return "IMSG_SMTP_MESSAGE_COMMIT";
2061 CASE(IMSG_SMTP_MESSAGE_CREATE)case IMSG_SMTP_MESSAGE_CREATE : return "IMSG_SMTP_MESSAGE_CREATE";
2062 CASE(IMSG_SMTP_MESSAGE_ROLLBACK)case IMSG_SMTP_MESSAGE_ROLLBACK : return "IMSG_SMTP_MESSAGE_ROLLBACK";
2063 CASE(IMSG_SMTP_MESSAGE_OPEN)case IMSG_SMTP_MESSAGE_OPEN : return "IMSG_SMTP_MESSAGE_OPEN";
2064 CASE(IMSG_SMTP_CHECK_SENDER)case IMSG_SMTP_CHECK_SENDER : return "IMSG_SMTP_CHECK_SENDER";
2065 CASE(IMSG_SMTP_EXPAND_RCPT)case IMSG_SMTP_EXPAND_RCPT : return "IMSG_SMTP_EXPAND_RCPT";
2066 CASE(IMSG_SMTP_LOOKUP_HELO)case IMSG_SMTP_LOOKUP_HELO : return "IMSG_SMTP_LOOKUP_HELO";
2067
2068 CASE(IMSG_SMTP_REQ_CONNECT)case IMSG_SMTP_REQ_CONNECT : return "IMSG_SMTP_REQ_CONNECT";
2069 CASE(IMSG_SMTP_REQ_HELO)case IMSG_SMTP_REQ_HELO : return "IMSG_SMTP_REQ_HELO";
2070 CASE(IMSG_SMTP_REQ_MAIL)case IMSG_SMTP_REQ_MAIL : return "IMSG_SMTP_REQ_MAIL";
2071 CASE(IMSG_SMTP_REQ_RCPT)case IMSG_SMTP_REQ_RCPT : return "IMSG_SMTP_REQ_RCPT";
2072 CASE(IMSG_SMTP_REQ_DATA)case IMSG_SMTP_REQ_DATA : return "IMSG_SMTP_REQ_DATA";
2073 CASE(IMSG_SMTP_REQ_EOM)case IMSG_SMTP_REQ_EOM : return "IMSG_SMTP_REQ_EOM";
2074 CASE(IMSG_SMTP_EVENT_RSET)case IMSG_SMTP_EVENT_RSET : return "IMSG_SMTP_EVENT_RSET";
2075 CASE(IMSG_SMTP_EVENT_COMMIT)case IMSG_SMTP_EVENT_COMMIT : return "IMSG_SMTP_EVENT_COMMIT";
2076 CASE(IMSG_SMTP_EVENT_ROLLBACK)case IMSG_SMTP_EVENT_ROLLBACK : return "IMSG_SMTP_EVENT_ROLLBACK";
2077 CASE(IMSG_SMTP_EVENT_DISCONNECT)case IMSG_SMTP_EVENT_DISCONNECT : return "IMSG_SMTP_EVENT_DISCONNECT";
2078
2079 CASE(IMSG_LKA_PROCESSOR_FORK)case IMSG_LKA_PROCESSOR_FORK : return "IMSG_LKA_PROCESSOR_FORK";
2080 CASE(IMSG_LKA_PROCESSOR_ERRFD)case IMSG_LKA_PROCESSOR_ERRFD : return "IMSG_LKA_PROCESSOR_ERRFD";
2081
2082 CASE(IMSG_REPORT_SMTP_LINK_CONNECT)case IMSG_REPORT_SMTP_LINK_CONNECT : return "IMSG_REPORT_SMTP_LINK_CONNECT";
2083 CASE(IMSG_REPORT_SMTP_LINK_DISCONNECT)case IMSG_REPORT_SMTP_LINK_DISCONNECT : return "IMSG_REPORT_SMTP_LINK_DISCONNECT";
2084 CASE(IMSG_REPORT_SMTP_LINK_GREETING)case IMSG_REPORT_SMTP_LINK_GREETING : return "IMSG_REPORT_SMTP_LINK_GREETING";
2085 CASE(IMSG_REPORT_SMTP_LINK_IDENTIFY)case IMSG_REPORT_SMTP_LINK_IDENTIFY : return "IMSG_REPORT_SMTP_LINK_IDENTIFY";
2086 CASE(IMSG_REPORT_SMTP_LINK_TLS)case IMSG_REPORT_SMTP_LINK_TLS : return "IMSG_REPORT_SMTP_LINK_TLS";
2087 CASE(IMSG_REPORT_SMTP_LINK_AUTH)case IMSG_REPORT_SMTP_LINK_AUTH : return "IMSG_REPORT_SMTP_LINK_AUTH";
2088 CASE(IMSG_REPORT_SMTP_TX_RESET)case IMSG_REPORT_SMTP_TX_RESET : return "IMSG_REPORT_SMTP_TX_RESET";
2089 CASE(IMSG_REPORT_SMTP_TX_BEGIN)case IMSG_REPORT_SMTP_TX_BEGIN : return "IMSG_REPORT_SMTP_TX_BEGIN";
2090 CASE(IMSG_REPORT_SMTP_TX_MAIL)case IMSG_REPORT_SMTP_TX_MAIL : return "IMSG_REPORT_SMTP_TX_MAIL";
2091 CASE(IMSG_REPORT_SMTP_TX_RCPT)case IMSG_REPORT_SMTP_TX_RCPT : return "IMSG_REPORT_SMTP_TX_RCPT";
2092 CASE(IMSG_REPORT_SMTP_TX_ENVELOPE)case IMSG_REPORT_SMTP_TX_ENVELOPE : return "IMSG_REPORT_SMTP_TX_ENVELOPE";
2093 CASE(IMSG_REPORT_SMTP_TX_DATA)case IMSG_REPORT_SMTP_TX_DATA : return "IMSG_REPORT_SMTP_TX_DATA";
2094 CASE(IMSG_REPORT_SMTP_TX_COMMIT)case IMSG_REPORT_SMTP_TX_COMMIT : return "IMSG_REPORT_SMTP_TX_COMMIT";
2095 CASE(IMSG_REPORT_SMTP_TX_ROLLBACK)case IMSG_REPORT_SMTP_TX_ROLLBACK : return "IMSG_REPORT_SMTP_TX_ROLLBACK";
2096 CASE(IMSG_REPORT_SMTP_PROTOCOL_CLIENT)case IMSG_REPORT_SMTP_PROTOCOL_CLIENT : return "IMSG_REPORT_SMTP_PROTOCOL_CLIENT";
2097 CASE(IMSG_REPORT_SMTP_PROTOCOL_SERVER)case IMSG_REPORT_SMTP_PROTOCOL_SERVER : return "IMSG_REPORT_SMTP_PROTOCOL_SERVER";
2098 CASE(IMSG_REPORT_SMTP_FILTER_RESPONSE)case IMSG_REPORT_SMTP_FILTER_RESPONSE : return "IMSG_REPORT_SMTP_FILTER_RESPONSE";
2099 CASE(IMSG_REPORT_SMTP_TIMEOUT)case IMSG_REPORT_SMTP_TIMEOUT : return "IMSG_REPORT_SMTP_TIMEOUT";
2100
2101 CASE(IMSG_FILTER_SMTP_BEGIN)case IMSG_FILTER_SMTP_BEGIN : return "IMSG_FILTER_SMTP_BEGIN";
2102 CASE(IMSG_FILTER_SMTP_END)case IMSG_FILTER_SMTP_END : return "IMSG_FILTER_SMTP_END";
2103 CASE(IMSG_FILTER_SMTP_PROTOCOL)case IMSG_FILTER_SMTP_PROTOCOL : return "IMSG_FILTER_SMTP_PROTOCOL";
2104 CASE(IMSG_FILTER_SMTP_DATA_BEGIN)case IMSG_FILTER_SMTP_DATA_BEGIN : return "IMSG_FILTER_SMTP_DATA_BEGIN";
2105 CASE(IMSG_FILTER_SMTP_DATA_END)case IMSG_FILTER_SMTP_DATA_END : return "IMSG_FILTER_SMTP_DATA_END";
2106
2107 CASE(IMSG_CA_RSA_PRIVENC)case IMSG_CA_RSA_PRIVENC : return "IMSG_CA_RSA_PRIVENC";
2108 CASE(IMSG_CA_RSA_PRIVDEC)case IMSG_CA_RSA_PRIVDEC : return "IMSG_CA_RSA_PRIVDEC";
2109 CASE(IMSG_CA_ECDSA_SIGN)case IMSG_CA_ECDSA_SIGN : return "IMSG_CA_ECDSA_SIGN";
2110
2111 default:
2112 (void)snprintf(buf, sizeof(buf), "IMSG_??? (%d)", type);
2113
2114 return buf;
2115 }
2116}
2117
2118int
2119parent_auth_user(const char *username, const char *password)
2120{
2121 char user[LOGIN_NAME_MAX32];
2122 char pass[LINE_MAX2048];
2123 int ret;
2124
2125 (void)strlcpy(user, username, sizeof(user));
2126 (void)strlcpy(pass, password, sizeof(pass));
2127
2128 ret = auth_userokay(user, NULL((void *)0), "auth-smtp", pass);
2129 if (ret)
2130 return LKA_OK;
2131 return LKA_PERMFAIL;
2132}