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