Add new template consts
ErrorOut+Log function Submission upload utility functions
This commit is contained in:
10
src/main.cpp
10
src/main.cpp
@ -17,13 +17,19 @@ using namespace std;
|
||||
using namespace TemplateConstCollection;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
Utilities::errorOut("Cavecomm Start", true);
|
||||
|
||||
Utilities::config configuration;
|
||||
if (argc > 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()) {
|
||||
cout << "ERROR: Unable to read configuration file: " << configuration.configPath << endl;
|
||||
cout << "Aborting Startup!" << endl;
|
||||
Utilities::errorOut("Unable to read configuration file: " + configuration.configPath + "\nAborting Startup!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -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_DELETE = "OPERATION_DELETE";
|
||||
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
|
||||
const static std::string COOKIE_LOGIN_KEY = "loginKey";
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
#include <cmath>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openssl/sha.h>
|
||||
#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_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
|
||||
*/
|
||||
@ -68,6 +96,23 @@ namespace Utilities {
|
||||
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
|
||||
*/
|
||||
@ -92,6 +137,7 @@ namespace Utilities {
|
||||
int itemsPerPage = 20;
|
||||
int bruteForceMitigationLockSeconds = 900;
|
||||
int bruteForceMitigationAttempts = 5;
|
||||
std::string submissionFileRootPath;
|
||||
int submissionMaxFileSizeMB = 4096;
|
||||
int submissionMaxtotalStorageMB = 131072;
|
||||
int submissionMaxStorageDurationH = 0;
|
||||
@ -112,6 +158,7 @@ namespace Utilities {
|
||||
|| sslKeyPath.empty()
|
||||
#endif
|
||||
|| domain.empty()
|
||||
|| !validateFolderWriteAccess(submissionFileRootPath)
|
||||
)
|
||||
return 1;
|
||||
|
||||
@ -139,7 +186,7 @@ namespace Utilities {
|
||||
}
|
||||
else {
|
||||
errorLevel = 1;
|
||||
std::cout << "ERROR: Config file is invalid" << std::endl;
|
||||
errorOut("Config file is invalid");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -228,6 +275,10 @@ namespace Utilities {
|
||||
bruteForceMitigationAttempts = std::stoi(lineString);
|
||||
continue;
|
||||
}
|
||||
if (lineVector.at(0) == "submissionFileRootPath") {
|
||||
submissionFileRootPath = lineString;
|
||||
continue;
|
||||
}
|
||||
if (lineVector.at(0) == "submissionMaxFileSizeMB") {
|
||||
submissionMaxFileSizeMB = std::stoi(lineString);
|
||||
continue;
|
||||
@ -354,10 +405,10 @@ namespace Utilities {
|
||||
std::string createHashSha256(const std::string& str){
|
||||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||
|
||||
SHA512_CTX sha256;
|
||||
SHA512_Init(&sha256);
|
||||
SHA512_Update(&sha256, str.c_str(), str.size());
|
||||
SHA512_Final(hash, &sha256);
|
||||
SHA256_CTX sha256;
|
||||
SHA256_Init(&sha256);
|
||||
SHA256_Update(&sha256, str.c_str(), str.size());
|
||||
SHA256_Final(hash, &sha256);
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
@ -367,6 +418,28 @@ namespace Utilities {
|
||||
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
|
||||
*/
|
||||
@ -474,6 +547,20 @@ namespace Utilities {
|
||||
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
|
||||
*/
|
||||
@ -603,5 +690,91 @@ namespace Utilities {
|
||||
std::string generateAliasRouteFreelancerTemplate(const std::string& freelancerName, const std::string& 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
|
Reference in New Issue
Block a user