From 1bc58618e5b36c929abcd343a796b614baca2bfe Mon Sep 17 00:00:00 2001 From: 0xdeadbeer Date: Wed, 4 Sep 2024 11:10:08 +0200 Subject: [PATCH] repo: rename library and update docs --- Makefile | 12 +-- README | 20 +++-- proxlib | Bin 0 -> 104944 bytes proxy.c => proxlib.c | 197 ++++++++++++++++++++++++++--------------- structs.h => proxlib.h | 6 ++ 5 files changed, 154 insertions(+), 81 deletions(-) create mode 100755 proxlib rename proxy.c => proxlib.c (74%) rename structs.h => proxlib.h (86%) diff --git a/Makefile b/Makefile index b4c6995..6ff3625 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,14 @@ CC=bear --append -- gcc CFLAGS= -g3 -Wall -Werror -all: proxy +all: proxlib -proxy: proxy.c - $(CC) $(CFLAGS) -o proxy.o -c proxy.c - $(CC) $(CFLAGS) -o proxy proxy.o +proxy: proxlib.c + $(CC) $(CFLAGS) -o proxlib.o -c proxlib.c + $(CC) $(CFLAGS) -o proxlib proxlib.o clean: - rm -f proxy *.o + rm -f proxlib *.o tar: - tar -cvzf proxy.tgz proxy.c structs.h README Makefile + tar -cvzf proxlib.tgz proxlib.c proxlib.h README Makefile diff --git a/README b/README index b552b51..5b058cd 100644 --- a/README +++ b/README @@ -1,8 +1,8 @@ -+==================+ -| CUSTOM PROXY | -+==================+ ++=============+ +| proxlib | ++=============+ - Proxy for HTTP/1.0 standard protocol + Proxy C library for HTTP/s protocol RFC: datatracker.ietf.org/doc/html/rfc1945 RES: cs.princeton.edu/courses/archive/spr13/cos461/assignments-proxy.html @@ -12,8 +12,16 @@ TECHNICALS - Parsing is done through a chain of regex expressions that verify - the format of received HTTP/1.0 messages. + Parsing is carried by a sub-library which I wrote named parslib. + +TODO + + * Connect with parslib + * Parse port out of Host header (default_value:80) + * Implement server message parsing + * Verify and search for memory leaks + * More testing, debugging, fixing + * Implement HTTPS with OpenSSL COMMITS diff --git a/proxlib b/proxlib new file mode 100755 index 0000000000000000000000000000000000000000..0af840b29d01dcb8334c06c9a160feabed1a034b GIT binary patch literal 104944 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%0A<%n8{dzyu%!R^X7p2K-kV#A=pgD-Z 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 G>;D6lD|DCu literal 0 HcmV?d00001 diff --git a/proxy.c b/proxlib.c similarity index 74% rename from proxy.c rename to proxlib.c index f38815a..b59aa91 100644 --- a/proxy.c +++ b/proxlib.c @@ -8,8 +8,9 @@ #include #include #include -#include "structs.h" +#include "proxlib.h" +int on = 1; int debug = 1; struct request *clt_data; regex_t preg; @@ -20,13 +21,17 @@ int statem; int clt_sock = -1; int srv_sock = -1; char *clt_msg = NULL; -int clt_msg_len = 0; char *srv_msg = NULL; +int clt_msg_len = 0; int srv_msg_len = 0; void *extractsub(const char *msg, regmatch_t match) { + void *buf = NULL; int buflen = match.rm_eo - match.rm_so; - void *buf = (void *) calloc(1, buflen); + if (!buflen) + goto _return; + + buf = (void *) calloc(1, buflen); if (buf == NULL) goto _return; @@ -77,6 +82,37 @@ _err: return -1; } +int parse_host(char *buff) { + int ret; + + ret = regcomp(&preg, REGEX_HOST, REG_EXTENDED); + if (ret != 0) + goto _err; + + ret = regexec(&preg, buff, REGEX_MATCHN, pmatch, 0); + if (ret != 0) + goto _err; + + char *host_name = extractsub(buff, pmatch[1]); + if (!host_name) + goto _err; + + char *host_port = extractsub(buff, pmatch[2]); + if (!host_port) { + host_port = PROXY_DEF_PORT; + } + + clt_data->host_name = host_name; + clt_data->host_port = host_port; + + regfree(&preg); + return 0; + +_err: + regfree(&preg); + return -1; +} + int parse_title(char *msgbuff) { int ret; @@ -109,13 +145,18 @@ _err: } -void free_title() { +void free_host(void) { + free(clt_data->host_name); + free(clt_data->host_port); +} + +void free_title(void) { free(clt_data->method); free(clt_data->uri); free(clt_data->ver); } -void free_headers() { +void free_headers(void) { for (int i = 0; i < clt_data->header_num; i++) { struct header *header = &clt_data->headers[i]; free(header->key); @@ -124,12 +165,27 @@ void free_headers() { free(clt_data->headers); } -void free_message() { +void free_clt_data(void) { + free_host(); free_title(); free_headers(); free(clt_data); } +void free_srv_data(void) { + +} + +void free_msg_buffs(void) { + free(clt_msg); + free(srv_msg); +} + +void free_data(void) { + free_clt_data(); + free_srv_data(); +} + int parse_line(char *line, int line_count) { int ret = 0; @@ -157,19 +213,20 @@ char *getheader(char *key) { void do_err(void) { int statem_code = statem & (~STATEM_ERR); - fprintf(stderr, "[%d,%d,%d] Errored out!\n", statem, statem_code, STATEM_ERR); + fprintf(stderr, "[%d,%d,%d] Errored out!\n", statem, statem_code, + STATEM_ERR); } int do_fwd_clt(void) { int bytes = 0; int ret = 0; - do { - ret = send(clt_sock, srv_msg+bytes, srv_msg_len-bytes, 0); - if (ret < 0) - return -1; - + while (bytes < srv_msg_len) { + ret = write(clt_sock, srv_msg+bytes, srv_msg_len-bytes); + if (ret < 0) + return -1; + bytes += ret; - } while (bytes < srv_msg_len); + } return 0; } @@ -183,21 +240,21 @@ int do_prs_srv(void) { int do_rcv_srv(void) { int bytes = 0; int ret = 0; - do { - ret = recv(srv_sock, srv_msg+bytes, PROXY_MAX_MSGLEN-bytes, 0); + while (bytes < PROXY_MAX_MSGLEN) { + ret = recv(srv_sock, srv_msg+bytes, PROXY_MAX_MSGLEN-bytes, MSG_PEEK); if (ret < 0) - return -1; + return -1; if (!ret) break; + ret = recv(srv_sock, srv_msg+bytes, PROXY_MAX_MSGLEN-bytes, 0); - bytes += ret; - } while (bytes < sizeof(PROXY_MAX_MSGLEN)); + bytes += ret; + } srv_msg_len = bytes; - if (debug) { - fprintf(stdout, "[%d] Received server message: %s\n", statem, srv_msg); - } + if (debug) + fprintf(stdout, "[%d] Received server message of size %d bytes\n", statem, srv_msg_len); return 0; } @@ -207,6 +264,10 @@ int do_con_srv(void) { char *host = getheader("Host"); if (!host) return -1; + + ret = parse_host(host); + if (ret < 0) + return -1; struct addrinfo hints; struct addrinfo *res; @@ -215,11 +276,12 @@ int do_con_srv(void) { hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; - ret = getaddrinfo(host, "80", &hints, &res); + ret = getaddrinfo(clt_data->host_name, clt_data->host_port, &hints, &res); if (ret < 0) return -1; - ret = srv_sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + ret = srv_sock = socket(res->ai_family, res->ai_socktype, + res->ai_protocol); if (ret < 0) return -1; @@ -233,13 +295,13 @@ int do_con_srv(void) { int do_fwd_srv(void) { int bytes = 0; int ret = 0; - do { - ret = send(srv_sock, clt_msg+bytes, clt_msg_len-bytes, 0); - if (ret < 0) - return -1; + while (bytes < clt_msg_len) { + ret = write(srv_sock, clt_msg+bytes, clt_msg_len-bytes); + if (ret < 0) + return -1; - bytes += ret; - } while (bytes < clt_msg_len); + bytes += ret; + } return 0; } @@ -268,21 +330,22 @@ int do_prs_clt(void) { int do_rcv_clt(void) { int bytes = 0; int ret = 0; - do { - ret = recv(clt_sock, clt_msg+bytes, PROXY_MAX_MSGLEN-bytes, 0); + while (bytes < PROXY_MAX_MSGLEN) { + ret = recv(clt_sock, clt_msg+bytes, PROXY_MAX_MSGLEN-bytes, MSG_PEEK); if (ret < 0) return -1; if (!ret) break; + ret = recv(clt_sock, clt_msg+bytes, PROXY_MAX_MSGLEN-bytes, 0); + bytes += ret; - } while (bytes < sizeof(PROXY_MAX_MSGLEN)); + } clt_msg_len = bytes; - if (debug) { - fprintf(stdout, "[%d] Received client message: %s\n", statem, clt_msg); - } + if (debug) + fprintf(stdout, "[%d] Received client message of size %d bytes\n", statem, clt_msg_len); return 0; } @@ -304,6 +367,8 @@ int do_alloc(void) { } void do_clear(void) { + statem = STATEM_RCV_CLT; + memset(clt_msg, 0, PROXY_MAX_MSGLEN); memset(srv_msg, 0, PROXY_MAX_MSGLEN); memset(clt_data, 0, sizeof(struct request)); @@ -312,7 +377,7 @@ void do_clear(void) { srv_msg_len = 0; } -void dostatem() { +void do_statem() { int ret = do_alloc(); if (ret < 0) { do_err(); @@ -356,7 +421,6 @@ void dostatem() { } if (statem & STATEM_FWD_CLT) { - statem = STATEM_RCV_CLT; do_clear(); continue; } @@ -364,9 +428,8 @@ void dostatem() { statem <<= 1; } - free_message(); - free(clt_msg); - free(srv_msg); + free_msg_buffs(); + free_data(); } void dohelp() { @@ -382,38 +445,36 @@ void dohelp() { ); } -int doserver(void) { - int ret, server_socket; +int do_srv(void) { + int ret, proxy_sock; + struct sockaddr_in serv_addr; - ret = server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + ret = proxy_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (ret < 0) { fprintf(stderr, "Failed to create a socket to listen on\n"); return -1; } - int on = 1; - ret = setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + ret = setsockopt(proxy_sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (ret < 0) { fprintf(stderr, "Failed flagging server socket as reusable\n"); return -1; } - struct sockaddr_in serv_addr; - memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(PROXY_PORT); - ret = bind(server_socket, (struct sockaddr *) &serv_addr, + ret = bind(proxy_sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); if (ret < 0) { fprintf(stderr, "Failed to bind to port %d\n", PROXY_PORT); return -1; } - ret = listen(server_socket, PROXY_CONN); + ret = listen(proxy_sock, PROXY_CONN); if (ret < 0) { fprintf(stderr, "Failed to listen on port %d\n", PROXY_PORT); return -1; @@ -422,12 +483,12 @@ int doserver(void) { fprintf(stdout, "Listening on port %d\n", PROXY_PORT); for (;;) { - struct sockaddr_in client_addr; - socklen_t client_addrlen = sizeof(client_addr); - int client_socket; + struct sockaddr_in new_clt_addr; + socklen_t new_clt_addr_len= sizeof(new_clt_addr); + int new_clt_sock; - ret = client_socket = accept(server_socket, (struct sockaddr *) - &client_addr, &client_addrlen); + ret = new_clt_sock = accept(proxy_sock, (struct sockaddr *) + &new_clt_addr, &new_clt_addr_len); if (ret < 0) { fprintf(stderr, "Failed to establish socket connection with" "client\n"); @@ -435,29 +496,27 @@ int doserver(void) { } ret = fork(); - switch (ret) { - case -1: + if (ret < 0) { fprintf(stderr, "[CLIENT SOCKET %d] Failed to fork child process" - "to handle the request\n", client_socket); + "to handle the request\n", new_clt_sock); return -1; - break; - case 0: - clt_sock = client_socket; + } + + if (!ret) { + clt_sock = new_clt_sock; statem = STATEM_RCV_CLT; - dostatem(); + do_statem(); return 0; - break; - default: - fprintf(stdout, "[PROGRAM] Successfully forked a new child process" - " with PID %d\n", ret); - break; } + + fprintf(stdout, "[PROGRAM] Successfully forked a new child process" + " with PID %d\n", ret); } return 0; } -int doclient(void) { +int do_clt(void) { int ret = 0; int client_socket; struct sockaddr_in serv_addr; @@ -510,11 +569,11 @@ int main(int argc, char *argv[]) { const char *mode = argv[1]; ret = strcmp(mode, SERVER_MODE); if (ret == 0) - return doserver(); + return do_srv(); ret = strcmp(mode, CLIENT_MODE); if (ret == 0) - return doclient(); + return do_clt(); fprintf(stderr, "Unknown proxy mode\n"); } diff --git a/structs.h b/proxlib.h similarity index 86% rename from structs.h rename to proxlib.h index ce2b0b6..61aeaea 100644 --- a/structs.h +++ b/proxlib.h @@ -9,11 +9,14 @@ #define PROXY_PORT 2020 #define PROXY_CONN 20 #define PROXY_MAX_MSGLEN 10000*1024 +#define PROXY_DEF_PORT "80" +#define PROXY_BASE_PORT 10 #define REGEX_MATCHN 4 #define REGEX_TITLE "^([A-Z]+)[ ]+([a-zA-Z0-9\\:/_.,-]+)"\ "[ ]+([a-zA-Z0-9_.,/-]+)[\n\r]*$" #define REGEX_HEADER "^([a-zA-Z0-9_-]*):[ \t]+([^\r\n]*)" +#define REGEX_HOST "^([a-zA-Z0-9_/,.-]+)(:[0-9]+)?$" #define CLIENT_MESSAGE "GET http://archive.0xdeadbeer.org/ HTTP/1.0\r\n\r\n"\ "Host: archive.0xdeadbeer.org\r\n"\ @@ -33,6 +36,9 @@ struct header { }; struct request { + char *host_name; + char *host_port; + char *method; char *uri; char *ver;