mutt stable branch with some hacks
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}