1 /* $Cambridge: exim/src/src/tls-gnu.c,v 1.3 2004/12/21 09:26:31 ph10 Exp $ */
3 /*************************************************
4 * Exim - an Internet mail transport agent *
5 *************************************************/
7 /* Copyright (c) University of Cambridge 1995 - 2004 */
8 /* See the file NOTICE for conditions of use and distribution. */
10 /* This module provides TLS (aka SSL) support for Exim using the GnuTLS
11 library. It is #included into tls.c when that library is used. The code herein
12 is based on a patch that was contributed by Nikos Mavroyanopoulos.
14 No cryptographic code is included in Exim. All this module does is to call
15 functions from the GnuTLS library. */
18 /* Heading stuff for GnuTLS */
20 #include <gnutls/gnutls.h>
21 #include <gnutls/x509.h>
24 #define UNKNOWN_NAME "unknown"
28 /* Values for verify_requirment and initialized */
30 enum { VERIFY_NONE, VERIFY_OPTIONAL, VERIFY_REQUIRED };
31 enum { INITIALIZED_NOT, INITIALIZED_SERVER, INITIALIZED_CLIENT };
33 /* Local static variables for GNUTLS */
35 static BOOL initialized = INITIALIZED_NOT;
36 static host_item *client_host;
38 static gnutls_rsa_params rsa_params = NULL;
39 static gnutls_dh_params dh_params = NULL;
41 static gnutls_certificate_server_credentials x509_cred = NULL;
42 static gnutls_session tls_session = NULL;
44 static char ssl_errstring[256];
46 static int ssl_session_timeout = 200;
47 static int verify_requirement;
49 /* Priorities for TLS algorithms to use. At present, only the cipher priority
50 vector can be altered. */
52 static const int protocol_priority[16] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
54 static const int kx_priority[16] = {
61 static int default_cipher_priority[16] = {
62 GNUTLS_CIPHER_AES_256_CBC,
63 GNUTLS_CIPHER_AES_128_CBC,
64 GNUTLS_CIPHER_3DES_CBC,
65 GNUTLS_CIPHER_ARCFOUR_128,
68 static int cipher_priority[16];
70 static const int mac_priority[16] = {
75 static const int comp_priority[16] = { GNUTLS_COMP_NULL, 0 };
76 static const int cert_type_priority[16] = { GNUTLS_CRT_X509, 0 };
78 /* Tables of cipher names and equivalent numbers */
80 typedef struct pri_item {
85 static int arcfour_128_codes[] = { GNUTLS_CIPHER_ARCFOUR_128, 0 };
86 static int arcfour_40_codes[] = { GNUTLS_CIPHER_ARCFOUR_40, 0 };
87 static int arcfour_codes[] = { GNUTLS_CIPHER_ARCFOUR_128,
88 GNUTLS_CIPHER_ARCFOUR_40, 0 };
89 static int aes_256_codes[] = { GNUTLS_CIPHER_AES_256_CBC, 0 };
90 static int aes_128_codes[] = { GNUTLS_CIPHER_AES_128_CBC, 0 };
91 static int aes_codes[] = { GNUTLS_CIPHER_AES_256_CBC,
92 GNUTLS_CIPHER_AES_128_CBC, 0 };
93 static int des3_codes[] = { GNUTLS_CIPHER_3DES_CBC, 0 };
95 static 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 }
107 /*************************************************
109 *************************************************/
111 /* Called from lots of places when errors occur before actually starting to do
112 the TLS handshake, that is, while the session is still in clear. Always returns
113 DEFER for a server and FAIL for a client so that most calls can use "return
114 tls_error(...)" to do this processing and then give an appropriate return. A
115 single function is used for both server and client, because it is called from
116 some shared functions.
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
124 Returns: OK/DEFER/FAIL
128 tls_error(uschar *prefix, host_item *host, int err)
130 uschar *errtext = US"";
131 if (err != 0) errtext = string_sprintf(": %s", gnutls_strerror(err));
134 log_write(0, LOG_MAIN, "TLS error on connection from %s (%s)%s",
135 (sender_fullhost != NULL)? sender_fullhost : US "local process",
141 log_write(0, LOG_MAIN, "TLS error on connection to %s [%s] (%s)%s",
142 host->name, host->address, prefix, errtext);
149 /*************************************************
150 * Verify certificate *
151 *************************************************/
153 /* Called after a successful handshake, when certificate verification is
154 required or optional, for both server and client.
157 session GNUTLS session
158 error where to put text giving a reason for failure
164 verify_certificate(gnutls_session session, uschar **error)
167 uschar *dn_string = US"";
168 const gnutls_datum *cert;
169 unsigned int cert_size = 0;
173 /* Get the peer's certificate. If it sent one, extract it's DN, and then
174 attempt to verify the certificate. If no certificate is supplied, verification
175 is forced to fail. */
177 cert = gnutls_certificate_get_peers(session, &cert_size);
181 gnutls_x509_crt gcert;
183 gnutls_x509_crt_init(&gcert);
184 dn_string = US"unknown";
186 if (gnutls_x509_crt_import(gcert, cert, GNUTLS_X509_FMT_DER) == 0)
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);
193 verify = gnutls_certificate_verify_peers(session);
197 DEBUG(D_tls) debug_printf("no peer certificate supplied\n");
198 verify = GNUTLS_CERT_INVALID;
199 *error = US"not supplied";
202 /* Handle the result of verification. INVALID seems to be set as well
203 as REVOKED, but leave the test for both. */
205 if ((verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED)) != 0)
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)
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 */
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);
222 tls_certificate_verified = TRUE;
223 DEBUG(D_tls) debug_printf("TLS certificate verified: peerdn=%s\n",
227 tls_peerdn = dn_string;
228 return TRUE; /* accept */
234 /*************************************************
235 * Write/read datum to/from file *
236 *************************************************/
238 /* These functions are used for saving and restoring the RSA and D-H parameters
239 for use by all Exim processes. Data that is read is placed in malloc'd store
240 because that's what happens for newly generated data.
243 fd the file descriptor
244 d points to the datum
246 returns: FALSE on error (errno set)
250 write_datum(int fd, gnutls_datum *d)
252 if (write(fd, &(d->size), sizeof(d->size)) != sizeof(d->size)) return FALSE;
253 if (write(fd, d->data, d->size) != d->size) return FALSE;
259 read_datum(int fd, gnutls_datum *d)
261 if (read(fd, &(d->size), sizeof(d->size)) != sizeof(d->size)) return FALSE;
262 d->data = malloc(d->size);
263 if (d->data == NULL) return FALSE;
264 if (read(fd, d->data, d->size) != d->size) return FALSE;
270 /*************************************************
271 * Setup up RSA and DH parameters *
272 *************************************************/
274 /* Generating the RSA and D-H parameters takes a long time. They only need to
275 be re-generated every so often, depending on security policy. What we do is to
276 keep these parameters in a file in the spool directory. If the file does not
277 exist, we generate them. This means that it is easy to cause a regeneration.
279 The new file is written as a temporary file and renamed, so that an incomplete
280 file is never present. If two processes both compute some new parameters, you
281 waste a bit of effort, but it doesn't seem worth messing around with locking to
285 host NULL for server, server for client (for error handling)
287 Returns: OK/DEFER/FAIL
291 init_rsa_dh(host_item *host)
294 gnutls_datum m, e, d, p, q, u, prime, generator;
295 uschar filename[200];
297 /* Initialize the data structures for holding the parameters */
299 ret = gnutls_rsa_params_init(&rsa_params);
300 if (ret < 0) return tls_error(US"init rsa_params", host, ret);
302 ret = gnutls_dh_params_init(&dh_params);
303 if (ret < 0) return tls_error(US"init dh_params", host, ret);
305 /* Set up the name of the cache file */
307 if (!string_format(filename, sizeof(filename), "%s/gnutls-params",
309 return tls_error(US"overlong filename", host, 0);
311 /* Open the cache file for reading. If this fails because of a non-existent
312 file, compute a new set of parameters, write them to a temporary file, and then
313 rename that file as the cache file. Other opening errors are bad. */
315 fd = Uopen(filename, O_RDONLY, 0);
318 unsigned int rsa_bits = RSA_BITS;
319 unsigned int dh_bits = DH_BITS;
320 uschar tempfilename[sizeof(filename) + 10];
323 return tls_error(string_open_failed(errno, "%s for reading", filename),
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);
330 DEBUG(D_tls) debug_printf("generating %d bit Diffie-Hellman key...\n",
332 ret = gnutls_dh_params_generate2(dh_params, DH_BITS);
333 if (ret < 0) return tls_error(US"D-H key generation", host, ret);
335 /* Write the parameters to a file in the spool directory so that we
336 can use them from other Exim processes. */
338 sprintf(CS tempfilename, "%s-%d", filename, (int)getpid());
339 fd = Uopen(tempfilename, O_WRONLY|O_CREAT, 0400);
341 return tls_error(string_open_failed(errno, "%s for writing", filename),
343 (void)fchown(fd, exim_uid, exim_gid); /* Probably not necessary */
345 ret = gnutls_rsa_params_export_raw(rsa_params, &m, &e, &d, &p, &q, &u,
347 if (ret < 0) return tls_error(US"RSA params export", host, ret);
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);
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);
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);
368 DEBUG(D_tls) debug_printf("wrote RSA and D-H parameters to file\n");
371 /* File opened for reading; get the data */
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);
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);
390 ret = gnutls_dh_params_import_raw(dh_params, &prime, &generator);
391 if (ret < 0) return tls_error(US"DH params import", host, ret);
393 DEBUG(D_tls) debug_printf("read RSA and D-H parameters from file\n");
396 DEBUG(D_tls) debug_printf("initialized RSA and D-H parameters\n");
403 /*************************************************
404 * Initialize for GnuTLS *
405 *************************************************/
407 /* Called from both server and client code. In the case of a server, errors
408 before actual TLS negotiation return DEFER.
411 host connected host, if client; NULL if server
412 certificate certificate file
413 privatekey private key file
417 Returns: OK/DEFER/FAIL
421 tls_init(host_item *host, uschar *certificate, uschar *privatekey, uschar *cas,
425 uschar *cert_expanded, *key_expanded, *cas_expanded, *crl_expanded;
427 initialized = (host == NULL)? INITIALIZED_SERVER : INITIALIZED_CLIENT;
429 rc = gnutls_global_init();
430 if (rc < 0) return tls_error(US"tls-init", host, rc);
432 /* Create RSA and D-H parameters, or read them from the cache file. This
433 function does its own SMTP error messaging. */
435 rc = init_rsa_dh(host);
436 if (rc != OK) return rc;
438 /* Create the credentials structure */
440 rc = gnutls_certificate_allocate_credentials(&x509_cred);
441 if (rc < 0) return tls_error(US"certificate_allocate_credentials", host, rc);
443 /* This stuff must be done for each session, because different certificates
444 may be required for different sessions. */
446 if (!expand_check(certificate, US"tls_certificate", &cert_expanded))
449 if (privatekey != NULL)
451 if (!expand_check(privatekey, US"tls_privatekey", &key_expanded))
454 else key_expanded = cert_expanded;
456 /* Set the certificate and private keys */
458 if (cert_expanded != NULL)
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);
466 uschar *msg = string_sprintf("cert/key setup: cert=%s key=%s",
467 cert_expanded, key_expanded);
468 return tls_error(msg, host, rc);
472 /* A certificate is mandatory in a server, but not in a client */
477 return tls_error(US"no TLS server certificate is specified", host, 0);
478 DEBUG(D_tls) debug_printf("no TLS client certificate is specified\n");
481 /* Set the trusted CAs file if one is provided, and then add the CRL if one is
482 provided. Experiment shows that, if the certificate file is empty, an unhelpful
483 error message is provided. However, if we just refrain from setting anything up
484 in that case, certificate verification fails, which seems to be the correct
491 if (!expand_check(cas, US"tls_verify_certificates", &cas_expanded))
494 if (stat(CS cas_expanded, &statbuf) < 0)
496 log_write(0, LOG_MAIN|LOG_PANIC, "could not stat %s "
497 "(tls_verify_certificates): %s", cas_expanded, strerror(errno));
501 DEBUG(D_tls) debug_printf("verify certificates = %s size=%d\n",
502 cas_expanded, (int)statbuf.st_size);
504 /* If the cert file is empty, there's no point in loading the CRL file. */
506 if (statbuf.st_size > 0)
508 rc = gnutls_certificate_set_x509_trust_file(x509_cred, CS cas_expanded,
509 GNUTLS_X509_FMT_PEM);
510 if (rc < 0) return tls_error(US"setup_certs", host, rc);
512 if (crl != NULL && *crl != 0)
514 if (!expand_check(crl, US"tls_crl", &crl_expanded))
516 DEBUG(D_tls) debug_printf("loading CRL file = %s\n", crl_expanded);
517 rc = gnutls_certificate_set_x509_crl_file(x509_cred, CS crl_expanded,
518 GNUTLS_X509_FMT_PEM);
519 if (rc < 0) return tls_error(US"CRL setup", host, rc);
524 /* Associate the parameters with the x509 credentials structure. */
526 gnutls_certificate_set_dh_params(x509_cred, dh_params);
527 gnutls_certificate_set_rsa_params(x509_cred, rsa_params);
529 DEBUG(D_tls) debug_printf("initialized certificate stuff\n");
536 /*************************************************
537 * Remove ciphers from priority list *
538 *************************************************/
540 /* Cautiously written so that it will remove duplicates if present.
543 list a zero-terminated list
544 remove_list a zero-terminated list to be removed
550 remove_ciphers(int *list, int *remove_list)
552 for (; *remove_list != 0; remove_list++)
557 if (*p == *remove_list)
560 do { pp[0] = pp[1]; pp++; } while (*pp != 0);
569 /*************************************************
570 * Add ciphers to priority list *
571 *************************************************/
573 /* Cautiously written to check the list size
576 list a zero-terminated list
577 list_max maximum offset in the list
578 add_list a zero-terminated list to be added
580 Returns: TRUE if OK; FALSE if list overflows
584 add_ciphers(int *list, int list_max, int *add_list)
587 while (list[next] != 0) next++;
588 while (*add_list != 0)
590 if (next >= list_max) return FALSE;
591 list[next++] = *add_list++;
599 /*************************************************
600 * Initialize a single GNUTLS session *
601 *************************************************/
603 /* Set the algorithm, the db backend, whether to request certificates etc.
605 TLS in Exim was first implemented using OpenSSL. This has a function to which
606 you pass a list of cipher suites that are permitted/not permitted. GnuTLS works
607 differently. It operates using priority lists for the different components of
610 For compatibility of configuration, we scan a list of cipher suites and set
611 priorities therefrom. However, at the moment, we pay attention only to the bulk
615 side one of GNUTLS_SERVER, GNUTLS_CLIENT
616 expciphers expanded ciphers list
618 Returns: a gnutls_session, or NULL if there is a problem
621 static gnutls_session
622 tls_session_init(int side, uschar *expciphers)
624 gnutls_session session;
626 gnutls_init(&session, side);
628 /* Handle the list of permitted ciphers */
630 memcpy(cipher_priority, default_cipher_priority, sizeof(cipher_priority));
632 if (expciphers != NULL)
638 /* The names OpenSSL uses are of the form DES-CBC3-SHA, using hyphen
639 separators. GnuTLS uses underscore separators. So that I can use either form
640 in my tests, and also for general convenience, we turn hyphens into
641 underscores before scanning the list. */
643 uschar *s = expciphers;
644 while (*s != 0) { if (*s == '-') *s = '_'; s++; }
646 while ((cipher = string_nextinlist(&expciphers, &sep, big_buffer,
647 big_buffer_size)) != NULL)
650 BOOL exclude = cipher[0] == '!';
651 if (first && !exclude) cipher_priority[0] = 0;
654 for (i = 0; i < sizeof(cipher_index)/sizeof(pri_item); i++)
656 uschar *ss = strstric(cipher, cipher_index[i].name, FALSE);
659 uschar *endss = ss + Ustrlen(cipher_index[i].name);
660 if ((ss == cipher || !isalnum(ss[-1])) && !isalnum(*endss))
663 remove_ciphers(cipher_priority, cipher_index[i].values);
666 if (!add_ciphers(cipher_priority,
667 sizeof(cipher_priority)/sizeof(pri_item),
668 cipher_index[i].values))
670 log_write(0, LOG_MAIN|LOG_PANIC, "GnuTLS init failed: cipher "
671 "priority table overflow");
672 gnutls_deinit(session);
683 int *ptr = cipher_priority;
684 debug_printf("adjusted cipher priorities:");
685 while (*ptr != 0) debug_printf(" %d", *ptr++);
690 /* Define the various priorities */
692 gnutls_cipher_set_priority(session, cipher_priority);
693 gnutls_compression_set_priority(session, comp_priority);
694 gnutls_kx_set_priority(session, kx_priority);
695 gnutls_protocol_set_priority(session, protocol_priority);
696 gnutls_mac_set_priority(session, mac_priority);
698 gnutls_cred_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
700 gnutls_dh_set_prime_bits(session, DH_BITS);
702 /* Request or demand a certificate of the peer, as configured. This will
703 happen only in a server. */
705 if (verify_requirement != VERIFY_NONE)
706 gnutls_certificate_server_set_request(session,
707 (verify_requirement == VERIFY_OPTIONAL)?
708 GNUTLS_CERT_REQUEST : GNUTLS_CERT_REQUIRE);
710 gnutls_db_set_cache_expiration(session, ssl_session_timeout);
712 DEBUG(D_tls) debug_printf("initialized GnuTLS session\n");
718 /*************************************************
719 * Get name of cipher in use *
720 *************************************************/
722 /* The answer is left in a static buffer, and tls_cipher is set to point
725 Argument: pointer to a GnuTLS session
730 construct_cipher_name(gnutls_session session)
732 static uschar cipherbuf[256];
734 int bits, c, kx, mac;
737 US gnutls_protocol_get_name(gnutls_protocol_get_version(session)));
738 if (Ustrncmp(ver, "TLS ", 4) == 0) ver[3] = '-'; /* Don't want space */
740 c = gnutls_cipher_get(session);
741 bits = gnutls_cipher_get_key_size(c);
743 mac = gnutls_mac_get(session);
744 kx = gnutls_kx_get(session);
746 string_format(cipherbuf, sizeof(cipherbuf), "%s:%s:%u", ver,
747 gnutls_cipher_suite_get_name(kx, c, mac), bits);
748 tls_cipher = cipherbuf;
750 DEBUG(D_tls) debug_printf("cipher: %s\n", cipherbuf);
755 /*************************************************
756 * Start a TLS session in a server *
757 *************************************************/
759 /* This is called when Exim is running as a server, after having received
760 the STARTTLS command. It must respond to that command, and then negotiate
764 require_ciphers list of allowed ciphers
766 Returns: OK on success
767 DEFER for errors before the start of the negotiation
768 FAIL for errors during the negotation; the server can't
773 tls_server_start(uschar *require_ciphers)
777 uschar *expciphers = NULL;
779 /* Check for previous activation */
783 log_write(0, LOG_MAIN, "STARTTLS received in already encrypted "
784 "connection from %s",
785 (sender_fullhost != NULL)? sender_fullhost : US"local process");
786 smtp_printf("554 Already in TLS\r\n");
790 /* Initialize the library. If it fails, it will already have logged the error
791 and sent an SMTP response. */
793 DEBUG(D_tls) debug_printf("initializing GnuTLS as a server\n");
795 rc = tls_init(NULL, tls_certificate, tls_privatekey, tls_verify_certificates,
797 if (rc != OK) return rc;
799 if (!expand_check(require_ciphers, US"tls_require_ciphers", &expciphers))
802 /* If this is a host for which certificate verification is mandatory or
803 optional, set up appropriately. */
805 tls_certificate_verified = FALSE;
806 verify_requirement = VERIFY_NONE;
808 if (verify_check_host(&tls_verify_hosts) == OK)
809 verify_requirement = VERIFY_REQUIRED;
810 else if (verify_check_host(&tls_try_verify_hosts) == OK)
811 verify_requirement = VERIFY_OPTIONAL;
813 /* Prepare for new connection */
815 tls_session = tls_session_init(GNUTLS_SERVER, expciphers);
816 if (tls_session == NULL)
817 return tls_error(US"tls_session_init", NULL, GNUTLS_E_MEMORY_ERROR);
819 /* Set context and tell client to go ahead, except in the case of TLS startup
820 on connection, where outputting anything now upsets the clients and tends to
821 make them disconnect. We need to have an explicit fflush() here, to force out
822 the response. Other smtp_printf() calls do not need it, because in non-TLS
823 mode, the fflush() happens when smtp_getc() is called. */
827 smtp_printf("220 TLS go ahead\r\n");
831 /* Now negotiate the TLS session. We put our own timer on it, since it seems
832 that the GnuTLS library doesn't. */
834 gnutls_transport_set_ptr(tls_session, (gnutls_transport_ptr)fileno(smtp_out));
836 sigalrm_seen = FALSE;
837 if (smtp_receive_timeout > 0) alarm(smtp_receive_timeout);
838 rc = gnutls_handshake(tls_session);
844 Ustrcpy(ssl_errstring, "timed out");
846 Ustrcpy(ssl_errstring, gnutls_strerror(rc));
847 log_write(0, LOG_MAIN,
848 "TLS error on connection from %s (gnutls_handshake): %s",
849 (sender_fullhost != NULL)? sender_fullhost : US"local process",
852 /* It seems that, except in the case of a timeout, we have to close the
853 connection right here; otherwise if the other end is running OpenSSL it hangs
854 until the server times out. */
865 DEBUG(D_tls) debug_printf("gnutls_handshake was successful\n");
867 if (verify_requirement != VERIFY_NONE &&
868 !verify_certificate(tls_session, &error))
870 log_write(0, LOG_MAIN,
871 "TLS error on connection from %s: certificate verification failed (%s)",
872 (sender_fullhost != NULL)? sender_fullhost : US"local process", error);
876 construct_cipher_name(tls_session);
878 /* TLS has been set up. Adjust the input functions to read via TLS,
879 and initialize appropriately. */
881 ssl_xfer_buffer = store_malloc(ssl_xfer_buffer_size);
882 ssl_xfer_buffer_lwm = ssl_xfer_buffer_hwm = 0;
883 ssl_xfer_eof = ssl_xfer_error = 0;
885 receive_getc = tls_getc;
886 receive_ungetc = tls_ungetc;
887 receive_feof = tls_feof;
888 receive_ferror = tls_ferror;
890 tls_active = fileno(smtp_out);
898 /*************************************************
899 * Start a TLS session in a client *
900 *************************************************/
902 /* Called from the smtp transport after STARTTLS has been accepted.
905 fd the fd of the connection
906 host connected host (for messages)
908 dhparam DH parameter file
909 certificate certificate file
910 privatekey private key file
911 verify_certs file for certificate verify
912 verify_crl CRL for verify
913 require_ciphers list of allowed ciphers
914 timeout startup timeout
916 Returns: OK/DEFER/FAIL (because using common functions),
917 but for a client, DEFER and FAIL have the same meaning
921 tls_client_start(int fd, host_item *host, address_item *addr, uschar *dhparam,
922 uschar *certificate, uschar *privatekey, uschar *verify_certs,
923 uschar *verify_crl, uschar *require_ciphers, int timeout)
925 const gnutls_datum *server_certs;
926 uschar *expciphers = NULL;
928 unsigned int server_certs_size;
931 DEBUG(D_tls) debug_printf("initializing GnuTLS as a client\n");
934 verify_requirement = (verify_certs == NULL)? VERIFY_NONE : VERIFY_REQUIRED;
935 rc = tls_init(host, certificate, privatekey, verify_certs, verify_crl);
936 if (rc != OK) return rc;
938 if (!expand_check(require_ciphers, US"tls_require_ciphers", &expciphers))
941 tls_session = tls_session_init(GNUTLS_CLIENT, expciphers);
942 if (tls_session == NULL)
943 return tls_error(US "tls_session_init", host, GNUTLS_E_MEMORY_ERROR);
945 gnutls_transport_set_ptr(tls_session, (gnutls_transport_ptr)fd);
947 /* There doesn't seem to be a built-in timeout on connection. */
949 sigalrm_seen = FALSE;
951 rc = gnutls_handshake(tls_session);
958 log_write(0, LOG_MAIN, "TLS error on connection to %s [%s]: "
959 "gnutls_handshake timed out", host->name, host->address);
962 else return tls_error(US "gnutls_handshake", host, rc);
965 server_certs = gnutls_certificate_get_peers(tls_session, &server_certs_size);
967 if (server_certs != NULL)
970 gnutls_x509_crt gcert;
972 gnutls_x509_crt_init(&gcert);
973 tls_peerdn = US"unknown";
975 if (gnutls_x509_crt_import(gcert, server_certs, GNUTLS_X509_FMT_DER) == 0)
977 size_t bufsize = sizeof(buff);
978 if (gnutls_x509_crt_get_dn(gcert, CS buff, &bufsize) >= 0)
979 tls_peerdn = string_copy_malloc(buff);
983 /* Should we also verify the hostname here? */
985 if (verify_requirement != VERIFY_NONE &&
986 !verify_certificate(tls_session, &error))
988 log_write(0, LOG_MAIN,
989 "TLS error on connection to %s [%s]: certificate verification failed (%s)",
990 host->name, host->address, error);
994 construct_cipher_name(tls_session); /* Sets tls_cipher */
1001 /*************************************************
1002 * Deal with logging errors during I/O *
1003 *************************************************/
1005 /* We have to get the identity of the peer from saved data.
1008 ec the GnuTLS error code, or 0 if it's a local error
1009 when text identifying read or write
1010 text local error text when ec is 0
1016 record_io_error(int ec, uschar *when, uschar *text)
1018 uschar *additional = US"";
1020 if (ec == GNUTLS_E_FATAL_ALERT_RECEIVED)
1021 additional = string_sprintf(": %s",
1022 gnutls_alert_get_name(gnutls_alert_get(tls_session)));
1024 if (initialized == INITIALIZED_SERVER)
1025 log_write(0, LOG_MAIN, "TLS %s error on connection from %s: %s%s", when,
1026 (sender_fullhost != NULL)? sender_fullhost : US "local process",
1027 (ec == 0)? text : US gnutls_strerror(ec), additional);
1030 log_write(0, LOG_MAIN, "TLS %s error on connection to %s [%s]: %s%s", when,
1031 client_host->name, client_host->address,
1032 (ec == 0)? text : US gnutls_strerror(ec), additional);
1037 /*************************************************
1038 * TLS version of getc *
1039 *************************************************/
1041 /* This gets the next byte from the TLS input buffer. If the buffer is empty,
1042 it refills the buffer via the GnuTLS reading function.
1045 Returns: the next character or EOF
1051 if (ssl_xfer_buffer_lwm >= ssl_xfer_buffer_hwm)
1055 DEBUG(D_tls) debug_printf("Calling gnutls_record_recv(%lx, %lx, %u)\n",
1056 (long) tls_session, (long) ssl_xfer_buffer, ssl_xfer_buffer_size);
1058 if (smtp_receive_timeout > 0) alarm(smtp_receive_timeout);
1059 inbytes = gnutls_record_recv(tls_session, CS ssl_xfer_buffer,
1060 ssl_xfer_buffer_size);
1063 /* A zero-byte return appears to mean that the TLS session has been
1064 closed down, not that the socket itself has been closed down. Revert to
1065 non-TLS handling. */
1069 DEBUG(D_tls) debug_printf("Got TLS_EOF\n");
1071 receive_getc = smtp_getc;
1072 receive_ungetc = smtp_ungetc;
1073 receive_feof = smtp_feof;
1074 receive_ferror = smtp_ferror;
1076 gnutls_deinit(tls_session);
1085 /* Handle genuine errors */
1087 else if (inbytes < 0)
1089 record_io_error(inbytes, US"recv", NULL);
1094 ssl_xfer_buffer_hwm = inbytes;
1095 ssl_xfer_buffer_lwm = 0;
1099 /* Something in the buffer; return next uschar */
1101 return ssl_xfer_buffer[ssl_xfer_buffer_lwm++];
1106 /*************************************************
1107 * Read bytes from TLS channel *
1108 *************************************************/
1115 Returns: the number of bytes read
1116 -1 after a failed read
1120 tls_read(uschar *buff, size_t len)
1124 DEBUG(D_tls) debug_printf("Calling gnutls_record_recv(%lx, %lx, %u)\n",
1125 (long) tls_session, (long) buff, len);
1127 inbytes = gnutls_record_recv(tls_session, CS buff, len);
1128 if (inbytes > 0) return inbytes;
1131 DEBUG(D_tls) debug_printf("Got TLS_EOF\n");
1133 else record_io_error(inbytes, US"recv", NULL);
1140 /*************************************************
1141 * Write bytes down TLS channel *
1142 *************************************************/
1149 Returns: the number of bytes after a successful write,
1150 -1 after a failed write
1154 tls_write(const uschar *buff, size_t len)
1159 DEBUG(D_tls) debug_printf("tls_do_write(%lx, %d)\n", (long) buff, left);
1162 DEBUG(D_tls) debug_printf("gnutls_record_send(SSL, %lx, %d)\n", (long)buff,
1164 outbytes = gnutls_record_send(tls_session, CS buff, left);
1166 DEBUG(D_tls) debug_printf("outbytes=%d\n", outbytes);
1169 record_io_error(outbytes, US"send", NULL);
1174 record_io_error(0, US"send", US"TLS channel closed on write");
1187 /*************************************************
1188 * Close down a TLS session *
1189 *************************************************/
1191 /* This is also called from within a delivery subprocess forked from the
1192 daemon, to shut down the TLS library, without actually doing a shutdown (which
1193 would tamper with the TLS session in the parent process).
1195 Arguments: TRUE if gnutls_bye is to be called
1200 tls_close(BOOL shutdown)
1202 if (tls_active < 0) return; /* TLS was not active */
1206 DEBUG(D_tls) debug_printf("tls_close(): shutting down TLS\n");
1207 gnutls_bye(tls_session, GNUTLS_SHUT_WR);
1210 gnutls_deinit(tls_session);
1212 gnutls_global_deinit();
1217 /* End of tls-gnu.c */