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