mutt stable branch with some hacks
at master 1110 lines 29 kB view raw
1/* 2 * Copyright (C) 1999-2001 Tommi Komulainen <Tommi.Komulainen@iki.fi> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 */ 18 19#if HAVE_CONFIG_H 20# include "config.h" 21#endif 22 23#include <openssl/ssl.h> 24#include <openssl/x509.h> 25#include <openssl/x509v3.h> 26#include <openssl/err.h> 27#include <openssl/rand.h> 28 29#undef _ 30 31#include <string.h> 32 33#include "mutt.h" 34#include "mutt_socket.h" 35#include "mutt_menu.h" 36#include "mutt_curses.h" 37#include "mutt_ssl.h" 38#include "mutt_idna.h" 39 40/* Just in case OpenSSL doesn't define DEVRANDOM */ 41#ifndef DEVRANDOM 42#define DEVRANDOM "/dev/urandom" 43#endif 44 45/* This is ugly, but as RAND_status came in on OpenSSL version 0.9.5 46 * and the code has to support older versions too, this is seemed to 47 * be cleaner way compared to having even uglier #ifdefs all around. 48 */ 49#ifdef HAVE_RAND_STATUS 50#define HAVE_ENTROPY() (RAND_status() == 1) 51#else 52static int entropy_byte_count = 0; 53/* OpenSSL fills the entropy pool from /dev/urandom if it exists */ 54#define HAVE_ENTROPY() (!access(DEVRANDOM, R_OK) || entropy_byte_count >= 16) 55#endif 56 57/* index for storing hostname as application specific data in SSL structure */ 58static int HostExDataIndex = -1; 59/* keep a handle on accepted certificates in case we want to 60 * open up another connection to the same server in this session */ 61static STACK_OF(X509) *SslSessionCerts = NULL; 62 63typedef struct 64{ 65 SSL_CTX *ctx; 66 SSL *ssl; 67 X509 *cert; 68 unsigned char isopen; 69} 70sslsockdata; 71 72/* local prototypes */ 73static int ssl_init (void); 74static int add_entropy (const char *file); 75static int ssl_socket_read (CONNECTION* conn, char* buf, size_t len); 76static int ssl_socket_write (CONNECTION* conn, const char* buf, size_t len); 77static int ssl_socket_open (CONNECTION * conn); 78static int ssl_socket_close (CONNECTION * conn); 79static int tls_close (CONNECTION* conn); 80static void ssl_err (sslsockdata *data, int err); 81static void ssl_dprint_err_stack (void); 82static int ssl_cache_trusted_cert (X509 *cert); 83static int ssl_verify_callback (int preverify_ok, X509_STORE_CTX *ctx); 84static int interactive_check_cert (X509 *cert, int idx, int len); 85static void ssl_get_client_cert(sslsockdata *ssldata, CONNECTION *conn); 86static int ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata); 87static int ssl_negotiate (CONNECTION *conn, sslsockdata*); 88 89/* mutt_ssl_starttls: Negotiate TLS over an already opened connection. 90 * TODO: Merge this code better with ssl_socket_open. */ 91int mutt_ssl_starttls (CONNECTION* conn) 92{ 93 sslsockdata* ssldata; 94 int maxbits; 95 long ssl_options = 0; 96 97 if (ssl_init()) 98 goto bail; 99 100 ssldata = (sslsockdata*) safe_calloc (1, sizeof (sslsockdata)); 101 /* the ssl_use_xxx protocol options don't apply. We must use TLS in TLS. 102 * 103 * However, we need to be able to negotiate amongst various TLS versions, 104 * which at present can only be done with the SSLv23_client_method; 105 * TLSv1_client_method gives us explicitly TLSv1.0, not 1.1 or 1.2 (True as 106 * of OpenSSL 1.0.1c) 107 */ 108 if (! (ssldata->ctx = SSL_CTX_new (SSLv23_client_method()))) 109 { 110 dprint (1, (debugfile, "mutt_ssl_starttls: Error allocating SSL_CTX\n")); 111 goto bail_ssldata; 112 } 113#ifdef SSL_OP_NO_TLSv1_2 114 if (!option(OPTTLSV1_2)) 115 ssl_options |= SSL_OP_NO_TLSv1_2; 116#endif 117#ifdef SSL_OP_NO_TLSv1_1 118 if (!option(OPTTLSV1_1)) 119 ssl_options |= SSL_OP_NO_TLSv1_1; 120#endif 121#ifdef SSL_OP_NO_TLSv1 122 if (!option(OPTTLSV1)) 123 ssl_options |= SSL_OP_NO_TLSv1; 124#endif 125 /* these are always set */ 126#ifdef SSL_OP_NO_SSLv3 127 ssl_options |= SSL_OP_NO_SSLv3; 128#endif 129#ifdef SSL_OP_NO_SSLv2 130 ssl_options |= SSL_OP_NO_SSLv2; 131#endif 132 if (! SSL_CTX_set_options(ssldata->ctx, ssl_options)) 133 { 134 dprint(1, (debugfile, "mutt_ssl_starttls: Error setting options to %ld\n", ssl_options)); 135 goto bail_ctx; 136 } 137 138 if (option (OPTSSLSYSTEMCERTS)) 139 { 140 if (! SSL_CTX_set_default_verify_paths (ssldata->ctx)) 141 { 142 dprint (1, (debugfile, "mutt_ssl_starttls: Error setting default verify paths\n")); 143 goto bail_ctx; 144 } 145 } 146 147 if (SslCertFile && ! SSL_CTX_load_verify_locations (ssldata->ctx, SslCertFile, NULL)) 148 dprint (1, (debugfile, "mutt_ssl_starttls: Error loading trusted certificates\n")); 149 150 ssl_get_client_cert(ssldata, conn); 151 152 if (SslCiphers) { 153 if (!SSL_CTX_set_cipher_list (ssldata->ctx, SslCiphers)) { 154 dprint (1, (debugfile, "mutt_ssl_starttls: Could not select preferred ciphers\n")); 155 goto bail_ctx; 156 } 157 } 158 159 if (! (ssldata->ssl = SSL_new (ssldata->ctx))) 160 { 161 dprint (1, (debugfile, "mutt_ssl_starttls: Error allocating SSL\n")); 162 goto bail_ctx; 163 } 164 165 if (SSL_set_fd (ssldata->ssl, conn->fd) != 1) 166 { 167 dprint (1, (debugfile, "mutt_ssl_starttls: Error setting fd\n")); 168 goto bail_ssl; 169 } 170 171 if (ssl_negotiate (conn, ssldata)) 172 goto bail_ssl; 173 174 ssldata->isopen = 1; 175 176 /* hmm. watch out if we're starting TLS over any method other than raw. */ 177 conn->sockdata = ssldata; 178 conn->conn_read = ssl_socket_read; 179 conn->conn_write = ssl_socket_write; 180 conn->conn_close = tls_close; 181 182 conn->ssf = SSL_CIPHER_get_bits (SSL_get_current_cipher (ssldata->ssl), 183 &maxbits); 184 185 return 0; 186 187 bail_ssl: 188 FREE (&ssldata->ssl); 189 bail_ctx: 190 FREE (&ssldata->ctx); 191 bail_ssldata: 192 FREE (&ssldata); 193 bail: 194 return -1; 195} 196 197/* 198 * OpenSSL library needs to be fed with sufficient entropy. On systems 199 * with /dev/urandom, this is done transparently by the library itself, 200 * on other systems we need to fill the entropy pool ourselves. 201 * 202 * Even though only OpenSSL 0.9.5 and later will complain about the 203 * lack of entropy, we try to our best and fill the pool with older 204 * versions also. (That's the reason for the ugly #ifdefs and macros, 205 * otherwise I could have simply #ifdef'd the whole ssl_init funcion) 206 */ 207static int ssl_init (void) 208{ 209 char path[_POSIX_PATH_MAX]; 210 static unsigned char init_complete = 0; 211 212 if (init_complete) 213 return 0; 214 215 if (! HAVE_ENTROPY()) 216 { 217 /* load entropy from files */ 218 add_entropy (SslEntropyFile); 219 add_entropy (RAND_file_name (path, sizeof (path))); 220 221 /* load entropy from egd sockets */ 222#ifdef HAVE_RAND_EGD 223 add_entropy (getenv ("EGDSOCKET")); 224 snprintf (path, sizeof(path), "%s/.entropy", NONULL(Homedir)); 225 add_entropy (path); 226 add_entropy ("/tmp/entropy"); 227#endif 228 229 /* shuffle $RANDFILE (or ~/.rnd if unset) */ 230 RAND_write_file (RAND_file_name (path, sizeof (path))); 231 mutt_clear_error (); 232 if (! HAVE_ENTROPY()) 233 { 234 mutt_error (_("Failed to find enough entropy on your system")); 235 mutt_sleep (2); 236 return -1; 237 } 238 } 239 240 /* I don't think you can do this just before reading the error. The call 241 * itself might clobber the last SSL error. */ 242 SSL_load_error_strings(); 243 SSL_library_init(); 244 init_complete = 1; 245 return 0; 246} 247 248static int add_entropy (const char *file) 249{ 250 struct stat st; 251 int n = -1; 252 253 if (!file) return 0; 254 255 if (stat (file, &st) == -1) 256 return errno == ENOENT ? 0 : -1; 257 258 mutt_message (_("Filling entropy pool: %s...\n"), 259 file); 260 261 /* check that the file permissions are secure */ 262 if (st.st_uid != getuid () || 263 ((st.st_mode & (S_IWGRP | S_IRGRP)) != 0) || 264 ((st.st_mode & (S_IWOTH | S_IROTH)) != 0)) 265 { 266 mutt_error (_("%s has insecure permissions!"), file); 267 mutt_sleep (2); 268 return -1; 269 } 270 271#ifdef HAVE_RAND_EGD 272 n = RAND_egd (file); 273#endif 274 if (n <= 0) 275 n = RAND_load_file (file, -1); 276 277#ifndef HAVE_RAND_STATUS 278 if (n > 0) entropy_byte_count += n; 279#endif 280 return n; 281} 282 283static int ssl_socket_open_err (CONNECTION *conn) 284{ 285 mutt_error (_("SSL disabled due to the lack of entropy")); 286 mutt_sleep (2); 287 return -1; 288} 289 290 291int mutt_ssl_socket_setup (CONNECTION * conn) 292{ 293 if (ssl_init() < 0) 294 { 295 conn->conn_open = ssl_socket_open_err; 296 return -1; 297 } 298 299 conn->conn_open = ssl_socket_open; 300 conn->conn_read = ssl_socket_read; 301 conn->conn_write = ssl_socket_write; 302 conn->conn_close = ssl_socket_close; 303 conn->conn_poll = raw_socket_poll; 304 305 return 0; 306} 307 308static int ssl_socket_read (CONNECTION* conn, char* buf, size_t len) 309{ 310 sslsockdata *data = conn->sockdata; 311 int rc; 312 313 rc = SSL_read (data->ssl, buf, len); 314 if (rc <= 0) 315 { 316 data->isopen = 0; 317 ssl_err (data, rc); 318 } 319 320 return rc; 321} 322 323static int ssl_socket_write (CONNECTION* conn, const char* buf, size_t len) 324{ 325 sslsockdata *data = conn->sockdata; 326 int rc; 327 328 rc = SSL_write (data->ssl, buf, len); 329 if (rc <= 0) 330 ssl_err (data, rc); 331 332 return rc; 333} 334 335static int ssl_socket_open (CONNECTION * conn) 336{ 337 sslsockdata *data; 338 int maxbits; 339 340 if (raw_socket_open (conn) < 0) 341 return -1; 342 343 data = (sslsockdata *) safe_calloc (1, sizeof (sslsockdata)); 344 conn->sockdata = data; 345 346 if (! (data->ctx = SSL_CTX_new (SSLv23_client_method ()))) 347 { 348 /* L10N: an SSL context is a data structure returned by the OpenSSL 349 * function SSL_CTX_new(). In this case it returned NULL: an 350 * error condition. 351 */ 352 mutt_error (_("Unable to create SSL context")); 353 ssl_dprint_err_stack (); 354 mutt_socket_close (conn); 355 return -1; 356 } 357 358 /* disable SSL protocols as needed */ 359 if (!option(OPTTLSV1)) 360 { 361 SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1); 362 } 363 /* TLSv1.1/1.2 support was added in OpenSSL 1.0.1, but some OS distros such 364 * as Fedora 17 are on OpenSSL 1.0.0. 365 */ 366#ifdef SSL_OP_NO_TLSv1_1 367 if (!option(OPTTLSV1_1)) 368 { 369 SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1_1); 370 } 371#endif 372#ifdef SSL_OP_NO_TLSv1_2 373 if (!option(OPTTLSV1_2)) 374 { 375 SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1_2); 376 } 377#endif 378 if (!option(OPTSSLV2)) 379 { 380 SSL_CTX_set_options(data->ctx, SSL_OP_NO_SSLv2); 381 } 382 if (!option(OPTSSLV3)) 383 { 384 SSL_CTX_set_options(data->ctx, SSL_OP_NO_SSLv3); 385 } 386 387 if (option (OPTSSLSYSTEMCERTS)) 388 { 389 if (! SSL_CTX_set_default_verify_paths (data->ctx)) 390 { 391 dprint (1, (debugfile, "ssl_socket_open: Error setting default verify paths\n")); 392 mutt_socket_close (conn); 393 return -1; 394 } 395 } 396 397 if (SslCertFile && ! SSL_CTX_load_verify_locations (data->ctx, SslCertFile, NULL)) 398 dprint (1, (debugfile, "ssl_socket_open: Error loading trusted certificates\n")); 399 400 ssl_get_client_cert(data, conn); 401 402 if (SslCiphers) { 403 SSL_CTX_set_cipher_list (data->ctx, SslCiphers); 404 } 405 406 data->ssl = SSL_new (data->ctx); 407 SSL_set_fd (data->ssl, conn->fd); 408 409 if (ssl_negotiate(conn, data)) 410 { 411 mutt_socket_close (conn); 412 return -1; 413 } 414 415 data->isopen = 1; 416 417 conn->ssf = SSL_CIPHER_get_bits (SSL_get_current_cipher (data->ssl), 418 &maxbits); 419 420 return 0; 421} 422 423/* ssl_negotiate: After SSL state has been initialized, attempt to negotiate 424 * SSL over the wire, including certificate checks. */ 425static int ssl_negotiate (CONNECTION *conn, sslsockdata* ssldata) 426{ 427 int err; 428 const char* errmsg; 429 430 if ((HostExDataIndex = SSL_get_ex_new_index (0, "host", NULL, NULL, NULL)) == -1) 431 { 432 dprint (1, (debugfile, "failed to get index for application specific data\n")); 433 return -1; 434 } 435 436 if (! SSL_set_ex_data (ssldata->ssl, HostExDataIndex, conn->account.host)) 437 { 438 dprint (1, (debugfile, "failed to save hostname in SSL structure\n")); 439 return -1; 440 } 441 442 SSL_set_verify (ssldata->ssl, SSL_VERIFY_PEER, ssl_verify_callback); 443 SSL_set_mode (ssldata->ssl, SSL_MODE_AUTO_RETRY); 444 445 if ((err = SSL_connect (ssldata->ssl)) != 1) 446 { 447 switch (SSL_get_error (ssldata->ssl, err)) 448 { 449 case SSL_ERROR_SYSCALL: 450 errmsg = _("I/O error"); 451 break; 452 case SSL_ERROR_SSL: 453 errmsg = ERR_error_string (ERR_get_error (), NULL); 454 break; 455 default: 456 errmsg = _("unknown error"); 457 } 458 459 mutt_error (_("SSL failed: %s"), errmsg); 460 mutt_sleep (1); 461 462 return -1; 463 } 464 465 /* L10N: 466 %1$s is version (e.g. "TLSv1.2") 467 %2$s is cipher_version (e.g. "TLSv1/SSLv3") 468 %3$s is cipher_name (e.g. "ECDHE-RSA-AES128-GCM-SHA256") */ 469 mutt_message (_("%s connection using %s (%s)"), 470 SSL_get_version(ssldata->ssl), SSL_get_cipher_version (ssldata->ssl), SSL_get_cipher_name (ssldata->ssl)); 471 mutt_sleep (0); 472 473 return 0; 474} 475 476static int ssl_socket_close (CONNECTION * conn) 477{ 478 sslsockdata *data = conn->sockdata; 479 if (data) 480 { 481 if (data->isopen) 482 SSL_shutdown (data->ssl); 483 484 /* hold onto this for the life of mutt, in case we want to reconnect. 485 * The purist in me wants a mutt_exit hook. */ 486#if 0 487 X509_free (data->cert); 488#endif 489 SSL_free (data->ssl); 490 SSL_CTX_free (data->ctx); 491 FREE (&conn->sockdata); 492 } 493 494 return raw_socket_close (conn); 495} 496 497static int tls_close (CONNECTION* conn) 498{ 499 int rc; 500 501 rc = ssl_socket_close (conn); 502 conn->conn_read = raw_socket_read; 503 conn->conn_write = raw_socket_write; 504 conn->conn_close = raw_socket_close; 505 506 return rc; 507} 508 509static void ssl_err (sslsockdata *data, int err) 510{ 511 const char* errmsg; 512 unsigned long sslerr; 513 514 switch (SSL_get_error (data->ssl, err)) 515 { 516 case SSL_ERROR_NONE: 517 return; 518 case SSL_ERROR_ZERO_RETURN: 519 errmsg = "SSL connection closed"; 520 data->isopen = 0; 521 break; 522 case SSL_ERROR_WANT_READ: 523 errmsg = "retry read"; 524 break; 525 case SSL_ERROR_WANT_WRITE: 526 errmsg = "retry write"; 527 break; 528 case SSL_ERROR_WANT_CONNECT: 529 errmsg = "retry connect"; 530 break; 531 case SSL_ERROR_WANT_ACCEPT: 532 errmsg = "retry accept"; 533 break; 534 case SSL_ERROR_WANT_X509_LOOKUP: 535 errmsg = "retry x509 lookup"; 536 break; 537 case SSL_ERROR_SYSCALL: 538 errmsg = "I/O error"; 539 data->isopen = 0; 540 break; 541 case SSL_ERROR_SSL: 542 sslerr = ERR_get_error (); 543 switch (sslerr) 544 { 545 case 0: 546 switch (err) 547 { 548 case 0: 549 errmsg = "EOF"; 550 break; 551 default: 552 errmsg = strerror(errno); 553 } 554 break; 555 default: 556 errmsg = ERR_error_string (sslerr, NULL); 557 } 558 break; 559 default: 560 errmsg = "unknown error"; 561 } 562 563 dprint (1, (debugfile, "SSL error: %s\n", errmsg)); 564} 565 566static void ssl_dprint_err_stack (void) 567{ 568#ifdef DEBUG 569 BIO *bio; 570 char *buf = NULL; 571 long buflen; 572 char *output; 573 574 if (! (bio = BIO_new (BIO_s_mem ()))) 575 return; 576 ERR_print_errors (bio); 577 if ((buflen = BIO_get_mem_data (bio, &buf)) > 0) 578 { 579 output = safe_malloc (buflen + 1); 580 memcpy (output, buf, buflen); 581 output[buflen] = '\0'; 582 dprint (1, (debugfile, "SSL error stack: %s\n", output)); 583 FREE (&output); 584 } 585 BIO_free (bio); 586#endif 587} 588 589 590static char *x509_get_part (X509_NAME *name, int nid) 591{ 592 static char ret[SHORT_STRING]; 593 594 if (!name || 595 X509_NAME_get_text_by_NID (name, nid, ret, sizeof (ret)) < 0) 596 strfcpy (ret, _("Unknown"), sizeof (ret)); 597 598 return ret; 599} 600 601static void x509_fingerprint (char *s, int l, X509 * cert) 602{ 603 unsigned char md[EVP_MAX_MD_SIZE]; 604 unsigned int n; 605 int j; 606 607 if (!X509_digest (cert, EVP_md5 (), md, &n)) 608 { 609 snprintf (s, l, _("[unable to calculate]")); 610 } 611 else 612 { 613 for (j = 0; j < (int) n; j++) 614 { 615 char ch[8]; 616 snprintf (ch, 8, "%02X%s", md[j], (j % 2 ? " " : "")); 617 safe_strcat (s, l, ch); 618 } 619 } 620} 621 622static char *asn1time_to_string (ASN1_UTCTIME *tm) 623{ 624 static char buf[64]; 625 BIO *bio; 626 627 strfcpy (buf, _("[invalid date]"), sizeof (buf)); 628 629 bio = BIO_new (BIO_s_mem()); 630 if (bio) 631 { 632 if (ASN1_TIME_print (bio, tm)) 633 (void) BIO_read (bio, buf, sizeof (buf)); 634 BIO_free (bio); 635 } 636 637 return buf; 638} 639 640static int compare_certificates (X509 *cert, X509 *peercert, 641 unsigned char *peermd, unsigned int peermdlen) 642{ 643 unsigned char md[EVP_MAX_MD_SIZE]; 644 unsigned int mdlen; 645 646 /* Avoid CPU-intensive digest calculation if the certificates are 647 * not even remotely equal. 648 */ 649 if (X509_subject_name_cmp (cert, peercert) != 0 || 650 X509_issuer_name_cmp (cert, peercert) != 0) 651 return -1; 652 653 if (!X509_digest (cert, EVP_sha1(), md, &mdlen) || peermdlen != mdlen) 654 return -1; 655 656 if (memcmp(peermd, md, mdlen) != 0) 657 return -1; 658 659 return 0; 660} 661 662static int check_certificate_cache (X509 *peercert) 663{ 664 unsigned char peermd[EVP_MAX_MD_SIZE]; 665 unsigned int peermdlen; 666 X509 *cert; 667 int i; 668 669 if (!X509_digest (peercert, EVP_sha1(), peermd, &peermdlen) 670 || !SslSessionCerts) 671 { 672 return 0; 673 } 674 675 for (i = sk_X509_num (SslSessionCerts); i-- > 0;) 676 { 677 cert = sk_X509_value (SslSessionCerts, i); 678 if (!compare_certificates (cert, peercert, peermd, peermdlen)) 679 { 680 return 1; 681 } 682 } 683 684 return 0; 685} 686 687static int check_certificate_by_digest (X509 *peercert) 688{ 689 unsigned char peermd[EVP_MAX_MD_SIZE]; 690 unsigned int peermdlen; 691 X509 *cert = NULL; 692 int pass = 0; 693 FILE *fp; 694 695 /* expiration check */ 696 if (option (OPTSSLVERIFYDATES) != MUTT_NO) 697 { 698 if (X509_cmp_current_time (X509_get_notBefore (peercert)) >= 0) 699 { 700 dprint (2, (debugfile, "Server certificate is not yet valid\n")); 701 mutt_error (_("Server certificate is not yet valid")); 702 mutt_sleep (2); 703 return 0; 704 } 705 if (X509_cmp_current_time (X509_get_notAfter (peercert)) <= 0) 706 { 707 dprint (2, (debugfile, "Server certificate has expired")); 708 mutt_error (_("Server certificate has expired")); 709 mutt_sleep (2); 710 return 0; 711 } 712 } 713 714 if ((fp = fopen (SslCertFile, "rt")) == NULL) 715 return 0; 716 717 if (!X509_digest (peercert, EVP_sha1(), peermd, &peermdlen)) 718 { 719 safe_fclose (&fp); 720 return 0; 721 } 722 723 while ((cert = PEM_read_X509 (fp, &cert, NULL, NULL)) != NULL) 724 { 725 pass = compare_certificates (cert, peercert, peermd, peermdlen) ? 0 : 1; 726 727 if (pass) 728 break; 729 } 730 X509_free (cert); 731 safe_fclose (&fp); 732 733 return pass; 734} 735 736/* port to mutt from msmtp's tls.c */ 737static int hostname_match (const char *hostname, const char *certname) 738{ 739 const char *cmp1, *cmp2; 740 741 if (strncmp(certname, "*.", 2) == 0) 742 { 743 cmp1 = certname + 2; 744 cmp2 = strchr(hostname, '.'); 745 if (!cmp2) 746 { 747 return 0; 748 } 749 else 750 { 751 cmp2++; 752 } 753 } 754 else 755 { 756 cmp1 = certname; 757 cmp2 = hostname; 758 } 759 760 if (*cmp1 == '\0' || *cmp2 == '\0') 761 { 762 return 0; 763 } 764 765 if (strcasecmp(cmp1, cmp2) != 0) 766 { 767 return 0; 768 } 769 770 return 1; 771} 772 773/* port to mutt from msmtp's tls.c */ 774static int check_host (X509 *x509cert, const char *hostname, char *err, size_t errlen) 775{ 776 int i, rc = 0; 777 /* hostname in ASCII format: */ 778 char *hostname_ascii = NULL; 779 /* needed to get the common name: */ 780 X509_NAME *x509_subject; 781 char *buf = NULL; 782 int bufsize; 783 /* needed to get the DNS subjectAltNames: */ 784 STACK_OF(GENERAL_NAME) *subj_alt_names; 785 int subj_alt_names_count; 786 GENERAL_NAME *subj_alt_name; 787 /* did we find a name matching hostname? */ 788 int match_found; 789 790 /* Check if 'hostname' matches the one of the subjectAltName extensions of 791 * type DNS or the Common Name (CN). */ 792 793#ifdef HAVE_LIBIDN 794 if (idna_to_ascii_lz(hostname, &hostname_ascii, 0) != IDNA_SUCCESS) 795 { 796 hostname_ascii = safe_strdup(hostname); 797 } 798#else 799 hostname_ascii = safe_strdup(hostname); 800#endif 801 802 /* Try the DNS subjectAltNames. */ 803 match_found = 0; 804 if ((subj_alt_names = X509_get_ext_d2i(x509cert, NID_subject_alt_name, 805 NULL, NULL))) 806 { 807 subj_alt_names_count = sk_GENERAL_NAME_num(subj_alt_names); 808 for (i = 0; i < subj_alt_names_count; i++) 809 { 810 subj_alt_name = sk_GENERAL_NAME_value(subj_alt_names, i); 811 if (subj_alt_name->type == GEN_DNS) 812 { 813 if (subj_alt_name->d.ia5->length >= 0 && 814 mutt_strlen((char *)subj_alt_name->d.ia5->data) == (size_t)subj_alt_name->d.ia5->length && 815 (match_found = hostname_match(hostname_ascii, 816 (char *)(subj_alt_name->d.ia5->data)))) 817 { 818 break; 819 } 820 } 821 } 822 } 823 824 if (!match_found) 825 { 826 /* Try the common name */ 827 if (!(x509_subject = X509_get_subject_name(x509cert))) 828 { 829 if (err && errlen) 830 strfcpy (err, _("cannot get certificate subject"), errlen); 831 goto out; 832 } 833 834 /* first get the space requirements */ 835 bufsize = X509_NAME_get_text_by_NID(x509_subject, NID_commonName, 836 NULL, 0); 837 if (bufsize == -1) 838 { 839 if (err && errlen) 840 strfcpy (err, _("cannot get certificate common name"), errlen); 841 goto out; 842 } 843 bufsize++; /* space for the terminal nul char */ 844 buf = safe_malloc((size_t)bufsize); 845 if (X509_NAME_get_text_by_NID(x509_subject, NID_commonName, 846 buf, bufsize) == -1) 847 { 848 if (err && errlen) 849 strfcpy (err, _("cannot get certificate common name"), errlen); 850 goto out; 851 } 852 /* cast is safe since bufsize is incremented above, so bufsize-1 is always 853 * zero or greater. 854 */ 855 if (mutt_strlen(buf) == (size_t)bufsize - 1) { 856 match_found = hostname_match(hostname_ascii, buf); 857 } 858 } 859 860 if (!match_found) 861 { 862 if (err && errlen) 863 snprintf (err, errlen, _("certificate owner does not match hostname %s"), 864 hostname); 865 goto out; 866 } 867 868 rc = 1; 869 870out: 871 FREE(&buf); 872 FREE(&hostname_ascii); 873 874 return rc; 875} 876 877static int ssl_cache_trusted_cert (X509 *c) 878{ 879 dprint (1, (debugfile, "ssl_cache_trusted_cert: trusted\n")); 880 if (!SslSessionCerts) 881 SslSessionCerts = sk_X509_new_null(); 882 return (sk_X509_push (SslSessionCerts, X509_dup(c))); 883} 884 885/* certificate verification callback, called for each certificate in the chain 886 * sent by the peer, starting from the root; returning 1 means that the given 887 * certificate is trusted, returning 0 immediately aborts the SSL connection */ 888static int ssl_verify_callback (int preverify_ok, X509_STORE_CTX *ctx) 889{ 890 char buf[STRING]; 891 const char *host; 892 int len, pos; 893 X509 *cert; 894 SSL *ssl; 895 896 if (! (ssl = X509_STORE_CTX_get_ex_data (ctx, SSL_get_ex_data_X509_STORE_CTX_idx ()))) 897 { 898 dprint (1, (debugfile, "ssl_verify_callback: failed to retrieve SSL structure from X509_STORE_CTX\n")); 899 return 0; 900 } 901 if (! (host = SSL_get_ex_data (ssl, HostExDataIndex))) 902 { 903 dprint (1, (debugfile, "ssl_verify_callback: failed to retrieve hostname from SSL structure\n")); 904 return 0; 905 } 906 907 cert = X509_STORE_CTX_get_current_cert (ctx); 908 pos = X509_STORE_CTX_get_error_depth (ctx); 909 len = sk_X509_num (X509_STORE_CTX_get_chain (ctx)); 910 911 dprint (1, (debugfile, "ssl_verify_callback: checking cert chain entry %s (preverify: %d)\n", 912 X509_NAME_oneline (X509_get_subject_name (cert), 913 buf, sizeof (buf)), preverify_ok)); 914 915 /* check session cache first */ 916 if (check_certificate_cache (cert)) 917 { 918 dprint (2, (debugfile, "ssl_verify_callback: using cached certificate\n")); 919 return 1; 920 } 921 922 /* check hostname only for the leaf certificate */ 923 buf[0] = 0; 924 if (pos == 0 && option (OPTSSLVERIFYHOST) != MUTT_NO) 925 { 926 if (!check_host (cert, host, buf, sizeof (buf))) 927 { 928 mutt_error (_("Certificate host check failed: %s"), buf); 929 mutt_sleep (2); 930 return interactive_check_cert (cert, pos, len); 931 } 932 dprint (2, (debugfile, "ssl_verify_callback: hostname check passed\n")); 933 } 934 935 if (!preverify_ok) 936 { 937 /* automatic check from user's database */ 938 if (SslCertFile && check_certificate_by_digest (cert)) 939 { 940 dprint (2, (debugfile, "ssl_verify_callback: digest check passed\n")); 941 return 1; 942 } 943 944#ifdef DEBUG 945 /* log verification error */ 946 { 947 int err = X509_STORE_CTX_get_error (ctx); 948 snprintf (buf, sizeof (buf), "%s (%d)", 949 X509_verify_cert_error_string (err), err); 950 dprint (2, (debugfile, "X509_verify_cert: %s\n", buf)); 951 } 952#endif 953 954 /* prompt user */ 955 return interactive_check_cert (cert, pos, len); 956 } 957 958 return 1; 959} 960 961static int interactive_check_cert (X509 *cert, int idx, int len) 962{ 963 static const int part[] = 964 { NID_commonName, /* CN */ 965 NID_pkcs9_emailAddress, /* Email */ 966 NID_organizationName, /* O */ 967 NID_organizationalUnitName, /* OU */ 968 NID_localityName, /* L */ 969 NID_stateOrProvinceName, /* ST */ 970 NID_countryName /* C */ }; 971 X509_NAME *x509_subject; 972 X509_NAME *x509_issuer; 973 char helpstr[LONG_STRING]; 974 char buf[STRING]; 975 char title[STRING]; 976 MUTTMENU *menu = mutt_new_menu (MENU_GENERIC); 977 int done, row, i; 978 FILE *fp; 979 980 menu->max = mutt_array_size (part) * 2 + 9; 981 menu->dialog = (char **) safe_calloc (1, menu->max * sizeof (char *)); 982 for (i = 0; i < menu->max; i++) 983 menu->dialog[i] = (char *) safe_calloc (1, SHORT_STRING * sizeof (char)); 984 985 row = 0; 986 strfcpy (menu->dialog[row], _("This certificate belongs to:"), SHORT_STRING); 987 row++; 988 x509_subject = X509_get_subject_name (cert); 989 for (i = 0; i < mutt_array_size (part); i++) 990 snprintf (menu->dialog[row++], SHORT_STRING, " %s", 991 x509_get_part (x509_subject, part[i])); 992 993 row++; 994 strfcpy (menu->dialog[row], _("This certificate was issued by:"), SHORT_STRING); 995 row++; 996 x509_issuer = X509_get_issuer_name (cert); 997 for (i = 0; i < mutt_array_size (part); i++) 998 snprintf (menu->dialog[row++], SHORT_STRING, " %s", 999 x509_get_part (x509_issuer, part[i])); 1000 1001 row++; 1002 snprintf (menu->dialog[row++], SHORT_STRING, _("This certificate is valid")); 1003 snprintf (menu->dialog[row++], SHORT_STRING, _(" from %s"), 1004 asn1time_to_string (X509_get_notBefore (cert))); 1005 snprintf (menu->dialog[row++], SHORT_STRING, _(" to %s"), 1006 asn1time_to_string (X509_get_notAfter (cert))); 1007 1008 row++; 1009 buf[0] = '\0'; 1010 x509_fingerprint (buf, sizeof (buf), cert); 1011 snprintf (menu->dialog[row++], SHORT_STRING, _("Fingerprint: %s"), buf); 1012 1013 snprintf (title, sizeof (title), 1014 _("SSL Certificate check (certificate %d of %d in chain)"), 1015 len - idx, len); 1016 menu->title = title; 1017 if (SslCertFile 1018 && (option (OPTSSLVERIFYDATES) == MUTT_NO 1019 || (X509_cmp_current_time (X509_get_notAfter (cert)) >= 0 1020 && X509_cmp_current_time (X509_get_notBefore (cert)) < 0))) 1021 { 1022 menu->prompt = _("(r)eject, accept (o)nce, (a)ccept always"); 1023 menu->keys = _("roa"); 1024 } 1025 else 1026 { 1027 menu->prompt = _("(r)eject, accept (o)nce"); 1028 menu->keys = _("ro"); 1029 } 1030 1031 helpstr[0] = '\0'; 1032 mutt_make_help (buf, sizeof (buf), _("Exit "), MENU_GENERIC, OP_EXIT); 1033 safe_strcat (helpstr, sizeof (helpstr), buf); 1034 mutt_make_help (buf, sizeof (buf), _("Help"), MENU_GENERIC, OP_HELP); 1035 safe_strcat (helpstr, sizeof (helpstr), buf); 1036 menu->help = helpstr; 1037 1038 done = 0; 1039 set_option(OPTIGNOREMACROEVENTS); 1040 while (!done) 1041 { 1042 switch (mutt_menuLoop (menu)) 1043 { 1044 case -1: /* abort */ 1045 case OP_MAX + 1: /* reject */ 1046 case OP_EXIT: 1047 done = 1; 1048 break; 1049 case OP_MAX + 3: /* accept always */ 1050 done = 0; 1051 if ((fp = fopen (SslCertFile, "a"))) 1052 { 1053 if (PEM_write_X509 (fp, cert)) 1054 done = 1; 1055 safe_fclose (&fp); 1056 } 1057 if (!done) 1058 { 1059 mutt_error (_("Warning: Couldn't save certificate")); 1060 mutt_sleep (2); 1061 } 1062 else 1063 { 1064 mutt_message (_("Certificate saved")); 1065 mutt_sleep (0); 1066 } 1067 /* fall through */ 1068 case OP_MAX + 2: /* accept once */ 1069 done = 2; 1070 ssl_cache_trusted_cert (cert); 1071 break; 1072 } 1073 } 1074 unset_option(OPTIGNOREMACROEVENTS); 1075 mutt_menuDestroy (&menu); 1076 set_option (OPTNEEDREDRAW); 1077 dprint (2, (debugfile, "ssl interactive_check_cert: done=%d\n", done)); 1078 return (done == 2); 1079} 1080 1081static void ssl_get_client_cert(sslsockdata *ssldata, CONNECTION *conn) 1082{ 1083 if (SslClientCert) 1084 { 1085 dprint (2, (debugfile, "Using client certificate %s\n", SslClientCert)); 1086 SSL_CTX_set_default_passwd_cb_userdata(ssldata->ctx, &conn->account); 1087 SSL_CTX_set_default_passwd_cb(ssldata->ctx, ssl_passwd_cb); 1088 SSL_CTX_use_certificate_file(ssldata->ctx, SslClientCert, SSL_FILETYPE_PEM); 1089 SSL_CTX_use_PrivateKey_file(ssldata->ctx, SslClientCert, SSL_FILETYPE_PEM); 1090 1091 /* if we are using a client cert, SASL may expect an external auth name */ 1092 mutt_account_getuser (&conn->account); 1093 } 1094} 1095 1096static int ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata) 1097{ 1098 ACCOUNT *account = (ACCOUNT*)userdata; 1099 1100 if (mutt_account_getuser (account)) 1101 return 0; 1102 1103 dprint (2, (debugfile, "ssl_passwd_cb: getting password for %s@%s:%u\n", 1104 account->user, account->host, account->port)); 1105 1106 if (mutt_account_getpass (account)) 1107 return 0; 1108 1109 return snprintf(buf, size, "%s", account->pass); 1110}