diff --git a/src/cpp/JSONInterface/JsonCreateUser.cpp b/src/cpp/JSONInterface/JsonCreateUser.cpp index 63d1cf1f4..0c8d2316f 100644 --- a/src/cpp/JSONInterface/JsonCreateUser.cpp +++ b/src/cpp/JSONInterface/JsonCreateUser.cpp @@ -5,14 +5,19 @@ #include "../controller/EmailVerificationCode.h" #include "../SingletonManager/EmailManager.h" +#include "../SingletonManager/SessionManager.h" + +#include "../tasks/AuthenticatedEncryptionCreateKeyTask.h" Poco::JSON::Object* JsonCreateUser::handle(Poco::Dynamic::Var params) { std::string email; std::string first_name; std::string last_name; + std::string password; int emailType; auto em = EmailManager::getInstance(); + auto sm = SessionManager::getInstance(); // if is json object if (params.type() == typeid(Poco::JSON::Object::Ptr)) { @@ -27,6 +32,9 @@ Poco::JSON::Object* JsonCreateUser::handle(Poco::Dynamic::Var params) paramJsonObject->get("first_name").convert(first_name); paramJsonObject->get("last_name").convert(last_name); paramJsonObject->get("emailType").convert(emailType); + if ((ServerConfig::g_AllowUnsecureFlags & ServerConfig::UNSECURE_PASSWORD_REQUESTS)) { + paramJsonObject->get("password").convert(password); + } } catch (Poco::Exception& ex) { return stateError("json exception", ex.displayText()); @@ -38,19 +46,43 @@ Poco::JSON::Object* JsonCreateUser::handle(Poco::Dynamic::Var params) auto user = controller::User::create(); if (user->load(email) > 0) { - Poco::JSON::Object* result = new Poco::JSON::Object; - result->set("state", "exist"); - result->set("msg", "user already exist"); - return result; + return customStateError("exist", "user already exist"); + } + + if (password.size()) { + ErrorList errors; + if (!sm->checkPwdValidation(password, &errors)) { + Poco::JSON::Object* result = new Poco::JSON::Object; + result->set("state", "error"); + result->set("msg", errors.getLastError()->getString(false)); + if (errors.errorCount()) { + result->set("details", errors.getLastError()->getString(false)); + } + return result; + } } // create user user = controller::User::create(email, first_name, last_name); auto userModel = user->getModel(); + Session* session = nullptr; + if (!userModel->insertIntoDB(true)) { userModel->sendErrorsAsEmail(); return stateError("insert user failed"); } + + if (password.size()) { + session = sm->getNewSession(); + session->setUser(user); + session->generateKeys(true, true); + session->setClientIp(mClientIP); + + // calculate encryption key, could need some time, will save encrypted privkey to db + UniLib::controller::TaskPtr create_authenticated_encrypten_key = new AuthenticatedEncryptionCreateKeyTask(user, password); + create_authenticated_encrypten_key->scheduleTask(create_authenticated_encrypten_key); + } + auto emailOptIn = controller::EmailVerificationCode::create(userModel->getID(), model::table::EMAIL_OPT_IN_REGISTER); auto emailOptInModel = emailOptIn->getModel(); if (!emailOptInModel->insertIntoDB(false)) { diff --git a/src/cpp/JSONInterface/JsonCreateUser.h b/src/cpp/JSONInterface/JsonCreateUser.h index a7123f12a..19b174752 100644 --- a/src/cpp/JSONInterface/JsonCreateUser.h +++ b/src/cpp/JSONInterface/JsonCreateUser.h @@ -6,9 +6,11 @@ class JsonCreateUser : public JsonRequestHandler { public: + JsonCreateUser(Poco::Net::IPAddress ip) : mClientIP(ip) {} Poco::JSON::Object* handle(Poco::Dynamic::Var params); protected: + Poco::Net::IPAddress mClientIP; }; diff --git a/src/cpp/JSONInterface/JsonRequestHandlerFactory.cpp b/src/cpp/JSONInterface/JsonRequestHandlerFactory.cpp index e58f6b464..aed26c939 100644 --- a/src/cpp/JSONInterface/JsonRequestHandlerFactory.cpp +++ b/src/cpp/JSONInterface/JsonRequestHandlerFactory.cpp @@ -13,6 +13,7 @@ #include "JsonAdminEmailVerificationResend.h" #include "JsonGetUserInfos.h" #include "JsonUpdateUserInfos.h" +#include "JsonUnsecureLogin.h" JsonRequestHandlerFactory::JsonRequestHandlerFactory() : mRemoveGETParameters("^/([a-zA-Z0-9_-]*)"), mLogging(Poco::Logger::get("requestLog")) @@ -45,7 +46,7 @@ Poco::Net::HTTPRequestHandler* JsonRequestHandlerFactory::createRequestHandler(c return new JsonGetUsers; } else if (url_first_part == "/createUser") { - return new JsonCreateUser; + return new JsonCreateUser(request.clientAddress().host()); } else if (url_first_part == "/adminEmailVerificationResend") { return new JsonAdminEmailVerificationResend; @@ -56,6 +57,9 @@ Poco::Net::HTTPRequestHandler* JsonRequestHandlerFactory::createRequestHandler(c else if (url_first_part == "/updateUserInfos") { return new JsonUpdateUserInfos; } + else if (url_first_part == "/unsecureLogin" && (ServerConfig::g_AllowUnsecureFlags & ServerConfig::UNSECURE_PASSWORD_REQUESTS)) { + return new JsonUnsecureLogin(request.clientAddress().host()); + } return new JsonUnknown; } diff --git a/src/cpp/JSONInterface/JsonUnsecureLogin.cpp b/src/cpp/JSONInterface/JsonUnsecureLogin.cpp new file mode 100644 index 000000000..18080cfa6 --- /dev/null +++ b/src/cpp/JSONInterface/JsonUnsecureLogin.cpp @@ -0,0 +1,114 @@ +#include "JsonUnsecureLogin.h" + +#include "../SingletonManager/SessionManager.h" +#include "../SingletonManager/SingletonTaskObserver.h" +#include "../SingletonManager/ErrorManager.h" + +#include "../controller/User.h" + +#include "../lib/DataTypeConverter.h" + +Poco::JSON::Object* JsonUnsecureLogin::handle(Poco::Dynamic::Var params) +{ + + auto sm = SessionManager::getInstance(); + auto observer = SingletonTaskObserver::getInstance(); + auto em = ErrorManager::getInstance(); + + /* + 'username', 'password' + */ + // incoming + + std::string email; + std::string password; + + // if is json object + if (params.type() == typeid(Poco::JSON::Object::Ptr)) { + Poco::JSON::Object::Ptr paramJsonObject = params.extract(); + /// Throws a RangeException if the value does not fit + /// into the result variable. + /// Throws a NotImplementedException if conversion is + /// not available for the given type. + /// Throws InvalidAccessException if Var is empty. + try { + paramJsonObject->get("email").convert(email); + paramJsonObject->get("password").convert(password); + } + catch (Poco::Exception& ex) { + return stateError("json exception", ex.displayText()); + } + } + else { + return stateError("parameter format unknown"); + } + + + if (!email.size() || !sm->isValid(email, VALIDATE_EMAIL)) { + return stateError("invalid or empty email"); + } + auto user = controller::User::create(); + if (1 != user->load(email)) { + return stateError("user with email not found", email); + } + + ErrorList pwd_errors; + Poco::JSON::Object* result = new Poco::JSON::Object; + + if (!password.size() || !sm->checkPwdValidation(password, &pwd_errors)) { + + result->set("state", "error"); + result->set("msg", pwd_errors.getLastError()->getString(false)); + if (pwd_errors.errorCount()) { + result->set("details", pwd_errors.getLastError()->getString(false)); + } + return result; + } + + auto session = sm->getNewSession(); + /* + USER_EMPTY, + USER_LOADED_FROM_DB, + USER_PASSWORD_INCORRECT, + USER_PASSWORD_ENCRYPTION_IN_PROCESS, + USER_EMAIL_NOT_ACTIVATED, + USER_NO_KEYS, + USER_NO_PRIVATE_KEY, + USER_KEYS_DONT_MATCH, + USER_COMPLETE, + USER_DISABLED + */ + auto user_state = session->loadUser(email, password); + + switch (user_state) { + case USER_EMPTY: + case USER_PASSWORD_INCORRECT: + result->set("state", "error"); + result->set("msg", "password incorrect"); + break; + case USER_PASSWORD_ENCRYPTION_IN_PROCESS: + result->set("state", "processing"); + result->set("msg", "password encryption in process"); + break; + case USER_KEYS_DONT_MATCH: + result->set("state", "error"); + result->set("msg", "saved keys mismatch"); + break; + case USER_DISABLED: + result->set("state", "disabled"); + result->set("msg", "user is disabled"); + break; + case USER_NO_PRIVATE_KEY: + case USER_COMPLETE: + case USER_EMAIL_NOT_ACTIVATED: + result->set("state", "success"); + result->set("session_id", session->getHandle()); + session->setClientIp(mClientIP); + return result; + } + + sm->releaseSession(session); + + return result; + +} \ No newline at end of file diff --git a/src/cpp/JSONInterface/JsonUnsecureLogin.h b/src/cpp/JSONInterface/JsonUnsecureLogin.h new file mode 100644 index 000000000..f1db32dc1 --- /dev/null +++ b/src/cpp/JSONInterface/JsonUnsecureLogin.h @@ -0,0 +1,18 @@ +#ifndef __JSON_INTERFACE_JSON_UNSECURE_LOGIN_ +#define __JSON_INTERFACE_JSON_UNSECURE_LOGIN_ + +#include "JsonRequestHandler.h" + +class JsonUnsecureLogin : public JsonRequestHandler +{ +public: + JsonUnsecureLogin(Poco::Net::IPAddress ip) : mClientIP(ip) {} + Poco::JSON::Object* handle(Poco::Dynamic::Var params); + +protected: + Poco::Net::IPAddress mClientIP; + + +}; + +#endif // __JSON_INTERFACE_JSON_UNSECURE_LOGIN_ \ No newline at end of file diff --git a/src/cpp/ServerConfig.cpp b/src/cpp/ServerConfig.cpp index 005e5911e..483364d67 100644 --- a/src/cpp/ServerConfig.cpp +++ b/src/cpp/ServerConfig.cpp @@ -56,6 +56,7 @@ namespace ServerConfig { ServerSetupType g_ServerSetupType = SERVER_TYPE_PRODUCTION; std::string g_gRPCRelayServerFullURL; MemoryBin* g_CryptoAppSecret = nullptr; + AllowUnsecure g_AllowUnsecureFlags = NOT_UNSECURE; #ifdef __linux__ #include @@ -234,6 +235,15 @@ namespace ServerConfig { 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); + } + return true; } diff --git a/src/cpp/ServerConfig.h b/src/cpp/ServerConfig.h index 3450b08fc..f1084d02d 100644 --- a/src/cpp/ServerConfig.h +++ b/src/cpp/ServerConfig.h @@ -39,6 +39,13 @@ namespace ServerConfig { 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 + }; + extern Mnemonic g_Mnemonic_WordLists[MNEMONIC_MAX]; @@ -65,6 +72,7 @@ namespace ServerConfig { 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); diff --git a/src/cpp/controller/User.h b/src/cpp/controller/User.h index e251beb19..33daa9eda 100644 --- a/src/cpp/controller/User.h +++ b/src/cpp/controller/User.h @@ -70,7 +70,6 @@ namespace controller { //! \return -3 password key creation already running //! - create authenticated encryption key from password and email //! - compare hash with in db saved hash - int login(const std::string& password); // *********************************************************************************** diff --git a/src/cpp/model/Session.cpp b/src/cpp/model/Session.cpp index a5dc4b1b3..baec70cbc 100644 --- a/src/cpp/model/Session.cpp +++ b/src/cpp/model/Session.cpp @@ -801,16 +801,16 @@ UserStates Session::loadUser(const std::string& email, const std::string& passwo //printf("after checking if session user is null\n"); //if (!mSessionUser) { if (mNewUser.isNull()) { - printf("new user is null\n"); + //printf("new user is null\n"); mNewUser = controller::User::create(); - printf("new user created\n"); + //printf("new user created\n"); // load user for email only once from db mNewUser->load(email); - printf("load new user from db with email: %s\n", email.data()); + //printf("load new user from db with email: %s\n", email.data()); mSessionUser = new User(mNewUser); //mSessionUser = new User(email.data()); - printf("user loaded from email\n"); + //printf("user loaded from email\n"); } //printf("before get model\n"); auto user_model = mNewUser->getModel();