[git commit] httpd: cgi-bin support for DELETE, PUT, OPTIONS etc methods
Denys Vlasenko
vda.linux at googlemail.com
Tue May 4 17:20:50 UTC 2021
commit: https://git.busybox.net/busybox/commit/?id=36e932abdfd79f55fdded4142d10319ba843839e
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master
function old new delta
handle_incoming_and_exit 2217 2240 +23
static.request_POST - 5 +5
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/0 up/down: 28/0) Total: 28 bytes
Signed-off-by: Alexander Sack <asac at pantacor.com>
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
networking/httpd.c | 85 +++++++++++++++++++++++++-----------------------------
1 file changed, 40 insertions(+), 45 deletions(-)
diff --git a/networking/httpd.c b/networking/httpd.c
index e6757d943..09e19dc29 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -344,13 +344,6 @@ typedef struct Htaccess_Proxy {
char *url_to;
} Htaccess_Proxy;
-typedef enum CGI_type {
- CGI_NONE = 0,
- CGI_NORMAL,
- CGI_INDEX,
- CGI_INTERPRETER,
-} CGI_type;
-
enum {
HTTP_OK = 200,
HTTP_PARTIAL_CONTENT = 206,
@@ -2174,7 +2167,6 @@ static void send_REQUEST_TIMEOUT_and_exit(int sig UNUSED_PARAM)
static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) NORETURN;
static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
{
- static const char request_GET[] ALIGN1 = "GET";
struct stat sb;
char *urlcopy;
char *urlp;
@@ -2186,13 +2178,17 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
unsigned total_headers_len;
#endif
#if ENABLE_FEATURE_HTTPD_CGI
+ static const char request_GET[] ALIGN1 = "GET";
static const char request_HEAD[] ALIGN1 = "HEAD";
+ static const char request_POST[] ALIGN1 = "POST";
const char *prequest;
- unsigned long length = 0;
- enum CGI_type cgi_type = CGI_NONE;
-#elif ENABLE_FEATURE_HTTPD_PROXY
-#define prequest request_GET
- unsigned long length = 0;
+ unsigned long POST_length;
+ enum CGI_type {
+ CGI_NONE = 0,
+ CGI_NORMAL,
+ CGI_INDEX,
+ CGI_INTERPRETER,
+ } cgi_type = CGI_NONE;
#endif
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
smallint authorized = -1;
@@ -2235,7 +2231,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
if (!get_line()) /* EOF or error or empty line */
send_headers_and_exit(HTTP_BAD_REQUEST);
- /* Determine type of request (GET/POST) */
+ /* Determine type of request (GET/POST/...) */
// rfc2616: method and URI is separated by exactly one space
//urlp = strpbrk(iobuf, " \t"); - no, tab isn't allowed
urlp = strchr(iobuf, ' ');
@@ -2244,16 +2240,20 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
*urlp++ = '\0';
#if ENABLE_FEATURE_HTTPD_CGI
prequest = request_GET;
- if (strcasecmp(iobuf, prequest) != 0) {
- prequest = request_HEAD;
- if (strcasecmp(iobuf, prequest) != 0) {
- prequest = "POST";
- if (strcasecmp(iobuf, prequest) != 0)
- send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
- }
- }
+ if (strcasecmp(iobuf, prequest) == 0)
+ goto found;
+ prequest = request_HEAD;
+ if (strcasecmp(iobuf, prequest) == 0)
+ goto found;
+ prequest = request_POST;
+ if (strcasecmp(iobuf, prequest) == 0)
+ goto found;
+ /* For CGI, allow other requests too (DELETE, PUT, OPTIONS, etc) */
+ prequest = alloca(16);
+ safe_strncpy((char*)prequest, iobuf, 16);
+ found:
#else
- if (strcasecmp(iobuf, request_GET) != 0)
+ if (strcasecmp(iobuf, "GET") != 0)
send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
#endif
// rfc2616: method and URI is separated by exactly one space
@@ -2300,7 +2300,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
* to http://hostname[:port]/new/pathSFX
*/
fdprintf(proxy_fd, "%s %s%s %s\r\n",
- prequest, /* "GET" or "POST" */
+ iobuf, /* "GET" / "POST" / etc */
proxy_entry->url_to, /* "/new/path" */
urlcopy + strlen(proxy_entry->url_from), /* "SFX" */
HTTP_slash /* "HTTP/xyz" */
@@ -2328,7 +2328,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
/* Algorithm stolen from libbb bb_simplify_path(),
* but don't strdup, retain trailing slash, protect root */
urlp = tptr = urlcopy;
- for (;;) {
+ while (1) {
if (*urlp == '/') {
/* skip duplicate (or initial) slash */
if (*tptr == '/') {
@@ -2435,6 +2435,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
#if ENABLE_FEATURE_HTTPD_CGI
total_headers_len = 0;
+ POST_length = 0;
#endif
/* Read until blank line */
@@ -2450,24 +2451,17 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
#endif
if (DEBUG)
bb_error_msg("header: '%s'", iobuf);
-#if ENABLE_FEATURE_HTTPD_CGI || ENABLE_FEATURE_HTTPD_PROXY
- /* Try and do our best to parse more lines */
- if (STRNCASECMP(iobuf, "Content-Length:") == 0) {
- /* extra read only for POST */
- if (prequest != request_GET
-# if ENABLE_FEATURE_HTTPD_CGI
- && prequest != request_HEAD
-# endif
- ) {
- tptr = skip_whitespace(iobuf + sizeof("Content-Length:") - 1);
- if (!tptr[0])
- send_headers_and_exit(HTTP_BAD_REQUEST);
- /* not using strtoul: it ignores leading minus! */
- length = bb_strtou(tptr, NULL, 10);
- /* length is "ulong", but we need to pass it to int later */
- if (errno || length > INT_MAX)
- send_headers_and_exit(HTTP_BAD_REQUEST);
- }
+#if ENABLE_FEATURE_HTTPD_CGI
+ /* Only POST needs to know POST_length */
+ if (prequest == request_POST && STRNCASECMP(iobuf, "Content-Length:") == 0) {
+ tptr = skip_whitespace(iobuf + sizeof("Content-Length:") - 1);
+ if (!tptr[0])
+ send_headers_and_exit(HTTP_BAD_REQUEST);
+ /* not using strtoul: it ignores leading minus! */
+ POST_length = bb_strtou(tptr, NULL, 10);
+ /* length is "ulong", but we need to pass it to int later */
+ if (errno || POST_length > INT_MAX)
+ send_headers_and_exit(HTTP_BAD_REQUEST);
continue;
}
#endif
@@ -2588,7 +2582,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
send_cgi_and_exit(
(cgi_type == CGI_INDEX) ? "/cgi-bin/index.cgi"
/*CGI_NORMAL or CGI_INTERPRETER*/ : urlcopy,
- urlcopy, prequest, length
+ urlcopy, prequest, POST_length
);
}
#endif
@@ -2599,13 +2593,14 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
#if ENABLE_FEATURE_HTTPD_CGI
if (prequest != request_GET && prequest != request_HEAD) {
- /* POST for files does not make sense */
+ /* POST / DELETE / PUT / OPTIONS for files do not make sense */
send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
}
send_file_and_exit(tptr,
(prequest != request_HEAD ? SEND_HEADERS_AND_BODY : SEND_HEADERS)
);
#else
+ /* It was verified earlier that it is a "GET" */
send_file_and_exit(tptr, SEND_HEADERS_AND_BODY);
#endif
}
More information about the busybox-cvs
mailing list