aboutsummaryrefslogtreecommitdiff
path: root/src/server/database/Database
diff options
context:
space:
mode:
authorTreeston <treeston.mmoc@gmail.com>2020-08-02 22:52:21 +0200
committerGitHub <noreply@github.com>2020-08-02 22:52:21 +0200
commit3164b58c7d170810b69378950c0891e5f5b8678b (patch)
tree893d675ab6fcfd71c294a8922f337f063836e9ce /src/server/database/Database
parent10f49793f9a7cd67c7b8b203290d7ea5f1829795 (diff)
Core/Authserver: Re-organize the `accounts` table (PR #25135)
- no longer use sha_pass_hash for anything else core-side (.account, SOAP, RA) - salt/verifier/session_key are now binary - old s/v/sha_pass_hash fields kept around for backwards compatibility - sha_pass_hash is still updated (for now), s/v are not - sha_pass_hash is only read if s/v have been manually changed - SRP6 b now uses the full 32 bytes of randomness (instead of randomly only using 19)
Diffstat (limited to 'src/server/database/Database')
-rw-r--r--src/server/database/Database/Field.cpp7
-rw-r--r--src/server/database/Database/Field.h11
-rw-r--r--src/server/database/Database/Implementation/LoginDatabase.cpp24
-rw-r--r--src/server/database/Database/Implementation/LoginDatabase.h4
-rw-r--r--src/server/database/Database/PreparedStatement.h6
5 files changed, 38 insertions, 14 deletions
diff --git a/src/server/database/Database/Field.cpp b/src/server/database/Database/Field.cpp
index f891bfd22b9..b9d25b3da1b 100644
--- a/src/server/database/Database/Field.cpp
+++ b/src/server/database/Database/Field.cpp
@@ -16,6 +16,7 @@
*/
#include "Field.h"
+#include "Errors.h"
#include "Log.h"
#include "MySQLHacks.h"
@@ -247,6 +248,12 @@ std::vector<uint8> Field::GetBinary() const
return result;
}
+void Field::GetBinarySizeChecked(uint8* buf, size_t length) const
+{
+ ASSERT(data.value && (data.length == length), "Expected %zu-byte binary blob, got %sdata (%u bytes) instead", length, data.value ? "" : "no ", data.length);
+ memcpy(buf, data.value, length);
+}
+
void Field::SetByteValue(char const* newValue, uint32 length)
{
// This value stores raw bytes that have to be explicitly cast later
diff --git a/src/server/database/Database/Field.h b/src/server/database/Database/Field.h
index ea7c82d1876..dcb03344031 100644
--- a/src/server/database/Database/Field.h
+++ b/src/server/database/Database/Field.h
@@ -20,6 +20,7 @@
#include "Define.h"
#include "DatabaseEnvFwd.h"
+#include <array>
#include <vector>
enum class DatabaseFieldTypes : uint8
@@ -104,6 +105,14 @@ class TC_DATABASE_API Field
char const* GetCString() const;
std::string GetString() const;
std::vector<uint8> GetBinary() const;
+ template <size_t S>
+ std::array<uint8, S> GetBinary() const
+ {
+ std::array<uint8, S> buf;
+ GetBinarySizeChecked(buf.data(), S);
+ return buf;
+ }
+
bool IsNull() const
{
@@ -129,6 +138,8 @@ class TC_DATABASE_API Field
QueryResultFieldMetadata const* meta;
void LogWrongType(char const* getter) const;
void SetMetadata(QueryResultFieldMetadata const* fieldMeta);
+
+ void GetBinarySizeChecked(uint8* buf, size_t size) const;
};
#endif
diff --git a/src/server/database/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp
index 39337f03963..74a291bf3fe 100644
--- a/src/server/database/Database/Implementation/LoginDatabase.cpp
+++ b/src/server/database/Database/Implementation/LoginDatabase.cpp
@@ -35,20 +35,21 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_SEL_ACCOUNT_BANNED_BY_USERNAME, "SELECT account.id, username FROM account, account_banned WHERE account.id = account_banned.id AND active = 1 AND username = ? GROUP BY account.id", CONNECTION_SYNCH);
PrepareStatement(LOGIN_INS_ACCOUNT_AUTO_BANNED, "INSERT INTO account_banned (id, bandate, unbandate, bannedby, banreason, active) VALUES (?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+?, 'Trinity Auth', 'Failed login autoban', 1)", CONNECTION_ASYNC);
PrepareStatement(LOGIN_DEL_ACCOUNT_BANNED, "DELETE FROM account_banned WHERE id = ?", CONNECTION_ASYNC);
- PrepareStatement(LOGIN_UPD_SV, "UPDATE account SET s = ?, v = ? WHERE id = ?", CONNECTION_ASYNC);
- PrepareStatement(LOGIN_UPD_LOGONPROOF, "UPDATE account SET sessionkey = ?, last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE username = ?", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_UPD_LOGON, "UPDATE account SET salt = ?, verifier = ?, s = DEFAULT, v = DEFAULT WHERE id = ?", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_UPD_LOGON_LEGACY, "UPDATE account SET sha_pass_hash = ? WHERE id = ?", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_UPD_LOGONPROOF, "UPDATE account SET session_key = ?, last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_LOGONCHALLENGE, "SELECT a.id, a.username, a.locked, a.lock_country, a.last_ip, a.failed_logins, ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, "
- "ab.unbandate = ab.bandate, aa.SecurityLevel, a.totp_secret, IF(length(a.s)<2 OR length(a.v)<2, a.sha_pass_hash, NULL), a.s, a.v "
+ "ab.unbandate = ab.bandate, aa.SecurityLevel, a.totp_secret, IF(a.s != DEFAULT(a.s) OR a.v != DEFAULT(a.v) OR a.salt IS NULL OR a.verifier IS NULL, a.sha_pass_hash, NULL), a.salt, a.verifier "
"FROM account a LEFT JOIN account_access aa ON a.id = aa.AccountID LEFT JOIN account_banned ab ON ab.id = a.id AND ab.active = 1 WHERE a.username = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_RECONNECTCHALLENGE, "SELECT a.id, UPPER(a.username), a.locked, a.lock_country, a.last_ip, a.failed_logins, ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, "
- "ab.unbandate = ab.bandate, aa.SecurityLevel, a.sessionKey "
- "FROM account a LEFT JOIN account_access aa ON a.id = aa.AccountID LEFT JOIN account_banned ab ON ab.id = a.id AND ab.active = 1 WHERE a.username = ?", CONNECTION_ASYNC);
+ "ab.unbandate = ab.bandate, aa.SecurityLevel, a.session_key "
+ "FROM account a LEFT JOIN account_access aa ON a.id = aa.AccountID LEFT JOIN account_banned ab ON ab.id = a.id AND ab.active = 1 WHERE a.username = ? AND a.session_key IS NOT NULL", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_FAILEDLOGINS, "UPDATE account SET failed_logins = failed_logins + 1 WHERE username = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_ACCOUNT_ID_BY_NAME, "SELECT id FROM account WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_LIST_BY_NAME, "SELECT id, username FROM account WHERE username = ?", CONNECTION_SYNCH);
- PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME, "SELECT a.id, a.sessionkey, a.last_ip, a.locked, a.lock_country, a.expansion, a.mutetime, a.locale, a.recruiter, a.os, aa.SecurityLevel, "
+ PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME, "SELECT a.id, a.session_key, a.last_ip, a.locked, a.lock_country, a.expansion, a.mutetime, a.locale, a.recruiter, a.os, aa.SecurityLevel, "
"ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, r.id FROM account a LEFT JOIN account_access aa ON a.id = aa.AccountID AND aa.RealmID IN (-1, ?) "
- "LEFT JOIN account_banned ab ON a.id = ab.id AND ab.active = 1 LEFT JOIN account r ON a.id = r.recruiter WHERE a.username = ? ORDER BY aa.RealmID DESC LIMIT 1", CONNECTION_ASYNC);
+ "LEFT JOIN account_banned ab ON a.id = ab.id AND ab.active = 1 LEFT JOIN account r ON a.id = r.recruiter WHERE a.username = ? AND a.session_key IS NOT NULL ORDER BY aa.RealmID DESC LIMIT 1", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_ACCOUNT_LIST_BY_EMAIL, "SELECT id, username FROM account WHERE email = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_REALM_CHARACTER_COUNTS, "SELECT realmid, numchars FROM realmcharacters WHERE acctid = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_ACCOUNT_BY_IP, "SELECT id, username FROM account WHERE last_ip = ?", CONNECTION_SYNCH);
@@ -61,14 +62,13 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_DEL_REALM_CHARACTERS, "DELETE FROM realmcharacters WHERE acctid = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_INS_REALM_CHARACTERS, "INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_SUM_REALM_CHARACTERS, "SELECT SUM(numchars) FROM realmcharacters WHERE acctid = ?", CONNECTION_ASYNC);
- PrepareStatement(LOGIN_INS_ACCOUNT, "INSERT INTO account(username, sha_pass_hash, reg_mail, email, joindate) VALUES(?, ?, ?, ?, NOW())", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_INS_ACCOUNT, "INSERT INTO account(username, salt, verifier, reg_mail, email, joindate) VALUES(?, ?, ?, ?, ?, NOW())", CONNECTION_SYNCH);
PrepareStatement(LOGIN_INS_REALM_CHARACTERS_INIT, "INSERT INTO realmcharacters (realmid, acctid, numchars) SELECT realmlist.id, account.id, 0 FROM realmlist, account LEFT JOIN realmcharacters ON acctid = account.id WHERE acctid IS NULL", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_EXPANSION, "UPDATE account SET expansion = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_ACCOUNT_LOCK, "UPDATE account SET locked = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_ACCOUNT_LOCK_COUNTRY, "UPDATE account SET lock_country = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_INS_LOG, "INSERT INTO logs (time, realm, type, level, string) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
- PrepareStatement(LOGIN_UPD_USERNAME, "UPDATE account SET v = 0, s = 0, username = ?, sha_pass_hash = ? WHERE id = ?", CONNECTION_ASYNC);
- PrepareStatement(LOGIN_UPD_PASSWORD, "UPDATE account SET v = 0, s = 0, sha_pass_hash = ? WHERE id = ?", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_UPD_USERNAME, "UPDATE account SET username = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_EMAIL, "UPDATE account SET email = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_REG_EMAIL, "UPDATE account SET reg_mail = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_MUTE_TIME, "UPDATE account SET mutetime = ? , mutereason = ? , muteby = ? WHERE id = ?", CONNECTION_ASYNC);
@@ -84,8 +84,8 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_GET_ACCOUNT_ID_BY_USERNAME, "SELECT id FROM account WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_GET_GMLEVEL_BY_REALMID, "SELECT SecurityLevel FROM account_access WHERE AccountID = ? AND (RealmID = ? OR RealmID = -1) ORDER BY RealmID DESC", CONNECTION_BOTH);
PrepareStatement(LOGIN_GET_USERNAME_BY_ID, "SELECT username FROM account WHERE id = ?", CONNECTION_SYNCH);
- PrepareStatement(LOGIN_SEL_CHECK_PASSWORD, "SELECT 1 FROM account WHERE id = ? AND sha_pass_hash = ?", CONNECTION_SYNCH);
- PrepareStatement(LOGIN_SEL_CHECK_PASSWORD_BY_NAME, "SELECT 1 FROM account WHERE username = ? AND sha_pass_hash = ?", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_SEL_CHECK_PASSWORD, "SELECT salt, verifier FROM account WHERE id = ? AND salt IS NOT NULL AND verifier IS NOT NULL", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_SEL_CHECK_PASSWORD_BY_NAME, "SELECT salt, verifier FROM account WHERE username = ? AND salt IS NOT NULL AND verifier IS NOT NULL", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_PINFO, "SELECT a.username, aa.SecurityLevel, a.email, a.reg_mail, a.last_ip, DATE_FORMAT(a.last_login, '%Y-%m-%d %T'), a.mutetime, a.mutereason, a.muteby, a.failed_logins, a.locked, a.OS FROM account a LEFT JOIN account_access aa ON (a.id = aa.AccountID AND (aa.RealmID = ? OR aa.RealmID = -1)) WHERE a.id = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_PINFO_BANS, "SELECT unbandate, bandate = unbandate, bannedby, banreason FROM account_banned WHERE id = ? AND active ORDER BY bandate ASC LIMIT 1", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_GM_ACCOUNTS, "SELECT a.username, aa.SecurityLevel FROM account a, account_access aa WHERE a.id = aa.AccountID AND aa.SecurityLevel >= ? AND (aa.RealmID = -1 OR aa.RealmID = ?)", CONNECTION_SYNCH);
diff --git a/src/server/database/Database/Implementation/LoginDatabase.h b/src/server/database/Database/Implementation/LoginDatabase.h
index eee8302457c..28eae7180ae 100644
--- a/src/server/database/Database/Implementation/LoginDatabase.h
+++ b/src/server/database/Database/Implementation/LoginDatabase.h
@@ -38,7 +38,8 @@ enum LoginDatabaseStatements : uint32
LOGIN_SEL_ACCOUNT_BANNED_BY_USERNAME,
LOGIN_INS_ACCOUNT_AUTO_BANNED,
LOGIN_DEL_ACCOUNT_BANNED,
- LOGIN_UPD_SV,
+ LOGIN_UPD_LOGON,
+ LOGIN_UPD_LOGON_LEGACY,
LOGIN_UPD_LOGONPROOF,
LOGIN_SEL_LOGONCHALLENGE,
LOGIN_SEL_RECONNECTCHALLENGE,
@@ -67,7 +68,6 @@ enum LoginDatabaseStatements : uint32
LOGIN_UPD_ACCOUNT_LOCK_COUNTRY,
LOGIN_INS_LOG,
LOGIN_UPD_USERNAME,
- LOGIN_UPD_PASSWORD,
LOGIN_UPD_EMAIL,
LOGIN_UPD_REG_EMAIL,
LOGIN_UPD_MUTE_TIME,
diff --git a/src/server/database/Database/PreparedStatement.h b/src/server/database/Database/PreparedStatement.h
index e7f39156252..b920289623e 100644
--- a/src/server/database/Database/PreparedStatement.h
+++ b/src/server/database/Database/PreparedStatement.h
@@ -77,6 +77,12 @@ class TC_DATABASE_API PreparedStatementBase
void setDouble(const uint8 index, const double value);
void setString(const uint8 index, const std::string& value);
void setBinary(const uint8 index, const std::vector<uint8>& value);
+ template <size_t Size>
+ void setBinary(const uint8 index, std::array<uint8, Size> const& value)
+ {
+ std::vector<uint8> vec(value.begin(), value.end());
+ setBinary(index, vec);
+ }
uint32 GetIndex() const { return m_index; }
std::vector<PreparedStatementData> const& GetParameters() const { return statement_data; }