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