Add ssl_cry() function to display error message plus any detailed error messages that OpenSSL might care to provide.

This can help to debug SSL communication issues.

Example output with a couple of problematic SSL client sessions (new log messages start with "-->" to indicate that they are providing additional detail to a previous log message):

Mongoose "2.9, $Rev: 517 $" started on port(s) "80,443s", serving directory "."
[1274991792] [error] [client 10.50.50.50] worker_thread: SSL handshake error
[1274991792] [error] [client 10.50.50.50]   --> error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number
[1274991882] [error] [client 10.50.50.50] worker_thread: SSL handshake error
[1274991882] [error] [client 10.50.50.50]   --> error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher
This commit is contained in:
mlamb 2010-05-27 15:44:59 -04:00
parent ddde5d9d1b
commit 22322f2851

View File

@ -269,6 +269,9 @@ struct ssl_func {
#define SSL_CTX_set_default_passwd_cb(x,y) \ #define SSL_CTX_set_default_passwd_cb(x,y) \
(* (void (*)(SSL_CTX *, mg_callback_t)) ssl_sw[13].ptr)((x),(y)) (* (void (*)(SSL_CTX *, mg_callback_t)) ssl_sw[13].ptr)((x),(y))
#define SSL_CTX_free(x) (* (void (*)(SSL_CTX *)) ssl_sw[14].ptr)(x) #define SSL_CTX_free(x) (* (void (*)(SSL_CTX *)) ssl_sw[14].ptr)(x)
#define ERR_get_error() (* (unsigned long (*)(void)) ssl_sw[15].ptr)()
#define ERR_error_string(x, y) (* (char * (*)(unsigned long, char *)) ssl_sw[16].ptr)((x), (y))
#define SSL_load_error_strings() (* (void (*)(void)) ssl_sw[17].ptr)()
#define CRYPTO_num_locks() (* (int (*)(void)) crypto_sw[0].ptr)() #define CRYPTO_num_locks() (* (int (*)(void)) crypto_sw[0].ptr)()
#define CRYPTO_set_locking_callback(x) \ #define CRYPTO_set_locking_callback(x) \
@ -299,6 +302,9 @@ static struct ssl_func ssl_sw[] = {
{"SSL_CTX_use_certificate_file",NULL}, {"SSL_CTX_use_certificate_file",NULL},
{"SSL_CTX_set_default_passwd_cb",NULL}, {"SSL_CTX_set_default_passwd_cb",NULL},
{"SSL_CTX_free", NULL}, {"SSL_CTX_free", NULL},
{"ERR_get_error", NULL},
{"ERR_error_string", NULL},
{"SSL_load_error_strings", NULL},
{NULL, NULL} {NULL, NULL}
}; };
@ -471,12 +477,32 @@ cry(struct mg_connection *conn, const char *fmt, ...)
(void) fprintf(fp, "%s", buf); (void) fprintf(fp, "%s", buf);
fputc('\n', fp); fputc('\n', fp);
funlockfile(fp); funlockfile(fp);
(void) fclose(fp); // (void) fclose(fp);
} }
} }
conn->request_info.log_message = NULL; conn->request_info.log_message = NULL;
} }
/*
* Print OpenSSL error messages, if any, to the error log.
*/
static void ssl_cry(struct mg_connection *conn, const char *fmt, ...) {
char buf[BUFSIZ];
va_list ap;
/* first just log the mongoose-level error message passed in via fmt, etc. */
va_start(ap, fmt);
(void) vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
cry(conn, buf);
/* then loop through any unlogged OpenSSL errors */
unsigned long err;
while ((err = ERR_get_error()) != 0) {
cry(conn, " OpenSSL: %s", ERR_error_string(err, NULL));
}
}
/* /*
* Return fake connection structure. Used for logging, if connection * Return fake connection structure. Used for logging, if connection
* is not applicable at the moment of logging. * is not applicable at the moment of logging.
@ -3874,20 +3900,21 @@ set_ssl_option(struct mg_context *ctx, const char *pem)
/* Initialize SSL crap */ /* Initialize SSL crap */
SSL_library_init(); SSL_library_init();
SSL_load_error_strings();
if ((CTX = SSL_CTX_new(SSLv23_server_method())) == NULL) if ((CTX = SSL_CTX_new(SSLv23_server_method())) == NULL)
cry(fc(ctx), "SSL_CTX_new error"); ssl_cry(fc(ctx), "SSL_CTX_new error");
else if (ctx->callbacks[MG_EVENT_SSL_PASSWORD] != NULL) else if (ctx->callbacks[MG_EVENT_SSL_PASSWORD] != NULL)
SSL_CTX_set_default_passwd_cb(CTX, SSL_CTX_set_default_passwd_cb(CTX,
ctx->callbacks[MG_EVENT_SSL_PASSWORD]); ctx->callbacks[MG_EVENT_SSL_PASSWORD]);
if (CTX != NULL && SSL_CTX_use_certificate_file( if (CTX != NULL && SSL_CTX_use_certificate_file(
CTX, pem, SSL_FILETYPE_PEM) == 0) { CTX, pem, SSL_FILETYPE_PEM) == 0) {
cry(fc(ctx), "%s: cannot open %s", __func__, pem); ssl_cry(fc(ctx), "%s: cannot open %s", __func__, pem);
return (MG_ERROR); return (MG_ERROR);
} else if (CTX != NULL && SSL_CTX_use_PrivateKey_file( } else if (CTX != NULL && SSL_CTX_use_PrivateKey_file(
CTX, pem, SSL_FILETYPE_PEM) == 0) { CTX, pem, SSL_FILETYPE_PEM) == 0) {
cry(fc(ctx), "%s: cannot open %s", NULL, pem); ssl_cry(fc(ctx), "%s: cannot open %s", NULL, pem);
return (MG_ERROR); return (MG_ERROR);
} }
@ -3897,7 +3924,7 @@ set_ssl_option(struct mg_context *ctx, const char *pem)
*/ */
size = sizeof(pthread_mutex_t) * CRYPTO_num_locks(); size = sizeof(pthread_mutex_t) * CRYPTO_num_locks();
if ((ssl_mutexes = (pthread_mutex_t *) malloc(size)) == NULL) { if ((ssl_mutexes = (pthread_mutex_t *) malloc(size)) == NULL) {
cry(fc(ctx), "%s: cannot allocate mutexes", __func__); ssl_cry(fc(ctx), "%s: cannot allocate mutexes", __func__);
return (MG_ERROR); return (MG_ERROR);
} }
@ -4363,12 +4390,12 @@ worker_thread(struct mg_context *ctx)
if (conn.client.is_ssl && if (conn.client.is_ssl &&
(conn.ssl = SSL_new(conn.ctx->ssl_ctx)) == NULL) { (conn.ssl = SSL_new(conn.ctx->ssl_ctx)) == NULL) {
cry(&conn, "%s: SSL_new: %d", __func__, ERRNO); ssl_cry(&conn, "%s: SSL_new: %d", __func__, ERRNO);
} else if (conn.client.is_ssl && } else if (conn.client.is_ssl &&
SSL_set_fd(conn.ssl, conn.client.sock) != 1) { SSL_set_fd(conn.ssl, conn.client.sock) != 1) {
cry(&conn, "%s: SSL_set_fd: %d", __func__, ERRNO); ssl_cry(&conn, "%s: SSL_set_fd: %d", __func__, ERRNO);
} else if (conn.client.is_ssl && SSL_accept(conn.ssl) != 1) { } else if (conn.client.is_ssl && SSL_accept(conn.ssl) != 1) {
cry(&conn, "%s: SSL handshake error", __func__); ssl_cry(&conn, "%s: SSL handshake error", __func__);
} else { } else {
process_new_connection(&conn); process_new_connection(&conn);
} }