1 /* $OpenBSD: smtp.c,v 1.102 2012/06/01 14:55:09 eric Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.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/types.h> 22 #include <sys/queue.h> 23 #include <sys/tree.h> 24 #include <sys/param.h> 25 #include <sys/socket.h> 26 27 #include <err.h> 28 #include <errno.h> 29 #include <event.h> 30 #include <imsg.h> 31 #include <netdb.h> 32 #include <pwd.h> 33 #include <signal.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <unistd.h> 38 39 #include "smtpd.h" 40 #include "log.h" 41 42 static void smtp_imsg(struct imsgev *, struct imsg *); 43 static void smtp_shutdown(void); 44 static void smtp_sig_handler(int, short, void *); 45 static void smtp_setup_events(void); 46 static void smtp_pause(void); 47 static int smtp_enqueue(uid_t *); 48 static void smtp_accept(int, short, void *); 49 static struct session *smtp_new(struct listener *); 50 static struct session *session_lookup(u_int64_t); 51 52 53 static void 54 smtp_imsg(struct imsgev *iev, struct imsg *imsg) 55 { 56 struct session skey; 57 struct submit_status *ss; 58 struct listener *l; 59 struct session *s; 60 struct auth *auth; 61 struct ssl *ssl; 62 struct dns *dns; 63 64 log_imsg(PROC_SMTP, iev->proc, imsg); 65 66 if (iev->proc == PROC_LKA) { 67 switch (imsg->hdr.type) { 68 case IMSG_DNS_PTR: 69 dns = imsg->data; 70 s = session_lookup(dns->id); 71 if (s == NULL) 72 fatalx("smtp: impossible quit"); 73 strlcpy(s->s_hostname, 74 dns->error ? "<unknown>" : dns->host, 75 sizeof s->s_hostname); 76 strlcpy(s->s_msg.hostname, s->s_hostname, 77 sizeof s->s_msg.hostname); 78 session_pickup(s, NULL); 79 return; 80 } 81 } 82 83 if (iev->proc == PROC_MFA) { 84 switch (imsg->hdr.type) { 85 case IMSG_MFA_CONNECT: 86 case IMSG_MFA_HELO: 87 case IMSG_MFA_MAIL: 88 case IMSG_MFA_RCPT: 89 case IMSG_MFA_DATALINE: 90 case IMSG_MFA_QUIT: 91 case IMSG_MFA_RSET: 92 ss = imsg->data; 93 s = session_lookup(ss->id); 94 if (s == NULL) 95 return; 96 session_pickup(s, ss); 97 return; 98 case IMSG_MFA_CLOSE: 99 return; 100 } 101 } 102 103 if (iev->proc == PROC_QUEUE) { 104 ss = imsg->data; 105 106 switch (imsg->hdr.type) { 107 case IMSG_QUEUE_CREATE_MESSAGE: 108 s = session_lookup(ss->id); 109 if (s == NULL) 110 return; 111 s->s_msg.id = ((u_int64_t)ss->u.msgid) << 32; 112 session_pickup(s, ss); 113 return; 114 115 case IMSG_QUEUE_MESSAGE_FILE: 116 s = session_lookup(ss->id); 117 if (s == NULL) { 118 close(imsg->fd); 119 return; 120 } 121 s->datafp = fdopen(imsg->fd, "w"); 122 if (s->datafp == NULL) { 123 /* queue may have experienced tempfail. */ 124 if (ss->code != 421) 125 fatalx("smtp: fdopen"); 126 close(imsg->fd); 127 } 128 session_pickup(s, ss); 129 return; 130 131 case IMSG_QUEUE_TEMPFAIL: 132 skey.s_id = ss->id; 133 /* do not use lookup since this is not a expected imsg -- eric@ */ 134 s = SPLAY_FIND(sessiontree, &env->sc_sessions, &skey); 135 if (s == NULL) 136 fatalx("smtp: session is gone"); 137 s->s_dstatus |= DS_TEMPFAILURE; 138 return; 139 140 case IMSG_QUEUE_COMMIT_ENVELOPES: 141 s = session_lookup(ss->id); 142 if (s == NULL) 143 return; 144 session_pickup(s, ss); 145 return; 146 147 case IMSG_QUEUE_COMMIT_MESSAGE: 148 s = session_lookup(ss->id); 149 if (s == NULL) 150 return; 151 session_pickup(s, ss); 152 return; 153 154 case IMSG_SMTP_ENQUEUE: 155 imsg_compose_event(iev, IMSG_SMTP_ENQUEUE, 0, 0, 156 smtp_enqueue(NULL), imsg->data, 157 sizeof(struct envelope)); 158 return; 159 } 160 } 161 162 if (iev->proc == PROC_PARENT) { 163 switch (imsg->hdr.type) { 164 165 case IMSG_CONF_START: 166 if (env->sc_flags & SMTPD_CONFIGURING) 167 return; 168 env->sc_flags |= SMTPD_CONFIGURING; 169 env->sc_listeners = calloc(1, sizeof *env->sc_listeners); 170 env->sc_ssl = calloc(1, sizeof *env->sc_ssl); 171 if (env->sc_listeners == NULL || env->sc_ssl == NULL) 172 fatal(NULL); 173 TAILQ_INIT(env->sc_listeners); 174 return; 175 176 case IMSG_CONF_SSL: 177 if (!(env->sc_flags & SMTPD_CONFIGURING)) 178 return; 179 ssl = calloc(1, sizeof *ssl); 180 if (ssl == NULL) 181 fatal(NULL); 182 *ssl = *(struct ssl *)imsg->data; 183 ssl->ssl_cert = strdup((char *)imsg->data + 184 sizeof *ssl); 185 if (ssl->ssl_cert == NULL) 186 fatal(NULL); 187 ssl->ssl_key = strdup((char *)imsg->data + sizeof *ssl + 188 ssl->ssl_cert_len); 189 if (ssl->ssl_key == NULL) 190 fatal(NULL); 191 if (ssl->ssl_dhparams_len) { 192 ssl->ssl_dhparams = strdup((char *)imsg->data 193 + sizeof *ssl + ssl->ssl_cert_len + 194 ssl->ssl_key_len); 195 if (ssl->ssl_dhparams == NULL) 196 fatal(NULL); 197 } 198 if (ssl->ssl_ca_len) { 199 ssl->ssl_ca = strdup((char *)imsg->data 200 + sizeof *ssl + ssl->ssl_cert_len + 201 ssl->ssl_key_len + ssl->ssl_dhparams_len); 202 if (ssl->ssl_ca == NULL) 203 fatal(NULL); 204 } 205 206 SPLAY_INSERT(ssltree, env->sc_ssl, ssl); 207 return; 208 209 case IMSG_CONF_LISTENER: 210 if (!(env->sc_flags & SMTPD_CONFIGURING)) 211 return; 212 l = calloc(1, sizeof *l); 213 if (l == NULL) 214 fatal(NULL); 215 *l = *(struct listener *)imsg->data; 216 l->fd = imsg->fd; 217 if (l->fd < 0) 218 fatalx("smtp: listener pass failed"); 219 if (l->flags & F_SSL) { 220 struct ssl key; 221 222 strlcpy(key.ssl_name, l->ssl_cert_name, 223 sizeof key.ssl_name); 224 l->ssl = SPLAY_FIND(ssltree, env->sc_ssl, &key); 225 if (l->ssl == NULL) 226 fatalx("smtp: ssltree out of sync"); 227 } 228 TAILQ_INSERT_TAIL(env->sc_listeners, l, entry); 229 return; 230 231 case IMSG_CONF_END: 232 if (!(env->sc_flags & SMTPD_CONFIGURING)) 233 return; 234 smtp_setup_events(); 235 if (env->sc_flags & SMTPD_SMTP_PAUSED) 236 smtp_pause(); 237 env->sc_flags &= ~SMTPD_CONFIGURING; 238 return; 239 240 case IMSG_PARENT_AUTHENTICATE: 241 auth = imsg->data; 242 s = session_lookup(auth->id); 243 if (s == NULL) 244 return; 245 if (auth->success) { 246 s->s_flags |= F_AUTHENTICATED; 247 s->s_msg.flags |= DF_AUTHENTICATED; 248 } else { 249 s->s_flags &= ~F_AUTHENTICATED; 250 s->s_msg.flags &= ~DF_AUTHENTICATED; 251 } 252 session_pickup(s, NULL); 253 return; 254 255 case IMSG_CTL_VERBOSE: 256 log_verbose(*(int *)imsg->data); 257 return; 258 } 259 } 260 261 if (iev->proc == PROC_CONTROL) { 262 switch (imsg->hdr.type) { 263 case IMSG_SMTP_ENQUEUE: 264 imsg_compose_event(iev, IMSG_SMTP_ENQUEUE, 265 imsg->hdr.peerid, 0, smtp_enqueue(imsg->data), 266 NULL, 0); 267 return; 268 269 case IMSG_SMTP_PAUSE: 270 smtp_pause(); 271 return; 272 273 case IMSG_SMTP_RESUME: 274 smtp_resume(); 275 return; 276 } 277 } 278 279 errx(1, "smtp_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); 280 } 281 282 static void 283 smtp_sig_handler(int sig, short event, void *p) 284 { 285 switch (sig) { 286 case SIGINT: 287 case SIGTERM: 288 smtp_shutdown(); 289 break; 290 default: 291 fatalx("smtp_sig_handler: unexpected signal"); 292 } 293 } 294 295 static void 296 smtp_shutdown(void) 297 { 298 log_info("smtp server exiting"); 299 _exit(0); 300 } 301 302 pid_t 303 smtp(void) 304 { 305 pid_t pid; 306 struct passwd *pw; 307 308 struct event ev_sigint; 309 struct event ev_sigterm; 310 311 struct peer peers[] = { 312 { PROC_PARENT, imsg_dispatch }, 313 { PROC_MFA, imsg_dispatch }, 314 { PROC_QUEUE, imsg_dispatch }, 315 { PROC_LKA, imsg_dispatch }, 316 { PROC_CONTROL, imsg_dispatch } 317 }; 318 319 switch (pid = fork()) { 320 case -1: 321 fatal("smtp: cannot fork"); 322 case 0: 323 break; 324 default: 325 return (pid); 326 } 327 328 ssl_init(); 329 purge_config(PURGE_EVERYTHING); 330 331 pw = env->sc_pw; 332 333 if (chroot(pw->pw_dir) == -1) 334 fatal("smtp: chroot"); 335 if (chdir("/") == -1) 336 fatal("smtp: chdir(\"/\")"); 337 338 smtpd_process = PROC_SMTP; 339 setproctitle("%s", env->sc_title[smtpd_process]); 340 341 if (setgroups(1, &pw->pw_gid) || 342 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 343 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 344 fatal("smtp: cannot drop privileges"); 345 346 imsg_callback = smtp_imsg; 347 event_init(); 348 349 signal_set(&ev_sigint, SIGINT, smtp_sig_handler, NULL); 350 signal_set(&ev_sigterm, SIGTERM, smtp_sig_handler, NULL); 351 signal_add(&ev_sigint, NULL); 352 signal_add(&ev_sigterm, NULL); 353 signal(SIGPIPE, SIG_IGN); 354 signal(SIGHUP, SIG_IGN); 355 356 /* Initial limit for use by IMSG_SMTP_ENQUEUE, will be tuned later once 357 * the listening sockets arrive. */ 358 env->sc_maxconn = availdesc() / 2; 359 360 config_pipes(peers, nitems(peers)); 361 config_peers(peers, nitems(peers)); 362 363 if (event_dispatch() < 0) 364 fatal("event_dispatch"); 365 smtp_shutdown(); 366 367 return (0); 368 } 369 370 static void 371 smtp_setup_events(void) 372 { 373 struct listener *l; 374 int avail = availdesc(); 375 376 TAILQ_FOREACH(l, env->sc_listeners, entry) { 377 log_debug("smtp: listen on %s port %d flags 0x%01x" 378 " cert \"%s\"", ss_to_text(&l->ss), ntohs(l->port), 379 l->flags, l->ssl_cert_name); 380 381 session_socket_blockmode(l->fd, BM_NONBLOCK); 382 if (listen(l->fd, SMTPD_BACKLOG) == -1) 383 fatal("listen"); 384 event_set(&l->ev, l->fd, EV_READ|EV_PERSIST, smtp_accept, l); 385 event_add(&l->ev, NULL); 386 ssl_setup(l); 387 avail--; 388 } 389 390 /* guarantee 2 fds to each accepted client */ 391 if ((env->sc_maxconn = avail / 2) < 1) 392 fatalx("smtp_setup_events: fd starvation"); 393 394 log_debug("smtp: will accept at most %d clients", env->sc_maxconn); 395 } 396 397 static void 398 smtp_pause(void) 399 { 400 struct listener *l; 401 402 log_debug("smtp: pausing listening sockets"); 403 env->sc_flags |= SMTPD_SMTP_PAUSED; 404 405 TAILQ_FOREACH(l, env->sc_listeners, entry) 406 event_del(&l->ev); 407 } 408 409 void 410 smtp_resume(void) 411 { 412 struct listener *l; 413 414 log_debug("smtp: resuming listening sockets"); 415 env->sc_flags &= ~SMTPD_SMTP_PAUSED; 416 417 TAILQ_FOREACH(l, env->sc_listeners, entry) 418 event_add(&l->ev, NULL); 419 } 420 421 static int 422 smtp_enqueue(uid_t *euid) 423 { 424 static struct listener local, *l; 425 static struct sockaddr_storage sa; 426 struct session *s; 427 int fd[2]; 428 429 if (l == NULL) { 430 struct addrinfo hints, *res; 431 432 l = &local; 433 strlcpy(l->tag, "local", sizeof(l->tag)); 434 435 bzero(&hints, sizeof(hints)); 436 hints.ai_family = PF_UNSPEC; 437 hints.ai_flags = AI_NUMERICHOST; 438 439 if (getaddrinfo("::1", NULL, &hints, &res)) 440 fatal("getaddrinfo"); 441 memcpy(&sa, res->ai_addr, res->ai_addrlen); 442 freeaddrinfo(res); 443 } 444 445 /* 446 * Some enqueue requests buffered in IMSG may still arrive even after 447 * call to smtp_pause() because enqueue listener is not a real socket 448 * and thus cannot be paused properly. 449 */ 450 if (env->sc_flags & SMTPD_SMTP_PAUSED) 451 return (-1); 452 453 if ((s = smtp_new(l)) == NULL) 454 return (-1); 455 456 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, fd)) 457 fatal("socketpair"); 458 459 s->s_io.sock = fd[0]; 460 s->s_ss = sa; 461 s->s_msg.flags |= DF_ENQUEUED; 462 463 if (euid) 464 bsnprintf(s->s_hostname, sizeof(s->s_hostname), "%d@localhost", 465 *euid); 466 else { 467 strlcpy(s->s_hostname, "localhost", sizeof(s->s_hostname)); 468 s->s_msg.flags |= DF_BOUNCE; 469 } 470 471 strlcpy(s->s_msg.hostname, s->s_hostname, 472 sizeof(s->s_msg.hostname)); 473 474 session_pickup(s, NULL); 475 476 return (fd[1]); 477 } 478 479 static void 480 smtp_accept(int fd, short event, void *p) 481 { 482 struct listener *l = p; 483 struct session *s; 484 socklen_t len; 485 486 if ((s = smtp_new(l)) == NULL) 487 return; 488 489 len = sizeof(s->s_ss); 490 if ((s->s_io.sock = accept(fd, (struct sockaddr *)&s->s_ss, &len)) == -1) { 491 if (errno == EINTR || errno == ECONNABORTED) 492 return; 493 fatal("smtp_accept"); 494 } 495 496 io_set_timeout(&s->s_io, SMTPD_SESSION_TIMEOUT * 1000); 497 io_set_write(&s->s_io); 498 dns_query_ptr(&s->s_ss, s->s_id); 499 } 500 501 502 static struct session * 503 smtp_new(struct listener *l) 504 { 505 struct session *s; 506 507 log_debug("smtp: new client on listener: %p", l); 508 509 if (env->sc_flags & SMTPD_SMTP_PAUSED) 510 fatalx("smtp_new: unexpected client"); 511 512 if ((s = calloc(1, sizeof(*s))) == NULL) 513 fatal(NULL); 514 s->s_id = generate_uid(); 515 s->s_l = l; 516 strlcpy(s->s_msg.tag, l->tag, sizeof(s->s_msg.tag)); 517 SPLAY_INSERT(sessiontree, &env->sc_sessions, s); 518 519 if (stat_increment(STATS_SMTP_SESSION) >= env->sc_maxconn) { 520 log_warnx("client limit hit, disabling incoming connections"); 521 smtp_pause(); 522 } 523 524 if (s->s_l->ss.ss_family == AF_INET) 525 stat_increment(STATS_SMTP_SESSION_INET4); 526 if (s->s_l->ss.ss_family == AF_INET6) 527 stat_increment(STATS_SMTP_SESSION_INET6); 528 529 iobuf_init(&s->s_iobuf, MAX_LINE_SIZE, MAX_LINE_SIZE); 530 io_init(&s->s_io, -1, s, session_io, &s->s_iobuf); 531 s->s_state = S_CONNECTED; 532 533 return (s); 534 } 535 536 /* 537 * Helper function for handling IMSG replies. 538 */ 539 static struct session * 540 session_lookup(u_int64_t id) 541 { 542 struct session key; 543 struct session *s; 544 545 key.s_id = id; 546 s = SPLAY_FIND(sessiontree, &env->sc_sessions, &key); 547 if (s == NULL) 548 fatalx("session_lookup: session is gone"); 549 550 if (s->s_flags & F_ZOMBIE) { 551 session_destroy(s, "(finalizing)"); 552 s = NULL; 553 } 554 555 return (s); 556 } 557