More documentation updates.
[exim.git] / src / src / tls-openssl.c
CommitLineData
58c01c94 1/* $Cambridge: exim/src/src/tls-openssl.c,v 1.11 2007/03/13 09:50:22 ph10 Exp $ */
059ec3d9
PH
2
3/*************************************************
4* Exim - an Internet mail transport agent *
5*************************************************/
6
184e8823 7/* Copyright (c) University of Cambridge 1995 - 2007 */
059ec3d9
PH
8/* See the file NOTICE for conditions of use and distribution. */
9
10/* This module provides the TLS (aka SSL) support for Exim using the OpenSSL
11library. It is #included into the tls.c file when that library is used. The
12code herein is based on a patch that was originally contributed by Steve
13Haslam. It was adapted from stunnel, a GPL program by Michal Trojnara.
14
15No cryptographic code is included in Exim. All this module does is to call
16functions from the OpenSSL library. */
17
18
19/* Heading stuff */
20
21#include <openssl/lhash.h>
22#include <openssl/ssl.h>
23#include <openssl/err.h>
24#include <openssl/rand.h>
25
26/* Structure for collecting random data for seeding. */
27
28typedef struct randstuff {
29 time_t t;
30 pid_t p;
31} randstuff;
32
33/* Local static variables */
34
35static BOOL verify_callback_called = FALSE;
36static const uschar *sid_ctx = US"exim";
37
38static SSL_CTX *ctx = NULL;
39static SSL *ssl = NULL;
40
41static char ssl_errstring[256];
42
43static int ssl_session_timeout = 200;
44static BOOL verify_optional = FALSE;
45
46
47
48
49
50/*************************************************
51* Handle TLS error *
52*************************************************/
53
54/* Called from lots of places when errors occur before actually starting to do
55the TLS handshake, that is, while the session is still in clear. Always returns
56DEFER for a server and FAIL for a client so that most calls can use "return
57tls_error(...)" to do this processing and then give an appropriate return. A
58single function is used for both server and client, because it is called from
59some shared functions.
60
61Argument:
62 prefix text to include in the logged error
63 host NULL if setting up a server;
64 the connected host if setting up a client
65
66Returns: OK/DEFER/FAIL
67*/
68
69static int
70tls_error(uschar *prefix, host_item *host)
71{
72ERR_error_string(ERR_get_error(), ssl_errstring);
73if (host == NULL)
74 {
75 log_write(0, LOG_MAIN, "TLS error on connection from %s (%s): %s",
76 (sender_fullhost != NULL)? sender_fullhost : US"local process",
77 prefix, ssl_errstring);
78 return DEFER;
79 }
80else
81 {
82 log_write(0, LOG_MAIN, "TLS error on connection to %s [%s] (%s): %s",
83 host->name, host->address, prefix, ssl_errstring);
84 return FAIL;
85 }
86}
87
88
89
90/*************************************************
91* Callback to generate RSA key *
92*************************************************/
93
94/*
95Arguments:
96 s SSL connection
97 export not used
98 keylength keylength
99
100Returns: pointer to generated key
101*/
102
103static RSA *
104rsa_callback(SSL *s, int export, int keylength)
105{
106RSA *rsa_key;
107export = export; /* Shut picky compilers up */
108DEBUG(D_tls) debug_printf("Generating %d bit RSA key...\n", keylength);
109rsa_key = RSA_generate_key(keylength, RSA_F4, NULL, NULL);
110if (rsa_key == NULL)
111 {
112 ERR_error_string(ERR_get_error(), ssl_errstring);
113 log_write(0, LOG_MAIN|LOG_PANIC, "TLS error (RSA_generate_key): %s",
114 ssl_errstring);
115 return NULL;
116 }
117return rsa_key;
118}
119
120
121
122
123/*************************************************
124* Callback for verification *
125*************************************************/
126
127/* The SSL library does certificate verification if set up to do so. This
128callback has the current yes/no state is in "state". If verification succeeded,
129we set up the tls_peerdn string. If verification failed, what happens depends
130on whether the client is required to present a verifiable certificate or not.
131
132If verification is optional, we change the state to yes, but still log the
133verification error. For some reason (it really would help to have proper
134documentation of OpenSSL), this callback function then gets called again, this
135time with state = 1. In fact, that's useful, because we can set up the peerdn
136value, but we must take care not to set the private verified flag on the second
137time through.
138
139Note: this function is not called if the client fails to present a certificate
140when asked. We get here only if a certificate has been received. Handling of
141optional verification for this case is done when requesting SSL to verify, by
142setting SSL_VERIFY_FAIL_IF_NO_PEER_CERT in the non-optional case.
143
144Arguments:
145 state current yes/no state as 1/0
146 x509ctx certificate information.
147
148Returns: 1 if verified, 0 if not
149*/
150
151static int
152verify_callback(int state, X509_STORE_CTX *x509ctx)
153{
154static uschar txt[256];
155
156X509_NAME_oneline(X509_get_subject_name(x509ctx->current_cert),
157 CS txt, sizeof(txt));
158
159if (state == 0)
160 {
161 log_write(0, LOG_MAIN, "SSL verify error: depth=%d error=%s cert=%s",
162 x509ctx->error_depth,
163 X509_verify_cert_error_string(x509ctx->error),
164 txt);
165 tls_certificate_verified = FALSE;
166 verify_callback_called = TRUE;
167 if (!verify_optional) return 0; /* reject */
168 DEBUG(D_tls) debug_printf("SSL verify failure overridden (host in "
169 "tls_try_verify_hosts)\n");
170 return 1; /* accept */
171 }
172
173if (x509ctx->error_depth != 0)
174 {
175 DEBUG(D_tls) debug_printf("SSL verify ok: depth=%d cert=%s\n",
176 x509ctx->error_depth, txt);
177 }
178else
179 {
180 DEBUG(D_tls) debug_printf("SSL%s peer: %s\n",
181 verify_callback_called? "" : " authenticated", txt);
182 tls_peerdn = txt;
183 }
184
059ec3d9
PH
185if (!verify_callback_called) tls_certificate_verified = TRUE;
186verify_callback_called = TRUE;
187
188return 1; /* accept */
189}
190
191
192
193/*************************************************
194* Information callback *
195*************************************************/
196
197/* The SSL library functions call this from time to time to indicate what they
198are doing. We copy the string to the debugging output when the level is high
199enough.
200
201Arguments:
202 s the SSL connection
203 where
204 ret
205
206Returns: nothing
207*/
208
209static void
210info_callback(SSL *s, int where, int ret)
211{
212where = where;
213ret = ret;
214DEBUG(D_tls) debug_printf("SSL info: %s\n", SSL_state_string_long(s));
215}
216
217
218
219/*************************************************
220* Initialize for DH *
221*************************************************/
222
223/* If dhparam is set, expand it, and load up the parameters for DH encryption.
224
225Arguments:
226 dhparam DH parameter file
227
228Returns: TRUE if OK (nothing to set up, or setup worked)
229*/
230
231static BOOL
232init_dh(uschar *dhparam)
233{
234BOOL yield = TRUE;
235BIO *bio;
236DH *dh;
237uschar *dhexpanded;
238
239if (!expand_check(dhparam, US"tls_dhparam", &dhexpanded))
240 return FALSE;
241
242if (dhexpanded == NULL) return TRUE;
243
244if ((bio = BIO_new_file(CS dhexpanded, "r")) == NULL)
245 {
246 log_write(0, LOG_MAIN, "DH: could not read %s: %s", dhexpanded,
247 strerror(errno));
248 yield = FALSE;
249 }
250else
251 {
252 if ((dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL)) == NULL)
253 {
254 log_write(0, LOG_MAIN, "DH: could not load params from %s",
255 dhexpanded);
256 yield = FALSE;
257 }
258 else
259 {
260 SSL_CTX_set_tmp_dh(ctx, dh);
261 DEBUG(D_tls)
262 debug_printf("Diffie-Hellman initialized from %s with %d-bit key\n",
263 dhexpanded, 8*DH_size(dh));
264 DH_free(dh);
265 }
266 BIO_free(bio);
267 }
268
269return yield;
270}
271
272
273
274
275/*************************************************
276* Initialize for TLS *
277*************************************************/
278
279/* Called from both server and client code, to do preliminary initialization of
280the library.
281
282Arguments:
283 host connected host, if client; NULL if server
284 dhparam DH parameter file
285 certificate certificate file
286 privatekey private key
287 addr address if client; NULL if server (for some randomness)
288
289Returns: OK/DEFER/FAIL
290*/
291
292static int
c91535f3
PH
293tls_init(host_item *host, uschar *dhparam, uschar *certificate,
294 uschar *privatekey, address_item *addr)
059ec3d9
PH
295{
296SSL_load_error_strings(); /* basic set up */
297OpenSSL_add_ssl_algorithms();
298
299/* Create a context */
300
301ctx = SSL_CTX_new((host == NULL)?
302 SSLv23_server_method() : SSLv23_client_method());
303
304if (ctx == NULL) return tls_error(US"SSL_CTX_new", host);
305
306/* It turns out that we need to seed the random number generator this early in
307order to get the full complement of ciphers to work. It took me roughly a day
308of work to discover this by experiment.
309
310On systems that have /dev/urandom, SSL may automatically seed itself from
311there. Otherwise, we have to make something up as best we can. Double check
312afterwards. */
313
314if (!RAND_status())
315 {
316 randstuff r;
317 r.t = time(NULL);
318 r.p = getpid();
319
320 RAND_seed((uschar *)(&r), sizeof(r));
321 RAND_seed((uschar *)big_buffer, big_buffer_size);
322 if (addr != NULL) RAND_seed((uschar *)addr, sizeof(addr));
323
324 if (!RAND_status())
325 {
326 if (host == NULL)
327 {
328 log_write(0, LOG_MAIN, "TLS error on connection from %s: "
329 "unable to seed random number generator",
330 (sender_fullhost != NULL)? sender_fullhost : US"local process");
331 return DEFER;
332 }
333 else
334 {
335 log_write(0, LOG_MAIN, "TLS error on connection to %s [%s]: "
336 "unable to seed random number generator",
337 host->name, host->address);
338 return FAIL;
339 }
340 }
341 }
342
343/* Set up the information callback, which outputs if debugging is at a suitable
344level. */
345
58c01c94 346SSL_CTX_set_info_callback(ctx, (void (*)())info_callback);
059ec3d9
PH
347
348/* The following patch was supplied by Robert Roselius */
349
350#if OPENSSL_VERSION_NUMBER > 0x00906040L
351/* Enable client-bug workaround.
352 Versions of OpenSSL as of 0.9.6d include a "CBC countermeasure" feature,
353 which causes problems with some clients (such as the Certicom SSL Plus
354 library used by Eudora). This option, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS,
355 disables the coutermeasure allowing Eudora to connect.
356 Some poppers and MTAs use SSL_OP_ALL, which enables all such bug
357 workarounds. */
358/* XXX (Silently?) ignore failure here? XXX*/
359
360if (!(SSL_CTX_set_options(ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)))
361 return tls_error(US"SSL_CTX_set_option", host);
362#endif
363
364/* Initialize with DH parameters if supplied */
365
366if (!init_dh(dhparam)) return DEFER;
367
368/* Set up certificate and key */
369
370if (certificate != NULL)
371 {
372 uschar *expanded;
373 if (!expand_check(certificate, US"tls_certificate", &expanded))
374 return DEFER;
375
376 if (expanded != NULL)
377 {
378 DEBUG(D_tls) debug_printf("tls_certificate file %s\n", expanded);
379 if (!SSL_CTX_use_certificate_chain_file(ctx, CS expanded))
d6453af2
PH
380 return tls_error(string_sprintf(
381 "SSL_CTX_use_certificate_chain_file file=%s", expanded), host);
059ec3d9
PH
382 }
383
384 if (privatekey != NULL &&
385 !expand_check(privatekey, US"tls_privatekey", &expanded))
386 return DEFER;
387
c91535f3
PH
388 /* If expansion was forced to fail, key_expanded will be NULL. If the result
389 of the expansion is an empty string, ignore it also, and assume the private
390 key is in the same file as the certificate. */
391
392 if (expanded != NULL && *expanded != 0)
059ec3d9
PH
393 {
394 DEBUG(D_tls) debug_printf("tls_privatekey file %s\n", expanded);
395 if (!SSL_CTX_use_PrivateKey_file(ctx, CS expanded, SSL_FILETYPE_PEM))
d6453af2
PH
396 return tls_error(string_sprintf(
397 "SSL_CTX_use_PrivateKey_file file=%s", expanded), host);
059ec3d9
PH
398 }
399 }
400
401/* Set up the RSA callback */
402
403SSL_CTX_set_tmp_rsa_callback(ctx, rsa_callback);
404
405/* Finally, set the timeout, and we are done */
406
407SSL_CTX_set_timeout(ctx, ssl_session_timeout);
408DEBUG(D_tls) debug_printf("Initialized TLS\n");
409return OK;
410}
411
412
413
414
415/*************************************************
416* Get name of cipher in use *
417*************************************************/
418
419/* The answer is left in a static buffer, and tls_cipher is set to point
420to it.
421
422Argument: pointer to an SSL structure for the connection
423Returns: nothing
424*/
425
426static void
427construct_cipher_name(SSL *ssl)
428{
429static uschar cipherbuf[256];
430SSL_CIPHER *c;
431uschar *ver;
432int bits;
433
434switch (ssl->session->ssl_version)
435 {
436 case SSL2_VERSION:
437 ver = US"SSLv2";
438 break;
439
440 case SSL3_VERSION:
441 ver = US"SSLv3";
442 break;
443
444 case TLS1_VERSION:
445 ver = US"TLSv1";
446 break;
447
448 default:
449 ver = US"UNKNOWN";
450 }
451
452c = SSL_get_current_cipher(ssl);
453SSL_CIPHER_get_bits(c, &bits);
454
455string_format(cipherbuf, sizeof(cipherbuf), "%s:%s:%u", ver,
456 SSL_CIPHER_get_name(c), bits);
457tls_cipher = cipherbuf;
458
459DEBUG(D_tls) debug_printf("Cipher: %s\n", cipherbuf);
460}
461
462
463
464
465
466/*************************************************
467* Set up for verifying certificates *
468*************************************************/
469
470/* Called by both client and server startup
471
472Arguments:
473 certs certs file or NULL
474 crl CRL file or NULL
475 host NULL in a server; the remote host in a client
476 optional TRUE if called from a server for a host in tls_try_verify_hosts;
477 otherwise passed as FALSE
478
479Returns: OK/DEFER/FAIL
480*/
481
482static int
483setup_certs(uschar *certs, uschar *crl, host_item *host, BOOL optional)
484{
485uschar *expcerts, *expcrl;
486
487if (!expand_check(certs, US"tls_verify_certificates", &expcerts))
488 return DEFER;
489
490if (expcerts != NULL)
491 {
492 struct stat statbuf;
493 if (!SSL_CTX_set_default_verify_paths(ctx))
494 return tls_error(US"SSL_CTX_set_default_verify_paths", host);
495
496 if (Ustat(expcerts, &statbuf) < 0)
497 {
498 log_write(0, LOG_MAIN|LOG_PANIC,
499 "failed to stat %s for certificates", expcerts);
500 return DEFER;
501 }
502 else
503 {
504 uschar *file, *dir;
505 if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
506 { file = NULL; dir = expcerts; }
507 else
508 { file = expcerts; dir = NULL; }
509
510 /* If a certificate file is empty, the next function fails with an
511 unhelpful error message. If we skip it, we get the correct behaviour (no
512 certificates are recognized, but the error message is still misleading (it
513 says no certificate was supplied.) But this is better. */
514
515 if ((file == NULL || statbuf.st_size > 0) &&
516 !SSL_CTX_load_verify_locations(ctx, CS file, CS dir))
517 return tls_error(US"SSL_CTX_load_verify_locations", host);
518
519 if (file != NULL)
520 {
521 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(CS file));
522 }
523 }
524
525 /* Handle a certificate revocation list. */
526
527 #if OPENSSL_VERSION_NUMBER > 0x00907000L
528
8b417f2c
PH
529 /* This bit of code is now the version supplied by Lars Mainka. (I have
530 * merely reformatted it into the Exim code style.)
531
532 * "From here I changed the code to add support for multiple crl's
533 * in pem format in one file or to support hashed directory entries in
534 * pem format instead of a file. This method now uses the library function
535 * X509_STORE_load_locations to add the CRL location to the SSL context.
536 * OpenSSL will then handle the verify against CA certs and CRLs by
537 * itself in the verify callback." */
538
059ec3d9
PH
539 if (!expand_check(crl, US"tls_crl", &expcrl)) return DEFER;
540 if (expcrl != NULL && *expcrl != 0)
541 {
8b417f2c
PH
542 struct stat statbufcrl;
543 if (Ustat(expcrl, &statbufcrl) < 0)
544 {
545 log_write(0, LOG_MAIN|LOG_PANIC,
546 "failed to stat %s for certificates revocation lists", expcrl);
547 return DEFER;
548 }
549 else
059ec3d9 550 {
8b417f2c
PH
551 /* is it a file or directory? */
552 uschar *file, *dir;
553 X509_STORE *cvstore = SSL_CTX_get_cert_store(ctx);
554 if ((statbufcrl.st_mode & S_IFMT) == S_IFDIR)
059ec3d9 555 {
8b417f2c
PH
556 file = NULL;
557 dir = expcrl;
558 DEBUG(D_tls) debug_printf("SSL CRL value is a directory %s\n", dir);
059ec3d9
PH
559 }
560 else
561 {
8b417f2c
PH
562 file = expcrl;
563 dir = NULL;
564 DEBUG(D_tls) debug_printf("SSL CRL value is a file %s\n", file);
059ec3d9 565 }
8b417f2c
PH
566 if (X509_STORE_load_locations(cvstore, CS file, CS dir) == 0)
567 return tls_error(US"X509_STORE_load_locations", host);
568
569 /* setting the flags to check against the complete crl chain */
570
571 X509_STORE_set_flags(cvstore,
572 X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
059ec3d9 573 }
059ec3d9
PH
574 }
575
576 #endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */
577
578 /* If verification is optional, don't fail if no certificate */
579
580 SSL_CTX_set_verify(ctx,
581 SSL_VERIFY_PEER | (optional? 0 : SSL_VERIFY_FAIL_IF_NO_PEER_CERT),
582 verify_callback);
583 }
584
585return OK;
586}
587
588
589
590/*************************************************
591* Start a TLS session in a server *
592*************************************************/
593
594/* This is called when Exim is running as a server, after having received
595the STARTTLS command. It must respond to that command, and then negotiate
596a TLS session.
597
598Arguments:
599 require_ciphers allowed ciphers
83da1223
PH
600 ------------------------------------------------------
601 require_mac list of allowed MACs ) Not used
602 require_kx list of allowed key_exchange methods ) for
603 require_proto list of allowed protocols ) OpenSSL
604 ------------------------------------------------------
059ec3d9
PH
605
606Returns: OK on success
607 DEFER for errors before the start of the negotiation
608 FAIL for errors during the negotation; the server can't
609 continue running.
610*/
611
612int
83da1223
PH
613tls_server_start(uschar *require_ciphers, uschar *require_mac,
614 uschar *require_kx, uschar *require_proto)
059ec3d9
PH
615{
616int rc;
617uschar *expciphers;
618
619/* Check for previous activation */
620
621if (tls_active >= 0)
622 {
623 log_write(0, LOG_MAIN, "STARTTLS received in already encrypted "
624 "connection from %s",
625 (sender_fullhost != NULL)? sender_fullhost : US"local process");
626 smtp_printf("554 Already in TLS\r\n");
627 return FAIL;
628 }
629
630/* Initialize the SSL library. If it fails, it will already have logged
631the error. */
632
633rc = tls_init(NULL, tls_dhparam, tls_certificate, tls_privatekey, NULL);
634if (rc != OK) return rc;
635
636if (!expand_check(require_ciphers, US"tls_require_ciphers", &expciphers))
637 return FAIL;
638
639/* In OpenSSL, cipher components are separated by hyphens. In GnuTLS, they
640are separated by underscores. So that I can use either form in my tests, and
641also for general convenience, we turn underscores into hyphens here. */
642
643if (expciphers != NULL)
644 {
645 uschar *s = expciphers;
646 while (*s != 0) { if (*s == '_') *s = '-'; s++; }
647 DEBUG(D_tls) debug_printf("required ciphers: %s\n", expciphers);
648 if (!SSL_CTX_set_cipher_list(ctx, CS expciphers))
649 return tls_error(US"SSL_CTX_set_cipher_list", NULL);
650 }
651
652/* If this is a host for which certificate verification is mandatory or
653optional, set up appropriately. */
654
655tls_certificate_verified = FALSE;
656verify_callback_called = FALSE;
657
658if (verify_check_host(&tls_verify_hosts) == OK)
659 {
660 rc = setup_certs(tls_verify_certificates, tls_crl, NULL, FALSE);
661 if (rc != OK) return rc;
662 verify_optional = FALSE;
663 }
664else if (verify_check_host(&tls_try_verify_hosts) == OK)
665 {
666 rc = setup_certs(tls_verify_certificates, tls_crl, NULL, TRUE);
667 if (rc != OK) return rc;
668 verify_optional = TRUE;
669 }
670
671/* Prepare for new connection */
672
673if ((ssl = SSL_new(ctx)) == NULL) return tls_error(US"SSL_new", NULL);
674SSL_clear(ssl);
675
676/* Set context and tell client to go ahead, except in the case of TLS startup
677on connection, where outputting anything now upsets the clients and tends to
678make them disconnect. We need to have an explicit fflush() here, to force out
679the response. Other smtp_printf() calls do not need it, because in non-TLS
680mode, the fflush() happens when smtp_getc() is called. */
681
682SSL_set_session_id_context(ssl, sid_ctx, Ustrlen(sid_ctx));
683if (!tls_on_connect)
684 {
685 smtp_printf("220 TLS go ahead\r\n");
686 fflush(smtp_out);
687 }
688
689/* Now negotiate the TLS session. We put our own timer on it, since it seems
690that the OpenSSL library doesn't. */
691
56f5d9bd
PH
692SSL_set_wfd(ssl, fileno(smtp_out));
693SSL_set_rfd(ssl, fileno(smtp_in));
059ec3d9
PH
694SSL_set_accept_state(ssl);
695
696DEBUG(D_tls) debug_printf("Calling SSL_accept\n");
697
698sigalrm_seen = FALSE;
699if (smtp_receive_timeout > 0) alarm(smtp_receive_timeout);
700rc = SSL_accept(ssl);
701alarm(0);
702
703if (rc <= 0)
704 {
705 if (sigalrm_seen) Ustrcpy(ssl_errstring, "timed out");
706 else ERR_error_string(ERR_get_error(), ssl_errstring);
707 log_write(0, LOG_MAIN, "TLS error on connection from %s (SSL_accept): %s",
708 (sender_fullhost != NULL)? sender_fullhost : US"local process",
709 ssl_errstring);
710 return FAIL;
711 }
712
713DEBUG(D_tls) debug_printf("SSL_accept was successful\n");
714
715/* TLS has been set up. Adjust the input functions to read via TLS,
716and initialize things. */
717
718construct_cipher_name(ssl);
719
720DEBUG(D_tls)
721 {
722 uschar buf[2048];
723 if (SSL_get_shared_ciphers(ssl, CS buf, sizeof(buf)) != NULL)
724 debug_printf("Shared ciphers: %s\n", buf);
725 }
726
727
728ssl_xfer_buffer = store_malloc(ssl_xfer_buffer_size);
729ssl_xfer_buffer_lwm = ssl_xfer_buffer_hwm = 0;
730ssl_xfer_eof = ssl_xfer_error = 0;
731
732receive_getc = tls_getc;
733receive_ungetc = tls_ungetc;
734receive_feof = tls_feof;
735receive_ferror = tls_ferror;
736
737tls_active = fileno(smtp_out);
738return OK;
739}
740
741
742
743
744
745/*************************************************
746* Start a TLS session in a client *
747*************************************************/
748
749/* Called from the smtp transport after STARTTLS has been accepted.
750
751Argument:
752 fd the fd of the connection
753 host connected host (for messages)
83da1223 754 addr the first address
059ec3d9
PH
755 dhparam DH parameter file
756 certificate certificate file
757 privatekey private key file
758 verify_certs file for certificate verify
759 crl file containing CRL
760 require_ciphers list of allowed ciphers
83da1223
PH
761 ------------------------------------------------------
762 require_mac list of allowed MACs ) Not used
763 require_kx list of allowed key_exchange methods ) for
764 require_proto list of allowed protocols ) OpenSSL
765 ------------------------------------------------------
766 timeout startup timeout
059ec3d9
PH
767
768Returns: OK on success
769 FAIL otherwise - note that tls_error() will not give DEFER
770 because this is not a server
771*/
772
773int
774tls_client_start(int fd, host_item *host, address_item *addr, uschar *dhparam,
775 uschar *certificate, uschar *privatekey, uschar *verify_certs, uschar *crl,
83da1223
PH
776 uschar *require_ciphers, uschar *require_mac, uschar *require_kx,
777 uschar *require_proto, int timeout)
059ec3d9
PH
778{
779static uschar txt[256];
780uschar *expciphers;
781X509* server_cert;
782int rc;
783
784rc = tls_init(host, dhparam, certificate, privatekey, addr);
785if (rc != OK) return rc;
786
787tls_certificate_verified = FALSE;
788verify_callback_called = FALSE;
789
790if (!expand_check(require_ciphers, US"tls_require_ciphers", &expciphers))
791 return FAIL;
792
793/* In OpenSSL, cipher components are separated by hyphens. In GnuTLS, they
794are separated by underscores. So that I can use either form in my tests, and
795also for general convenience, we turn underscores into hyphens here. */
796
797if (expciphers != NULL)
798 {
799 uschar *s = expciphers;
800 while (*s != 0) { if (*s == '_') *s = '-'; s++; }
801 DEBUG(D_tls) debug_printf("required ciphers: %s\n", expciphers);
802 if (!SSL_CTX_set_cipher_list(ctx, CS expciphers))
803 return tls_error(US"SSL_CTX_set_cipher_list", host);
804 }
805
806rc = setup_certs(verify_certs, crl, host, FALSE);
807if (rc != OK) return rc;
808
809if ((ssl = SSL_new(ctx)) == NULL) return tls_error(US"SSL_new", host);
810SSL_set_session_id_context(ssl, sid_ctx, Ustrlen(sid_ctx));
811SSL_set_fd(ssl, fd);
812SSL_set_connect_state(ssl);
813
814/* There doesn't seem to be a built-in timeout on connection. */
815
816DEBUG(D_tls) debug_printf("Calling SSL_connect\n");
817sigalrm_seen = FALSE;
818alarm(timeout);
819rc = SSL_connect(ssl);
820alarm(0);
821
822if (rc <= 0)
823 {
824 if (sigalrm_seen)
825 {
826 log_write(0, LOG_MAIN, "TLS error on connection to %s [%s]: "
827 "SSL_connect timed out", host->name, host->address);
828 return FAIL;
829 }
830 else return tls_error(US"SSL_connect", host);
831 }
832
833DEBUG(D_tls) debug_printf("SSL_connect succeeded\n");
834
835server_cert = SSL_get_peer_certificate (ssl);
836tls_peerdn = US X509_NAME_oneline(X509_get_subject_name(server_cert),
837 CS txt, sizeof(txt));
838tls_peerdn = txt;
839
840construct_cipher_name(ssl); /* Sets tls_cipher */
841
842tls_active = fd;
843return OK;
844}
845
846
847
848
849
850/*************************************************
851* TLS version of getc *
852*************************************************/
853
854/* This gets the next byte from the TLS input buffer. If the buffer is empty,
855it refills the buffer via the SSL reading function.
856
857Arguments: none
858Returns: the next character or EOF
859*/
860
861int
862tls_getc(void)
863{
864if (ssl_xfer_buffer_lwm >= ssl_xfer_buffer_hwm)
865 {
866 int error;
867 int inbytes;
868
869 DEBUG(D_tls) debug_printf("Calling SSL_read(%lx, %lx, %u)\n", (long)ssl,
870 (long)ssl_xfer_buffer, ssl_xfer_buffer_size);
871
872 if (smtp_receive_timeout > 0) alarm(smtp_receive_timeout);
873 inbytes = SSL_read(ssl, CS ssl_xfer_buffer, ssl_xfer_buffer_size);
874 error = SSL_get_error(ssl, inbytes);
875 alarm(0);
876
877 /* SSL_ERROR_ZERO_RETURN appears to mean that the SSL session has been
878 closed down, not that the socket itself has been closed down. Revert to
879 non-SSL handling. */
880
881 if (error == SSL_ERROR_ZERO_RETURN)
882 {
883 DEBUG(D_tls) debug_printf("Got SSL_ERROR_ZERO_RETURN\n");
884
885 receive_getc = smtp_getc;
886 receive_ungetc = smtp_ungetc;
887 receive_feof = smtp_feof;
888 receive_ferror = smtp_ferror;
889
890 SSL_free(ssl);
891 ssl = NULL;
892 tls_active = -1;
893 tls_cipher = NULL;
894 tls_peerdn = NULL;
895
896 return smtp_getc();
897 }
898
899 /* Handle genuine errors */
900
901 else if (error != SSL_ERROR_NONE)
902 {
903 DEBUG(D_tls) debug_printf("Got SSL error %d\n", error);
904 ssl_xfer_error = 1;
905 return EOF;
906 }
907
908 ssl_xfer_buffer_hwm = inbytes;
909 ssl_xfer_buffer_lwm = 0;
910 }
911
912/* Something in the buffer; return next uschar */
913
914return ssl_xfer_buffer[ssl_xfer_buffer_lwm++];
915}
916
917
918
919/*************************************************
920* Read bytes from TLS channel *
921*************************************************/
922
923/*
924Arguments:
925 buff buffer of data
926 len size of buffer
927
928Returns: the number of bytes read
929 -1 after a failed read
930*/
931
932int
933tls_read(uschar *buff, size_t len)
934{
935int inbytes;
936int error;
937
938DEBUG(D_tls) debug_printf("Calling SSL_read(%lx, %lx, %u)\n", (long)ssl,
939 (long)buff, (unsigned int)len);
940
941inbytes = SSL_read(ssl, CS buff, len);
942error = SSL_get_error(ssl, inbytes);
943
944if (error == SSL_ERROR_ZERO_RETURN)
945 {
946 DEBUG(D_tls) debug_printf("Got SSL_ERROR_ZERO_RETURN\n");
947 return -1;
948 }
949else if (error != SSL_ERROR_NONE)
950 {
951 return -1;
952 }
953
954return inbytes;
955}
956
957
958
959
960
961/*************************************************
962* Write bytes down TLS channel *
963*************************************************/
964
965/*
966Arguments:
967 buff buffer of data
968 len number of bytes
969
970Returns: the number of bytes after a successful write,
971 -1 after a failed write
972*/
973
974int
975tls_write(const uschar *buff, size_t len)
976{
977int outbytes;
978int error;
979int left = len;
980
981DEBUG(D_tls) debug_printf("tls_do_write(%lx, %d)\n", (long)buff, left);
982while (left > 0)
983 {
984 DEBUG(D_tls) debug_printf("SSL_write(SSL, %lx, %d)\n", (long)buff, left);
985 outbytes = SSL_write(ssl, CS buff, left);
986 error = SSL_get_error(ssl, outbytes);
987 DEBUG(D_tls) debug_printf("outbytes=%d error=%d\n", outbytes, error);
988 switch (error)
989 {
990 case SSL_ERROR_SSL:
991 ERR_error_string(ERR_get_error(), ssl_errstring);
992 log_write(0, LOG_MAIN, "TLS error (SSL_write): %s", ssl_errstring);
993 return -1;
994
995 case SSL_ERROR_NONE:
996 left -= outbytes;
997 buff += outbytes;
998 break;
999
1000 case SSL_ERROR_ZERO_RETURN:
1001 log_write(0, LOG_MAIN, "SSL channel closed on write");
1002 return -1;
1003
1004 default:
1005 log_write(0, LOG_MAIN, "SSL_write error %d", error);
1006 return -1;
1007 }
1008 }
1009return len;
1010}
1011
1012
1013
1014/*************************************************
1015* Close down a TLS session *
1016*************************************************/
1017
1018/* This is also called from within a delivery subprocess forked from the
1019daemon, to shut down the TLS library, without actually doing a shutdown (which
1020would tamper with the SSL session in the parent process).
1021
1022Arguments: TRUE if SSL_shutdown is to be called
1023Returns: nothing
1024*/
1025
1026void
1027tls_close(BOOL shutdown)
1028{
1029if (tls_active < 0) return; /* TLS was not active */
1030
1031if (shutdown)
1032 {
1033 DEBUG(D_tls) debug_printf("tls_close(): shutting down SSL\n");
1034 SSL_shutdown(ssl);
1035 }
1036
1037SSL_free(ssl);
1038ssl = NULL;
1039
1040tls_active = -1;
1041}
1042
1043/* End of tls-openssl.c */