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