Fix processing of the default_password setting. It is now actually used as the plaint...
authorKahrl <kahrl@gmx.net>
Sun, 20 Nov 2011 19:16:15 +0000 (20:16 +0100)
committerPerttu Ahola <celeron55@gmail.com>
Thu, 1 Dec 2011 10:06:39 +0000 (12:06 +0200)
src/auth.cpp
src/auth.h
src/server.cpp
src/server.h
src/servercommand.cpp

index 684391654ab62909484d43d4e12928c389877b0b..9920e0e40a9dbae0766b5aeaba8fb1fdffb1e763 100644 (file)
@@ -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;
        }
index 9939632a9b1d031bbccdb48978a6b2c7ee3648b2..0ef94735f643e11004493a857d37d69823a8bc5d 100644 (file)
@@ -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
index 5646c0ac9c9dffdccff84b15f7e5ee00d83ce738..660fdfea9f252bc2ee04c5e69143d1a26b10b4f4 100644 (file)
@@ -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 \""
index 98c4f65d662395ea7d7611fd161ec17dc243ba13..618b05d99064bbccfbaba245d7d3d3293e956be8 100644 (file)
@@ -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;
index afd704fd3f761fd04943b8276191886b74085d23..d971b18a04c34d103a1a26d104b4e8bceecfea28 100644 (file)
@@ -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")