xref: /openbsd-src/usr.sbin/smtpd/lka.c (revision 2b0358df1d88d06ef4139321dd05bd5e05d91eaf)
1 /*	$OpenBSD: lka.c,v 1.39 2009/04/05 16:33:12 gilles Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
5  * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/types.h>
21 #include <sys/queue.h>
22 #include <sys/tree.h>
23 #include <sys/param.h>
24 #include <sys/socket.h>
25 
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
28 
29 #include <ctype.h>
30 #include <event.h>
31 #include <netdb.h>
32 #include <pwd.h>
33 #include <regex.h>
34 #include <signal.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <unistd.h>
39 
40 #include <keynote.h>
41 
42 #include "smtpd.h"
43 
44 __dead void	lka_shutdown(void);
45 void		lka_sig_handler(int, short, void *);
46 void		lka_dispatch_parent(int, short, void *);
47 void		lka_dispatch_mfa(int, short, void *);
48 void		lka_dispatch_smtp(int, short, void *);
49 void		lka_dispatch_queue(int, short, void *);
50 void		lka_dispatch_runner(int, short, void *);
51 void		lka_dispatch_mta(int, short, void *);
52 void		lka_setup_events(struct smtpd *);
53 void		lka_disable_events(struct smtpd *);
54 int		lka_verify_mail(struct smtpd *, struct path *);
55 int		lka_resolve_mail(struct smtpd *, struct rule *, struct path *);
56 int		lka_forward_file(struct passwd *);
57 size_t		lka_expand(char *, size_t, struct path *);
58 int		aliases_exist(struct smtpd *, char *);
59 int		aliases_get(struct smtpd *, struct aliaseslist *, char *);
60 int		lka_resolve_alias(struct smtpd *, struct path *, struct alias *);
61 int		lka_parse_include(char *);
62 int		lka_check_source(struct smtpd *, struct map *, struct sockaddr_storage *);
63 int		lka_match_mask(struct sockaddr_storage *, struct netaddr *);
64 int		aliases_virtual_get(struct smtpd *, struct aliaseslist *, struct path *);
65 int		aliases_virtual_exist(struct smtpd *, struct path *);
66 int		lka_resolve_path(struct smtpd *, struct path *);
67 void		lka_expand_rcpt(struct smtpd *, struct aliaseslist *, struct lkasession *);
68 int		lka_expand_rcpt_iteration(struct smtpd *, struct aliaseslist *, struct lkasession *);
69 void		lka_rcpt_action(struct smtpd *, struct path *);
70 void		lka_clear_aliaseslist(struct aliaseslist *);
71 int		lka_encode_credentials(char *, char *);
72 
73 void
74 lka_sig_handler(int sig, short event, void *p)
75 {
76 	switch (sig) {
77 	case SIGINT:
78 	case SIGTERM:
79 		lka_shutdown();
80 		break;
81 	default:
82 		fatalx("lka_sig_handler: unexpected signal");
83 	}
84 }
85 
86 void
87 lka_dispatch_parent(int sig, short event, void *p)
88 {
89 	struct smtpd		*env = p;
90 	struct imsgbuf		*ibuf;
91 	struct imsg		 imsg;
92 	ssize_t			 n;
93 
94 	ibuf = env->sc_ibufs[PROC_PARENT];
95 	switch (event) {
96 	case EV_READ:
97 		if ((n = imsg_read(ibuf)) == -1)
98 			fatal("imsg_read_error");
99 		if (n == 0) {
100 			/* this pipe is dead, so remove the event handler */
101 			event_del(&ibuf->ev);
102 			event_loopexit(NULL);
103 			return;
104 		}
105 		break;
106 	case EV_WRITE:
107 		if (msgbuf_write(&ibuf->w) == -1)
108 			fatal("msgbuf_write");
109 		imsg_event_add(ibuf);
110 		return;
111 	default:
112 		fatalx("unknown event");
113 	}
114 
115 	for (;;) {
116 		if ((n = imsg_get(ibuf, &imsg)) == -1)
117 			fatal("parent_dispatch_lka: imsg_read error");
118 		if (n == 0)
119 			break;
120 
121 		switch (imsg.hdr.type) {
122 		case IMSG_PARENT_FORWARD_OPEN: {
123 			int fd;
124 			struct forward_req	*fwreq;
125 			struct lkasession	key;
126 			struct lkasession	*lkasession;
127 
128 			fwreq = imsg.data;
129 
130 			key.id = fwreq->id;
131 			lkasession = SPLAY_FIND(lkatree, &env->lka_sessions, &key);
132 			if (lkasession == NULL)
133 				fatal("lka_dispatch_parent: lka session is gone");
134 			fd = imsg_get_fd(ibuf, &imsg);
135 			--lkasession->pending;
136 
137 			if (fd == -1) {
138 				if (! fwreq->status) {
139 					lkasession->ss.code = 530;
140 					lkasession->flags |= F_ERROR;
141 				}
142 				else {
143 					struct alias *alias;
144 					struct message message;
145 
146 					alias = calloc(1, sizeof(struct alias));
147 					if (alias == NULL)
148 						fatal("lka_dispatch_parent: calloc");
149 
150 					alias_parse(alias, fwreq->pw_name);
151 
152 					message = lkasession->message;
153 					bzero(&message.recipient, sizeof(struct path));
154 					lka_resolve_alias(env, &message.recipient, alias);
155 					lka_rcpt_action(env, &message.recipient);
156 
157 					imsg_compose(env->sc_ibufs[PROC_QUEUE],
158 					    IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1,
159 					    &message, sizeof(struct message));
160 
161 					if (! lkasession->pending)
162 						imsg_compose(env->sc_ibufs[PROC_QUEUE],
163 						    IMSG_QUEUE_COMMIT_ENVELOPES, 0, 0, -1,
164 						    &message, sizeof(struct message));
165 					break;
166 				}
167 			}
168 			else {
169 				if (! forwards_get(fd, &lkasession->aliaseslist)) {
170 					lkasession->ss.code = 530;
171 					lkasession->flags |= F_ERROR;
172 				}
173 				close(fd);
174 			}
175 			lka_expand_rcpt(env, &lkasession->aliaseslist, lkasession);
176 			break;
177 		}
178 		default:
179 			log_warnx("lka_dispatch_parent: got imsg %d",
180 			    imsg.hdr.type);
181 			fatalx("lka_dispatch_parent: unexpected imsg");
182 		}
183 		imsg_free(&imsg);
184 	}
185 	imsg_event_add(ibuf);
186 }
187 
188 void
189 lka_dispatch_mfa(int sig, short event, void *p)
190 {
191 	struct smtpd		*env = p;
192 	struct imsgbuf		*ibuf;
193 	struct imsg		 imsg;
194 	ssize_t			 n;
195 
196 	ibuf = env->sc_ibufs[PROC_MFA];
197 	switch (event) {
198 	case EV_READ:
199 		if ((n = imsg_read(ibuf)) == -1)
200 			fatal("imsg_read_error");
201 		if (n == 0) {
202 			/* this pipe is dead, so remove the event handler */
203 			event_del(&ibuf->ev);
204 			event_loopexit(NULL);
205 			return;
206 		}
207 		break;
208 	case EV_WRITE:
209 		if (msgbuf_write(&ibuf->w) == -1)
210 			fatal("msgbuf_write");
211 		imsg_event_add(ibuf);
212 		return;
213 	default:
214 		fatalx("unknown event");
215 	}
216 
217 	for (;;) {
218 		if ((n = imsg_get(ibuf, &imsg)) == -1)
219 			fatal("lka_dispatch_mfa: imsg_read error");
220 		if (n == 0)
221 			break;
222 
223 		switch (imsg.hdr.type) {
224 		case IMSG_LKA_MAIL: {
225 			struct submit_status	 *ss;
226 
227 			ss = imsg.data;
228 			ss->code = 530;
229 
230 			if (ss->u.path.user[0] == '\0' && ss->u.path.domain[0] == '\0')
231 				ss->code = 250;
232 			else
233 				if (lka_verify_mail(env, &ss->u.path))
234 					ss->code = 250;
235 
236 			imsg_compose(ibuf, IMSG_LKA_MAIL, 0, 0, -1,
237 				ss, sizeof(*ss));
238 
239 			break;
240 		}
241 		case IMSG_LKA_RCPT: {
242 			struct submit_status	*ss;
243 			struct message		message;
244 			struct lkasession	*lkasession;
245 			struct forward_req	 fwreq;
246 			int ret;
247 
248 			ss = imsg.data;
249 			ss->code = 530;
250 
251 			if (IS_RELAY(ss->u.path.rule.r_action)) {
252 				ss->code = 250;
253 				message = ss->msg;
254 				message.recipient = ss->u.path;
255 				imsg_compose(env->sc_ibufs[PROC_QUEUE],
256 				    IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1,
257 				    &message, sizeof(struct message));
258 				imsg_compose(env->sc_ibufs[PROC_QUEUE],
259 				    IMSG_QUEUE_COMMIT_ENVELOPES, 0, 0, -1,
260 				    &message, sizeof(struct message));
261 				break;
262 			}
263 
264 			if (! lka_resolve_path(env, &ss->u.path)) {
265 				imsg_compose(ibuf, IMSG_LKA_RCPT, 0, 0, -1,
266 				    ss, sizeof(*ss));
267 				break;
268 			}
269 
270 			ss->code = 250;
271 
272 			lkasession = calloc(1, sizeof(struct lkasession));
273 			if (lkasession == NULL)
274 				fatal("lka_dispatch_mfa: calloc");
275 			lkasession->id = queue_generate_id();
276 			lkasession->path = ss->u.path;
277 			lkasession->message = ss->msg;
278 			lkasession->ss = *ss;
279 
280 			TAILQ_INIT(&lkasession->aliaseslist);
281 
282 			SPLAY_INSERT(lkatree, &env->lka_sessions, lkasession);
283 
284 			ret = 0;
285 			if (lkasession->path.flags & F_ACCOUNT) {
286 				fwreq.id = lkasession->id;
287 				(void)strlcpy(fwreq.pw_name, ss->u.path.pw_name, sizeof(fwreq.pw_name));
288 				imsg_compose(env->sc_ibufs[PROC_PARENT], IMSG_PARENT_FORWARD_OPEN, 0, 0, -1,
289 				    &fwreq, sizeof(fwreq));
290 				++lkasession->pending;
291 				break;
292 			}
293 			else if (lkasession->path.flags & F_ALIAS) {
294 				ret = aliases_get(env, &lkasession->aliaseslist, lkasession->path.user);
295 			}
296 			else if (lkasession->path.flags & F_VIRTUAL) {
297 				ret = aliases_virtual_get(env, &lkasession->aliaseslist, &lkasession->path);
298 			}
299 			else
300 				fatal("lka_dispatch_mfa: path with illegal flag");
301 
302 			if (ret == 0) {
303 				/* No aliases ... */
304 				ss->code = 530;
305 				imsg_compose(ibuf, IMSG_LKA_RCPT, 0, 0,
306 				    -1, ss, sizeof(*ss));
307 				break;
308 			}
309 
310 			lka_expand_rcpt(env, &lkasession->aliaseslist, lkasession);
311 
312 			break;
313 		}
314 		default:
315 			log_warnx("lka_dispatch_mfa: got imsg %d",
316 			    imsg.hdr.type);
317 			fatalx("lka_dispatch_mfa: unexpected imsg");
318 		}
319 		imsg_free(&imsg);
320 	}
321 	imsg_event_add(ibuf);
322 }
323 
324 void
325 lka_dispatch_mta(int sig, short event, void *p)
326 {
327 	struct smtpd		*env = p;
328 	struct imsgbuf		*ibuf;
329 	struct imsg		 imsg;
330 	ssize_t			 n;
331 
332 	ibuf = env->sc_ibufs[PROC_MTA];
333 	switch (event) {
334 	case EV_READ:
335 		if ((n = imsg_read(ibuf)) == -1)
336 			fatal("imsg_read_error");
337 		if (n == 0) {
338 			/* this pipe is dead, so remove the event handler */
339 			event_del(&ibuf->ev);
340 			event_loopexit(NULL);
341 			return;
342 		}
343 		break;
344 	case EV_WRITE:
345 		if (msgbuf_write(&ibuf->w) == -1)
346 			fatal("msgbuf_write");
347 		imsg_event_add(ibuf);
348 		return;
349 	default:
350 		fatalx("unknown event");
351 	}
352 
353 	for (;;) {
354 		if ((n = imsg_get(ibuf, &imsg)) == -1)
355 			fatal("lka_dispatch_mta: imsg_read error");
356 		if (n == 0)
357 			break;
358 
359 		switch (imsg.hdr.type) {
360 		case IMSG_LKA_MX: {
361 			struct mxreq *mxreq;
362 			struct mxrep mxrep;
363 			struct addrinfo hints, *res, *resp;
364 			char **mx = NULL;
365 			char *lmx[1];
366 			int len, i;
367 			int mxcnt;
368 			int error;
369 			struct mxhost mxhost;
370 			char *secret;
371 
372 			mxreq = imsg.data;
373 			mxrep.id = mxreq->id;
374 			mxrep.getaddrinfo_error = 0;
375 
376 			if (mxreq->rule.r_action == A_RELAY) {
377 				log_debug("attempting to resolve %s", mxreq->hostname);
378 				len = getmxbyname(mxreq->hostname, &mx);
379 				if (len < 0) {
380 					mxrep.getaddrinfo_error = len;
381 					imsg_compose(ibuf, IMSG_LKA_MX_END, 0, 0, -1,
382 					    &mxrep, sizeof(struct mxrep));
383 					break;
384 				}
385 				if (len == 0) {
386 					lmx[0] = mxreq->hostname;
387 					mx = lmx;
388 					len = 1;
389 				}
390 			}
391 			else if (mxreq->rule.r_action == A_RELAYVIA) {
392 				lmx[0] = mxreq->rule.r_value.relayhost.hostname;
393 				log_debug("attempting to resolve %s:%d (forced)", lmx[0],
394 				    ntohs(mxreq->rule.r_value.relayhost.port));
395 				mx = lmx;
396 				len = 1;
397 
398 			}
399 			memset(&hints, 0, sizeof(hints));
400 			hints.ai_family = PF_UNSPEC;
401 			hints.ai_protocol = IPPROTO_TCP;
402 
403 			for (i = 0; i < len; ++i) {
404 
405 				error = getaddrinfo(mx[i], NULL, &hints, &res);
406 				if (error) {
407 					mxrep.getaddrinfo_error = error;
408 					imsg_compose(ibuf, IMSG_LKA_MX_END, 0, 0, -1,
409 					    &mxrep, sizeof(struct mxrep));
410 				}
411 
412 				if (mxreq->rule.r_action == A_RELAYVIA)
413 					mxhost.flags = mxreq->rule.r_value.relayhost.flags;
414 
415 				if (mxhost.flags & F_AUTH) {
416 					secret = map_dblookup(env, "secrets", mx[i]);
417 					if (secret == NULL) {
418 						log_warnx("no credentials for relay through \"%s\"", mx[i]);
419 						freeaddrinfo(res);
420 						continue;
421 					}
422 				}
423 				if (secret)
424 					lka_encode_credentials(mxhost.credentials, secret);
425 
426 				for (resp = res; resp != NULL && mxcnt < MAX_MX_COUNT; resp = resp->ai_next) {
427 
428 					if (resp->ai_family == PF_INET) {
429 						struct sockaddr_in *ssin;
430 
431 						mxhost.ss = *(struct sockaddr_storage *)resp->ai_addr;
432 
433 						ssin = (struct sockaddr_in *)&mxhost.ss;
434 						if (mxreq->rule.r_value.relayhost.port != 0) {
435 							ssin->sin_port = mxreq->rule.r_value.relayhost.port;
436 							mxrep.mxhost = mxhost;
437 							imsg_compose(ibuf, IMSG_LKA_MX, 0, 0, -1, &mxrep,
438 							    sizeof(struct mxrep));
439 							continue;
440 						}
441 
442 						switch (mxhost.flags & F_SSL) {
443 						case F_SSMTP:
444 							ssin->sin_port = htons(465);
445 							mxrep.mxhost = mxhost;
446 							imsg_compose(ibuf, IMSG_LKA_MX, 0, 0, -1, &mxrep,
447 							    sizeof(struct mxrep));
448 							break;
449 						case F_SSL:
450 							ssin->sin_port = htons(465);
451 							mxrep.mxhost = mxhost;
452 							mxrep.mxhost.flags &= ~F_STARTTLS;
453 							imsg_compose(ibuf, IMSG_LKA_MX, 0, 0, -1, &mxrep,
454 							    sizeof(struct mxrep));
455 						case F_STARTTLS:
456 							ssin->sin_port = htons(25);
457 							mxrep.mxhost = mxhost;
458 							mxrep.mxhost.flags &= ~F_SSMTP;
459 							imsg_compose(ibuf, IMSG_LKA_MX, 0, 0, -1, &mxrep,
460 							    sizeof(struct mxrep));
461 							break;
462 						default:
463 							ssin->sin_port = htons(25);
464 							mxrep.mxhost = mxhost;
465 							imsg_compose(ibuf, IMSG_LKA_MX, 0, 0, -1, &mxrep,
466 							    sizeof(struct mxrep));
467 						}
468 					}
469 
470 					if (resp->ai_family == PF_INET6) {
471 						struct sockaddr_in6 *ssin6;
472 
473 						mxhost.ss = *(struct sockaddr_storage *)resp->ai_addr;
474 						ssin6 = (struct sockaddr_in6 *)&mxhost.ss;
475 						if (mxreq->rule.r_value.relayhost.port != 0) {
476 							ssin6->sin6_port = mxreq->rule.r_value.relayhost.port;
477 							mxrep.mxhost = mxhost;
478 							imsg_compose(ibuf, IMSG_LKA_MX, 0, 0, -1, &mxrep,
479 							    sizeof(struct mxrep));
480 							continue;
481 						}
482 
483 						switch (mxhost.flags & F_SSL) {
484 						case F_SSMTP:
485 							ssin6->sin6_port = htons(465);
486 							mxrep.mxhost = mxhost;
487 							imsg_compose(ibuf, IMSG_LKA_MX, 0, 0, -1, &mxrep,
488 							    sizeof(struct mxrep));
489 							break;
490 						case F_SSL:
491 							ssin6->sin6_port = htons(465);
492 							mxrep.mxhost = mxhost;
493 							mxrep.mxhost.flags &= ~F_STARTTLS;
494 							imsg_compose(ibuf, IMSG_LKA_MX, 0, 0, -1, &mxrep,
495 							    sizeof(struct mxrep));
496 						case F_STARTTLS:
497 							ssin6->sin6_port = htons(25);
498 							mxrep.mxhost = mxhost;
499 							mxrep.mxhost.flags &= ~F_SSMTP;
500 							imsg_compose(ibuf, IMSG_LKA_MX, 0, 0, -1, &mxrep,
501 							    sizeof(struct mxrep));
502 							break;
503 						default:
504 							ssin6->sin6_port = htons(25);
505 							mxrep.mxhost = mxhost;
506 							imsg_compose(ibuf, IMSG_LKA_MX, 0, 0, -1, &mxrep,
507 							    sizeof(struct mxrep));
508 						}
509 					}
510 				}
511 				freeaddrinfo(res);
512 				free(secret);
513 				bzero(&mxhost.credentials, MAX_LINE_SIZE);
514 			}
515 
516 			mxrep.getaddrinfo_error = error;
517 
518 			imsg_compose(ibuf, IMSG_LKA_MX_END, 0, 0, -1,
519 			    &mxrep, sizeof(struct mxrep));
520 
521 			if (mx != lmx)
522 				free(mx);
523 
524 			break;
525 		}
526 
527 		default:
528 			log_warnx("lka_dispatch_mta: got imsg %d",
529 			    imsg.hdr.type);
530 			fatalx("lka_dispatch_mta: unexpected imsg");
531 		}
532 		imsg_free(&imsg);
533 	}
534 	imsg_event_add(ibuf);
535 }
536 
537 void
538 lka_dispatch_smtp(int sig, short event, void *p)
539 {
540 	struct smtpd		*env = p;
541 	struct imsgbuf		*ibuf;
542 	struct imsg		 imsg;
543 	ssize_t			 n;
544 
545 	ibuf = env->sc_ibufs[PROC_SMTP];
546 	switch (event) {
547 	case EV_READ:
548 		if ((n = imsg_read(ibuf)) == -1)
549 			fatal("imsg_read_error");
550 		if (n == 0) {
551 			/* this pipe is dead, so remove the event handler */
552 			event_del(&ibuf->ev);
553 			event_loopexit(NULL);
554 			return;
555 		}
556 		break;
557 	case EV_WRITE:
558 		if (msgbuf_write(&ibuf->w) == -1)
559 			fatal("msgbuf_write");
560 		imsg_event_add(ibuf);
561 		return;
562 	default:
563 		fatalx("unknown event");
564 	}
565 
566 	for (;;) {
567 		if ((n = imsg_get(ibuf, &imsg)) == -1)
568 			fatal("lka_dispatch_mfa: imsg_read error");
569 		if (n == 0)
570 			break;
571 
572 		switch (imsg.hdr.type) {
573 		case IMSG_LKA_HOST: {
574 			struct sockaddr *sa;
575 			char addr[NI_MAXHOST];
576 			struct addrinfo hints, *res;
577 			struct session *s;
578 
579 			s = imsg.data;
580 			sa = (struct sockaddr *)&s->s_ss;
581 			if (getnameinfo(sa, sa->sa_len, addr, sizeof(addr),
582 			    NULL, 0, NI_NAMEREQD))
583 				break;
584 
585 			memset(&hints, 0, sizeof(hints));
586 			hints.ai_socktype = SOCK_DGRAM;
587 			hints.ai_flags = AI_NUMERICHOST;
588 			if (getaddrinfo(addr, NULL, &hints, &res) == 0) {
589 				/* Malicious PTR record. */
590 				freeaddrinfo(res);
591 				break;
592 			}
593 
594 			strlcpy(s->s_hostname, addr, sizeof(s->s_hostname));
595 			imsg_compose(ibuf, IMSG_LKA_HOST, 0, 0, -1, s,
596 			    sizeof(struct session));
597 			break;
598 		}
599 		default:
600 			log_warnx("lka_dispatch_smtp: got imsg %d",
601 			    imsg.hdr.type);
602 			fatalx("lka_dispatch_smtp: unexpected imsg");
603 		}
604 		imsg_free(&imsg);
605 	}
606 	imsg_event_add(ibuf);
607 }
608 
609 void
610 lka_dispatch_queue(int sig, short event, void *p)
611 {
612 	struct smtpd		*env = p;
613 	struct imsgbuf		*ibuf;
614 	struct imsg		 imsg;
615 	ssize_t			 n;
616 
617 	ibuf = env->sc_ibufs[PROC_QUEUE];
618 	switch (event) {
619 	case EV_READ:
620 		if ((n = imsg_read(ibuf)) == -1)
621 			fatal("imsg_read_error");
622 		if (n == 0) {
623 			/* this pipe is dead, so remove the event handler */
624 			event_del(&ibuf->ev);
625 			event_loopexit(NULL);
626 			return;
627 		}
628 		break;
629 	case EV_WRITE:
630 		if (msgbuf_write(&ibuf->w) == -1)
631 			fatal("msgbuf_write");
632 		imsg_event_add(ibuf);
633 		return;
634 	default:
635 		fatalx("unknown event");
636 	}
637 
638 	for (;;) {
639 		if ((n = imsg_get(ibuf, &imsg)) == -1)
640 			fatal("lka_dispatch_queue: imsg_read error");
641 		if (n == 0)
642 			break;
643 
644 		switch (imsg.hdr.type) {
645 		default:
646 			log_warnx("lka_dispatch_queue: got imsg %d",
647 			   imsg.hdr.type);
648 			fatalx("lka_dispatch_queue: unexpected imsg");
649 		}
650 		imsg_free(&imsg);
651 	}
652 	imsg_event_add(ibuf);
653 }
654 
655 void
656 lka_dispatch_runner(int sig, short event, void *p)
657 {
658 	struct smtpd		*env = p;
659 	struct imsgbuf		*ibuf;
660 	struct imsg		 imsg;
661 	ssize_t			 n;
662 
663 	ibuf = env->sc_ibufs[PROC_RUNNER];
664 	switch (event) {
665 	case EV_READ:
666 		if ((n = imsg_read(ibuf)) == -1)
667 			fatal("imsg_read_error");
668 		if (n == 0) {
669 			/* this pipe is dead, so remove the event handler */
670 			event_del(&ibuf->ev);
671 			event_loopexit(NULL);
672 			return;
673 		}
674 		break;
675 	case EV_WRITE:
676 		if (msgbuf_write(&ibuf->w) == -1)
677 			fatal("msgbuf_write");
678 		imsg_event_add(ibuf);
679 		return;
680 	default:
681 		fatalx("unknown event");
682 	}
683 
684 	for (;;) {
685 		if ((n = imsg_get(ibuf, &imsg)) == -1)
686 			fatal("lka_dispatch_runner: imsg_read error");
687 		if (n == 0)
688 			break;
689 
690 		switch (imsg.hdr.type) {
691 		default:
692 			log_warnx("lka_dispatch_runner: got imsg %d",
693 			    imsg.hdr.type);
694 			fatalx("lka_dispatch_runner: unexpected imsg");
695 		}
696 		imsg_free(&imsg);
697 	}
698 	imsg_event_add(ibuf);
699 }
700 
701 void
702 lka_shutdown(void)
703 {
704 	log_info("lookup agent exiting");
705 	_exit(0);
706 }
707 
708 void
709 lka_setup_events(struct smtpd *env)
710 {
711 }
712 
713 void
714 lka_disable_events(struct smtpd *env)
715 {
716 }
717 
718 pid_t
719 lka(struct smtpd *env)
720 {
721 	pid_t		 pid;
722 	struct passwd	*pw;
723 
724 	struct event	 ev_sigint;
725 	struct event	 ev_sigterm;
726 
727 	struct peer peers[] = {
728 		{ PROC_PARENT,	lka_dispatch_parent },
729 		{ PROC_MFA,	lka_dispatch_mfa },
730 		{ PROC_QUEUE,	lka_dispatch_queue },
731 		{ PROC_SMTP,	lka_dispatch_smtp },
732 		{ PROC_RUNNER,	lka_dispatch_runner },
733 		{ PROC_MTA,	lka_dispatch_mta }
734 	};
735 
736 	switch (pid = fork()) {
737 	case -1:
738 		fatal("lka: cannot fork");
739 	case 0:
740 		break;
741 	default:
742 		return (pid);
743 	}
744 
745 //	purge_config(env, PURGE_EVERYTHING);
746 
747 	pw = env->sc_pw;
748 
749 	setproctitle("lookup agent");
750 	smtpd_process = PROC_LKA;
751 
752 #ifndef DEBUG
753 	if (setgroups(1, &pw->pw_gid) ||
754 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
755 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
756 		fatal("lka: cannot drop privileges");
757 #endif
758 
759 	event_init();
760 	SPLAY_INIT(&env->lka_sessions);
761 
762 	signal_set(&ev_sigint, SIGINT, lka_sig_handler, env);
763 	signal_set(&ev_sigterm, SIGTERM, lka_sig_handler, env);
764 	signal_add(&ev_sigint, NULL);
765 	signal_add(&ev_sigterm, NULL);
766 	signal(SIGPIPE, SIG_IGN);
767 	signal(SIGHUP, SIG_IGN);
768 
769 	config_pipes(env, peers, 6);
770 	config_peers(env, peers, 6);
771 
772 	lka_setup_events(env);
773 	event_dispatch();
774 	lka_shutdown();
775 
776 	return (0);
777 }
778 
779 int
780 lka_verify_mail(struct smtpd *env, struct path *path)
781 {
782 	struct rule *r;
783 	struct cond *cond;
784 	struct map *map;
785 	struct mapel *me;
786 
787 	TAILQ_FOREACH(r, env->sc_rules, r_entry) {
788 		TAILQ_FOREACH(cond, &r->r_conditions, c_entry) {
789 			if (cond->c_type == C_ALL) {
790 				path->rule = *r;
791 				if (r->r_action == A_MBOX ||
792 				    r->r_action == A_MAILDIR) {
793 					return lka_resolve_mail(env, r, path);
794 				}
795 				return 1;
796 			}
797 
798 			if (cond->c_type == C_DOM) {
799 				cond->c_match = map_find(env, cond->c_map);
800 				if (cond->c_match == NULL)
801 					fatal("lka failed to lookup map.");
802 
803 				map = cond->c_match;
804 				TAILQ_FOREACH(me, &map->m_contents, me_entry) {
805 					if (hostname_match(path->domain, me->me_key.med_string)) {
806 						path->rule = *r;
807 						if (r->r_action == A_MBOX ||
808 						    r->r_action == A_MAILDIR ||
809 						    r->r_action == A_EXT) {
810 							return lka_resolve_mail(env, r, path);
811 						}
812 						return 1;
813 					}
814 				}
815 			}
816 		}
817 	}
818 	path->rule.r_action = A_RELAY;
819 	return 1;
820 }
821 
822 int
823 lka_resolve_mail(struct smtpd *env, struct rule *rule, struct path *path)
824 {
825 	char username[MAXLOGNAME];
826 	struct passwd *pw;
827 	char *p;
828 
829 	(void)strlcpy(username, path->user, sizeof(username));
830 
831 	for (p = &username[0]; *p != '\0' && *p != '+'; ++p)
832 		*p = tolower((int)*p);
833 	*p = '\0';
834 
835 	if (aliases_virtual_exist(env, path))
836 		path->flags |= F_VIRTUAL;
837 	else if (aliases_exist(env, username))
838 		path->flags |= F_ALIAS;
839 	else {
840 		pw = safe_getpwnam(username);
841 		if (pw == NULL)
842 			return 0;
843 		(void)strlcpy(path->pw_name, pw->pw_name,
844 		    sizeof(path->pw_name));
845 		if (lka_expand(path->rule.r_value.path,
846 		    sizeof(path->rule.r_value.path), path) >=
847 		    sizeof(path->rule.r_value.path))
848 			return 0;
849 	}
850 
851 	return 1;
852 }
853 
854 size_t
855 lka_expand(char *buf, size_t len, struct path *path)
856 {
857 	char *p, *pbuf;
858 	struct rule r;
859 	size_t ret;
860 	struct passwd *pw;
861 
862 	bzero(r.r_value.path, MAXPATHLEN);
863 	pbuf = r.r_value.path;
864 
865 	ret = 0;
866 	for (p = path->rule.r_value.path; *p != '\0'; ++p) {
867 		if (p == path->rule.r_value.path && *p == '~') {
868 			if (*(p + 1) == '/' || *(p + 1) == '\0') {
869 				pw = safe_getpwnam(path->pw_name);
870 				if (pw == NULL)
871 					continue;
872 
873 				ret += strlcat(pbuf, pw->pw_dir, len);
874 				if (ret >= len)
875 					return ret;
876 				pbuf += strlen(pw->pw_dir);
877 				continue;
878 			}
879 
880 			if (*(p + 1) != '/') {
881 				char username[MAXLOGNAME];
882 				char *delim;
883 
884 				ret = strlcpy(username, p + 1,
885 				    sizeof(username));
886 				delim = strchr(username, '/');
887 				if (delim == NULL && ret >= sizeof(username)) {
888 					continue;
889 				}
890 
891 				if (delim != NULL) {
892 					*delim = '\0';
893 				}
894 
895 				pw = safe_getpwnam(username);
896 				if (pw == NULL)
897 					continue;
898 
899 				ret += strlcat(pbuf, pw->pw_dir, len);
900 				if (ret >= len)
901 					return ret;
902 				pbuf += strlen(pw->pw_dir);
903 				p += strlen(username);
904 				continue;
905 			}
906 		}
907 		if (strncmp(p, "%a", 2) == 0) {
908 			ret += strlcat(pbuf, path->user, len);
909 			if (ret >= len)
910 				return ret;
911 			pbuf += strlen(path->user);
912 			++p;
913 			continue;
914 		}
915 		if (strncmp(p, "%u", 2) == 0) {
916 			ret += strlcat(pbuf, path->pw_name, len);
917 			if (ret >= len)
918 				return ret;
919 			pbuf += strlen(path->pw_name);
920 			++p;
921 			continue;
922 		}
923 		if (strncmp(p, "%d", 2) == 0) {
924 			ret += strlcat(pbuf, path->domain, len);
925 			if (ret >= len)
926 				return ret;
927 			pbuf += strlen(path->domain);
928 			++p;
929 			continue;
930 		}
931 		if (*p == '%' && isdigit((int)*(p+1)) && *(p+2) == 'a') {
932 			size_t idx;
933 
934 			idx = *(p+1) - '0';
935 			if (idx < strlen(path->user))
936 				*pbuf++ = path->user[idx];
937 			p+=2;
938 			++ret;
939 			continue;
940 		}
941 		if (*p == '%' && isdigit((int)*(p+1)) && *(p+2) == 'u') {
942 			size_t idx;
943 
944 			idx = *(p+1) - '0';
945 			if (idx < strlen(path->pw_name))
946 				*pbuf++ = path->pw_name[idx];
947 			p+=2;
948 			++ret;
949 			continue;
950 		}
951 		if (*p == '%' && isdigit((int)*(p+1)) && *(p+2) == 'd') {
952 			size_t idx;
953 
954 			idx = *(p+1) - '0';
955 			if (idx < strlen(path->domain))
956 				*pbuf++ = path->domain[idx];
957 			p+=2;
958 			++ret;
959 			continue;
960 		}
961 
962 		*pbuf++ = *p;
963 		++ret;
964 	}
965 
966 	memcpy(path->rule.r_value.path, r.r_value.path, ret);
967 
968 	return ret;
969 }
970 
971 int
972 lka_resolve_alias(struct smtpd *env, struct path *path, struct alias *alias)
973 {
974 	switch (alias->type) {
975 	case ALIAS_USERNAME:
976 		log_debug("USERNAME: %s", alias->u.username);
977 		if (strlcpy(path->pw_name, alias->u.username,
978 			sizeof(path->pw_name)) >= sizeof(path->pw_name))
979 			return 0;
980 		if (path->user[0] == '\0') {
981 			if (strlcpy(path->user, alias->u.username,
982 				sizeof(path->user)) >= sizeof(path->user))
983 				return 0;
984 		}
985 		if (path->domain[0] == '\0') {
986 			if (strlcpy(path->domain, env->sc_hostname,
987 				sizeof(path->domain)) >= sizeof(path->domain))
988 				return 0;
989 		}
990 		break;
991 
992 	case ALIAS_FILENAME:
993 		log_debug("FILENAME: %s", alias->u.filename);
994 		path->rule.r_action = A_FILENAME;
995 		strlcpy(path->u.filename, alias->u.filename,
996 		    sizeof(path->u.filename));
997 		break;
998 
999 	case ALIAS_FILTER:
1000 		log_debug("FILTER: %s", alias->u.filter);
1001 		path->rule.r_action = A_EXT;
1002 		strlcpy(path->rule.r_value.command, alias->u.filter + 2,
1003 		    sizeof(path->rule.r_value.command));
1004 		path->rule.r_value.command[strlen(path->rule.r_value.command) - 1] = '\0';
1005 		break;
1006 
1007 	case ALIAS_ADDRESS:
1008 		log_debug("ADDRESS: %s@%s", alias->u.path.user, alias->u.path.domain);
1009 		*path = alias->u.path;
1010 		break;
1011 	case ALIAS_INCLUDE:
1012 		fatalx("lka_resolve_alias: unexpected type");
1013 		break;
1014 	}
1015 	return 1;
1016 }
1017 
1018 void
1019 lka_expand_rcpt(struct smtpd *env, struct aliaseslist *aliases, struct lkasession *lkasession)
1020 {
1021 	int	ret;
1022 	struct alias	*alias;
1023 	struct message	message;
1024 
1025 	ret = 0;
1026 	while (! (lkasession->flags & F_ERROR) &&
1027 	    ! lkasession->pending && lkasession->iterations < 5) {
1028 		++lkasession->iterations;
1029 		ret = lka_expand_rcpt_iteration(env, &lkasession->aliaseslist, lkasession);
1030 		if (ret == -1) {
1031 			lkasession->ss.code = 530;
1032 			lkasession->flags |= F_ERROR;
1033 		}
1034 
1035 		if (lkasession->pending || ret <= 0)
1036 			break;
1037 	}
1038 
1039 	if (lkasession->pending)
1040 		return;
1041 
1042 	if (lkasession->flags & F_ERROR) {
1043 		lka_clear_aliaseslist(&lkasession->aliaseslist);
1044 		imsg_compose(env->sc_ibufs[PROC_MFA], IMSG_LKA_RCPT, 0, 0,
1045 		    -1, &lkasession->ss, sizeof(struct submit_status));
1046 	}
1047 	else if (TAILQ_FIRST(&lkasession->aliaseslist) == NULL) {
1048 		message = lkasession->message;
1049 		message.recipient = lkasession->path;
1050 		imsg_compose(env->sc_ibufs[PROC_QUEUE],
1051 		    IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1,
1052 		    &message, sizeof(struct message));
1053 		imsg_compose(env->sc_ibufs[PROC_QUEUE],
1054 		    IMSG_QUEUE_COMMIT_ENVELOPES, 0, 0, -1,
1055 		    &message, sizeof(struct message));
1056 	}
1057 	else {
1058 		log_debug("a list of aliases is available");
1059 		message = lkasession->message;
1060 		while ((alias = TAILQ_FIRST(&lkasession->aliaseslist)) != NULL) {
1061 			bzero(&message.recipient, sizeof(struct path));
1062 
1063 			lka_resolve_alias(env, &message.recipient, alias);
1064 			lka_rcpt_action(env, &message.recipient);
1065 
1066 			imsg_compose(env->sc_ibufs[PROC_QUEUE],
1067 			    IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1,
1068 			    &message, sizeof(struct message));
1069 
1070 			TAILQ_REMOVE(&lkasession->aliaseslist, alias, entry);
1071 			free(alias);
1072 		}
1073 		imsg_compose(env->sc_ibufs[PROC_QUEUE],
1074 		    IMSG_QUEUE_COMMIT_ENVELOPES, 0, 0, -1, &message,
1075 		    sizeof(struct message));
1076 	}
1077 	SPLAY_REMOVE(lkatree, &env->lka_sessions, lkasession);
1078 	free(lkasession);
1079 }
1080 
1081 int
1082 lka_expand_rcpt_iteration(struct smtpd *env, struct aliaseslist *aliases, struct lkasession *lkasession)
1083 {
1084 	u_int8_t done = 1;
1085 	struct alias *rmalias = NULL;
1086 	struct alias *alias;
1087 	struct forward_req fwreq;
1088 
1089 	rmalias = NULL;
1090 	TAILQ_FOREACH(alias, aliases, entry) {
1091 		if (rmalias) {
1092 			TAILQ_REMOVE(aliases, rmalias, entry);
1093 			free(rmalias);
1094 			rmalias = NULL;
1095 		}
1096 
1097 		if (alias->type == ALIAS_ADDRESS) {
1098 			if (aliases_virtual_get(env, aliases, &alias->u.path)) {
1099 				rmalias = alias;
1100 				done = 0;
1101 			}
1102 		}
1103 
1104 		else if (alias->type == ALIAS_USERNAME) {
1105 			if (aliases_get(env, aliases, alias->u.username)) {
1106 				done = 0;
1107 				rmalias = alias;
1108 			}
1109 			else {
1110 				done = 0;
1111 				fwreq.id = lkasession->id;
1112 				(void)strlcpy(fwreq.pw_name, alias->u.username, sizeof(fwreq.pw_name));
1113 				imsg_compose(env->sc_ibufs[PROC_PARENT], IMSG_PARENT_FORWARD_OPEN, 0, 0, -1,
1114 				    &fwreq, sizeof(fwreq));
1115 				++lkasession->pending;
1116 				rmalias = alias;
1117 			}
1118 		}
1119 	}
1120 	if (rmalias) {
1121 		TAILQ_REMOVE(aliases, rmalias, entry);
1122 		free(rmalias);
1123 		rmalias = NULL;
1124 	}
1125 
1126 	if (!done && lkasession->iterations == 5)
1127 		return -1;
1128 
1129 	if (TAILQ_FIRST(aliases) == NULL)
1130 		return 0;
1131 
1132 	return 1;
1133 }
1134 
1135 int
1136 lka_resolve_path(struct smtpd *env, struct path *path)
1137 {
1138 	char username[MAXLOGNAME];
1139 	struct passwd *pw;
1140 	char *p;
1141 
1142 	(void)strlcpy(username, path->user, sizeof(username));
1143 
1144 	for (p = &username[0]; *p != '\0' && *p != '+'; ++p)
1145 		*p = tolower((int)*p);
1146 	*p = '\0';
1147 
1148 	if (aliases_virtual_exist(env, path))
1149 		path->flags |= F_VIRTUAL;
1150 	else if (aliases_exist(env, username))
1151 		path->flags |= F_ALIAS;
1152 	else {
1153 		path->flags |= F_ACCOUNT;
1154 		pw = safe_getpwnam(username);
1155 		if (pw == NULL)
1156 			return 0;
1157 		(void)strlcpy(path->pw_name, pw->pw_name,
1158 		    sizeof(path->pw_name));
1159 		if (lka_expand(path->rule.r_value.path,
1160 		    sizeof(path->rule.r_value.path), path) >=
1161 		    sizeof(path->rule.r_value.path))
1162 			return 0;
1163 	}
1164 
1165 	return 1;
1166 }
1167 
1168 void
1169 lka_rcpt_action(struct smtpd *env, struct path *path)
1170 {
1171 	struct rule *r;
1172 	struct cond *cond;
1173 	struct map *map;
1174 	struct mapel *me;
1175 
1176 	if (path->domain[0] == '\0')
1177 		(void)strlcpy(path->domain, "localhost", sizeof (path->domain));
1178 
1179 	TAILQ_FOREACH(r, env->sc_rules, r_entry) {
1180 
1181 		TAILQ_FOREACH(cond, &r->r_conditions, c_entry) {
1182 			if (cond->c_type == C_ALL) {
1183 				path->rule = *r;
1184 				return;
1185 			}
1186 
1187 			if (cond->c_type == C_DOM) {
1188 				cond->c_match = map_find(env, cond->c_map);
1189 				if (cond->c_match == NULL)
1190 					fatal("mfa failed to lookup map.");
1191 
1192 				map = cond->c_match;
1193 				TAILQ_FOREACH(me, &map->m_contents, me_entry) {
1194 					log_debug("trying to match [%s] with [%s]",
1195 					    path->domain, me->me_key.med_string);
1196 					if (hostname_match(path->domain, me->me_key.med_string)) {
1197 						path->rule = *r;
1198 						return;
1199 					}
1200 				}
1201 			}
1202 		}
1203 	}
1204 	path->rule.r_action = A_RELAY;
1205 	return;
1206 }
1207 
1208 int
1209 lkasession_cmp(struct lkasession *s1, struct lkasession *s2)
1210 {
1211 	/*
1212 	 * do not return u_int64_t's
1213 	 */
1214 	if (s1->id < s2->id)
1215 		return (-1);
1216 
1217 	if (s1->id > s2->id)
1218 		return (1);
1219 
1220 	return (0);
1221 }
1222 
1223 void
1224 lka_clear_aliaseslist(struct aliaseslist *aliaseslist)
1225 {
1226 	struct alias *alias;
1227 
1228 	while ((alias = TAILQ_FIRST(aliaseslist)) != NULL) {
1229 		TAILQ_REMOVE(aliaseslist, alias, entry);
1230 		free(alias);
1231 	}
1232 }
1233 
1234 int
1235 lka_encode_credentials(char *dest, char *src)
1236 {
1237 	size_t len;
1238 	char buffer[MAX_LINE_SIZE];
1239 	size_t i;
1240 
1241 	len = strlen(src) + 1;
1242 	if (len < 1)
1243 		return 0;
1244 
1245 	bzero(buffer, sizeof (buffer));
1246 	if (strlcpy(buffer + 1, src, sizeof(buffer) - 1) >=
1247 	    sizeof (buffer) - 1)
1248 		return 0;
1249 
1250 	for (i = 0; i < len; ++i) {
1251 		if (buffer[i] == ':') {
1252 			buffer[i] = '\0';
1253 			break;
1254 		}
1255 	}
1256 	if (kn_encode_base64(buffer, len, dest, MAX_LINE_SIZE - 1) == -1)
1257 		return 0;
1258 	return 1;
1259 }
1260 
1261 SPLAY_GENERATE(lkatree, lkasession, nodes, lkasession_cmp);
1262