Bug Summary

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