Browse Source

Merge pull request #975 from DL6ER/tweak/local_uri_raw

Add dedicated raw (local) URI variable
bel2125 4 years ago
parent
commit
a02c529c9c
3 changed files with 43 additions and 14 deletions
  1. 5 1
      include/civetweb.h
  2. 37 13
      src/civetweb.c
  3. 1 0
      src/mod_lua.inl

+ 5 - 1
include/civetweb.h

@@ -151,9 +151,13 @@ struct mg_request_info {
 	const char *request_method;  /* "GET", "POST", etc */
 	const char *request_uri;     /* URL-decoded URI (absolute or relative,
 	                              * as in the request) */
-	const char *local_uri;       /* URL-decoded URI (relative). Can be NULL
+	const char *local_uri_raw;   /* URL-decoded URI (relative). Can be NULL
 	                              * if the request_uri does not address a
 	                              * resource at the server host. */
+	char *local_uri;             /* Same as local_uri_raw, however, cleaned
+	                              * so a path like
+	                              *   allowed_dir/../forbidden_file
+	                              * is not possible */
 #if defined(MG_LEGACY_INTERFACE) /* 2017-02-04, deprecated 2014-09-14 */
 	const char *uri;             /* Deprecated: use local_uri instead */
 #endif

+ 37 - 13
src/civetweb.c

@@ -3677,8 +3677,9 @@ mg_get_request_info(const struct mg_connection *conn)
 		}
 
 		((struct mg_connection *)conn)->request_info.local_uri =
-		    ((struct mg_connection *)conn)->request_info.request_uri =
-		        tls->txtbuf; /* use thread safe buffer */
+		    ((struct mg_connection *)conn)->request_info.local_uri_raw =
+		        ((struct mg_connection *)conn)->request_info.request_uri =
+		            tls->txtbuf; /* use thread safe buffer */
 
 		((struct mg_connection *)conn)->request_info.num_headers =
 		    conn->response_info.num_headers;
@@ -11131,6 +11132,7 @@ prepare_cgi_environment(struct mg_connection *conn,
 
 	addenv(env, "REQUEST_URI=%s", conn->request_info.request_uri);
 	addenv(env, "LOCAL_URI=%s", conn->request_info.local_uri);
+	addenv(env, "LOCAL_URI_RAW=%s", conn->request_info.local_uri_raw);
 
 	/* SCRIPT_NAME */
 	uri_len = (int)strlen(conn->request_info.local_uri);
@@ -14084,9 +14086,14 @@ handle_request(struct mg_connection *conn)
 		}
 	}
 
-	/* 1.4. clean URIs, so a path like allowed_dir/../forbidden_file is
-	 * not possible */
-	remove_dot_segments((char *)ri->local_uri);
+	/* 1.4. clean URIs, so a path like allowed_dir/../forbidden_file is not
+	 * possible. The fact that we cleaned the URI is stored in that the
+	 * pointer to ri->local_ur and ri->local_uri_raw are now different.
+	 * ri->local_uri_raw still points to memory allocated in
+	 * worker_thread_run(). ri->local_uri is private to the request so we
+	 * don't have to use preallocated memory here. */
+	ri->local_uri = mg_strdup(ri->local_uri_raw);
+	remove_dot_segments(ri->local_uri);
 
 	/* step 1. completed, the url is known now */
 	uri_len = (int)strlen(ri->local_uri);
@@ -16814,6 +16821,13 @@ reset_per_request_attributes(struct mg_connection *conn)
 	conn->request_info.remote_user = NULL;
 	conn->request_info.request_method = NULL;
 	conn->request_info.request_uri = NULL;
+
+	/* Free cleaned local URI (if any) */
+	if(conn->request_info.local_uri != conn->request_info.local_uri_raw)
+	{
+		mg_free(conn->request_info.local_uri);
+		conn->request_info.local_uri = NULL;
+	}
 	conn->request_info.local_uri = NULL;
 
 #if defined(MG_LEGACY_INTERFACE)
@@ -17907,7 +17921,8 @@ mg_get_response(struct mg_connection *conn,
 	 *       2) here, ri.uri is the http response code */
 	conn->request_info.uri = conn->request_info.request_uri;
 #endif
-	conn->request_info.local_uri = conn->request_info.request_uri;
+	conn->request_info.local_uri_raw = conn->request_info.request_uri;
+	conn->request_info.local_uri = (char*)conn->request_info.local_uri_raw;
 
 	/* TODO (mid): Define proper return values - maybe return length?
 	 * For the first test use <0 for error and >0 for OK */
@@ -17957,7 +17972,7 @@ mg_download(const char *host,
 			 *       2) here, ri.uri is the http response code */
 			conn->request_info.uri = conn->request_info.request_uri;
 #endif
-			conn->request_info.local_uri = conn->request_info.request_uri;
+			conn->request_info.local_uri = (char*)conn->request_info.request_uri;
 		}
 	}
 
@@ -18166,7 +18181,8 @@ mg_connect_websocket_client_impl(const struct mg_client_options *client_options,
 		mg_close_connection(conn);
 		return NULL;
 	}
-	conn->request_info.local_uri = conn->request_info.request_uri;
+	conn->request_info.local_uri_raw = conn->request_info.request_uri;
+	conn->request_info.local_uri = (char*)conn->request_info.local_uri_raw;
 
 #if defined(__clang__)
 #pragma clang diagnostic pop
@@ -18457,12 +18473,12 @@ process_new_connection(struct mg_connection *conn)
 			switch (uri_type) {
 			case 1:
 				/* Asterisk */
-				conn->request_info.local_uri = 0;
+				conn->request_info.local_uri_raw = 0;
 				/* TODO: Deal with '*'. */
 				break;
 			case 2:
 				/* relative uri */
-				conn->request_info.local_uri = conn->request_info.request_uri;
+				conn->request_info.local_uri_raw = conn->request_info.request_uri;
 				break;
 			case 3:
 			case 4:
@@ -18470,9 +18486,9 @@ process_new_connection(struct mg_connection *conn)
 				hostend = get_rel_url_at_current_server(
 				    conn->request_info.request_uri, conn);
 				if (hostend) {
-					conn->request_info.local_uri = hostend;
+					conn->request_info.local_uri_raw = hostend;
 				} else {
-					conn->request_info.local_uri = NULL;
+					conn->request_info.local_uri_raw = NULL;
 				}
 				break;
 			default:
@@ -18482,9 +18498,10 @@ process_new_connection(struct mg_connection *conn)
 				            sizeof(ebuf),
 				            "Invalid URI");
 				mg_send_http_error(conn, 400, "%s", ebuf);
-				conn->request_info.local_uri = NULL;
+				conn->request_info.local_uri_raw = NULL;
 				break;
 			}
+			conn->request_info.local_uri = (char*)conn->request_info.local_uri_raw;
 
 #if defined(MG_LEGACY_INTERFACE)
 			/* Legacy before split into local_uri and request_uri */
@@ -18973,6 +18990,13 @@ worker_thread_run(struct mg_connection *conn)
 	mg_free(conn->buf);
 	conn->buf = NULL;
 
+	/* Free cleaned URI (if any) */
+	if(conn->request_info.local_uri != conn->request_info.local_uri_raw)
+	{
+		mg_free(conn->request_info.local_uri);
+		conn->request_info.local_uri = NULL;
+	}
+
 #if defined(USE_SERVER_STATS)
 	conn->conn_state = 9; /* done */
 #endif

+ 1 - 0
src/mod_lua.inl

@@ -2469,6 +2469,7 @@ prepare_lua_request_info(struct mg_connection *conn, lua_State *L)
 	reg_string(L, "request_method", conn->request_info.request_method);
 	reg_string(L, "request_uri", conn->request_info.request_uri);
 	reg_string(L, "uri", conn->request_info.local_uri);
+	reg_string(L, "uri_raw", conn->request_info.local_uri_raw);
 	reg_string(L, "http_version", conn->request_info.http_version);
 	reg_string(L, "query_string", conn->request_info.query_string);
 	reg_string(L, "remote_addr", conn->request_info.remote_addr);