浏览代码

Allow to separate server private key and certificate chain in two different files

This is required for wolfSSL (see #437), but should be possible for other
TLS libraries (like openSSL) as well.
bel2125 8 年之前
父节点
当前提交
95603a3a74
共有 1 个文件被更改,包括 44 次插入13 次删除
  1. 44 13
      src/civetweb.c

+ 44 - 13
src/civetweb.c

@@ -1737,6 +1737,7 @@ enum {
 	LISTENING_PORTS,
 	DOCUMENT_ROOT,
 	SSL_CERTIFICATE,
+	SSL_CERTIFICATE_CHAIN,
 	NUM_THREADS,
 	RUN_AS_USER,
 	REWRITE,
@@ -1825,6 +1826,7 @@ static struct mg_option config_options[] = {
     {"listening_ports", CONFIG_TYPE_STRING, "8080"},
     {"document_root", CONFIG_TYPE_DIRECTORY, NULL},
     {"ssl_certificate", CONFIG_TYPE_FILE, NULL},
+    {"ssl_certificate_chain", CONFIG_TYPE_FILE, NULL},
     {"num_threads", CONFIG_TYPE_NUMBER, "50"},
     {"run_as_user", CONFIG_TYPE_STRING, NULL},
     {"url_rewrite_patterns", CONFIG_TYPE_STRING, NULL},
@@ -12227,7 +12229,8 @@ tls_dtor(void *key)
 
 #if !defined(NO_SSL)
 
-static int ssl_use_pem_file(struct mg_context *ctx, const char *pem);
+static int
+ssl_use_pem_file(struct mg_context *ctx, const char *pem, const char *chain);
 static const char *ssl_error(void);
 
 
@@ -12240,7 +12243,8 @@ refresh_trust(struct mg_connection *conn)
 
 	struct stat cert_buf;
 	long int t;
-	char *pem;
+	const char *pem;
+	const char *chain;
 	int should_verify_peer;
 
 	if ((pem = conn->ctx->config[SSL_CERTIFICATE]) == NULL) {
@@ -12248,6 +12252,13 @@ refresh_trust(struct mg_connection *conn)
 		 * refresh_trust still can not work. */
 		return 0;
 	}
+	chain = conn->ctx->config[SSL_CERTIFICATE_CHAIN];
+	if (chain == NULL) {
+		chain = pem;
+	}
+	if (*chain == 0) {
+		chain = NULL;
+	}
 
 	t = data_check;
 	if (stat(pem, &cert_buf) != -1) {
@@ -12280,7 +12291,7 @@ refresh_trust(struct mg_connection *conn)
 		}
 
 		if (1 == mg_atomic_inc(p_reload_lock)) {
-			if (ssl_use_pem_file(conn->ctx, pem) == 0) {
+			if (ssl_use_pem_file(conn->ctx, pem, chain) == 0) {
 				return 0;
 			}
 			*p_reload_lock = 0;
@@ -12691,7 +12702,7 @@ initialize_ssl(char *ebuf, size_t ebuf_len)
 
 
 static int
-ssl_use_pem_file(struct mg_context *ctx, const char *pem)
+ssl_use_pem_file(struct mg_context *ctx, const char *pem, const char *chain)
 {
 	if (SSL_CTX_use_certificate_file(ctx->ssl_ctx, pem, 1) == 0) {
 		mg_cry(fc(ctx),
@@ -12720,13 +12731,23 @@ ssl_use_pem_file(struct mg_context *ctx, const char *pem)
 		return 0;
 	}
 
-	if (SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem) == 0) {
-		mg_cry(fc(ctx),
-		       "%s: cannot use certificate chain file %s: %s",
-		       __func__,
-		       pem,
-		       ssl_error());
-		return 0;
+	/* In contrast to OpenSSL, wolfSSL does not support certificate
+	 * chain files that contain private keys and certificates in
+	 * SSL_CTX_use_certificate_chain_file.
+	 * The CivetWeb-Server used pem-Files that contained both information.
+	 * In order to make wolfSSL work, it is split in two files.
+	 * One file that contains key and certificate used by the server and
+	 * an optional chain file for the ssl stack.
+	 */
+	if (chain) {
+		if (SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, chain) == 0) {
+			mg_cry(fc(ctx),
+			       "%s: cannot use certificate chain file %s: %s",
+			       __func__,
+			       pem,
+			       ssl_error());
+			return 0;
+		}
 	}
 	return 1;
 }
@@ -12770,6 +12791,7 @@ static int
 set_ssl_option(struct mg_context *ctx)
 {
 	const char *pem;
+	const char *chain;
 	int callback_ret;
 	int should_verify_peer;
 	const char *ca_path;
@@ -12792,6 +12814,13 @@ set_ssl_option(struct mg_context *ctx)
 	    && ctx->callbacks.init_ssl == NULL) {
 		return 1;
 	}
+	chain = ctx->config[SSL_CERTIFICATE_CHAIN];
+	if (chain == NULL) {
+		chain = pem;
+	}
+	if (*chain == 0) {
+		chain = NULL;
+	}
 
 	if (!initialize_ssl(ebuf, sizeof(ebuf))) {
 		mg_cry(fc(ctx), "%s", ebuf);
@@ -12877,7 +12906,7 @@ set_ssl_option(struct mg_context *ctx)
 	                               sizeof(ssl_context_id));
 
 	if (pem != NULL) {
-		if (!ssl_use_pem_file(ctx, pem)) {
+		if (!ssl_use_pem_file(ctx, pem, chain)) {
 			return 0;
 		}
 	}
@@ -13387,7 +13416,9 @@ mg_connect_client_impl(const struct mg_client_options *client_options,
 			 * SSL_VERIFY_PEER, verify_ssl_server); */
 
 			if (client_options->client_cert) {
-				if (!ssl_use_pem_file(&fake_ctx, client_options->client_cert)) {
+				if (!ssl_use_pem_file(&fake_ctx,
+				                      client_options->client_cert,
+				                      NULL)) {
 					mg_snprintf(NULL,
 					            NULL, /* No truncation check for ebuf */
 					            ebuf,