MH's patch for allowing control characters as list separators.
[exim.git] / src / src / tls-gnu.c
CommitLineData
83da1223 1/* $Cambridge: exim/src/src/tls-gnu.c,v 1.18 2007/01/18 15:35:42 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;
979
980tls_active = fileno(smtp_out);
981
982return OK;
983}
984
985
986
987
988/*************************************************
989* Start a TLS session in a client *
990*************************************************/
991
992/* Called from the smtp transport after STARTTLS has been accepted.
993
994Arguments:
995 fd the fd of the connection
996 host connected host (for messages)
83da1223 997 addr the first address (not used)
059ec3d9
PH
998 dhparam DH parameter file
999 certificate certificate file
1000 privatekey private key file
1001 verify_certs file for certificate verify
1002 verify_crl CRL for verify
83da1223
PH
1003 require_ciphers list of allowed ciphers or NULL
1004 require_mac list of allowed MACs or NULL
1005 require_kx list of allowed key_exchange methods or NULL
1006 require_proto list of allowed protocols or NULL
059ec3d9
PH
1007 timeout startup timeout
1008
1009Returns: OK/DEFER/FAIL (because using common functions),
1010 but for a client, DEFER and FAIL have the same meaning
1011*/
1012
1013int
1014tls_client_start(int fd, host_item *host, address_item *addr, uschar *dhparam,
1015 uschar *certificate, uschar *privatekey, uschar *verify_certs,
83da1223
PH
1016 uschar *verify_crl, uschar *require_ciphers, uschar *require_mac,
1017 uschar *require_kx, uschar *require_proto, int timeout)
059ec3d9
PH
1018{
1019const gnutls_datum *server_certs;
1020uschar *expciphers = NULL;
83da1223
PH
1021uschar *expmac = NULL;
1022uschar *expkx = NULL;
1023uschar *expproto = NULL;
059ec3d9
PH
1024uschar *error;
1025unsigned int server_certs_size;
1026int rc;
1027
1028DEBUG(D_tls) debug_printf("initializing GnuTLS as a client\n");
1029
1030client_host = host;
1031verify_requirement = (verify_certs == NULL)? VERIFY_NONE : VERIFY_REQUIRED;
1032rc = tls_init(host, certificate, privatekey, verify_certs, verify_crl);
1033if (rc != OK) return rc;
1034
83da1223
PH
1035if (!expand_check(require_ciphers, US"tls_require_ciphers", &expciphers) ||
1036 !expand_check(require_mac, US"gnutls_require_mac", &expmac) ||
1037 !expand_check(require_kx, US"gnutls_require_kx", &expkx) ||
1038 !expand_check(require_proto, US"gnutls_require_proto", &expproto))
059ec3d9
PH
1039 return FAIL;
1040
83da1223
PH
1041tls_session = tls_session_init(GNUTLS_CLIENT, expciphers, expmac, expkx,
1042 expproto);
1043
059ec3d9
PH
1044if (tls_session == NULL)
1045 return tls_error(US "tls_session_init", host, GNUTLS_E_MEMORY_ERROR);
1046
1047gnutls_transport_set_ptr(tls_session, (gnutls_transport_ptr)fd);
1048
1049/* There doesn't seem to be a built-in timeout on connection. */
1050
1051sigalrm_seen = FALSE;
1052alarm(timeout);
1053rc = gnutls_handshake(tls_session);
1054alarm(0);
1055
1056if (rc < 0)
1057 {
1058 if (sigalrm_seen)
1059 {
1060 log_write(0, LOG_MAIN, "TLS error on connection to %s [%s]: "
1061 "gnutls_handshake timed out", host->name, host->address);
1062 return FAIL;
1063 }
1064 else return tls_error(US "gnutls_handshake", host, rc);
1065 }
1066
1067server_certs = gnutls_certificate_get_peers(tls_session, &server_certs_size);
1068
1069if (server_certs != NULL)
1070 {
1071 uschar buff[1024];
1072 gnutls_x509_crt gcert;
1073
1074 gnutls_x509_crt_init(&gcert);
1075 tls_peerdn = US"unknown";
1076
1077 if (gnutls_x509_crt_import(gcert, server_certs, GNUTLS_X509_FMT_DER) == 0)
1078 {
1079 size_t bufsize = sizeof(buff);
1080 if (gnutls_x509_crt_get_dn(gcert, CS buff, &bufsize) >= 0)
1081 tls_peerdn = string_copy_malloc(buff);
1082 }
1083 }
1084
1085/* Should we also verify the hostname here? */
1086
1087if (verify_requirement != VERIFY_NONE &&
1088 !verify_certificate(tls_session, &error))
1089 {
1090 log_write(0, LOG_MAIN,
1091 "TLS error on connection to %s [%s]: certificate verification failed (%s)",
1092 host->name, host->address, error);
1093 return FAIL;
1094 }
1095
1096construct_cipher_name(tls_session); /* Sets tls_cipher */
1097tls_active = fd;
1098return OK;
1099}
1100
1101
1102
1103/*************************************************
1104* Deal with logging errors during I/O *
1105*************************************************/
1106
1107/* We have to get the identity of the peer from saved data.
1108
1109Argument:
1110 ec the GnuTLS error code, or 0 if it's a local error
1111 when text identifying read or write
1112 text local error text when ec is 0
1113
1114Returns: nothing
1115*/
1116
1117static void
1118record_io_error(int ec, uschar *when, uschar *text)
1119{
1120uschar *additional = US"";
1121
1122if (ec == GNUTLS_E_FATAL_ALERT_RECEIVED)
1123 additional = string_sprintf(": %s",
1124 gnutls_alert_get_name(gnutls_alert_get(tls_session)));
1125
1126if (initialized == INITIALIZED_SERVER)
1127 log_write(0, LOG_MAIN, "TLS %s error on connection from %s: %s%s", when,
1128 (sender_fullhost != NULL)? sender_fullhost : US "local process",
1129 (ec == 0)? text : US gnutls_strerror(ec), additional);
1130
1131else
1132 log_write(0, LOG_MAIN, "TLS %s error on connection to %s [%s]: %s%s", when,
1133 client_host->name, client_host->address,
1134 (ec == 0)? text : US gnutls_strerror(ec), additional);
1135}
1136
1137
1138
1139/*************************************************
1140* TLS version of getc *
1141*************************************************/
1142
1143/* This gets the next byte from the TLS input buffer. If the buffer is empty,
1144it refills the buffer via the GnuTLS reading function.
1145
1146Arguments: none
1147Returns: the next character or EOF
1148*/
1149
1150int
1151tls_getc(void)
1152{
1153if (ssl_xfer_buffer_lwm >= ssl_xfer_buffer_hwm)
1154 {
1155 int inbytes;
1156
1157 DEBUG(D_tls) debug_printf("Calling gnutls_record_recv(%lx, %lx, %u)\n",
1158 (long) tls_session, (long) ssl_xfer_buffer, ssl_xfer_buffer_size);
1159
1160 if (smtp_receive_timeout > 0) alarm(smtp_receive_timeout);
1161 inbytes = gnutls_record_recv(tls_session, CS ssl_xfer_buffer,
1162 ssl_xfer_buffer_size);
1163 alarm(0);
1164
1165 /* A zero-byte return appears to mean that the TLS session has been
1166 closed down, not that the socket itself has been closed down. Revert to
1167 non-TLS handling. */
1168
1169 if (inbytes == 0)
1170 {
1171 DEBUG(D_tls) debug_printf("Got TLS_EOF\n");
1172
1173 receive_getc = smtp_getc;
1174 receive_ungetc = smtp_ungetc;
1175 receive_feof = smtp_feof;
1176 receive_ferror = smtp_ferror;
1177
1178 gnutls_deinit(tls_session);
1179 tls_session = NULL;
1180 tls_active = -1;
1181 tls_cipher = NULL;
1182 tls_peerdn = NULL;
1183
1184 return smtp_getc();
1185 }
1186
1187 /* Handle genuine errors */
1188
1189 else if (inbytes < 0)
1190 {
1191 record_io_error(inbytes, US"recv", NULL);
1192 ssl_xfer_error = 1;
1193 return EOF;
1194 }
1195
1196 ssl_xfer_buffer_hwm = inbytes;
1197 ssl_xfer_buffer_lwm = 0;
1198 }
1199
1200
1201/* Something in the buffer; return next uschar */
1202
1203return ssl_xfer_buffer[ssl_xfer_buffer_lwm++];
1204}
1205
1206
1207
1208/*************************************************
1209* Read bytes from TLS channel *
1210*************************************************/
1211
1212/*
1213Arguments:
1214 buff buffer of data
1215 len size of buffer
1216
1217Returns: the number of bytes read
1218 -1 after a failed read
1219*/
1220
1221int
1222tls_read(uschar *buff, size_t len)
1223{
1224int inbytes;
1225
1226DEBUG(D_tls) debug_printf("Calling gnutls_record_recv(%lx, %lx, %u)\n",
1227 (long) tls_session, (long) buff, len);
1228
1229inbytes = gnutls_record_recv(tls_session, CS buff, len);
1230if (inbytes > 0) return inbytes;
1231if (inbytes == 0)
1232 {
1233 DEBUG(D_tls) debug_printf("Got TLS_EOF\n");
1234 }
1235else record_io_error(inbytes, US"recv", NULL);
1236
1237return -1;
1238}
1239
1240
1241
1242/*************************************************
1243* Write bytes down TLS channel *
1244*************************************************/
1245
1246/*
1247Arguments:
1248 buff buffer of data
1249 len number of bytes
1250
1251Returns: the number of bytes after a successful write,
1252 -1 after a failed write
1253*/
1254
1255int
1256tls_write(const uschar *buff, size_t len)
1257{
1258int outbytes;
1259int left = len;
1260
1261DEBUG(D_tls) debug_printf("tls_do_write(%lx, %d)\n", (long) buff, left);
1262while (left > 0)
1263 {
1264 DEBUG(D_tls) debug_printf("gnutls_record_send(SSL, %lx, %d)\n", (long)buff,
1265 left);
1266 outbytes = gnutls_record_send(tls_session, CS buff, left);
1267
1268 DEBUG(D_tls) debug_printf("outbytes=%d\n", outbytes);
1269 if (outbytes < 0)
1270 {
1271 record_io_error(outbytes, US"send", NULL);
1272 return -1;
1273 }
1274 if (outbytes == 0)
1275 {
1276 record_io_error(0, US"send", US"TLS channel closed on write");
1277 return -1;
1278 }
1279
1280 left -= outbytes;
1281 buff += outbytes;
1282 }
1283
1284return len;
1285}
1286
1287
1288
1289/*************************************************
1290* Close down a TLS session *
1291*************************************************/
1292
1293/* This is also called from within a delivery subprocess forked from the
1294daemon, to shut down the TLS library, without actually doing a shutdown (which
1295would tamper with the TLS session in the parent process).
1296
1297Arguments: TRUE if gnutls_bye is to be called
1298Returns: nothing
1299*/
1300
1301void
1302tls_close(BOOL shutdown)
1303{
1304if (tls_active < 0) return; /* TLS was not active */
1305
1306if (shutdown)
1307 {
1308 DEBUG(D_tls) debug_printf("tls_close(): shutting down TLS\n");
1309 gnutls_bye(tls_session, GNUTLS_SHUT_WR);
1310 }
1311
1312gnutls_deinit(tls_session);
1313tls_session = NULL;
1314gnutls_global_deinit();
1315
1316tls_active = -1;
1317}
1318
1319/* End of tls-gnu.c */