-/* $Cambridge: exim/src/src/tls-openssl.c,v 1.25 2010/06/05 09:36:11 pdp Exp $ */
-
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
SSL_CTX_set_info_callback(ctx, (void (*)())info_callback);
+/* Automatically re-try reads/writes after renegotiation. */
+(void) SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
+
/* Apply administrator-supplied work-arounds.
Historically we applied just one requested option,
SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS, but when bug 994 requested a second, we
okay = tls_openssl_options_parse(openssl_options, &init_options);
if (!okay)
- return tls_error("openssl_options parsing failed", host, NULL);
+ return tls_error(US"openssl_options parsing failed", host, NULL);
if (init_options)
{
construct_cipher_name(SSL *ssl)
{
static uschar cipherbuf[256];
-SSL_CIPHER *c;
+/* With OpenSSL 1.0.0a, this needs to be const but the documentation doesn't
+yet reflect that. It should be a safe change anyway, even 0.9.8 versions have
+the accessor functions use const in the prototype. */
+const SSL_CIPHER *c;
uschar *ver;
-int bits;
switch (ssl->session->ssl_version)
{
ver = US"TLSv1";
break;
+#ifdef TLS1_1_VERSION
+ case TLS1_1_VERSION:
+ ver = US"TLSv1.1";
+ break;
+#endif
+
+#ifdef TLS1_2_VERSION
+ case TLS1_2_VERSION:
+ ver = US"TLSv1.2";
+ break;
+#endif
+
default:
ver = US"UNKNOWN";
}
-c = SSL_get_current_cipher(ssl);
-SSL_CIPHER_get_bits(c, &bits);
+c = (const SSL_CIPHER *) SSL_get_current_cipher(ssl);
+SSL_CIPHER_get_bits(c, &tls_bits);
string_format(cipherbuf, sizeof(cipherbuf), "%s:%s:%u", ver,
- SSL_CIPHER_get_name(c), bits);
+ SSL_CIPHER_get_name(c), tls_bits);
tls_cipher = cipherbuf;
DEBUG(D_tls) debug_printf("Cipher: %s\n", cipherbuf);
tls_error(US"SSL_accept", NULL, sigalrm_seen ? US"timed out" : NULL);
if (ERR_get_error() == 0)
log_write(0, LOG_MAIN,
- " => client disconnected cleanly (rejected our certificate?)\n");
+ "TLS client disconnected cleanly (rejected our certificate?)");
return FAIL;
}
DEBUG(D_tls) debug_printf("SSL_connect succeeded\n");
+/* Beware anonymous ciphers which lead to server_cert being NULL */
server_cert = SSL_get_peer_certificate (ssl);
-tls_peerdn = US X509_NAME_oneline(X509_get_subject_name(server_cert),
- CS txt, sizeof(txt));
-tls_peerdn = txt;
+if (server_cert)
+ {
+ tls_peerdn = US X509_NAME_oneline(X509_get_subject_name(server_cert),
+ CS txt, sizeof(txt));
+ tls_peerdn = txt;
+ }
+else
+ tls_peerdn = NULL;
construct_cipher_name(ssl); /* Sets tls_cipher */
int error;
int inbytes;
- DEBUG(D_tls) debug_printf("Calling SSL_read(%lx, %lx, %u)\n", (long)ssl,
- (long)ssl_xfer_buffer, ssl_xfer_buffer_size);
+ DEBUG(D_tls) debug_printf("Calling SSL_read(%p, %p, %u)\n", ssl,
+ ssl_xfer_buffer, ssl_xfer_buffer_size);
if (smtp_receive_timeout > 0) alarm(smtp_receive_timeout);
inbytes = SSL_read(ssl, CS ssl_xfer_buffer, ssl_xfer_buffer_size);
ssl_xfer_error = 1;
return EOF;
}
+
#ifndef DISABLE_DKIM
dkim_exim_verify_feed(ssl_xfer_buffer, inbytes);
#endif
int inbytes;
int error;
-DEBUG(D_tls) debug_printf("Calling SSL_read(%lx, %lx, %u)\n", (long)ssl,
- (long)buff, (unsigned int)len);
+DEBUG(D_tls) debug_printf("Calling SSL_read(%p, %p, %u)\n", ssl,
+ buff, (unsigned int)len);
inbytes = SSL_read(ssl, CS buff, len);
error = SSL_get_error(ssl, inbytes);
int error;
int left = len;
-DEBUG(D_tls) debug_printf("tls_do_write(%lx, %d)\n", (long)buff, left);
+DEBUG(D_tls) debug_printf("tls_do_write(%p, %d)\n", buff, left);
while (left > 0)
{
- DEBUG(D_tls) debug_printf("SSL_write(SSL, %lx, %d)\n", (long)buff, left);
+ DEBUG(D_tls) debug_printf("SSL_write(SSL, %p, %d)\n", buff, left);
outbytes = SSL_write(ssl, CS buff, left);
error = SSL_get_error(ssl, outbytes);
DEBUG(D_tls) debug_printf("outbytes=%d error=%d\n", outbytes, error);
void
tls_version_report(FILE *f)
{
-fprintf(f, "OpenSSL compile-time version: %s\n", OPENSSL_VERSION_TEXT);
-fprintf(f, "OpenSSL runtime version: %s\n", SSLeay_version(SSLEAY_VERSION));
+fprintf(f, "Library version: OpenSSL: Compile: %s\n"
+ " Runtime: %s\n",
+ OPENSSL_VERSION_TEXT,
+ SSLeay_version(SSLEAY_VERSION));
}
to apply.
This list is current as of:
- ==> 0.9.8n <== */
+ ==> 1.0.1b <== */
static struct exim_openssl_option exim_openssl_options[] = {
/* KEEP SORTED ALPHABETICALLY! */
#ifdef SSL_OP_ALL
- { "all", SSL_OP_ALL },
+ { US"all", SSL_OP_ALL },
#endif
#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
- { "allow_unsafe_legacy_renegotiation", SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION },
+ { US"allow_unsafe_legacy_renegotiation", SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION },
#endif
#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
- { "cipher_server_preference", SSL_OP_CIPHER_SERVER_PREFERENCE },
+ { US"cipher_server_preference", SSL_OP_CIPHER_SERVER_PREFERENCE },
#endif
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
- { "dont_insert_empty_fragments", SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS },
+ { US"dont_insert_empty_fragments", SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS },
#endif
#ifdef SSL_OP_EPHEMERAL_RSA
- { "ephemeral_rsa", SSL_OP_EPHEMERAL_RSA },
+ { US"ephemeral_rsa", SSL_OP_EPHEMERAL_RSA },
#endif
#ifdef SSL_OP_LEGACY_SERVER_CONNECT
- { "legacy_server_connect", SSL_OP_LEGACY_SERVER_CONNECT },
+ { US"legacy_server_connect", SSL_OP_LEGACY_SERVER_CONNECT },
#endif
#ifdef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
- { "microsoft_big_sslv3_buffer", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER },
+ { US"microsoft_big_sslv3_buffer", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER },
#endif
#ifdef SSL_OP_MICROSOFT_SESS_ID_BUG
- { "microsoft_sess_id_bug", SSL_OP_MICROSOFT_SESS_ID_BUG },
+ { US"microsoft_sess_id_bug", SSL_OP_MICROSOFT_SESS_ID_BUG },
#endif
#ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING
- { "msie_sslv2_rsa_padding", SSL_OP_MSIE_SSLV2_RSA_PADDING },
+ { US"msie_sslv2_rsa_padding", SSL_OP_MSIE_SSLV2_RSA_PADDING },
#endif
#ifdef SSL_OP_NETSCAPE_CHALLENGE_BUG
- { "netscape_challenge_bug", SSL_OP_NETSCAPE_CHALLENGE_BUG },
+ { US"netscape_challenge_bug", SSL_OP_NETSCAPE_CHALLENGE_BUG },
#endif
#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
- { "netscape_reuse_cipher_change_bug", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG },
+ { US"netscape_reuse_cipher_change_bug", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG },
+#endif
+#ifdef SSL_OP_NO_COMPRESSION
+ { US"no_compression", SSL_OP_NO_COMPRESSION },
#endif
#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
- { "no_session_resumption_on_renegotiation", SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION },
+ { US"no_session_resumption_on_renegotiation", SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION },
+#endif
+#ifdef SSL_OP_NO_SSLv2
+ { US"no_sslv2", SSL_OP_NO_SSLv2 },
+#endif
+#ifdef SSL_OP_NO_SSLv3
+ { US"no_sslv3", SSL_OP_NO_SSLv3 },
+#endif
+#ifdef SSL_OP_NO_TICKET
+ { US"no_ticket", SSL_OP_NO_TICKET },
+#endif
+#ifdef SSL_OP_NO_TLSv1
+ { US"no_tlsv1", SSL_OP_NO_TLSv1 },
+#endif
+#ifdef SSL_OP_NO_TLSv1_1
+#if SSL_OP_NO_TLSv1_1 == 0x00000400L
+ /* Error in chosen value in 1.0.1a; see first item in CHANGES for 1.0.1b */
+#warning OpenSSL 1.0.1a uses a bad value for SSL_OP_NO_TLSv1_1, ignoring
+#else
+ { US"no_tlsv1_1", SSL_OP_NO_TLSv1_1 },
+#endif
+#endif
+#ifdef SSL_OP_NO_TLSv1_2
+ { US"no_tlsv1_2", SSL_OP_NO_TLSv1_2 },
#endif
#ifdef SSL_OP_SINGLE_DH_USE
- { "single_dh_use", SSL_OP_SINGLE_DH_USE },
+ { US"single_dh_use", SSL_OP_SINGLE_DH_USE },
#endif
#ifdef SSL_OP_SINGLE_ECDH_USE
- { "single_ecdh_use", SSL_OP_SINGLE_ECDH_USE },
+ { US"single_ecdh_use", SSL_OP_SINGLE_ECDH_USE },
#endif
#ifdef SSL_OP_SSLEAY_080_CLIENT_DH_BUG
- { "ssleay_080_client_dh_bug", SSL_OP_SSLEAY_080_CLIENT_DH_BUG },
+ { US"ssleay_080_client_dh_bug", SSL_OP_SSLEAY_080_CLIENT_DH_BUG },
#endif
#ifdef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
- { "sslref2_reuse_cert_type_bug", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG },
+ { US"sslref2_reuse_cert_type_bug", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG },
#endif
#ifdef SSL_OP_TLS_BLOCK_PADDING_BUG
- { "tls_block_padding_bug", SSL_OP_TLS_BLOCK_PADDING_BUG },
+ { US"tls_block_padding_bug", SSL_OP_TLS_BLOCK_PADDING_BUG },
#endif
#ifdef SSL_OP_TLS_D5_BUG
- { "tls_d5_bug", SSL_OP_TLS_D5_BUG },
+ { US"tls_d5_bug", SSL_OP_TLS_D5_BUG },
#endif
#ifdef SSL_OP_TLS_ROLLBACK_BUG
- { "tls_rollback_bug", SSL_OP_TLS_ROLLBACK_BUG },
+ { US"tls_rollback_bug", SSL_OP_TLS_ROLLBACK_BUG },
#endif
};
static int exim_openssl_options_size =
sizeof(exim_openssl_options)/sizeof(struct exim_openssl_option);
+
static BOOL
tls_openssl_one_option_parse(uschar *name, long *value)
{
uschar keep_c;
BOOL adding, item_parsed;
+result = 0L;
/* We grandfather in as default the one option which we used to set always. */
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
-result = SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
-#else
-result = 0L;
+result |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
#endif
if (option_spec == NULL)
if (*s != '+' && *s != '-')
{
DEBUG(D_tls) debug_printf("malformed openssl option setting: "
- "+ or - expected but found \"%s\"", s);
+ "+ or - expected but found \"%s\"\n", s);
return FALSE;
}
adding = *s++ == '+';
item_parsed = tls_openssl_one_option_parse(s, &item);
if (!item_parsed)
{
- DEBUG(D_tls) debug_printf("openssl option setting unrecognised: \"%s\"", s);
+ DEBUG(D_tls) debug_printf("openssl option setting unrecognised: \"%s\"\n", s);
return FALSE;
}
DEBUG(D_tls) debug_printf("openssl option, %s from %lx: %lx (%s)\n",