Fix list pointer bug in proxy

This commit is contained in:
2023-01-12 01:58:14 +01:00
parent 820ce8dac9
commit 07d6280864
9 changed files with 23 additions and 29 deletions

View File

@ -88,6 +88,7 @@ void http_free_res(http_res *res) {
} }
int http_init_hdr(http_hdr *hdr) { int http_init_hdr(http_hdr *hdr) {
hdr->last_field_num = -1;
hdr->fields = list_create(sizeof(http_field), HTTP_INIT_HEADER_FIELD_NUM); hdr->fields = list_create(sizeof(http_field), HTTP_INIT_HEADER_FIELD_NUM);
if (hdr->fields == NULL) if (hdr->fields == NULL)
return error_http(HTTP_ERROR_SYSCALL); return error_http(HTTP_ERROR_SYSCALL);
@ -122,8 +123,11 @@ int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr,
str_trim_lws(&pos1, &pos2); str_trim_lws(&pos1, &pos2);
long len2 = pos2 - pos1; long len2 = pos2 - pos1;
char header_name[256];
sprintf(header_name, "%.*s", (int) len1, buf);
int field_num = list_size(hdr->fields); int field_num = list_size(hdr->fields);
int found = http_get_header_field_num_len(hdr, buf, len1); int found = http_get_header_field_num(hdr, header_name);
if (!(flags & HTTP_MERGE_FIELDS) || found == -1) { if (!(flags & HTTP_MERGE_FIELDS) || found == -1) {
if (http_add_header_field_len(hdr, buf, len1, pos1, len2 < 0 ? 0 : len2) != 0) if (http_add_header_field_len(hdr, buf, len1, pos1, len2 < 0 ? 0 : len2) != 0)
return error_http(HTTP_ERROR_TOO_MANY_HEADER_FIELDS); return error_http(HTTP_ERROR_TOO_MANY_HEADER_FIELDS);
@ -206,7 +210,6 @@ int http_receive_request(sock *client, http_req *req) {
memset(req->method, 0, sizeof(req->method)); memset(req->method, 0, sizeof(req->method));
memset(req->version, 0, sizeof(req->version)); memset(req->version, 0, sizeof(req->version));
req->uri = NULL; req->uri = NULL;
req->hdr.last_field_num = -1;
http_init_hdr(&req->hdr); http_init_hdr(&req->hdr);
rcv_len = sock_recv(client, buf, CLIENT_MAX_HEADER_SIZE - 1, MSG_PEEK); rcv_len = sock_recv(client, buf, CLIENT_MAX_HEADER_SIZE - 1, MSG_PEEK);
@ -227,21 +230,13 @@ int http_receive_request(sock *client, http_req *req) {
} }
const char *http_get_header_field(const http_hdr *hdr, const char *field_name) { const char *http_get_header_field(const http_hdr *hdr, const char *field_name) {
return http_get_header_field_len(hdr, field_name, strlen(field_name)); int num = http_get_header_field_num(hdr, field_name);
}
const char *http_get_header_field_len(const http_hdr *hdr, const char *field_name, unsigned long len) {
int num = http_get_header_field_num_len(hdr, field_name, len);
return (num >= 0 && num < list_size(hdr->fields)) ? http_field_get_value(&hdr->fields[num]) : NULL; return (num >= 0 && num < list_size(hdr->fields)) ? http_field_get_value(&hdr->fields[num]) : NULL;
} }
int http_get_header_field_num(const http_hdr *hdr, const char *field_name) { int http_get_header_field_num(const http_hdr *hdr, const char *field_name) {
return http_get_header_field_num_len(hdr, field_name, strlen(field_name));
}
int http_get_header_field_num_len(const http_hdr *hdr, const char *field_name, unsigned long len) {
for (int i = 0; i < list_size(hdr->fields); i++) { for (int i = 0; i < list_size(hdr->fields); i++) {
if (strncasecmp(field_name, http_field_get_name(&hdr->fields[i]), len) == 0) if (strcasecmp(field_name, http_field_get_name(&hdr->fields[i])) == 0)
return i; return i;
} }

View File

@ -156,12 +156,8 @@ int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr,
const char *http_get_header_field(const http_hdr *hdr, const char *field_name); const char *http_get_header_field(const http_hdr *hdr, const char *field_name);
const char *http_get_header_field_len(const http_hdr *hdr, const char *field_name, unsigned long len);
int http_get_header_field_num(const http_hdr *hdr, const char *field_name); int http_get_header_field_num(const http_hdr *hdr, const char *field_name);
int http_get_header_field_num_len(const http_hdr *hdr, const char *field_name, unsigned long len);
int http_add_header_field(http_hdr *hdr, const char *field_name, const char *field_value); int http_add_header_field(http_hdr *hdr, const char *field_name, const char *field_value);
int http_add_header_field_len(http_hdr *hdr, const char *name, unsigned long name_len, const char *value, unsigned long value_len); int http_add_header_field_len(http_hdr *hdr, const char *name, unsigned long name_len, const char *value, unsigned long value_len);

View File

@ -113,7 +113,7 @@ void *list_remove(void *list_ptr, int n) {
memset(array + list->size * list->elem_size, 0, list->elem_size); memset(array + list->size * list->elem_size, 0, list->elem_size);
list->size--; list->size--;
if (list->size < list->max_size / FACTOR / 2 && list->max_size / FACTOR >= list->init_size) { if (list->size <= list->max_size / FACTOR * 3 / 4 && list->max_size / FACTOR >= list->init_size) {
if ((list = list_resize(list, list->max_size / FACTOR)) == NULL) { if ((list = list_resize(list, list->max_size / FACTOR)) == NULL) {
return NULL; return NULL;
} }
@ -135,8 +135,7 @@ void *list_clear(void *list_ptr) {
list_meta_t *list = meta(list_ptr); list_meta_t *list = meta(list_ptr);
list->size = 0; list->size = 0;
memset(list_ptr, 0, list->max_size * list->elem_size); memset(list_ptr, 0, list->max_size * list->elem_size);
list->max_size = list->init_size; return data(list_resize(list, list->init_size));
return data(list_resize(list, list->max_size));
} }
void list_free(void *list_ptr) { void list_free(void *list_ptr) {

View File

@ -163,20 +163,19 @@ int proxy_request_header(http_req *req, sock *sock) {
http_add_header_field(&req->hdr, "Via", buf2); http_add_header_field(&req->hdr, "Via", buf2);
} }
const char *host = http_get_header_field(&req->hdr, "Host");
const char *forwarded = http_get_header_field(&req->hdr, "Forwarded");
int client_ipv6 = strchr(sock->addr, ':') != NULL; int client_ipv6 = strchr(sock->addr, ':') != NULL;
int server_ipv6 = strchr(sock->s_addr, ':') != NULL; int server_ipv6 = strchr(sock->s_addr, ':') != NULL;
p_len = snprintf(buf1, sizeof(buf1), "by=%s%s%s;for=%s%s%s;host=%s;proto=%s", p_len = snprintf(buf1, sizeof(buf1), "by=%s%s%s;for=%s%s%s;host=%s;proto=%s",
server_ipv6 ? "\"[" : "", sock->s_addr, server_ipv6 ? "]\"" : "", server_ipv6 ? "\"[" : "", sock->s_addr, server_ipv6 ? "]\"" : "",
client_ipv6 ? "\"[" : "", sock->addr, client_ipv6 ? "]\"" : "", client_ipv6 ? "\"[" : "", sock->addr, client_ipv6 ? "]\"" : "",
host, sock->enc ? "https" : "http"); http_get_header_field(&req->hdr, "Host"), sock->enc ? "https" : "http");
if (p_len < 0 || p_len >= sizeof(buf1)) { if (p_len < 0 || p_len >= sizeof(buf1)) {
error("Appended part of header field 'Forwarded' too long"); error("Appended part of header field 'Forwarded' too long");
return -1; return -1;
} }
const char *forwarded = http_get_header_field(&req->hdr, "Forwarded");
if (forwarded == NULL) { if (forwarded == NULL) {
http_add_header_field(&req->hdr, "Forwarded", buf1); http_add_header_field(&req->hdr, "Forwarded", buf1);
} else { } else {
@ -199,9 +198,10 @@ int proxy_request_header(http_req *req, sock *sock) {
} }
const char *xfh = http_get_header_field(&req->hdr, "X-Forwarded-Host"); const char *xfh = http_get_header_field(&req->hdr, "X-Forwarded-Host");
forwarded = http_get_header_field(&req->hdr, "Forwarded");
if (xfh == NULL) { if (xfh == NULL) {
if (forwarded == NULL) { if (forwarded == NULL) {
http_add_header_field(&req->hdr, "X-Forwarded-Host", host); http_add_header_field(&req->hdr, "X-Forwarded-Host", http_get_header_field(&req->hdr, "Host"));
} else { } else {
char *ptr = strchr(forwarded, ','); char *ptr = strchr(forwarded, ',');
unsigned long len; unsigned long len;
@ -220,6 +220,7 @@ int proxy_request_header(http_req *req, sock *sock) {
} }
const char *xfp = http_get_header_field(&req->hdr, "X-Forwarded-Proto"); const char *xfp = http_get_header_field(&req->hdr, "X-Forwarded-Proto");
forwarded = http_get_header_field(&req->hdr, "Forwarded");
if (xfp == NULL) { if (xfp == NULL) {
if (forwarded == NULL) { if (forwarded == NULL) {
http_add_header_field(&req->hdr, "X-Forwarded-Proto", sock->enc ? "https" : "http"); http_add_header_field(&req->hdr, "X-Forwarded-Proto", sock->enc ? "https" : "http");

View File

@ -165,14 +165,15 @@ static int logger_remaining(void) {
void logger_set_name(const char *restrict format, ...) { void logger_set_name(const char *restrict format, ...) {
va_list args; va_list args;
void *ptr;
if (key_name == -1) { if (key_name == -1) {
// not initialized // not initialized
va_start(args, format); va_start(args, format);
vsnprintf(global_name, sizeof(global_name), format, args); vsnprintf(global_name, sizeof(global_name), format, args);
ptr = global_name;
} else { } else {
int ret; int ret;
void *ptr = pthread_getspecific(key_name); if ((ptr = pthread_getspecific(key_name)) == NULL) {
if (!ptr) {
ptr = malloc(LOG_NAME_LEN); ptr = malloc(LOG_NAME_LEN);
if ((ret = pthread_setspecific(key_name, ptr)) != 0) { if ((ret = pthread_setspecific(key_name, ptr)) != 0) {
errno = ret; errno = ret;
@ -185,6 +186,9 @@ void logger_set_name(const char *restrict format, ...) {
vsnprintf(ptr, LOG_NAME_LEN, format, args); vsnprintf(ptr, LOG_NAME_LEN, format, args);
} }
// set thread name
pthread_setname_np(pthread_self(), global_name);
// cleanup // cleanup
va_end(args); va_end(args);
} }

View File

@ -23,7 +23,7 @@ typedef struct {
char cc[3], host[256]; char cc[3], host[256];
char req_host[256], err_msg[256]; char req_host[256], err_msg[256];
char log_prefix[128]; char log_prefix[128];
char _c_addr[ADDRSTRLEN + 1], _s_addr[ADDRSTRLEN + 1]; char _c_addr[INET6_ADDRSTRLEN + 1], _s_addr[INET6_ADDRSTRLEN + 1];
long cnx_s, cnx_e, req_s, res_ts, req_e; long cnx_s, cnx_e, req_s, res_ts, req_e;
http_req req; http_req req;
http_res res; http_res res;

View File

@ -14,7 +14,6 @@
#include "../workers.h" #include "../workers.h"
#include <string.h> #include <string.h>
#include <errno.h>
static int proxy_handler_1(client_ctx_t *ctx); static int proxy_handler_1(client_ctx_t *ctx);
static int proxy_handler_2(client_ctx_t *ctx); static int proxy_handler_2(client_ctx_t *ctx);

View File

@ -62,10 +62,8 @@ static void init_ctx(client_ctx_t *ctx) {
memset(&ctx->req, 0, sizeof(ctx->req)); memset(&ctx->req, 0, sizeof(ctx->req));
memset(&ctx->res, 0, sizeof(ctx->res)); memset(&ctx->res, 0, sizeof(ctx->res));
ctx->res.status = http_get_status(501); ctx->res.status = http_get_status(501);
http_init_hdr(&ctx->res.hdr); http_init_hdr(&ctx->res.hdr);
ctx->res.hdr.last_field_num = -1;
sprintf(ctx->res.version, "1.1"); sprintf(ctx->res.version, "1.1");
ctx->status.status = 0; ctx->status.status = 0;

View File

@ -32,6 +32,8 @@ void tcp_acceptor_func(client_ctx_t *ctx) {
static int tcp_acceptor(client_ctx_t *ctx) { static int tcp_acceptor(client_ctx_t *ctx) {
struct sockaddr_in6 server_addr; struct sockaddr_in6 server_addr;
memset(ctx->_c_addr, 0, sizeof(ctx->_c_addr));
memset(ctx->_s_addr, 0, sizeof(ctx->_s_addr));
inet_ntop(ctx->socket._addr.ipv6.sin6_family, &ctx->socket._addr.ipv6.sin6_addr, ctx->_c_addr, sizeof(ctx->_c_addr)); inet_ntop(ctx->socket._addr.ipv6.sin6_family, &ctx->socket._addr.ipv6.sin6_addr, ctx->_c_addr, sizeof(ctx->_c_addr));
if (strstarts(ctx->_c_addr, "::ffff:")) { if (strstarts(ctx->_c_addr, "::ffff:")) {
ctx->socket.addr = ctx->_c_addr + 7; ctx->socket.addr = ctx->_c_addr + 7;