|
@@ -841,10 +841,20 @@ typedef struct ssl_method_st SSL_METHOD;
|
|
|
typedef struct ssl_ctx_st SSL_CTX;
|
|
|
typedef struct x509_store_ctx_st X509_STORE_CTX;
|
|
|
|
|
|
+#define SSL_CTRL_OPTIONS (32)
|
|
|
+#define SSL_CTRL_CLEAR_OPTIONS (77)
|
|
|
+
|
|
|
#define SSL_VERIFY_NONE (0)
|
|
|
#define SSL_VERIFY_PEER (1)
|
|
|
#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT (2)
|
|
|
#define SSL_VERIFY_CLIENT_ONCE (4)
|
|
|
+#define SSL_OP_ALL (0x80000BFFL)
|
|
|
+#define SSL_OP_NO_SSLv2 (0x01000000L)
|
|
|
+#define SSL_OP_NO_SSLv3 (0x02000000L)
|
|
|
+#define SSL_OP_NO_TLSv1 (0x04000000L)
|
|
|
+#define SSL_OP_NO_TLSv1_2 (0x08000000L)
|
|
|
+#define SSL_OP_NO_TLSv1_1 (0x10000000L)
|
|
|
+#define SSL_OP_SINGLE_DH_USE (0x00100000L)
|
|
|
|
|
|
struct ssl_func {
|
|
|
const char *name; /* SSL function name */
|
|
@@ -891,6 +901,14 @@ struct ssl_func {
|
|
|
#define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[28].ptr)
|
|
|
#define SSL_CTX_set_session_id_context \
|
|
|
(*(int (*)(SSL_CTX *, const unsigned char *, unsigned int))ssl_sw[29].ptr)
|
|
|
+#define SSL_CTX_ctrl \
|
|
|
+ (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[30].ptr)
|
|
|
+#define SSL_CTX_set_cipher_list \
|
|
|
+ (*(int (*)(SSL_CTX *, const char *))ssl_sw[31].ptr)
|
|
|
+#define SSL_CTX_set_options(ctx,op) \
|
|
|
+ SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL)
|
|
|
+#define SSL_CTX_clear_options(ctx,op) \
|
|
|
+ SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_OPTIONS,(op),NULL)
|
|
|
|
|
|
#define CRYPTO_num_locks (*(int (*)(void))crypto_sw[0].ptr)
|
|
|
#define CRYPTO_set_locking_callback \
|
|
@@ -935,6 +953,8 @@ static struct ssl_func ssl_sw[] = {{"SSL_free", NULL},
|
|
|
{"SSL_CIPHER_get_name", NULL},
|
|
|
{"SSL_CTX_check_private_key", NULL},
|
|
|
{"SSL_CTX_set_session_id_context", NULL},
|
|
|
+ {"SSL_CTX_ctrl", NULL},
|
|
|
+ {"SSL_CTX_set_cipher_list", NULL},
|
|
|
{NULL, NULL}};
|
|
|
|
|
|
|
|
@@ -1037,7 +1057,8 @@ enum {
|
|
|
SSL_CA_FILE,
|
|
|
SSL_VERIFY_DEPTH,
|
|
|
SSL_DEFAULT_VERIFY_PATHS,
|
|
|
- SSL_FORWARD_SECRECY,
|
|
|
+ SSL_CIPHER_LIST,
|
|
|
+ SSL_PROTOCOL_VERSION,
|
|
|
#if defined(USE_WEBSOCKET)
|
|
|
WEBSOCKET_TIMEOUT,
|
|
|
#endif
|
|
@@ -1103,7 +1124,8 @@ static struct mg_option config_options[] = {
|
|
|
{"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"},
|
|
|
+ {"ssl_cipher_list", CONFIG_TYPE_STRING, NULL},
|
|
|
+ {"ssl_protocol_version", CONFIG_TYPE_NUMBER, "0"},
|
|
|
#if defined(USE_WEBSOCKET)
|
|
|
{"websocket_timeout_ms", CONFIG_TYPE_NUMBER, "30000"},
|
|
|
#endif
|
|
@@ -10489,7 +10511,6 @@ initialize_ssl(struct mg_context *ctx)
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
static int
|
|
|
ssl_use_pem_file(struct mg_context *ctx, const char *pem)
|
|
|
{
|
|
@@ -10503,7 +10524,6 @@ ssl_use_pem_file(struct mg_context *ctx, const char *pem)
|
|
|
}
|
|
|
|
|
|
/* could use SSL_CTX_set_default_passwd_cb_userdata */
|
|
|
-
|
|
|
if (SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem, 1) == 0) {
|
|
|
mg_cry(fc(ctx),
|
|
|
"%s: cannot open private key file %s: %s",
|
|
@@ -10533,6 +10553,21 @@ ssl_use_pem_file(struct mg_context *ctx, const char *pem)
|
|
|
}
|
|
|
|
|
|
|
|
|
+static long
|
|
|
+ssl_get_protocol(int version_id)
|
|
|
+{
|
|
|
+ long ret = SSL_OP_ALL;
|
|
|
+ if (version_id > 0)
|
|
|
+ ret |= SSL_OP_NO_SSLv2;
|
|
|
+ if (version_id > 1)
|
|
|
+ ret |= SSL_OP_NO_SSLv3;
|
|
|
+ if (version_id > 2)
|
|
|
+ ret |= SSL_OP_NO_TLSv1;
|
|
|
+ if(version_id > 3)
|
|
|
+ ret |= SSL_OP_NO_TLSv1_1;
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
/* Dynamically load SSL library. Set up ctx->ssl_ctx pointer. */
|
|
|
static int
|
|
|
set_ssl_option(struct mg_context *ctx)
|
|
@@ -10548,6 +10583,7 @@ set_ssl_option(struct mg_context *ctx)
|
|
|
struct timespec now_mt;
|
|
|
md5_byte_t ssl_context_id[16];
|
|
|
md5_state_t md5state;
|
|
|
+ int protocol_ver;
|
|
|
|
|
|
/* If PEM file is not specified and the init_ssl callback
|
|
|
* is not specified, skip SSL initialization. */
|
|
@@ -10581,6 +10617,13 @@ set_ssl_option(struct mg_context *ctx)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+ SSL_CTX_clear_options(ctx->ssl_ctx, SSL_OP_NO_SSLv2 |
|
|
|
+ SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 |
|
|
|
+ SSL_OP_NO_TLSv1_1);
|
|
|
+ protocol_ver = atoi(ctx->config[SSL_PROTOCOL_VERSION]);
|
|
|
+ SSL_CTX_set_options(ctx->ssl_ctx, ssl_get_protocol(protocol_ver));
|
|
|
+ SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_SINGLE_DH_USE);
|
|
|
+
|
|
|
/* If a callback has been specified, call it. */
|
|
|
callback_ret =
|
|
|
(ctx->callbacks.init_ssl == NULL)
|
|
@@ -10663,8 +10706,13 @@ set_ssl_option(struct mg_context *ctx)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- /* TODO: could set use SSL_CTX_set_cipher_list if set */
|
|
|
+ if (ctx->config[SSL_CIPHER_LIST] != NULL) {
|
|
|
+ if (SSL_CTX_set_cipher_list(ctx->ssl_ctx, ctx->config[SSL_CIPHER_LIST]) != 1) {
|
|
|
+ mg_cry(fc(ctx),
|
|
|
+ "SSL_CTX_set_cipher_list error: %s",
|
|
|
+ ssl_error());
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
return 1;
|
|
|
}
|