/************************************************* * Exim - an Internet mail transport agent * *************************************************/ /* Copyright (c) University of Cambridge 1995 - 2012 */ /* See the file NOTICE for conditions of use and distribution. */ /* This module provides TLS (aka SSL) support for Exim. The code for OpenSSL is based on a patch that was originally contributed by Steve Haslam. It was adapted from stunnel, a GPL program by Michal Trojnara. The code for GNU TLS is based on a patch contributed by Nikos Mavroyanopoulos. Because these packages are so very different, the functions for each are kept in separate files. The relevant file is #included as required, after any any common functions. No cryptographic code is included in Exim. All this module does is to call functions from the OpenSSL or GNU TLS libraries. */ #include "exim.h" /* This module is compiled only when it is specifically requested in the build-time configuration. However, some compilers don't like compiling empty modules, so keep them happy with a dummy when skipping the rest. Make it reference itself to stop picky compilers complaining that it is unused, and put in a dummy argument to stop even pickier compilers complaining about infinite loops. */ #ifndef SUPPORT_TLS static void dummy(int x) { dummy(x-1); } #else /* Static variables that are used for buffering data by both sets of functions and the common functions below. We're moving away from this; GnuTLS is already using a state, which can switch, so we can do TLS callouts during ACLs. */ static const int ssl_xfer_buffer_size = 4096; #ifndef USE_GNUTLS static uschar *ssl_xfer_buffer = NULL; static int ssl_xfer_buffer_lwm = 0; static int ssl_xfer_buffer_hwm = 0; static int ssl_xfer_eof = 0; static int ssl_xfer_error = 0; #endif uschar *tls_channelbinding_b64 = NULL; /************************************************* * Expand string; give error on failure * *************************************************/ /* If expansion is forced to fail, set the result NULL and return TRUE. Other failures return FALSE. For a server, an SMTP response is given. Arguments: s the string to expand; if NULL just return TRUE name name of string being expanded (for error) result where to put the result Returns: TRUE if OK; result may still be NULL after forced failure */ static BOOL expand_check(const uschar *s, const uschar *name, uschar **result) { if (s == NULL) *result = NULL; else { *result = expand_string(US s); /* need to clean up const some more */ if (*result == NULL && !expand_string_forcedfail) { log_write(0, LOG_MAIN|LOG_PANIC, "expansion of %s failed: %s", name, expand_string_message); return FALSE; } } return TRUE; } /************************************************* * Many functions are package-specific * *************************************************/ #ifdef USE_GNUTLS #include "tls-gnu.c" #define ssl_xfer_buffer (state_server.xfer_buffer) #define ssl_xfer_buffer_lwm (state_server.xfer_buffer_lwm) #define ssl_xfer_buffer_hwm (state_server.xfer_buffer_hwm) #define ssl_xfer_eof (state_server.xfer_eof) #define ssl_xfer_error (state_server.xfer_error) #else #include "tls-openssl.c" #endif /************************************************* * TLS version of ungetc * *************************************************/ /* Puts a character back in the input buffer. Only ever called once. Only used by the server-side TLS. Arguments: ch the character Returns: the character */ int tls_ungetc(int ch) { ssl_xfer_buffer[--ssl_xfer_buffer_lwm] = ch; return ch; } /************************************************* * TLS version of feof * *************************************************/ /* Tests for a previous EOF Only used by the server-side TLS. Arguments: none Returns: non-zero if the eof flag is set */ int tls_feof(void) { return ssl_xfer_eof; } /************************************************* * TLS version of ferror * *************************************************/ /* Tests for a previous read error, and returns with errno restored to what it was when the error was detected. Only used by the server-side TLS. >>>>> Hmm. Errno not handled yet. Where do we get it from? >>>>> Arguments: none Returns: non-zero if the error flag is set */ int tls_ferror(void) { return ssl_xfer_error; } /************************************************* * TLS version of smtp_buffered * *************************************************/ /* Tests for unused chars in the TLS input buffer. Only used by the server-side TLS. Arguments: none Returns: TRUE/FALSE */ BOOL tls_smtp_buffered(void) { return ssl_xfer_buffer_lwm < ssl_xfer_buffer_hwm; } #endif /* SUPPORT_TLS */ /* End of tls.c */