Bug Summary

File:src/usr.sbin/smtpd/smtpd/../smtpd.c
Warning:line 595, column 15
Access to field 'sc_opts' results in a dereference of a null pointer (loaded from variable 'env')

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))
1
Assuming the condition is false
2
Taking false branch
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)
;
3
Loop condition is false. Exiting loop
485
486 while ((c = getopt(argc, argv, "B:dD:hnP:f:FT:vx:")) != -1) {
4
Assuming the condition is true
5
Loop condition is true. Entering loop body
10
Execution continues on line 486
11
Assuming the condition is false
12
Loop condition is false. Execution continues on line 589
487 switch (c) {
6
Control jumps to 'case 68:' at line 504
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)
7
Null pointer value stored to 'env'
8
Assuming the condition is false
9
Taking false branch
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)
13
Assuming 'argc' is 0
14
Assuming the condition is false
15
Taking false branch
593 usage();
594
595 env->sc_opts |= opts;
16
Access to field 'sc_opts' results in a dereference of a null pointer (loaded from variable 'env')
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)) {
1821 imsg_callback(p, imsg);
1822 return;
1823 }
1824
1825 log_imsg(smtpd_process, p->proc, imsg);
1826
1827 if (profiling & PROFILE_IMSG0x0002)
1828 clock_gettime(CLOCK_MONOTONIC3, &t0);
1829
1830 msg = imsg->hdr.type;
1831 imsg_callback(p, imsg);
1832
1833 if (profiling & PROFILE_IMSG0x0002) {
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)
;
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}