1
0
mirror of https://github.com/lammertb/libhttp.git synced 2026-01-03 16:02:30 +03:00

Allow scripts to use the PATCH HTTP method (RFC 5789)

See https://tools.ietf.org/html/rfc5789

This method is only allowed for CGI, Lua/LSP scripts and callbacks,
not for static resources such ase files.
This commit is contained in:
bel
2015-07-26 21:08:59 +02:00
parent ec81082452
commit e6a293590d

View File

@@ -1381,14 +1381,14 @@ static void mg_vsnprintf(const struct mg_connection *conn,
#endif
if (!ok) {
if (conn) {
conn->must_close = 1;
}
mg_cry(conn,
if (conn) {
conn->must_close = 1;
}
mg_cry(conn,
"truncating vsnprintf buffer: [%.*s]",
n > 200 ? 200 : n,
buf);
n = (int)buflen - 1;
n = (int)buflen - 1;
}
buf[n] = '\0';
}
@@ -2033,12 +2033,12 @@ send_http_error(struct mg_connection *conn, int status, const char *fmt, ...)
break;
}
/* String truncation in buf may only occur if error_handler
* is too long. This string is from the config, not from a
* client. */
len = (int)strlen(buf);
/* String truncation in buf may only occur if error_handler
* is too long. This string is from the config, not from a
* client. */
len = (int)strlen(buf);
tstr = strchr(error_page_file_ext, '.');
tstr = strchr(error_page_file_ext, '.');
while (tstr) {
for (i = 1; i < 32 && tstr[i] != 0 && tstr[i] != ',';
@@ -2707,8 +2707,8 @@ static pid_t spawn_process(struct mg_connection *conn,
/* Read the first line of the script into the buffer */
mg_snprintf(conn, cmdline, sizeof(cmdline), "%s%c%s", dir, '/', prog);
/* TODO(high): kick client on buffer overflow */
/* TODO(high): kick client on buffer overflow */
if (mg_fopen(conn, cmdline, "r", &file)) {
p = (char *)file.membuf;
@@ -2744,7 +2744,7 @@ static pid_t spawn_process(struct mg_connection *conn,
conn, cmdline, sizeof(cmdline), "\"%s\\%s\"", full_dir, prog);
}
/* TODO(high): kick client on buffer overflow */
/* TODO(high): kick client on buffer overflow */
DEBUG_TRACE("Running [%s]", cmdline);
if (CreateProcessA(NULL,
@@ -3745,7 +3745,7 @@ static int is_put_or_delete_method(const struct mg_connection *conn)
if (conn) {
const char *s = conn->request_info.request_method;
return s != NULL && (!strcmp(s, "PUT") || !strcmp(s, "DELETE") ||
!strcmp(s, "MKCOL"));
!strcmp(s, "MKCOL") || !strcmp(s, "PATCH"));
}
return 0;
}
@@ -3804,7 +3804,7 @@ interpret_uri(struct mg_connection *conn, /* in: request */
* If document_root is NULL, leave the file empty. */
mg_snprintf(conn, filename, filename_buf_len - 1, "%s%s", root, uri);
/* TODO(high): kick client on buffer overflow */
/* TODO(high): kick client on buffer overflow */
rewrite = conn->ctx->config[REWRITE];
while ((rewrite = next_option(rewrite, &a, &b)) != NULL) {
@@ -3820,7 +3820,7 @@ interpret_uri(struct mg_connection *conn, /* in: request */
}
}
/* TODO(high): kick client on buffer overflow */
/* TODO(high): kick client on buffer overflow */
/* Local file path and name, corresponding to requested URI
* is now stored in "filename" variable. */
@@ -3867,7 +3867,7 @@ interpret_uri(struct mg_connection *conn, /* in: request */
if (strstr(accept_encoding, "gzip") != NULL) {
mg_snprintf(conn, gz_path, sizeof(gz_path), "%s.gz", filename);
/* TODO(high): kick client on buffer overflow */
/* TODO(high): kick client on buffer overflow */
if (mg_stat(conn, gz_path, filep)) {
if (filep) {
@@ -4292,7 +4292,7 @@ open_auth_file(struct mg_connection *conn, const char *path, struct file *filep)
'/',
PASSWORDS_FILE_NAME);
/* TODO(high): kick client on buffer overflow */
/* TODO(high): kick client on buffer overflow */
if (!mg_fopen(conn, name, "r", filep)) {
#ifdef DEBUG
@@ -4315,7 +4315,7 @@ open_auth_file(struct mg_connection *conn, const char *path, struct file *filep)
'/',
PASSWORDS_FILE_NAME);
/* TODO(high): kick client on buffer overflow */
/* TODO(high): kick client on buffer overflow */
if (!mg_fopen(conn, name, "r", filep)) {
#ifdef DEBUG
@@ -4610,7 +4610,7 @@ static int check_authorization(struct mg_connection *conn, const char *path)
(int)filename_vec.len,
filename_vec.ptr);
/* TODO(high): kick client on buffer overflow */
/* TODO(high): kick client on buffer overflow */
if (!mg_fopen(conn, fname, "r", &file)) {
mg_cry(conn,
@@ -4950,7 +4950,7 @@ static void print_dir_entry(struct de *de)
}
}
/* Note: mg_snprintf will not cause a buffer overflow above. */
/* Note: mg_snprintf will not cause a buffer overflow above. */
tm = localtime(&de->file.last_modified);
if (tm != NULL) {
@@ -5048,7 +5048,7 @@ static int scan_directory(struct mg_connection *conn,
mg_snprintf(
conn, path, sizeof(path), "%s%c%s", dir, '/', dp->d_name);
/* TODO(high): kick client on buffer overflow */
/* TODO(high): kick client on buffer overflow */
/* If we don't memset stat structure to zero, mtime will have
* garbage and strftime() will segfault later on in
@@ -5094,7 +5094,7 @@ static int remove_directory(struct mg_connection *conn, const char *dir)
mg_snprintf(
conn, path, sizeof(path), "%s%c%s", dir, '/', dp->d_name);
/* TODO(high): kick client on buffer overflow */
/* TODO(high): kick client on buffer overflow */
/* If we don't memset stat structure to zero, mtime will have
* garbage and strftime() will segfault later on in
@@ -5374,7 +5374,7 @@ static void handle_static_file_request(struct mg_connection *conn,
struct file *filep)
{
char date[64], lm[64], etag[64];
char range[128]; /* large enough, so there will be no overflow */
char range[128]; /* large enough, so there will be no overflow */
const char *msg = "OK", *hdr;
time_t curtime = time(NULL);
int64_t cl, r1, r2;
@@ -5405,7 +5405,7 @@ static void handle_static_file_request(struct mg_connection *conn,
if (filep->gzipped) {
mg_snprintf(conn, gz_path, sizeof(gz_path), "%s.gz", path);
/* TODO(high): kick client on buffer overflow */
/* TODO(high): kick client on buffer overflow */
path = gz_path;
encoding = "Content-Encoding: gzip\r\n";
@@ -5553,9 +5553,10 @@ static int is_valid_http_method(const char *method)
!strcmp(method, "HEAD") || !strcmp(method, "CONNECT") ||
!strcmp(method, "PUT") || !strcmp(method, "DELETE") ||
!strcmp(method, "OPTIONS") || !strcmp(method, "PROPFIND") ||
!strcmp(method, "MKCOL");
!strcmp(method, "MKCOL") || !strcmp(method, "PATCH");
/* TRACE method is not supported for security reasons */
/* PATCH method (RFC 5789) only allowed for CGI/Lua/LSP and callbacks. */
}
/* Parse HTTP request, fill in mg_request_info structure.
@@ -5855,7 +5856,7 @@ static char *addenv(struct cgi_env_block *block, const char *fmt, ...)
mg_vsnprintf(block->conn, added, (size_t)space, fmt, ap);
va_end(ap);
/* TODO(high): don't add partial environment variables */
/* TODO(high): don't add partial environment variables */
/* Number of bytes added to the environment */
n = strlen(added) + 1;
@@ -6045,7 +6046,7 @@ static void handle_cgi_request(struct mg_connection *conn, const char *prog)
* executable program name relative to 'dir'. */
(void)mg_snprintf(conn, dir, sizeof(dir), "%s", prog);
/* TODO(high): kick client on buffer overflow */
/* TODO(high): kick client on buffer overflow */
if ((p = strrchr(dir, '/')) != NULL) {
*p++ = '\0';
@@ -6540,7 +6541,7 @@ static void do_ssi_include(struct mg_connection *conn,
'/',
file_name);
/* TODO(high): kick client on buffer overflow */
/* TODO(high): kick client on buffer overflow */
} else if (sscanf(tag, " abspath=\"%511[^\"]\"", file_name) == 1) {
/* File name is relative to the webserver working directory
@@ -6548,7 +6549,7 @@ static void do_ssi_include(struct mg_connection *conn,
file_name[511] = 0;
(void)mg_snprintf(conn, path, sizeof(path), "%s", file_name);
/* TODO(high): kick client on buffer overflow */
/* TODO(high): kick client on buffer overflow */
} else if (sscanf(tag, " file=\"%511[^\"]\"", file_name) == 1 ||
sscanf(tag, " \"%511[^\"]\"", file_name) == 1) {
@@ -6556,7 +6557,7 @@ static void do_ssi_include(struct mg_connection *conn,
file_name[511] = 0;
(void)mg_snprintf(conn, path, sizeof(path), "%s", ssi);
/* TODO(high): kick client on buffer overflow */
/* TODO(high): kick client on buffer overflow */
if ((p = strrchr(path, '/')) != NULL) {
p[1] = '\0';
@@ -6565,7 +6566,7 @@ static void do_ssi_include(struct mg_connection *conn,
(void)mg_snprintf(
conn, path + len, sizeof(path) - len, "%s", file_name);
/* TODO(high): kick client on buffer overflow */
/* TODO(high): kick client on buffer overflow */
} else {
mg_cry(conn, "Bad SSI #include: [%s]", tag);
@@ -6817,7 +6818,7 @@ static void print_dav_dir_entry(struct de *de, void *data)
conn->request_info.uri,
de->file_name);
/* TODO(high): kick client on buffer overflow */
/* TODO(high): kick client on buffer overflow */
mg_url_encode(href, href_encoded, PATH_MAX - 1);
print_props(conn, href_encoded, &de->file);
@@ -7136,7 +7137,7 @@ static void send_websocket_handshake(struct mg_connection *conn)
mg_get_header(conn, "Sec-WebSocket-Key"),
magic);
/* TODO(high): kick client on buffer overflow */
/* TODO(high): kick client on buffer overflow */
SHA1Init(&sha_ctx);
SHA1Update(&sha_ctx, (unsigned char *)buf, (uint32_t)strlen(buf));
@@ -7658,7 +7659,7 @@ int mg_upload(struct mg_connection *conn, const char *destination_dir)
/* Different users should use a different destination_dir. */
mg_snprintf(conn, path, sizeof(path) - 1, "%s/%s", destination_dir, s);
/* TODO(high): kick client on buffer overflow */
/* TODO(high): kick client on buffer overflow */
strcpy(tmp_path, path);
strcat(tmp_path, "~");
@@ -8304,7 +8305,9 @@ static void handle_request(struct mg_connection *conn)
mkcol(conn, path);
return;
}
/* 11.4. should never reach this point */
/* 11.4. PATCH method
* This method is not supported for static resources,
* only for scripts (Lua, CGI) and callbacks. */
send_http_error(conn,
405,
"%s method not allowed",