From 623247da4f423e72940028157e6edfeb16b36965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Sun, 17 May 2026 17:15:51 +0200 Subject: [PATCH 1/2] httpd: Added extra content_type check for login. Ensure login content_type is "application/x-www-form-urlencoded". --- httpd/httpd.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/httpd/httpd.c b/httpd/httpd.c index 77db515..2b84adf 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -442,6 +442,13 @@ void handle_post(void) cmd_available = 1; } else if (is_word(request_path, "login")) { dbg_string("POST login\n"); + + if (!content_type || !is_word(content_type, "application/x-www-form-urlencoded")) { + dbg_string("Bad request!\n"); + send_bad_request(); + return; + } + p += 8; // Read also over "pwd=" if (is_url_word_x(p, passwd)) { dbg_string("Password accepted!\n"); From 4b40efafbb027c4bb892e25a767ed8a0143061b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Sun, 17 May 2026 17:12:38 +0200 Subject: [PATCH 2/2] Fix and refactor is_url_word_x(). With content_type = "application/x-www-form-urlencoded", "+" means space. This case was not handled. Also refactor the code to make a loop to process the hex digits. --- httpd/httpd.c | 57 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/httpd/httpd.c b/httpd/httpd.c index 2b84adf..affc8d9 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -131,28 +131,46 @@ char is_word(__xdata uint8_t *c, __code uint8_t * __xdata d) } -char is_url_word_x(__xdata uint8_t *c, __xdata uint8_t *d) +bool is_url_word_x(__xdata uint8_t *uri_str_p, __xdata uint8_t *src_str_p) { - uint8_t i = 0, j = 0; + uint8_t u, s; - while (d[i]) { - if (c[j] == '%') { - uint8_t v; - j++; - v = c[j] - '0' < 10 ? (c[j] - '0') << 4 : (c[j] - 'A' + 10) << 4; - j++; - v += c[j] - '0' < 10 ? c[j] - '0' : c[j] - 'A' + 10; - if (d[i] != v) - return 0; - } else if (d[i] != c[j]) - return 0; - i++; - j++; + while(1) { + u = *uri_str_p++; + s = *src_str_p++; + + if (s == '\0') { + if (u != '\0' && u != ' ' && u != '\t' && u != ':' && u != '?' && u != '=' && u != '\n' && u != '\r') + return false; + return true; + } + + if (u == '%') { + bool again = true; + u = 0; + + while(1) { + // Swap instruction is fine for rotation + u = (u << 4) | (u >> 4); + + uint8_t p = *uri_str_p++; + u |= p - '0' < 10 ? (p - '0') : (p - 'A' + 10); + + // force `jbc`-instruction. + if (again) { + again = false; + } else { + break; + } + } + } else if (u == '+') { + u = ' '; + } + + if (s != u) { + return false; + } } - - if (c[j] != ' ' && c[j] != '\t' && c[j] != ':' && c[j] != '?' && c[j] != '=' && c[j] != '\n' && c[j] != '\r' && c[j]) - return 0; - return 1; } @@ -461,6 +479,7 @@ void handle_post(void) outbuf[slen++] = session_id[i]; slen += strtox(outbuf + slen, "; SameSite=Strict\r\n\r\n"); } else { + dbg_string("Password invalid!\n"); slen = strtox(outbuf, "HTTP/1.1 302 Found\r\nLocation: login.html\r\n\r\n"); } return;