|
@@ -811,6 +811,7 @@ typedef int socklen_t;
|
|
|
typedef struct ssl_st SSL;
|
|
|
typedef struct ssl_method_st SSL_METHOD;
|
|
|
typedef struct ssl_ctx_st SSL_CTX;
|
|
|
+typedef struct x5099_store_ctx_st X509_STORE_CTX;
|
|
|
|
|
|
struct ssl_func {
|
|
|
const char *name; /* SSL function name */
|
|
@@ -842,6 +843,11 @@ struct ssl_func {
|
|
|
#define SSL_pending (*(int (*)(SSL *))ssl_sw[18].ptr)
|
|
|
#define SSL_CTX_set_verify (*(void (*)(SSL_CTX *, int, int))ssl_sw[19].ptr)
|
|
|
#define SSL_shutdown (*(int (*)(SSL *))ssl_sw[20].ptr)
|
|
|
+#define SSL_CTX_load_verify_locations \
|
|
|
+(*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[21].ptr)
|
|
|
+#define SSL_CTX_set_default_verify_paths \
|
|
|
+(*(int (*)(SSL_CTX *))ssl_sw[22].ptr)
|
|
|
+#define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[23].ptr)
|
|
|
|
|
|
#define CRYPTO_num_locks (*(int (*)(void))crypto_sw[0].ptr)
|
|
|
#define CRYPTO_set_locking_callback \
|
|
@@ -876,6 +882,9 @@ static struct ssl_func ssl_sw[] = {{"SSL_free", NULL},
|
|
|
{"SSL_pending", NULL},
|
|
|
{"SSL_CTX_set_verify", NULL},
|
|
|
{"SSL_shutdown", NULL},
|
|
|
+ {"SSL_CTX_load_verify_locations", NULL},
|
|
|
+ {"SSL_CTX_set_default_verify_paths", NULL},
|
|
|
+ {"SSL_CTX_set_verify_depth", NULL},
|
|
|
{NULL, NULL}};
|
|
|
|
|
|
/* Similar array as ssl_sw. These functions could be located in different
|
|
@@ -971,6 +980,12 @@ enum {
|
|
|
REWRITE,
|
|
|
HIDE_FILES,
|
|
|
REQUEST_TIMEOUT,
|
|
|
+ SSL_VERIFY_PEER,
|
|
|
+ SSL_CA_PATH,
|
|
|
+ SSL_CA_FILE,
|
|
|
+ SSL_VERIFY_DEPTH,
|
|
|
+ SSL_DEFAULT_VERIFY_PATHS,
|
|
|
+ SSL_FORWARD_SECRECY,
|
|
|
#if defined(USE_WEBSOCKET)
|
|
|
WEBSOCKET_TIMEOUT,
|
|
|
#endif
|
|
@@ -1030,6 +1045,12 @@ static struct mg_option config_options[] = {
|
|
|
{"url_rewrite_patterns", CONFIG_TYPE_STRING, NULL},
|
|
|
{"hide_files_patterns", CONFIG_TYPE_EXT_PATTERN, NULL},
|
|
|
{"request_timeout_ms", CONFIG_TYPE_NUMBER, "30000"},
|
|
|
+ {"ssl_verify_peer", CONFIG_TYPE_BOOLEAN, "no"},
|
|
|
+ {"ssl_ca_path", CONFIG_TYPE_DIRECTORY, NULL},
|
|
|
+ {"ssl_ca_file", CONFIG_TYPE_FILE, NULL},
|
|
|
+ {"ssl_verify_depth", CONFIG_TYPE_NUMBER, "9"},
|
|
|
+ {"ssl_default_verify_paths", CONFIG_TYPE_BOOLEAN, "yes"},
|
|
|
+ {"ssl_forward_secrecy", CONFIG_TYPE_BOOLEAN, "yes"},
|
|
|
#if defined(USE_WEBSOCKET)
|
|
|
{"websocket_timeout_ms", CONFIG_TYPE_NUMBER, "30000"},
|
|
|
#endif
|
|
@@ -9872,7 +9893,8 @@ sslize(struct mg_connection *conn, SSL_CTX *s, int (*func)(SSL *))
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- return (conn->ssl = SSL_new(s)) != NULL
|
|
|
+ conn->ssl = SSL_new(s);
|
|
|
+ return (conn->ssl != NULL)
|
|
|
&& SSL_set_fd(conn->ssl, conn->client.sock) == 1
|
|
|
&& func(conn->ssl) == 1;
|
|
|
}
|
|
@@ -10004,6 +10026,11 @@ set_ssl_option(struct mg_context *ctx)
|
|
|
{
|
|
|
const char *pem;
|
|
|
int callback_ret;
|
|
|
+ int should_verify_peer;
|
|
|
+ const char* ca_path;
|
|
|
+ const char* ca_file;
|
|
|
+ int use_default_verify_paths;
|
|
|
+ int verify_depth;
|
|
|
|
|
|
/* If PEM file is not specified and the init_ssl callback
|
|
|
* is not specified, skip SSL initialization. */
|
|
@@ -10068,6 +10095,36 @@ set_ssl_option(struct mg_context *ctx)
|
|
|
(void)SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem);
|
|
|
}
|
|
|
|
|
|
+ should_verify_peer = (ctx->config[SSL_VERIFY_PEER] != NULL)
|
|
|
+ && (mg_strcasecmp(ctx->config[SSL_VERIFY_PEER], "yes") == 0);
|
|
|
+
|
|
|
+ use_default_verify_paths = (ctx->config[SSL_DEFAULT_VERIFY_PATHS] != NULL)
|
|
|
+ && (mg_strcasecmp(ctx->config[SSL_DEFAULT_VERIFY_PATHS], "yes") == 0);
|
|
|
+
|
|
|
+ if (should_verify_peer) {
|
|
|
+ ca_path = ctx->config[SSL_CA_PATH];
|
|
|
+ ca_file = ctx->config[SSL_CA_FILE];
|
|
|
+ if (SSL_CTX_load_verify_locations(ctx->ssl_ctx, ca_file, ca_path) != 1) {
|
|
|
+ mg_cry(fc(ctx), "SSL_CTX_load_verify_locations error: %s "
|
|
|
+ "ssl_verify_peer requires setting "
|
|
|
+ "either ssl_ca_path or ssl_ca_file. Is any of them present in "
|
|
|
+ "the .conf file?", ssl_error());
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ SSL_CTX_set_verify(ctx->ssl_ctx, 3, 0);
|
|
|
+
|
|
|
+ if (use_default_verify_paths
|
|
|
+ && SSL_CTX_set_default_verify_paths(ctx->ssl_ctx) != 1) {
|
|
|
+ mg_cry(fc(ctx), "SSL_CTX_set_default_verify_paths error: %s", ssl_error());
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ctx->config[SSL_VERIFY_DEPTH]){
|
|
|
+ verify_depth = atoi(ctx->config[SSL_VERIFY_DEPTH]);
|
|
|
+ SSL_CTX_set_verify_depth(ctx->ssl_ctx, verify_depth);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
@@ -10368,7 +10425,8 @@ mg_connect_client(const char *host,
|
|
|
(void)pthread_mutex_init(&conn->mutex, &pthread_mutex_attr);
|
|
|
#ifndef NO_SSL
|
|
|
if (use_ssl) {
|
|
|
- /* SSL_CTX_set_verify call is needed to switch off server
|
|
|
+ /* TODO: Check ssl_verify_peer and ssl_ca_path here.
|
|
|
+ SSL_CTX_set_verify call is needed to switch off server
|
|
|
* certificate checking, which is off by default in OpenSSL and on
|
|
|
* in yaSSL. */
|
|
|
SSL_CTX_set_verify(conn->client_ssl_ctx, 0, 0);
|