1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Make early protocol auth mechanism generic, and add SRP

Adds everything needed for SRP (and everything works too),
but still deactivated, as protocol v25 init packets aren't final yet.
Can be activated by changing the LATEST_PROTOCOL_VERSION header to 25
inside networkprotocol.h.
This commit is contained in:
est31 2015-04-12 04:49:13 +02:00
parent 181f7baa45
commit 82e35edff5
25 changed files with 3351 additions and 309 deletions

View file

@ -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);
}
Send(&pkt);
}
for(u8 i = 0; i < PASSWORD_SIZE; i++) {
pkt << (u8) (i < newpwd.length() ? newpwd[i] : 0);
}
Send(&pkt);
}