xref: /openbsd/usr.sbin/smtpd/lka.c (revision 510586ac)
1 /*	$OpenBSD: lka.c,v 1.248 2024/01/20 09:01:03 claudio Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
5  * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
6  * Copyright (c) 2012 Eric Faurot <eric@faurot.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 
23 #include <errno.h>
24 #include <pwd.h>
25 #include <signal.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 
29 #include "smtpd.h"
30 #include "log.h"
31 
32 static void lka_imsg(struct mproc *, struct imsg *);
33 static void lka_shutdown(void);
34 static void lka_sig_handler(int, short, void *);
35 static int lka_authenticate(const char *, const char *, const char *);
36 static int lka_credentials(const char *, const char *, char *, size_t);
37 static int lka_userinfo(const char *, const char *, struct userinfo *);
38 static int lka_addrname(const char *, const struct sockaddr *,
39     struct addrname *);
40 static int lka_mailaddrmap(const char *, const char *, const struct mailaddr *);
41 
42 static void proc_timeout(int fd, short event, void *p);
43 
44 struct event	 ev_proc_ready;
45 
46 static void
lka_imsg(struct mproc * p,struct imsg * imsg)47 lka_imsg(struct mproc *p, struct imsg *imsg)
48 {
49 	struct table		*table;
50 	int			 ret, fd;
51 	struct sockaddr_storage	 ss;
52 	struct userinfo		 userinfo;
53 	struct addrname		 addrname;
54 	struct envelope		 evp;
55 	struct mailaddr		 maddr;
56 	struct msg		 m;
57 	union lookup		 lk;
58 	char			 buf[LINE_MAX];
59 	const char		*tablename, *username, *password, *label, *procname;
60 	uint64_t		 reqid;
61 	int			 v;
62 	struct timeval		 tv;
63 	const char		*direction;
64 	const char		*rdns;
65 	const char		*command;
66 	const char		*response;
67 	const char		*ciphers;
68 	const char		*address;
69 	const char		*domain;
70 	const char		*helomethod;
71 	const char		*heloname;
72 	const char		*filter_name;
73 	const char		*result;
74 	struct sockaddr_storage	ss_src, ss_dest;
75 	int                      filter_response;
76 	int                      filter_phase;
77 	const char              *filter_param;
78 	uint32_t		 msgid;
79 	uint32_t		 subsystems;
80 	uint64_t		 evpid;
81 	size_t			 msgsz;
82 	int			 ok;
83 	int			 fcrdns;
84 
85 	if (imsg == NULL)
86 		lka_shutdown();
87 
88 	switch (imsg->hdr.type) {
89 
90 	case IMSG_GETADDRINFO:
91 	case IMSG_GETNAMEINFO:
92 	case IMSG_RES_QUERY:
93 		resolver_dispatch_request(p, imsg);
94 		return;
95 
96 	case IMSG_MTA_DNS_HOST:
97 	case IMSG_MTA_DNS_MX:
98 	case IMSG_MTA_DNS_MX_PREFERENCE:
99 		dns_imsg(p, imsg);
100 		return;
101 
102 	case IMSG_SMTP_CHECK_SENDER:
103 		m_msg(&m, imsg);
104 		m_get_id(&m, &reqid);
105 		m_get_string(&m, &tablename);
106 		m_get_string(&m, &username);
107 		m_get_mailaddr(&m, &maddr);
108 		m_end(&m);
109 
110 		ret = lka_mailaddrmap(tablename, username, &maddr);
111 
112 		m_create(p, IMSG_SMTP_CHECK_SENDER, 0, 0, -1);
113 		m_add_id(p, reqid);
114 		m_add_int(p, ret);
115 		m_close(p);
116 		return;
117 
118 	case IMSG_SMTP_EXPAND_RCPT:
119 		m_msg(&m, imsg);
120 		m_get_id(&m, &reqid);
121 		m_get_envelope(&m, &evp);
122 		m_end(&m);
123 		lka_session(reqid, &evp);
124 		return;
125 
126 	case IMSG_SMTP_LOOKUP_HELO:
127 		m_msg(&m, imsg);
128 		m_get_id(&m, &reqid);
129 		m_get_string(&m, &tablename);
130 		m_get_sockaddr(&m, (struct sockaddr *)&ss);
131 		m_end(&m);
132 
133 		ret = lka_addrname(tablename, (struct sockaddr*)&ss,
134 		    &addrname);
135 
136 		m_create(p, IMSG_SMTP_LOOKUP_HELO, 0, 0, -1);
137 		m_add_id(p, reqid);
138 		m_add_int(p, ret);
139 		if (ret == LKA_OK)
140 			m_add_string(p, addrname.name);
141 		m_close(p);
142 		return;
143 
144 	case IMSG_SMTP_AUTHENTICATE:
145 		m_msg(&m, imsg);
146 		m_get_id(&m, &reqid);
147 		m_get_string(&m, &tablename);
148 		m_get_string(&m, &username);
149 		m_get_string(&m, &password);
150 		m_end(&m);
151 
152 		if (!tablename[0]) {
153 			m_create(p_parent, IMSG_LKA_AUTHENTICATE,
154 			    0, 0, -1);
155 			m_add_id(p_parent, reqid);
156 			m_add_string(p_parent, username);
157 			m_add_string(p_parent, password);
158 			m_close(p_parent);
159 			return;
160 		}
161 
162 		ret = lka_authenticate(tablename, username, password);
163 
164 		m_create(p, IMSG_SMTP_AUTHENTICATE, 0, 0, -1);
165 		m_add_id(p, reqid);
166 		m_add_int(p, ret);
167 		m_close(p);
168 		return;
169 
170 	case IMSG_MDA_LOOKUP_USERINFO:
171 		m_msg(&m, imsg);
172 		m_get_id(&m, &reqid);
173 		m_get_string(&m, &tablename);
174 		m_get_string(&m, &username);
175 		m_end(&m);
176 
177 		ret = lka_userinfo(tablename, username, &userinfo);
178 
179 		m_create(p, IMSG_MDA_LOOKUP_USERINFO, 0, 0, -1);
180 		m_add_id(p, reqid);
181 		m_add_int(p, ret);
182 		if (ret == LKA_OK)
183 			m_add_data(p, &userinfo, sizeof(userinfo));
184 		m_close(p);
185 		return;
186 
187 	case IMSG_MTA_LOOKUP_CREDENTIALS:
188 		m_msg(&m, imsg);
189 		m_get_id(&m, &reqid);
190 		m_get_string(&m, &tablename);
191 		m_get_string(&m, &label);
192 		m_end(&m);
193 
194 		lka_credentials(tablename, label, buf, sizeof(buf));
195 
196 		m_create(p, IMSG_MTA_LOOKUP_CREDENTIALS, 0, 0, -1);
197 		m_add_id(p, reqid);
198 		m_add_string(p, buf);
199 		m_close(p);
200 		return;
201 
202 	case IMSG_MTA_LOOKUP_SOURCE:
203 		m_msg(&m, imsg);
204 		m_get_id(&m, &reqid);
205 		m_get_string(&m, &tablename);
206 		m_end(&m);
207 
208 		table = table_find(env, tablename);
209 
210 		m_create(p, IMSG_MTA_LOOKUP_SOURCE, 0, 0, -1);
211 		m_add_id(p, reqid);
212 
213 		if (table == NULL) {
214 			log_warn("warn: source address table %s missing",
215 			    tablename);
216 			m_add_int(p, LKA_TEMPFAIL);
217 		}
218 		else {
219 			ret = table_fetch(table, K_SOURCE, &lk);
220 			if (ret == -1)
221 				m_add_int(p, LKA_TEMPFAIL);
222 			else if (ret == 0)
223 				m_add_int(p, LKA_PERMFAIL);
224 			else {
225 				m_add_int(p, LKA_OK);
226 				m_add_sockaddr(p,
227 				    (struct sockaddr *)&lk.source.addr);
228 			}
229 		}
230 		m_close(p);
231 		return;
232 
233 	case IMSG_MTA_LOOKUP_HELO:
234 		m_msg(&m, imsg);
235 		m_get_id(&m, &reqid);
236 		m_get_string(&m, &tablename);
237 		m_get_sockaddr(&m, (struct sockaddr *)&ss);
238 		m_end(&m);
239 
240 		ret = lka_addrname(tablename, (struct sockaddr*)&ss,
241 		    &addrname);
242 
243 		m_create(p, IMSG_MTA_LOOKUP_HELO, 0, 0, -1);
244 		m_add_id(p, reqid);
245 		m_add_int(p, ret);
246 		if (ret == LKA_OK)
247 			m_add_string(p, addrname.name);
248 		m_close(p);
249 		return;
250 
251 	case IMSG_MTA_LOOKUP_SMARTHOST:
252 		m_msg(&m, imsg);
253 		m_get_id(&m, &reqid);
254 		m_get_string(&m, &domain);
255 		m_get_string(&m, &tablename);
256 		m_end(&m);
257 
258 		table = table_find(env, tablename);
259 
260 		m_create(p, IMSG_MTA_LOOKUP_SMARTHOST, 0, 0, -1);
261 		m_add_id(p, reqid);
262 
263 		if (table == NULL) {
264 			log_warn("warn: smarthost table %s missing", tablename);
265 			m_add_int(p, LKA_TEMPFAIL);
266 		}
267 		else {
268 			if (domain == NULL)
269 				ret = table_fetch(table, K_RELAYHOST, &lk);
270 			else
271 				ret = table_lookup(table, K_RELAYHOST, domain, &lk);
272 
273 			if (ret == -1)
274 				m_add_int(p, LKA_TEMPFAIL);
275 			else if (ret == 0)
276 				m_add_int(p, LKA_PERMFAIL);
277 			else {
278 				m_add_int(p, LKA_OK);
279 				m_add_string(p, lk.relayhost);
280 			}
281 		}
282 		m_close(p);
283 		return;
284 
285 	case IMSG_CONF_START:
286 		return;
287 
288 	case IMSG_CONF_END:
289 		if (tracing & TRACE_TABLES)
290 			table_dump_all(env);
291 
292 		/* fork & exec tables that need it */
293 		table_open_all(env);
294 
295 		/* revoke proc & exec */
296 		if (pledge("stdio rpath inet dns getpw recvfd sendfd",
297 			NULL) == -1)
298 			fatal("pledge");
299 
300 		/* setup proc registering task */
301 		evtimer_set(&ev_proc_ready, proc_timeout, &ev_proc_ready);
302 		tv.tv_sec = 0;
303 		tv.tv_usec = 10;
304 		evtimer_add(&ev_proc_ready, &tv);
305 		return;
306 
307 	case IMSG_LKA_OPEN_FORWARD:
308 		lka_session_forward_reply(imsg->data, imsg_get_fd(imsg));
309 		return;
310 
311 	case IMSG_LKA_AUTHENTICATE:
312 		imsg->hdr.type = IMSG_SMTP_AUTHENTICATE;
313 		m_forward(p_dispatcher, imsg);
314 		return;
315 
316 	case IMSG_CTL_VERBOSE:
317 		m_msg(&m, imsg);
318 		m_get_int(&m, &v);
319 		m_end(&m);
320 		log_trace_verbose(v);
321 		return;
322 
323 	case IMSG_CTL_PROFILE:
324 		m_msg(&m, imsg);
325 		m_get_int(&m, &v);
326 		m_end(&m);
327 		profiling = v;
328 		return;
329 
330 	case IMSG_CTL_UPDATE_TABLE:
331 		ret = 0;
332 		table = table_find(env, imsg->data);
333 		if (table == NULL) {
334 			log_warnx("warn: Lookup table not found: "
335 			    "\"%s\"", (char *)imsg->data);
336 		} else
337 			ret = table_update(table);
338 
339 		m_compose(p_control,
340 		    (ret == 1) ? IMSG_CTL_OK : IMSG_CTL_FAIL,
341 		    imsg->hdr.peerid, 0, -1, NULL, 0);
342 		return;
343 
344 	case IMSG_LKA_PROCESSOR_FORK:
345 		m_msg(&m, imsg);
346 		m_get_string(&m, &procname);
347 		m_get_u32(&m, &subsystems);
348 		m_end(&m);
349 
350 		m_create(p, IMSG_LKA_PROCESSOR_ERRFD, 0, 0, -1);
351 		m_add_string(p, procname);
352 		m_close(p);
353 
354 		lka_proc_forked(procname, subsystems, imsg_get_fd(imsg));
355 		return;
356 
357 	case IMSG_LKA_PROCESSOR_ERRFD:
358 		m_msg(&m, imsg);
359 		m_get_string(&m, &procname);
360 		m_end(&m);
361 
362 		fd = imsg_get_fd(imsg);
363 		lka_proc_errfd(procname, fd);
364 		shutdown(fd, SHUT_WR);
365 		return;
366 
367 	case IMSG_REPORT_SMTP_LINK_CONNECT:
368 		m_msg(&m, imsg);
369 		m_get_string(&m, &direction);
370 		m_get_timeval(&m, &tv);
371 		m_get_id(&m, &reqid);
372 		m_get_string(&m, &rdns);
373 		m_get_int(&m, &fcrdns);
374 		m_get_sockaddr(&m, (struct sockaddr *)&ss_src);
375 		m_get_sockaddr(&m, (struct sockaddr *)&ss_dest);
376 		m_end(&m);
377 
378 		lka_report_smtp_link_connect(direction, &tv, reqid, rdns, fcrdns, &ss_src, &ss_dest);
379 		return;
380 
381 	case IMSG_REPORT_SMTP_LINK_GREETING:
382 		m_msg(&m, imsg);
383 		m_get_string(&m, &direction);
384 		m_get_timeval(&m, &tv);
385 		m_get_id(&m, &reqid);
386 		m_get_string(&m, &domain);
387 		m_end(&m);
388 
389 		lka_report_smtp_link_greeting(direction, reqid, &tv, domain);
390 		return;
391 
392 	case IMSG_REPORT_SMTP_LINK_DISCONNECT:
393 		m_msg(&m, imsg);
394 		m_get_string(&m, &direction);
395 		m_get_timeval(&m, &tv);
396 		m_get_id(&m, &reqid);
397 		m_end(&m);
398 
399 		lka_report_smtp_link_disconnect(direction, &tv, reqid);
400 		return;
401 
402 	case IMSG_REPORT_SMTP_LINK_IDENTIFY:
403 		m_msg(&m, imsg);
404 		m_get_string(&m, &direction);
405 		m_get_timeval(&m, &tv);
406 		m_get_id(&m, &reqid);
407 		m_get_string(&m, &helomethod);
408 		m_get_string(&m, &heloname);
409 		m_end(&m);
410 
411 		lka_report_smtp_link_identify(direction, &tv, reqid, helomethod, heloname);
412 		return;
413 
414 	case IMSG_REPORT_SMTP_LINK_TLS:
415 		m_msg(&m, imsg);
416 		m_get_string(&m, &direction);
417 		m_get_timeval(&m, &tv);
418 		m_get_id(&m, &reqid);
419 		m_get_string(&m, &ciphers);
420 		m_end(&m);
421 
422 		lka_report_smtp_link_tls(direction, &tv, reqid, ciphers);
423 		return;
424 
425 	case IMSG_REPORT_SMTP_LINK_AUTH:
426 		m_msg(&m, imsg);
427 		m_get_string(&m, &direction);
428 		m_get_timeval(&m, &tv);
429 		m_get_id(&m, &reqid);
430 		m_get_string(&m, &username);
431 		m_get_string(&m, &result);
432 		m_end(&m);
433 
434 		lka_report_smtp_link_auth(direction, &tv, reqid, username, result);
435 		return;
436 
437 	case IMSG_REPORT_SMTP_TX_RESET:
438 		m_msg(&m, imsg);
439 		m_get_string(&m, &direction);
440 		m_get_timeval(&m, &tv);
441 		m_get_id(&m, &reqid);
442 		m_get_u32(&m, &msgid);
443 		m_end(&m);
444 
445 		lka_report_smtp_tx_reset(direction, &tv, reqid, msgid);
446 		return;
447 
448 	case IMSG_REPORT_SMTP_TX_BEGIN:
449 		m_msg(&m, imsg);
450 		m_get_string(&m, &direction);
451 		m_get_timeval(&m, &tv);
452 		m_get_id(&m, &reqid);
453 		m_get_u32(&m, &msgid);
454 		m_end(&m);
455 
456 		lka_report_smtp_tx_begin(direction, &tv, reqid, msgid);
457 		return;
458 
459 	case IMSG_REPORT_SMTP_TX_MAIL:
460 		m_msg(&m, imsg);
461 		m_get_string(&m, &direction);
462 		m_get_timeval(&m, &tv);
463 		m_get_id(&m, &reqid);
464 		m_get_u32(&m, &msgid);
465 		m_get_string(&m, &address);
466 		m_get_int(&m, &ok);
467 		m_end(&m);
468 
469 		lka_report_smtp_tx_mail(direction, &tv, reqid, msgid, address, ok);
470 		return;
471 
472 	case IMSG_REPORT_SMTP_TX_RCPT:
473 		m_msg(&m, imsg);
474 		m_get_string(&m, &direction);
475 		m_get_timeval(&m, &tv);
476 		m_get_id(&m, &reqid);
477 		m_get_u32(&m, &msgid);
478 		m_get_string(&m, &address);
479 		m_get_int(&m, &ok);
480 		m_end(&m);
481 
482 		lka_report_smtp_tx_rcpt(direction, &tv, reqid, msgid, address, ok);
483 		return;
484 
485 	case IMSG_REPORT_SMTP_TX_ENVELOPE:
486 		m_msg(&m, imsg);
487 		m_get_string(&m, &direction);
488 		m_get_timeval(&m, &tv);
489 		m_get_id(&m, &reqid);
490 		m_get_u32(&m, &msgid);
491 		m_get_id(&m, &evpid);
492 		m_end(&m);
493 
494 		lka_report_smtp_tx_envelope(direction, &tv, reqid, msgid, evpid);
495 		return;
496 
497 	case IMSG_REPORT_SMTP_TX_DATA:
498 		m_msg(&m, imsg);
499 		m_get_string(&m, &direction);
500 		m_get_timeval(&m, &tv);
501 		m_get_id(&m, &reqid);
502 		m_get_u32(&m, &msgid);
503 		m_get_int(&m, &ok);
504 		m_end(&m);
505 
506 		lka_report_smtp_tx_data(direction, &tv, reqid, msgid, ok);
507 		return;
508 
509 	case IMSG_REPORT_SMTP_TX_COMMIT:
510 		m_msg(&m, imsg);
511 		m_get_string(&m, &direction);
512 		m_get_timeval(&m, &tv);
513 		m_get_id(&m, &reqid);
514 		m_get_u32(&m, &msgid);
515 		m_get_size(&m, &msgsz);
516 		m_end(&m);
517 
518 		lka_report_smtp_tx_commit(direction, &tv, reqid, msgid, msgsz);
519 		return;
520 
521 	case IMSG_REPORT_SMTP_TX_ROLLBACK:
522 		m_msg(&m, imsg);
523 		m_get_string(&m, &direction);
524 		m_get_timeval(&m, &tv);
525 		m_get_id(&m, &reqid);
526 		m_get_u32(&m, &msgid);
527 		m_end(&m);
528 
529 		lka_report_smtp_tx_rollback(direction, &tv, reqid, msgid);
530 		return;
531 
532 	case IMSG_REPORT_SMTP_PROTOCOL_CLIENT:
533 		m_msg(&m, imsg);
534 		m_get_string(&m, &direction);
535 		m_get_timeval(&m, &tv);
536 		m_get_id(&m, &reqid);
537 		m_get_string(&m, &command);
538 		m_end(&m);
539 
540 		lka_report_smtp_protocol_client(direction, &tv, reqid, command);
541 		return;
542 
543 	case IMSG_REPORT_SMTP_PROTOCOL_SERVER:
544 		m_msg(&m, imsg);
545 		m_get_string(&m, &direction);
546 		m_get_timeval(&m, &tv);
547 		m_get_id(&m, &reqid);
548 		m_get_string(&m, &response);
549 		m_end(&m);
550 
551 		lka_report_smtp_protocol_server(direction, &tv, reqid, response);
552 		return;
553 
554 	case IMSG_REPORT_SMTP_FILTER_RESPONSE:
555 		m_msg(&m, imsg);
556 		m_get_string(&m, &direction);
557 		m_get_timeval(&m, &tv);
558 		m_get_id(&m, &reqid);
559 		m_get_int(&m, &filter_phase);
560 		m_get_int(&m, &filter_response);
561 		m_get_string(&m, &filter_param);
562 		m_end(&m);
563 
564 		lka_report_smtp_filter_response(direction, &tv, reqid,
565 		    filter_phase, filter_response, filter_param);
566 		return;
567 
568 	case IMSG_REPORT_SMTP_TIMEOUT:
569 		m_msg(&m, imsg);
570 		m_get_string(&m, &direction);
571 		m_get_timeval(&m, &tv);
572 		m_get_id(&m, &reqid);
573 		m_end(&m);
574 
575 		lka_report_smtp_timeout(direction, &tv, reqid);
576 		return;
577 
578 	case IMSG_FILTER_SMTP_PROTOCOL:
579 		m_msg(&m, imsg);
580 		m_get_id(&m, &reqid);
581 		m_get_int(&m, &filter_phase);
582 		m_get_string(&m, &filter_param);
583 		m_end(&m);
584 
585 		lka_filter_protocol(reqid, filter_phase, filter_param);
586 		return;
587 
588 	case IMSG_FILTER_SMTP_BEGIN:
589 		m_msg(&m, imsg);
590 		m_get_id(&m, &reqid);
591 		m_get_string(&m, &filter_name);
592 		m_end(&m);
593 
594 		lka_filter_begin(reqid, filter_name);
595 		return;
596 
597 	case IMSG_FILTER_SMTP_END:
598 		m_msg(&m, imsg);
599 		m_get_id(&m, &reqid);
600 		m_end(&m);
601 
602 		lka_filter_end(reqid);
603 		return;
604 
605 	case IMSG_FILTER_SMTP_DATA_BEGIN:
606 		m_msg(&m, imsg);
607 		m_get_id(&m, &reqid);
608 		m_end(&m);
609 
610 		lka_filter_data_begin(reqid);
611 		return;
612 
613 	case IMSG_FILTER_SMTP_DATA_END:
614 		m_msg(&m, imsg);
615 		m_get_id(&m, &reqid);
616 		m_end(&m);
617 
618 		lka_filter_data_end(reqid);
619 		return;
620 
621 	}
622 
623 	fatalx("lka_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type));
624 }
625 
626 static void
lka_sig_handler(int sig,short event,void * p)627 lka_sig_handler(int sig, short event, void *p)
628 {
629 	int status;
630 	pid_t pid;
631 
632 	switch (sig) {
633 	case SIGCHLD:
634 		do {
635 			pid = waitpid(-1, &status, WNOHANG);
636 		} while (pid > 0 || (pid == -1 && errno == EINTR));
637 		break;
638 	default:
639 		fatalx("lka_sig_handler: unexpected signal");
640 	}
641 }
642 
643 void
lka_shutdown(void)644 lka_shutdown(void)
645 {
646 	log_debug("debug: lookup agent exiting");
647 	_exit(0);
648 }
649 
650 int
lka(void)651 lka(void)
652 {
653 	struct passwd	*pw;
654 	struct event	 ev_sigchld;
655 
656 	purge_config(PURGE_LISTENERS);
657 
658 	if ((pw = getpwnam(SMTPD_USER)) == NULL)
659 		fatalx("unknown user " SMTPD_USER);
660 
661 	config_process(PROC_LKA);
662 
663 	if (initgroups(pw->pw_name, pw->pw_gid) ||
664 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
665 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
666 		fatal("lka: cannot drop privileges");
667 
668 	imsg_callback = lka_imsg;
669 	event_init();
670 
671 	signal_set(&ev_sigchld, SIGCHLD, lka_sig_handler, NULL);
672 	signal_add(&ev_sigchld, NULL);
673 	signal(SIGINT, SIG_IGN);
674 	signal(SIGTERM, SIG_IGN);
675 	signal(SIGPIPE, SIG_IGN);
676 	signal(SIGHUP, SIG_IGN);
677 
678 	config_peer(PROC_PARENT);
679 	config_peer(PROC_QUEUE);
680 	config_peer(PROC_CONTROL);
681 	config_peer(PROC_DISPATCHER);
682 
683 	/* Ignore them until we get our config */
684 	mproc_disable(p_dispatcher);
685 
686 	lka_report_init();
687 	lka_filter_init();
688 
689 	/* proc & exec will be revoked before serving requests */
690 	if (pledge("stdio rpath inet dns getpw recvfd sendfd proc exec", NULL) == -1)
691 		fatal("pledge");
692 
693 	event_dispatch();
694 	fatalx("exited event loop");
695 
696 	return (0);
697 }
698 
699 static void
proc_timeout(int fd,short event,void * p)700 proc_timeout(int fd, short event, void *p)
701 {
702 	struct event	*ev = p;
703 	struct timeval	 tv;
704 
705 	if (!lka_proc_ready())
706 		goto reset;
707 
708 	lka_filter_ready();
709 	mproc_enable(p_dispatcher);
710 	return;
711 
712 reset:
713 	tv.tv_sec = 0;
714 	tv.tv_usec = 10;
715 	evtimer_add(ev, &tv);
716 }
717 
718 
719 static int
lka_authenticate(const char * tablename,const char * user,const char * password)720 lka_authenticate(const char *tablename, const char *user, const char *password)
721 {
722 	struct table		*table;
723 	union lookup		 lk;
724 
725 	log_debug("debug: lka: authenticating for %s:%s", tablename, user);
726 	table = table_find(env, tablename);
727 	if (table == NULL) {
728 		log_warnx("warn: could not find table %s needed for authentication",
729 		    tablename);
730 		return (LKA_TEMPFAIL);
731 	}
732 
733 	switch (table_lookup(table, K_CREDENTIALS, user, &lk)) {
734 	case -1:
735 		log_warnx("warn: user credentials lookup fail for %s:%s",
736 		    tablename, user);
737 		return (LKA_TEMPFAIL);
738 	case 0:
739 		return (LKA_PERMFAIL);
740 	default:
741 		if (crypt_checkpass(password, lk.creds.password) == 0)
742 			return (LKA_OK);
743 		return (LKA_PERMFAIL);
744 	}
745 }
746 
747 static int
lka_credentials(const char * tablename,const char * label,char * dst,size_t sz)748 lka_credentials(const char *tablename, const char *label, char *dst, size_t sz)
749 {
750 	struct table		*table;
751 	union lookup		 lk;
752 	char			*buf;
753 	int			 buflen, r;
754 
755 	table = table_find(env, tablename);
756 	if (table == NULL) {
757 		log_warnx("warn: credentials table %s missing", tablename);
758 		return (LKA_TEMPFAIL);
759 	}
760 
761 	dst[0] = '\0';
762 
763 	switch (table_lookup(table, K_CREDENTIALS, label, &lk)) {
764 	case -1:
765 		log_warnx("warn: credentials lookup fail for %s:%s",
766 		    tablename, label);
767 		return (LKA_TEMPFAIL);
768 	case 0:
769 		log_warnx("warn: credentials not found for %s:%s",
770 		    tablename, label);
771 		return (LKA_PERMFAIL);
772 	default:
773 		if ((buflen = asprintf(&buf, "%c%s%c%s", '\0',
774 		    lk.creds.username, '\0', lk.creds.password)) == -1) {
775 			log_warn("warn");
776 			return (LKA_TEMPFAIL);
777 		}
778 
779 		r = base64_encode((unsigned char *)buf, buflen, dst, sz);
780 		free(buf);
781 
782 		if (r == -1) {
783 			log_warnx("warn: credentials parse error for %s:%s",
784 			    tablename, label);
785 			return (LKA_TEMPFAIL);
786 		}
787 		return (LKA_OK);
788 	}
789 }
790 
791 static int
lka_userinfo(const char * tablename,const char * username,struct userinfo * res)792 lka_userinfo(const char *tablename, const char *username, struct userinfo *res)
793 {
794 	struct table	*table;
795 	union lookup	 lk;
796 
797 	log_debug("debug: lka: userinfo %s:%s", tablename, username);
798 	table = table_find(env, tablename);
799 	if (table == NULL) {
800 		log_warnx("warn: cannot find user table %s", tablename);
801 		return (LKA_TEMPFAIL);
802 	}
803 
804 	switch (table_lookup(table, K_USERINFO, username, &lk)) {
805 	case -1:
806 		log_warnx("warn: failure during userinfo lookup %s:%s",
807 		    tablename, username);
808 		return (LKA_TEMPFAIL);
809 	case 0:
810 		return (LKA_PERMFAIL);
811 	default:
812 		*res = lk.userinfo;
813 		return (LKA_OK);
814 	}
815 }
816 
817 static int
lka_addrname(const char * tablename,const struct sockaddr * sa,struct addrname * res)818 lka_addrname(const char *tablename, const struct sockaddr *sa,
819     struct addrname *res)
820 {
821 	struct table	*table;
822 	union lookup	 lk;
823 	const char	*source;
824 
825 	source = sa_to_text(sa);
826 
827 	log_debug("debug: lka: helo %s:%s", tablename, source);
828 	table = table_find(env, tablename);
829 	if (table == NULL) {
830 		log_warnx("warn: cannot find helo table %s", tablename);
831 		return (LKA_TEMPFAIL);
832 	}
833 
834 	switch (table_lookup(table, K_ADDRNAME, source, &lk)) {
835 	case -1:
836 		log_warnx("warn: failure during helo lookup %s:%s",
837 		    tablename, source);
838 		return (LKA_TEMPFAIL);
839 	case 0:
840 		return (LKA_PERMFAIL);
841 	default:
842 		*res = lk.addrname;
843 		return (LKA_OK);
844 	}
845 }
846 
847 static int
lka_mailaddrmap(const char * tablename,const char * username,const struct mailaddr * maddr)848 lka_mailaddrmap(const char *tablename, const char *username, const struct mailaddr *maddr)
849 {
850 	struct table	       *table;
851 	struct maddrnode       *mn;
852 	union lookup		lk;
853 	int			found;
854 
855 	log_debug("debug: lka: mailaddrmap %s:%s", tablename, username);
856 	table = table_find(env, tablename);
857 	if (table == NULL) {
858 		log_warnx("warn: cannot find mailaddrmap table %s", tablename);
859 		return (LKA_TEMPFAIL);
860 	}
861 
862 	switch (table_lookup(table, K_MAILADDRMAP, username, &lk)) {
863 	case -1:
864 		log_warnx("warn: failure during mailaddrmap lookup %s:%s",
865 		    tablename, username);
866 		return (LKA_TEMPFAIL);
867 	case 0:
868 		return (LKA_PERMFAIL);
869 	default:
870 		found = 0;
871 		TAILQ_FOREACH(mn, &lk.maddrmap->queue, entries) {
872 			if (!mailaddr_match(maddr, &mn->mailaddr))
873 				continue;
874 			found = 1;
875 			break;
876 		}
877 		maddrmap_free(lk.maddrmap);
878 		if (found)
879 			return (LKA_OK);
880 		return (LKA_PERMFAIL);
881 	}
882 	return (LKA_OK);
883 }
884