Ver código fonte

Merge pull request #227 from MGralka/cipher_list

Option to set cipher list
bel2125 9 anos atrás
pai
commit
0ef099d8ac
2 arquivos alterados com 75 adições e 8 exclusões
  1. 21 2
      docs/UserManual.md
  2. 54 6
      src/civetweb.c

+ 21 - 2
docs/UserManual.md

@@ -407,8 +407,27 @@ than the depth set here connection is refused.
 ### ssl_default_verify_paths `yes`
 ### ssl_default_verify_paths `yes`
 Loads default trusted certificates locations set at openssl compile time.
 Loads default trusted certificates locations set at openssl compile time.
 
 
-### ssl_forward_secrecy `yes`
-Enable [forward secrecy](https://en.wikipedia.org/wiki/Forward_secrecy).
+### ssl_cipher_list
+List of ciphers to present to the client. Entries should be separated by 
+colons, commas or spaces.
+
+    ALL           All available ciphers
+    ALL:!eNULL    All ciphers excluding NULL ciphers
+    AES128:!MD5   AES 128 with digests other than MD5
+
+See [this entry](https://www.openssl.org/docs/manmaster/apps/ciphers.html) in
+OpenSSL documentation for full list of options and additional examples.
+
+### ssl_protocol_version `0`
+Sets the minimal accepted version of SSL/TLS protocol according to the table:
+
+Protocols | Value
+------------ | -------------
+SSL2+SSL3+TLS1.0+TLS1.1+TLS1.2  | 0
+SSL3+TLS1.0+TLS1.1+TLS1.2  | 1
+TLS1.0+TLS1.1+TLS1.2 | 2
+TLS1.1+TLS1.2 | 3
+TLS1.2 | 4
 
 
 # Lua Scripts and Lua Server Pages
 # Lua Scripts and Lua Server Pages
 Pre-built Windows and Mac civetweb binaries have built-in Lua scripting
 Pre-built Windows and Mac civetweb binaries have built-in Lua scripting

+ 54 - 6
src/civetweb.c

@@ -841,10 +841,20 @@ typedef struct ssl_method_st SSL_METHOD;
 typedef struct ssl_ctx_st SSL_CTX;
 typedef struct ssl_ctx_st SSL_CTX;
 typedef struct x509_store_ctx_st X509_STORE_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_NONE (0)
 #define SSL_VERIFY_PEER (1)
 #define SSL_VERIFY_PEER (1)
 #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT (2)
 #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT (2)
 #define SSL_VERIFY_CLIENT_ONCE (4)
 #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 {
 struct ssl_func {
 	const char *name;  /* SSL function name */
 	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_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[28].ptr)
 #define SSL_CTX_set_session_id_context                                         \
 #define SSL_CTX_set_session_id_context                                         \
 	(*(int (*)(SSL_CTX *, const unsigned char *, unsigned int))ssl_sw[29].ptr)
 	(*(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_num_locks (*(int (*)(void))crypto_sw[0].ptr)
 #define CRYPTO_set_locking_callback                                            \
 #define CRYPTO_set_locking_callback                                            \
@@ -935,6 +953,8 @@ static struct ssl_func ssl_sw[] = {{"SSL_free", NULL},
                                    {"SSL_CIPHER_get_name", NULL},
                                    {"SSL_CIPHER_get_name", NULL},
                                    {"SSL_CTX_check_private_key", NULL},
                                    {"SSL_CTX_check_private_key", NULL},
                                    {"SSL_CTX_set_session_id_context", NULL},
                                    {"SSL_CTX_set_session_id_context", NULL},
+                                   {"SSL_CTX_ctrl", NULL},
+                                   {"SSL_CTX_set_cipher_list", NULL},
                                    {NULL, NULL}};
                                    {NULL, NULL}};
 
 
 
 
@@ -1037,7 +1057,8 @@ enum {
 	SSL_CA_FILE,
 	SSL_CA_FILE,
 	SSL_VERIFY_DEPTH,
 	SSL_VERIFY_DEPTH,
 	SSL_DEFAULT_VERIFY_PATHS,
 	SSL_DEFAULT_VERIFY_PATHS,
-	SSL_FORWARD_SECRECY,
+	SSL_CIPHER_LIST,
+	SSL_PROTOCOL_VERSION,
 #if defined(USE_WEBSOCKET)
 #if defined(USE_WEBSOCKET)
 	WEBSOCKET_TIMEOUT,
 	WEBSOCKET_TIMEOUT,
 #endif
 #endif
@@ -1103,7 +1124,8 @@ static struct mg_option config_options[] = {
     {"ssl_ca_file", CONFIG_TYPE_FILE, NULL},
     {"ssl_ca_file", CONFIG_TYPE_FILE, NULL},
     {"ssl_verify_depth", CONFIG_TYPE_NUMBER, "9"},
     {"ssl_verify_depth", CONFIG_TYPE_NUMBER, "9"},
     {"ssl_default_verify_paths", CONFIG_TYPE_BOOLEAN, "yes"},
     {"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)
 #if defined(USE_WEBSOCKET)
     {"websocket_timeout_ms", CONFIG_TYPE_NUMBER, "30000"},
     {"websocket_timeout_ms", CONFIG_TYPE_NUMBER, "30000"},
 #endif
 #endif
@@ -10489,7 +10511,6 @@ initialize_ssl(struct mg_context *ctx)
 	return 1;
 	return 1;
 }
 }
 
 
-
 static int
 static int
 ssl_use_pem_file(struct mg_context *ctx, const char *pem)
 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 */
 	/* could use SSL_CTX_set_default_passwd_cb_userdata */
-
 	if (SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem, 1) == 0) {
 	if (SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem, 1) == 0) {
 		mg_cry(fc(ctx),
 		mg_cry(fc(ctx),
 		       "%s: cannot open private key file %s: %s",
 		       "%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. */
 /* Dynamically load SSL library. Set up ctx->ssl_ctx pointer. */
 static int
 static int
 set_ssl_option(struct mg_context *ctx)
 set_ssl_option(struct mg_context *ctx)
@@ -10548,6 +10583,7 @@ set_ssl_option(struct mg_context *ctx)
 	struct timespec now_mt;
 	struct timespec now_mt;
 	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;
 
 
 	/* If PEM file is not specified and the init_ssl callback
 	/* If PEM file is not specified and the init_ssl callback
 	 * is not specified, skip SSL initialization. */
 	 * is not specified, skip SSL initialization. */
@@ -10581,6 +10617,13 @@ set_ssl_option(struct mg_context *ctx)
 		return 0;
 		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. */
 	/* If a callback has been specified, call it. */
 	callback_ret =
 	callback_ret =
 	    (ctx->callbacks.init_ssl == NULL)
 	    (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;
 	return 1;
 }
 }