diff options
Diffstat (limited to 'src/client.cpp')
-rw-r--r-- | src/client.cpp | 134 |
1 files changed, 122 insertions, 12 deletions
diff --git a/src/client.cpp b/src/client.cpp index ceea56ba0..8cfcc85a7 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -22,10 +22,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #include <sstream> #include <IFileSystem.h> #include "jthread/jmutexautolock.h" +#include "util/auth.h" #include "util/directiontables.h" #include "util/pointedthing.h" #include "util/serialize.h" #include "util/string.h" +#include "util/srp.h" #include "client.h" #include "network/clientopcodes.h" #include "filesys.h" @@ -255,6 +257,8 @@ Client::Client( m_highlighted_pos(0,0,0), m_map_seed(0), m_password(password), + m_chosen_auth_mech(AUTH_MECHANISM_NONE), + m_auth_data(NULL), m_access_denied(false), m_itemdef_received(false), m_nodedef_received(false), @@ -404,10 +408,13 @@ void Client::step(float dtime) memset(pName, 0, PLAYERNAME_SIZE * sizeof(char)); memset(pPassword, 0, PASSWORD_SIZE * sizeof(char)); + std::string hashed_password = translatePassword(myplayer->getName(), m_password); snprintf(pName, PLAYERNAME_SIZE, "%s", myplayer->getName()); - snprintf(pPassword, PASSWORD_SIZE, "%s", m_password.c_str()); + snprintf(pPassword, PASSWORD_SIZE, "%s", hashed_password.c_str()); sendLegacyInit(pName, pPassword); + if (LATEST_PROTOCOL_VERSION >= 25) + sendInit(myplayer->getName()); } // Not connected, return @@ -943,6 +950,39 @@ void Client::interact(u8 action, const PointedThing& pointed) Send(&pkt); } +void Client::deleteAuthData() +{ + if (!m_auth_data) + return; + + switch (m_chosen_auth_mech) { + case AUTH_MECHANISM_FIRST_SRP: + break; + case AUTH_MECHANISM_SRP: + case AUTH_MECHANISM_LEGACY_PASSWORD: + srp_user_delete((SRPUser *) m_auth_data); + m_auth_data = NULL; + break; + case AUTH_MECHANISM_NONE: + break; + } +} + + +AuthMechanism Client::choseAuthMech(const u32 mechs) +{ + if (mechs & AUTH_MECHANISM_SRP) + return AUTH_MECHANISM_SRP; + + if (mechs & AUTH_MECHANISM_FIRST_SRP) + return AUTH_MECHANISM_FIRST_SRP; + + if (mechs & AUTH_MECHANISM_LEGACY_PASSWORD) + return AUTH_MECHANISM_LEGACY_PASSWORD; + + return AUTH_MECHANISM_NONE; +} + void Client::sendLegacyInit(const char* playerName, const char* playerPassword) { NetworkPacket pkt(TOSERVER_INIT_LEGACY, @@ -956,6 +996,70 @@ void Client::sendLegacyInit(const char* playerName, const char* playerPassword) Send(&pkt); } +void Client::sendInit(const std::string &playerName) +{ + NetworkPacket pkt(TOSERVER_INIT, 1 + 2 + 2 + (1 + playerName.size())); + + // TODO (later) actually send supported compression modes + pkt << (u8) SER_FMT_VER_HIGHEST_READ << (u8) 42; + pkt << (u16) CLIENT_PROTOCOL_VERSION_MIN << (u16) CLIENT_PROTOCOL_VERSION_MAX; + pkt << playerName; + + Send(&pkt); +} + +void Client::startAuth(AuthMechanism chosen_auth_mechanism) +{ + m_chosen_auth_mech = chosen_auth_mechanism; + + switch (chosen_auth_mechanism) { + case AUTH_MECHANISM_FIRST_SRP: { + // send srp verifier to server + NetworkPacket resp_pkt(TOSERVER_FIRST_SRP, 0); + char *salt, *bytes_v; + std::size_t len_salt, len_v; + salt = NULL; + getSRPVerifier(getPlayerName(), m_password, + &salt, &len_salt, &bytes_v, &len_v); + resp_pkt + << std::string((char*)salt, len_salt) + << std::string((char*)bytes_v, len_v) + << (u8)((m_password == "") ? 1 : 0); + free(salt); + free(bytes_v); + Send(&resp_pkt); + break; + } + case AUTH_MECHANISM_SRP: + case AUTH_MECHANISM_LEGACY_PASSWORD: { + u8 based_on = 1; + + if (chosen_auth_mechanism == AUTH_MECHANISM_LEGACY_PASSWORD) { + m_password = translatePassword(getPlayerName(), m_password); + based_on = 0; + } + + std::string playername_u = lowercase(getPlayerName()); + m_auth_data = srp_user_new(SRP_SHA256, SRP_NG_2048, + getPlayerName().c_str(), playername_u.c_str(), + (const unsigned char *) m_password.c_str(), + m_password.length(), NULL, NULL); + char *bytes_A = 0; + size_t len_A = 0; + srp_user_start_authentication((struct SRPUser *) m_auth_data, + NULL, NULL, 0, (unsigned char **) &bytes_A, &len_A); + + NetworkPacket resp_pkt(TOSERVER_SRP_BYTES_A, 0); + resp_pkt << std::string(bytes_A, len_A) << based_on; + free(bytes_A); + Send(&resp_pkt); + break; + } + case AUTH_MECHANISM_NONE: + break; // not handled in this method + } +} + void Client::sendDeletedBlocks(std::vector<v3s16> &blocks) { NetworkPacket pkt(TOSERVER_DELETEDBLOCKS, 1 + sizeof(v3s16) * blocks.size()); @@ -1066,24 +1170,30 @@ void Client::sendChangePassword(const std::string &oldpassword, const std::string &newpassword) { Player *player = m_env.getLocalPlayer(); - if(player == NULL) + if (player == NULL) return; std::string playername = player->getName(); - std::string oldpwd = translatePassword(playername, oldpassword); - std::string newpwd = translatePassword(playername, newpassword); + if (m_proto_ver >= 25) { + // get into sudo mode and then send new password to server + m_password = oldpassword; + m_new_password = newpassword; + startAuth(choseAuthMech(m_sudo_auth_methods)); + } else { + std::string oldpwd = translatePassword(playername, oldpassword); + std::string newpwd = translatePassword(playername, newpassword); - NetworkPacket pkt(TOSERVER_PASSWORD_LEGACY, 2 * PASSWORD_SIZE); + NetworkPacket pkt(TOSERVER_PASSWORD_LEGACY, 2 * PASSWORD_SIZE); - for(u8 i = 0; i < PASSWORD_SIZE; i++) { - pkt << (u8) (i < oldpwd.length() ? oldpwd[i] : 0); - } + for (u8 i = 0; i < PASSWORD_SIZE; i++) { + pkt << (u8) (i < oldpwd.length() ? oldpwd[i] : 0); + } - for(u8 i = 0; i < PASSWORD_SIZE; i++) { - pkt << (u8) (i < newpwd.length() ? newpwd[i] : 0); + for (u8 i = 0; i < PASSWORD_SIZE; i++) { + pkt << (u8) (i < newpwd.length() ? newpwd[i] : 0); + } + Send(&pkt); } - - Send(&pkt); } |