From 9bc8e297c0f6fe1be1d2ae34e41afb94ad7dc38d Mon Sep 17 00:00:00 2001 From: Karai Csaba Date: Sat, 30 Apr 2016 20:24:10 +0200 Subject: [PATCH] handle invalid upload --- esp-link/cgiwebserver.c | 23 ++++++++++++++---- httpd/multipart.c | 53 ++++++++++++++++++++++++++++------------- httpd/multipart.h | 5 ++-- 3 files changed, 58 insertions(+), 23 deletions(-) diff --git a/esp-link/cgiwebserver.c b/esp-link/cgiwebserver.c index 194b585..8dbe042 100644 --- a/esp-link/cgiwebserver.c +++ b/esp-link/cgiwebserver.c @@ -5,27 +5,40 @@ #include "cgi.h" #include "cgioptiboot.h" #include "multipart.h" +#include "espfsformat.h" -void webServerMultipartCallback(MultipartCmd cmd, char *data, int dataLen, int position) +int webServerMultipartCallback(MultipartCmd cmd, char *data, int dataLen, int position) { switch(cmd) { case FILE_START: - os_printf("CB: File start: %s\n", data); + // do nothing break; case FILE_DATA: - os_printf("CB: Data (%d): %s\n", position, data); + if( position < 4 ) + { + for(int p = position; p < 4; p++ ) + { + if( data[p - position] != ((ESPFS_MAGIC >> (p * 8) ) & 255 ) ) + { + os_printf("Not an espfs image!\n"); + return 1; + } + data[p - position] = 0xFF; // clean espfs magic to mark as invalid + } + } + // TODO: flash write break; case FILE_DONE: - os_printf("CB: Done\n"); + // TODO: finalize changes, set back espfs magic break; } + return 0; } MultipartCtx webServerContext = {.callBack = webServerMultipartCallback, .position = 0, .recvPosition = 0, .startTime = 0, .boundaryBuffer = NULL}; int ICACHE_FLASH_ATTR cgiWebServerUpload(HttpdConnData *connData) { - os_printf("WebServer upload\n"); return multipartProcess(&webServerContext, connData); } diff --git a/httpd/multipart.c b/httpd/multipart.c index e4a99a4..813ac82 100644 --- a/httpd/multipart.c +++ b/httpd/multipart.c @@ -22,7 +22,7 @@ void multipartFreeBoundaryBuffer(MultipartCtx * context) } } -void multipartProcessBoundaryBuffer(MultipartCtx * context, char * boundary, char * buff, int len, int last) +int multipartProcessBoundaryBuffer(MultipartCtx * context, char * boundary, char * buff, int len, int last) { if( len != 0 ) { @@ -35,7 +35,7 @@ void multipartProcessBoundaryBuffer(MultipartCtx * context, char * boundary, cha while( context->boundaryBufferPtr > 0 ) { if( ! last && context->boundaryBufferPtr <= 2 * BOUNDARY_SIZE ) - return; + return 0; int dataSize = BOUNDARY_SIZE; @@ -96,7 +96,8 @@ void multipartProcessBoundaryBuffer(MultipartCtx * context, char * boundary, cha { context->boundaryBuffer[pos] = 0; os_printf("Uploading file: %s\n", context->boundaryBuffer + start); - context->callBack( FILE_START, context->boundaryBuffer + start, pos - start, 0 ); + if( context->callBack( FILE_START, context->boundaryBuffer + start, pos - start, 0 ) ) + return 1; context->boundaryBuffer[pos] = '"'; context->state = STATE_SEARCH_HEADER_END; } @@ -111,7 +112,8 @@ void multipartProcessBoundaryBuffer(MultipartCtx * context, char * boundary, cha { char c = context->boundaryBuffer[dataSize]; context->boundaryBuffer[dataSize] = 0; // add terminating zero (for easier handling) - context->callBack( FILE_DATA, context->boundaryBuffer, dataSize, context->position ); + if( context->callBack( FILE_DATA, context->boundaryBuffer, dataSize, context->position ) ) + return 1; context->boundaryBuffer[dataSize] = c; context->position += dataSize; } @@ -126,7 +128,8 @@ void multipartProcessBoundaryBuffer(MultipartCtx * context, char * boundary, cha dataSize += os_strlen(boundary); if( context->state == STATE_UPLOAD_FILE ) { - context->callBack( FILE_DONE, NULL, 0, context->position ); + if( context->callBack( FILE_DONE, NULL, 0, context->position ) ) + return 1; os_printf("File upload done\n"); } @@ -136,6 +139,7 @@ void multipartProcessBoundaryBuffer(MultipartCtx * context, char * boundary, cha context->boundaryBufferPtr -= dataSize; os_memcpy(context->boundaryBuffer, context->boundaryBuffer + dataSize, context->boundaryBufferPtr); } + return 0; } int ICACHE_FLASH_ATTR multipartProcess(MultipartCtx * context, HttpdConnData * connData ) @@ -162,25 +166,42 @@ int ICACHE_FLASH_ATTR multipartProcess(MultipartCtx * context, HttpdConnData * c multipartAllocBoundaryBuffer(context); } - int feed = 0; - while( feed < post->buffLen ) + if( context->state != STATE_ERROR ) { - int len = post->buffLen - feed; - if( len > BOUNDARY_SIZE ) - len = BOUNDARY_SIZE; - multipartProcessBoundaryBuffer(context, post->multipartBoundary, post->buff + feed, len, 0); - feed += len; + int feed = 0; + while( feed < post->buffLen ) + { + int len = post->buffLen - feed; + if( len > BOUNDARY_SIZE ) + len = BOUNDARY_SIZE; + if( multipartProcessBoundaryBuffer(context, post->multipartBoundary, post->buff + feed, len, 0) ) + { + context->state = STATE_ERROR; + break; + } + feed += len; + } } context->recvPosition += post->buffLen; if( context->recvPosition < post->len ) return HTTPD_CGI_MORE; - multipartProcessBoundaryBuffer(context, post->multipartBoundary, NULL, 0, 1); + if( context->state != STATE_ERROR ) + { + if( multipartProcessBoundaryBuffer(context, post->multipartBoundary, NULL, 0, 1) ) + context->state = STATE_ERROR; + } + multipartFreeBoundaryBuffer( context ); - - httpdStartResponse(connData, 204); - httpdEndHeaders(connData); + + if( context->state == STATE_ERROR ) + errorResponse(connData, 400, "Invalid file upload!"); + else + { + httpdStartResponse(connData, 204); + httpdEndHeaders(connData); + } return HTTPD_CGI_DONE; } else { diff --git a/httpd/multipart.h b/httpd/multipart.h index 76e15c4..d22815d 100644 --- a/httpd/multipart.h +++ b/httpd/multipart.h @@ -13,10 +13,11 @@ typedef enum { STATE_SEARCH_BOUNDARY = 0, STATE_SEARCH_HEADER, STATE_SEARCH_HEADER_END, - STATE_UPLOAD_FILE + STATE_UPLOAD_FILE, + STATE_ERROR, } MultipartState; -typedef void (* MultipartCallback)(MultipartCmd cmd, char *data, int dataLen, int position); +typedef int (* MultipartCallback)(MultipartCmd cmd, char *data, int dataLen, int position); typedef struct { MultipartCallback callBack;