chore: update c, h files
This commit is contained in:
parent
fed98080d6
commit
685cfdff80
@ -10,6 +10,14 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Version 0.10.0 - 2026-01-06
|
||||||
|
|
||||||
|
update c, h files
|
||||||
|
|
||||||
|
**Changes:** 4 files, 145 lines
|
||||||
|
**Languages:** C (145 lines)
|
||||||
|
|
||||||
## Version 0.9.0 - 2026-01-01
|
## Version 0.9.0 - 2026-01-01
|
||||||
|
|
||||||
update c files
|
update c files
|
||||||
|
|||||||
@ -776,14 +776,12 @@ static void handle_client_read(connection_t *conn) {
|
|||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
conn->request_start_time = ts.tv_sec + ts.tv_nsec / 1e9;
|
conn->request_start_time = ts.tv_sec + ts.tv_nsec / 1e9;
|
||||||
|
|
||||||
#define DASHBOARD_PATH "/rproxy/dashboard"
|
if (http_uri_is_internal_route(conn->request.uri)) {
|
||||||
#define STATS_PATH "/rproxy/api/stats"
|
char normalized_uri[2048];
|
||||||
|
http_normalize_uri_path(conn->request.uri, normalized_uri, sizeof(normalized_uri));
|
||||||
|
|
||||||
if (strncmp(conn->request.uri, DASHBOARD_PATH, sizeof(DASHBOARD_PATH) - 1) == 0 ||
|
log_info("[ROUTING-INTERNAL] Serving internal route %s (normalized: %s) for fd=%d",
|
||||||
strncmp(conn->request.uri, STATS_PATH, sizeof(STATS_PATH) - 1) == 0) {
|
conn->request.uri, normalized_uri, conn->fd);
|
||||||
|
|
||||||
log_info("[ROUTING-INTERNAL] Serving internal route %s for fd=%d",
|
|
||||||
conn->request.uri, conn->fd);
|
|
||||||
|
|
||||||
if (conn->pair) {
|
if (conn->pair) {
|
||||||
connection_close(conn->pair->fd);
|
connection_close(conn->pair->fd);
|
||||||
@ -791,10 +789,14 @@ static void handle_client_read(connection_t *conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
conn->state = CLIENT_STATE_SERVING_INTERNAL;
|
conn->state = CLIENT_STATE_SERVING_INTERNAL;
|
||||||
if (strncmp(conn->request.uri, DASHBOARD_PATH, sizeof(DASHBOARD_PATH) - 1) == 0) {
|
if (strncmp(normalized_uri, "/rproxy/dashboard", 17) == 0) {
|
||||||
dashboard_serve(conn, data_start, headers_len);
|
dashboard_serve(conn, data_start, headers_len);
|
||||||
} else {
|
} else if (strncmp(normalized_uri, "/rproxy/api/stats", 17) == 0) {
|
||||||
dashboard_serve_stats_api(conn, data_start, headers_len);
|
dashboard_serve_stats_api(conn, data_start, headers_len);
|
||||||
|
} else {
|
||||||
|
connection_send_error_response(conn, 404, "Not Found", "Internal route not found.");
|
||||||
|
buffer_consume(buf, total_request_len);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_consume(buf, total_request_len);
|
buffer_consume(buf, total_request_len);
|
||||||
@ -805,9 +807,6 @@ static void handle_client_read(connection_t *conn) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef DASHBOARD_PATH
|
|
||||||
#undef STATS_PATH
|
|
||||||
|
|
||||||
route_config_t *route = config_find_route(conn->request.host);
|
route_config_t *route = config_find_route(conn->request.host);
|
||||||
if (route && route->use_auth) {
|
if (route && route->use_auth) {
|
||||||
char auth_header[1024] = "";
|
char auth_header[1024] = "";
|
||||||
|
|||||||
68
src/http.c
68
src/http.c
@ -308,3 +308,71 @@ int http_extract_status_code(const char *data, size_t len) {
|
|||||||
|
|
||||||
return (status >= 100 && status < 600) ? status : 0;
|
return (status >= 100 && status < 600) ? status : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void http_normalize_uri_path(const char *uri, char *normalized, size_t normalized_size) {
|
||||||
|
if (!uri || !normalized || normalized_size == 0) return;
|
||||||
|
|
||||||
|
size_t uri_len = strlen(uri);
|
||||||
|
size_t out_pos = 0;
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
const char *query = strchr(uri, '?');
|
||||||
|
size_t path_len = query ? (size_t)(query - uri) : uri_len;
|
||||||
|
|
||||||
|
while (i < path_len && out_pos < normalized_size - 1) {
|
||||||
|
if (uri[i] == '/') {
|
||||||
|
if (out_pos == 0 || normalized[out_pos - 1] != '/') {
|
||||||
|
normalized[out_pos++] = '/';
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (i < path_len && uri[i] == '.') {
|
||||||
|
if (i + 1 >= path_len || uri[i + 1] == '/' || uri[i + 1] == '?') {
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (uri[i + 1] == '.' && (i + 2 >= path_len || uri[i + 2] == '/' || uri[i + 2] == '?')) {
|
||||||
|
if (out_pos > 1) {
|
||||||
|
out_pos--;
|
||||||
|
while (out_pos > 0 && normalized[out_pos - 1] != '/') {
|
||||||
|
out_pos--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
normalized[out_pos++] = uri[i++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query && out_pos < normalized_size - 1) {
|
||||||
|
size_t query_len = uri_len - (query - uri);
|
||||||
|
if (out_pos + query_len >= normalized_size) {
|
||||||
|
query_len = normalized_size - out_pos - 1;
|
||||||
|
}
|
||||||
|
memcpy(normalized + out_pos, query, query_len);
|
||||||
|
out_pos += query_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
normalized[out_pos] = '\0';
|
||||||
|
|
||||||
|
if (out_pos == 0 && normalized_size > 1) {
|
||||||
|
normalized[0] = '/';
|
||||||
|
normalized[1] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int http_uri_is_internal_route(const char *uri) {
|
||||||
|
if (!uri) return 0;
|
||||||
|
|
||||||
|
char normalized[2048];
|
||||||
|
http_normalize_uri_path(uri, normalized, sizeof(normalized));
|
||||||
|
|
||||||
|
if (strncmp(normalized, "/rproxy/", 8) == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@ -13,5 +13,7 @@ int http_find_headers_end(const char *data, size_t len, size_t *headers_end);
|
|||||||
int http_rewrite_content_length(char *headers, size_t *headers_len, size_t max_len, long new_length);
|
int http_rewrite_content_length(char *headers, size_t *headers_len, size_t max_len, long new_length);
|
||||||
int http_find_header_line_bounds(const char* data, size_t len, const char* name, const char** line_start, const char** line_end);
|
int http_find_header_line_bounds(const char* data, size_t len, const char* name, const char** line_start, const char** line_end);
|
||||||
int http_extract_status_code(const char *data, size_t len);
|
int http_extract_status_code(const char *data, size_t len);
|
||||||
|
int http_uri_is_internal_route(const char *uri);
|
||||||
|
void http_normalize_uri_path(const char *uri, char *normalized, size_t normalized_size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -182,6 +182,56 @@ void test_http_malformed_requests(void) {
|
|||||||
TEST_SUITE_END();
|
TEST_SUITE_END();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_http_uri_normalization(void) {
|
||||||
|
TEST_SUITE_BEGIN("HTTP URI Path Normalization");
|
||||||
|
|
||||||
|
char normalized[256];
|
||||||
|
|
||||||
|
http_normalize_uri_path("/rproxy/dashboard", normalized, sizeof(normalized));
|
||||||
|
TEST_ASSERT_STR_EQ("/rproxy/dashboard", normalized, "Normal path unchanged");
|
||||||
|
|
||||||
|
http_normalize_uri_path("//rproxy/dashboard", normalized, sizeof(normalized));
|
||||||
|
TEST_ASSERT_STR_EQ("/rproxy/dashboard", normalized, "Double slash at start collapsed");
|
||||||
|
|
||||||
|
http_normalize_uri_path("/rproxy//dashboard", normalized, sizeof(normalized));
|
||||||
|
TEST_ASSERT_STR_EQ("/rproxy/dashboard", normalized, "Double slash in middle collapsed");
|
||||||
|
|
||||||
|
http_normalize_uri_path("/./rproxy/dashboard", normalized, sizeof(normalized));
|
||||||
|
TEST_ASSERT_STR_EQ("/rproxy/dashboard", normalized, "Dot segment at start removed");
|
||||||
|
|
||||||
|
http_normalize_uri_path("/rproxy/./dashboard", normalized, sizeof(normalized));
|
||||||
|
TEST_ASSERT_STR_EQ("/rproxy/dashboard", normalized, "Dot segment in middle removed");
|
||||||
|
|
||||||
|
http_normalize_uri_path("/foo/../rproxy/dashboard", normalized, sizeof(normalized));
|
||||||
|
TEST_ASSERT_STR_EQ("/rproxy/dashboard", normalized, "Parent reference resolved");
|
||||||
|
|
||||||
|
http_normalize_uri_path("/rproxy/dashboard?foo=bar", normalized, sizeof(normalized));
|
||||||
|
TEST_ASSERT_STR_EQ("/rproxy/dashboard?foo=bar", normalized, "Query string preserved");
|
||||||
|
|
||||||
|
http_normalize_uri_path("///rproxy///dashboard///", normalized, sizeof(normalized));
|
||||||
|
TEST_ASSERT_STR_EQ("/rproxy/dashboard/", normalized, "Multiple slashes collapsed");
|
||||||
|
|
||||||
|
TEST_SUITE_END();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_http_internal_route_detection(void) {
|
||||||
|
TEST_SUITE_BEGIN("HTTP Internal Route Detection");
|
||||||
|
|
||||||
|
TEST_ASSERT_EQ(1, http_uri_is_internal_route("/rproxy/dashboard"), "Normal dashboard path detected");
|
||||||
|
TEST_ASSERT_EQ(1, http_uri_is_internal_route("/rproxy/api/stats"), "Normal stats path detected");
|
||||||
|
TEST_ASSERT_EQ(1, http_uri_is_internal_route("//rproxy/dashboard"), "Double slash bypass detected");
|
||||||
|
TEST_ASSERT_EQ(1, http_uri_is_internal_route("/./rproxy/dashboard"), "Dot segment bypass detected");
|
||||||
|
TEST_ASSERT_EQ(1, http_uri_is_internal_route("/foo/../rproxy/dashboard"), "Parent reference bypass detected");
|
||||||
|
TEST_ASSERT_EQ(1, http_uri_is_internal_route("/rproxy//dashboard"), "Slash in path bypass detected");
|
||||||
|
TEST_ASSERT_EQ(1, http_uri_is_internal_route("/rproxy/./api/stats"), "Dot in internal path detected");
|
||||||
|
TEST_ASSERT_EQ(0, http_uri_is_internal_route("/api/data"), "Non-internal path rejected");
|
||||||
|
TEST_ASSERT_EQ(0, http_uri_is_internal_route("/"), "Root path rejected");
|
||||||
|
TEST_ASSERT_EQ(0, http_uri_is_internal_route("/rproxynotreal"), "Similar prefix rejected");
|
||||||
|
TEST_ASSERT_EQ(0, http_uri_is_internal_route(NULL), "NULL path rejected");
|
||||||
|
|
||||||
|
TEST_SUITE_END();
|
||||||
|
}
|
||||||
|
|
||||||
void run_http_tests(void) {
|
void run_http_tests(void) {
|
||||||
test_http_parse_get_request();
|
test_http_parse_get_request();
|
||||||
test_http_parse_post_request();
|
test_http_parse_post_request();
|
||||||
@ -193,4 +243,6 @@ void run_http_tests(void) {
|
|||||||
test_http_parse_host_with_port();
|
test_http_parse_host_with_port();
|
||||||
test_http_is_request_start();
|
test_http_is_request_start();
|
||||||
test_http_malformed_requests();
|
test_http_malformed_requests();
|
||||||
|
test_http_uri_normalization();
|
||||||
|
test_http_internal_route_detection();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user