1 /* $OpenBSD: ssl.c,v 1.22 2009/10/03 07:59:55 jacekm 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" 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 54 SSL *ssl_client_init(int, char *, size_t, char *, size_t); 55 56 int ssl_buf_read(SSL *, struct buf_read *); 57 int ssl_buf_write(SSL *, struct msgbuf *); 58 59 DH *get_dh512(void); 60 void ssl_set_ephemeral_key_exchange(SSL_CTX *); 61 62 extern void bufferevent_read_pressure_cb(struct evbuffer *, size_t, 63 size_t, void *); 64 65 /* From OpenSSL's documentation: 66 * 67 * If "strong" primes were used to generate the DH parameters, it is 68 * not strictly necessary to generate a new key for each handshake 69 * but it does improve forward secrecy. 70 * 71 * These are the parameters used by both sendmail and openssl's 72 * s_server. 73 * 74 * -- gilles@ 75 */ 76 77 unsigned char dh512_p[] = { 78 0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75, 79 0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F, 80 0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3, 81 0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12, 82 0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C, 83 0x47,0x74,0xE8,0x33, 84 }; 85 86 unsigned char dh512_g[] = { 87 0x02, 88 }; 89 90 void 91 ssl_connect(int fd, short event, void *p) 92 { 93 struct session *s = p; 94 int ret; 95 int retry_flag; 96 int ssl_err; 97 98 if (event == EV_TIMEOUT) { 99 log_debug("ssl_connect: session timed out"); 100 session_destroy(s); 101 return; 102 } 103 104 ret = SSL_connect(s->s_ssl); 105 if (ret <= 0) { 106 ssl_err = SSL_get_error(s->s_ssl, ret); 107 108 switch (ssl_err) { 109 case SSL_ERROR_WANT_READ: 110 retry_flag = EV_READ; 111 goto retry; 112 case SSL_ERROR_WANT_WRITE: 113 retry_flag = EV_WRITE; 114 goto retry; 115 case SSL_ERROR_ZERO_RETURN: 116 case SSL_ERROR_SYSCALL: 117 if (ret == 0) { 118 log_debug("session destroy in MTA #1"); 119 session_destroy(s); 120 return; 121 } 122 /* FALLTHROUGH */ 123 default: 124 ssl_error("ssl_session_connect"); 125 session_destroy(s); 126 return; 127 } 128 } 129 130 event_set(&s->s_bev->ev_read, s->s_fd, EV_READ, ssl_read, s->s_bev); 131 event_set(&s->s_bev->ev_write, s->s_fd, EV_WRITE, ssl_write, s->s_bev); 132 133 log_info("ssl_connect: connected to remote ssl server"); 134 bufferevent_enable(s->s_bev, EV_READ|EV_WRITE); 135 s->s_flags |= F_SECURE; 136 137 if (s->s_flags & F_PEERHASTLS) { 138 session_respond(s, "EHLO %s", s->s_env->sc_hostname); 139 } 140 141 return; 142 retry: 143 event_add(&s->s_ev, &s->s_tv); 144 } 145 146 void 147 ssl_read(int fd, short event, void *p) 148 { 149 struct bufferevent *bufev = p; 150 struct session *s = bufev->cbarg; 151 int ret; 152 int ssl_err; 153 short what; 154 size_t len; 155 char rbuf[READ_BUF_SIZE]; 156 int howmuch = READ_BUF_SIZE; 157 158 what = EVBUFFER_READ; 159 ret = ssl_err = 0; 160 161 if (event == EV_TIMEOUT) { 162 what |= EVBUFFER_TIMEOUT; 163 goto err; 164 } 165 166 if (bufev->wm_read.high != 0) 167 howmuch = MIN(sizeof(rbuf), bufev->wm_read.high); 168 169 ret = SSL_read(s->s_ssl, rbuf, howmuch); 170 if (ret <= 0) { 171 ssl_err = SSL_get_error(s->s_ssl, ret); 172 173 switch (ssl_err) { 174 case SSL_ERROR_WANT_READ: 175 goto retry; 176 case SSL_ERROR_WANT_WRITE: 177 goto retry; 178 default: 179 if (ret == 0) 180 what |= EVBUFFER_EOF; 181 else { 182 ssl_error("ssl_read"); 183 what |= EVBUFFER_ERROR; 184 } 185 goto err; 186 } 187 } 188 189 if (evbuffer_add(bufev->input, rbuf, ret) == -1) { 190 what |= EVBUFFER_ERROR; 191 goto err; 192 } 193 194 ssl_bufferevent_add(&bufev->ev_read, bufev->timeout_read); 195 196 len = EVBUFFER_LENGTH(bufev->input); 197 if (bufev->wm_read.low != 0 && len < bufev->wm_read.low) 198 return; 199 if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) { 200 struct evbuffer *buf = bufev->input; 201 event_del(&bufev->ev_read); 202 evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev); 203 return; 204 } 205 206 if (bufev->readcb != NULL) 207 (*bufev->readcb)(bufev, bufev->cbarg); 208 return; 209 210 retry: 211 ssl_bufferevent_add(&bufev->ev_read, bufev->timeout_read); 212 return; 213 214 err: 215 (*bufev->errorcb)(bufev, what, bufev->cbarg); 216 } 217 218 219 void 220 ssl_write(int fd, short event, void *p) 221 { 222 struct bufferevent *bufev = p; 223 struct session *s = bufev->cbarg; 224 int ret; 225 int ssl_err; 226 short what; 227 228 ret = 0; 229 what = EVBUFFER_WRITE; 230 231 if (event == EV_TIMEOUT) { 232 what |= EV_TIMEOUT; 233 goto err; 234 } 235 236 if (EVBUFFER_LENGTH(bufev->output)) { 237 if (s->s_buf == NULL) { 238 s->s_buflen = EVBUFFER_LENGTH(bufev->output); 239 if ((s->s_buf = malloc(s->s_buflen)) == NULL) { 240 what |= EVBUFFER_ERROR; 241 goto err; 242 } 243 memcpy(s->s_buf, EVBUFFER_DATA(bufev->output), 244 s->s_buflen); 245 } 246 247 ret = SSL_write(s->s_ssl, s->s_buf, s->s_buflen); 248 if (ret <= 0) { 249 ssl_err = SSL_get_error(s->s_ssl, ret); 250 251 switch (ssl_err) { 252 case SSL_ERROR_WANT_READ: 253 goto retry; 254 case SSL_ERROR_WANT_WRITE: 255 goto retry; 256 default: 257 if (ret == 0) 258 what |= EVBUFFER_EOF; 259 else { 260 ssl_error("ssl_write"); 261 what |= EVBUFFER_ERROR; 262 } 263 goto err; 264 } 265 } 266 evbuffer_drain(bufev->output, ret); 267 } 268 if (s->s_buf != NULL) { 269 free(s->s_buf); 270 s->s_buf = NULL; 271 s->s_buflen = 0; 272 } 273 if (EVBUFFER_LENGTH(bufev->output) != 0) 274 ssl_bufferevent_add(&bufev->ev_write, bufev->timeout_write); 275 276 if (bufev->writecb != NULL && 277 EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low) 278 (*bufev->writecb)(bufev, bufev->cbarg); 279 return; 280 281 retry: 282 if (s->s_buflen != 0) 283 ssl_bufferevent_add(&bufev->ev_write, bufev->timeout_write); 284 return; 285 286 err: 287 if (s->s_buf != NULL) { 288 free(s->s_buf); 289 s->s_buf = NULL; 290 s->s_buflen = 0; 291 } 292 (*bufev->errorcb)(bufev, what, bufev->cbarg); 293 } 294 295 int 296 ssl_bufferevent_add(struct event *ev, int timeout) 297 { 298 struct timeval tv; 299 struct timeval *ptv = NULL; 300 301 if (timeout) { 302 timerclear(&tv); 303 tv.tv_sec = timeout; 304 ptv = &tv; 305 } 306 307 return (event_add(ev, ptv)); 308 } 309 310 int 311 ssl_cmp(struct ssl *s1, struct ssl *s2) 312 { 313 return (strcmp(s1->ssl_name, s2->ssl_name)); 314 } 315 316 SPLAY_GENERATE(ssltree, ssl, ssl_nodes, ssl_cmp); 317 318 char * 319 ssl_load_file(const char *name, off_t *len) 320 { 321 struct stat st; 322 off_t size; 323 char *buf = NULL; 324 int fd; 325 326 if ((fd = open(name, O_RDONLY)) == -1) 327 return (NULL); 328 if (fstat(fd, &st) != 0) 329 goto fail; 330 size = st.st_size; 331 if ((buf = calloc(1, size + 1)) == NULL) 332 goto fail; 333 if (read(fd, buf, size) != size) 334 goto fail; 335 close(fd); 336 337 *len = size + 1; 338 return (buf); 339 340 fail: 341 if (buf != NULL) 342 free(buf); 343 close(fd); 344 return (NULL); 345 } 346 347 SSL_CTX * 348 ssl_ctx_create(void) 349 { 350 SSL_CTX *ctx; 351 352 ctx = SSL_CTX_new(SSLv23_method()); 353 if (ctx == NULL) { 354 ssl_error("ssl_ctx_create"); 355 fatal("ssl_ctx_create: could not create SSL context"); 356 } 357 358 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); 359 SSL_CTX_set_timeout(ctx, SMTPD_SESSION_TIMEOUT); 360 SSL_CTX_set_options(ctx, SSL_OP_ALL); 361 SSL_CTX_set_options(ctx, 362 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); 363 364 if (!SSL_CTX_set_cipher_list(ctx, SSL_CIPHERS)) { 365 ssl_error("ssl_ctx_create"); 366 fatal("ssl_ctx_create: could not set cipher list"); 367 } 368 return (ctx); 369 } 370 371 int 372 ssl_load_certfile(struct smtpd *env, const char *name, u_int8_t flags) 373 { 374 struct ssl *s; 375 struct ssl key; 376 char certfile[PATH_MAX]; 377 378 if (strlcpy(key.ssl_name, name, sizeof(key.ssl_name)) 379 >= sizeof(key.ssl_name)) { 380 log_warn("ssl_load_certfile: certificate name truncated"); 381 return -1; 382 } 383 384 s = SPLAY_FIND(ssltree, env->sc_ssl, &key); 385 if (s != NULL) { 386 s->flags |= flags; 387 return 0; 388 } 389 390 if ((s = calloc(1, sizeof(*s))) == NULL) 391 fatal(NULL); 392 393 s->flags = flags; 394 (void)strlcpy(s->ssl_name, key.ssl_name, sizeof(s->ssl_name)); 395 396 if (! bsnprintf(certfile, sizeof(certfile), 397 "/etc/mail/certs/%s.crt", name)) { 398 free(s); 399 return (-1); 400 } 401 402 if ((s->ssl_cert = ssl_load_file(certfile, &s->ssl_cert_len)) == NULL) { 403 free(s); 404 return (-1); 405 } 406 407 if (! bsnprintf(certfile, sizeof(certfile), 408 "/etc/mail/certs/%s.key", name)) { 409 free(s->ssl_cert); 410 free(s); 411 return -1; 412 } 413 414 if ((s->ssl_key = ssl_load_file(certfile, &s->ssl_key_len)) == NULL) { 415 free(s->ssl_cert); 416 free(s); 417 return (-1); 418 } 419 420 SPLAY_INSERT(ssltree, env->sc_ssl, s); 421 422 return (0); 423 } 424 425 void 426 ssl_init(void) 427 { 428 SSL_library_init(); 429 SSL_load_error_strings(); 430 431 OpenSSL_add_all_algorithms(); 432 433 /* Init hardware crypto engines. */ 434 ENGINE_load_builtin_engines(); 435 ENGINE_register_all_complete(); 436 } 437 438 void 439 ssl_setup(struct smtpd *env, struct listener *l) 440 { 441 struct ssl key; 442 443 if (!(l->flags & F_SSL)) 444 return; 445 446 if (strlcpy(key.ssl_name, l->ssl_cert_name, sizeof(key.ssl_name)) 447 >= sizeof(key.ssl_name)) 448 fatal("ssl_setup: certificate name truncated"); 449 450 if ((l->ssl = SPLAY_FIND(ssltree, env->sc_ssl, &key)) == NULL) 451 fatal("ssl_setup: certificate tree corrupted"); 452 453 l->ssl_ctx = ssl_ctx_create(); 454 455 if (!ssl_ctx_use_certificate_chain(l->ssl_ctx, 456 l->ssl->ssl_cert, l->ssl->ssl_cert_len)) 457 goto err; 458 if (!ssl_ctx_use_private_key(l->ssl_ctx, 459 l->ssl->ssl_key, l->ssl->ssl_key_len)) 460 goto err; 461 462 if (!SSL_CTX_check_private_key(l->ssl_ctx)) 463 goto err; 464 if (!SSL_CTX_set_session_id_context(l->ssl_ctx, 465 (const unsigned char *)l->ssl_cert_name, strlen(l->ssl_cert_name) + 1)) 466 goto err; 467 468 ssl_set_ephemeral_key_exchange(l->ssl_ctx); 469 470 log_debug("ssl_setup: ssl setup finished for listener: %p", l); 471 return; 472 473 err: 474 if (l->ssl_ctx != NULL) 475 SSL_CTX_free(l->ssl_ctx); 476 ssl_error("ssl_setup"); 477 fatal("ssl_setup: cannot set SSL up"); 478 return; 479 } 480 481 void 482 ssl_error(const char *where) 483 { 484 unsigned long code; 485 char errbuf[128]; 486 extern int debug; 487 488 if (!debug) 489 return; 490 for (; (code = ERR_get_error()) != 0 ;) { 491 ERR_error_string_n(code, errbuf, sizeof(errbuf)); 492 log_debug("SSL library error: %s: %s", where, errbuf); 493 } 494 } 495 496 void 497 ssl_session_accept(int fd, short event, void *p) 498 { 499 struct session *s = p; 500 int ret; 501 int retry_flag; 502 int ssl_err; 503 504 if (event == EV_TIMEOUT) { 505 log_debug("ssl_session_accept: session timed out"); 506 session_destroy(s); 507 return; 508 } 509 510 retry_flag = ssl_err = 0; 511 512 log_debug("ssl_session_accept: accepting client"); 513 ret = SSL_accept(s->s_ssl); 514 if (ret <= 0) { 515 ssl_err = SSL_get_error(s->s_ssl, ret); 516 517 switch (ssl_err) { 518 case SSL_ERROR_WANT_READ: 519 retry_flag = EV_READ; 520 goto retry; 521 case SSL_ERROR_WANT_WRITE: 522 retry_flag = EV_WRITE; 523 goto retry; 524 case SSL_ERROR_ZERO_RETURN: 525 case SSL_ERROR_SYSCALL: 526 if (ret == 0) { 527 session_destroy(s); 528 return; 529 } 530 /* FALLTHROUGH */ 531 default: 532 ssl_error("ssl_session_accept"); 533 session_destroy(s); 534 return; 535 } 536 } 537 538 539 log_info("ssl_session_accept: accepted ssl client"); 540 s->s_flags |= F_SECURE; 541 542 if (s->s_l->flags & F_SMTPS) { 543 s->s_env->stats->smtp.smtps++; 544 s->s_env->stats->smtp.smtps_active++; 545 } 546 if (s->s_l->flags & F_STARTTLS) { 547 s->s_env->stats->smtp.starttls++; 548 s->s_env->stats->smtp.starttls_active++; 549 } 550 551 session_bufferevent_new(s); 552 event_set(&s->s_bev->ev_read, s->s_fd, EV_READ, ssl_read, s->s_bev); 553 event_set(&s->s_bev->ev_write, s->s_fd, EV_WRITE, ssl_write, s->s_bev); 554 session_pickup(s, NULL); 555 556 return; 557 retry: 558 event_add(&s->s_ev, &s->s_tv); 559 } 560 561 void 562 ssl_session_init(struct session *s) 563 { 564 struct listener *l; 565 SSL *ssl; 566 567 l = s->s_l; 568 569 if (!(l->flags & F_SSL)) 570 return; 571 572 log_debug("ssl_session_init: switching to SSL"); 573 ssl = SSL_new(l->ssl_ctx); 574 if (ssl == NULL) 575 goto err; 576 577 if (!SSL_set_ssl_method(ssl, SSLv23_server_method())) 578 goto err; 579 if (!SSL_set_fd(ssl, s->s_fd)) 580 goto err; 581 SSL_set_accept_state(ssl); 582 583 s->s_ssl = ssl; 584 585 s->s_tv.tv_sec = SMTPD_SESSION_TIMEOUT; 586 s->s_tv.tv_usec = 0; 587 event_set(&s->s_ev, s->s_fd, EV_READ|EV_TIMEOUT, ssl_session_accept, s); 588 event_add(&s->s_ev, &s->s_tv); 589 return; 590 591 err: 592 if (ssl != NULL) 593 SSL_free(ssl); 594 ssl_error("ssl_session_init"); 595 } 596 597 SSL * 598 ssl_client_init(int fd, char *cert, size_t certsz, char *key, size_t keysz) 599 { 600 SSL_CTX *ctx; 601 SSL *ssl = NULL; 602 int rv = -1; 603 604 ctx = ssl_ctx_create(); 605 606 if (cert && key) { 607 if (!ssl_ctx_use_certificate_chain(ctx, cert, certsz)) 608 goto done; 609 else if (!ssl_ctx_use_private_key(ctx, key, keysz)) 610 goto done; 611 else if (!SSL_CTX_check_private_key(ctx)) 612 goto done; 613 } 614 615 if ((ssl = SSL_new(ctx)) == NULL) 616 goto done; 617 618 if (!SSL_set_ssl_method(ssl, SSLv23_client_method())) 619 goto done; 620 if (!SSL_set_fd(ssl, fd)) 621 goto done; 622 SSL_set_connect_state(ssl); 623 624 rv = 0; 625 done: 626 if (rv) { 627 if (ssl) 628 SSL_free(ssl); 629 else if (ctx) 630 SSL_CTX_free(ctx); 631 ssl = NULL; 632 } 633 return (ssl); 634 } 635 636 void 637 ssl_session_destroy(struct session *s) 638 { 639 SSL_free(s->s_ssl); 640 641 if (s->s_l == NULL) { 642 /* called from mta */ 643 return; 644 } 645 646 if (s->s_l->flags & F_SMTPS) { 647 if (s->s_flags & F_SECURE) 648 s->s_env->stats->smtp.smtps_active--; 649 } 650 if (s->s_l->flags & F_STARTTLS) { 651 if (s->s_flags & F_SECURE) 652 s->s_env->stats->smtp.starttls_active--; 653 } 654 } 655 656 int 657 ssl_buf_read(SSL *s, struct buf_read *r) 658 { 659 int ret; 660 661 ret = SSL_read(s, r->buf + r->wpos, sizeof(r->buf) - r->wpos); 662 663 if (ret > 0) 664 r->wpos += ret; 665 666 return SSL_get_error(s, ret); 667 } 668 669 int 670 ssl_buf_write(SSL *s, struct msgbuf *msgbuf) 671 { 672 struct buf *buf; 673 int ret; 674 675 buf = TAILQ_FIRST(&msgbuf->bufs); 676 if (buf == NULL) 677 return (SSL_ERROR_NONE); 678 679 ret = SSL_write(s, buf->buf + buf->rpos, buf->wpos - buf->rpos); 680 681 if (ret > 0) 682 msgbuf_drain(msgbuf, ret); 683 684 return SSL_get_error(s, ret); 685 } 686 687 DH * 688 get_dh512(void) 689 { 690 DH *dh; 691 692 if ((dh = DH_new()) == NULL) 693 return NULL; 694 695 dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), NULL); 696 dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), NULL); 697 if (dh->p == NULL || dh->g == NULL) 698 return NULL; 699 700 return dh; 701 } 702 703 704 void 705 ssl_set_ephemeral_key_exchange(SSL_CTX *ctx) 706 { 707 DH *dh; 708 709 dh = get_dh512(); 710 if (dh != NULL) 711 SSL_CTX_set_tmp_dh(ctx, dh); 712 } 713