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