1 /* $OpenBSD: ssl.c,v 1.11 2009/03/15 19:32:11 gilles Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> 5 * Copyright (c) 2008 Reyk Floeter <reyk@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 #include <sys/stat.h> 26 #include <sys/time.h> 27 28 #include <ctype.h> 29 #include <event.h> 30 #include <fcntl.h> 31 #include <pwd.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <unistd.h> 36 37 #include <openssl/ssl.h> 38 #include <openssl/engine.h> 39 #include <openssl/err.h> 40 41 #include "smtpd.h" 42 43 #define SSL_CIPHERS "HIGH:!ADH" 44 45 void ssl_error(const char *); 46 char *ssl_load_file(const char *, off_t *); 47 SSL_CTX *ssl_ctx_create(void); 48 void ssl_session_accept(int, short, void *); 49 void ssl_read(int, short, void *); 50 void ssl_write(int, short, void *); 51 int ssl_bufferevent_add(struct event *, int); 52 void ssl_connect(int, short, void *); 53 void ssl_client_init(struct session *); 54 55 extern void bufferevent_read_pressure_cb(struct evbuffer *, size_t, 56 size_t, void *); 57 58 extern struct s_session s_smtp; 59 60 void 61 ssl_connect(int fd, short event, void *p) 62 { 63 struct session *s = p; 64 int ret; 65 int retry_flag; 66 int ssl_err; 67 68 if (event == EV_TIMEOUT) { 69 log_debug("ssl_session_accept: session timed out"); 70 session_destroy(s); 71 return; 72 } 73 74 ret = SSL_connect(s->s_ssl); 75 if (ret <= 0) { 76 ssl_err = SSL_get_error(s->s_ssl, ret); 77 78 switch (ssl_err) { 79 case SSL_ERROR_WANT_READ: 80 retry_flag = EV_READ; 81 goto retry; 82 case SSL_ERROR_WANT_WRITE: 83 retry_flag = EV_WRITE; 84 goto retry; 85 case SSL_ERROR_ZERO_RETURN: 86 case SSL_ERROR_SYSCALL: 87 if (ret == 0) { 88 log_debug("session destroy in MTA #1"); 89 session_destroy(s); 90 return; 91 } 92 /* FALLTHROUGH */ 93 default: 94 ssl_error("ssl_session_connect"); 95 session_destroy(s); 96 return; 97 } 98 } 99 100 event_set(&s->s_bev->ev_read, s->s_fd, EV_READ, ssl_read, s->s_bev); 101 event_set(&s->s_bev->ev_write, s->s_fd, EV_WRITE, ssl_write, s->s_bev); 102 103 log_info("ssl_connect: connected to remote ssl server"); 104 bufferevent_enable(s->s_bev, EV_READ|EV_WRITE); 105 s->s_flags |= F_SECURE; 106 107 if (s->s_flags & F_PEERHASTLS) { 108 session_respond(s, "EHLO %s", s->s_env->sc_hostname); 109 } 110 111 return; 112 retry: 113 event_add(&s->s_ev, &s->s_tv); 114 } 115 116 void 117 ssl_read(int fd, short event, void *p) 118 { 119 struct bufferevent *bufev = p; 120 struct session *s = bufev->cbarg; 121 int ret; 122 int ssl_err; 123 short what; 124 size_t len; 125 char rbuf[READ_BUF_SIZE]; 126 int howmuch = READ_BUF_SIZE; 127 128 what = EVBUFFER_READ; 129 ret = ssl_err = 0; 130 131 if (event == EV_TIMEOUT) { 132 what |= EVBUFFER_TIMEOUT; 133 goto err; 134 } 135 136 if (bufev->wm_read.high != 0) 137 howmuch = MIN(sizeof(rbuf), bufev->wm_read.high); 138 139 ret = SSL_read(s->s_ssl, rbuf, howmuch); 140 if (ret <= 0) { 141 ssl_err = SSL_get_error(s->s_ssl, ret); 142 143 switch (ssl_err) { 144 case SSL_ERROR_WANT_READ: 145 goto retry; 146 case SSL_ERROR_WANT_WRITE: 147 goto retry; 148 default: 149 if (ret == 0) 150 what |= EVBUFFER_EOF; 151 else { 152 ssl_error("ssl_read"); 153 what |= EVBUFFER_ERROR; 154 } 155 goto err; 156 } 157 } 158 159 if (evbuffer_add(bufev->input, rbuf, ret) == -1) { 160 what |= EVBUFFER_ERROR; 161 goto err; 162 } 163 164 ssl_bufferevent_add(&bufev->ev_read, bufev->timeout_read); 165 166 len = EVBUFFER_LENGTH(bufev->input); 167 if (bufev->wm_read.low != 0 && len < bufev->wm_read.low) 168 return; 169 if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) { 170 struct evbuffer *buf = bufev->input; 171 event_del(&bufev->ev_read); 172 evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev); 173 return; 174 } 175 176 if (bufev->readcb != NULL) 177 (*bufev->readcb)(bufev, bufev->cbarg); 178 return; 179 180 retry: 181 ssl_bufferevent_add(&bufev->ev_read, bufev->timeout_read); 182 return; 183 184 err: 185 (*bufev->errorcb)(bufev, what, bufev->cbarg); 186 } 187 188 189 void 190 ssl_write(int fd, short event, void *p) 191 { 192 struct bufferevent *bufev = p; 193 struct session *s = bufev->cbarg; 194 int ret; 195 int ssl_err; 196 short what; 197 198 ret = 0; 199 what = EVBUFFER_WRITE; 200 201 if (event == EV_TIMEOUT) { 202 what |= EV_TIMEOUT; 203 goto err; 204 } 205 206 if (EVBUFFER_LENGTH(bufev->output)) { 207 if (s->s_buf == NULL) { 208 s->s_buflen = EVBUFFER_LENGTH(bufev->output); 209 if ((s->s_buf = malloc(s->s_buflen)) == NULL) { 210 what |= EVBUFFER_ERROR; 211 goto err; 212 } 213 memcpy(s->s_buf, EVBUFFER_DATA(bufev->output), 214 s->s_buflen); 215 } 216 217 ret = SSL_write(s->s_ssl, s->s_buf, s->s_buflen); 218 if (ret <= 0) { 219 ssl_err = SSL_get_error(s->s_ssl, ret); 220 221 switch (ssl_err) { 222 case SSL_ERROR_WANT_READ: 223 goto retry; 224 case SSL_ERROR_WANT_WRITE: 225 goto retry; 226 default: 227 if (ret == 0) 228 what |= EVBUFFER_EOF; 229 else { 230 ssl_error("ssl_write"); 231 what |= EVBUFFER_ERROR; 232 } 233 goto err; 234 } 235 } 236 evbuffer_drain(bufev->output, ret); 237 } 238 if (s->s_buf != NULL) { 239 free(s->s_buf); 240 s->s_buf = NULL; 241 s->s_buflen = 0; 242 } 243 if (EVBUFFER_LENGTH(bufev->output) != 0) 244 ssl_bufferevent_add(&bufev->ev_write, bufev->timeout_write); 245 246 if (bufev->writecb != NULL && 247 EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low) 248 (*bufev->writecb)(bufev, bufev->cbarg); 249 return; 250 251 retry: 252 if (s->s_buflen != 0) 253 ssl_bufferevent_add(&bufev->ev_write, bufev->timeout_write); 254 return; 255 256 err: 257 if (s->s_buf != NULL) { 258 free(s->s_buf); 259 s->s_buf = NULL; 260 s->s_buflen = 0; 261 } 262 (*bufev->errorcb)(bufev, what, bufev->cbarg); 263 } 264 265 int 266 ssl_bufferevent_add(struct event *ev, int timeout) 267 { 268 struct timeval tv; 269 struct timeval *ptv = NULL; 270 271 if (timeout) { 272 timerclear(&tv); 273 tv.tv_sec = timeout; 274 ptv = &tv; 275 } 276 277 return (event_add(ev, ptv)); 278 } 279 280 int 281 ssl_cmp(struct ssl *s1, struct ssl *s2) 282 { 283 return (strcmp(s1->ssl_name, s2->ssl_name)); 284 } 285 286 SPLAY_GENERATE(ssltree, ssl, ssl_nodes, ssl_cmp); 287 288 char * 289 ssl_load_file(const char *name, off_t *len) 290 { 291 struct stat st; 292 off_t size; 293 char *buf = NULL; 294 int fd; 295 296 if ((fd = open(name, O_RDONLY)) == -1) 297 return (NULL); 298 if (fstat(fd, &st) != 0) 299 goto fail; 300 size = st.st_size; 301 if ((buf = calloc(1, size + 1)) == NULL) 302 goto fail; 303 if (read(fd, buf, size) != size) 304 goto fail; 305 close(fd); 306 307 *len = size + 1; 308 return (buf); 309 310 fail: 311 if (buf != NULL) 312 free(buf); 313 close(fd); 314 return (NULL); 315 } 316 317 SSL_CTX * 318 ssl_ctx_create(void) 319 { 320 SSL_CTX *ctx; 321 322 ctx = SSL_CTX_new(SSLv23_method()); 323 if (ctx == NULL) { 324 ssl_error("ssl_ctx_create"); 325 fatal("ssl_ctx_create: could not create SSL context"); 326 } 327 328 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); 329 SSL_CTX_set_timeout(ctx, SMTPD_SESSION_TIMEOUT); 330 SSL_CTX_set_options(ctx, SSL_OP_ALL); 331 SSL_CTX_set_options(ctx, 332 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); 333 334 if (!SSL_CTX_set_cipher_list(ctx, SSL_CIPHERS)) { 335 ssl_error("ssl_ctx_create"); 336 fatal("ssl_ctx_create: could not set cipher list"); 337 } 338 return (ctx); 339 } 340 341 int 342 ssl_load_certfile(struct smtpd *env, const char *name) 343 { 344 struct ssl *s; 345 struct ssl key; 346 char certfile[PATH_MAX]; 347 348 if (strlcpy(key.ssl_name, name, sizeof(key.ssl_name)) 349 >= sizeof(key.ssl_name)) { 350 log_warn("ssl_load_certfile: certificate name truncated"); 351 return -1; 352 } 353 354 s = SPLAY_FIND(ssltree, &env->sc_ssl, &key); 355 if (s != NULL) 356 return 0; 357 358 if ((s = calloc(1, sizeof(*s))) == NULL) 359 fatal(NULL); 360 361 (void)strlcpy(s->ssl_name, key.ssl_name, sizeof(s->ssl_name)); 362 363 if (! bsnprintf(certfile, sizeof(certfile), 364 "/etc/mail/certs/%s.crt", name)) { 365 free(s); 366 return (-1); 367 } 368 369 if ((s->ssl_cert = ssl_load_file(certfile, &s->ssl_cert_len)) == NULL) { 370 free(s); 371 return (-1); 372 } 373 374 if (! bsnprintf(certfile, sizeof(certfile), 375 "/etc/mail/certs/%s.key", name)) { 376 free(s->ssl_cert); 377 free(s); 378 return -1; 379 } 380 381 if ((s->ssl_key = ssl_load_file(certfile, &s->ssl_key_len)) == NULL) { 382 free(s->ssl_cert); 383 free(s); 384 return (-1); 385 } 386 387 if (s->ssl_cert == NULL || s->ssl_key == NULL) 388 fatal("invalid certificates"); 389 390 SPLAY_INSERT(ssltree, &env->sc_ssl, s); 391 392 return (0); 393 } 394 395 void 396 ssl_init(void) 397 { 398 SSL_library_init(); 399 SSL_load_error_strings(); 400 401 OpenSSL_add_all_algorithms(); 402 403 /* Init hardware crypto engines. */ 404 ENGINE_load_builtin_engines(); 405 ENGINE_register_all_complete(); 406 } 407 408 void 409 ssl_setup(struct smtpd *env, struct listener *l) 410 { 411 struct ssl key; 412 413 if (!(l->flags & F_SSL)) 414 return; 415 416 if (strlcpy(key.ssl_name, l->ssl_cert_name, sizeof(key.ssl_name)) 417 >= sizeof(key.ssl_name)) 418 fatal("ssl_setup: certificate name truncated"); 419 420 if ((l->ssl = SPLAY_FIND(ssltree, &env->sc_ssl, &key)) == NULL) 421 fatal("ssl_setup: certificate tree corrupted"); 422 423 l->ssl_ctx = ssl_ctx_create(); 424 425 if (!ssl_ctx_use_certificate_chain(l->ssl_ctx, 426 l->ssl->ssl_cert, l->ssl->ssl_cert_len)) 427 goto err; 428 if (!ssl_ctx_use_private_key(l->ssl_ctx, 429 l->ssl->ssl_key, l->ssl->ssl_key_len)) 430 goto err; 431 432 if (!SSL_CTX_check_private_key(l->ssl_ctx)) 433 goto err; 434 if (!SSL_CTX_set_session_id_context(l->ssl_ctx, 435 (const unsigned char *)l->ssl_cert_name, strlen(l->ssl_cert_name) + 1)) 436 goto err; 437 438 log_debug("ssl_setup: ssl setup finished for listener: %p", l); 439 return; 440 441 err: 442 if (l->ssl_ctx != NULL) 443 SSL_CTX_free(l->ssl_ctx); 444 ssl_error("ssl_setup"); 445 fatal("ssl_setup: cannot set SSL up"); 446 return; 447 } 448 449 void 450 ssl_error(const char *where) 451 { 452 unsigned long code; 453 char errbuf[128]; 454 extern int debug; 455 456 if (!debug) 457 return; 458 for (; (code = ERR_get_error()) != 0 ;) { 459 ERR_error_string_n(code, errbuf, sizeof(errbuf)); 460 log_debug("SSL library error: %s: %s", where, errbuf); 461 } 462 } 463 464 void 465 ssl_session_accept(int fd, short event, void *p) 466 { 467 struct session *s = p; 468 int ret; 469 int retry_flag; 470 int ssl_err; 471 472 if (event == EV_TIMEOUT) { 473 log_debug("ssl_session_accept: session timed out"); 474 session_destroy(s); 475 return; 476 } 477 478 retry_flag = ssl_err = 0; 479 480 log_debug("ssl_session_accept: accepting client"); 481 ret = SSL_accept(s->s_ssl); 482 if (ret <= 0) { 483 ssl_err = SSL_get_error(s->s_ssl, ret); 484 485 switch (ssl_err) { 486 case SSL_ERROR_WANT_READ: 487 retry_flag = EV_READ; 488 goto retry; 489 case SSL_ERROR_WANT_WRITE: 490 retry_flag = EV_WRITE; 491 goto retry; 492 case SSL_ERROR_ZERO_RETURN: 493 case SSL_ERROR_SYSCALL: 494 if (ret == 0) { 495 session_destroy(s); 496 return; 497 } 498 /* FALLTHROUGH */ 499 default: 500 ssl_error("ssl_session_accept"); 501 session_destroy(s); 502 return; 503 } 504 } 505 506 event_set(&s->s_bev->ev_read, s->s_fd, EV_READ, ssl_read, s->s_bev); 507 event_set(&s->s_bev->ev_write, s->s_fd, EV_WRITE, ssl_write, s->s_bev); 508 509 log_info("ssl_session_accept: accepted ssl client"); 510 s->s_flags |= F_SECURE; 511 512 if (s->s_l->flags & F_SSMTP) { 513 s_smtp.ssmtp++; 514 s_smtp.ssmtp_active++; 515 } 516 if (s->s_l->flags & F_STARTTLS) { 517 s_smtp.starttls++; 518 s_smtp.starttls_active++; 519 } 520 521 session_pickup(s, NULL); 522 return; 523 retry: 524 event_add(&s->s_ev, &s->s_tv); 525 } 526 527 void 528 ssl_session_init(struct session *s) 529 { 530 struct listener *l; 531 SSL *ssl; 532 533 l = s->s_l; 534 535 if (!(l->flags & F_SSL)) 536 return; 537 538 log_debug("ssl_session_init: switching to SSL"); 539 ssl = SSL_new(l->ssl_ctx); 540 if (ssl == NULL) 541 goto err; 542 543 if (!SSL_set_ssl_method(ssl, SSLv23_server_method())) 544 goto err; 545 if (!SSL_set_fd(ssl, s->s_fd)) 546 goto err; 547 SSL_set_accept_state(ssl); 548 549 s->s_ssl = ssl; 550 551 s->s_tv.tv_sec = SMTPD_SESSION_TIMEOUT; 552 s->s_tv.tv_usec = 0; 553 event_set(&s->s_ev, s->s_fd, EV_READ|EV_TIMEOUT, ssl_session_accept, s); 554 event_add(&s->s_ev, &s->s_tv); 555 return; 556 557 err: 558 if (ssl != NULL) 559 SSL_free(ssl); 560 ssl_error("ssl_session_init"); 561 } 562 563 void 564 ssl_client_init(struct session *s) 565 { 566 SSL_CTX *ctx; 567 568 log_debug("ssl_client_init: preparing SSL"); 569 ctx = ssl_ctx_create(); 570 571 s->s_ssl = SSL_new(ctx); 572 if (s->s_ssl == NULL) 573 goto err; 574 575 if (!SSL_set_ssl_method(s->s_ssl, SSLv23_client_method())) 576 goto err; 577 if (!SSL_set_fd(s->s_ssl, s->s_fd)) 578 goto err; 579 SSL_set_connect_state(s->s_ssl); 580 581 s->s_tv.tv_sec = SMTPD_SESSION_TIMEOUT; 582 s->s_tv.tv_usec = 0; 583 584 event_set(&s->s_ev, s->s_fd, EV_WRITE|EV_TIMEOUT, ssl_connect, s); 585 event_add(&s->s_ev, &s->s_tv); 586 return; 587 588 err: 589 if (s->s_ssl != NULL) 590 SSL_free(s->s_ssl); 591 ssl_error("ssl_client_init"); 592 } 593 594 void 595 ssl_session_destroy(struct session *s) 596 { 597 SSL_free(s->s_ssl); 598 599 if (s->s_l == NULL) { 600 /* called from mta */ 601 return; 602 } 603 604 if (s->s_l->flags & F_SSMTP) { 605 if (s->s_flags & F_SECURE) 606 s_smtp.ssmtp_active--; 607 } 608 if (s->s_l->flags & F_STARTTLS) { 609 if (s->s_flags & F_SECURE) 610 s_smtp.starttls_active--; 611 } 612 } 613