|
@@ -1875,6 +1875,8 @@ typedef struct x509 X509;
|
|
#define SSL_TLSEXT_ERR_ALERT_FATAL (2)
|
|
#define SSL_TLSEXT_ERR_ALERT_FATAL (2)
|
|
#define SSL_TLSEXT_ERR_NOACK (3)
|
|
#define SSL_TLSEXT_ERR_NOACK (3)
|
|
|
|
|
|
|
|
+#define SSL_SESS_CACHE_BOTH (3)
|
|
|
|
+
|
|
enum ssl_func_category {
|
|
enum ssl_func_category {
|
|
TLS_Mandatory, /* required for HTTPS */
|
|
TLS_Mandatory, /* required for HTTPS */
|
|
TLS_ALPN, /* required for Application Layer Protocol Negotiation */
|
|
TLS_ALPN, /* required for Application Layer Protocol Negotiation */
|
|
@@ -1971,6 +1973,11 @@ typedef int (*tSSL_next_protos_advertised_cb)(SSL *ssl,
|
|
(*(void (*)(SSL_CTX *, tSSL_next_protos_advertised_cb, void *))ssl_sw[41] \
|
|
(*(void (*)(SSL_CTX *, tSSL_next_protos_advertised_cb, void *))ssl_sw[41] \
|
|
.ptr)
|
|
.ptr)
|
|
|
|
|
|
|
|
+#define SSL_CTX_set_session_cache_mode \
|
|
|
|
+ (*(long (*)(SSL_CTX *, long))ssl_sw[42].ptr)
|
|
|
|
+#define SSL_CTX_sess_set_cache_size (*(long (*)(SSL_CTX *, long))ssl_sw[43].ptr)
|
|
|
|
+#define SSL_CTX_set_timeout (*(long (*)(SSL_CTX *, long))ssl_sw[44].ptr)
|
|
|
|
+
|
|
#define SSL_CTX_clear_options(ctx, op) \
|
|
#define SSL_CTX_clear_options(ctx, op) \
|
|
SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL)
|
|
SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL)
|
|
#define SSL_CTX_set_ecdh_auto(ctx, onoff) \
|
|
#define SSL_CTX_set_ecdh_auto(ctx, onoff) \
|
|
@@ -2067,6 +2074,9 @@ static struct ssl_func ssl_sw[] = {
|
|
{"SSL_CTX_set_alpn_protos", TLS_ALPN, NULL},
|
|
{"SSL_CTX_set_alpn_protos", TLS_ALPN, NULL},
|
|
{"SSL_CTX_set_alpn_select_cb", TLS_ALPN, NULL},
|
|
{"SSL_CTX_set_alpn_select_cb", TLS_ALPN, NULL},
|
|
{"SSL_CTX_set_next_protos_advertised_cb", TLS_ALPN, NULL},
|
|
{"SSL_CTX_set_next_protos_advertised_cb", TLS_ALPN, NULL},
|
|
|
|
+ {"SSL_CTX_set_session_cache_mode", TLS_Mandatory, NULL},
|
|
|
|
+ {"SSL_CTX_sess_set_cache_size", TLS_Mandatory, NULL},
|
|
|
|
+ {"SSL_CTX_set_timeout", TLS_Mandatory, NULL},
|
|
{NULL, TLS_END_OF_LIST, NULL}};
|
|
{NULL, TLS_END_OF_LIST, NULL}};
|
|
|
|
|
|
|
|
|
|
@@ -2165,6 +2175,11 @@ typedef int (*tSSL_next_protos_advertised_cb)(SSL *ssl,
|
|
(*(void (*)(SSL_CTX *, tSSL_next_protos_advertised_cb, void *))ssl_sw[41] \
|
|
(*(void (*)(SSL_CTX *, tSSL_next_protos_advertised_cb, void *))ssl_sw[41] \
|
|
.ptr)
|
|
.ptr)
|
|
|
|
|
|
|
|
+#define SSL_CTX_set_session_cache_mode \
|
|
|
|
+ (*(long (*)(SSL_CTX *, long))ssl_sw[42].ptr)
|
|
|
|
+#define SSL_CTX_sess_set_cache_size (*(long (*)(SSL_CTX *, long))ssl_sw[43].ptr)
|
|
|
|
+#define SSL_CTX_set_timeout (*(long (*)(SSL_CTX *, long))ssl_sw[44].ptr)
|
|
|
|
+
|
|
|
|
|
|
#define SSL_CTX_set_options(ctx, op) \
|
|
#define SSL_CTX_set_options(ctx, op) \
|
|
SSL_CTX_ctrl((ctx), SSL_CTRL_OPTIONS, (op), NULL)
|
|
SSL_CTX_ctrl((ctx), SSL_CTRL_OPTIONS, (op), NULL)
|
|
@@ -2279,6 +2294,9 @@ static struct ssl_func ssl_sw[] = {
|
|
{"SSL_CTX_set_alpn_protos", TLS_ALPN, NULL},
|
|
{"SSL_CTX_set_alpn_protos", TLS_ALPN, NULL},
|
|
{"SSL_CTX_set_alpn_select_cb", TLS_ALPN, NULL},
|
|
{"SSL_CTX_set_alpn_select_cb", TLS_ALPN, NULL},
|
|
{"SSL_CTX_set_next_protos_advertised_cb", TLS_ALPN, NULL},
|
|
{"SSL_CTX_set_next_protos_advertised_cb", TLS_ALPN, NULL},
|
|
|
|
+ {"SSL_CTX_set_session_cache_mode", TLS_Mandatory, NULL},
|
|
|
|
+ {"SSL_CTX_sess_set_cache_size", TLS_Mandatory, NULL},
|
|
|
|
+ {"SSL_CTX_set_timeout", TLS_Mandatory, NULL},
|
|
{NULL, TLS_END_OF_LIST, NULL}};
|
|
{NULL, TLS_END_OF_LIST, NULL}};
|
|
|
|
|
|
|
|
|
|
@@ -2486,6 +2504,7 @@ enum {
|
|
URL_REWRITE_PATTERN,
|
|
URL_REWRITE_PATTERN,
|
|
HIDE_FILES,
|
|
HIDE_FILES,
|
|
SSL_DO_VERIFY_PEER,
|
|
SSL_DO_VERIFY_PEER,
|
|
|
|
+ SSL_CACHE_TIMEOUT,
|
|
SSL_CA_PATH,
|
|
SSL_CA_PATH,
|
|
SSL_CA_FILE,
|
|
SSL_CA_FILE,
|
|
SSL_VERIFY_DEPTH,
|
|
SSL_VERIFY_DEPTH,
|
|
@@ -2603,6 +2622,7 @@ static const struct mg_option config_options[] = {
|
|
{"hide_files_patterns", MG_CONFIG_TYPE_EXT_PATTERN, NULL},
|
|
{"hide_files_patterns", MG_CONFIG_TYPE_EXT_PATTERN, NULL},
|
|
|
|
|
|
{"ssl_verify_peer", MG_CONFIG_TYPE_YES_NO_OPTIONAL, "no"},
|
|
{"ssl_verify_peer", MG_CONFIG_TYPE_YES_NO_OPTIONAL, "no"},
|
|
|
|
+ {"ssl_cache_timeout", MG_CONFIG_TYPE_NUMBER, "-1"},
|
|
|
|
|
|
{"ssl_ca_path", MG_CONFIG_TYPE_DIRECTORY, NULL},
|
|
{"ssl_ca_path", MG_CONFIG_TYPE_DIRECTORY, NULL},
|
|
{"ssl_ca_file", MG_CONFIG_TYPE_FILE, NULL},
|
|
{"ssl_ca_file", MG_CONFIG_TYPE_FILE, NULL},
|
|
@@ -16474,6 +16494,7 @@ init_ssl_ctx_impl(struct mg_context *phys_ctx,
|
|
md5_byte_t ssl_context_id[16];
|
|
md5_byte_t ssl_context_id[16];
|
|
md5_state_t md5state;
|
|
md5_state_t md5state;
|
|
int protocol_ver;
|
|
int protocol_ver;
|
|
|
|
+ int ssl_cache_timeout;
|
|
|
|
|
|
#if defined(OPENSSL_API_1_1)
|
|
#if defined(OPENSSL_API_1_1)
|
|
if ((dom_ctx->ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) {
|
|
if ((dom_ctx->ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) {
|
|
@@ -16665,6 +16686,16 @@ init_ssl_ctx_impl(struct mg_context *phys_ctx,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /* SSL session caching */
|
|
|
|
+ ssl_cache_timeout = ((dom_ctx->config[SSL_CACHE_TIMEOUT] != NULL)
|
|
|
|
+ ? atoi(dom_ctx->config[SSL_CACHE_TIMEOUT])
|
|
|
|
+ : 0);
|
|
|
|
+ if (ssl_cache_timeout > 0) {
|
|
|
|
+ SSL_CTX_set_session_cache_mode(dom_ctx->ssl_ctx, SSL_SESS_CACHE_BOTH);
|
|
|
|
+ /* SSL_CTX_sess_set_cache_size(dom_ctx->ssl_ctx, 10000); ... use default */
|
|
|
|
+ SSL_CTX_set_timeout(dom_ctx->ssl_ctx, (long)ssl_cache_timeout);
|
|
|
|
+ }
|
|
|
|
+
|
|
/* Initialize ALPN only of TLS library (OpenSSL version) supports ALPN */
|
|
/* Initialize ALPN only of TLS library (OpenSSL version) supports ALPN */
|
|
#if !defined(NO_SSL_DL)
|
|
#if !defined(NO_SSL_DL)
|
|
if (!tls_feature_missing[TLS_ALPN])
|
|
if (!tls_feature_missing[TLS_ALPN])
|
|
@@ -16710,11 +16741,14 @@ init_ssl_ctx(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx)
|
|
phys_ctx->user_data));
|
|
phys_ctx->user_data));
|
|
|
|
|
|
if (callback_ret < 0) {
|
|
if (callback_ret < 0) {
|
|
|
|
+ /* Callback exists and returns <0: Initializing failed. */
|
|
mg_cry_ctx_internal(phys_ctx,
|
|
mg_cry_ctx_internal(phys_ctx,
|
|
"external_ssl_ctx callback returned error: %i",
|
|
"external_ssl_ctx callback returned error: %i",
|
|
callback_ret);
|
|
callback_ret);
|
|
return 0;
|
|
return 0;
|
|
} else if (callback_ret > 0) {
|
|
} else if (callback_ret > 0) {
|
|
|
|
+ /* Callback exists and returns >0: Initializing complete,
|
|
|
|
+ * civetweb should not modify the SSL context. */
|
|
dom_ctx->ssl_ctx = (SSL_CTX *)ssl_ctx;
|
|
dom_ctx->ssl_ctx = (SSL_CTX *)ssl_ctx;
|
|
if (!initialize_ssl(ebuf, sizeof(ebuf))) {
|
|
if (!initialize_ssl(ebuf, sizeof(ebuf))) {
|
|
mg_cry_ctx_internal(phys_ctx, "%s", ebuf);
|
|
mg_cry_ctx_internal(phys_ctx, "%s", ebuf);
|
|
@@ -16722,8 +16756,10 @@ init_ssl_ctx(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx)
|
|
}
|
|
}
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
+ /* If the callback does not exist or return 0, civetweb must initialize
|
|
|
|
+ * the SSL context. Handle "domain" callback next. */
|
|
|
|
|
|
- /* Check for external domain SSL_CTX */
|
|
|
|
|
|
+ /* Check for external domain SSL_CTX callback. */
|
|
callback_ret = (phys_ctx->callbacks.external_ssl_ctx_domain == NULL)
|
|
callback_ret = (phys_ctx->callbacks.external_ssl_ctx_domain == NULL)
|
|
? 0
|
|
? 0
|
|
: (phys_ctx->callbacks.external_ssl_ctx_domain(
|
|
: (phys_ctx->callbacks.external_ssl_ctx_domain(
|
|
@@ -16732,12 +16768,14 @@ init_ssl_ctx(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx)
|
|
phys_ctx->user_data));
|
|
phys_ctx->user_data));
|
|
|
|
|
|
if (callback_ret < 0) {
|
|
if (callback_ret < 0) {
|
|
|
|
+ /* Callback < 0: Error. Abort init. */
|
|
mg_cry_ctx_internal(
|
|
mg_cry_ctx_internal(
|
|
phys_ctx,
|
|
phys_ctx,
|
|
"external_ssl_ctx_domain callback returned error: %i",
|
|
"external_ssl_ctx_domain callback returned error: %i",
|
|
callback_ret);
|
|
callback_ret);
|
|
return 0;
|
|
return 0;
|
|
} else if (callback_ret > 0) {
|
|
} else if (callback_ret > 0) {
|
|
|
|
+ /* Callback > 0: Consider init done. */
|
|
dom_ctx->ssl_ctx = (SSL_CTX *)ssl_ctx;
|
|
dom_ctx->ssl_ctx = (SSL_CTX *)ssl_ctx;
|
|
if (!initialize_ssl(ebuf, sizeof(ebuf))) {
|
|
if (!initialize_ssl(ebuf, sizeof(ebuf))) {
|
|
mg_cry_ctx_internal(phys_ctx, "%s", ebuf);
|
|
mg_cry_ctx_internal(phys_ctx, "%s", ebuf);
|
|
@@ -16762,11 +16800,14 @@ init_ssl_ctx(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /* If a certificate chain is configured, use it. */
|
|
chain = dom_ctx->config[SSL_CERTIFICATE_CHAIN];
|
|
chain = dom_ctx->config[SSL_CERTIFICATE_CHAIN];
|
|
if (chain == NULL) {
|
|
if (chain == NULL) {
|
|
|
|
+ /* Default: certificate chain in PEM file */
|
|
chain = pem;
|
|
chain = pem;
|
|
}
|
|
}
|
|
if ((chain != NULL) && (*chain == 0)) {
|
|
if ((chain != NULL) && (*chain == 0)) {
|
|
|
|
+ /* If the chain is an empty string, don't use it. */
|
|
chain = NULL;
|
|
chain = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -18337,6 +18378,7 @@ init_connection(struct mg_connection *conn)
|
|
* goes to crule42. */
|
|
* goes to crule42. */
|
|
conn->data_len = 0;
|
|
conn->data_len = 0;
|
|
conn->handled_requests = 0;
|
|
conn->handled_requests = 0;
|
|
|
|
+ conn->connection_type = CONNECTION_TYPE_INVALID;
|
|
mg_set_user_connection_data(conn, NULL);
|
|
mg_set_user_connection_data(conn, NULL);
|
|
|
|
|
|
#if defined(USE_SERVER_STATS)
|
|
#if defined(USE_SERVER_STATS)
|