From 70c474051c2c687c4f07d56ab557d3eca062b58b Mon Sep 17 00:00:00 2001 From: Tina_Azure <-> Date: Mon, 31 Jul 2023 18:00:34 +0200 Subject: [PATCH] Add filepath size validation --- .gitignore | 1 + spec/spec.md | 2 + src/default-cavecomm.conf | 7 +-- src/main.cpp | 17 +++++-- src/templateConstCollection.cpp | 1 + src/utilities.cpp | 51 +++++++++++++++++-- .../freelancer_Submission_Management_Add.html | 3 ++ .../freelancerSubmissionUpload.js.html | 8 ++- 8 files changed, 78 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index ca1646b..fdfa364 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ example.crt example.key .idea/ log.txt +submissions/ diff --git a/spec/spec.md b/spec/spec.md index 2a12b87..e3da1ad 100644 --- a/spec/spec.md +++ b/spec/spec.md @@ -265,4 +265,6 @@ optional:{default} submissionMaxtotalStorageMB={131072} Filesize in MB; submissionMaxStorageDurationH={0} Duration in hours 0 = unlimited; submissionAllowedFiletypes={rar|zip|7z} Allowed file extensions like rar|zip|7z|webm|avi etc; + submissionMaxFileNameSize={255} 12 characters are used for hash, How big a file name can be the default persumes the NAME_MAX length within common file systems + submissionMaxFilePathSize={4096} How big a file path can be the default persumes the PATH_MAX length within common file systems diff --git a/src/default-cavecomm.conf b/src/default-cavecomm.conf index 8c229e8..de9f83d 100644 --- a/src/default-cavecomm.conf +++ b/src/default-cavecomm.conf @@ -27,7 +27,8 @@ # submissionMaxtotalStorageMB={131072} # Filesize in MB; # submissionMaxStorageDurationH={0} # Duration in hours 0 = unlimited; # submissionAllowedFiletypes={rar|zip|7z} # Allowed file extensions like rar|zip|7z|webm|avi etc; -# submissionDeletedFileRetentionForNextCycle={true} # File deletion will be executed on the execution of the next Regular Task Execution cylce if true, if false file deletion will be executed immediately. +# submissionMaxFileNameSize={255} # 12 characters are used for hash, How big a file name can be the default persumes the NAME_MAX length within common file systems +# submissionMaxFilePathSize={4096} # How big a file path can be the default persumes the PATH_MAX length within common file systems @@ -58,7 +59,7 @@ submissionMaxFileSizeMB=8; submissionMaxtotalStorageMB=16; submissionMaxStorageDurationH=24; submissionAllowedFiletypes=rar|zip|7z|arc|jpg|jpeg|png|mp4|webm; -submissionDeletedFileRetentionForNextCycle=false; - +submissionMaxFileNameSize=255; +submissionMaxFilePathSize=4096; #configend# diff --git a/src/main.cpp b/src/main.cpp index 9839013..c553f88 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -33,6 +33,8 @@ int main(int argc, char *argv[]) { return 1; } + configuration.calculateBaseDirectoryPathSize(argv[0]); + //simple email test, header validation via https://mailheader.org/ //SMTPManager::sendEmail(configuration, "mail@mail.de", "testsubject", "

bluetest


blue
yellow"); //return 0; @@ -985,6 +987,7 @@ int main(int argc, char *argv[]) { size_t maxStorageInMB = configuration.submissionMaxtotalStorageMB; ctx[MUSTACHE_FREELANCER_AVAILIBLE_STORAGE_IN_MB] = usedStorageInMB; ctx[MUSTACHE_FREELANCER_MAXIMUM_STORAGE_IN_MB] = maxStorageInMB; + ctx[MUSTACHE_FREELANCER_MAXIMUM_FILE_NAME_SIZE] = configuration.submissionMaxFileNameSize; string allowedFiletypes; for (const string &filetype: configuration.submissionAllowedFiletypes) { @@ -1067,11 +1070,14 @@ int main(int argc, char *argv[]) { string filename = postRequest.body.substr(filenamePositionStart, contentDispositionTypeEnd - filenamePositionStart - 1); - if (!Utilities::checkFiletypeValidity(configuration, filename)) { + if (!Utilities::checkFiletypeValidity(configuration, filename)) return crow::response(400, "Submitted File does not have a valid filetype"); - if (!Utilities::validateFileSize(configuration, postRequest.body)) - return crow::response(400, "File Size is not valid"); - } + + if (!Utilities::validateFileSize(configuration, postRequest.body)) + return crow::response(400, "File Size is not valid"); + + if (!Utilities::validateFileNameSize(configuration, filename)) + return crow::response(400, "Filename too long"); const std::string outputFolderPath = Utilities::generateSubmissionFolderPath(configuration, freelancerName, freelancerID); @@ -1084,6 +1090,9 @@ int main(int argc, char *argv[]) { if (!Utilities::validateFilePath(outputFilePath)) return crow::response(400, "file already exists - hash collision"); + if (!Utilities::validateFilePathSize(configuration, outputFilePath)) + return crow::response(400, "Filepath too long"); + std::ofstream outputFileStream(outputFilePath); if (!outputFileStream) return crow::response(500, "File could not be written to disk"); diff --git a/src/templateConstCollection.cpp b/src/templateConstCollection.cpp index 07be521..349668c 100644 --- a/src/templateConstCollection.cpp +++ b/src/templateConstCollection.cpp @@ -89,6 +89,7 @@ namespace TemplateConstCollection { const static std::string MUSTACHE_FREELANCER_SUBMISSION_NAME = "FILE_SUBMISSION"; const static std::string MUSTACHE_FREELANCER_AVAILIBLE_STORAGE_IN_MB = "AVAILIBLE_STORAGE_IN_MB"; const static std::string MUSTACHE_FREELANCER_MAXIMUM_STORAGE_IN_MB = "MAXIMUM_STORAGE_IN_MB"; + const static std::string MUSTACHE_FREELANCER_MAXIMUM_FILE_NAME_SIZE = "MAXIMUM_FILE_NAME_SIZE"; const static std::string MUSTACHE_FREELANCER_ALLOWED_FILE_TYPES_LIST_COMMA_SEPARATED = "ALLOWED_FILE_TYPES_LIST_COMMA_SEPARATED"; const static std::string MUSTACHE_FREELANCER_UPLOAD_AVAILIBLE = "UPLOAD_AVAILIBLE"; diff --git a/src/utilities.cpp b/src/utilities.cpp index 1517a19..fccfa1a 100644 --- a/src/utilities.cpp +++ b/src/utilities.cpp @@ -142,7 +142,17 @@ namespace Utilities { int submissionMaxtotalStorageMB = 131072; int submissionMaxStorageDurationH = 0; std::vector submissionAllowedFiletypes = {"rar", "zip","7z"}; - bool submissionDeletedFileRetentionForNextCycle = true; + int submissionMaxFileNameSize = 255; + int submissionMaxFilePathSize = 4096; + int baseDirectoryPathSize = 0; + + /* + * calculates absolute file path length based on submission directory and current path + */ + void calculateBaseDirectoryPathSize(const std::string& baseDirectory) { + std::string baseDir = baseDirectory.substr(0, baseDirectory.rfind('/') + 1); + baseDirectoryPathSize = baseDir.size(); + } /* * validates existence of mandatory variables in config @@ -296,8 +306,12 @@ namespace Utilities { submissionAllowedFiletypes = Utilities::splitStringIntoVector(lineString, '|'); continue; } - if (lineVector.at(0) == "submissionDeletedFileRetentionForNextCycle") { - submissionDeletedFileRetentionForNextCycle = (lineString == "true"); + if (lineVector.at(0) == "submissionMaxFileNameSize") { + submissionMaxFileNameSize = std::stoi(lineString); + continue; + } + if (lineVector.at(0) == "submissionMaxFilePathSize") { + submissionMaxFilePathSize = std::stoi(lineString); continue; } } @@ -775,6 +789,37 @@ namespace Utilities { return validity; } + /* + * Checks if a filename size is within the limit of submissionMaxFileNameSize + * takes the config and the filename which has to include the extension + */ + bool validateFileNameSize(const Utilities::config& configuration, const std::string& fileName){ + bool validity = false; + if (configuration.submissionMaxFileNameSize >= fileName.size()) + validity = true; + return validity; + } + + /* + * Checks if a filepath size is within the limit of submissionMaxFilePathSize + * takes the config and the filename which has to include the extension + */ + bool validateFilePathSize(const Utilities::config& configuration, const std::string& filePath){ + bool validity = false; + std::size_t filePathSize = configuration.baseDirectoryPathSize; + std::string submissionPathRelativityValidation = filePath.substr(0, 2); + if (submissionPathRelativityValidation == "./") { //relative path with . token + filePathSize = filePathSize + filePath.size() - 2; + } else if (submissionPathRelativityValidation[0] == '/') { //absolute path + filePathSize = filePath.size(); + } else { //relative path without . token + filePathSize = filePathSize + filePath.size(); + } + if (configuration.submissionMaxFilePathSize >= filePathSize) + validity = true; + return validity; + } + bool validateFileSize(const Utilities::config& configuration, const std::string& file){ size_t fileSizeMegaBytes = file.size() / 1048576; if (configuration.submissionMaxFileSizeMB < fileSizeMegaBytes) diff --git a/templates/freelancer_Submission_Management_Add.html b/templates/freelancer_Submission_Management_Add.html index 443e4d4..972c077 100644 --- a/templates/freelancer_Submission_Management_Add.html +++ b/templates/freelancer_Submission_Management_Add.html @@ -16,6 +16,9 @@

Allowed File Types: {{ALLOWED_FILE_TYPES_LIST_COMMA_SEPARATED}}

+

+ Allowed File Name Length: {{MAXIMUM_FILE_NAME_SIZE}} +

{{#UPLOAD_AVAILIBLE}}
diff --git a/templates/templateIncludes/freelancerSubmissionUpload.js.html b/templates/templateIncludes/freelancerSubmissionUpload.js.html index c5cdb38..686e044 100644 --- a/templates/templateIncludes/freelancerSubmissionUpload.js.html +++ b/templates/templateIncludes/freelancerSubmissionUpload.js.html @@ -8,12 +8,16 @@ var file = _("FILE_SUBMISSION").files[0]; const fileSize = file.size / 1024 / 1024; const maxSize = {{MAXIMUM_STORAGE_IN_MB}} - {{AVAILIBLE_STORAGE_IN_MB}}; + const maxFileNameLength = {{MAXIMUM_FILE_NAME_SIZE}}; console.log(maxSize); - + console.log(maxFileNameLength); if (fileSize > maxSize) { alert('File size exceeds availible space by: ' + (Math.trunc((fileSize - maxSize) * 100) / 100) + ' MB'); unHide(); - } + } else if(file.name.length > maxFileNameLength) { + alert('File name exceeds allowed length by ' + (file.name.length - maxFileNameLength) + ' characters'); + unHide(); + } else { var formdata = new FormData(); formdata.append("FILE_SUBMISSION", file);