Explorar o código

Added server_domain parameter to an external_ssl_domain callback

Drew Wells %!s(int64=5) %!d(string=hai) anos
pai
achega
b0dfc92861
Modificáronse 3 ficheiros con 49 adicións e 9 borrados
  1. 3 1
      docs/api/mg_callbacks.md
  2. 17 2
      include/civetweb.h
  3. 29 6
      src/civetweb.c

+ 3 - 1
docs/api/mg_callbacks.md

@@ -20,8 +20,10 @@
 | |The callback function `init_context()` is called after the CivetWeb server has been started and initialized, but before any requests are served. This allowes the application to perform some initialization activities before the first requests are handled.|
 |**`init_lua`**|**`void (*init_lua)( const struct mg_connection *conn, void *lua_context );`**|
 | |The callback function `init_lua()` is called just before a Lua server page is to be served. Lua page serving must have been enabled at compile time for this callback function to be called. The parameter `lua_context` is a `lua_State *` pointer.|
-|**`external_ssl_ctx`**|**`int (*external_ssl_ctx)(void **ssl_ctx, void *user_data);`**|
+|**`external_ssl_ctx`**|**`int (*external_ssl_ctx)( void **ssl_ctx, void *user_data );`**|
 | |The callback function `external_ssl_ctx()` is called when civetweb is about to create (`*ssl_ctx` is `NULL`) or free (`*ssl_ctx` is not `NULL`) a SSL context. The parameter `user_data` contains a pointer to the data which was provided to `mg_start()` when the server was started. The callback function can return 0 to signal that CivetWeb should setup the SSL context. With a return value of 1 the callback function signals CivetWeb that the SSL context has already been setup and no further processing is necessary. Also with a return value of 1 other callback functions `init_ssl()` and `init_ssl_domain()` are not called. The value -1 should be returned when the SSL context initialization fails.|
+|**`external_ssl_ctx_domain`**|**`int (*external_ssl_ctx_domain)( const char *server_domain, void **ssl_ctx, void *user_data );`**|
+| |The callback function `external_ssl_ctx_domain()` is called when civetweb is about to create (`*ssl_ctx` is `NULL`) or free (`*ssl_ctx` is not `NULL`) a SSL context. The parameter `server_domain` is a pointer to the `authentication_domain` config parameter of the domain being created or freed. The parameter `user_data` contains a pointer to the data which was provided to `mg_start()` when the server was started. The callback function can return 0 to signal that CivetWeb should setup the SSL context. With a return value of 1 the callback function signals CivetWeb that the SSL context has already been setup and no further processing is necessary. Also with a return value of 1 other callback functions `init_ssl()` and `init_ssl_domain()` are not called. The value -1 should be returned when the SSL context initialization fails.|
 |**`init_ssl`**|**`int (*init_ssl)( void *ssl_ctx, void *user_data );`**|
 | |The callback function `init_ssl()` is called when CivetWeb initializes the SSL library. The `ssl_ctx` parameter is a pointer to the SSL context being configure. The parameter `user_data` contains a pointer to the data which was provided to `mg_start()` when the server was started. The callback function can return 0 to signal that CivetWeb should setup the SSL certificate. With a return value of 1 the callback function signals CivetWeb that the certificate has already been setup and no further processing is necessary. The value -1 should be returned when the SSL initialization fails.|
 |**`init_ssl_domain`**|**`int (*init_ssl_domain)( const char *server_domain, void *ssl_ctx, void *user_data );`**|

+ 17 - 2
include/civetweb.h

@@ -268,8 +268,8 @@ struct mg_callbacks {
 
 	/* Called when civetweb is about to create or free a SSL_CTX.
 	Parameters:
-	   ssl_ctx: SSL_CTX pointer. NULL at creation time, Not NULL when mg_context
-	            will be freed
+	     ssl_ctx: SSL_CTX pointer. NULL at creation time, Not NULL when mg_context
+	              will be freed
 	     user_data: parameter user_data passed when starting the server.
 	   Return value:
 	     0: civetweb will continue to create the context, just as if the
@@ -280,6 +280,21 @@ struct mg_callbacks {
 	    -1: initializing ssl fails.*/
 	int (*external_ssl_ctx)(void **ssl_ctx, void *user_data);
 
+	/* Called when civetweb is about to create or free a SSL_CTX for a domain.
+	Parameters:
+	     server_domain: authentication_domain from the domain config.
+	     ssl_ctx: SSL_CTX pointer. NULL at creation time, Not NULL when mg_context
+	              will be freed
+	     user_data: parameter user_data passed when starting the server.
+	   Return value:
+	     0: civetweb will continue to create the context, just as if the
+	        callback would not be present.
+	        The value in *ssl_ctx when the function returns is ignored.
+	     1: civetweb will copy the value from *ssl_ctx to the civetweb context
+	        and doesn't create its own.
+	    -1: initializing ssl fails.*/
+	int (*external_ssl_ctx_domain)(const char *server_domain, void **ssl_ctx, void *user_data);
+
 #if defined(MG_LEGACY_INTERFACE) /* 2015-08-19 */
 	/* Called when websocket request is received, before websocket handshake.
 	   Return value:

+ 29 - 6
src/civetweb.c

@@ -15092,7 +15092,7 @@ refresh_trust(struct mg_connection *conn)
 	int should_verify_peer;
 
 	if ((pem = conn->dom_ctx->config[SSL_CERTIFICATE]) == NULL) {
-		/* If peem is NULL and conn->phys_ctx->callbacks.init_ssl is not,
+		/* If pem is NULL and conn->phys_ctx->callbacks.init_ssl is not,
 		 * refresh_trust still can not work. */
 		return 0;
 	}
@@ -16106,14 +16106,37 @@ init_ssl_ctx(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx)
 		}
 		return 1;
 	}
-	/* else: external_ssl_ctx does not exist or returns 0,
+
+	/* Check for external domain SSL_CTX */
+	callback_ret =
+	    (phys_ctx->callbacks.external_ssl_ctx_domain == NULL)
+	        ? 0
+	        : (phys_ctx->callbacks.external_ssl_ctx_domain(dom_ctx->config[AUTHENTICATION_DOMAIN],
+	                                                       &ssl_ctx,
+	                                                       phys_ctx->user_data));
+
+	if (callback_ret < 0) {
+		mg_cry_ctx_internal(phys_ctx,
+		                    "external_ssl_ctx_domain callback returned error: %i",
+		                    callback_ret);
+		return 0;
+	} else if (callback_ret > 0) {
+		dom_ctx->ssl_ctx = (SSL_CTX *)ssl_ctx;
+		if (!initialize_ssl(ebuf, sizeof(ebuf))) {
+			mg_cry_ctx_internal(phys_ctx, "%s", ebuf);
+			return 0;
+		}
+		return 1;
+	}
+	/* else: external_ssl_ctx/external_ssl_ctx_domain do not exist or return 0,
 	 * CivetWeb should continue initializing SSL */
 
-	/* If PEM file is not specified and the init_ssl callback
-	 * is not specified, setup will fail. */
+	/* If PEM file is not specified and the init_ssl callbacks
+	 * are not specified, setup will fail. */
 	if (((pem = dom_ctx->config[SSL_CERTIFICATE]) == NULL)
-	    && (phys_ctx->callbacks.init_ssl == NULL)) {
-		/* No certificate and no callback:
+	    && (phys_ctx->callbacks.init_ssl == NULL)
+	    && (phys_ctx->callbacks.init_ssl_domain == NULL)) {
+		/* No certificate and no init_ssl callbacks:
 		 * Essential data to set up TLS is missing.
 		 */
 		mg_cry_ctx_internal(phys_ctx,