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