Bläddra i källkod

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.
bel 10 år sedan
förälder
incheckning
e6a293590d
1 ändrade filer med 39 tillägg och 36 borttagningar
  1. 39 36
      src/civetweb.c

+ 39 - 36
src/civetweb.c

@@ -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",