Start
[exim.git] / src / src / tls-gnu.c
1 /* $Cambridge: exim/src/src/tls-gnu.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
2
3 /*************************************************
4 *     Exim - an Internet mail transport agent    *
5 *************************************************/
6
7 /* Copyright (c) University of Cambridge 1995 - 2004 */
8 /* See the file NOTICE for conditions of use and distribution. */
9
10 /* This module provides TLS (aka SSL) support for Exim using the GnuTLS
11 library. It is #included into tls.c when that library is used. The code herein
12 is based on a patch that was contributed by Nikos Mavroyanopoulos.
13
14 No cryptographic code is included in Exim. All this module does is to call
15 functions from the GnuTLS library. */
16
17
18 /* Heading stuff for GnuTLS */
19
20 #include <gnutls/gnutls.h>
21 #include <gnutls/x509.h>
22
23
24 #define UNKNOWN_NAME "unknown"
25 #define DH_BITS      768
26 #define RSA_BITS     512
27
28 /* Values for verify_requirment and initialized */
29
30 enum { VERIFY_NONE, VERIFY_OPTIONAL, VERIFY_REQUIRED };
31 enum { INITIALIZED_NOT, INITIALIZED_SERVER, INITIALIZED_CLIENT };
32
33 /* Local static variables for GNUTLS */
34
35 static BOOL initialized = INITIALIZED_NOT;
36 static host_item *client_host;
37
38 static gnutls_rsa_params rsa_params = NULL;
39 static gnutls_dh_params dh_params = NULL;
40
41 static gnutls_certificate_server_credentials x509_cred = NULL;
42 static gnutls_session tls_session = NULL;
43
44 static char ssl_errstring[256];
45
46 static int  ssl_session_timeout = 200;
47 static int  verify_requirement;
48
49 /* Priorities for TLS algorithms to use. At present, only the cipher priority
50 vector can be altered. */
51
52 static const int protocol_priority[16] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
53
54 static const int kx_priority[16] = {
55   GNUTLS_KX_RSA,
56   GNUTLS_KX_DHE_DSS,
57   GNUTLS_KX_DHE_RSA,
58   GNUTLS_KX_RSA_EXPORT,
59   0 };
60
61 static int default_cipher_priority[16] = {
62   GNUTLS_CIPHER_ARCFOUR_128,
63   GNUTLS_CIPHER_AES_128_CBC,
64   GNUTLS_CIPHER_3DES_CBC,
65   GNUTLS_CIPHER_ARCFOUR_40,
66   0 };
67
68 static int cipher_priority[16];
69
70 static const int mac_priority[16] = {
71   GNUTLS_MAC_SHA,
72   GNUTLS_MAC_MD5,
73   0 };
74
75 static const int comp_priority[16] = { GNUTLS_COMP_NULL, 0 };
76 static const int cert_type_priority[16] = { GNUTLS_CRT_X509, 0 };
77
78 /* Tables of cipher names and equivalent numbers */
79
80 typedef struct pri_item {
81   uschar *name;
82   int *values;
83 } pri_item;
84
85 static int arcfour_128_codes[] = { GNUTLS_CIPHER_ARCFOUR_128, 0 };
86 static int arcfour_40_codes[]  = { GNUTLS_CIPHER_ARCFOUR_40, 0 };
87 static int arcfour_codes[]     = { GNUTLS_CIPHER_ARCFOUR_128,
88                                    GNUTLS_CIPHER_ARCFOUR_40, 0 };
89 static int aes_256_codes[]     = { GNUTLS_CIPHER_AES_256_CBC, 0 };
90 static int aes_128_codes[]     = { GNUTLS_CIPHER_AES_128_CBC, 0 };
91 static int aes_codes[]         = { GNUTLS_CIPHER_AES_256_CBC,
92                                    GNUTLS_CIPHER_AES_128_CBC, 0 };
93 static int des3_codes[]        = { GNUTLS_CIPHER_3DES_CBC, 0 };
94
95 static pri_item cipher_index[] = {
96   { US"ARCFOUR_128", arcfour_128_codes },
97   { US"ARCFOUR_40", arcfour_40_codes },
98   { US"ARCFOUR", arcfour_codes },
99   { US"AES_256", aes_256_codes },
100   { US"AES_128", aes_128_codes },
101   { US"AES", aes_codes },
102   { US"3DES", des3_codes }
103 };
104
105
106
107 /*************************************************
108 *               Handle TLS error                 *
109 *************************************************/
110
111 /* Called from lots of places when errors occur before actually starting to do
112 the TLS handshake, that is, while the session is still in clear. Always returns
113 DEFER for a server and FAIL for a client so that most calls can use "return
114 tls_error(...)" to do this processing and then give an appropriate return. A
115 single function is used for both server and client, because it is called from
116 some shared functions.
117
118 Argument:
119   prefix    text to include in the logged error
120   host      NULL if setting up a server;
121             the connected host if setting up a client
122   err       a GnuTLS error number, or 0 if local error
123
124 Returns:    OK/DEFER/FAIL
125 */
126
127 static int
128 tls_error(uschar *prefix, host_item *host, int err)
129 {
130 uschar *errtext = US"";
131 if (err != 0) errtext = string_sprintf(": %s", gnutls_strerror(err));
132 if (host == NULL)
133   {
134   log_write(0, LOG_MAIN, "TLS error on connection from %s (%s)%s",
135     (sender_fullhost != NULL)? sender_fullhost : US "local process",
136     prefix, errtext);
137   return DEFER;
138   }
139 else
140   {
141   log_write(0, LOG_MAIN, "TLS error on connection to %s [%s] (%s)%s",
142     host->name, host->address, prefix, errtext);
143   return FAIL;
144   }
145 }
146
147
148
149 /*************************************************
150 *             Verify certificate                 *
151 *************************************************/
152
153 /* Called after a successful handshake, when certificate verification is
154 required or optional, for both server and client.
155
156 Arguments:
157   session    GNUTLS session
158   error      where to put text giving a reason for failure
159
160 Returns:     TRUE/FALSE
161 */
162
163 static BOOL
164 verify_certificate(gnutls_session session, uschar **error)
165 {
166 int verify;
167 uschar *dn_string = US"";
168 const gnutls_datum *cert;
169 unsigned int cert_size = 0;
170
171 *error = NULL;
172
173 /* Get the peer's certificate. If it sent one, extract it's DN, and then
174 attempt to verify the certificate. If no certificate is supplied, verification
175 is forced to fail. */
176
177 cert = gnutls_certificate_get_peers(session, &cert_size);
178 if (cert != NULL)
179   {
180   uschar buff[1024];
181   gnutls_x509_crt gcert;
182
183   gnutls_x509_crt_init(&gcert);
184   dn_string = US"unknown";
185
186   if (gnutls_x509_crt_import(gcert, cert, GNUTLS_X509_FMT_DER) == 0)
187     {
188     size_t bufsize = sizeof(buff);
189     if (gnutls_x509_crt_get_dn(gcert, CS buff, &bufsize) >= 0)
190       dn_string = string_copy_malloc(buff);
191     }
192
193   verify = gnutls_certificate_verify_peers(session);
194   }
195 else
196   {
197   DEBUG(D_tls) debug_printf("no peer certificate supplied\n");
198   verify = GNUTLS_CERT_INVALID;
199   *error = US"not supplied";
200   }
201
202 /* Handle the result of verification. INVALID seems to be set as well
203 as REVOKED, but leave the test for both. */
204
205 if ((verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED)) != 0)
206   {
207   tls_certificate_verified = FALSE;
208   if (*error == NULL) *error = ((verify & GNUTLS_CERT_REVOKED) != 0)?
209     US"revoked" : US"invalid";
210   if (verify_requirement == VERIFY_REQUIRED)
211     {
212     DEBUG(D_tls) debug_printf("TLS certificate verification failed (%s): "
213       "peerdn=%s\n", *error, dn_string);
214     gnutls_alert_send(session, GNUTLS_AL_FATAL, GNUTLS_A_BAD_CERTIFICATE);
215     return FALSE;                       /* reject */
216     }
217   DEBUG(D_tls) debug_printf("TLS certificate verify failure (%s) overridden "
218       "(host in tls_try_verify_hosts): peerdn=%s\n", *error, dn_string);
219   }
220 else
221   {
222   tls_certificate_verified = TRUE;
223   DEBUG(D_tls) debug_printf("TLS certificate verified: peerdn=%s\n",
224     dn_string);
225   }
226
227 tls_peerdn = dn_string;
228 return TRUE;                            /* accept */
229 }
230
231
232
233
234 /*************************************************
235 *        Write/read datum to/from file           *
236 *************************************************/
237
238 /* These functions are used for saving and restoring the RSA and D-H parameters
239 for use by all Exim processes. Data that is read is placed in malloc'd store
240 because that's what happens for newly generated data.
241
242 Arguments:
243   fd          the file descriptor
244   d           points to the datum
245
246 returns:      FALSE on error (errno set)
247 */
248
249 static BOOL
250 write_datum(int fd, gnutls_datum *d)
251 {
252 if (write(fd, &(d->size), sizeof(d->size)) != sizeof(d->size)) return FALSE;
253 if (write(fd, d->data, d->size) != d->size) return FALSE;
254 return TRUE;
255 }
256
257
258 static BOOL
259 read_datum(int fd, gnutls_datum *d)
260 {
261 if (read(fd, &(d->size), sizeof(d->size)) != sizeof(d->size)) return FALSE;
262 d->data = malloc(d->size);
263 if (d->data == NULL) return FALSE;
264 if (read(fd, d->data, d->size) != d->size) return FALSE;
265 return TRUE;
266 }
267
268
269
270 /*************************************************
271 *          Setup up RSA and DH parameters        *
272 *************************************************/
273
274 /* Generating the RSA and D-H parameters takes a long time. They only need to
275 be re-generated every so often, depending on security policy. What we do is to
276 keep these parameters in a file in the spool directory. If the file does not
277 exist, we generate them. This means that it is easy to cause a regeneration.
278
279 The new file is written as a temporary file and renamed, so that an incomplete
280 file is never present. If two processes both compute some new parameters, you
281 waste a bit of effort, but it doesn't seem worth messing around with locking to
282 prevent this.
283
284 Argument:
285   host       NULL for server, server for client (for error handling)
286
287 Returns:     OK/DEFER/FAIL
288 */
289
290 static int
291 init_rsa_dh(host_item *host)
292 {
293 int fd, ret;
294 gnutls_datum m, e, d, p, q, u, prime, generator;
295 uschar filename[200];
296
297 /* Initialize the data structures for holding the parameters */
298
299 ret = gnutls_rsa_params_init(&rsa_params);
300 if (ret < 0) return tls_error(US"init rsa_params", host, ret);
301
302 ret = gnutls_dh_params_init(&dh_params);
303 if (ret < 0) return tls_error(US"init dh_params", host, ret);
304
305 /* Set up the name of the cache file */
306
307 if (!string_format(filename, sizeof(filename), "%s/gnutls-params",
308       spool_directory))
309   return tls_error(US"overlong filename", host, 0);
310
311 /* Open the cache file for reading. If this fails because of a non-existent
312 file, compute a new set of parameters, write them to a temporary file, and then
313 rename that file as the cache file. Other opening errors are bad. */
314
315 fd = Uopen(filename, O_RDONLY, 0);
316 if (fd < 0)
317   {
318   unsigned int rsa_bits = RSA_BITS;
319   unsigned int dh_bits = DH_BITS;
320   uschar tempfilename[sizeof(filename) + 10];
321
322   if (errno != ENOENT)
323     return tls_error(string_open_failed(errno, "%s for reading", filename),
324       host, 0);
325
326   DEBUG(D_tls) debug_printf("generating %d bit RSA key...\n", RSA_BITS);
327   ret = gnutls_rsa_params_generate2(rsa_params, RSA_BITS);
328   if (ret < 0) return tls_error(US"RSA key generation", host, ret);
329
330   DEBUG(D_tls) debug_printf("generating %d bit Diffie-Hellman key...\n",
331     DH_BITS);
332   ret = gnutls_dh_params_generate2(dh_params, DH_BITS);
333   if (ret < 0) return tls_error(US"D-H key generation", host, ret);
334
335   /* Write the parameters to a file in the spool directory so that we
336   can use them from other Exim processes. */
337
338   sprintf(CS tempfilename, "%s-%d", filename, (int)getpid());
339   fd = Uopen(tempfilename, O_WRONLY|O_CREAT, 0400);
340   if (fd < 0)
341     return tls_error(string_open_failed(errno, "%s for writing", filename),
342       host, 0);
343   (void)fchown(fd, exim_uid, exim_gid);   /* Probably not necessary */
344
345   ret = gnutls_rsa_params_export_raw(rsa_params, &m, &e, &d, &p, &q, &u,
346     &rsa_bits);
347   if (ret < 0) return tls_error(US"RSA params export", host, ret);
348
349   ret = gnutls_dh_params_export_raw(dh_params, &prime, &generator, &dh_bits);
350   if (ret < 0) return tls_error(US"DH params export", host, ret);
351
352   if (!write_datum(fd, &m) ||
353       !write_datum(fd, &e) ||
354       !write_datum(fd, &d) ||
355       !write_datum(fd, &p) ||
356       !write_datum(fd, &q) ||
357       !write_datum(fd, &u) ||
358       !write_datum(fd, &prime) ||
359       !write_datum(fd, &generator))
360     return tls_error(US"TLS cache write failed", host, 0);
361
362   (void)close(fd);
363
364   if (rename(CS tempfilename, CS filename) < 0)
365     return tls_error(string_sprintf("failed to rename %s as %s: %s",
366       tempfilename, filename, strerror(errno)), host, 0);
367
368   DEBUG(D_tls) debug_printf("wrote RSA and D-H parameters to file\n");
369   }
370
371 /* File opened for reading; get the data */
372
373 else
374   {
375   if (!read_datum(fd, &m) ||
376       !read_datum(fd, &e) ||
377       !read_datum(fd, &d) ||
378       !read_datum(fd, &p) ||
379       !read_datum(fd, &q) ||
380       !read_datum(fd, &u) ||
381       !read_datum(fd, &prime) ||
382       !read_datum(fd, &generator))
383     return tls_error(US"TLS cache read failed", host, 0);
384
385   (void)close(fd);
386
387   ret = gnutls_rsa_params_import_raw(rsa_params, &m, &e, &d, &p, &q, &u);
388   if (ret < 0) return tls_error(US"RSA params import", host, ret);
389
390   ret = gnutls_dh_params_import_raw(dh_params, &prime, &generator);
391   if (ret < 0) return tls_error(US"DH params import", host, ret);
392
393   DEBUG(D_tls) debug_printf("read RSA and D-H parameters from file\n");
394   }
395
396 DEBUG(D_tls) debug_printf("initialized RSA and D-H parameters\n");
397 return OK;
398 }
399
400
401
402
403 /*************************************************
404 *            Initialize for GnuTLS               *
405 *************************************************/
406
407 /* Called from both server and client code. In the case of a server, errors
408 before actual TLS negotiation return DEFER.
409
410 Arguments:
411   host            connected host, if client; NULL if server
412   certificate     certificate file
413   privatekey      private key file
414   cas             CA certs file
415   crl             CRL file
416
417 Returns:          OK/DEFER/FAIL
418 */
419
420 static int
421 tls_init(host_item *host, uschar *certificate, uschar *privatekey, uschar *cas,
422   uschar *crl)
423 {
424 int rc;
425 uschar *cert_expanded, *key_expanded, *cas_expanded, *crl_expanded;
426
427 initialized = (host == NULL)? INITIALIZED_SERVER : INITIALIZED_CLIENT;
428
429 rc = gnutls_global_init();
430 if (rc < 0) return tls_error(US"tls-init", host, rc);
431
432 /* Create RSA and D-H parameters, or read them from the cache file. This
433 function does its own SMTP error messaging. */
434
435 rc = init_rsa_dh(host);
436 if (rc != OK) return rc;
437
438 /* Create the credentials structure */
439
440 rc = gnutls_certificate_allocate_credentials(&x509_cred);
441 if (rc < 0) return tls_error(US"certificate_allocate_credentials", host, rc);
442
443 /* This stuff must be done for each session, because different certificates
444 may be required for different sessions. */
445
446 if (!expand_check(certificate, US"tls_certificate", &cert_expanded))
447   return DEFER;
448
449 if (privatekey != NULL)
450   {
451   if (!expand_check(privatekey, US"tls_privatekey", &key_expanded))
452     return DEFER;
453   }
454 else key_expanded = cert_expanded;
455
456 /* Set the certificate and private keys */
457
458 if (cert_expanded != NULL)
459   {
460   DEBUG(D_tls) debug_printf("certificate file = %s\nkey file = %s\n",
461     cert_expanded, key_expanded);
462   rc = gnutls_certificate_set_x509_key_file(x509_cred, CS cert_expanded,
463     CS key_expanded, GNUTLS_X509_FMT_PEM);
464   if (rc < 0) return tls_error(US"cert/key setup", host, rc);
465   }
466
467 /* A certificate is mandatory in a server, but not in a client */
468
469 else
470   {
471   if (host == NULL)
472     return tls_error(US"no TLS server certificate is specified", host, 0);
473   DEBUG(D_tls) debug_printf("no TLS client certificate is specified\n");
474   }
475
476 /* Set the trusted CAs file if one is provided, and then add the CRL if one is
477 provided. Experiment shows that, if the certificate file is empty, an unhelpful
478 error message is provided. However, if we just refrain from setting anything up
479 in that case, certificate verification fails, which seems to be the correct
480 behaviour. */
481
482 if (cas != NULL)
483   {
484   struct stat statbuf;
485
486   if (!expand_check(cas, US"tls_verify_certificates", &cas_expanded))
487     return DEFER;
488
489   if (stat(CS cas_expanded, &statbuf) < 0)
490     {
491     log_write(0, LOG_MAIN|LOG_PANIC, "could not stat %s "
492       "(tls_verify_certificates): %s", cas_expanded, strerror(errno));
493     return DEFER;
494     }
495
496   DEBUG(D_tls) debug_printf("verify certificates = %s size=%d\n",
497     cas_expanded, (int)statbuf.st_size);
498
499   /* If the cert file is empty, there's no point in loading the CRL file. */
500
501   if (statbuf.st_size > 0)
502     {
503     rc = gnutls_certificate_set_x509_trust_file(x509_cred, CS cas_expanded,
504       GNUTLS_X509_FMT_PEM);
505     if (rc < 0) return tls_error(US"setup_certs", host, rc);
506
507     if (crl != NULL && *crl != 0)
508       {
509       if (!expand_check(crl, US"tls_crl", &crl_expanded))
510         return DEFER;
511       DEBUG(D_tls) debug_printf("loading CRL file = %s\n", crl_expanded);
512       rc = gnutls_certificate_set_x509_crl_file(x509_cred, CS crl_expanded,
513         GNUTLS_X509_FMT_PEM);
514       if (rc < 0) return tls_error(US"CRL setup", host, rc);
515       }
516     }
517   }
518
519 /* Associate the parameters with the x509 credentials structure. */
520
521 gnutls_certificate_set_dh_params(x509_cred, dh_params);
522 gnutls_certificate_set_rsa_params(x509_cred, rsa_params);
523
524 DEBUG(D_tls) debug_printf("initialized certificate stuff\n");
525 return OK;
526 }
527
528
529
530
531 /*************************************************
532 *        Remove ciphers from priority list       *
533 *************************************************/
534
535 /* Cautiously written so that it will remove duplicates if present.
536
537 Arguments:
538   list         a zero-terminated list
539   remove_list  a zero-terminated list to be removed
540
541 Returns:       nothing
542 */
543
544 static void
545 remove_ciphers(int *list, int *remove_list)
546 {
547 for (; *remove_list != 0; remove_list++)
548   {
549   int *p = list;
550   while (*p != 0)
551     {
552     if (*p == *remove_list)
553       {
554       int *pp = p;
555       do { pp[0] = pp[1]; pp++; } while (*pp != 0);
556       }
557     else p++;
558     }
559   }
560 }
561
562
563
564 /*************************************************
565 *        Add ciphers to priority list            *
566 *************************************************/
567
568 /* Cautiously written to check the list size
569
570 Arguments:
571   list         a zero-terminated list
572   list_max     maximum offset in the list
573   add_list     a zero-terminated list to be added
574
575 Returns:       TRUE if OK; FALSE if list overflows
576 */
577
578 static BOOL
579 add_ciphers(int *list, int list_max, int *add_list)
580 {
581 int next = 0;
582 while (list[next] != 0) next++;
583 while (*add_list != 0)
584   {
585   if (next >= list_max) return FALSE;
586   list[next++] = *add_list++;
587   }
588 list[next] = 0;
589 return TRUE;
590 }
591
592
593
594 /*************************************************
595 *        Initialize a single GNUTLS session      *
596 *************************************************/
597
598 /* Set the algorithm, the db backend, whether to request certificates etc.
599
600 TLS in Exim was first implemented using OpenSSL. This has a function to which
601 you pass a list of cipher suites that are permitted/not permitted. GnuTLS works
602 differently. It operates using priority lists for the different components of
603 cipher suites.
604
605 For compatibility of configuration, we scan a list of cipher suites and set
606 priorities therefrom. However, at the moment, we pay attention only to the bulk
607 cipher.
608
609 Arguments:
610   side         one of GNUTLS_SERVER, GNUTLS_CLIENT
611   expciphers   expanded ciphers list
612
613 Returns:  a gnutls_session, or NULL if there is a problem
614 */
615
616 static gnutls_session
617 tls_session_init(int side, uschar *expciphers)
618 {
619 gnutls_session session;
620
621 gnutls_init(&session, side);
622
623 /* Handle the list of permitted ciphers */
624
625 memcpy(cipher_priority, default_cipher_priority, sizeof(cipher_priority));
626
627 if (expciphers != NULL)
628   {
629   int sep = 0;
630   BOOL first = TRUE;
631   uschar *cipher;
632
633   /* The names OpenSSL uses are of the form DES-CBC3-SHA, using hyphen
634   separators. GnuTLS uses underscore separators. So that I can use either form
635   in my tests, and also for general convenience, we turn hyphens into
636   underscores before scanning the list. */
637
638   uschar *s = expciphers;
639   while (*s != 0) { if (*s == '-') *s = '_'; s++; }
640
641   while ((cipher = string_nextinlist(&expciphers, &sep, big_buffer,
642              big_buffer_size)) != NULL)
643     {
644     int i;
645     BOOL exclude = cipher[0] == '!';
646     if (first && !exclude) cipher_priority[0] = 0;
647     first = FALSE;
648
649     for (i = 0; i < sizeof(cipher_index)/sizeof(pri_item); i++)
650       {
651       uschar *ss = strstric(cipher, cipher_index[i].name, FALSE);
652       if (ss != NULL)
653         {
654         uschar *endss = ss + Ustrlen(cipher_index[i].name);
655         if ((ss == cipher || !isalnum(ss[-1])) && !isalnum(*endss))
656           {
657           if (exclude)
658             remove_ciphers(cipher_priority, cipher_index[i].values);
659           else
660             {
661             if (!add_ciphers(cipher_priority,
662                              sizeof(cipher_priority)/sizeof(pri_item),
663                              cipher_index[i].values))
664               {
665               log_write(0, LOG_MAIN|LOG_PANIC, "GnuTLS init failed: cipher "
666                 "priority table overflow");
667               gnutls_deinit(session);
668               return NULL;
669               }
670             }
671           }
672         }
673       }
674     }
675
676   DEBUG(D_tls)
677     {
678     int *ptr = cipher_priority;
679     debug_printf("adjusted cipher priorities:");
680     while (*ptr != 0) debug_printf(" %d", *ptr++);
681     debug_printf("\n");
682     }
683   }
684
685 /* Define the various priorities */
686
687 gnutls_cipher_set_priority(session, cipher_priority);
688 gnutls_compression_set_priority(session, comp_priority);
689 gnutls_kx_set_priority(session, kx_priority);
690 gnutls_protocol_set_priority(session, protocol_priority);
691 gnutls_mac_set_priority(session, mac_priority);
692
693 gnutls_cred_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
694
695 gnutls_dh_set_prime_bits(session, DH_BITS);
696
697 /* Request or demand a certificate of the peer, as configured. This will
698 happen only in a server. */
699
700 if (verify_requirement != VERIFY_NONE)
701   gnutls_certificate_server_set_request(session,
702     (verify_requirement == VERIFY_OPTIONAL)?
703       GNUTLS_CERT_REQUEST : GNUTLS_CERT_REQUIRE);
704
705 gnutls_db_set_cache_expiration(session, ssl_session_timeout);
706
707 DEBUG(D_tls) debug_printf("initialized GnuTLS session\n");
708 return session;
709 }
710
711
712
713 /*************************************************
714 *           Get name of cipher in use            *
715 *************************************************/
716
717 /* The answer is left in a static buffer, and tls_cipher is set to point
718 to it.
719
720 Argument:   pointer to a GnuTLS session
721 Returns:    nothing
722 */
723
724 static void
725 construct_cipher_name(gnutls_session session)
726 {
727 static uschar cipherbuf[256];
728 uschar *ver;
729 int bits, c, kx, mac;
730
731 ver = string_copy(
732   US gnutls_protocol_get_name(gnutls_protocol_get_version(session)));
733 if (Ustrncmp(ver, "TLS ", 4) == 0) ver[3] = '-';   /* Don't want space */
734
735 c = gnutls_cipher_get(session);
736 bits = gnutls_cipher_get_key_size(c);
737
738 mac = gnutls_mac_get(session);
739 kx = gnutls_kx_get(session);
740
741 string_format(cipherbuf, sizeof(cipherbuf), "%s:%s:%u", ver,
742   gnutls_cipher_suite_get_name(kx, c, mac), bits);
743 tls_cipher = cipherbuf;
744
745 DEBUG(D_tls) debug_printf("cipher: %s\n", cipherbuf);
746 }
747
748
749
750 /*************************************************
751 *       Start a TLS session in a server          *
752 *************************************************/
753
754 /* This is called when Exim is running as a server, after having received
755 the STARTTLS command. It must respond to that command, and then negotiate
756 a TLS session.
757
758 Arguments:
759   require_ciphers  list of allowed ciphers
760
761 Returns:           OK on success
762                    DEFER for errors before the start of the negotiation
763                    FAIL for errors during the negotation; the server can't
764                      continue running.
765 */
766
767 int
768 tls_server_start(uschar *require_ciphers)
769 {
770 int rc;
771 uschar *error;
772 uschar *expciphers = NULL;
773
774 /* Check for previous activation */
775
776 if (tls_active >= 0)
777   {
778   log_write(0, LOG_MAIN, "STARTTLS received in already encrypted "
779     "connection from %s",
780     (sender_fullhost != NULL)? sender_fullhost : US"local process");
781   smtp_printf("554 Already in TLS\r\n");
782   return FAIL;
783   }
784
785 /* Initialize the library. If it fails, it will already have logged the error
786 and sent an SMTP response. */
787
788 DEBUG(D_tls) debug_printf("initializing GnuTLS as a server\n");
789
790 rc = tls_init(NULL, tls_certificate, tls_privatekey, tls_verify_certificates,
791   tls_crl);
792 if (rc != OK) return rc;
793
794 if (!expand_check(require_ciphers, US"tls_require_ciphers", &expciphers))
795   return FAIL;
796
797 /* If this is a host for which certificate verification is mandatory or
798 optional, set up appropriately. */
799
800 tls_certificate_verified = FALSE;
801 verify_requirement = VERIFY_NONE;
802
803 if (verify_check_host(&tls_verify_hosts) == OK)
804   verify_requirement = VERIFY_REQUIRED;
805 else if (verify_check_host(&tls_try_verify_hosts) == OK)
806   verify_requirement = VERIFY_OPTIONAL;
807
808 /* Prepare for new connection */
809
810 tls_session = tls_session_init(GNUTLS_SERVER, expciphers);
811 if (tls_session == NULL)
812   return tls_error(US"tls_session_init", NULL, GNUTLS_E_MEMORY_ERROR);
813
814 /* Set context and tell client to go ahead, except in the case of TLS startup
815 on connection, where outputting anything now upsets the clients and tends to
816 make them disconnect. We need to have an explicit fflush() here, to force out
817 the response. Other smtp_printf() calls do not need it, because in non-TLS
818 mode, the fflush() happens when smtp_getc() is called. */
819
820 if (!tls_on_connect)
821   {
822   smtp_printf("220 TLS go ahead\r\n");
823   fflush(smtp_out);
824   }
825
826 /* Now negotiate the TLS session. We put our own timer on it, since it seems
827 that the GnuTLS library doesn't. */
828
829 gnutls_transport_set_ptr(tls_session, (gnutls_transport_ptr)fileno(smtp_out));
830
831 sigalrm_seen = FALSE;
832 if (smtp_receive_timeout > 0) alarm(smtp_receive_timeout);
833 rc = gnutls_handshake(tls_session);
834 alarm(0);
835
836 if (rc < 0)
837   {
838   if (sigalrm_seen)
839     Ustrcpy(ssl_errstring, "timed out");
840   else
841     Ustrcpy(ssl_errstring, gnutls_strerror(rc));
842   log_write(0, LOG_MAIN,
843     "TLS error on connection from %s (gnutls_handshake): %s",
844     (sender_fullhost != NULL)? sender_fullhost : US"local process",
845     ssl_errstring);
846
847   /* It seems that, except in the case of a timeout, we have to close the
848   connection right here; otherwise if the other end is running OpenSSL it hangs
849   until the server times out. */
850
851   if (!sigalrm_seen)
852     {
853     fclose(smtp_out);
854     fclose(smtp_in);
855     }
856
857   return FAIL;
858   }
859
860 DEBUG(D_tls) debug_printf("gnutls_handshake was successful\n");
861
862 if (verify_requirement != VERIFY_NONE &&
863      !verify_certificate(tls_session, &error))
864   {
865   log_write(0, LOG_MAIN,
866     "TLS error on connection from %s: certificate verification failed (%s)",
867     (sender_fullhost != NULL)? sender_fullhost : US"local process", error);
868   return FAIL;
869   }
870
871 construct_cipher_name(tls_session);
872
873 /* TLS has been set up. Adjust the input functions to read via TLS,
874 and initialize appropriately. */
875
876 ssl_xfer_buffer = store_malloc(ssl_xfer_buffer_size);
877 ssl_xfer_buffer_lwm = ssl_xfer_buffer_hwm = 0;
878 ssl_xfer_eof = ssl_xfer_error = 0;
879
880 receive_getc = tls_getc;
881 receive_ungetc = tls_ungetc;
882 receive_feof = tls_feof;
883 receive_ferror = tls_ferror;
884
885 tls_active = fileno(smtp_out);
886
887 return OK;
888 }
889
890
891
892
893 /*************************************************
894 *    Start a TLS session in a client             *
895 *************************************************/
896
897 /* Called from the smtp transport after STARTTLS has been accepted.
898
899 Arguments:
900   fd                the fd of the connection
901   host              connected host (for messages)
902   addr
903   dhparam           DH parameter file
904   certificate       certificate file
905   privatekey        private key file
906   verify_certs      file for certificate verify
907   verify_crl        CRL for verify
908   require_ciphers   list of allowed ciphers
909   timeout           startup timeout
910
911 Returns:            OK/DEFER/FAIL (because using common functions),
912                     but for a client, DEFER and FAIL have the same meaning
913 */
914
915 int
916 tls_client_start(int fd, host_item *host, address_item *addr, uschar *dhparam,
917   uschar *certificate, uschar *privatekey, uschar *verify_certs,
918   uschar *verify_crl, uschar *require_ciphers, int timeout)
919 {
920 const gnutls_datum *server_certs;
921 uschar *expciphers = NULL;
922 uschar *error;
923 unsigned int server_certs_size;
924 int rc;
925
926 DEBUG(D_tls) debug_printf("initializing GnuTLS as a client\n");
927
928 client_host = host;
929 verify_requirement = (verify_certs == NULL)? VERIFY_NONE : VERIFY_REQUIRED;
930 rc = tls_init(host, certificate, privatekey, verify_certs, verify_crl);
931 if (rc != OK) return rc;
932
933 if (!expand_check(require_ciphers, US"tls_require_ciphers", &expciphers))
934   return FAIL;
935
936 tls_session = tls_session_init(GNUTLS_CLIENT, expciphers);
937 if (tls_session == NULL)
938   return tls_error(US "tls_session_init", host, GNUTLS_E_MEMORY_ERROR);
939
940 gnutls_transport_set_ptr(tls_session, (gnutls_transport_ptr)fd);
941
942 /* There doesn't seem to be a built-in timeout on connection. */
943
944 sigalrm_seen = FALSE;
945 alarm(timeout);
946 rc = gnutls_handshake(tls_session);
947 alarm(0);
948
949 if (rc < 0)
950   {
951   if (sigalrm_seen)
952     {
953     log_write(0, LOG_MAIN, "TLS error on connection to %s [%s]: "
954       "gnutls_handshake timed out", host->name, host->address);
955     return FAIL;
956     }
957   else return tls_error(US "gnutls_handshake", host, rc);
958   }
959
960 server_certs = gnutls_certificate_get_peers(tls_session, &server_certs_size);
961
962 if (server_certs != NULL)
963   {
964   uschar buff[1024];
965   gnutls_x509_crt gcert;
966
967   gnutls_x509_crt_init(&gcert);
968   tls_peerdn = US"unknown";
969
970   if (gnutls_x509_crt_import(gcert, server_certs, GNUTLS_X509_FMT_DER) == 0)
971     {
972     size_t bufsize = sizeof(buff);
973     if (gnutls_x509_crt_get_dn(gcert, CS buff, &bufsize) >= 0)
974       tls_peerdn = string_copy_malloc(buff);
975     }
976   }
977
978 /* Should we also verify the hostname here? */
979
980 if (verify_requirement != VERIFY_NONE &&
981       !verify_certificate(tls_session, &error))
982   {
983   log_write(0, LOG_MAIN,
984     "TLS error on connection to %s [%s]: certificate verification failed (%s)",
985     host->name, host->address, error);
986   return FAIL;
987   }
988
989 construct_cipher_name(tls_session);    /* Sets tls_cipher */
990 tls_active = fd;
991 return OK;
992 }
993
994
995
996 /*************************************************
997 *    Deal with logging errors during I/O         *
998 *************************************************/
999
1000 /* We have to get the identity of the peer from saved data.
1001
1002 Argument:
1003   ec       the GnuTLS error code, or 0 if it's a local error
1004   when     text identifying read or write
1005   text     local error text when ec is 0
1006
1007 Returns:   nothing
1008 */
1009
1010 static void
1011 record_io_error(int ec, uschar *when, uschar *text)
1012 {
1013 uschar *additional = US"";
1014
1015 if (ec == GNUTLS_E_FATAL_ALERT_RECEIVED)
1016   additional = string_sprintf(": %s",
1017     gnutls_alert_get_name(gnutls_alert_get(tls_session)));
1018
1019 if (initialized == INITIALIZED_SERVER)
1020   log_write(0, LOG_MAIN, "TLS %s error on connection from %s: %s%s", when,
1021     (sender_fullhost != NULL)? sender_fullhost : US "local process",
1022     (ec == 0)? text : US gnutls_strerror(ec), additional);
1023
1024 else
1025   log_write(0, LOG_MAIN, "TLS %s error on connection to %s [%s]: %s%s", when,
1026     client_host->name, client_host->address,
1027     (ec == 0)? text : US gnutls_strerror(ec), additional);
1028 }
1029
1030
1031
1032 /*************************************************
1033 *            TLS version of getc                 *
1034 *************************************************/
1035
1036 /* This gets the next byte from the TLS input buffer. If the buffer is empty,
1037 it refills the buffer via the GnuTLS reading function.
1038
1039 Arguments:  none
1040 Returns:    the next character or EOF
1041 */
1042
1043 int
1044 tls_getc(void)
1045 {
1046 if (ssl_xfer_buffer_lwm >= ssl_xfer_buffer_hwm)
1047   {
1048   int inbytes;
1049
1050   DEBUG(D_tls) debug_printf("Calling gnutls_record_recv(%lx, %lx, %u)\n",
1051     (long) tls_session, (long) ssl_xfer_buffer, ssl_xfer_buffer_size);
1052
1053   if (smtp_receive_timeout > 0) alarm(smtp_receive_timeout);
1054   inbytes = gnutls_record_recv(tls_session, CS ssl_xfer_buffer,
1055     ssl_xfer_buffer_size);
1056   alarm(0);
1057
1058   /* A zero-byte return appears to mean that the TLS session has been
1059      closed down, not that the socket itself has been closed down. Revert to
1060      non-TLS handling. */
1061
1062   if (inbytes == 0)
1063     {
1064     DEBUG(D_tls) debug_printf("Got TLS_EOF\n");
1065
1066     receive_getc = smtp_getc;
1067     receive_ungetc = smtp_ungetc;
1068     receive_feof = smtp_feof;
1069     receive_ferror = smtp_ferror;
1070
1071     gnutls_deinit(tls_session);
1072     tls_session = NULL;
1073     tls_active = -1;
1074     tls_cipher = NULL;
1075     tls_peerdn = NULL;
1076
1077     return smtp_getc();
1078     }
1079
1080   /* Handle genuine errors */
1081
1082   else if (inbytes < 0)
1083     {
1084     record_io_error(inbytes, US"recv", NULL);
1085     ssl_xfer_error = 1;
1086     return EOF;
1087     }
1088
1089   ssl_xfer_buffer_hwm = inbytes;
1090   ssl_xfer_buffer_lwm = 0;
1091   }
1092
1093
1094 /* Something in the buffer; return next uschar */
1095
1096 return ssl_xfer_buffer[ssl_xfer_buffer_lwm++];
1097 }
1098
1099
1100
1101 /*************************************************
1102 *          Read bytes from TLS channel           *
1103 *************************************************/
1104
1105 /*
1106 Arguments:
1107   buff      buffer of data
1108   len       size of buffer
1109
1110 Returns:    the number of bytes read
1111             -1 after a failed read
1112 */
1113
1114 int
1115 tls_read(uschar *buff, size_t len)
1116 {
1117 int inbytes;
1118
1119 DEBUG(D_tls) debug_printf("Calling gnutls_record_recv(%lx, %lx, %u)\n",
1120   (long) tls_session, (long) buff, len);
1121
1122 inbytes = gnutls_record_recv(tls_session, CS buff, len);
1123 if (inbytes > 0) return inbytes;
1124 if (inbytes == 0)
1125   {
1126   DEBUG(D_tls) debug_printf("Got TLS_EOF\n");
1127   }
1128 else record_io_error(inbytes, US"recv", NULL);
1129
1130 return -1;
1131 }
1132
1133
1134
1135 /*************************************************
1136 *         Write bytes down TLS channel           *
1137 *************************************************/
1138
1139 /*
1140 Arguments:
1141   buff      buffer of data
1142   len       number of bytes
1143
1144 Returns:    the number of bytes after a successful write,
1145             -1 after a failed write
1146 */
1147
1148 int
1149 tls_write(const uschar *buff, size_t len)
1150 {
1151 int outbytes;
1152 int left = len;
1153
1154 DEBUG(D_tls) debug_printf("tls_do_write(%lx, %d)\n", (long) buff, left);
1155 while (left > 0)
1156   {
1157   DEBUG(D_tls) debug_printf("gnutls_record_send(SSL, %lx, %d)\n", (long)buff,
1158     left);
1159   outbytes = gnutls_record_send(tls_session, CS buff, left);
1160
1161   DEBUG(D_tls) debug_printf("outbytes=%d\n", outbytes);
1162   if (outbytes < 0)
1163     {
1164     record_io_error(outbytes, US"send", NULL);
1165     return -1;
1166     }
1167   if (outbytes == 0)
1168     {
1169     record_io_error(0, US"send", US"TLS channel closed on write");
1170     return -1;
1171     }
1172
1173   left -= outbytes;
1174   buff += outbytes;
1175   }
1176
1177 return len;
1178 }
1179
1180
1181
1182 /*************************************************
1183 *         Close down a TLS session               *
1184 *************************************************/
1185
1186 /* This is also called from within a delivery subprocess forked from the
1187 daemon, to shut down the TLS library, without actually doing a shutdown (which
1188 would tamper with the TLS session in the parent process).
1189
1190 Arguments:   TRUE if gnutls_bye is to be called
1191 Returns:     nothing
1192 */
1193
1194 void
1195 tls_close(BOOL shutdown)
1196 {
1197 if (tls_active < 0) return;  /* TLS was not active */
1198
1199 if (shutdown)
1200   {
1201   DEBUG(D_tls) debug_printf("tls_close(): shutting down TLS\n");
1202   gnutls_bye(tls_session, GNUTLS_SHUT_WR);
1203   }
1204
1205 gnutls_deinit(tls_session);
1206 tls_session = NULL;
1207 gnutls_global_deinit();
1208
1209 tls_active = -1;
1210 }
1211
1212 /* End of tls-gnu.c */