From 12b3f750ac2253b962c7bd5c4f7cff1d5a53afbb Mon Sep 17 00:00:00 2001 From: Kevin Jerebica Date: Tue, 3 Sep 2024 00:03:32 +0200 Subject: [PATCH] feat: implement parsing of headers some todos left before I call it stable --- .gitignore | 1 + .gitmodules | 3 ++ Makefile | 5 +- headers.c | 108 +++++++++++++++++++++++++++++++++++++++++++ streecmp | 1 + tinyparser | Bin 55144 -> 77032 bytes tinyparser.c | 126 +++++++++++++++++++++++++++++++++++++++++---------- tinyparser.h | 38 +++++++++++++--- 8 files changed, 248 insertions(+), 34 deletions(-) create mode 100644 .gitmodules create mode 100644 headers.c create mode 160000 streecmp diff --git a/.gitignore b/.gitignore index d8ac7ef..4fc5420 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.o compile_commands.json +tinyparser diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..43538c2 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "streecmp"] + path = streecmp + url = http://git.0xdeadbeer.xyz/0xdeadbeer/streecmp diff --git a/Makefile b/Makefile index 50ca2fa..1d7bc82 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,11 @@ CC=gcc CFLAGS=-g3 -CFILES=tinyparser.c +CFILES=tinyparser.c headers.c +CFILES_STREECMP=streecmp/streecmp.c OUTPUT=tinyparser all: - $(CC) $(CFLAGS) $(CFILES) -o $(OUTPUT) + $(CC) $(CFLAGS) $(CFILES) $(CFILES_STREECMP) -o $(OUTPUT) run: ./$(OUTPUT) diff --git a/headers.c b/headers.c new file mode 100644 index 0000000..ccb1e79 --- /dev/null +++ b/headers.c @@ -0,0 +1,108 @@ +char *headers = "A-IM\n" + "Accept\n" + "Accept-Charset\n" + "Accept-Datetime\n" + "Accept-Encoding\n" + "Accept-Language\n" + "Access-Control-Request-Method\n" + "Access-Control-Request-Headers\n" + "Authorization\n" + "Cache-Control\n" + "Connection\n" + "Content-Encoding\n" + "Content-Length\n" + "Content-MD5\n" + "Content-Type\n" + "Cookie\n" + "Date\n" + "Expect\n" + "Forwarded\n" + "From\n" + "Host\n" + "HTTP2-Settings\n" + "If-Match\n" + "If-Modified-Since\n" + "If-None-Match\n" + "If-Range\n" + "If-Unmodified-Since\n" + "Max-Forwards\n" + "Origin\n" + "Pragma\n" + "Prefer\n" + "Proxy-Authorization\n" + "Range\n" + "Referer\n" + "TE\n" + "Trailer\n" + "Transfer-Encoding\n" + "User-Agent\n" + "Upgrade\n" + "Via\n" + "Warning\n" + "Upgrade-Insecure-Requests\n" + "X-Requested-With\n" + "DNT\n" + "X-Forwarded-For\n" + "X-Forwarded-Host\n" + "X-Forwarded-Proto\n" + "Front-End-Https\n" + "X-Http-Method-Override\n" + "X-ATT-DeviceID\n" + "X-Wap-Profile\n" + "Proxy-Connection\n" + "X-UIDH\n" + "X-Csrf-Token\n" + "X-Request-ID\n" + "X-Correlation-ID\n" + "Correlation-ID\n" + "Save-Data\n" + "Sec-GPC\n" + "Accept-CH\n" + "Access-Control-Allow-Origin\n" + "Access-Control-Allow-Credentials\n" + "Access-Control-Expose-Headers\n" + "Access-Control-Max-Age\n" + "Access-Control-Allow-Methods\n" + "Access-Control-Allow-Headers\n" + "Accept-Patch\n" + "Accept-Ranges\n" + "Age\n" + "Allow\n" + "Alt-Svc\n" + "Content-Disposition\n" + "Content-Language\n" + "Content-Location\n" + "Content-Range\n" + "Delta-Base\n" + "ETag\n" + "Expires\n" + "IM\n" + "Last-Modified\n" + "Link\n" + "Location\n" + "P3P\n" + "Preference-Applied\n" + "Proxy-Authenticate\n" + "Public-Key-Pins\n" + "Retry-After\n" + "Server\n" + "Set-Cookie\n" + "Strict-Transport-Security\n" + "Tk\n" + "Vary\n" + "WWW-Authenticate\n" + "X-Frame-Options\n" + "Content-Security-Policy\n" + "Expect-CT\n" + "NEL\n" + "Permissions-Policy\n" + "Refresh\n" + "Report-To\n" + "Status\n" + "Timing-Allow-Origin\n" + "X-Content-Duration\n" + "X-Content-Type-Options\n" + "X-Powered-By\n" + "X-Redirect-By\n" + "X-UA-Compatible\n" + "X-XSS-Protection"; diff --git a/streecmp b/streecmp new file mode 160000 index 0000000..42ed963 --- /dev/null +++ b/streecmp @@ -0,0 +1 @@ +Subproject commit 42ed96353d186078e34e4c541e7c92d433cda138 diff --git a/tinyparser b/tinyparser index a3ed8f5d4f3edac9dcc067bfee80eb556a4fcc21..27b4e40a8cd2741ba199a9dcc164abd982048dab 100755 GIT binary patch literal 77032 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 Fe*j^$9LfLy delta 16983 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

-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 EAJ3l?z5oCK diff --git a/tinyparser.c b/tinyparser.c index 0fbfd97..19bc727 100644 --- a/tinyparser.c +++ b/tinyparser.c @@ -2,6 +2,9 @@ #include #include #include "tinyparser.h" +#include "streecmp/streecmp.h" + +extern char *headers; enum errs err = err_init; enum states state = state_init; @@ -11,17 +14,25 @@ char *ver = NULL; int uri_len = 0; int ver_len = 0; -int read_line(char **cursor, int cursor_size) { - int diff = 0; - char *match = strchr(*cursor, '\n'); +struct nod *header_tree = NULL; +char **header_table = NULL; - if (!match) - match = (*cursor)+cursor_size-1; - - diff = match - (*cursor); - *cursor += diff + 1; - - return diff; +int read_line(char **buffer, char **buffer_limit) { + int diff = 0; + if ((*buffer) >= (*buffer_limit)) { + return diff; + } + + int ret = 0; + char *match = strstr(*buffer, "\r\n"); + if (match) { + ret = match-(*buffer); + *buffer += 2; + } else { + ret = (*buffer_limit)-(*buffer); + } + *buffer += ret; + return ret; } int cmp_orig(char *ch, char *orig, char *limit) { @@ -57,18 +68,43 @@ int cmp_ascii(char *ch, char *limit) { return diff; } -int parse_title(char *title_offset, int title_len) { - int title_cursor = 0; +int parse_header(char *offset, int len) { + int cursor = 0; + int ret = 0; + char *header_limit = offset+len; + char *sep = strchr(offset, ':'); + if (!sep) { + return -1; + } + + if (sep > header_limit) { + return -1; + } + + int htitle_len = sep-offset; + ret = streencmp(header_tree, offset, htitle_len); + if (ret == 0) { + return -1; + } + + char *hvalue = sep+1; + header_table[ret] = hvalue; + + return 0; +} + +int parse_title(char *offset, int len) { + int cursor = 0; while (state != state_title_ok && state != state_title_err) { - if (title_cursor >= title_len) { + if (cursor >= len) { state = state_title_err; err = err_parse_title; } int ret = 0; - char *ch = title_offset+title_cursor; - char *lim = title_offset+title_len-1; + char *ch = offset+cursor; + char *lim = offset+len-1; switch (state) { case state_init: @@ -76,19 +112,19 @@ int parse_title(char *title_offset, int title_len) { break; case state_title_method: if ((ret = cmp_orig(ch, "GET", lim))) { - title_cursor += ret; + cursor += ret; state = state_title_after_method; method = method_get; break; } if ((ret = cmp_orig(ch, "POST", lim))) { - title_cursor += ret; + cursor += ret; state = state_title_after_method; method = method_post; break; } if ((ret = cmp_orig(ch, "HEAD", lim))) { - title_cursor += ret; + cursor += ret; state = state_title_after_method; method = method_head; break; @@ -98,7 +134,7 @@ int parse_title(char *title_offset, int title_len) { err = err_parse_title_method; break; case state_title_after_method: - title_cursor++; + cursor++; state = state_title_uri; break; case state_title_uri: @@ -115,11 +151,11 @@ int parse_title(char *title_offset, int title_len) { } uri_len = ret; - title_cursor += ret; + cursor += ret; state = state_title_after_uri; break; case state_title_after_uri: - title_cursor++; + cursor++; state = state_title_version; break; case state_title_version: @@ -136,7 +172,7 @@ int parse_title(char *title_offset, int title_len) { } ver_len = ret; - title_cursor += ret; + cursor += ret; state = state_title_ok; break; case state_title_ok: @@ -144,6 +180,7 @@ int parse_title(char *title_offset, int title_len) { if (*ch == ' ') continue; if (*ch == '\t') continue; if (*ch == '\0') continue; + if (*ch == '\r') continue; state = state_title_err; err = err_parse_title; @@ -164,16 +201,35 @@ int parse_title(char *title_offset, int title_len) { int parse_request(char *buffer) { int ret; - int buffer_size = strlen(buffer); + char *buffer_limit = buffer+strlen(buffer); char *title_offset = buffer; - int title_len = read_line(&buffer, buffer_size); - + int title_len = read_line(&buffer, &buffer_limit); if ((ret = parse_title(title_offset, title_len)) < 0) { fprintf(stderr, "Failed parsing title\n"); return -1; } + for (int bound = 0; bound < MAX_BOUND; bound++) { + char *header_offset = buffer; + int header_len = read_line(&buffer, &buffer_limit); + char *header_limit = header_offset+header_len; + + // IF END OF MESSAGE + if (!header_len) { + state = state_fin; + break; + } + + if ((ret = parse_header(header_offset, header_len)) < 0) { + fprintf(stderr, "Failed parsing header\n"); + return -1; + } + } + + free(uri); + free(ver); + return 0; } @@ -181,6 +237,24 @@ int main(void) { int ret; char *str = strdup(TEST_ONE); + header_table = (char **) calloc(header_count, sizeof(char *)); + if (!header_table) { + fprintf(stderr, "Not enough dynamic memory\n"); + return -1; + } + + header_tree = allocnod(); + if (!header_tree) { + fprintf(stderr, "Not enough dynamic memory\n"); + return -1; + } + + ret = gentree(header_tree, headers, NULL); + if (gentree < 0) { + fprintf(stderr, "Failed generating the header comparison tree\n"); + return -1; + } + ret = parse_request(str); if (ret < 0) { fprintf(stderr, "Failed parsing request\n"); @@ -189,6 +263,8 @@ int main(void) { fprintf(stderr, "Finished parsing request\n"); + frenod(header_tree); + free(header_table); free(str); return 0; diff --git a/tinyparser.h b/tinyparser.h index 406c5ca..b6d3002 100644 --- a/tinyparser.h +++ b/tinyparser.h @@ -1,12 +1,19 @@ #ifndef PARSER_H #define PARSER_H +#define CRLF "\r\n" +#define MAX_BOUND 1024 #define LINE_BUF 1024 #define TEST_ONE "GET / HTTP/1.1\r\n"\ "Host: archive.0xdeadbeer.xyz\r\n"\ "User-Agent: curl/8.9.1\r\n"\ - "Accept: */*\r\n" + "Accept: */*\r\n"\ + "\r\n"\ + "{\"key\": \"kefjoiawejfojgorgjbosejrgo\"}"\ +// ENUMS + +// SRC:https://datatracker.ietf.org/doc/html/rfc2616 enum errs { err_init = 0, err_generic, @@ -14,9 +21,11 @@ enum errs { err_parse_title, err_parse_title_method, err_parse_title_uri, - err_parse_title_version + err_parse_title_version, + err_parse_header_not_found }; +// SRC:https://datatracker.ietf.org/doc/html/rfc2616 enum states { state_init = 0, state_title_method, @@ -25,9 +34,23 @@ enum states { state_title_after_uri, state_title_version, state_title_ok, - state_title_err + state_title_err, + + state_header_init, + state_header_alloc, + state_header_parse, + state_header_not_found, + state_header_ok, + state_header_err, + + state_body_init, + state_body_ok, + state_body_err, + + state_fin, }; +// SRC:https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods enum methods { method_init = 0, method_get, @@ -35,8 +58,9 @@ enum methods { method_head }; +// SRC:https://en.wikipedia.org/wiki/List_of_HTTP_header_fields enum headers { - header_a_im = 0, + header_a_im = 1, header_accept, header_accept_charset, header_accept_datetime, @@ -77,7 +101,6 @@ enum headers { header_upgrade, header_via, header_warning, - header_upgrade_insecure_requests, header_x_requested_with, header_dnt, @@ -96,7 +119,6 @@ enum headers { header_correlation_id, header_save_data, header_sec_gpc, - header_accept_ch, header_access_control_allow_origin, header_access_control_allow_credentials, @@ -145,7 +167,9 @@ enum headers { header_x_powered_by, header_x_redirect_by, header_x_ua_compatible, - header_x_xss_protection + header_x_xss_protection, + + header_count }; #endif