diff options
author | Kahrl <kahrl@gmx.net> | 2011-11-20 20:16:15 +0100 |
---|---|---|
committer | Perttu Ahola <celeron55@gmail.com> | 2011-12-01 12:06:39 +0200 |
commit | 2ca00fa585087f2097796d994d378708041a7194 (patch) | |
tree | b2aecfa7d40b17f3b5eeac3b27942767c2b2aeec | |
parent | 1901158b3eacc95d945becea62ac28039618f460 (diff) | |
download | minetest-2ca00fa585087f2097796d994d378708041a7194.tar.gz minetest-2ca00fa585087f2097796d994d378708041a7194.tar.bz2 minetest-2ca00fa585087f2097796d994d378708041a7194.zip |
Fix processing of the default_password setting. It is now actually used as the plaintext password for new users. Also add /setpassword and /clearpassword server commands that can be used by admins with the PRIV_PASSWORD privilege, and update the /help message.
-rw-r--r-- | src/auth.cpp | 6 | ||||
-rw-r--r-- | src/auth.h | 1 | ||||
-rw-r--r-- | src/server.cpp | 73 | ||||
-rw-r--r-- | src/server.h | 9 | ||||
-rw-r--r-- | src/servercommand.cpp | 56 |
5 files changed, 109 insertions, 36 deletions
diff --git a/src/auth.cpp b/src/auth.cpp index 684391654..9920e0e40 100644 --- a/src/auth.cpp +++ b/src/auth.cpp @@ -42,6 +42,8 @@ std::set<std::string> privsToSet(u64 privs) s.insert("ban"); if(privs & PRIV_GIVE) s.insert("give"); + if(privs & PRIV_PASSWORD) + s.insert("password"); return s; } @@ -64,6 +66,8 @@ std::string privsToString(u64 privs) os<<"ban,"; if(privs & PRIV_GIVE) os<<"give,"; + if(privs & PRIV_PASSWORD) + os<<"password,"; if(os.tellp()) { // Drop the trailing comma. (Why on earth can't @@ -98,6 +102,8 @@ u64 stringToPrivs(std::string str) privs |= PRIV_BAN; else if(s == "give") privs |= PRIV_GIVE; + else if(s == "password") + privs |= PRIV_PASSWORD; else return PRIV_INVALID; } diff --git a/src/auth.h b/src/auth.h index 9939632a9..0ef94735f 100644 --- a/src/auth.h +++ b/src/auth.h @@ -41,6 +41,7 @@ const u64 PRIV_SHOUT = 32; // Can broadcast chat messages to all // players const u64 PRIV_BAN = 64; // Can ban players const u64 PRIV_GIVE = 128; // Can give stuff +const u64 PRIV_PASSWORD = 256; // Can set other players' passwords // Default privileges - these can be overriden for new players using the // config option "default_privs" - however, this value still applies for diff --git a/src/server.cpp b/src/server.cpp index 5646c0ac9..660fdfea9 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2171,20 +2171,33 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) password[PASSWORD_SIZE-1] = 0; } - std::string checkpwd; - if(m_authmanager.exists(playername)) - { - checkpwd = m_authmanager.getPassword(playername); - } - else + // Add player to auth manager + if(m_authmanager.exists(playername) == false) { - checkpwd = g_settings->get("default_password"); + std::wstring default_password = + narrow_to_wide(g_settings->get("default_password")); + std::string translated_default_password = + translatePassword(playername, default_password); + + // If default_password is empty, allow any initial password + if (default_password.length() == 0) + translated_default_password = password; + + infostream<<"Server: adding player "<<playername + <<" to auth manager"<<std::endl; + m_authmanager.add(playername); + m_authmanager.setPassword(playername, translated_default_password); + m_authmanager.setPrivs(playername, + stringToPrivs(g_settings->get("default_privs"))); + m_authmanager.save(); } - + + std::string checkpwd = m_authmanager.getPassword(playername); + /*infostream<<"Server: Client gave password '"<<password <<"', the correct one is '"<<checkpwd<<"'"<<std::endl;*/ - - if(password != checkpwd && m_authmanager.exists(playername)) + + if(password != checkpwd) { infostream<<"Server: peer_id="<<peer_id <<": supplied invalid password for " @@ -2193,23 +2206,11 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) return; } - // Add player to auth manager - if(m_authmanager.exists(playername) == false) - { - infostream<<"Server: adding player "<<playername - <<" to auth manager"<<std::endl; - m_authmanager.add(playername); - m_authmanager.setPassword(playername, checkpwd); - m_authmanager.setPrivs(playername, - stringToPrivs(g_settings->get("default_privs"))); - m_authmanager.save(); - } - // Enforce user limit. // Don't enforce for users that have some admin right if(m_clients.size() >= g_settings->getU16("max_users") && (m_authmanager.getPrivs(playername) - & (PRIV_SERVER|PRIV_BAN|PRIV_PRIVS)) == 0 && + & (PRIV_SERVER|PRIV_BAN|PRIV_PRIVS|PRIV_PASSWORD)) == 0 && playername != g_settings->get("name")) { SendAccessDenied(m_con, peer_id, L"Too many users."); @@ -2217,7 +2218,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) } // Get player - Player *player = emergePlayer(playername, password, peer_id); + Player *player = emergePlayer(playername, peer_id); // If failed, cancel if(player == NULL) @@ -4678,6 +4679,22 @@ std::wstring Server::getStatusString() return os.str(); } +void Server::setPlayerPassword(const std::string &name, const std::wstring &password) +{ + // Add player to auth manager + if(m_authmanager.exists(name) == false) + { + infostream<<"Server: adding player "<<name + <<" to auth manager"<<std::endl; + m_authmanager.add(name); + m_authmanager.setPrivs(name, + stringToPrivs(g_settings->get("default_privs"))); + } + // Change password and save + m_authmanager.setPassword(name, translatePassword(name, password)); + m_authmanager.save(); +} + // Saves g_settings to configpath given at initialization void Server::saveConfig() { @@ -4813,7 +4830,7 @@ v3f findSpawnPos(ServerMap &map) return intToFloat(nodepos, BS); } -Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id) +Player *Server::emergePlayer(const char *name, u16 peer_id) { /* Try to get an existing player @@ -4859,12 +4876,6 @@ Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id Create a new player */ { - // Add authentication stuff - m_authmanager.add(name); - m_authmanager.setPassword(name, password); - m_authmanager.setPrivs(name, - stringToPrivs(g_settings->get("default_privs"))); - /* Set player position */ infostream<<"Server: Finding spawn place for player \"" diff --git a/src/server.h b/src/server.h index 98c4f65d6..618b05d99 100644 --- a/src/server.h +++ b/src/server.h @@ -456,6 +456,10 @@ public: dstream<<"WARNING: Auth not found for "<<name<<std::endl; } } + + // Changes a player's password, password must be given as plaintext + // If the player doesn't exist, a new entry is added to the auth manager + void setPlayerPassword(const std::string &name, const std::wstring &password); // Saves g_settings to configpath given at initialization void saveConfig(); @@ -591,12 +595,11 @@ private: /* Get a player from memory or creates one. If player is already connected, return NULL - The password is not checked here - it is only used to - set the password if a new player is created. + Does not verify/modify auth info and password. Call with env and con locked. */ - Player *emergePlayer(const char *name, const char *password, u16 peer_id); + Player *emergePlayer(const char *name, u16 peer_id); // Locks environment and connection by its own struct PeerChange; diff --git a/src/servercommand.cpp b/src/servercommand.cpp index afd704fd3..d971b18a0 100644 --- a/src/servercommand.cpp +++ b/src/servercommand.cpp @@ -281,6 +281,54 @@ void cmd_banunban(std::wostringstream &os, ServerCommandContext *ctx) } } +void cmd_setclearpassword(std::wostringstream &os, + ServerCommandContext *ctx) +{ + if((ctx->privs & PRIV_PASSWORD) == 0) + { + os<<L"-!- You don't have permission to do that"; + return; + } + + std::string playername; + std::wstring password; + + if(ctx->parms[0] == L"setpassword") + { + if(ctx->parms.size() != 3) + { + os<<L"-!- Missing parameter"; + return; + } + + playername = wide_to_narrow(ctx->parms[1]); + password = ctx->parms[2]; + + actionstream<<ctx->player->getName()<<" sets password of " + <<playername<<std::endl; + } + else + { + // clearpassword + + if(ctx->parms.size() != 2) + { + os<<L"-!- Missing parameter"; + return; + } + + playername = wide_to_narrow(ctx->parms[1]); + password = L""; + + actionstream<<ctx->player->getName()<<" clears password of" + <<playername<<std::endl; + } + + ctx->server->setPlayerPassword(playername, password); + + os<<L"-!- Password change for "<<narrow_to_wide(playername)<<" successful"; +} + void cmd_clearobjects(std::wostringstream &os, ServerCommandContext *ctx) { @@ -322,9 +370,9 @@ std::wstring processServerCommand(ServerCommandContext *ctx) if(ctx->parms.size() == 0 || ctx->parms[0] == L"help") { os<<L"-!- Available commands: "; - os<<L"status privs "; + os<<L"me status privs"; if(privs & PRIV_SERVER) - os<<L"shutdown setting "; + os<<L" shutdown setting clearobjects"; if(privs & PRIV_SETTIME) os<<L" time"; if(privs & PRIV_TELEPORT) @@ -333,6 +381,8 @@ std::wstring processServerCommand(ServerCommandContext *ctx) os<<L" grant revoke"; if(privs & PRIV_BAN) os<<L" ban unban"; + if(privs & PRIV_PASSWORD) + os<<L" setpassword clearpassword"; } else if(ctx->parms[0] == L"status") cmd_status(os, ctx); @@ -350,6 +400,8 @@ std::wstring processServerCommand(ServerCommandContext *ctx) cmd_teleport(os, ctx); else if(ctx->parms[0] == L"ban" || ctx->parms[0] == L"unban") cmd_banunban(os, ctx); + else if(ctx->parms[0] == L"setpassword" || ctx->parms[0] == L"clearpassword") + cmd_setclearpassword(os, ctx); else if(ctx->parms[0] == L"me") cmd_me(os, ctx); else if(ctx->parms[0] == L"clearobjects") |