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;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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";
|
||||||
|
@ -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
|
Reference in New Issue
Block a user