etc~ scripts and random things |
| git clone https://github.com/djnnvx/etc.git |
| log | files | refs | archive |
fuzz_auth_header.c (4196B)
1 /* 2 * AFL++ / LibFuzzer harness — TTYD HTTP Authentication Header 3 * 4 * Target: the real check_auth() function from ttyd's http.c 5 * Technique: #include the source file directly so static functions are 6 * accessible (standard OSS-Fuzz approach). 7 * 8 * Input format: [mode:1][credential_len:2 BE][credential][auth_header_value] 9 * mode 0 — no auth required 10 * mode 1 — Basic auth (credential = expected base64 value) 11 * mode 2 — custom header auth (X-Auth-User) 12 * 13 * Build (handled by build_fuzzers.sh): 14 * afl-clang-fast -fsanitize=address,undefined -g -O1 15 * -I fuzz-include -I ttyd-src/src 16 * fuzz_auth_header.c 17 * ttyd-obj/{http,protocol,utils,fuzz_lws_mock,mock_server_globals,mock_pty_stubs}.o 18 * -ljson-c -o fuzz_auth_header 19 */ 20 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <stdint.h> 25 #include <stdbool.h> 26 27 /* Mock lws control state — must come before including the real ttyd source */ 28 #include "fuzz_lws_mock.h" 29 30 /* Pull in the real ttyd structs (server.h included transitively via http.c) */ 31 /* fuzz-include/libwebsockets.h and fuzz-include/uv.h shadow the real ones */ 32 #include "ttyd-src/src/http.c" /* gives us static check_auth() */ 33 34 /* Provided by mock_server_globals.c */ 35 extern struct server _fuzz_server; 36 extern void fuzz_server_reset(void); 37 38 /* ── fuzz target ─────────────────────────────────────────────────────────── */ 39 40 int fuzz_target(const uint8_t *data, size_t size) { 41 if (size < 3) return 0; 42 43 /* Parse structured input */ 44 uint8_t mode = data[0] % 3; 45 uint16_t cred_len = (uint16_t)((data[1] << 8) | data[2]); 46 if ((size_t)cred_len > size - 3) cred_len = (uint16_t)(size - 3); 47 48 /* Reset fuzzer-controlled lws state and the server global */ 49 fuzz_lws_reset(); 50 fuzz_server_reset(); 51 52 /* Set up the credential the server expects */ 53 static char cred_buf[65536]; 54 if (mode == 1 && cred_len > 0) { 55 /* Basic auth: credential bytes become the expected base64 value */ 56 memcpy(cred_buf, data + 3, cred_len); 57 cred_buf[cred_len] = '\0'; 58 _fuzz_server.credential = cred_buf; 59 _fuzz_server.auth_header = NULL; 60 } else if (mode == 2) { 61 /* Custom header auth */ 62 _fuzz_server.credential = NULL; 63 _fuzz_server.auth_header = (char *)"X-Auth-User"; 64 } 65 /* mode 0: no auth, both remain NULL */ 66 67 /* Remaining bytes are the inbound Authorization header value that 68 * lws_hdr_copy() will return via the mock */ 69 const uint8_t *auth_data = data + 3 + cred_len; 70 size_t auth_len = size - 3 - cred_len; 71 fuzz_lws_set_auth((const char *)auth_data, (int)auth_len); 72 73 /* For custom-header mode, same bytes are treated as the custom header */ 74 if (mode == 2) 75 fuzz_lws_set_custom((const char *)auth_data, (int)auth_len); 76 77 /* Call the REAL check_auth() from http.c */ 78 struct lws mock_wsi = {0}; 79 struct pss_http pss = {0}; 80 (void)check_auth(&mock_wsi, &pss); 81 82 return 0; 83 } 84 85 /* ── AFL++ persistent mode ───────────────────────────────────────────────── */ 86 #ifdef __AFL_FUZZ_TESTCASE_LEN 87 __AFL_FUZZ_INIT(); 88 int main(void) { 89 #ifdef __AFL_HAVE_MANUAL_CONTROL 90 __AFL_INIT(); 91 #endif 92 unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF; 93 while (__AFL_LOOP(10000)) { 94 fuzz_target(buf, __AFL_FUZZ_TESTCASE_LEN); 95 } 96 return 0; 97 } 98 99 #else 100 /* LibFuzzer */ 101 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 102 return fuzz_target(data, size); 103 } 104 105 #ifndef LIBFUZZER 106 /* Standalone file-based testing */ 107 int main(int argc, char **argv) { 108 if (argc != 2) { fprintf(stderr, "Usage: %s <input_file>\n", argv[0]); return 1; } 109 FILE *f = fopen(argv[1], "rb"); 110 if (!f) { perror("fopen"); return 1; } 111 fseek(f, 0, SEEK_END); long sz = ftell(f); rewind(f); 112 uint8_t *buf = malloc(sz); 113 fread(buf, 1, sz, f); fclose(f); 114 fuzz_target(buf, sz); 115 free(buf); 116 return 0; 117 } 118 #endif 119 #endif