Server audit table (#2423)
* Creating of server side audit table for auditing actions such as password resets, account registrations and log queries. * Add migration script Add migration script for database * Update database script Update database script to reflect new audit table * Creating of server side audit table for auditing actions such as password resets, account registrations and log queries. * Add migration script Add migration script for database * Update database script Update database script to reflect new audit table * Corrected results column possible value(s). * Fixed migration script. * Added boolean audit logic Added enable/disable audit options Added audit functionality for forgot password * Added registration auditing Added registration auditing * Updated ActivateAccount Function Created clientid variable and used it in preporation for future potential protocol expansion. * Extended activation protocol Added clientid to activation command protocol * Typo correction Fix typo's * Missed type fix Found the infamous E! * Updated database function syntax Updated if/else syntax in db add audit function * Untabify content Untab files changed in PR
This commit is contained in:
parent
3c2063df40
commit
d0088f6a18
10 changed files with 256 additions and 62 deletions
|
@ -139,6 +139,7 @@ void RemoteClient::processServerIdentificationEvent(const Event_ServerIdentifica
|
||||||
Command_Activate cmdActivate;
|
Command_Activate cmdActivate;
|
||||||
cmdActivate.set_user_name(userName.toStdString());
|
cmdActivate.set_user_name(userName.toStdString());
|
||||||
cmdActivate.set_token(token.toStdString());
|
cmdActivate.set_token(token.toStdString());
|
||||||
|
cmdActivate.set_clientid(getSrvClientID(lastHostname).toStdString());
|
||||||
|
|
||||||
PendingCommand *pend = prepareSessionCommand(cmdActivate);
|
PendingCommand *pend = prepareSessionCommand(cmdActivate);
|
||||||
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(activateResponse(Response)));
|
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(activateResponse(Response)));
|
||||||
|
|
|
@ -137,6 +137,7 @@ message Command_Activate {
|
||||||
required string user_name = 1;
|
required string user_name = 1;
|
||||||
// Activation token
|
// Activation token
|
||||||
required string token = 2;
|
required string token = 2;
|
||||||
|
optional string clientid = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Command_AccountEdit {
|
message Command_AccountEdit {
|
||||||
|
|
16
servatrice/migrations/servatrice_0021_to_0022.sql
Normal file
16
servatrice/migrations/servatrice_0021_to_0022.sql
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `cockatrice_audit` (
|
||||||
|
`id` int(7) unsigned zerofill NOT NULL auto_increment,
|
||||||
|
`id_server` tinyint(3) NOT NULL,
|
||||||
|
`name` varchar(35) NOT NULL,
|
||||||
|
`ip_address` varchar(255) NOT NULL,
|
||||||
|
`clientid` varchar(15) NOT NULL,
|
||||||
|
`incidentDate` datetime NOT NULL default '0000-00-00 00:00:00',
|
||||||
|
`action` varchar(35) NOT NULL,
|
||||||
|
`results` ENUM('fail', 'success') NOT NULL DEFAULT 'fail',
|
||||||
|
`details` varchar(255) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `user_name` (`name`)
|
||||||
|
) ENGINE=INNODB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
UPDATE cockatrice_schema_version SET version=22 WHERE version=21;
|
|
@ -353,6 +353,22 @@ log_user_msg_chat=false
|
||||||
; Log user messages coming from other servers in the network
|
; Log user messages coming from other servers in the network
|
||||||
log_user_msg_isl=false
|
log_user_msg_isl=false
|
||||||
|
|
||||||
|
[audit]
|
||||||
|
|
||||||
|
; Servatrice can record certain actions being performed in the database for server operators to better understand
|
||||||
|
; if some one may be abusing application functionality. Enabling auditing will allow servatrice to record any
|
||||||
|
; of the below enabled audit functionality to be recorded.
|
||||||
|
; Default: true
|
||||||
|
enable_audit=true
|
||||||
|
|
||||||
|
; Servatrice can record when users attempt a new account registration. Should we enable auditing for this action?
|
||||||
|
; Default: true
|
||||||
|
enable_registration_audit=true
|
||||||
|
|
||||||
|
; Servatrice can record when a users attempts to reset the account password. Should we enable auditing for this action?
|
||||||
|
; Default: true
|
||||||
|
enable_forgotpassword_audit=true
|
||||||
|
|
||||||
|
|
||||||
; EXPERIMENTAL - NOT WORKING YET
|
; EXPERIMENTAL - NOT WORKING YET
|
||||||
; The following settings are relative to the server network functionality, that is not yet complete.
|
; The following settings are relative to the server network functionality, that is not yet complete.
|
||||||
|
|
|
@ -20,7 +20,7 @@ CREATE TABLE IF NOT EXISTS `cockatrice_schema_version` (
|
||||||
PRIMARY KEY (`version`)
|
PRIMARY KEY (`version`)
|
||||||
) ENGINE=INNODB DEFAULT CHARSET=utf8;
|
) ENGINE=INNODB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
INSERT INTO cockatrice_schema_version VALUES(21);
|
INSERT INTO cockatrice_schema_version VALUES(22);
|
||||||
|
|
||||||
-- users and user data tables
|
-- users and user data tables
|
||||||
CREATE TABLE IF NOT EXISTS `cockatrice_users` (
|
CREATE TABLE IF NOT EXISTS `cockatrice_users` (
|
||||||
|
@ -267,3 +267,17 @@ CREATE TABLE IF NOT EXISTS `cockatrice_forgot_password` (
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `user_name` (`name`)
|
KEY `user_name` (`name`)
|
||||||
) ENGINE=INNODB DEFAULT CHARSET=utf8;
|
) ENGINE=INNODB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `cockatrice_audit` (
|
||||||
|
`id` int(7) unsigned zerofill NOT NULL auto_increment,
|
||||||
|
`id_server` tinyint(3) NOT NULL,
|
||||||
|
`name` varchar(35) NOT NULL,
|
||||||
|
`ip_address` varchar(255) NOT NULL,
|
||||||
|
`clientid` varchar(15) NOT NULL,
|
||||||
|
`incidentDate` datetime NOT NULL default '0000-00-00 00:00:00',
|
||||||
|
`action` varchar(35) NOT NULL,
|
||||||
|
`results` ENUM('fail', 'success') NOT NULL DEFAULT 'fail',
|
||||||
|
`details` varchar(255) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `user_name` (`name`)
|
||||||
|
) ENGINE=INNODB DEFAULT CHARSET=utf8;
|
||||||
|
|
|
@ -252,11 +252,17 @@ bool Servatrice::initServer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Forgot password enabled: " << getEnableForgotPassword();
|
qDebug() << "Forgot password enabled: " << getEnableForgotPassword();
|
||||||
if (getEnableForgotPassword()) {
|
if (getEnableForgotPassword()) {
|
||||||
qDebug() << "Forgot password token life (in minutes): " << getForgotPasswordTokenLife();
|
qDebug() << "Forgot password token life (in minutes): " << getForgotPasswordTokenLife();
|
||||||
qDebug() << "Forgot password challenge on: " << getEnableForgotPasswordChallenge();
|
qDebug() << "Forgot password challenge on: " << getEnableForgotPasswordChallenge();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qDebug() << "Auditing enabled: " << getEnableAudit();
|
||||||
|
if (getEnableAudit()) {
|
||||||
|
qDebug() << "Audit registration attempts enabled: " << getEnableRegistrationAudit();
|
||||||
|
qDebug() << "Audit forgot password attepts enabled: " << getEnableForgotPasswordAudit();
|
||||||
|
}
|
||||||
|
|
||||||
if (getDBTypeString() == "mysql") {
|
if (getDBTypeString() == "mysql") {
|
||||||
databaseType = DatabaseMySql;
|
databaseType = DatabaseMySql;
|
||||||
|
@ -550,49 +556,49 @@ void Servatrice::statusUpdate()
|
||||||
|
|
||||||
if (getRegistrationEnabled() && getEnableInternalSMTPClient())
|
if (getRegistrationEnabled() && getEnableInternalSMTPClient())
|
||||||
{
|
{
|
||||||
if (getRequireEmailActivationEnabled())
|
if (getRequireEmailActivationEnabled())
|
||||||
{
|
{
|
||||||
QSqlQuery *query = servatriceDatabaseInterface->prepareQuery("select a.name, b.email, b.token from {prefix}_activation_emails a left join {prefix}_users b on a.name = b.name");
|
QSqlQuery *query = servatriceDatabaseInterface->prepareQuery("select a.name, b.email, b.token from {prefix}_activation_emails a left join {prefix}_users b on a.name = b.name");
|
||||||
if (!servatriceDatabaseInterface->execSqlQuery(query))
|
if (!servatriceDatabaseInterface->execSqlQuery(query))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QSqlQuery *queryDelete = servatriceDatabaseInterface->prepareQuery("delete from {prefix}_activation_emails where name = :name");
|
QSqlQuery *queryDelete = servatriceDatabaseInterface->prepareQuery("delete from {prefix}_activation_emails where name = :name");
|
||||||
|
|
||||||
while (query->next()) {
|
while (query->next()) {
|
||||||
const QString userName = query->value(0).toString();
|
const QString userName = query->value(0).toString();
|
||||||
const QString emailAddress = query->value(1).toString();
|
const QString emailAddress = query->value(1).toString();
|
||||||
const QString token = query->value(2).toString();
|
const QString token = query->value(2).toString();
|
||||||
|
|
||||||
if (smtpClient->enqueueActivationTokenMail(userName, emailAddress, token))
|
if (smtpClient->enqueueActivationTokenMail(userName, emailAddress, token))
|
||||||
{
|
{
|
||||||
queryDelete->bindValue(":name", userName);
|
queryDelete->bindValue(":name", userName);
|
||||||
servatriceDatabaseInterface->execSqlQuery(queryDelete);
|
servatriceDatabaseInterface->execSqlQuery(queryDelete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getEnableForgotPassword())
|
if (getEnableForgotPassword())
|
||||||
{
|
{
|
||||||
QSqlQuery *query = servatriceDatabaseInterface->prepareQuery("select a.name, b.email, b.token from {prefix}_forgot_password a left join {prefix}_users b on a.name = b.name where a.emailed = 0");
|
QSqlQuery *query = servatriceDatabaseInterface->prepareQuery("select a.name, b.email, b.token from {prefix}_forgot_password a left join {prefix}_users b on a.name = b.name where a.emailed = 0");
|
||||||
if (!servatriceDatabaseInterface->execSqlQuery(query))
|
if (!servatriceDatabaseInterface->execSqlQuery(query))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QSqlQuery *queryDelete = servatriceDatabaseInterface->prepareQuery("update {prefix}_forgot_password set emailed = 1 where name = :name");
|
QSqlQuery *queryDelete = servatriceDatabaseInterface->prepareQuery("update {prefix}_forgot_password set emailed = 1 where name = :name");
|
||||||
|
|
||||||
while (query->next()) {
|
while (query->next()) {
|
||||||
const QString userName = query->value(0).toString();
|
const QString userName = query->value(0).toString();
|
||||||
const QString emailAddress = query->value(1).toString();
|
const QString emailAddress = query->value(1).toString();
|
||||||
const QString token = query->value(2).toString();
|
const QString token = query->value(2).toString();
|
||||||
|
|
||||||
if (smtpClient->enqueueForgotPasswordTokenMail(userName, emailAddress, token))
|
if (smtpClient->enqueueForgotPasswordTokenMail(userName, emailAddress, token))
|
||||||
{
|
{
|
||||||
queryDelete->bindValue(":name", userName);
|
queryDelete->bindValue(":name", userName);
|
||||||
servatriceDatabaseInterface->execSqlQuery(queryDelete);
|
servatriceDatabaseInterface->execSqlQuery(queryDelete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
smtpClient->sendAllEmails();
|
smtpClient->sendAllEmails();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -877,17 +883,29 @@ bool Servatrice::getEnableInternalSMTPClient() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Servatrice::getEnableForgotPassword() const {
|
bool Servatrice::getEnableForgotPassword() const {
|
||||||
return settingsCache->value("forgotpassword/enable", false).toBool();
|
return settingsCache->value("forgotpassword/enable", false).toBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Servatrice::getForgotPasswordTokenLife() const {
|
int Servatrice::getForgotPasswordTokenLife() const {
|
||||||
return settingsCache->value("forgotpassword/tokenlife", 60).toInt();
|
return settingsCache->value("forgotpassword/tokenlife", 60).toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Servatrice::getEnableForgotPasswordChallenge() const {
|
bool Servatrice::getEnableForgotPasswordChallenge() const {
|
||||||
return settingsCache->value("forgotpassword/enablechallenge", false).toBool();
|
return settingsCache->value("forgotpassword/enablechallenge", false).toBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Servatrice::getEmailBlackList() const {
|
QString Servatrice::getEmailBlackList() const {
|
||||||
return settingsCache->value("registration/emailproviderblacklist").toString();
|
return settingsCache->value("registration/emailproviderblacklist").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Servatrice::getEnableAudit() const {
|
||||||
|
return settingsCache->value("audit/enable_audit", true).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Servatrice::getEnableRegistrationAudit() const {
|
||||||
|
return settingsCache->value("audit/enable_registration_audit", true).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Servatrice::getEnableForgotPasswordAudit() const {
|
||||||
|
return settingsCache->value("audit/enable_forgotpassword_audit", true).toBool();
|
||||||
}
|
}
|
|
@ -193,6 +193,9 @@ public:
|
||||||
bool getEnableLogQuery() const;
|
bool getEnableLogQuery() const;
|
||||||
bool getEnableForgotPassword() const;
|
bool getEnableForgotPassword() const;
|
||||||
bool getEnableForgotPasswordChallenge() const;
|
bool getEnableForgotPasswordChallenge() const;
|
||||||
|
bool getEnableAudit() const;
|
||||||
|
bool getEnableRegistrationAudit() const;
|
||||||
|
bool getEnableForgotPasswordAudit() const;
|
||||||
int getIdleClientTimeout() const;
|
int getIdleClientTimeout() const;
|
||||||
int getServerID() const;
|
int getServerID() const;
|
||||||
int getMaxGameInactivityTime() const;
|
int getMaxGameInactivityTime() const;
|
||||||
|
|
|
@ -1218,3 +1218,26 @@ bool Servatrice_DatabaseInterface::validateTableColumnStringData(const QString &
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Servatrice_DatabaseInterface::addAuditRecord(const QString &user, const QString &ipaddress, const QString &clientid, const QString &action, const QString &details, const bool &results = false)
|
||||||
|
{
|
||||||
|
if (!checkSql())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!server->getEnableAudit())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (user.isEmpty() || ipaddress.isEmpty() || clientid.isEmpty() || action.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QSqlQuery *query = prepareQuery("insert into {prefix}_audit (id_server,name,ip_address,clientid,incidentDate,action,results,details) values (:idserver,:username,:ipaddress,:clientid,NOW(),:action,:results,:details)");
|
||||||
|
query->bindValue(":idserver", server->getServerID());
|
||||||
|
query->bindValue(":username", user);
|
||||||
|
query->bindValue(":ipaddress", ipaddress);
|
||||||
|
query->bindValue(":clientid", clientid);
|
||||||
|
query->bindValue(":action", action);
|
||||||
|
query->bindValue(":results", results ? "success" : "fail");
|
||||||
|
|
||||||
|
query->bindValue(":details", details);
|
||||||
|
execSqlQuery(query);
|
||||||
|
}
|
|
@ -9,7 +9,7 @@
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "server_database_interface.h"
|
#include "server_database_interface.h"
|
||||||
|
|
||||||
#define DATABASE_SCHEMA_VERSION 21
|
#define DATABASE_SCHEMA_VERSION 22
|
||||||
|
|
||||||
class Servatrice;
|
class Servatrice;
|
||||||
|
|
||||||
|
@ -86,6 +86,7 @@ public:
|
||||||
bool doesForgotPasswordExist(const QString &user);
|
bool doesForgotPasswordExist(const QString &user);
|
||||||
bool updateUserToken(const QString &token, const QString &user);
|
bool updateUserToken(const QString &token, const QString &user);
|
||||||
bool validateTableColumnStringData(const QString &table, const QString &column, const QString &_user, const QString &_datatocheck);
|
bool validateTableColumnStringData(const QString &table, const QString &column, const QString &_user, const QString &_datatocheck);
|
||||||
|
void addAuditRecord(const QString &user, const QString &ipaddress, const QString &clientid, const QString &action, const QString &details, const bool &results);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -881,8 +881,12 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C
|
||||||
qDebug() << "Got register command: " << userName;
|
qDebug() << "Got register command: " << userName;
|
||||||
|
|
||||||
bool registrationEnabled = settingsCache->value("registration/enabled", false).toBool();
|
bool registrationEnabled = settingsCache->value("registration/enabled", false).toBool();
|
||||||
if (!registrationEnabled)
|
if (!registrationEnabled) {
|
||||||
|
if (servatrice->getEnableRegistrationAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "REGISTER_ACCOUNT", "Server functionality disabled", false);
|
||||||
|
|
||||||
return Response::RespRegistrationDisabled;
|
return Response::RespRegistrationDisabled;
|
||||||
|
}
|
||||||
|
|
||||||
QString emailBlackList = servatrice->getEmailBlackList();
|
QString emailBlackList = servatrice->getEmailBlackList();
|
||||||
QString emailAddress = QString::fromStdString(cmd.email());
|
QString emailAddress = QString::fromStdString(cmd.email());
|
||||||
|
@ -892,6 +896,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C
|
||||||
if (!emailBlackList.trimmed().isEmpty()) {
|
if (!emailBlackList.trimmed().isEmpty()) {
|
||||||
foreach(QString blackListEmailAddress, emailBlackListFilters) {
|
foreach(QString blackListEmailAddress, emailBlackListFilters) {
|
||||||
if (emailAddress.contains(blackListEmailAddress, Qt::CaseInsensitive)) {
|
if (emailAddress.contains(blackListEmailAddress, Qt::CaseInsensitive)) {
|
||||||
|
if (servatrice->getEnableRegistrationAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "REGISTER_ACCOUNT", "Email used is blacklisted", false);
|
||||||
|
|
||||||
return Response::RespEmailBlackListed;
|
return Response::RespEmailBlackListed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -909,20 +916,34 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C
|
||||||
QString errorString;
|
QString errorString;
|
||||||
if (!sqlInterface->usernameIsValid(userName, errorString))
|
if (!sqlInterface->usernameIsValid(userName, errorString))
|
||||||
{
|
{
|
||||||
|
if (servatrice->getEnableRegistrationAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "REGISTER_ACCOUNT", "Username is invalid", false);
|
||||||
|
|
||||||
Response_Register *re = new Response_Register;
|
Response_Register *re = new Response_Register;
|
||||||
re->set_denied_reason_str(errorString.toStdString());
|
re->set_denied_reason_str(errorString.toStdString());
|
||||||
rc.setResponseExtension(re);
|
rc.setResponseExtension(re);
|
||||||
return Response::RespUsernameInvalid;
|
return Response::RespUsernameInvalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userName.toLower().simplified() == "servatrice")
|
if (userName.toLower().simplified() == "servatrice") {
|
||||||
return Response::RespUsernameInvalid;
|
if (servatrice->getEnableRegistrationAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "REGISTER_ACCOUNT", "Username is invalid", false);
|
||||||
|
|
||||||
|
return Response::RespUsernameInvalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sqlInterface->userExists(userName)) {
|
||||||
|
if (servatrice->getEnableRegistrationAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "REGISTER_ACCOUNT", "Username already exists", false);
|
||||||
|
|
||||||
if(sqlInterface->userExists(userName))
|
|
||||||
return Response::RespUserAlreadyExists;
|
return Response::RespUserAlreadyExists;
|
||||||
|
}
|
||||||
|
|
||||||
if (servatrice->getMaxAccountsPerEmail() && !(sqlInterface->checkNumberOfUserAccounts(emailAddress) < servatrice->getMaxAccountsPerEmail()))
|
if (servatrice->getMaxAccountsPerEmail() && !(sqlInterface->checkNumberOfUserAccounts(emailAddress) < servatrice->getMaxAccountsPerEmail()))
|
||||||
{
|
{
|
||||||
|
if (servatrice->getEnableRegistrationAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "REGISTER_ACCOUNT", "Too many usernames registered with this email address", false);
|
||||||
|
|
||||||
return Response::RespTooManyRequests;
|
return Response::RespTooManyRequests;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -930,6 +951,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C
|
||||||
int banSecondsRemaining;
|
int banSecondsRemaining;
|
||||||
if (sqlInterface->checkUserIsBanned(this->getAddress(), userName, clientId, banReason, banSecondsRemaining))
|
if (sqlInterface->checkUserIsBanned(this->getAddress(), userName, clientId, banReason, banSecondsRemaining))
|
||||||
{
|
{
|
||||||
|
if (servatrice->getEnableRegistrationAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "REGISTER_ACCOUNT", "User is banned", false);
|
||||||
|
|
||||||
Response_Register *re = new Response_Register;
|
Response_Register *re = new Response_Register;
|
||||||
re->set_denied_reason_str(banReason.toStdString());
|
re->set_denied_reason_str(banReason.toStdString());
|
||||||
if (banSecondsRemaining != 0)
|
if (banSecondsRemaining != 0)
|
||||||
|
@ -938,8 +962,12 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C
|
||||||
return Response::RespUserIsBanned;
|
return Response::RespUserIsBanned;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tooManyRegistrationAttempts(this->getAddress()))
|
if (tooManyRegistrationAttempts(this->getAddress())) {
|
||||||
|
if (servatrice->getEnableRegistrationAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "REGISTER_ACCOUNT", "Too many registration attempts from this ip address", false);
|
||||||
|
|
||||||
return Response::RespTooManyRequests;
|
return Response::RespTooManyRequests;
|
||||||
|
}
|
||||||
|
|
||||||
QString realName = QString::fromStdString(cmd.real_name());
|
QString realName = QString::fromStdString(cmd.real_name());
|
||||||
ServerInfo_User_Gender gender = cmd.gender();
|
ServerInfo_User_Gender gender = cmd.gender();
|
||||||
|
@ -947,8 +975,12 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C
|
||||||
QString password = QString::fromStdString(cmd.password());
|
QString password = QString::fromStdString(cmd.password());
|
||||||
|
|
||||||
// TODO make this configurable?
|
// TODO make this configurable?
|
||||||
if(password.length() < 6)
|
if (password.length() < 6) {
|
||||||
|
if (servatrice->getEnableRegistrationAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "REGISTER_ACCOUNT", "Password is too short", false);
|
||||||
|
|
||||||
return Response::RespPasswordTooShort;
|
return Response::RespPasswordTooShort;
|
||||||
|
}
|
||||||
|
|
||||||
QString token;
|
QString token;
|
||||||
bool requireEmailActivation = settingsCache->value("registration/requireemailactivation", true).toBool();
|
bool requireEmailActivation = settingsCache->value("registration/requireemailactivation", true).toBool();
|
||||||
|
@ -964,11 +996,22 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C
|
||||||
if (!sqlInterface->execSqlQuery(query))
|
if (!sqlInterface->execSqlQuery(query))
|
||||||
return Response::RespRegistrationFailed;
|
return Response::RespRegistrationFailed;
|
||||||
|
|
||||||
|
if (servatrice->getEnableRegistrationAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "REGISTER_ACCOUNT", "", true);
|
||||||
|
|
||||||
return Response::RespRegistrationAcceptedNeedsActivation;
|
return Response::RespRegistrationAcceptedNeedsActivation;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
if (servatrice->getEnableRegistrationAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "REGISTER_ACCOUNT", "", true);
|
||||||
|
|
||||||
return Response::RespRegistrationAccepted;
|
return Response::RespRegistrationAccepted;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
if (servatrice->getEnableRegistrationAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "REGISTER_ACCOUNT", "Unknown reason for failure", false);
|
||||||
|
|
||||||
return Response::RespRegistrationFailed;
|
return Response::RespRegistrationFailed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -984,13 +1027,25 @@ Response::ResponseCode AbstractServerSocketInterface::cmdActivateAccount(const C
|
||||||
{
|
{
|
||||||
QString userName = QString::fromStdString(cmd.user_name());
|
QString userName = QString::fromStdString(cmd.user_name());
|
||||||
QString token = QString::fromStdString(cmd.token());
|
QString token = QString::fromStdString(cmd.token());
|
||||||
|
QString clientID = QString::fromStdString(cmd.clientid());
|
||||||
|
|
||||||
|
if (clientID.isEmpty())
|
||||||
|
clientID = "UNKNOWN";
|
||||||
|
|
||||||
if(sqlInterface->activateUser(userName, token))
|
if(sqlInterface->activateUser(userName, token))
|
||||||
{
|
{
|
||||||
qDebug() << "Accepted activation for user" << QString::fromStdString(cmd.user_name());
|
qDebug() << "Accepted activation for user" << QString::fromStdString(cmd.user_name());
|
||||||
|
|
||||||
|
if (servatrice->getEnableRegistrationAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), clientID, "ACTIVATE_ACCOUNT", "", true);
|
||||||
|
|
||||||
return Response::RespActivationAccepted;
|
return Response::RespActivationAccepted;
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Failed activation for user" << QString::fromStdString(cmd.user_name());
|
qDebug() << "Failed activation for user" << QString::fromStdString(cmd.user_name());
|
||||||
|
|
||||||
|
if (servatrice->getEnableRegistrationAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), clientID, "ACTIVATE_ACCOUNT", "Failed to activate account, incorrect activation token", false);
|
||||||
|
|
||||||
return Response::RespActivationFailed;
|
return Response::RespActivationFailed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1067,13 +1122,25 @@ Response::ResponseCode AbstractServerSocketInterface::cmdForgotPasswordRequest(c
|
||||||
{
|
{
|
||||||
qDebug() << "Received forgot password request from user: " << QString::fromStdString(cmd.user_name());
|
qDebug() << "Received forgot password request from user: " << QString::fromStdString(cmd.user_name());
|
||||||
|
|
||||||
if (!servatrice->getEnableForgotPassword())
|
if (!servatrice->getEnableForgotPassword()) {
|
||||||
return Response::RespFunctionNotAllowed;
|
if (servatrice->getEnableForgotPasswordAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "PASSWORD_RESET_REQUEST", "Server functionality disabled", false);
|
||||||
|
|
||||||
if (!sqlInterface->userExists(QString::fromStdString(cmd.user_name())))
|
|
||||||
return Response::RespFunctionNotAllowed;
|
return Response::RespFunctionNotAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sqlInterface->userExists(QString::fromStdString(cmd.user_name()))) {
|
||||||
|
if (servatrice->getEnableForgotPasswordAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "PASSWORD_RESET_REQUEST", "User does not exist", false);
|
||||||
|
|
||||||
|
return Response::RespFunctionNotAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
if (sqlInterface->doesForgotPasswordExist(QString::fromStdString(cmd.user_name()))) {
|
if (sqlInterface->doesForgotPasswordExist(QString::fromStdString(cmd.user_name()))) {
|
||||||
|
|
||||||
|
if (servatrice->getEnableForgotPasswordAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "PASSWORD_RESET_REQUEST", "Request already exists", true);
|
||||||
|
|
||||||
Response_ForgotPasswordRequest *re = new Response_ForgotPasswordRequest;
|
Response_ForgotPasswordRequest *re = new Response_ForgotPasswordRequest;
|
||||||
re->set_challenge_email(false);
|
re->set_challenge_email(false);
|
||||||
rc.setResponseExtension(re);
|
rc.setResponseExtension(re);
|
||||||
|
@ -1081,10 +1148,17 @@ Response::ResponseCode AbstractServerSocketInterface::cmdForgotPasswordRequest(c
|
||||||
}
|
}
|
||||||
|
|
||||||
QString banReason; int banTimeRemaining;
|
QString banReason; int banTimeRemaining;
|
||||||
if (sqlInterface->checkUserIsBanned(this->getAddress(), QString::fromStdString(cmd.user_name()), QString::fromStdString(cmd.clientid()), banReason, banTimeRemaining))
|
if (sqlInterface->checkUserIsBanned(this->getAddress(), QString::fromStdString(cmd.user_name()), QString::fromStdString(cmd.clientid()), banReason, banTimeRemaining)) {
|
||||||
|
if (servatrice->getEnableForgotPasswordAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "PASSWORD_RESET_REQUEST", "User is banned", false);
|
||||||
|
|
||||||
return Response::RespFunctionNotAllowed;
|
return Response::RespFunctionNotAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
if (servatrice->getEnableForgotPasswordChallenge()) {
|
if (servatrice->getEnableForgotPasswordChallenge()) {
|
||||||
|
if (servatrice->getEnableForgotPasswordAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "PASSWORD_RESET_REQUEST", "Request does not exist, challenge requested", true);
|
||||||
|
|
||||||
Response_ForgotPasswordRequest *re = new Response_ForgotPasswordRequest;
|
Response_ForgotPasswordRequest *re = new Response_ForgotPasswordRequest;
|
||||||
re->set_challenge_email(true);
|
re->set_challenge_email(true);
|
||||||
rc.setResponseExtension(re);
|
rc.setResponseExtension(re);
|
||||||
|
@ -1092,6 +1166,10 @@ Response::ResponseCode AbstractServerSocketInterface::cmdForgotPasswordRequest(c
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (sqlInterface->addForgotPassword(QString::fromStdString(cmd.user_name()))) {
|
if (sqlInterface->addForgotPassword(QString::fromStdString(cmd.user_name()))) {
|
||||||
|
|
||||||
|
if (servatrice->getEnableForgotPasswordAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "PASSWORD_RESET_REQUEST", "Request does not exist, challenge not requested", true);
|
||||||
|
|
||||||
Response_ForgotPasswordRequest *re = new Response_ForgotPasswordRequest;
|
Response_ForgotPasswordRequest *re = new Response_ForgotPasswordRequest;
|
||||||
re->set_challenge_email(false);
|
re->set_challenge_email(false);
|
||||||
rc.setResponseExtension(re);
|
rc.setResponseExtension(re);
|
||||||
|
@ -1107,13 +1185,24 @@ Response::ResponseCode AbstractServerSocketInterface::cmdForgotPasswordReset(con
|
||||||
Q_UNUSED(rc);
|
Q_UNUSED(rc);
|
||||||
qDebug() << "Received forgot password reset from user: " << QString::fromStdString(cmd.user_name());
|
qDebug() << "Received forgot password reset from user: " << QString::fromStdString(cmd.user_name());
|
||||||
|
|
||||||
if (!sqlInterface->doesForgotPasswordExist(QString::fromStdString(cmd.user_name())))
|
if (!sqlInterface->doesForgotPasswordExist(QString::fromStdString(cmd.user_name()))) {
|
||||||
return Response::RespFunctionNotAllowed;
|
if (servatrice->getEnableForgotPasswordAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "PASSWORD_RESET", "Request does not exist for user", false);
|
||||||
|
|
||||||
if (!sqlInterface->validateTableColumnStringData("{prefix}_users","token", QString::fromStdString(cmd.user_name()),QString::fromStdString(cmd.token())))
|
|
||||||
return Response::RespFunctionNotAllowed;
|
return Response::RespFunctionNotAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sqlInterface->validateTableColumnStringData("{prefix}_users", "token", QString::fromStdString(cmd.user_name()), QString::fromStdString(cmd.token()))) {
|
||||||
|
if (servatrice->getEnableForgotPasswordAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "PASSWORD_RESET", "Failed token validation", false);
|
||||||
|
|
||||||
|
return Response::RespFunctionNotAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
if (sqlInterface->changeUserPassword(QString::fromStdString(cmd.user_name()), "", QString::fromStdString(cmd.new_password()), true)) {
|
if (sqlInterface->changeUserPassword(QString::fromStdString(cmd.user_name()), "", QString::fromStdString(cmd.new_password()), true)) {
|
||||||
|
if (servatrice->getEnableForgotPasswordAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "PASSWORD_RESET", "", true);
|
||||||
|
|
||||||
sqlInterface->removeForgotPassword(QString::fromStdString(cmd.user_name()));
|
sqlInterface->removeForgotPassword(QString::fromStdString(cmd.user_name()));
|
||||||
return Response::RespOk;
|
return Response::RespOk;
|
||||||
}
|
}
|
||||||
|
@ -1126,12 +1215,24 @@ Response::ResponseCode AbstractServerSocketInterface::cmdForgotPasswordChallenge
|
||||||
Q_UNUSED(rc);
|
Q_UNUSED(rc);
|
||||||
qDebug() << "Received forgot password challenge from user: " << QString::fromStdString(cmd.user_name());
|
qDebug() << "Received forgot password challenge from user: " << QString::fromStdString(cmd.user_name());
|
||||||
|
|
||||||
if (sqlInterface->doesForgotPasswordExist(QString::fromStdString(cmd.user_name())))
|
if (sqlInterface->doesForgotPasswordExist(QString::fromStdString(cmd.user_name()))) {
|
||||||
return Response::RespOk;
|
if (servatrice->getEnableForgotPasswordAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "PASSWORD_RESET_CHALLANGE", "Request does not exist for user", false);
|
||||||
|
|
||||||
|
return Response::RespOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sqlInterface->validateTableColumnStringData("{prefix}_users", "email", QString::fromStdString(cmd.user_name()), QString::fromStdString(cmd.email()))) {
|
||||||
|
if (servatrice->getEnableForgotPasswordAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "PASSWORD_RESET_CHALLANGE", "", true);
|
||||||
|
|
||||||
if (sqlInterface->validateTableColumnStringData("{prefix}_users","email", QString::fromStdString(cmd.user_name()), QString::fromStdString(cmd.email())))
|
|
||||||
if (sqlInterface->addForgotPassword(QString::fromStdString(cmd.user_name())))
|
if (sqlInterface->addForgotPassword(QString::fromStdString(cmd.user_name())))
|
||||||
return Response::RespOk;
|
return Response::RespOk;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (servatrice->getEnableForgotPasswordAudit())
|
||||||
|
sqlInterface->addAuditRecord(QString::fromStdString(cmd.user_name()).simplified(), this->getAddress(), QString::fromStdString(cmd.clientid()).simplified(), "PASSWORD_RESET_CHALLANGE", "Failed to answer email challenge question", false);
|
||||||
|
}
|
||||||
|
|
||||||
return Response::RespFunctionNotAllowed;
|
return Response::RespFunctionNotAllowed;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue