From 9d5ab8f683263d778c810222e0d3de9dbb5fda8e Mon Sep 17 00:00:00 2001 From: Dario Date: Tue, 3 Nov 2020 08:44:41 +0100 Subject: [PATCH] add option to fill consensus message with json representation of gradido transaction for easy debug --- src/cpp/ServerConfig.cpp | 713 ++++++++++++------------ src/cpp/ServerConfig.h | 185 +++--- src/cpp/model/gradido/Transaction.cpp | 41 +- src/cpp/model/gradido/TransactionBody.h | 1 + 4 files changed, 502 insertions(+), 438 deletions(-) diff --git a/src/cpp/ServerConfig.cpp b/src/cpp/ServerConfig.cpp index f319ea460..727c55e1c 100644 --- a/src/cpp/ServerConfig.cpp +++ b/src/cpp/ServerConfig.cpp @@ -1,349 +1,366 @@ -#include "ServerConfig.h" -#include "Crypto/mnemonic_german.h" -#include "Crypto/mnemonic_german2.h" -#include "Crypto/mnemonic_bip0039.h" -#include "Crypto/DRRandom.h" -#include "lib/DataTypeConverter.h" -#include "sodium.h" - - -#include "Poco/Net/SSLManager.h" -#include "Poco/Net/KeyConsoleHandler.h" -#include "Poco/Net/RejectCertificateHandler.h" -#include "Poco/Net/DNS.h" -#include "Poco/SharedPtr.h" - -#include "Poco/Mutex.h" -#include "Poco/Path.h" -#include "Poco/FileStream.h" -#include "Poco/LocalDateTime.h" -#include "Poco/DateTimeFormat.h" -#include "Poco/DateTimeFormatter.h" - - -using Poco::Net::SSLManager; -using Poco::Net::Context; -using Poco::Net::KeyConsoleHandler; -using Poco::Net::PrivateKeyPassphraseHandler; -using Poco::Net::InvalidCertificateHandler; -using Poco::Net::RejectCertificateHandler; -using Poco::SharedPtr; - -namespace ServerConfig { - -#define SESSION_TIMEOUT_DEFAULT 10 - - Mnemonic g_Mnemonic_WordLists[MNEMONIC_MAX]; - ObfusArray* g_ServerCryptoKey = nullptr; - ObfusArray* g_ServerKeySeed = nullptr; -// std::string g_ServerAdminPublic; - UniLib::controller::CPUSheduler* g_CPUScheduler = nullptr; - UniLib::controller::CPUSheduler* g_CryptoCPUScheduler = nullptr; - Context::Ptr g_SSL_CLient_Context = nullptr; - Poco::Util::Timer g_CronJobsTimer; - EmailAccount g_EmailAccount; - int g_SessionTimeout = SESSION_TIMEOUT_DEFAULT; - std::string g_serverPath; - int g_serverPort = 0; - Languages g_default_locale; - std::string g_php_serverPath; - std::string g_php_serverHost; - int g_phpServerPort; - Poco::Mutex g_TimeMutex; - int g_FakeLoginSleepTime = 820; - std::string g_versionString = ""; - bool g_disableEmail = false; - ServerSetupType g_ServerSetupType = SERVER_TYPE_PRODUCTION; - std::string g_gRPCRelayServerFullURL; - MemoryBin* g_CryptoAppSecret = nullptr; - AllowUnsecure g_AllowUnsecureFlags = NOT_UNSECURE; - -#ifdef __linux__ -#include -#include -#include -#include -#include -#include -#endif //#ifdef __linux__ - - std::string getHostIpString() - { -#ifdef __linux__ - struct ifaddrs * ifAddrStruct = NULL; - struct ifaddrs * ifa = NULL; - void * tmpAddrPtr = NULL; - - getifaddrs(&ifAddrStruct); - std::string ipAddressString; - - for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) { - if (!ifa->ifa_addr) { - continue; - } - if (ifa->ifa_addr->sa_family == AF_INET) { // check it is IP4 - // is a valid IP4 Address - tmpAddrPtr = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; - char addressBuffer[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN); - ipAddressString = addressBuffer; - printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer); - } - else if (ifa->ifa_addr->sa_family == AF_INET6) { // check it is IP6 - // is a valid IP6 Address - tmpAddrPtr = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; - char addressBuffer[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN); - printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer); - } - } - if (ifAddrStruct != NULL) freeifaddrs(ifAddrStruct); - return ipAddressString; -#else //__linux__ - std::string ipAddressString = ""; - auto host = Poco::Net::DNS::thisHost(); - for (auto it = host.addresses().begin(); it != host.addresses().end(); it++) { - auto ipAddress = *it; - if (!ipAddress.isIPv4Compatible() && !ipAddress.isIPv4Mapped()) { - continue; - } - if (ipAddress.isLoopback()) { - continue; - } - ipAddressString = ipAddress.toString(); - //isIPv4Compatible - //!isLoopback - //printf("ipaddress: %s\n", ipAddressString.data()); - break; - //break; - } - return ipAddressString; -#endif // __linux__ - } - - bool replaceZeroIPWithLocalhostIP(std::string& url) - { - auto pos = url.find("0.0.0.0", 0); - if (pos != std::string::npos) { - std::string ipAddressString = getHostIpString(); - if ("" != ipAddressString) { - url.replace(pos, 7, ipAddressString); - } - } - - //printf("ipaddress: %s\n", ipAddress.data()); - - return true; - } - - ServerSetupType getServerSetupTypeFromString(const std::string& serverSetupTypeString) { - if ("test" == serverSetupTypeString) { - return SERVER_TYPE_TEST; - } - if ("staging" == serverSetupTypeString) { - return SERVER_TYPE_STAGING; - } - if ("production" == serverSetupTypeString) { - return SERVER_TYPE_PRODUCTION; - } - return SERVER_TYPE_PRODUCTION; - } - - - bool loadMnemonicWordLists() - { - for (int i = 0; i < MNEMONIC_MAX; i++) { - int iResult = 0; - switch (i) { - case MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER: - iResult = g_Mnemonic_WordLists[i].init(populate_mnemonic_german, g_mnemonic_german_original_size, g_mnemonic_german_compressed_size); - if (iResult) { - printf("[%s] error init german mnemonic set, error nr: %d\n", __FUNCTION__, iResult); - return false; - } - g_Mnemonic_WordLists[i].printToFile("de_words.txt"); - break; - case MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER_FIXED_CASES: - iResult = g_Mnemonic_WordLists[i].init(populate_mnemonic_german2, g_mnemonic_german2_original_size, g_mnemonic_german2_compressed_size); - if (iResult) { - printf("[%s] error init german mnemonic set 2, error nr: %d\n", __FUNCTION__, iResult); - return false; - } - g_Mnemonic_WordLists[i].printToFile("de_words2.txt"); - break; - case MNEMONIC_BIP0039_SORTED_ORDER: - iResult = g_Mnemonic_WordLists[i].init(populate_mnemonic_bip0039, g_mnemonic_bip0039_original_size, g_mnemonic_bip0039_compressed_size); - if (iResult) { - printf("[%s] error init bip0039 mnemonic set, error nr: %d\n", __FUNCTION__, iResult); - return false; - } - //g_Mnemonic_WordLists[i].printToFile("en_words.txt"); - break; - default: printf("[%s] unknown MnemonicType\n", __FUNCTION__); return false; - } - } - return true; - } - - bool initServerCrypto(const Poco::Util::LayeredConfiguration& cfg) - { - auto serverKey = cfg.getString("crypto.server_key"); - unsigned char key[crypto_shorthash_KEYBYTES]; - size_t realBinSize = 0; - NULLPAD_10; - if (sodium_hex2bin(key, crypto_shorthash_KEYBYTES, serverKey.data(), serverKey.size(), nullptr, &realBinSize, nullptr)) { - printf("[%s] serverKey isn't valid hex: %s\n", __FUNCTION__, serverKey.data()); - return false; - } - if (realBinSize != crypto_shorthash_KEYBYTES) { - printf("[%s] serverKey hasn't valid size, expecting: %u, get: %lu\n", - __FUNCTION__, crypto_shorthash_KEYBYTES, realBinSize); - return false; - } - g_ServerCryptoKey = new ObfusArray(realBinSize, key); - g_ServerKeySeed = new ObfusArray(9*8); - Poco::Int64 i1 = randombytes_random(); - Poco::Int64 i2 = randombytes_random(); - g_ServerKeySeed->put(0, i1 | (i2 << 8)); - - //g_ServerAdminPublic = cfg.getString("crypto.server_admin_public"); - - DISASM_FALSERET; - g_SessionTimeout = cfg.getInt("session.timeout", SESSION_TIMEOUT_DEFAULT); - g_serverPath = cfg.getString("loginServer.path", ""); - replaceZeroIPWithLocalhostIP(g_serverPath); - g_default_locale = LanguageManager::languageFromString(cfg.getString("loginServer.default_locale")); - g_serverPort = cfg.getInt("loginServer.port", 0); - g_phpServerPort = cfg.getInt("phpServer.port", 0); - // replace 0.0.0.0 with actual server ip - - g_php_serverPath = cfg.getString("phpServer.url", ""); - replaceZeroIPWithLocalhostIP(g_php_serverPath); - g_php_serverHost = cfg.getString("phpServer.host", ""); - replaceZeroIPWithLocalhostIP(g_php_serverHost); - //g_ServerSetupType - auto serverSetupTypeString = cfg.getString("ServerSetupType", ""); - g_ServerSetupType = getServerSetupTypeFromString(serverSetupTypeString); - - // app secret for encrypt user private keys - // TODO: encrypt with server admin key - auto app_secret_string = cfg.getString("crypto.app_secret", ""); - if ("" != app_secret_string) { - g_CryptoAppSecret = DataTypeConverter::hexToBin(app_secret_string); - } - //g_CryptoAppSecret - - g_gRPCRelayServerFullURL = cfg.getString("grpc.server", ""); - - // unsecure flags - //g_AllowUnsecureFlags - if (cfg.getInt("unsecure.allow_passwort_via_json_request", 0) == 1) { - g_AllowUnsecureFlags = (AllowUnsecure)(g_AllowUnsecureFlags | UNSECURE_PASSWORD_REQUESTS); - } - if (cfg.getInt("unsecure.allow_auto_sign_transactions", 0) == 1) { - g_AllowUnsecureFlags = (AllowUnsecure)(g_AllowUnsecureFlags | UNSECURE_AUTO_SIGN_TRANSACTIONS); - } - if (cfg.getInt("unsecure.allow_cors_all", 0) == 1) { - g_AllowUnsecureFlags = (AllowUnsecure)(g_AllowUnsecureFlags | UNSECURE_CORS_ALL); - } - if (cfg.getInt("unsecure.allow_all_passwords", 0) == 1) { - g_AllowUnsecureFlags = (AllowUnsecure)(g_AllowUnsecureFlags | UNSECURE_ALLOW_ALL_PASSWORDS); - } - - return true; - } - - bool initEMailAccount(const Poco::Util::LayeredConfiguration& cfg) - { - g_disableEmail = cfg.getBool("email.disable", false); - if (g_disableEmail) { - printf("Email is disabled!\n"); - } - else { - g_EmailAccount.sender = cfg.getString("email.sender"); - g_EmailAccount.username = cfg.getString("email.username"); - g_EmailAccount.password = cfg.getString("email.password"); - g_EmailAccount.url = cfg.getString("email.smtp.url"); - g_EmailAccount.port = cfg.getInt("email.smtp.port"); - } - DISASM_FALSERET; - //g_ServerKeySeed->put(3, DRRandom::r64()); - return true; - } - - bool initSSLClientContext() - { - SharedPtr pCert = new RejectCertificateHandler(false); // reject invalid certificates - /* - Context(Usage usage, - const std::string& certificateNameOrPath, - VerificationMode verMode = VERIFY_RELAXED, - int options = OPT_DEFAULTS, - const std::string& certificateStoreName = CERT_STORE_MY); - */ - try { -#ifdef POCO_NETSSL_WIN - g_SSL_CLient_Context = new Context(Context::CLIENT_USE, "cacert.pem", Context::VERIFY_RELAXED, Context::OPT_DEFAULTS); -#else - - g_SSL_CLient_Context = new Context(Context::CLIENT_USE, "", "", Poco::Path::config() + "grd_login/cacert.pem", Context::VERIFY_RELAXED, 9, true, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); -#endif - } catch(Poco::Exception& ex) { - printf("[ServerConfig::initSSLClientContext] error init ssl context, maybe no cacert.pem found?\nPlease make sure you have cacert.pem (CA/root certificates) next to binary from https://curl.haxx.se/docs/caextract.html\n"); - return false; - } - DISASM_FALSERET; - SSLManager::instance().initializeClient(0, pCert, g_SSL_CLient_Context); - - g_ServerKeySeed->put(5, DRRandom::r64()); - - return true; - } - - void unload() { - if (g_ServerCryptoKey) { - delete g_ServerCryptoKey; - } - if (g_ServerKeySeed) { - delete g_ServerKeySeed; - } - if (g_CPUScheduler) { - delete g_CPUScheduler; - } - - if (g_CryptoCPUScheduler) { - delete g_CryptoCPUScheduler; - } - if (g_CryptoAppSecret) { - MemoryManager::getInstance()->releaseMemory(g_CryptoAppSecret); - g_CryptoAppSecret = nullptr; - } - } - - void writeToFile(std::istream& datas, std::string fileName) - { - static Poco::Mutex mutex; - - mutex.lock(); - - Poco::FileOutputStream file(fileName, std::ios::out | std::ios::app); - - if (!file.good()) { - printf("[ServerConfig::writeToFile] error creating file with name: %s\n", fileName.data()); - mutex.unlock(); - return; - } - - Poco::LocalDateTime now; - - std::string dateTimeStr = Poco::DateTimeFormatter::format(now, Poco::DateTimeFormat::ISO8601_FORMAT); - file << dateTimeStr << std::endl; - - for (std::string line; std::getline(datas, line); ) { - file << line << std::endl; - } - file << std::endl; - file.close(); - mutex.unlock(); - } +#include "ServerConfig.h" +#include "Crypto/mnemonic_german.h" +#include "Crypto/mnemonic_german2.h" +#include "Crypto/mnemonic_bip0039.h" +#include "Crypto/DRRandom.h" +#include "lib/DataTypeConverter.h" +#include "sodium.h" + + +#include "Poco/Net/SSLManager.h" +#include "Poco/Net/KeyConsoleHandler.h" +#include "Poco/Net/RejectCertificateHandler.h" +#include "Poco/Net/DNS.h" +#include "Poco/SharedPtr.h" + +#include "Poco/Mutex.h" +#include "Poco/Path.h" +#include "Poco/FileStream.h" +#include "Poco/LocalDateTime.h" +#include "Poco/DateTimeFormat.h" +#include "Poco/DateTimeFormatter.h" + + +using Poco::Net::SSLManager; +using Poco::Net::Context; +using Poco::Net::KeyConsoleHandler; +using Poco::Net::PrivateKeyPassphraseHandler; +using Poco::Net::InvalidCertificateHandler; +using Poco::Net::RejectCertificateHandler; +using Poco::SharedPtr; + +namespace ServerConfig { + +#define SESSION_TIMEOUT_DEFAULT 10 + + Mnemonic g_Mnemonic_WordLists[MNEMONIC_MAX]; + ObfusArray* g_ServerCryptoKey = nullptr; + ObfusArray* g_ServerKeySeed = nullptr; +// std::string g_ServerAdminPublic; + UniLib::controller::CPUSheduler* g_CPUScheduler = nullptr; + UniLib::controller::CPUSheduler* g_CryptoCPUScheduler = nullptr; + Context::Ptr g_SSL_CLient_Context = nullptr; + Poco::Util::Timer g_CronJobsTimer; + EmailAccount g_EmailAccount; + int g_SessionTimeout = SESSION_TIMEOUT_DEFAULT; + std::string g_serverPath; + int g_serverPort = 0; + Languages g_default_locale; + std::string g_php_serverPath; + std::string g_php_serverHost; + int g_phpServerPort; + Poco::Mutex g_TimeMutex; + int g_FakeLoginSleepTime = 820; + std::string g_versionString = ""; + bool g_disableEmail = false; + ServerSetupType g_ServerSetupType = SERVER_TYPE_PRODUCTION; + std::string g_gRPCRelayServerFullURL; + MemoryBin* g_CryptoAppSecret = nullptr; + HederaConsensusMessageFormat g_ConsensusMessageFormat = HEDERA_CONSENSUS_FORMAT_BINARY; + +#ifdef __linux__ +#include +#include +#include +#include +#include +#include +#endif //#ifdef __linux__ + + std::string getHostIpString() + { +#ifdef __linux__ + struct ifaddrs * ifAddrStruct = NULL; + struct ifaddrs * ifa = NULL; + void * tmpAddrPtr = NULL; + + getifaddrs(&ifAddrStruct); + std::string ipAddressString; + + for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) { + if (!ifa->ifa_addr) { + continue; + } + if (ifa->ifa_addr->sa_family == AF_INET) { // check it is IP4 + // is a valid IP4 Address + tmpAddrPtr = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; + char addressBuffer[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN); + ipAddressString = addressBuffer; + printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer); + } + else if (ifa->ifa_addr->sa_family == AF_INET6) { // check it is IP6 + // is a valid IP6 Address + tmpAddrPtr = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; + char addressBuffer[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN); + printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer); + } + } + if (ifAddrStruct != NULL) freeifaddrs(ifAddrStruct); + return ipAddressString; +#else //__linux__ + std::string ipAddressString = ""; + auto host = Poco::Net::DNS::thisHost(); + for (auto it = host.addresses().begin(); it != host.addresses().end(); it++) { + auto ipAddress = *it; + if (!ipAddress.isIPv4Compatible() && !ipAddress.isIPv4Mapped()) { + continue; + } + if (ipAddress.isLoopback()) { + continue; + } + ipAddressString = ipAddress.toString(); + //isIPv4Compatible + //!isLoopback + //printf("ipaddress: %s\n", ipAddressString.data()); + break; + //break; + } + return ipAddressString; +#endif // __linux__ + } + + bool replaceZeroIPWithLocalhostIP(std::string& url) + { + auto pos = url.find("0.0.0.0", 0); + if (pos != std::string::npos) { + std::string ipAddressString = getHostIpString(); + if ("" != ipAddressString) { + url.replace(pos, 7, ipAddressString); + } + } + + //printf("ipaddress: %s\n", ipAddress.data()); + + return true; + } + + ServerSetupType getServerSetupTypeFromString(const std::string& serverSetupTypeString) { + if ("test" == serverSetupTypeString) { + return SERVER_TYPE_TEST; + } + if ("staging" == serverSetupTypeString) { + return SERVER_TYPE_STAGING; + } + if ("production" == serverSetupTypeString) { + return SERVER_TYPE_PRODUCTION; + } + return SERVER_TYPE_PRODUCTION; + } + + HederaConsensusMessageFormat getHederaConsensusMessageFormatFromString(const std::string& hederaConsensusMessageFormatString) + { + if ("json" == hederaConsensusMessageFormatString) { + return HEDERA_CONSENSUS_FORMAT_JSON; + } + if ("binary" == hederaConsensusMessageFormatString || "bin" == hederaConsensusMessageFormatString) { + return HEDERA_CONSENSUS_FORMAT_BINARY; + } + if ("base64" == hederaConsensusMessageFormatString) { + return HEDERA_CONSENSUS_FORMAT_BASE64_URLSAVE_NO_PADDING; + } + return HEDERA_CONSENSUS_FORMAT_BINARY; + } + + + bool loadMnemonicWordLists() + { + for (int i = 0; i < MNEMONIC_MAX; i++) { + int iResult = 0; + switch (i) { + case MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER: + iResult = g_Mnemonic_WordLists[i].init(populate_mnemonic_german, g_mnemonic_german_original_size, g_mnemonic_german_compressed_size); + if (iResult) { + printf("[%s] error init german mnemonic set, error nr: %d\n", __FUNCTION__, iResult); + return false; + } + g_Mnemonic_WordLists[i].printToFile("de_words.txt"); + break; + case MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER_FIXED_CASES: + iResult = g_Mnemonic_WordLists[i].init(populate_mnemonic_german2, g_mnemonic_german2_original_size, g_mnemonic_german2_compressed_size); + if (iResult) { + printf("[%s] error init german mnemonic set 2, error nr: %d\n", __FUNCTION__, iResult); + return false; + } + g_Mnemonic_WordLists[i].printToFile("de_words2.txt"); + break; + case MNEMONIC_BIP0039_SORTED_ORDER: + iResult = g_Mnemonic_WordLists[i].init(populate_mnemonic_bip0039, g_mnemonic_bip0039_original_size, g_mnemonic_bip0039_compressed_size); + if (iResult) { + printf("[%s] error init bip0039 mnemonic set, error nr: %d\n", __FUNCTION__, iResult); + return false; + } + //g_Mnemonic_WordLists[i].printToFile("en_words.txt"); + break; + default: printf("[%s] unknown MnemonicType\n", __FUNCTION__); return false; + } + } + return true; + } + + bool initServerCrypto(const Poco::Util::LayeredConfiguration& cfg) + { + auto serverKey = cfg.getString("crypto.server_key"); + unsigned char key[crypto_shorthash_KEYBYTES]; + size_t realBinSize = 0; + NULLPAD_10; + if (sodium_hex2bin(key, crypto_shorthash_KEYBYTES, serverKey.data(), serverKey.size(), nullptr, &realBinSize, nullptr)) { + printf("[%s] serverKey isn't valid hex: %s\n", __FUNCTION__, serverKey.data()); + return false; + } + if (realBinSize != crypto_shorthash_KEYBYTES) { + printf("[%s] serverKey hasn't valid size, expecting: %u, get: %lu\n", + __FUNCTION__, crypto_shorthash_KEYBYTES, realBinSize); + return false; + } + g_ServerCryptoKey = new ObfusArray(realBinSize, key); + g_ServerKeySeed = new ObfusArray(9*8); + Poco::Int64 i1 = randombytes_random(); + Poco::Int64 i2 = randombytes_random(); + g_ServerKeySeed->put(0, i1 | (i2 << 8)); + + //g_ServerAdminPublic = cfg.getString("crypto.server_admin_public"); + + DISASM_FALSERET; + g_SessionTimeout = cfg.getInt("session.timeout", SESSION_TIMEOUT_DEFAULT); + g_serverPath = cfg.getString("loginServer.path", ""); + replaceZeroIPWithLocalhostIP(g_serverPath); + g_default_locale = LanguageManager::languageFromString(cfg.getString("loginServer.default_locale")); + g_serverPort = cfg.getInt("loginServer.port", 0); + g_phpServerPort = cfg.getInt("phpServer.port", 0); + // replace 0.0.0.0 with actual server ip + + g_php_serverPath = cfg.getString("phpServer.url", ""); + replaceZeroIPWithLocalhostIP(g_php_serverPath); + g_php_serverHost = cfg.getString("phpServer.host", ""); + replaceZeroIPWithLocalhostIP(g_php_serverHost); + //g_ServerSetupType + auto serverSetupTypeString = cfg.getString("ServerSetupType", ""); + g_ServerSetupType = getServerSetupTypeFromString(serverSetupTypeString); + + auto hedera_consensus_message_format_string = cfg.getString("hedera.consensus.message_format", "bin"); + g_ConsensusMessageFormat = getHederaConsensusMessageFormatFromString(hedera_consensus_message_format_string); + + // app secret for encrypt user private keys + // TODO: encrypt with server admin key + auto app_secret_string = cfg.getString("crypto.app_secret", ""); + if ("" != app_secret_string) { + g_CryptoAppSecret = DataTypeConverter::hexToBin(app_secret_string); + } + //g_CryptoAppSecret + + g_gRPCRelayServerFullURL = cfg.getString("grpc.server", ""); + + // unsecure flags + //g_AllowUnsecureFlags + if (cfg.getInt("unsecure.allow_passwort_via_json_request", 0) == 1) { + g_AllowUnsecureFlags = (AllowUnsecure)(g_AllowUnsecureFlags | UNSECURE_PASSWORD_REQUESTS); + } + if (cfg.getInt("unsecure.allow_auto_sign_transactions", 0) == 1) { + g_AllowUnsecureFlags = (AllowUnsecure)(g_AllowUnsecureFlags | UNSECURE_AUTO_SIGN_TRANSACTIONS); + } + if (cfg.getInt("unsecure.allow_cors_all", 0) == 1) { + g_AllowUnsecureFlags = (AllowUnsecure)(g_AllowUnsecureFlags | UNSECURE_CORS_ALL); + } + if (cfg.getInt("unsecure.allow_all_passwords", 0) == 1) { + g_AllowUnsecureFlags = (AllowUnsecure)(g_AllowUnsecureFlags | UNSECURE_ALLOW_ALL_PASSWORDS); + } + + return true; + } + + bool initEMailAccount(const Poco::Util::LayeredConfiguration& cfg) + { + g_disableEmail = cfg.getBool("email.disable", false); + if (g_disableEmail) { + printf("Email is disabled!\n"); + } + else { + g_EmailAccount.sender = cfg.getString("email.sender"); + g_EmailAccount.username = cfg.getString("email.username"); + g_EmailAccount.password = cfg.getString("email.password"); + g_EmailAccount.url = cfg.getString("email.smtp.url"); + g_EmailAccount.port = cfg.getInt("email.smtp.port"); + } + DISASM_FALSERET; + //g_ServerKeySeed->put(3, DRRandom::r64()); + return true; + } + + bool initSSLClientContext() + { + SharedPtr pCert = new RejectCertificateHandler(false); // reject invalid certificates + /* + Context(Usage usage, + const std::string& certificateNameOrPath, + VerificationMode verMode = VERIFY_RELAXED, + int options = OPT_DEFAULTS, + const std::string& certificateStoreName = CERT_STORE_MY); + */ + try { +#ifdef POCO_NETSSL_WIN + g_SSL_CLient_Context = new Context(Context::CLIENT_USE, "cacert.pem", Context::VERIFY_RELAXED, Context::OPT_DEFAULTS); +#else + + g_SSL_CLient_Context = new Context(Context::CLIENT_USE, "", "", Poco::Path::config() + "grd_login/cacert.pem", Context::VERIFY_RELAXED, 9, true, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); +#endif + } catch(Poco::Exception& ex) { + printf("[ServerConfig::initSSLClientContext] error init ssl context, maybe no cacert.pem found?\nPlease make sure you have cacert.pem (CA/root certificates) next to binary from https://curl.haxx.se/docs/caextract.html\n"); + return false; + } + DISASM_FALSERET; + SSLManager::instance().initializeClient(0, pCert, g_SSL_CLient_Context); + + g_ServerKeySeed->put(5, DRRandom::r64()); + + return true; + } + + void unload() { + if (g_ServerCryptoKey) { + delete g_ServerCryptoKey; + } + if (g_ServerKeySeed) { + delete g_ServerKeySeed; + } + if (g_CPUScheduler) { + delete g_CPUScheduler; + } + + if (g_CryptoCPUScheduler) { + delete g_CryptoCPUScheduler; + } + if (g_CryptoAppSecret) { + MemoryManager::getInstance()->releaseMemory(g_CryptoAppSecret); + g_CryptoAppSecret = nullptr; + } + } + + void writeToFile(std::istream& datas, std::string fileName) + { + static Poco::Mutex mutex; + + mutex.lock(); + + Poco::FileOutputStream file(fileName, std::ios::out | std::ios::app); + + if (!file.good()) { + printf("[ServerConfig::writeToFile] error creating file with name: %s\n", fileName.data()); + mutex.unlock(); + return; + } + + Poco::LocalDateTime now; + + std::string dateTimeStr = Poco::DateTimeFormatter::format(now, Poco::DateTimeFormat::ISO8601_FORMAT); + file << dateTimeStr << std::endl; + + for (std::string line; std::getline(datas, line); ) { + file << line << std::endl; + } + file << std::endl; + file.close(); + mutex.unlock(); + } } \ No newline at end of file diff --git a/src/cpp/ServerConfig.h b/src/cpp/ServerConfig.h index aef4ea28d..21c5c58e4 100644 --- a/src/cpp/ServerConfig.h +++ b/src/cpp/ServerConfig.h @@ -1,90 +1,97 @@ -#ifndef __GRADIDO_LOGIN_SERVER_SERVER_CONFIG__ -#define __GRADIDO_LOGIN_SERVER_SERVER_CONFIG__ - -#include "Crypto/mnemonic.h" -#include "Crypto/Obfus_array.h" -#include "Poco/Util/LayeredConfiguration.h" -#include "Poco/Net/Context.h" -#include "Poco/Types.h" -#include "Poco/Util/Timer.h" - -#include "tasks/CPUSheduler.h" - -#include "SingletonManager/LanguageManager.h" -#include "SingletonManager/MemoryManager.h" - -#define DISABLE_EMAIL - -namespace ServerConfig { - - enum Mnemonic_Types { - MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER, - MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER_FIXED_CASES, - MNEMONIC_BIP0039_SORTED_ORDER, - MNEMONIC_MAX - }; - // depracted, moved to email manager - struct EmailAccount { - std::string sender; - std::string admin_receiver; - std::string username; - std::string password; - std::string url; - int port; - }; - - enum ServerSetupType { - SERVER_TYPE_TEST, - SERVER_TYPE_STAGING, - SERVER_TYPE_PRODUCTION - }; - - // used with bit-operators, so only use numbers with control exactly one bit (1,2,4,8,16...) - enum AllowUnsecure { - NOT_UNSECURE = 0, - UNSECURE_PASSWORD_REQUESTS = 1, - UNSECURE_AUTO_SIGN_TRANSACTIONS = 2, - UNSECURE_CORS_ALL = 4, - UNSECURE_ALLOW_ALL_PASSWORDS = 8 - }; - - - extern Mnemonic g_Mnemonic_WordLists[MNEMONIC_MAX]; - - extern ObfusArray* g_ServerCryptoKey; - extern ObfusArray* g_ServerKeySeed; - - //extern unsigned char g_ServerAdminPublic[]; - extern UniLib::controller::CPUSheduler* g_CPUScheduler; - extern UniLib::controller::CPUSheduler* g_CryptoCPUScheduler; - extern Poco::Net::Context::Ptr g_SSL_CLient_Context; - extern Poco::Util::Timer g_CronJobsTimer; - extern EmailAccount g_EmailAccount; - extern int g_SessionTimeout; - extern std::string g_serverPath; - extern int g_serverPort; - extern Languages g_default_locale; - extern std::string g_php_serverPath; - extern std::string g_php_serverHost; - extern int g_phpServerPort; - extern Poco::Mutex g_TimeMutex; - extern int g_FakeLoginSleepTime; - extern std::string g_versionString; - extern bool g_disableEmail; - extern ServerSetupType g_ServerSetupType; - extern std::string g_gRPCRelayServerFullURL; - extern MemoryBin* g_CryptoAppSecret; - extern AllowUnsecure g_AllowUnsecureFlags; - - bool loadMnemonicWordLists(); - bool initServerCrypto(const Poco::Util::LayeredConfiguration& cfg); - bool initEMailAccount(const Poco::Util::LayeredConfiguration& cfg); - bool initSSLClientContext(); - - - void writeToFile(std::istream& datas, std::string fileName); - - void unload(); -}; - +#ifndef __GRADIDO_LOGIN_SERVER_SERVER_CONFIG__ +#define __GRADIDO_LOGIN_SERVER_SERVER_CONFIG__ + +#include "Crypto/mnemonic.h" +#include "Crypto/Obfus_array.h" +#include "Poco/Util/LayeredConfiguration.h" +#include "Poco/Net/Context.h" +#include "Poco/Types.h" +#include "Poco/Util/Timer.h" + +#include "tasks/CPUSheduler.h" + +#include "SingletonManager/LanguageManager.h" +#include "SingletonManager/MemoryManager.h" + +#define DISABLE_EMAIL + +namespace ServerConfig { + + enum Mnemonic_Types { + MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER, + MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER_FIXED_CASES, + MNEMONIC_BIP0039_SORTED_ORDER, + MNEMONIC_MAX + }; + // depracted, moved to email manager + struct EmailAccount { + std::string sender; + std::string admin_receiver; + std::string username; + std::string password; + std::string url; + int port; + }; + + enum ServerSetupType { + SERVER_TYPE_TEST, + SERVER_TYPE_STAGING, + SERVER_TYPE_PRODUCTION + }; + + // used with bit-operators, so only use numbers with control exactly one bit (1,2,4,8,16...) + enum AllowUnsecure { + NOT_UNSECURE = 0, + UNSECURE_PASSWORD_REQUESTS = 1, + UNSECURE_AUTO_SIGN_TRANSACTIONS = 2, + UNSECURE_CORS_ALL = 4, + UNSECURE_ALLOW_ALL_PASSWORDS = 8 + }; + + enum HederaConsensusMessageFormat { + HEDERA_CONSENSUS_FORMAT_BINARY, + HEDERA_CONSENSUS_FORMAT_JSON, + HEDERA_CONSENSUS_FORMAT_BASE64_URLSAVE_NO_PADDING + }; + + + extern Mnemonic g_Mnemonic_WordLists[MNEMONIC_MAX]; + + extern ObfusArray* g_ServerCryptoKey; + extern ObfusArray* g_ServerKeySeed; + + //extern unsigned char g_ServerAdminPublic[]; + extern UniLib::controller::CPUSheduler* g_CPUScheduler; + extern UniLib::controller::CPUSheduler* g_CryptoCPUScheduler; + extern Poco::Net::Context::Ptr g_SSL_CLient_Context; + extern Poco::Util::Timer g_CronJobsTimer; + extern EmailAccount g_EmailAccount; + extern int g_SessionTimeout; + extern std::string g_serverPath; + extern int g_serverPort; + extern Languages g_default_locale; + extern std::string g_php_serverPath; + extern std::string g_php_serverHost; + extern int g_phpServerPort; + extern Poco::Mutex g_TimeMutex; + extern int g_FakeLoginSleepTime; + extern std::string g_versionString; + extern bool g_disableEmail; + extern ServerSetupType g_ServerSetupType; + extern std::string g_gRPCRelayServerFullURL; + extern MemoryBin* g_CryptoAppSecret; + extern AllowUnsecure g_AllowUnsecureFlags; + extern HederaConsensusMessageFormat g_ConsensusMessageFormat; + + bool loadMnemonicWordLists(); + bool initServerCrypto(const Poco::Util::LayeredConfiguration& cfg); + bool initEMailAccount(const Poco::Util::LayeredConfiguration& cfg); + bool initSSLClientContext(); + + + void writeToFile(std::istream& datas, std::string fileName); + + void unload(); +}; + #endif //__GRADIDO_LOGIN_SERVER_SERVER_CONFIG__ \ No newline at end of file diff --git a/src/cpp/model/gradido/Transaction.cpp b/src/cpp/model/gradido/Transaction.cpp index 44b1ae708..d2c3605e4 100644 --- a/src/cpp/model/gradido/Transaction.cpp +++ b/src/cpp/model/gradido/Transaction.cpp @@ -12,6 +12,8 @@ #include "../../tasks/HederaTask.h" +#include + #include @@ -474,12 +476,49 @@ namespace model { { model::hedera::ConsensusSubmitMessage consensus_submit_message(topic_id); std::string raw_message = mProtoTransaction.SerializeAsString(); + + if (ServerConfig::HEDERA_CONSENSUS_FORMAT_BINARY == ServerConfig::g_ConsensusMessageFormat) { + consensus_submit_message.setMessage(raw_message); + } + else if (ServerConfig::HEDERA_CONSENSUS_FORMAT_BASE64_URLSAVE_NO_PADDING == ServerConfig::g_ConsensusMessageFormat) { + consensus_submit_message.setMessage(DataTypeConverter::binToBase64((const unsigned char*)raw_message.data(), raw_message.size(), sodium_base64_VARIANT_URLSAFE_NO_PADDING)); + } + else if (ServerConfig::HEDERA_CONSENSUS_FORMAT_JSON == ServerConfig::g_ConsensusMessageFormat) { + std::string json_message = ""; + std::string json_message_body = ""; + google::protobuf::util::JsonPrintOptions options; + options.add_whitespace = true; + options.always_print_primitive_fields = true; + + auto status = google::protobuf::util::MessageToJsonString(mProtoTransaction, &json_message, options); + if (!status.ok()) { + addError(new ParamError(function_name, "error by parsing transaction message to json", status.ToString())); + addError(new ParamError(function_name, "pending task id: ", getModel()->getID())); + sendErrorsAsEmail(); + return -7; + } + + status = google::protobuf::util::MessageToJsonString(*mTransactionBody->getBody(), &json_message_body, options); + if (!status.ok()) { + addError(new ParamError(function_name, "error by parsing transaction body message to json", status.ToString())); + addError(new ParamError(function_name, "pending task id: ", getModel()->getID())); + sendErrorsAsEmail(); + return -8; + } + //\"bodyBytes\": \"MigKIC7Sihz14RbYNhVAa8V3FSIhwvd0pWVvZqDnVA91dtcbIgRnZGQx\" + int startBodyBytes = json_message.find("bodyBytes") + std::string("\"bodyBytes\": \"").size()-2; + int endCur = json_message.find_first_of('\"', startBodyBytes+2)+1; + json_message.replace(startBodyBytes, endCur - startBodyBytes, json_message_body); + //printf("json: %s\n", json_message.data()); + + consensus_submit_message.setMessage(json_message); + } // if using testnet, transfer message base64 encoded to check messages in hedera block explorer //if (network_type == table::HEDERA_TESTNET) { //consensus_submit_message.setMessage(DataTypeConverter::binToBase64((const unsigned char*)raw_message.data(), raw_message.size(), sodium_base64_VARIANT_URLSAFE_NO_PADDING)); //} //else { - consensus_submit_message.setMessage(raw_message); + //} auto hedera_transaction_body = hedera_operator_account->createTransactionBody(); hedera_transaction_body->setConsensusSubmitMessage(consensus_submit_message); diff --git a/src/cpp/model/gradido/TransactionBody.h b/src/cpp/model/gradido/TransactionBody.h index 5bea7eccd..d79221b9f 100644 --- a/src/cpp/model/gradido/TransactionBody.h +++ b/src/cpp/model/gradido/TransactionBody.h @@ -49,6 +49,7 @@ namespace model { bool isGroupMemberUpdate() { Poco::ScopedLock _lock(mWorkMutex); return mType == TRANSACTION_GROUP_MEMBER_UPDATE; } std::string getBodyBytes(); + const proto::gradido::TransactionBody* getBody() { return &mTransactionBody; } TransactionCreation* getCreationTransaction(); TransactionTransfer* getTransferTransaction();