mem_calloc -> p_new
[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 #ifdef USE_SSL
15
16 #include <openssl/ssl.h>
17 #include <openssl/x509.h>
18 #include <openssl/err.h>
19 #include <openssl/rand.h>
20
21 #undef _
22
23 #include <string.h>
24
25 #include <lib-lib/mem.h>
26
27 #include "mutt.h"
28 #include "mutt_socket.h"
29 #include "mutt_menu.h"
30 #include "mutt_curses.h"
31 #include "mutt_ssl.h"
32
33 #include "lib/mem.h"
34 #include "lib/intl.h"
35 #include "lib/str.h"
36 #include "lib/debug.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 static 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 = p_new(sslsockdata, 1);
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     debug_print (1, ("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     debug_print (1, ("Error allocating SSL\n"));
102     goto bail_ctx;
103   }
104
105   if (SSL_set_fd (ssldata->ssl, conn->fd) != 1) {
106     debug_print (1, ("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   p_delete(&ssldata->ssl);
126 bail_ctx:
127   p_delete(&ssldata->ctx);
128 bail_ssldata:
129   p_delete(&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 static 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 mutt_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 = p_new(sslsockdata, 1);
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 #if 0
351     X509_free (data->cert);
352 #endif
353     SSL_free (data->ssl);
354     SSL_CTX_free (data->ctx);
355     p_delete(&conn->sockdata);
356   }
357
358   return raw_socket_close (conn);
359 }
360
361 static int compare_certificates (X509 *cert, X509 *peercert, 
362                                  unsigned char *peermd,
363                                  unsigned int peermdlen) {
364   unsigned char md[EVP_MAX_MD_SIZE];
365   unsigned int mdlen;
366
367   /* Avoid CPU-intensive digest calculation if the certificates are
368   * not even remotely equal.
369   */
370   if (X509_subject_name_cmp (cert, peercert) != 0 || 
371       X509_issuer_name_cmp (cert, peercert) != 0)
372     return -1;
373
374   if (!X509_digest (cert, EVP_sha1(), md, &mdlen) || peermdlen != mdlen)
375     return -1;
376
377   if (memcmp(peermd, md, mdlen) != 0)
378     return -1;
379
380   return 0;
381 }
382
383 static int check_certificate_cache (X509 *peercert) {
384   unsigned char peermd[EVP_MAX_MD_SIZE];
385   unsigned int peermdlen;
386   X509 *cert;
387   LIST *scert;
388
389   if (!X509_digest (peercert, EVP_sha1(), peermd, &peermdlen)) 
390     return 0;
391
392   for (scert = SslSessionCerts; scert; scert = scert->next) {
393     cert = *(X509**)scert->data;
394     if (!compare_certificates (cert, peercert, peermd, peermdlen)) {
395       return 1;
396     }
397   }
398  return 0;
399 }
400
401 static int tls_close (CONNECTION * conn)
402 {
403   int rc;
404
405   rc = ssl_socket_close (conn);
406   conn->conn_read = raw_socket_read;
407   conn->conn_write = raw_socket_write;
408   conn->conn_close = raw_socket_close;
409
410   return rc;
411 }
412
413 static char *x509_get_part (char *line, const char *ndx)
414 {
415   static char ret[SHORT_STRING];
416   char *c, *c2;
417
418   strfcpy (ret, _("Unknown"), sizeof (ret));
419
420   c = strstr (line, ndx);
421   if (c) {
422     c += str_len (ndx);
423     c2 = strchr (c, '/');
424     if (c2)
425       *c2 = '\0';
426     strfcpy (ret, c, sizeof (ret));
427     if (c2)
428       *c2 = '/';
429   }
430
431   return ret;
432 }
433
434 static void x509_fingerprint (char *s, int l, X509 * cert)
435 {
436   unsigned char md[EVP_MAX_MD_SIZE];
437   unsigned int n;
438   int j;
439
440   if (!X509_digest (cert, EVP_md5 (), md, &n)) {
441     snprintf (s, l, "%s", _("[unable to calculate]"));
442   }
443   else {
444     for (j = 0; j < (int) n; j++) {
445       char ch[8];
446
447       snprintf (ch, 8, "%02X%s", md[j], (j % 2 ? " " : ""));
448       str_cat (s, l, ch);
449     }
450   }
451 }
452
453 static char *asn1time_to_string (ASN1_UTCTIME * tm)
454 {
455   static char buf[64];
456   BIO *bio;
457
458   strfcpy (buf, _("[invalid date]"), sizeof (buf));
459
460   bio = BIO_new (BIO_s_mem ());
461   if (bio) {
462     if (ASN1_TIME_print (bio, tm))
463       (void) BIO_read (bio, buf, sizeof (buf));
464     BIO_free (bio);
465   }
466
467   return buf;
468 }
469
470 static int check_certificate_by_signer (X509 * peercert)
471 {
472   X509_STORE_CTX xsc;
473   X509_STORE *ctx;
474   int pass = 0;
475
476   ctx = X509_STORE_new ();
477   if (ctx == NULL)
478     return 0;
479
480   if (option (OPTSSLSYSTEMCERTS)) {
481     if (X509_STORE_set_default_paths (ctx))
482       pass++;
483     else
484       debug_print (2, ("X509_STORE_set_default_paths failed\n"));
485   }
486
487   if (X509_STORE_load_locations (ctx, SslCertFile, NULL))
488     pass++;
489   else
490     debug_print (2, ("X509_STORE_load_locations_failed\n"));
491
492   if (pass == 0) {
493     /* nothing to do */
494     X509_STORE_free (ctx);
495     return 0;
496   }
497
498   X509_STORE_CTX_init (&xsc, ctx, peercert, NULL);
499
500   pass = (X509_verify_cert (&xsc) > 0);
501 #ifdef DEBUG
502   if (!pass) {
503     char buf[SHORT_STRING];
504     int err;
505
506     err = X509_STORE_CTX_get_error (&xsc);
507     snprintf (buf, sizeof (buf), "%s (%d)",
508               X509_verify_cert_error_string (err), err);
509     debug_print (2, ("X509_verify_cert: %s\n", buf));
510   }
511 #endif
512   X509_STORE_CTX_cleanup (&xsc);
513   X509_STORE_free (ctx);
514
515   return pass;
516 }
517
518 static int check_certificate_by_digest (X509 * peercert)
519 {
520   unsigned char peermd[EVP_MAX_MD_SIZE];
521   unsigned int peermdlen;
522   X509 *cert = NULL;
523   int pass = 0;
524   FILE *fp;
525
526   /* expiration check */
527   if (X509_cmp_current_time (X509_get_notBefore (peercert)) >= 0) {
528     debug_print (2, ("Server certificate is not yet valid\n"));
529     mutt_error (_("Server certificate is not yet valid"));
530     mutt_sleep (2);
531     return 0;
532   }
533   if (X509_cmp_current_time (X509_get_notAfter (peercert)) <= 0) {
534     debug_print (2, ("Server certificate has expired\n"));
535     mutt_error (_("Server certificate has expired"));
536     mutt_sleep (2);
537     return 0;
538   }
539
540   if ((fp = fopen (SslCertFile, "rt")) == NULL)
541     return 0;
542
543   if (!X509_digest (peercert, EVP_sha1 (), peermd, &peermdlen)) {
544     fclose (fp);
545     return 0;
546   }
547
548   while ((cert = READ_X509_KEY (fp, &cert)) != NULL) {
549     pass = compare_certificates (cert, peercert, peermd, peermdlen) ? 0 : 1;
550     if (pass)
551       break;
552   }
553   X509_free (cert);
554   fclose (fp);
555
556   return pass;
557 }
558
559 static int ssl_check_certificate (sslsockdata * data)
560 {
561   char *part[] = { "/CN=", "/Email=", "/O=", "/OU=", "/L=", "/ST=", "/C=" };
562   char helpstr[SHORT_STRING];
563   char buf[SHORT_STRING];
564   MUTTMENU *menu;
565   int done, row, i;
566   FILE *fp;
567   char *name = NULL, *c;
568
569   /* check session cache first */
570   if (check_certificate_cache (data->cert)) {
571     debug_print (1, ("ssl_check_certificate: using cached certificate\n"));
572     return 1;
573   }
574
575   if (check_certificate_by_signer (data->cert)) {
576     debug_print (1, ("signer check passed\n"));
577     return 1;
578   }
579
580   /* automatic check from user's database */
581   if (SslCertFile && check_certificate_by_digest (data->cert)) {
582     debug_print (1, ("digest check passed\n"));
583     return 1;
584   }
585
586   /* interactive check from user */
587   menu = mutt_new_menu ();
588   menu->max = 19;
589   menu->dialog = p_new(char *, menu->max);
590   for (i = 0; i < menu->max; i++)
591     menu->dialog[i] = p_new(char, SHORT_STRING);
592
593   row = 0;
594   strfcpy (menu->dialog[row], _("This certificate belongs to:"),
595            SHORT_STRING);
596   row++;
597   name = X509_NAME_oneline (X509_get_subject_name (data->cert),
598                             buf, sizeof (buf));
599   for (i = 0; i < 5; i++) {
600     c = x509_get_part (name, part[i]);
601     snprintf (menu->dialog[row++], SHORT_STRING, "   %s", c);
602   }
603
604   row++;
605   strfcpy (menu->dialog[row], _("This certificate was issued by:"),
606            SHORT_STRING);
607   row++;
608   name = X509_NAME_oneline (X509_get_issuer_name (data->cert),
609                             buf, sizeof (buf));
610   for (i = 0; i < 5; i++) {
611     c = x509_get_part (name, part[i]);
612     snprintf (menu->dialog[row++], SHORT_STRING, "   %s", c);
613   }
614
615   row++;
616   snprintf (menu->dialog[row++], SHORT_STRING, "%s",
617             _("This certificate is valid"));
618   snprintf (menu->dialog[row++], SHORT_STRING, _("   from %s"),
619             asn1time_to_string (X509_get_notBefore (data->cert)));
620   snprintf (menu->dialog[row++], SHORT_STRING, _("     to %s"),
621             asn1time_to_string (X509_get_notAfter (data->cert)));
622
623   row++;
624   buf[0] = '\0';
625   x509_fingerprint (buf, sizeof (buf), data->cert);
626   snprintf (menu->dialog[row++], SHORT_STRING, _("Fingerprint: %s"), buf);
627
628   menu->title = _("SSL Certificate check");
629
630   if (SslCertFile && X509_cmp_current_time (X509_get_notAfter (data->cert)) >= 0
631       && X509_cmp_current_time (X509_get_notBefore (data->cert)) < 0) {
632     menu->prompt = _("(r)eject, accept (o)nce, (a)ccept always");
633     menu->keys = _("roa");
634   }
635   else {
636     menu->prompt = _("(r)eject, accept (o)nce");
637     menu->keys = _("ro");
638   }
639
640   helpstr[0] = '\0';
641   mutt_make_help (buf, sizeof (buf), _("Exit  "), MENU_GENERIC, OP_EXIT);
642   str_cat (helpstr, sizeof (helpstr), buf);
643   mutt_make_help (buf, sizeof (buf), _("Help"), MENU_GENERIC, OP_HELP);
644   str_cat (helpstr, sizeof (helpstr), buf);
645   menu->help = helpstr;
646
647   done = 0;
648   set_option (OPTUNBUFFEREDINPUT);
649   while (!done) {
650     switch (mutt_menuLoop (menu)) {
651     case -1:                   /* abort */
652     case OP_MAX + 1:           /* reject */
653     case OP_EXIT:
654       done = 1;
655       break;
656     case OP_MAX + 3:           /* accept always */
657       done = 0;
658       if ((fp = fopen (SslCertFile, "a"))) {
659         if (PEM_write_X509 (fp, data->cert))
660           done = 1;
661         fclose (fp);
662       }
663       if (!done) {
664         mutt_error (_("Warning: Couldn't save certificate"));
665         mutt_sleep (2);
666       }
667       else {
668         mutt_message (_("Certificate saved"));
669         mutt_sleep (0);
670       }
671       /* fall through */
672     case OP_MAX + 2:           /* accept once */
673       done = 2;
674       /* keep a handle on accepted certificates in case we want to
675        * open up another connection to the same server in this session */
676       SslSessionCerts = mutt_add_list_n (SslSessionCerts, &data->cert,
677                                          sizeof (X509 **));
678       break;
679     }
680   }
681   unset_option (OPTUNBUFFEREDINPUT);
682   mutt_menuDestroy (&menu);
683   return (done == 2);
684 }
685
686 static void ssl_get_client_cert (sslsockdata * ssldata, CONNECTION * conn)
687 {
688   if (SslClientCert) {
689     debug_print (2, ("Using client certificate %s\n", SslClientCert));
690     SSL_CTX_set_default_passwd_cb_userdata (ssldata->ctx, &conn->account);
691     SSL_CTX_set_default_passwd_cb (ssldata->ctx, ssl_passwd_cb);
692     SSL_CTX_use_certificate_file (ssldata->ctx, SslClientCert,
693                                   SSL_FILETYPE_PEM);
694     SSL_CTX_use_PrivateKey_file (ssldata->ctx, SslClientCert,
695                                  SSL_FILETYPE_PEM);
696   }
697 }
698
699 static int ssl_passwd_cb (char *buf, int size, int rwflag, void *userdata)
700 {
701   ACCOUNT *account = (ACCOUNT *) userdata;
702
703   if (mutt_account_getuser (account))
704     return 0;
705
706   debug_print (2, ("getting password for %s@%s:%u\n",
707               account->user, account->host, account->port));
708
709   if (mutt_account_getpass (account))
710     return 0;
711
712   return snprintf (buf, size, "%s", account->pass);
713 }
714
715 #endif /* USE_SSL */