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