diff options
Diffstat (limited to 'src/network/clientpackethandler.cpp')
-rw-r--r-- | src/network/clientpackethandler.cpp | 99 |
1 files changed, 95 insertions, 4 deletions
diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index bddf8f6fd..2106e4368 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "strfnd.h" #include "network/clientopcodes.h" #include "util/serialize.h" +#include "util/srp.h" void Client::handleCommand_Deprecated(NetworkPacket* pkt) { @@ -44,10 +45,16 @@ void Client::handleCommand_Hello(NetworkPacket* pkt) return; u8 deployed; - *pkt >> deployed; + u32 auth_mechs; + std::string username_legacy; // for case insensitivity + *pkt >> deployed >> auth_mechs >> username_legacy; + + // Chose an auth method we support + AuthMechanism chosen_auth_mechanism = choseAuthMech(auth_mechs); infostream << "Client: TOCLIENT_HELLO received with " - "deployed=" << ((int)deployed & 0xff) << std::endl; + "deployed=" << ((int)deployed & 0xff) << ", auth_mechs=" + << auth_mechs << ", chosen=" << chosen_auth_mechanism << std::endl; if (!ser_ver_supported(deployed)) { infostream << "Client: TOCLIENT_HELLO: Server sent " @@ -56,14 +63,43 @@ void Client::handleCommand_Hello(NetworkPacket* pkt) } m_server_ser_ver = deployed; + m_proto_ver = deployed; + + //TODO verify that username_legacy matches sent username, only + // differs in casing (make both uppercase and compare) + // This is only neccessary though when we actually want to add casing support + + if (m_chosen_auth_mech != AUTH_MECHANISM_NONE) { + // we recieved a TOCLIENT_HELLO while auth was already going on + errorstream << "Client: TOCLIENT_HELLO while auth was already going on" + << "(chosen_mech=" << m_chosen_auth_mech << ")." << std::endl; + if ((m_chosen_auth_mech == AUTH_MECHANISM_SRP) + || (m_chosen_auth_mech == AUTH_MECHANISM_LEGACY_PASSWORD)) { + srp_user_delete((SRPUser *) m_auth_data); + m_auth_data = 0; + } + } + + // Authenticate using that method, or abort if there wasn't any method found + if (chosen_auth_mechanism != AUTH_MECHANISM_NONE) { + startAuth(chosen_auth_mechanism); + } else { + m_chosen_auth_mech = AUTH_MECHANISM_NONE; + m_access_denied = true; + m_access_denied_reason = "Unknown"; + m_con.Disconnect(); + } - // @ TODO auth to server } void Client::handleCommand_AuthAccept(NetworkPacket* pkt) { + m_chosen_auth_mech = AUTH_MECHANISM_NONE; + deleteAuthData(); + v3f playerpos; - *pkt >> playerpos >> m_map_seed >> m_recommended_send_interval; + *pkt >> playerpos >> m_map_seed >> m_recommended_send_interval + >> m_sudo_auth_methods; playerpos -= v3f(0, BS / 2, 0); @@ -82,7 +118,28 @@ void Client::handleCommand_AuthAccept(NetworkPacket* pkt) m_state = LC_Init; } +void Client::handleCommand_AcceptSudoMode(NetworkPacket* pkt) +{ + m_chosen_auth_mech = AUTH_MECHANISM_NONE; + deleteAuthData(); + + m_password = m_new_password; + + verbosestream << "Client: Recieved TOCLIENT_ACCEPT_SUDO_MODE." << std::endl; + // send packet to actually set the password + startAuth(AUTH_MECHANISM_FIRST_SRP); + + // reset again + m_chosen_auth_mech = AUTH_MECHANISM_NONE; +} +void Client::handleCommand_DenySudoMode(NetworkPacket* pkt) +{ + m_chat_queue.push(L"Password change denied. Password NOT changed."); + // reset everything and be sad + deleteAuthData(); + m_chosen_auth_mech = AUTH_MECHANISM_NONE; +} void Client::handleCommand_InitLegacy(NetworkPacket* pkt) { if (pkt->getSize() < 1) @@ -101,6 +158,7 @@ void Client::handleCommand_InitLegacy(NetworkPacket* pkt) } m_server_ser_ver = deployed; + m_proto_ver = deployed; // Get player position v3s16 playerpos_s16(0, BS * 2 + BS * 20, 0); @@ -1105,3 +1163,36 @@ void Client::handleCommand_EyeOffset(NetworkPacket* pkt) *pkt >> player->eye_offset_first >> player->eye_offset_third; } + +void Client::handleCommand_SrpBytesSandB(NetworkPacket* pkt) +{ + if ((m_chosen_auth_mech != AUTH_MECHANISM_LEGACY_PASSWORD) + && (m_chosen_auth_mech != AUTH_MECHANISM_SRP)) { + errorstream << "Client: Recieved SRP S_B login message," + << " but wasn't supposed to (chosen_mech=" + << m_chosen_auth_mech << ")." << std::endl; + return; + } + + char *bytes_M = 0; + size_t len_M = 0; + SRPUser *usr = (SRPUser *) m_auth_data; + std::string s; + std::string B; + *pkt >> s >> B; + + infostream << "Client: Recieved TOCLIENT_SRP_BYTES_S_B." << std::endl; + + srp_user_process_challenge(usr, (const unsigned char *) s.c_str(), s.size(), + (const unsigned char *) B.c_str(), B.size(), + (unsigned char **) &bytes_M, &len_M); + + if ( !bytes_M ) { + errorstream << "Client: SRP-6a S_B safety check violation!" << std::endl; + return; + } + + NetworkPacket resp_pkt(TOSERVER_SRP_BYTES_M, 0); + resp_pkt << std::string(bytes_M, len_M); + Send(&resp_pkt); +} |