Browse Source

Change authorization handlers to a separate type

Neil Jensen 9 years ago
parent
commit
ed9ae22a65
3 changed files with 135 additions and 81 deletions
  1. 1 1
      include/CivetServer.h
  2. 15 1
      include/civetweb.h
  3. 119 79
      src/civetweb.c

+ 1 - 1
include/CivetServer.h

@@ -113,7 +113,7 @@ class CIVETWEB_API CivetAuthHandler
 
 	/**
 	 * Callback method for authorization requests. It is up the this handler
-	 * to generate authorization requests.
+	 * to generate 401 responses if authorization fails.
 	 *
 	 * @param server - the calling server
 	 * @param conn - the connection information

+ 15 - 1
include/civetweb.h

@@ -334,13 +334,27 @@ mg_set_websocket_handler(struct mg_context *ctx,
                          mg_websocket_close_handler close_handler,
                          void *cbdata);
 
+/* mg_authorization_handler
+
+   Some description here
+
+   Parameters:
+      conn: current connection information.
+      cbdata: the callback data configured with mg_set_request_handler().
+   Returns:
+      0: access denied
+      1: access granted
+ */
+typedef int (*mg_authorization_handler)(struct mg_connection *conn,
+                                        void *cbdata);
+
 /* mg_set_auth_handler
 
    Sets or removes a URI mapping for an authorization handler.
    This function works similar to mg_set_request_handler - see there. */
 CIVETWEB_API void mg_set_auth_handler(struct mg_context *ctx,
                                       const char *uri,
-                                      mg_request_handler handler,
+                                      mg_authorization_handler handler,
                                       void *cbdata);
 
 /* Get the value of particular configuration parameter.

+ 119 - 79
src/civetweb.c

@@ -1136,15 +1136,14 @@ mg_static_assert((sizeof(config_options) / sizeof(config_options[0]))
                      == (NUM_OPTIONS + 1),
                  "config_options and enum not sync");
 
-enum { REQUEST_HANDLER, WEBSOCKET_HANDLER, AUTH_HANDLER, NUM_HANDLERS };
+enum { REQUEST_HANDLER, WEBSOCKET_HANDLER, AUTH_HANDLER };
 
-struct mg_request_handler_info {
+struct mg_handler_info {
 	/* Name/Pattern of the URI. */
 	char *uri;
 	size_t uri_len;
 
-	/* handler type: ws/wss (websocket) or http/https (web page) or
-	 * authorization. */
+	/* handler type */
 	int handler_type;
 
 	/* Handler for http/https or authorization requests. */
@@ -1156,11 +1155,14 @@ struct mg_request_handler_info {
 	mg_websocket_data_handler data_handler;
 	mg_websocket_close_handler close_handler;
 
+	/* Handler for authorization requests */
+	mg_authorization_handler auth_handler;
+
 	/* User supplied argument for the handler function. */
 	void *cbdata;
 
-	/* next request handler in a linked list */
-	struct mg_request_handler_info *next;
+	/* next handler in a linked list */
+	struct mg_handler_info *next;
 };
 
 struct mg_context {
@@ -1198,7 +1200,7 @@ struct mg_context {
 	char *systemName; /* What operating system is running */
 
 	/* linked list of uri handlers */
-	struct mg_request_handler_info *request_handlers;
+	struct mg_handler_info *handlers;
 
 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
 	/* linked list of shared lua websockets */
@@ -9032,27 +9034,28 @@ redirect_to_https_port(struct mg_connection *conn, int ssl_index)
 
 
 static void
-mg_set_request_handler_type(struct mg_context *ctx,
-                            const char *uri,
-                            int handler_type,
-                            int is_delete_request,
-                            mg_request_handler handler,
-                            mg_websocket_connect_handler connect_handler,
-                            mg_websocket_ready_handler ready_handler,
-                            mg_websocket_data_handler data_handler,
-                            mg_websocket_close_handler close_handler,
-                            void *cbdata)
-{
-	struct mg_request_handler_info *tmp_rh, **lastref;
+mg_set_handler_type(struct mg_context *ctx,
+                    const char *uri,
+                    int handler_type,
+                    int is_delete_request,
+                    mg_request_handler handler,
+                    mg_websocket_connect_handler connect_handler,
+                    mg_websocket_ready_handler ready_handler,
+                    mg_websocket_data_handler data_handler,
+                    mg_websocket_close_handler close_handler,
+                    mg_authorization_handler auth_handler,
+                    void *cbdata)
+{
+	struct mg_handler_info *tmp_rh, **lastref;
 	size_t urilen = strlen(uri);
-	int is_websocket_handler = (handler_type == WEBSOCKET_HANDLER);
 
-	if (is_websocket_handler) {
+	if (handler_type == WEBSOCKET_HANDLER) {
 		/* assert(handler == NULL); */
 		/* assert(is_delete_request || connect_handler!=NULL ||
 		 *        ready_handler!=NULL || data_handler!=NULL ||
 		 *        close_handler!=NULL);
 		 */
+		/* assert(auth_handler == NULL); */
 		if (handler != NULL) {
 			return;
 		}
@@ -9062,11 +9065,15 @@ mg_set_request_handler_type(struct mg_context *ctx,
 		    && close_handler == NULL) {
 			return;
 		}
-	} else {
+		if (auth_handler != NULL) {
+			return;
+		}
+	} else if (handler_type == REQUEST_HANDLER) {
 		/* assert(connect_handler==NULL && ready_handler==NULL &&
 		 *        data_handler==NULL && close_handler==NULL); */
 		/* assert(is_delete_request || (handler!=NULL));
 		 */
+		/* assert(auth_handler == NULL); */
 		if (connect_handler != NULL || ready_handler != NULL
 		    || data_handler != NULL
 		    || close_handler != NULL) {
@@ -9075,6 +9082,25 @@ mg_set_request_handler_type(struct mg_context *ctx,
 		if (!is_delete_request && (handler == NULL)) {
 			return;
 		}
+		if (auth_handler != NULL) {
+			return;
+		}
+	} else { /* AUTH_HANDLER */
+		     /* assert(handler == NULL); */
+		     /* assert(connect_handler==NULL && ready_handler==NULL &&
+		      *        data_handler==NULL && close_handler==NULL); */
+		/* assert(auth_handler != NULL); */
+		if (handler != NULL) {
+			return;
+		}
+		if (connect_handler != NULL || ready_handler != NULL
+		    || data_handler != NULL
+		    || close_handler != NULL) {
+			return;
+		}
+		if (!is_delete_request && (auth_handler == NULL)) {
+			return;
+		}
 	}
 
 	if (!ctx) {
@@ -9084,20 +9110,21 @@ mg_set_request_handler_type(struct mg_context *ctx,
 	mg_lock_context(ctx);
 
 	/* first try to find an existing handler */
-	lastref = &(ctx->request_handlers);
-	for (tmp_rh = ctx->request_handlers; tmp_rh != NULL;
-	     tmp_rh = tmp_rh->next) {
+	lastref = &(ctx->handlers);
+	for (tmp_rh = ctx->handlers; tmp_rh != NULL; tmp_rh = tmp_rh->next) {
 		if (tmp_rh->handler_type == handler_type) {
 			if (urilen == tmp_rh->uri_len && !strcmp(tmp_rh->uri, uri)) {
 				if (!is_delete_request) {
 					/* update existing handler */
-					if (!is_websocket_handler) {
+					if (handler_type == REQUEST_HANDLER) {
 						tmp_rh->handler = handler;
-					} else {
+					} else if (handler_type == WEBSOCKET_HANDLER) {
 						tmp_rh->connect_handler = connect_handler;
 						tmp_rh->ready_handler = ready_handler;
 						tmp_rh->data_handler = data_handler;
 						tmp_rh->close_handler = close_handler;
+					} else { /* AUTH_HANDLER */
+						tmp_rh->auth_handler = auth_handler;
 					}
 					tmp_rh->cbdata = cbdata;
 				} else {
@@ -9120,8 +9147,8 @@ mg_set_request_handler_type(struct mg_context *ctx,
 		return;
 	}
 
-	tmp_rh = (struct mg_request_handler_info *)
-	    mg_calloc(sizeof(struct mg_request_handler_info), 1);
+	tmp_rh =
+	    (struct mg_handler_info *)mg_calloc(sizeof(struct mg_handler_info), 1);
 	if (tmp_rh == NULL) {
 		mg_unlock_context(ctx);
 		mg_cry(fc(ctx), "%s", "Cannot create new request handler struct, OOM");
@@ -9135,13 +9162,15 @@ mg_set_request_handler_type(struct mg_context *ctx,
 		return;
 	}
 	tmp_rh->uri_len = urilen;
-	if (!is_websocket_handler) {
+	if (handler_type == REQUEST_HANDLER) {
 		tmp_rh->handler = handler;
-	} else {
+	} else if (handler_type == WEBSOCKET_HANDLER) {
 		tmp_rh->connect_handler = connect_handler;
 		tmp_rh->ready_handler = ready_handler;
 		tmp_rh->data_handler = data_handler;
 		tmp_rh->close_handler = close_handler;
+	} else { /* AUTH_HANDLER */
+		tmp_rh->auth_handler = auth_handler;
 	}
 	tmp_rh->cbdata = cbdata;
 	tmp_rh->handler_type = handler_type;
@@ -9158,16 +9187,17 @@ mg_set_request_handler(struct mg_context *ctx,
                        mg_request_handler handler,
                        void *cbdata)
 {
-	mg_set_request_handler_type(ctx,
-	                            uri,
-	                            REQUEST_HANDLER,
-	                            handler == NULL,
-	                            handler,
-	                            NULL,
-	                            NULL,
-	                            NULL,
-	                            NULL,
-	                            cbdata);
+	mg_set_handler_type(ctx,
+	                    uri,
+	                    REQUEST_HANDLER,
+	                    handler == NULL,
+	                    handler,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    cbdata);
 }
 
 
@@ -9183,16 +9213,17 @@ mg_set_websocket_handler(struct mg_context *ctx,
 	int is_delete_request = (connect_handler == NULL) && (ready_handler == NULL)
 	                        && (data_handler == NULL)
 	                        && (close_handler == NULL);
-	mg_set_request_handler_type(ctx,
-	                            uri,
-	                            WEBSOCKET_HANDLER,
-	                            is_delete_request,
-	                            NULL,
-	                            connect_handler,
-	                            ready_handler,
-	                            data_handler,
-	                            close_handler,
-	                            cbdata);
+	mg_set_handler_type(ctx,
+	                    uri,
+	                    WEBSOCKET_HANDLER,
+	                    is_delete_request,
+	                    NULL,
+	                    connect_handler,
+	                    ready_handler,
+	                    data_handler,
+	                    close_handler,
+	                    NULL,
+	                    cbdata);
 }
 
 void
@@ -9201,16 +9232,17 @@ mg_set_auth_handler(struct mg_context *ctx,
                     mg_request_handler handler,
                     void *cbdata)
 {
-	mg_set_request_handler_type(ctx,
-	                            uri,
-	                            AUTH_HANDLER,
-	                            handler == NULL,
-	                            handler,
-	                            NULL,
-	                            NULL,
-	                            NULL,
-	                            NULL,
-	                            cbdata);
+	mg_set_handler_type(ctx,
+	                    uri,
+	                    AUTH_HANDLER,
+	                    handler == NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    NULL,
+	                    handler,
+	                    cbdata);
 }
 
 static int
@@ -9221,14 +9253,14 @@ get_request_handler(struct mg_connection *conn,
                     mg_websocket_ready_handler *ready_handler,
                     mg_websocket_data_handler *data_handler,
                     mg_websocket_close_handler *close_handler,
+                    mg_authorization_handler *auth_handler,
                     void **cbdata)
 {
 	const struct mg_request_info *request_info = mg_get_request_info(conn);
 	if (request_info) {
 		const char *uri = request_info->local_uri;
 		size_t urilen = strlen(uri);
-		struct mg_request_handler_info *tmp_rh;
-		int is_websocket_request = (handler_type == WEBSOCKET_HANDLER);
+		struct mg_handler_info *tmp_rh;
 
 		if (!conn || !conn->ctx) {
 			return 0;
@@ -9237,17 +9269,19 @@ get_request_handler(struct mg_connection *conn,
 		mg_lock_context(conn->ctx);
 
 		/* first try for an exact match */
-		for (tmp_rh = conn->ctx->request_handlers; tmp_rh != NULL;
+		for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
 		     tmp_rh = tmp_rh->next) {
 			if (tmp_rh->handler_type == handler_type) {
 				if (urilen == tmp_rh->uri_len && !strcmp(tmp_rh->uri, uri)) {
-					if (is_websocket_request) {
+					if (handler_type == WEBSOCKET_HANDLER) {
 						*connect_handler = tmp_rh->connect_handler;
 						*ready_handler = tmp_rh->ready_handler;
 						*data_handler = tmp_rh->data_handler;
 						*close_handler = tmp_rh->close_handler;
-					} else {
+					} else if (handler_type == REQUEST_HANDLER) {
 						*handler = tmp_rh->handler;
+					} else { /* AUTH_HANDLER */
+						*auth_handler = tmp_rh->auth_handler;
 					}
 					*cbdata = tmp_rh->cbdata;
 					mg_unlock_context(conn->ctx);
@@ -9257,18 +9291,20 @@ get_request_handler(struct mg_connection *conn,
 		}
 
 		/* next try for a partial match, we will accept uri/something */
-		for (tmp_rh = conn->ctx->request_handlers; tmp_rh != NULL;
+		for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
 		     tmp_rh = tmp_rh->next) {
 			if (tmp_rh->handler_type == handler_type) {
 				if (tmp_rh->uri_len < urilen && uri[tmp_rh->uri_len] == '/'
 				    && memcmp(tmp_rh->uri, uri, tmp_rh->uri_len) == 0) {
-					if (is_websocket_request) {
+					if (handler_type == WEBSOCKET_HANDLER) {
 						*connect_handler = tmp_rh->connect_handler;
 						*ready_handler = tmp_rh->ready_handler;
 						*data_handler = tmp_rh->data_handler;
 						*close_handler = tmp_rh->close_handler;
-					} else {
+					} else if (handler_type == REQUEST_HANDLER) {
 						*handler = tmp_rh->handler;
+					} else { /* AUTH_HANDLER */
+						*auth_handler = tmp_rh->auth_handler;
 					}
 					*cbdata = tmp_rh->cbdata;
 					mg_unlock_context(conn->ctx);
@@ -9278,17 +9314,19 @@ get_request_handler(struct mg_connection *conn,
 		}
 
 		/* finally try for pattern match */
-		for (tmp_rh = conn->ctx->request_handlers; tmp_rh != NULL;
+		for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
 		     tmp_rh = tmp_rh->next) {
 			if (tmp_rh->handler_type == handler_type) {
 				if (match_prefix(tmp_rh->uri, tmp_rh->uri_len, uri) > 0) {
-					if (is_websocket_request) {
+					if (handler_type == WEBSOCKET_HANDLER) {
 						*connect_handler = tmp_rh->connect_handler;
 						*ready_handler = tmp_rh->ready_handler;
 						*data_handler = tmp_rh->data_handler;
 						*close_handler = tmp_rh->close_handler;
-					} else {
+					} else if (handler_type == REQUEST_HANDLER) {
 						*handler = tmp_rh->handler;
+					} else { /* AUTH_HANDLER */
+						*auth_handler = tmp_rh->auth_handler;
 					}
 					*cbdata = tmp_rh->cbdata;
 					mg_unlock_context(conn->ctx);
@@ -9365,7 +9403,7 @@ handle_request(struct mg_connection *conn)
 		mg_websocket_data_handler ws_data_handler = NULL;
 		mg_websocket_close_handler ws_close_handler = NULL;
 		void *callback_data = NULL;
-		mg_request_handler auth_handler = NULL;
+		mg_authorization_handler auth_handler = NULL;
 		void *auth_callback_data = NULL;
 #if !defined(NO_FILES)
 		time_t curtime = time(NULL);
@@ -9457,6 +9495,7 @@ handle_request(struct mg_connection *conn)
 		                        &ws_ready_handler,
 		                        &ws_data_handler,
 		                        &ws_close_handler,
+		                        NULL,
 		                        &callback_data)) {
 			/* 5.2.1. A callback will handle this request. All requests handled
 			 * by a callback have to be considered as requests to a script
@@ -9484,11 +9523,12 @@ handle_request(struct mg_connection *conn)
 		/* 6.1. a custom authorization handler is installed */
 		if (get_request_handler(conn,
 		                        AUTH_HANDLER,
-		                        &auth_handler,
 		                        NULL,
 		                        NULL,
 		                        NULL,
 		                        NULL,
+		                        NULL,
+		                        &auth_handler,
 		                        &auth_callback_data)) {
 			if (!auth_handler(conn, auth_callback_data)) {
 				return;
@@ -12047,7 +12087,7 @@ static void
 free_context(struct mg_context *ctx)
 {
 	int i;
-	struct mg_request_handler_info *tmp_rh;
+	struct mg_handler_info *tmp_rh;
 
 	if (ctx == NULL) {
 		return;
@@ -12082,9 +12122,9 @@ free_context(struct mg_context *ctx)
 	}
 
 	/* Deallocate request handlers */
-	while (ctx->request_handlers) {
-		tmp_rh = ctx->request_handlers;
-		ctx->request_handlers = tmp_rh->next;
+	while (ctx->handlers) {
+		tmp_rh = ctx->handlers;
+		ctx->handlers = tmp_rh->next;
 		mg_free(tmp_rh->uri);
 		mg_free(tmp_rh);
 	}
@@ -12278,7 +12318,7 @@ mg_start(const struct mg_callbacks *callbacks,
 		ctx->callbacks.exit_context = 0;
 	}
 	ctx->user_data = user_data;
-	ctx->request_handlers = NULL;
+	ctx->handlers = NULL;
 
 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
 	ctx->shared_lua_websockets = 0;