Permalink
Browse files

Fail early on TLS certificate loading errors. Fixes #447

* Swap incorrect 'ssl-privatekey/certificate not loaded' error messages
* Fail early on TLS certificate loading errors. Report unsupported STARTTLS to LOG_MISC.
* Add TLS alert strings to debug logs.
* Add exit state to tls debug logs.
* Fatal if exactly one of cert/key is set.
  • Loading branch information...
thommey authored and vanosg committed Nov 4, 2017
1 parent 5c7a6b6 commit 5dea00822b00cb52cf46ec479a6093f2517a1662
Showing with 51 additions and 39 deletions.
  1. +49 −37 src/tls.c
  2. +2 −2 src/version.h
View
@@ -36,7 +36,7 @@ extern int tls_vfydcc;
extern struct dcc_t *dcc;
int tls_maxdepth = 9; /* Max certificate chain verification depth */
int ssl_files_loaded = 1; /* Check for loaded SSL key/cert files */
int ssl_files_loaded = 0; /* Check for loaded SSL key/cert files */
SSL_CTX *ssl_ctx = NULL; /* SSL context object */
char *tls_randfile = NULL; /* Random seed file for SSL */
char tls_capath[121] = ""; /* Path to trusted CA certificates */
@@ -137,47 +137,46 @@ int ssl_init()
ERR_free_strings();
return -1;
}
if (!tls_certfile[0]) {
ssl_files_loaded = 0;
if (tls_keyfile[0])
putlog(LOG_MISC, "*", "ERROR: TLS: ssl-certificate not set, ignoring ssl-privatekey.");
} else if (!tls_keyfile[0]) {
ssl_files_loaded = 0;
putlog(LOG_MISC, "*", "ERROR: TLS: ssl-privatekey not set, ignoring ssl-certificate.");
} else {
ssl_files_loaded = 1;
ssl_files_loaded = 0;
if (tls_certfile[0] ^ tls_keyfile[0]) {
/* Both need to be set or unset */
putlog(LOG_MISC, "*", "ERROR: TLS: %s set but %s unset. Both must be set "
"to use a certificate, or unset both to disable.",
tls_certfile[0] ? "ssl-certificate" : "ssl-privatekey",
tls_certfile[0] ? "ssl-privatekey" : "ssl-certificate");
fatal("ssl-privatekey and ssl-certificate must both be set or unset.", 0);
}
if (tls_certfile[0] && tls_keyfile[0]) {
/* Load our own certificate and private key. Mandatory for acting as
server, because we don't support anonymous ciphers by default. */
if (SSL_CTX_use_certificate_chain_file(ssl_ctx, tls_certfile) != 1) {
putlog(LOG_MISC, "*", "ERROR: TLS: unable to load own certificate: %s",
ERR_error_string(ERR_get_error(), NULL));
putlog(LOG_MISC, "*", " Check ssl-certificate in config.");
ssl_files_loaded = 0;
putlog(LOG_MISC, "*", "ERROR: TLS: unable to load own certificate from %s: %s",
tls_certfile, ERR_error_string(ERR_get_error(), NULL));
fatal("Unable to load TLS certificate (ssl-certificate config setting)!", 0);
}
if (SSL_CTX_use_PrivateKey_file(ssl_ctx, tls_keyfile,
SSL_FILETYPE_PEM) != 1) {
putlog(LOG_MISC, "*", "ERROR: TLS: unable to load private key: %s",
ERR_error_string(ERR_get_error(), NULL));
putlog(LOG_MISC, "*", " Check ssl-privatekey in config.");
ssl_files_loaded = 0;
if (SSL_CTX_use_PrivateKey_file(ssl_ctx, tls_keyfile, SSL_FILETYPE_PEM) != 1) {
putlog(LOG_MISC, "*", "ERROR: TLS: unable to load private key from %s: %s",
tls_keyfile, ERR_error_string(ERR_get_error(), NULL));
fatal("Unable to load TLS private key (ssl-privatekey config setting)!", 0);
}
ssl_files_loaded = 1;
}
if ((tls_capath[0] || tls_cafile[0]) &&
!SSL_CTX_load_verify_locations(ssl_ctx, tls_cafile[0] ? tls_cafile : NULL,
tls_capath[0] ? tls_capath : NULL))
tls_capath[0] ? tls_capath : NULL)) {
putlog(LOG_MISC, "*", "ERROR: TLS: unable to set CA certificates location: %s",
ERR_error_string(ERR_get_error(), NULL));
ERR_free_strings();
}
/* Let advanced users specify the list of allowed ssl ciphers */
if (tls_ciphers[0])
if (!SSL_CTX_set_cipher_list(ssl_ctx, tls_ciphers)) {
/* this replaces any preset ciphers so an invalid list is fatal */
putlog(LOG_MISC, "*", "ERROR: TLS: no valid ciphers found. Disabling SSL.");
ERR_free_strings();
SSL_CTX_free(ssl_ctx);
ssl_ctx = NULL;
return -3;
}
if (tls_ciphers[0] && !SSL_CTX_set_cipher_list(ssl_ctx, tls_ciphers)) {
/* this replaces any preset ciphers so an invalid list is fatal */
putlog(LOG_MISC, "*", "ERROR: TLS: no valid ciphers found. Disabling SSL.");
ERR_free_strings();
SSL_CTX_free(ssl_ctx);
ssl_ctx = NULL;
return -3;
}
return 0;
}
@@ -211,7 +210,7 @@ char *ssl_fpconv(char *in, char *out)
OPENSSL_free(fp);
return out;
}
OPENSSL_free(md5);
OPENSSL_free(md5);
}
return NULL;
}
@@ -605,11 +604,12 @@ void ssl_info(SSL *ssl, int where, int ret)
const SSL_CIPHER *cipher;
int secret, processed;
if (!(data = (ssl_appdata *) SSL_get_app_data(ssl)))
return;
/* We're doing non-blocking IO, so we check here if the handshake has
finished */
if (where & SSL_CB_HANDSHAKE_DONE) {
if (!(data = (ssl_appdata *) SSL_get_app_data(ssl)))
return;
/* Callback for completed handshake. Cheaper and more convenient than
using H_tls */
sock = SSL_get_fd(ssl);
@@ -640,10 +640,18 @@ void ssl_info(SSL *ssl, int where, int ret)
/* More verbose information, for debugging only */
SSL_CIPHER_description(cipher, buf, sizeof buf);
debug1("TLS: cipher details: %s", buf);
} else if (where & SSL_CB_ALERT) {
putlog(data->loglevel, "*", "TLS: alert during %s: %s (%s).",
(where & SSL_CB_READ) ? "read" : "write",
SSL_alert_type_string_long(ret),
SSL_alert_desc_string_long(ret));
} else if (where & SSL_CB_EXIT) {
putlog(data->loglevel, "*", "TLS: failed in: %s.",
SSL_state_string_long(ssl));
} else {
/* Display the state of the engine for debugging purposes */
debug1("TLS: state change: %s", SSL_state_string_long(ssl));
}
/* Display the state of the engine for debugging purposes */
debug1("TLS: state change: %s", SSL_state_string_long(ssl));
}
/* Switch a socket to SSL communication
@@ -675,6 +683,10 @@ int ssl_handshake(int sock, int flags, int verify, int loglevel, char *host,
debug0("TLS: Failed. OpenSSL not initialized properly.");
return -1;
}
if ((flags & TLS_LISTEN) && !ssl_files_loaded) {
putlog(LOG_MISC, "*", "TLS: Failed. Certificate/Key not loaded, cannot support SSL/TLS for client (see doc/TLS).");
return -4;
}
/* find the socket in the list */
i = findsock(sock);
if (i == -1) {
View
@@ -27,5 +27,5 @@
*/
#define EGG_STRINGVER "1.8.2"
#define EGG_NUMVER 1080206
#define EGG_PATCH "rejectlink"
#define EGG_NUMVER 1080207
#define EGG_PATCH "sslfatal"

0 comments on commit 5dea008

Please sign in to comment.