Nico Golde:
[apps/madmutt.git] / mutt_ssl.c
1 /*
2  * Copyright notice from original mutt:
3  * Copyright (C) 1999-2001 Tommi Komulainen <Tommi.Komulainen@iki.fi>
4  *
5  * This file is part of mutt-ng, see http://www.muttng.org/.
6  * It's licensed under the GNU General Public License,
7  * please see the file GPL in the top level source directory.
8  */
9
10 #if HAVE_CONFIG_H
11 # include "config.h"
12 #endif
13
14 #include <openssl/ssl.h>
15 #include <openssl/x509.h>
16 #include <openssl/err.h>
17 #include <openssl/rand.h>
18
19 #undef _
20
21 #include <string.h>
22
23 #include "mutt.h"
24 #include "mutt_socket.h"
25 #include "mutt_menu.h"
26 #include "mutt_curses.h"
27 #include "mutt_ssl.h"
28
29 #include "lib/mem.h"
30 #include "lib/intl.h"
31 #include "lib/str.h"
32
33 #if OPENSSL_VERSION_NUMBER >= 0x00904000L
34 #define READ_X509_KEY(fp, key)  PEM_read_X509(fp, key, NULL, NULL)
35 #else
36 #define READ_X509_KEY(fp, key)  PEM_read_X509(fp, key, NULL)
37 #endif
38
39 /* Just in case OpenSSL doesn't define DEVRANDOM */
40 #ifndef DEVRANDOM
41 #define DEVRANDOM "/dev/urandom"
42 #endif
43
44 /* This is ugly, but as RAND_status came in on OpenSSL version 0.9.5
45  * and the code has to support older versions too, this is seemed to
46  * be cleaner way compared to having even uglier #ifdefs all around.
47  */
48 #ifdef HAVE_RAND_STATUS
49 #define HAVE_ENTROPY()  (RAND_status() == 1)
50 #else
51 static int entropy_byte_count = 0;
52
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 typedef struct _sslsockdata {
58   SSL_CTX *ctx;
59   SSL *ssl;
60   X509 *cert;
61 } sslsockdata;
62
63 /* local prototypes */
64 int ssl_init (void);
65 static int add_entropy (const char *file);
66 static int ssl_socket_read (CONNECTION * conn, char *buf, size_t len);
67 static int ssl_socket_write (CONNECTION * conn, const char *buf, size_t len);
68 static int ssl_socket_open (CONNECTION * conn);
69 static int ssl_socket_close (CONNECTION * conn);
70 static int tls_close (CONNECTION * conn);
71 static int ssl_check_certificate (sslsockdata * data);
72 static void ssl_get_client_cert (sslsockdata * ssldata, CONNECTION * conn);
73 static int ssl_passwd_cb (char *buf, int size, int rwflag, void *userdata);
74 static int ssl_negotiate (sslsockdata *);
75
76 /* mutt_ssl_starttls: Negotiate TLS over an already opened connection.
77  *   TODO: Merge this code better with ssl_socket_open. */
78 int mutt_ssl_starttls (CONNECTION * conn)
79 {
80   sslsockdata *ssldata;
81   int maxbits;
82
83   if (ssl_init ())
84     goto bail;
85
86   ssldata = (sslsockdata *) safe_calloc (1, sizeof (sslsockdata));
87   /* the ssl_use_xxx protocol options don't apply. We must use TLS in TLS. */
88   if (!(ssldata->ctx = SSL_CTX_new (TLSv1_client_method ()))) {
89     dprint (1, (debugfile, "mutt_ssl_starttls: Error allocating SSL_CTX\n"));
90     goto bail_ssldata;
91   }
92
93   ssl_get_client_cert (ssldata, conn);
94
95   if (!(ssldata->ssl = SSL_new (ssldata->ctx))) {
96     dprint (1, (debugfile, "mutt_ssl_starttls: Error allocating SSL\n"));
97     goto bail_ctx;
98   }
99
100   if (SSL_set_fd (ssldata->ssl, conn->fd) != 1) {
101     dprint (1, (debugfile, "mutt_ssl_starttls: Error setting fd\n"));
102     goto bail_ssl;
103   }
104
105   if (ssl_negotiate (ssldata))
106     goto bail_ssl;
107
108   /* hmm. watch out if we're starting TLS over any method other than raw. */
109   conn->sockdata = ssldata;
110   conn->conn_read = ssl_socket_read;
111   conn->conn_write = ssl_socket_write;
112   conn->conn_close = tls_close;
113
114   conn->ssf = SSL_CIPHER_get_bits (SSL_get_current_cipher (ssldata->ssl),
115                                    &maxbits);
116
117   return 0;
118
119 bail_ssl:
120   FREE (&ssldata->ssl);
121 bail_ctx:
122   FREE (&ssldata->ctx);
123 bail_ssldata:
124   FREE (&ssldata);
125 bail:
126   return -1;
127 }
128
129 /* 
130  * OpenSSL library needs to be fed with sufficient entropy. On systems
131  * with /dev/urandom, this is done transparently by the library itself,
132  * on other systems we need to fill the entropy pool ourselves.
133  *
134  * Even though only OpenSSL 0.9.5 and later will complain about the
135  * lack of entropy, we try to our best and fill the pool with older
136  * versions also. (That's the reason for the ugly #ifdefs and macros,
137  * otherwise I could have simply #ifdef'd the whole ssl_init funcion)
138  */
139 int ssl_init (void)
140 {
141   char path[_POSIX_PATH_MAX];
142   static unsigned char init_complete = 0;
143
144   if (init_complete)
145     return 0;
146
147   if (!HAVE_ENTROPY ()) {
148     /* load entropy from files */
149     add_entropy (SslEntropyFile);
150     add_entropy (RAND_file_name (path, sizeof (path)));
151
152     /* load entropy from egd sockets */
153 #ifdef HAVE_RAND_EGD
154     add_entropy (getenv ("EGDSOCKET"));
155     snprintf (path, sizeof (path), "%s/.entropy", NONULL (Homedir));
156     add_entropy (path);
157     add_entropy ("/tmp/entropy");
158 #endif
159
160     /* shuffle $RANDFILE (or ~/.rnd if unset) */
161     RAND_write_file (RAND_file_name (path, sizeof (path)));
162     mutt_clear_error ();
163     if (!HAVE_ENTROPY ()) {
164       mutt_error (_("Failed to find enough entropy on your system"));
165       mutt_sleep (2);
166       return -1;
167     }
168   }
169
170   /* I don't think you can do this just before reading the error. The call
171    * itself might clobber the last SSL error. */
172   SSL_load_error_strings ();
173   SSL_library_init ();
174   init_complete = 1;
175   return 0;
176 }
177
178 static int add_entropy (const char *file)
179 {
180   struct stat st;
181   int n = -1;
182
183   if (!file)
184     return 0;
185
186   if (stat (file, &st) == -1)
187     return errno == ENOENT ? 0 : -1;
188
189   mutt_message (_("Filling entropy pool: %s...\n"), file);
190
191   /* check that the file permissions are secure */
192   if (st.st_uid != getuid () ||
193       ((st.st_mode & (S_IWGRP | S_IRGRP)) != 0) ||
194       ((st.st_mode & (S_IWOTH | S_IROTH)) != 0)) {
195     mutt_error (_("%s has insecure permissions!"), file);
196     mutt_sleep (2);
197     return -1;
198   }
199
200 #ifdef HAVE_RAND_EGD
201   n = RAND_egd (file);
202 #endif
203   if (n <= 0)
204     n = RAND_load_file (file, -1);
205
206 #ifndef HAVE_RAND_STATUS
207   if (n > 0)
208     entropy_byte_count += n;
209 #endif
210   return n;
211 }
212
213 static int ssl_socket_open_err (CONNECTION * conn)
214 {
215   mutt_error (_("SSL disabled due the lack of entropy"));
216   mutt_sleep (2);
217   return -1;
218 }
219
220
221 int ssl_socket_setup (CONNECTION * conn)
222 {
223   if (ssl_init () < 0) {
224     conn->conn_open = ssl_socket_open_err;
225     return -1;
226   }
227
228   conn->conn_open = ssl_socket_open;
229   conn->conn_read = ssl_socket_read;
230   conn->conn_write = ssl_socket_write;
231   conn->conn_close = ssl_socket_close;
232
233   return 0;
234 }
235
236 static int ssl_socket_read (CONNECTION * conn, char *buf, size_t len)
237 {
238   sslsockdata *data = conn->sockdata;
239
240   return SSL_read (data->ssl, buf, len);
241 }
242
243 static int ssl_socket_write (CONNECTION * conn, const char *buf, size_t len)
244 {
245   sslsockdata *data = conn->sockdata;
246
247   return SSL_write (data->ssl, buf, len);
248 }
249
250 static int ssl_socket_open (CONNECTION * conn)
251 {
252   sslsockdata *data;
253   int maxbits;
254
255   if (raw_socket_open (conn) < 0)
256     return -1;
257
258   data = (sslsockdata *) safe_calloc (1, sizeof (sslsockdata));
259   conn->sockdata = data;
260
261   data->ctx = SSL_CTX_new (SSLv23_client_method ());
262
263   /* disable SSL protocols as needed */
264   if (!option (OPTTLSV1)) {
265     SSL_CTX_set_options (data->ctx, SSL_OP_NO_TLSv1);
266   }
267   if (!option (OPTSSLV2)) {
268     SSL_CTX_set_options (data->ctx, SSL_OP_NO_SSLv2);
269   }
270   if (!option (OPTSSLV3)) {
271     SSL_CTX_set_options (data->ctx, SSL_OP_NO_SSLv3);
272   }
273
274   ssl_get_client_cert (data, conn);
275
276   data->ssl = SSL_new (data->ctx);
277   SSL_set_fd (data->ssl, conn->fd);
278
279   if (ssl_negotiate (data)) {
280     mutt_socket_close (conn);
281     return -1;
282   }
283
284   conn->ssf = SSL_CIPHER_get_bits (SSL_get_current_cipher (data->ssl),
285                                    &maxbits);
286
287   return 0;
288 }
289
290 /* ssl_negotiate: After SSL state has been initialised, attempt to negotiate
291  *   SSL over the wire, including certificate checks. */
292 static int ssl_negotiate (sslsockdata * ssldata)
293 {
294   int err;
295   const char *errmsg;
296
297 #if OPENSSL_VERSION_NUMBER >= 0x00906000L
298   /* This only exists in 0.9.6 and above. Without it we may get interrupted
299    *   reads or writes. Bummer. */
300   SSL_set_mode (ssldata->ssl, SSL_MODE_AUTO_RETRY);
301 #endif
302
303   if ((err = SSL_connect (ssldata->ssl)) != 1) {
304     switch (SSL_get_error (ssldata->ssl, err)) {
305     case SSL_ERROR_SYSCALL:
306       errmsg = _("I/O error");
307       break;
308     case SSL_ERROR_SSL:
309       errmsg = ERR_error_string (ERR_get_error (), NULL);
310       break;
311     default:
312       errmsg = _("unknown error");
313     }
314
315     mutt_error (_("SSL failed: %s"), errmsg);
316     mutt_sleep (1);
317
318     return -1;
319   }
320
321   ssldata->cert = SSL_get_peer_certificate (ssldata->ssl);
322   if (!ssldata->cert) {
323     mutt_error (_("Unable to get certificate from peer"));
324     mutt_sleep (1);
325     return -1;
326   }
327
328   if (!ssl_check_certificate (ssldata))
329     return -1;
330
331   mutt_message (_("SSL connection using %s (%s)"),
332                 SSL_get_cipher_version (ssldata->ssl),
333                 SSL_get_cipher_name (ssldata->ssl));
334   mutt_sleep (0);
335
336   return 0;
337 }
338
339 static int ssl_socket_close (CONNECTION * conn)
340 {
341   sslsockdata *data = conn->sockdata;
342
343   if (data) {
344     SSL_shutdown (data->ssl);
345
346     X509_free (data->cert);
347     SSL_free (data->ssl);
348     SSL_CTX_free (data->ctx);
349     FREE (&conn->sockdata);
350   }
351
352   return raw_socket_close (conn);
353 }
354
355 static int tls_close (CONNECTION * conn)
356 {
357   int rc;
358
359   rc = ssl_socket_close (conn);
360   conn->conn_read = raw_socket_read;
361   conn->conn_write = raw_socket_write;
362   conn->conn_close = raw_socket_close;
363
364   return rc;
365 }
366
367 static char *x509_get_part (char *line, const char *ndx)
368 {
369   static char ret[SHORT_STRING];
370   char *c, *c2;
371
372   strfcpy (ret, _("Unknown"), sizeof (ret));
373
374   c = strstr (line, ndx);
375   if (c) {
376     c += mutt_strlen (ndx);
377     c2 = strchr (c, '/');
378     if (c2)
379       *c2 = '\0';
380     strfcpy (ret, c, sizeof (ret));
381     if (c2)
382       *c2 = '/';
383   }
384
385   return ret;
386 }
387
388 static void x509_fingerprint (char *s, int l, X509 * cert)
389 {
390   unsigned char md[EVP_MAX_MD_SIZE];
391   unsigned int n;
392   int j;
393
394   if (!X509_digest (cert, EVP_md5 (), md, &n)) {
395     snprintf (s, l, "%s", _("[unable to calculate]"));
396   }
397   else {
398     for (j = 0; j < (int) n; j++) {
399       char ch[8];
400
401       snprintf (ch, 8, "%02X%s", md[j], (j % 2 ? " " : ""));
402       safe_strcat (s, l, ch);
403     }
404   }
405 }
406
407 static char *asn1time_to_string (ASN1_UTCTIME * tm)
408 {
409   static char buf[64];
410   BIO *bio;
411
412   strfcpy (buf, _("[invalid date]"), sizeof (buf));
413
414   bio = BIO_new (BIO_s_mem ());
415   if (bio) {
416     if (ASN1_TIME_print (bio, tm))
417       (void) BIO_read (bio, buf, sizeof (buf));
418     BIO_free (bio);
419   }
420
421   return buf;
422 }
423
424 static int check_certificate_by_signer (X509 * peercert)
425 {
426   X509_STORE_CTX xsc;
427   X509_STORE *ctx;
428   int pass = 0;
429
430   ctx = X509_STORE_new ();
431   if (ctx == NULL)
432     return 0;
433
434   if (option (OPTSSLSYSTEMCERTS)) {
435     if (X509_STORE_set_default_paths (ctx))
436       pass++;
437     else
438       dprint (2, (debugfile, "X509_STORE_set_default_paths failed\n"));
439   }
440
441   if (X509_STORE_load_locations (ctx, SslCertFile, NULL))
442     pass++;
443   else
444     dprint (2, (debugfile, "X509_STORE_load_locations_failed\n"));
445
446   if (pass == 0) {
447     /* nothing to do */
448     X509_STORE_free (ctx);
449     return 0;
450   }
451
452   X509_STORE_CTX_init (&xsc, ctx, peercert, NULL);
453
454   pass = (X509_verify_cert (&xsc) > 0);
455 #ifdef DEBUG
456   if (!pass) {
457     char buf[SHORT_STRING];
458     int err;
459
460     err = X509_STORE_CTX_get_error (&xsc);
461     snprintf (buf, sizeof (buf), "%s (%d)",
462               X509_verify_cert_error_string (err), err);
463     dprint (2, (debugfile, "X509_verify_cert: %s\n", buf));
464   }
465 #endif
466   X509_STORE_CTX_cleanup (&xsc);
467   X509_STORE_free (ctx);
468
469   return pass;
470 }
471
472 static int check_certificate_by_digest (X509 * peercert)
473 {
474   unsigned char peermd[EVP_MAX_MD_SIZE];
475   unsigned int peermdlen;
476   X509 *cert = NULL;
477   int pass = 0;
478   FILE *fp;
479
480   /* expiration check */
481   if (X509_cmp_current_time (X509_get_notBefore (peercert)) >= 0) {
482     dprint (2, (debugfile, "Server certificate is not yet valid\n"));
483     mutt_error (_("Server certificate is not yet valid"));
484     mutt_sleep (2);
485     return 0;
486   }
487   if (X509_cmp_current_time (X509_get_notAfter (peercert)) <= 0) {
488     dprint (2, (debugfile, "Server certificate has expired"));
489     mutt_error (_("Server certificate has expired"));
490     mutt_sleep (2);
491     return 0;
492   }
493
494   if ((fp = fopen (SslCertFile, "rt")) == NULL)
495     return 0;
496
497   if (!X509_digest (peercert, EVP_sha1 (), peermd, &peermdlen)) {
498     fclose (fp);
499     return 0;
500   }
501
502   while ((cert = READ_X509_KEY (fp, &cert)) != NULL) {
503     unsigned char md[EVP_MAX_MD_SIZE];
504     unsigned int mdlen;
505
506     /* Avoid CPU-intensive digest calculation if the certificates are
507      * not even remotely equal.
508      */
509     if (X509_subject_name_cmp (cert, peercert) != 0 ||
510         X509_issuer_name_cmp (cert, peercert) != 0)
511       continue;
512
513     if (!X509_digest (cert, EVP_sha1 (), md, &mdlen) || peermdlen != mdlen)
514       continue;
515
516     if (memcmp (peermd, md, mdlen) != 0)
517       continue;
518
519     pass = 1;
520     break;
521   }
522   X509_free (cert);
523   fclose (fp);
524
525   return pass;
526 }
527
528 static int ssl_check_certificate (sslsockdata * data)
529 {
530   char *part[] = { "/CN=", "/Email=", "/O=", "/OU=", "/L=", "/ST=", "/C=" };
531   char helpstr[SHORT_STRING];
532   char buf[SHORT_STRING];
533   MUTTMENU *menu;
534   int done, row, i;
535   FILE *fp;
536   char *name = NULL, *c;
537
538   if (check_certificate_by_signer (data->cert)) {
539     dprint (1, (debugfile, "ssl_check_certificate: signer check passed\n"));
540     return 1;
541   }
542
543   /* automatic check from user's database */
544   if (SslCertFile && check_certificate_by_digest (data->cert)) {
545     dprint (1, (debugfile, "ssl_check_certificate: digest check passed\n"));
546     return 1;
547   }
548
549   /* interactive check from user */
550   menu = mutt_new_menu ();
551   menu->max = 19;
552   menu->dialog = (char **) safe_calloc (1, menu->max * sizeof (char *));
553   for (i = 0; i < menu->max; i++)
554     menu->dialog[i] = (char *) safe_calloc (1, SHORT_STRING * sizeof (char));
555
556   row = 0;
557   strfcpy (menu->dialog[row], _("This certificate belongs to:"),
558            SHORT_STRING);
559   row++;
560   name = X509_NAME_oneline (X509_get_subject_name (data->cert),
561                             buf, sizeof (buf));
562   for (i = 0; i < 5; i++) {
563     c = x509_get_part (name, part[i]);
564     snprintf (menu->dialog[row++], SHORT_STRING, "   %s", c);
565   }
566
567   row++;
568   strfcpy (menu->dialog[row], _("This certificate was issued by:"),
569            SHORT_STRING);
570   row++;
571   name = X509_NAME_oneline (X509_get_issuer_name (data->cert),
572                             buf, sizeof (buf));
573   for (i = 0; i < 5; i++) {
574     c = x509_get_part (name, part[i]);
575     snprintf (menu->dialog[row++], SHORT_STRING, "   %s", c);
576   }
577
578   row++;
579   snprintf (menu->dialog[row++], SHORT_STRING, "%s",
580             _("This certificate is valid"));
581   snprintf (menu->dialog[row++], SHORT_STRING, _("   from %s"),
582             asn1time_to_string (X509_get_notBefore (data->cert)));
583   snprintf (menu->dialog[row++], SHORT_STRING, _("     to %s"),
584             asn1time_to_string (X509_get_notAfter (data->cert)));
585
586   row++;
587   buf[0] = '\0';
588   x509_fingerprint (buf, sizeof (buf), data->cert);
589   snprintf (menu->dialog[row++], SHORT_STRING, _("Fingerprint: %s"), buf);
590
591   menu->title = _("SSL Certificate check");
592   if (SslCertFile) {
593     menu->prompt = _("(r)eject, accept (o)nce, (a)ccept always");
594     menu->keys = _("roa");
595   }
596   else {
597     menu->prompt = _("(r)eject, accept (o)nce");
598     menu->keys = _("ro");
599   }
600
601   helpstr[0] = '\0';
602   mutt_make_help (buf, sizeof (buf), _("Exit  "), MENU_GENERIC, OP_EXIT);
603   safe_strcat (helpstr, sizeof (helpstr), buf);
604   mutt_make_help (buf, sizeof (buf), _("Help"), MENU_GENERIC, OP_HELP);
605   safe_strcat (helpstr, sizeof (helpstr), buf);
606   menu->help = helpstr;
607
608   done = 0;
609   set_option (OPTUNBUFFEREDINPUT);
610   while (!done) {
611     switch (mutt_menuLoop (menu)) {
612     case -1:                   /* abort */
613     case OP_MAX + 1:           /* reject */
614     case OP_EXIT:
615       done = 1;
616       break;
617     case OP_MAX + 3:           /* accept always */
618       done = 0;
619       if ((fp = fopen (SslCertFile, "a"))) {
620         if (PEM_write_X509 (fp, data->cert))
621           done = 1;
622         fclose (fp);
623       }
624       if (!done) {
625         mutt_error (_("Warning: Couldn't save certificate"));
626         mutt_sleep (2);
627       }
628       else {
629         mutt_message (_("Certificate saved"));
630         mutt_sleep (0);
631       }
632       /* fall through */
633     case OP_MAX + 2:           /* accept once */
634       done = 2;
635       break;
636     }
637   }
638   unset_option (OPTUNBUFFEREDINPUT);
639   mutt_menuDestroy (&menu);
640   return (done == 2);
641 }
642
643 static void ssl_get_client_cert (sslsockdata * ssldata, CONNECTION * conn)
644 {
645   if (SslClientCert) {
646     dprint (2, (debugfile, "Using client certificate %s\n", SslClientCert));
647     SSL_CTX_set_default_passwd_cb_userdata (ssldata->ctx, &conn->account);
648     SSL_CTX_set_default_passwd_cb (ssldata->ctx, ssl_passwd_cb);
649     SSL_CTX_use_certificate_file (ssldata->ctx, SslClientCert,
650                                   SSL_FILETYPE_PEM);
651     SSL_CTX_use_PrivateKey_file (ssldata->ctx, SslClientCert,
652                                  SSL_FILETYPE_PEM);
653   }
654 }
655
656 static int ssl_passwd_cb (char *buf, int size, int rwflag, void *userdata)
657 {
658   ACCOUNT *account = (ACCOUNT *) userdata;
659
660   if (mutt_account_getuser (account))
661     return 0;
662
663   dprint (2, (debugfile, "ssl_passwd_cb: getting password for %s@%s:%u\n",
664               account->user, account->host, account->port));
665
666   if (mutt_account_getpass (account))
667     return 0;
668
669   return snprintf (buf, size, "%s", account->pass);
670 }