Add new template consts

ErrorOut+Log function
Submission upload utility functions
This commit is contained in:
Tina_Azure
2023-07-11 20:21:21 +02:00
parent d4d5b1888d
commit 55eecbb046
3 changed files with 190 additions and 7 deletions

View File

@ -17,13 +17,19 @@ using namespace std;
using namespace TemplateConstCollection; using namespace TemplateConstCollection;
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
Utilities::errorOut("Cavecomm Start", true);
Utilities::config configuration; Utilities::config configuration;
if (argc > 1) if (argc > 1)
configuration.configPath = argv[1]; configuration.configPath = argv[1];
#ifndef CROW_ENABLE_SSL
Utilities::errorOut("CROW_ENABLE_SSL is not defined and thus SSL is deactivated", true);
#endif
if (configuration.readConfigFile()) { if (configuration.readConfigFile()) {
cout << "ERROR: Unable to read configuration file: " << configuration.configPath << endl; Utilities::errorOut("Unable to read configuration file: " + configuration.configPath + "\nAborting Startup!");
cout << "Aborting Startup!" << endl;
return 1; return 1;
} }

View File

@ -87,6 +87,10 @@ namespace TemplateConstCollection {
const static std::string MUSTACHE_FREELANCER_TEMPLATE_OPERATION_FULFILMENT_EDIT = "OPERATION_EDIT"; const static std::string MUSTACHE_FREELANCER_TEMPLATE_OPERATION_FULFILMENT_EDIT = "OPERATION_EDIT";
const static std::string MUSTACHE_FREELANCER_TEMPLATE_OPERATION_FULFILMENT_DELETE = "OPERATION_DELETE"; const static std::string MUSTACHE_FREELANCER_TEMPLATE_OPERATION_FULFILMENT_DELETE = "OPERATION_DELETE";
const static std::string MUSTACHE_FREELANCER_SUBMISSION_NAME = "FILE_SUBMISSION"; 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_ALLOWED_FILE_TYPES_LIST_COMMA_SEPARATED = "ALLOWED_FILE_TYPES_LIST_COMMA_SEPARATED";
const static std::string MUSTACHE_FREELANCER_UPLOAD_AVAILIBLE = "UPLOAD_AVAILIBLE";
//Cookie names //Cookie names
const static std::string COOKIE_LOGIN_KEY = "loginKey"; const static std::string COOKIE_LOGIN_KEY = "loginKey";

View File

@ -10,6 +10,7 @@
#include <stdexcept> #include <stdexcept>
#include <thread> #include <thread>
#include <cmath> #include <cmath>
#include <unistd.h>
#include <openssl/sha.h> #include <openssl/sha.h>
#include <pqxx/pqxx> #include <pqxx/pqxx>
@ -34,6 +35,33 @@ namespace Utilities {
const static std::string MODULE_NAME_FREELANCER_RESET_KEY_CLEANER = "freelancerResetKeyCleaner"; const static std::string MODULE_NAME_FREELANCER_RESET_KEY_CLEANER = "freelancerResetKeyCleaner";
const static std::string MODULE_NAME_SUBMISSION_STORAGE_CLEANER = "submissionStorageCleaner"; const static std::string MODULE_NAME_SUBMISSION_STORAGE_CLEANER = "submissionStorageCleaner";
/*
* Outputs Error/Warning Messages and writes them to log.txt with a timestamp
*/
void errorOut(const std::string& errorMessage, bool warning = false) {
const auto timePointNow = std::chrono::system_clock::now();
const std::time_t time = std::chrono::system_clock::to_time_t(timePointNow);
if (warning)
std::cout << std::ctime(&time) << "----WARNING----" << std::endl;
else
std::cout << std::ctime(&time) << "----ERROR----" << std::endl;
std::cout << errorMessage << std::endl;
std::cout << "----------------" << std::endl;
std::ofstream logfile;
logfile.open("log.txt", std::ios_base::app);
logfile << std::endl << std::ctime(&time);
if (warning)
logfile << "----WARNING----" << std::endl;
else
logfile << "----ERROR----" << std::endl;
logfile << errorMessage << std::endl;
logfile << "----------------" << std::endl;
logfile.close();
}
/* /*
* Takes string to split it into a vector based on a given delimiter * Takes string to split it into a vector based on a given delimiter
*/ */
@ -68,6 +96,23 @@ namespace Utilities {
return true; return true;
} }
/*
* Checks if a path has a valid and accessible folder
*/
bool validateFolderWriteAccess(const std::string& path) {
if (path.empty())
return false;
if(access(path.c_str(), F_OK)) {
errorOut("submissionFileRootPath=" + path + " does not exist");
return false;
}
if(access(path.c_str(), R_OK | W_OK)) {
errorOut("submissionFileRootPath=" + path + " does not have Read/Write access");
return false;
}
return true;
}
/* /*
* Struct representing the configuration file * Struct representing the configuration file
*/ */
@ -92,6 +137,7 @@ namespace Utilities {
int itemsPerPage = 20; int itemsPerPage = 20;
int bruteForceMitigationLockSeconds = 900; int bruteForceMitigationLockSeconds = 900;
int bruteForceMitigationAttempts = 5; int bruteForceMitigationAttempts = 5;
std::string submissionFileRootPath;
int submissionMaxFileSizeMB = 4096; int submissionMaxFileSizeMB = 4096;
int submissionMaxtotalStorageMB = 131072; int submissionMaxtotalStorageMB = 131072;
int submissionMaxStorageDurationH = 0; int submissionMaxStorageDurationH = 0;
@ -112,6 +158,7 @@ namespace Utilities {
|| sslKeyPath.empty() || sslKeyPath.empty()
#endif #endif
|| domain.empty() || domain.empty()
|| !validateFolderWriteAccess(submissionFileRootPath)
) )
return 1; return 1;
@ -139,7 +186,7 @@ namespace Utilities {
} }
else { else {
errorLevel = 1; errorLevel = 1;
std::cout << "ERROR: Config file is invalid" << std::endl; errorOut("Config file is invalid");
break; break;
} }
} }
@ -228,6 +275,10 @@ namespace Utilities {
bruteForceMitigationAttempts = std::stoi(lineString); bruteForceMitigationAttempts = std::stoi(lineString);
continue; continue;
} }
if (lineVector.at(0) == "submissionFileRootPath") {
submissionFileRootPath = lineString;
continue;
}
if (lineVector.at(0) == "submissionMaxFileSizeMB") { if (lineVector.at(0) == "submissionMaxFileSizeMB") {
submissionMaxFileSizeMB = std::stoi(lineString); submissionMaxFileSizeMB = std::stoi(lineString);
continue; continue;
@ -354,10 +405,10 @@ namespace Utilities {
std::string createHashSha256(const std::string& str){ std::string createHashSha256(const std::string& str){
unsigned char hash[SHA256_DIGEST_LENGTH]; unsigned char hash[SHA256_DIGEST_LENGTH];
SHA512_CTX sha256; SHA256_CTX sha256;
SHA512_Init(&sha256); SHA256_Init(&sha256);
SHA512_Update(&sha256, str.c_str(), str.size()); SHA256_Update(&sha256, str.c_str(), str.size());
SHA512_Final(hash, &sha256); SHA256_Final(hash, &sha256);
std::stringstream ss; std::stringstream ss;
@ -367,6 +418,28 @@ namespace Utilities {
return ss.str(); return ss.str();
} }
/*
* Sha1 hash for quick hash creation with the option to vary digest length to a max of SHA_DIGEST_LENGTH (20)
*/
std::string createShrinkableHashSha1(const std::string& str, size_t digestLength = SHA_DIGEST_LENGTH){
if (digestLength > SHA_DIGEST_LENGTH)
digestLength = SHA_DIGEST_LENGTH;
unsigned char hash[digestLength];
SHA_CTX sha1;
SHA1_Init(&sha1);
SHA1_Update(&sha1, str.c_str(), str.size());
SHA1_Final(hash, &sha1);
std::stringstream ss;
for(int i = 0; i < digestLength; i++){
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>( hash[i] );
}
return ss.str();
}
/* /*
* Generates a salt using Mersenne Twister * Generates a salt using Mersenne Twister
*/ */
@ -474,6 +547,20 @@ namespace Utilities {
return createHashSha256(generateSalt() + generateSalt()); return createHashSha256(generateSalt() + generateSalt());
} }
/*
* Generates a hash based on a combination of 2 random salts
*/
std::string generateRandomHashValueSHA1() {
return createShrinkableHashSha1(generateSalt() + generateSalt());
}
/*
* Generates a hash based on a combination of 2 random salts with a limited length
*/
std::string generateRandomHashValueSHA1Short(size_t hashSize) {
return createShrinkableHashSha1(generateSalt() + generateSalt(), hashSize);
}
/* /*
* Generates a secure cookie * Generates a secure cookie
*/ */
@ -603,5 +690,91 @@ namespace Utilities {
std::string generateAliasRouteFreelancerTemplate(const std::string& freelancerName, const std::string& templateName) { std::string generateAliasRouteFreelancerTemplate(const std::string& freelancerName, const std::string& templateName) {
return "/customer/" + freelancerName + "/template/" + templateName; return "/customer/" + freelancerName + "/template/" + templateName;
} }
std::string generateSubmissionFolderPath(const Utilities::config& configuration, const std::string& freelancerName, const std::string& freelancerID){
std::string folderPath = configuration.submissionFileRootPath;
folderPath.append("/");
folderPath.append(freelancerName);
folderPath.append(".");
folderPath.append(freelancerID);
return folderPath;
}
std::string generateSubmissionFilePath(const std::string& folderPath, const std::string& fileName){
std::string filePath = folderPath;
filePath.append("/[");
filePath.append(generateRandomHashValueSHA1Short(5));
filePath.append("]");
filePath.append(fileName);
return filePath;
}
/*
* Checks if a path has a valid and accessible folder and creates the submission folder if it doesn't yet exist
* returns true at success
*/
bool validateFolderPath(const std::string& path) {
if (path.empty()) {
errorOut("submissionFolderPath is empty");
return false;
}
if(access(path.c_str(), F_OK)) {
int errorCode = mkdir(path.c_str(), 0777);
if (errorCode < 0) {
errorOut("submissionFolderPath=" + path + " unable to create folder.");
return false;
}
}
if(access(path.c_str(), R_OK | W_OK)) {
errorOut("submissionFolderPath=" + path + " does not have Read/Write access");
return false;
}
return true;
}
/*
* Checks if a file can be written to a path
* returns true at success
*/
bool validateFilePath(const std::string& path) {
if (path.empty()) {
errorOut("submissionFilePath is empty");
return false;
}
if(access(path.c_str(), F_OK) == 0) {
errorOut("submissionFilePath=" + path + " already exists");
return false;
}
return true;
}
/*
* Checks if a filetype is within the submissionAllowedFiletypes within the config
* takes the config and the filename which has to include the extension
*/
bool checkFiletypeValidity(const Utilities::config& configuration, const std::string& fileName){
bool validity = false;
std::string::size_type position;
position = fileName.rfind('.');
if(position != std::string::npos)
{
std::string extension = fileName.substr(position+1);
for (const std::string& whitelistExtension : configuration.submissionAllowedFiletypes) {
if(extension == whitelistExtension) {
validity = true;
break;
}
}
}
return validity;
}
bool validateFileSize(const Utilities::config& configuration, const std::string& file){
size_t fileSizeMegaBytes = file.size() / 1048576;
if (configuration.submissionMaxFileSizeMB < fileSizeMegaBytes)
return false;
return true;
}
} }
#endif #endif