mutt stable branch with some hacks
at jcs 1418 lines 38 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/x509_vfy.h> 27#include <openssl/err.h> 28#include <openssl/rand.h> 29#include <openssl/evp.h> 30 31/* LibreSSL defines OPENSSL_VERSION_NUMBER but sets it to 0x20000000L. 32 * So technically we don't need the defined(OPENSSL_VERSION_NUMBER) check. 33 */ 34#if (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L) || \ 35 (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL) 36#define X509_get0_notBefore X509_get_notBefore 37#define X509_get0_notAfter X509_get_notAfter 38#define X509_getm_notBefore X509_get_notBefore 39#define X509_getm_notAfter X509_get_notAfter 40#define X509_STORE_CTX_get0_chain X509_STORE_CTX_get_chain 41#define SSL_has_pending SSL_pending 42#endif 43 44/* Unimplemented OpenSSL 1.1 api calls */ 45#if (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x2070000fL) 46#define SSL_has_pending SSL_pending 47#endif 48 49#undef _ 50 51#include <string.h> 52 53#include "mutt.h" 54#include "mutt_socket.h" 55#include "mutt_menu.h" 56#include "mutt_curses.h" 57#include "mutt_ssl.h" 58#include "mutt_idna.h" 59 60/* Just in case OpenSSL doesn't define DEVRANDOM */ 61#ifndef DEVRANDOM 62#define DEVRANDOM "/dev/urandom" 63#endif 64 65/* This is ugly, but as RAND_status came in on OpenSSL version 0.9.5 66 * and the code has to support older versions too, this is seemed to 67 * be cleaner way compared to having even uglier #ifdefs all around. 68 */ 69#ifdef HAVE_RAND_STATUS 70#define HAVE_ENTROPY() (RAND_status() == 1) 71#else 72static int entropy_byte_count = 0; 73/* OpenSSL fills the entropy pool from /dev/urandom if it exists */ 74#define HAVE_ENTROPY() (!access(DEVRANDOM, R_OK) || entropy_byte_count >= 16) 75#endif 76 77/* index for storing hostname as application specific data in SSL structure */ 78static int HostExDataIndex = -1; 79 80/* Index for storing the "skip mode" state in SSL structure. When the 81 * user skips a certificate in the chain, the stored value will be 82 * non-null. */ 83static int SkipModeExDataIndex = -1; 84 85/* keep a handle on accepted certificates in case we want to 86 * open up another connection to the same server in this session */ 87static STACK_OF(X509) *SslSessionCerts = NULL; 88 89typedef struct 90{ 91 SSL_CTX *ctx; 92 SSL *ssl; 93 X509 *cert; 94 unsigned char isopen; 95} 96sslsockdata; 97 98/* local prototypes */ 99static int ssl_init (void); 100static int add_entropy (const char *file); 101static int ssl_socket_read (CONNECTION* conn, char* buf, size_t len); 102static int ssl_socket_write (CONNECTION* conn, const char* buf, size_t len); 103static int ssl_socket_poll (CONNECTION* conn, time_t wait_secs); 104static int ssl_socket_open (CONNECTION * conn); 105static int ssl_socket_close (CONNECTION * conn); 106static int tls_close (CONNECTION* conn); 107static void ssl_err (sslsockdata *data, int err); 108static void ssl_dprint_err_stack (void); 109static int ssl_cache_trusted_cert (X509 *cert); 110static int ssl_verify_callback (int preverify_ok, X509_STORE_CTX *ctx); 111static int interactive_check_cert (X509 *cert, int idx, int len, SSL *ssl, int allow_always); 112static void ssl_get_client_cert(sslsockdata *ssldata, CONNECTION *conn); 113static int ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata); 114static int ssl_negotiate (CONNECTION *conn, sslsockdata*); 115 116/* ssl certificate verification can behave strangely if there are expired 117 * certs loaded into the trusted store. This function filters out expired 118 * certs. 119 * Previously the code used this form: 120 * SSL_CTX_load_verify_locations (ssldata->ctx, SslCertFile, NULL); 121 */ 122static int ssl_load_certificates (SSL_CTX *ctx) 123{ 124 FILE *fp; 125 X509 *cert = NULL; 126 X509_STORE *store; 127 char buf[STRING]; 128 int rv = 1; 129 130 dprint (2, (debugfile, "ssl_load_certificates: loading trusted certificates\n")); 131 store = SSL_CTX_get_cert_store (ctx); 132 if (!store) 133 { 134 store = X509_STORE_new (); 135 SSL_CTX_set_cert_store (ctx, store); 136 } 137 138 if ((fp = fopen (SslCertFile, "rt")) == NULL) 139 return 0; 140 141 while (NULL != PEM_read_X509 (fp, &cert, NULL, NULL)) 142 { 143 if ((X509_cmp_current_time (X509_get0_notBefore (cert)) >= 0) || 144 (X509_cmp_current_time (X509_get0_notAfter (cert)) <= 0)) 145 { 146 dprint (2, (debugfile, "ssl_load_certificates: filtering expired cert: %s\n", 147 X509_NAME_oneline (X509_get_subject_name (cert), buf, sizeof (buf)))); 148 } 149 else 150 { 151 X509_STORE_add_cert (store, cert); 152 } 153 } 154 /* PEM_read_X509 sets the error NO_START_LINE on eof */ 155 if (ERR_GET_REASON(ERR_peek_last_error()) != PEM_R_NO_START_LINE) 156 rv = 0; 157 ERR_clear_error(); 158 159 X509_free (cert); 160 safe_fclose (&fp); 161 162 return rv; 163} 164 165static int ssl_set_verify_partial (SSL_CTX *ctx) 166{ 167 int rv = 0; 168#ifdef HAVE_SSL_PARTIAL_CHAIN 169 X509_VERIFY_PARAM *param; 170 171 if (option (OPTSSLVERIFYPARTIAL)) 172 { 173 param = X509_VERIFY_PARAM_new(); 174 if (param) 175 { 176 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_PARTIAL_CHAIN); 177 if (0 == SSL_CTX_set1_param(ctx, param)) 178 { 179 dprint (2, (debugfile, "ssl_set_verify_partial: SSL_CTX_set1_param() failed.")); 180 rv = -1; 181 } 182 X509_VERIFY_PARAM_free(param); 183 } 184 else 185 { 186 dprint (2, (debugfile, "ssl_set_verify_partial: X509_VERIFY_PARAM_new() failed.")); 187 rv = -1; 188 } 189 } 190#endif 191 return rv; 192} 193 194/* mutt_ssl_starttls: Negotiate TLS over an already opened connection. 195 * TODO: Merge this code better with ssl_socket_open. */ 196int mutt_ssl_starttls (CONNECTION* conn) 197{ 198 sslsockdata* ssldata; 199 int maxbits; 200 long ssl_options = 0; 201 202 if (ssl_init()) 203 goto bail; 204 205 ssldata = (sslsockdata*) safe_calloc (1, sizeof (sslsockdata)); 206 /* the ssl_use_xxx protocol options don't apply. We must use TLS in TLS. 207 * 208 * However, we need to be able to negotiate amongst various TLS versions, 209 * which at present can only be done with the SSLv23_client_method; 210 * TLSv1_client_method gives us explicitly TLSv1.0, not 1.1 or 1.2 (True as 211 * of OpenSSL 1.0.1c) 212 */ 213 if (! (ssldata->ctx = SSL_CTX_new (SSLv23_client_method()))) 214 { 215 dprint (1, (debugfile, "mutt_ssl_starttls: Error allocating SSL_CTX\n")); 216 goto bail_ssldata; 217 } 218#ifdef SSL_OP_NO_TLSv1_3 219 if (!option(OPTTLSV1_3)) 220 ssl_options |= SSL_OP_NO_TLSv1_3; 221#endif 222#ifdef SSL_OP_NO_TLSv1_2 223 if (!option(OPTTLSV1_2)) 224 ssl_options |= SSL_OP_NO_TLSv1_2; 225#endif 226#ifdef SSL_OP_NO_TLSv1_1 227 if (!option(OPTTLSV1_1)) 228 ssl_options |= SSL_OP_NO_TLSv1_1; 229#endif 230#ifdef SSL_OP_NO_TLSv1 231 if (!option(OPTTLSV1)) 232 ssl_options |= SSL_OP_NO_TLSv1; 233#endif 234 /* these are always set */ 235#ifdef SSL_OP_NO_SSLv3 236 ssl_options |= SSL_OP_NO_SSLv3; 237#endif 238#ifdef SSL_OP_NO_SSLv2 239 ssl_options |= SSL_OP_NO_SSLv2; 240#endif 241 if (! SSL_CTX_set_options(ssldata->ctx, ssl_options)) 242 { 243 dprint(1, (debugfile, "mutt_ssl_starttls: Error setting options to %ld\n", ssl_options)); 244 goto bail_ctx; 245 } 246 247 if (option (OPTSSLSYSTEMCERTS)) 248 { 249 if (! SSL_CTX_set_default_verify_paths (ssldata->ctx)) 250 { 251 dprint (1, (debugfile, "mutt_ssl_starttls: Error setting default verify paths\n")); 252 goto bail_ctx; 253 } 254 } 255 256 if (SslCertFile && !ssl_load_certificates (ssldata->ctx)) 257 dprint (1, (debugfile, "mutt_ssl_starttls: Error loading trusted certificates\n")); 258 259 ssl_get_client_cert(ssldata, conn); 260 261 if (SslCiphers) 262 { 263 if (!SSL_CTX_set_cipher_list (ssldata->ctx, SslCiphers)) 264 { 265 dprint (1, (debugfile, "mutt_ssl_starttls: Could not select preferred ciphers\n")); 266 goto bail_ctx; 267 } 268 } 269 270 if (ssl_set_verify_partial (ssldata->ctx)) 271 { 272 mutt_error (_("Warning: error enabling ssl_verify_partial_chains")); 273 mutt_sleep (2); 274 } 275 276 if (! (ssldata->ssl = SSL_new (ssldata->ctx))) 277 { 278 dprint (1, (debugfile, "mutt_ssl_starttls: Error allocating SSL\n")); 279 goto bail_ctx; 280 } 281 282 if (SSL_set_fd (ssldata->ssl, conn->fd) != 1) 283 { 284 dprint (1, (debugfile, "mutt_ssl_starttls: Error setting fd\n")); 285 goto bail_ssl; 286 } 287 288 if (ssl_negotiate (conn, ssldata)) 289 goto bail_ssl; 290 291 ssldata->isopen = 1; 292 293 /* hmm. watch out if we're starting TLS over any method other than raw. */ 294 conn->sockdata = ssldata; 295 conn->conn_read = ssl_socket_read; 296 conn->conn_write = ssl_socket_write; 297 conn->conn_close = tls_close; 298 conn->conn_poll = ssl_socket_poll; 299 300 conn->ssf = SSL_CIPHER_get_bits (SSL_get_current_cipher (ssldata->ssl), 301 &maxbits); 302 303 return 0; 304 305bail_ssl: 306 SSL_free (ssldata->ssl); 307 ssldata->ssl = 0; 308bail_ctx: 309 SSL_CTX_free (ssldata->ctx); 310 ssldata->ctx = 0; 311bail_ssldata: 312 FREE (&ssldata); 313bail: 314 return -1; 315} 316 317/* 318 * OpenSSL library needs to be fed with sufficient entropy. On systems 319 * with /dev/urandom, this is done transparently by the library itself, 320 * on other systems we need to fill the entropy pool ourselves. 321 * 322 * Even though only OpenSSL 0.9.5 and later will complain about the 323 * lack of entropy, we try to our best and fill the pool with older 324 * versions also. (That's the reason for the ugly #ifdefs and macros, 325 * otherwise I could have simply #ifdef'd the whole ssl_init function) 326 */ 327static int ssl_init (void) 328{ 329 BUFFER *path = NULL; 330 static unsigned char init_complete = 0; 331 332 if (init_complete) 333 return 0; 334 335 if (! HAVE_ENTROPY()) 336 { 337 /* load entropy from files */ 338 add_entropy (SslEntropyFile); 339 340 path = mutt_buffer_pool_get (); 341 add_entropy (RAND_file_name (path->data, path->dsize)); 342 343 /* load entropy from egd sockets */ 344#ifdef HAVE_RAND_EGD 345 add_entropy (getenv ("EGDSOCKET")); 346 mutt_buffer_printf (path, "%s/.entropy", NONULL(Homedir)); 347 add_entropy (mutt_b2s (path)); 348 add_entropy ("/tmp/entropy"); 349#endif 350 351 /* shuffle $RANDFILE (or ~/.rnd if unset) */ 352 RAND_write_file (RAND_file_name (path->data, path->dsize)); 353 mutt_buffer_pool_release (&path); 354 355 mutt_clear_error (); 356 if (! HAVE_ENTROPY()) 357 { 358 mutt_error (_("Failed to find enough entropy on your system")); 359 mutt_sleep (2); 360 return -1; 361 } 362 } 363 364/* OpenSSL performs automatic initialization as of 1.1. 365 * However LibreSSL does not (as of 2.8.3). */ 366#if (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L) || \ 367 (defined(LIBRESSL_VERSION_NUMBER)) 368 /* I don't think you can do this just before reading the error. The call 369 * itself might clobber the last SSL error. */ 370 SSL_load_error_strings(); 371 SSL_library_init(); 372#endif 373 init_complete = 1; 374 return 0; 375} 376 377static int add_entropy (const char *file) 378{ 379 struct stat st; 380 int n = -1; 381 382 if (!file) return 0; 383 384 if (stat (file, &st) == -1) 385 return errno == ENOENT ? 0 : -1; 386 387 mutt_message (_("Filling entropy pool: %s...\n"), 388 file); 389 390 /* check that the file permissions are secure */ 391 if (st.st_uid != getuid () || 392 ((st.st_mode & (S_IWGRP | S_IRGRP)) != 0) || 393 ((st.st_mode & (S_IWOTH | S_IROTH)) != 0)) 394 { 395 mutt_error (_("%s has insecure permissions!"), file); 396 mutt_sleep (2); 397 return -1; 398 } 399 400#ifdef HAVE_RAND_EGD 401 n = RAND_egd (file); 402#endif 403 if (n <= 0) 404 n = RAND_load_file (file, -1); 405 406#ifndef HAVE_RAND_STATUS 407 if (n > 0) entropy_byte_count += n; 408#endif 409 return n; 410} 411 412static int ssl_socket_open_err (CONNECTION *conn) 413{ 414 mutt_error (_("SSL disabled due to the lack of entropy")); 415 mutt_sleep (2); 416 return -1; 417} 418 419 420int mutt_ssl_socket_setup (CONNECTION * conn) 421{ 422 if (ssl_init() < 0) 423 { 424 conn->conn_open = ssl_socket_open_err; 425 return -1; 426 } 427 428 conn->conn_open = ssl_socket_open; 429 conn->conn_read = ssl_socket_read; 430 conn->conn_write = ssl_socket_write; 431 conn->conn_close = ssl_socket_close; 432 conn->conn_poll = ssl_socket_poll; 433 434 return 0; 435} 436 437static int ssl_socket_read (CONNECTION* conn, char* buf, size_t len) 438{ 439 sslsockdata *data = conn->sockdata; 440 int rc; 441 442 rc = SSL_read (data->ssl, buf, len); 443 if (rc <= 0) 444 { 445 data->isopen = 0; 446 ssl_err (data, rc); 447 } 448 449 return rc; 450} 451 452static int ssl_socket_write (CONNECTION* conn, const char* buf, size_t len) 453{ 454 sslsockdata *data = conn->sockdata; 455 int rc; 456 457 rc = SSL_write (data->ssl, buf, len); 458 if (rc <= 0) 459 ssl_err (data, rc); 460 461 return rc; 462} 463 464static int ssl_socket_poll (CONNECTION* conn, time_t wait_secs) 465{ 466 sslsockdata *data = conn->sockdata; 467 468 if (!data) 469 return -1; 470 471 if (SSL_has_pending (data->ssl)) 472 return 1; 473 else 474 return raw_socket_poll (conn, wait_secs); 475} 476 477static int ssl_socket_open (CONNECTION * conn) 478{ 479 sslsockdata *data; 480 int maxbits; 481 482 if (raw_socket_open (conn) < 0) 483 return -1; 484 485 data = (sslsockdata *) safe_calloc (1, sizeof (sslsockdata)); 486 conn->sockdata = data; 487 488 if (! (data->ctx = SSL_CTX_new (SSLv23_client_method ()))) 489 { 490 /* L10N: an SSL context is a data structure returned by the OpenSSL 491 * function SSL_CTX_new(). In this case it returned NULL: an 492 * error condition. 493 */ 494 mutt_error (_("Unable to create SSL context")); 495 ssl_dprint_err_stack (); 496 mutt_socket_close (conn); 497 return -1; 498 } 499 500 /* disable SSL protocols as needed */ 501 if (!option(OPTTLSV1)) 502 { 503 SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1); 504 } 505 /* TLSv1.1/1.2 support was added in OpenSSL 1.0.1, but some OS distros such 506 * as Fedora 17 are on OpenSSL 1.0.0. 507 */ 508#ifdef SSL_OP_NO_TLSv1_1 509 if (!option(OPTTLSV1_1)) 510 { 511 SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1_1); 512 } 513#endif 514#ifdef SSL_OP_NO_TLSv1_2 515 if (!option(OPTTLSV1_2)) 516 { 517 SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1_2); 518 } 519#endif 520#ifdef SSL_OP_NO_TLSv1_3 521 if (!option(OPTTLSV1_3)) 522 { 523 SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1_3); 524 } 525#endif 526 if (!option(OPTSSLV2)) 527 { 528 SSL_CTX_set_options(data->ctx, SSL_OP_NO_SSLv2); 529 } 530 if (!option(OPTSSLV3)) 531 { 532 SSL_CTX_set_options(data->ctx, SSL_OP_NO_SSLv3); 533 } 534 535 if (option (OPTSSLSYSTEMCERTS)) 536 { 537 if (! SSL_CTX_set_default_verify_paths (data->ctx)) 538 { 539 dprint (1, (debugfile, "ssl_socket_open: Error setting default verify paths\n")); 540 mutt_socket_close (conn); 541 return -1; 542 } 543 } 544 545 if (SslCertFile && !ssl_load_certificates (data->ctx)) 546 dprint (1, (debugfile, "ssl_socket_open: Error loading trusted certificates\n")); 547 548 ssl_get_client_cert(data, conn); 549 550 if (SslCiphers) 551 { 552 SSL_CTX_set_cipher_list (data->ctx, SslCiphers); 553 } 554 555 if (ssl_set_verify_partial (data->ctx)) 556 { 557 mutt_error (_("Warning: error enabling ssl_verify_partial_chains")); 558 mutt_sleep (2); 559 } 560 561 data->ssl = SSL_new (data->ctx); 562 SSL_set_fd (data->ssl, conn->fd); 563 564 if (ssl_negotiate(conn, data)) 565 { 566 mutt_socket_close (conn); 567 return -1; 568 } 569 570 data->isopen = 1; 571 572 conn->ssf = SSL_CIPHER_get_bits (SSL_get_current_cipher (data->ssl), 573 &maxbits); 574 575 return 0; 576} 577 578/* ssl_negotiate: After SSL state has been initialized, attempt to negotiate 579 * SSL over the wire, including certificate checks. */ 580static int ssl_negotiate (CONNECTION *conn, sslsockdata* ssldata) 581{ 582 int err; 583 const char* errmsg; 584 585 if ((HostExDataIndex = SSL_get_ex_new_index (0, "host", NULL, NULL, NULL)) == -1) 586 { 587 dprint (1, (debugfile, "failed to get index for application specific data\n")); 588 return -1; 589 } 590 591 if (! SSL_set_ex_data (ssldata->ssl, HostExDataIndex, conn->account.host)) 592 { 593 dprint (1, (debugfile, "failed to save hostname in SSL structure\n")); 594 return -1; 595 } 596 597 if ((SkipModeExDataIndex = SSL_get_ex_new_index (0, "skip", NULL, NULL, NULL)) == -1) 598 { 599 dprint (1, (debugfile, "failed to get index for application specific data\n")); 600 return -1; 601 } 602 603 if (! SSL_set_ex_data (ssldata->ssl, SkipModeExDataIndex, NULL)) 604 { 605 dprint (1, (debugfile, "failed to save skip mode in SSL structure\n")); 606 return -1; 607 } 608 609 SSL_set_verify (ssldata->ssl, SSL_VERIFY_PEER, ssl_verify_callback); 610 SSL_set_mode (ssldata->ssl, SSL_MODE_AUTO_RETRY); 611 612 if (!SSL_set_tlsext_host_name (ssldata->ssl, conn->account.host)) 613 { 614 /* L10N: This is a warning when trying to set the host name for 615 * TLS Server Name Indication (SNI). This allows the server to present 616 * the correct certificate if it supports multiple hosts. */ 617 mutt_error _("Warning: unable to set TLS SNI host name"); 618 mutt_sleep (1); 619 } 620 621 ERR_clear_error (); 622 623 if ((err = SSL_connect (ssldata->ssl)) != 1) 624 { 625 switch (SSL_get_error (ssldata->ssl, err)) 626 { 627 case SSL_ERROR_SYSCALL: 628 errmsg = _("I/O error"); 629 break; 630 case SSL_ERROR_SSL: 631 errmsg = ERR_error_string (ERR_get_error (), NULL); 632 break; 633 default: 634 errmsg = _("unknown error"); 635 } 636 637 mutt_error (_("SSL failed: %s"), errmsg); 638 mutt_sleep (1); 639 640 return -1; 641 } 642 643 /* L10N: 644 %1$s is version (e.g. "TLSv1.2") 645 %2$s is cipher_version (e.g. "TLSv1/SSLv3") 646 %3$s is cipher_name (e.g. "ECDHE-RSA-AES128-GCM-SHA256") */ 647 mutt_message (_("%s connection using %s (%s)"), 648 SSL_get_version(ssldata->ssl), 649 SSL_get_cipher_version (ssldata->ssl), 650 SSL_get_cipher_name (ssldata->ssl)); 651 652 return 0; 653} 654 655static int ssl_socket_close (CONNECTION * conn) 656{ 657 sslsockdata *data = conn->sockdata; 658 if (data) 659 { 660 if (data->isopen) 661 SSL_shutdown (data->ssl); 662 663 /* hold onto this for the life of mutt, in case we want to reconnect. 664 * The purist in me wants a mutt_exit hook. */ 665#if 0 666 X509_free (data->cert); 667#endif 668 SSL_free (data->ssl); 669 SSL_CTX_free (data->ctx); 670 FREE (&conn->sockdata); 671 } 672 673 return raw_socket_close (conn); 674} 675 676static int tls_close (CONNECTION* conn) 677{ 678 int rc; 679 680 rc = ssl_socket_close (conn); 681 conn->conn_read = raw_socket_read; 682 conn->conn_write = raw_socket_write; 683 conn->conn_close = raw_socket_close; 684 conn->conn_poll = raw_socket_poll; 685 686 return rc; 687} 688 689static void ssl_err (sslsockdata *data, int err) 690{ 691 const char* errmsg; 692 unsigned long sslerr; 693 694 switch (SSL_get_error (data->ssl, err)) 695 { 696 case SSL_ERROR_NONE: 697 return; 698 case SSL_ERROR_ZERO_RETURN: 699 errmsg = "SSL connection closed"; 700 data->isopen = 0; 701 break; 702 case SSL_ERROR_WANT_READ: 703 errmsg = "retry read"; 704 break; 705 case SSL_ERROR_WANT_WRITE: 706 errmsg = "retry write"; 707 break; 708 case SSL_ERROR_WANT_CONNECT: 709 errmsg = "retry connect"; 710 break; 711 case SSL_ERROR_WANT_ACCEPT: 712 errmsg = "retry accept"; 713 break; 714 case SSL_ERROR_WANT_X509_LOOKUP: 715 errmsg = "retry x509 lookup"; 716 break; 717 case SSL_ERROR_SYSCALL: 718 errmsg = "I/O error"; 719 data->isopen = 0; 720 break; 721 case SSL_ERROR_SSL: 722 sslerr = ERR_get_error (); 723 switch (sslerr) 724 { 725 case 0: 726 switch (err) 727 { 728 case 0: 729 errmsg = "EOF"; 730 break; 731 default: 732 errmsg = strerror(errno); 733 } 734 break; 735 default: 736 errmsg = ERR_error_string (sslerr, NULL); 737 } 738 break; 739 default: 740 errmsg = "unknown error"; 741 } 742 743 dprint (1, (debugfile, "SSL error: %s\n", errmsg)); 744} 745 746static void ssl_dprint_err_stack (void) 747{ 748#ifdef DEBUG 749 BIO *bio; 750 char *buf = NULL; 751 long buflen; 752 char *output; 753 754 if (! (bio = BIO_new (BIO_s_mem ()))) 755 return; 756 ERR_print_errors (bio); 757 if ((buflen = BIO_get_mem_data (bio, &buf)) > 0) 758 { 759 output = safe_malloc (buflen + 1); 760 memcpy (output, buf, buflen); 761 output[buflen] = '\0'; 762 dprint (1, (debugfile, "SSL error stack: %s\n", output)); 763 FREE (&output); 764 } 765 BIO_free (bio); 766#endif 767} 768 769 770static char *x509_get_part (X509_NAME *name, int nid) 771{ 772 static char ret[SHORT_STRING]; 773 774 if (!name || 775 X509_NAME_get_text_by_NID (name, nid, ret, sizeof (ret)) < 0) 776 strfcpy (ret, _("Unknown"), sizeof (ret)); 777 778 return ret; 779} 780 781static void x509_fingerprint (char *s, int l, X509 * cert, const EVP_MD *(*hashfunc)(void)) 782{ 783 unsigned char md[EVP_MAX_MD_SIZE]; 784 unsigned int n; 785 int j; 786 787 if (!X509_digest (cert, hashfunc(), md, &n)) 788 { 789 snprintf (s, l, "%s", _("[unable to calculate]")); 790 } 791 else 792 { 793 for (j = 0; j < (int) n; j++) 794 { 795 char ch[8]; 796 snprintf (ch, 8, "%02X%s", md[j], (j % 2 ? " " : "")); 797 safe_strcat (s, l, ch); 798 } 799 } 800} 801 802static char *asn1time_to_string (ASN1_UTCTIME *tm) 803{ 804 static char buf[64]; 805 BIO *bio; 806 807 strfcpy (buf, _("[invalid date]"), sizeof (buf)); 808 809 bio = BIO_new (BIO_s_mem()); 810 if (bio) 811 { 812 if (ASN1_TIME_print (bio, tm)) 813 (void) BIO_read (bio, buf, sizeof (buf)); 814 BIO_free (bio); 815 } 816 817 return buf; 818} 819 820static int compare_certificates (X509 *cert, X509 *peercert, 821 unsigned char *peermd, unsigned int peermdlen) 822{ 823 unsigned char md[EVP_MAX_MD_SIZE]; 824 unsigned int mdlen; 825 826 /* Avoid CPU-intensive digest calculation if the certificates are 827 * not even remotely equal. 828 */ 829 if (X509_subject_name_cmp (cert, peercert) != 0 || 830 X509_issuer_name_cmp (cert, peercert) != 0) 831 return -1; 832 833 if (!X509_digest (cert, EVP_sha256(), md, &mdlen) || peermdlen != mdlen) 834 return -1; 835 836 if (memcmp(peermd, md, mdlen) != 0) 837 return -1; 838 839 return 0; 840} 841 842static int check_certificate_cache (X509 *peercert) 843{ 844 unsigned char peermd[EVP_MAX_MD_SIZE]; 845 unsigned int peermdlen; 846 X509 *cert; 847 int i; 848 849 if (!X509_digest (peercert, EVP_sha256(), peermd, &peermdlen) 850 || !SslSessionCerts) 851 { 852 return 0; 853 } 854 855 for (i = sk_X509_num (SslSessionCerts); i-- > 0;) 856 { 857 cert = sk_X509_value (SslSessionCerts, i); 858 if (!compare_certificates (cert, peercert, peermd, peermdlen)) 859 { 860 return 1; 861 } 862 } 863 864 return 0; 865} 866 867static int check_certificate_expiration (X509 *peercert, int silent) 868{ 869 if (option (OPTSSLVERIFYDATES) != MUTT_NO) 870 { 871 if (X509_cmp_current_time (X509_get0_notBefore (peercert)) >= 0) 872 { 873 if (!silent) 874 { 875 dprint (2, (debugfile, "Server certificate is not yet valid\n")); 876 mutt_error (_("Server certificate is not yet valid")); 877 mutt_sleep (2); 878 } 879 return 0; 880 } 881 if (X509_cmp_current_time (X509_get0_notAfter (peercert)) <= 0) 882 { 883 if (!silent) 884 { 885 dprint (2, (debugfile, "Server certificate has expired\n")); 886 mutt_error (_("Server certificate has expired")); 887 mutt_sleep (2); 888 } 889 return 0; 890 } 891 } 892 893 return 1; 894} 895 896static int check_certificate_file (X509 *peercert) 897{ 898 unsigned char peermd[EVP_MAX_MD_SIZE]; 899 unsigned int peermdlen; 900 X509 *cert = NULL; 901 int pass = 0; 902 FILE *fp; 903 904 if (!SslCertFile) 905 return 0; 906 907 if ((fp = fopen (SslCertFile, "rt")) == NULL) 908 return 0; 909 910 if (!X509_digest (peercert, EVP_sha256(), peermd, &peermdlen)) 911 { 912 safe_fclose (&fp); 913 return 0; 914 } 915 916 while (PEM_read_X509 (fp, &cert, NULL, NULL) != NULL) 917 { 918 if ((compare_certificates (cert, peercert, peermd, peermdlen) == 0) && 919 check_certificate_expiration (cert, 1)) 920 { 921 pass = 1; 922 break; 923 } 924 } 925 /* PEM_read_X509 sets an error on eof */ 926 if (!pass) 927 ERR_clear_error(); 928 X509_free (cert); 929 safe_fclose (&fp); 930 931 return pass; 932} 933 934static int check_certificate_by_digest (X509 *peercert) 935{ 936 return check_certificate_expiration (peercert, 0) && 937 check_certificate_file (peercert); 938} 939 940/* port to mutt from msmtp's tls.c */ 941static int hostname_match (const char *hostname, const char *certname) 942{ 943 const char *cmp1, *cmp2; 944 945 if (strncmp(certname, "*.", 2) == 0) 946 { 947 cmp1 = certname + 2; 948 cmp2 = strchr(hostname, '.'); 949 if (!cmp2) 950 { 951 return 0; 952 } 953 else 954 { 955 cmp2++; 956 } 957 } 958 else 959 { 960 cmp1 = certname; 961 cmp2 = hostname; 962 } 963 964 if (*cmp1 == '\0' || *cmp2 == '\0') 965 { 966 return 0; 967 } 968 969 if (strcasecmp(cmp1, cmp2) != 0) 970 { 971 return 0; 972 } 973 974 return 1; 975} 976 977/* port to mutt from msmtp's tls.c */ 978static int check_host (X509 *x509cert, const char *hostname, char *err, size_t errlen) 979{ 980 int i, rc = 0; 981 /* hostname in ASCII format: */ 982 char *hostname_ascii = NULL; 983 /* needed to get the common name: */ 984 X509_NAME *x509_subject; 985 char *buf = NULL; 986 int bufsize; 987 /* needed to get the DNS subjectAltNames: */ 988 STACK_OF(GENERAL_NAME) *subj_alt_names; 989 int subj_alt_names_count; 990 GENERAL_NAME *subj_alt_name; 991 /* did we find a name matching hostname? */ 992 int match_found; 993 994 /* Check if 'hostname' matches the one of the subjectAltName extensions of 995 * type DNS or the Common Name (CN). */ 996 997#if defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2) 998 if (idna_to_ascii_lz(hostname, &hostname_ascii, 0) != IDNA_SUCCESS) 999 { 1000 hostname_ascii = safe_strdup(hostname); 1001 } 1002#else 1003 hostname_ascii = safe_strdup(hostname); 1004#endif 1005 1006 /* Try the DNS subjectAltNames. */ 1007 match_found = 0; 1008 if ((subj_alt_names = X509_get_ext_d2i(x509cert, NID_subject_alt_name, 1009 NULL, NULL))) 1010 { 1011 subj_alt_names_count = sk_GENERAL_NAME_num(subj_alt_names); 1012 for (i = 0; i < subj_alt_names_count; i++) 1013 { 1014 subj_alt_name = sk_GENERAL_NAME_value(subj_alt_names, i); 1015 if (subj_alt_name->type == GEN_DNS) 1016 { 1017 if (subj_alt_name->d.ia5->length >= 0 && 1018 mutt_strlen((char *)subj_alt_name->d.ia5->data) == (size_t)subj_alt_name->d.ia5->length && 1019 (match_found = hostname_match(hostname_ascii, 1020 (char *)(subj_alt_name->d.ia5->data)))) 1021 { 1022 break; 1023 } 1024 } 1025 } 1026 GENERAL_NAMES_free(subj_alt_names); 1027 } 1028 1029 if (!match_found) 1030 { 1031 /* Try the common name */ 1032 if (!(x509_subject = X509_get_subject_name(x509cert))) 1033 { 1034 if (err && errlen) 1035 strfcpy (err, _("cannot get certificate subject"), errlen); 1036 goto out; 1037 } 1038 1039 /* first get the space requirements */ 1040 bufsize = X509_NAME_get_text_by_NID(x509_subject, NID_commonName, 1041 NULL, 0); 1042 if (bufsize == -1) 1043 { 1044 if (err && errlen) 1045 strfcpy (err, _("cannot get certificate common name"), errlen); 1046 goto out; 1047 } 1048 bufsize++; /* space for the terminal nul char */ 1049 buf = safe_malloc((size_t)bufsize); 1050 if (X509_NAME_get_text_by_NID(x509_subject, NID_commonName, 1051 buf, bufsize) == -1) 1052 { 1053 if (err && errlen) 1054 strfcpy (err, _("cannot get certificate common name"), errlen); 1055 goto out; 1056 } 1057 /* cast is safe since bufsize is incremented above, so bufsize-1 is always 1058 * zero or greater. 1059 */ 1060 if (mutt_strlen(buf) == (size_t)bufsize - 1) 1061 { 1062 match_found = hostname_match(hostname_ascii, buf); 1063 } 1064 } 1065 1066 if (!match_found) 1067 { 1068 if (err && errlen) 1069 snprintf (err, errlen, _("certificate owner does not match hostname %s"), 1070 hostname); 1071 goto out; 1072 } 1073 1074 rc = 1; 1075 1076out: 1077 FREE(&buf); 1078 FREE(&hostname_ascii); 1079 1080 return rc; 1081} 1082 1083static int ssl_cache_trusted_cert (X509 *c) 1084{ 1085 dprint (1, (debugfile, "ssl_cache_trusted_cert: trusted\n")); 1086 if (!SslSessionCerts) 1087 SslSessionCerts = sk_X509_new_null(); 1088 return (sk_X509_push (SslSessionCerts, X509_dup(c))); 1089} 1090 1091/* certificate verification callback, called for each certificate in the chain 1092 * sent by the peer, starting from the root; returning 1 means that the given 1093 * certificate is trusted, returning 0 immediately aborts the SSL connection */ 1094static int ssl_verify_callback (int preverify_ok, X509_STORE_CTX *ctx) 1095{ 1096 char buf[STRING]; 1097 const char *host; 1098 int len, pos; 1099 X509 *cert; 1100 SSL *ssl; 1101 int skip_mode; 1102#ifdef HAVE_SSL_PARTIAL_CHAIN 1103 static int last_pos = 0; 1104 static X509 *last_cert = NULL; 1105 unsigned char last_cert_md[EVP_MAX_MD_SIZE]; 1106 unsigned int last_cert_mdlen; 1107#endif 1108 1109 if (! (ssl = X509_STORE_CTX_get_ex_data (ctx, SSL_get_ex_data_X509_STORE_CTX_idx ()))) 1110 { 1111 dprint (1, (debugfile, "ssl_verify_callback: failed to retrieve SSL structure from X509_STORE_CTX\n")); 1112 return 0; 1113 } 1114 if (! (host = SSL_get_ex_data (ssl, HostExDataIndex))) 1115 { 1116 dprint (1, (debugfile, "ssl_verify_callback: failed to retrieve hostname from SSL structure\n")); 1117 return 0; 1118 } 1119 1120 /* This is true when a previous entry in the certificate chain did 1121 * not verify and the user manually chose to skip it via the 1122 * $ssl_verify_partial_chains option. 1123 * In this case, all following certificates need to be treated as non-verified 1124 * until one is actually verified. 1125 */ 1126 skip_mode = (SSL_get_ex_data (ssl, SkipModeExDataIndex) != NULL); 1127 1128 cert = X509_STORE_CTX_get_current_cert (ctx); 1129 pos = X509_STORE_CTX_get_error_depth (ctx); 1130 len = sk_X509_num (X509_STORE_CTX_get0_chain (ctx)); 1131 1132 dprint (1, (debugfile, 1133 "ssl_verify_callback: checking cert chain entry %s (preverify: %d skipmode: %d)\n", 1134 X509_NAME_oneline (X509_get_subject_name (cert), buf, sizeof (buf)), 1135 preverify_ok, skip_mode)); 1136 1137#ifdef HAVE_SSL_PARTIAL_CHAIN 1138 /* Sometimes, when a certificate is (s)kipped, OpenSSL will pass it 1139 * a second time with preverify_ok = 1. Don't show it or the user 1140 * will think their "s" key is broken. 1141 */ 1142 if (option (OPTSSLVERIFYPARTIAL)) 1143 { 1144 if (skip_mode && preverify_ok && (pos == last_pos) && last_cert) 1145 { 1146 if (X509_digest (last_cert, EVP_sha256(), last_cert_md, &last_cert_mdlen) && 1147 !compare_certificates (cert, last_cert, last_cert_md, last_cert_mdlen)) 1148 { 1149 dprint (2, (debugfile, 1150 "ssl_verify_callback: ignoring duplicate skipped certificate.\n")); 1151 return 1; 1152 } 1153 } 1154 1155 last_pos = pos; 1156 if (last_cert) 1157 X509_free (last_cert); 1158 last_cert = X509_dup (cert); 1159 } 1160#endif 1161 1162 /* check session cache first */ 1163 if (check_certificate_cache (cert)) 1164 { 1165 dprint (2, (debugfile, "ssl_verify_callback: using cached certificate\n")); 1166 SSL_set_ex_data (ssl, SkipModeExDataIndex, NULL); 1167 return 1; 1168 } 1169 1170 /* check hostname only for the leaf certificate */ 1171 buf[0] = 0; 1172 if (pos == 0 && option (OPTSSLVERIFYHOST) != MUTT_NO) 1173 { 1174 if (!check_host (cert, host, buf, sizeof (buf))) 1175 { 1176 mutt_error (_("Certificate host check failed: %s"), buf); 1177 mutt_sleep (2); 1178 /* we disallow (a)ccept always in the prompt, because it will have no effect 1179 * for hostname mismatches. */ 1180 return interactive_check_cert (cert, pos, len, ssl, 0); 1181 } 1182 dprint (2, (debugfile, "ssl_verify_callback: hostname check passed\n")); 1183 } 1184 1185 if (!preverify_ok || skip_mode) 1186 { 1187 /* automatic check from user's database */ 1188 if (SslCertFile && check_certificate_by_digest (cert)) 1189 { 1190 dprint (2, (debugfile, "ssl_verify_callback: digest check passed\n")); 1191 SSL_set_ex_data (ssl, SkipModeExDataIndex, NULL); 1192 return 1; 1193 } 1194 1195#ifdef DEBUG 1196 /* log verification error */ 1197 { 1198 int err = X509_STORE_CTX_get_error (ctx); 1199 snprintf (buf, sizeof (buf), "%s (%d)", 1200 X509_verify_cert_error_string (err), err); 1201 dprint (2, (debugfile, "X509_verify_cert: %s\n", buf)); 1202 } 1203#endif 1204 1205 /* prompt user */ 1206 return interactive_check_cert (cert, pos, len, ssl, 1); 1207 } 1208 1209 return 1; 1210} 1211 1212static int interactive_check_cert (X509 *cert, int idx, int len, SSL *ssl, int allow_always) 1213{ 1214 static const int part[] = 1215 { NID_commonName, /* CN */ 1216 NID_pkcs9_emailAddress, /* Email */ 1217 NID_organizationName, /* O */ 1218 NID_organizationalUnitName, /* OU */ 1219 NID_localityName, /* L */ 1220 NID_stateOrProvinceName, /* ST */ 1221 NID_countryName /* C */ }; 1222 X509_NAME *x509_subject; 1223 X509_NAME *x509_issuer; 1224 char helpstr[LONG_STRING]; 1225 char buf[STRING]; 1226 char title[STRING]; 1227 MUTTMENU *menu = mutt_new_menu (MENU_GENERIC); 1228 int done; 1229 BUFFER *drow = NULL; 1230 unsigned u; 1231 FILE *fp; 1232 int allow_skip = 0, reset_ignoremacro = 0; 1233 1234 mutt_push_current_menu (menu); 1235 1236 drow = mutt_buffer_pool_get (); 1237 1238 mutt_menu_add_dialog_row (menu, _("This certificate belongs to:")); 1239 x509_subject = X509_get_subject_name (cert); 1240 for (u = 0; u < mutt_array_size (part); u++) 1241 { 1242 mutt_buffer_printf (drow, " %s", x509_get_part (x509_subject, part[u])); 1243 mutt_menu_add_dialog_row (menu, mutt_b2s (drow)); 1244 } 1245 1246 mutt_menu_add_dialog_row (menu, ""); 1247 mutt_menu_add_dialog_row (menu, _("This certificate was issued by:")); 1248 x509_issuer = X509_get_issuer_name (cert); 1249 for (u = 0; u < mutt_array_size (part); u++) 1250 { 1251 mutt_buffer_printf (drow, " %s", x509_get_part (x509_issuer, part[u])); 1252 mutt_menu_add_dialog_row (menu, mutt_b2s (drow)); 1253 } 1254 1255 mutt_menu_add_dialog_row (menu, ""); 1256 mutt_menu_add_dialog_row (menu, _("This certificate is valid")); 1257 mutt_buffer_printf (drow, _(" from %s"), 1258 asn1time_to_string (X509_getm_notBefore (cert))); 1259 mutt_menu_add_dialog_row (menu, mutt_b2s (drow)); 1260 mutt_buffer_printf (drow, _(" to %s"), 1261 asn1time_to_string (X509_getm_notAfter (cert))); 1262 mutt_menu_add_dialog_row (menu, mutt_b2s (drow)); 1263 1264 mutt_menu_add_dialog_row (menu, ""); 1265 buf[0] = '\0'; 1266 x509_fingerprint (buf, sizeof (buf), cert, EVP_sha1); 1267 mutt_buffer_printf (drow, _("SHA1 Fingerprint: %s"), buf); 1268 mutt_menu_add_dialog_row (menu, mutt_b2s (drow)); 1269 buf[0] = '\0'; 1270 buf[40] = '\0'; /* Ensure the second printed line is null terminated */ 1271 x509_fingerprint (buf, sizeof (buf), cert, EVP_sha256); 1272 buf[39] = '\0'; /* Divide into two lines of output */ 1273 mutt_buffer_printf (drow, "%s%s", _("SHA256 Fingerprint: "), buf); 1274 mutt_menu_add_dialog_row (menu, mutt_b2s (drow)); 1275 mutt_buffer_printf (drow, "%*s%s", 1276 (int)mutt_strlen (_("SHA256 Fingerprint: ")), "", buf + 40); 1277 mutt_menu_add_dialog_row (menu, mutt_b2s (drow)); 1278 1279 snprintf (title, sizeof (title), 1280 _("SSL Certificate check (certificate %d of %d in chain)"), 1281 len - idx, len); 1282 menu->title = title; 1283 1284 /* The leaf/host certificate can't be skipped. */ 1285#ifdef HAVE_SSL_PARTIAL_CHAIN 1286 if ((idx != 0) && 1287 (option (OPTSSLVERIFYPARTIAL))) 1288 allow_skip = 1; 1289#endif 1290 1291 /* Inside ssl_verify_callback(), this function is guarded by a call to 1292 * check_certificate_by_digest(). This means if check_certificate_expiration() is 1293 * true, then check_certificate_file() must be false. Therefore we don't need 1294 * to also scan the certificate file here. 1295 */ 1296 allow_always = allow_always && 1297 SslCertFile && 1298 check_certificate_expiration (cert, 1); 1299 1300 /* L10N: 1301 * These four letters correspond to the choices in the next four strings: 1302 * (r)eject, accept (o)nce, (a)ccept always, (s)kip. 1303 * These prompts are the interactive certificate confirmation prompts for 1304 * an OpenSSL connection. 1305 */ 1306 menu->keys = _("roas"); 1307 if (allow_always) 1308 { 1309 if (allow_skip) 1310 menu->prompt = _("(r)eject, accept (o)nce, (a)ccept always, (s)kip"); 1311 else 1312 menu->prompt = _("(r)eject, accept (o)nce, (a)ccept always"); 1313 } 1314 else 1315 { 1316 if (allow_skip) 1317 menu->prompt = _("(r)eject, accept (o)nce, (s)kip"); 1318 else 1319 menu->prompt = _("(r)eject, accept (o)nce"); 1320 } 1321 1322 helpstr[0] = '\0'; 1323 mutt_make_help (buf, sizeof (buf), _("Exit "), MENU_GENERIC, OP_EXIT); 1324 safe_strcat (helpstr, sizeof (helpstr), buf); 1325 mutt_make_help (buf, sizeof (buf), _("Help"), MENU_GENERIC, OP_HELP); 1326 safe_strcat (helpstr, sizeof (helpstr), buf); 1327 menu->help = helpstr; 1328 1329 done = 0; 1330 1331 if (!option (OPTIGNOREMACROEVENTS)) 1332 { 1333 set_option (OPTIGNOREMACROEVENTS); 1334 reset_ignoremacro = 1; 1335 } 1336 while (!done) 1337 { 1338 switch (mutt_menuLoop (menu)) 1339 { 1340 case -1: /* abort */ 1341 case OP_MAX + 1: /* reject */ 1342 case OP_EXIT: 1343 done = 1; 1344 break; 1345 case OP_MAX + 3: /* accept always */ 1346 if (!allow_always) 1347 break; 1348 done = 0; 1349 if ((fp = fopen (SslCertFile, "a"))) 1350 { 1351 if (PEM_write_X509 (fp, cert)) 1352 done = 1; 1353 safe_fclose (&fp); 1354 } 1355 if (!done) 1356 { 1357 mutt_error (_("Warning: Couldn't save certificate")); 1358 mutt_sleep (2); 1359 } 1360 else 1361 { 1362 mutt_message (_("Certificate saved")); 1363 mutt_sleep (0); 1364 } 1365 /* fall through */ 1366 case OP_MAX + 2: /* accept once */ 1367 done = 2; 1368 SSL_set_ex_data (ssl, SkipModeExDataIndex, NULL); 1369 ssl_cache_trusted_cert (cert); 1370 break; 1371 case OP_MAX + 4: /* skip */ 1372 if (!allow_skip) 1373 break; 1374 done = 2; 1375 SSL_set_ex_data (ssl, SkipModeExDataIndex, &SkipModeExDataIndex); 1376 break; 1377 } 1378 } 1379 if (reset_ignoremacro) 1380 unset_option (OPTIGNOREMACROEVENTS); 1381 1382 mutt_buffer_pool_release (&drow); 1383 mutt_pop_current_menu (menu); 1384 mutt_menuDestroy (&menu); 1385 dprint (2, (debugfile, "ssl interactive_check_cert: done=%d\n", done)); 1386 return (done == 2); 1387} 1388 1389static void ssl_get_client_cert(sslsockdata *ssldata, CONNECTION *conn) 1390{ 1391 if (SslClientCert) 1392 { 1393 dprint (2, (debugfile, "Using client certificate %s\n", SslClientCert)); 1394 SSL_CTX_set_default_passwd_cb_userdata(ssldata->ctx, &conn->account); 1395 SSL_CTX_set_default_passwd_cb(ssldata->ctx, ssl_passwd_cb); 1396 SSL_CTX_use_certificate_file(ssldata->ctx, SslClientCert, SSL_FILETYPE_PEM); 1397 SSL_CTX_use_PrivateKey_file(ssldata->ctx, SslClientCert, SSL_FILETYPE_PEM); 1398 1399 /* if we are using a client cert, SASL may expect an external auth name */ 1400 mutt_account_getuser (&conn->account); 1401 } 1402} 1403 1404static int ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata) 1405{ 1406 ACCOUNT *account = (ACCOUNT*)userdata; 1407 1408 if (mutt_account_getuser (account)) 1409 return 0; 1410 1411 dprint (2, (debugfile, "ssl_passwd_cb: getting password for %s@%s:%u\n", 1412 account->user, account->host, account->port)); 1413 1414 if (mutt_account_getpass (account)) 1415 return 0; 1416 1417 return snprintf(buf, size, "%s", account->pass); 1418}