add unsecure options, add unsecure login, update create user to use it in unsecure mode with password

This commit is contained in:
einhornimmond 2021-02-08 12:35:50 +01:00 committed by Ulf Gebhardt
parent 49c672c737
commit 3ed94b8a9c
No known key found for this signature in database
GPG Key ID: 81308EFE29ABFEBD
9 changed files with 197 additions and 10 deletions

View File

@ -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)) {

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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<Poco::JSON::Object::Ptr>();
/// 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;
}

View File

@ -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_

View File

@ -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 <stdio.h>
@ -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;
}

View File

@ -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);

View File

@ -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);
// ***********************************************************************************

View File

@ -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();