summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPerttu Ahola <celeron55@gmail.com>2012-03-30 18:42:18 +0300
committerPerttu Ahola <celeron55@gmail.com>2012-03-30 18:42:18 +0300
commit7cad0a2dcd817b179f82066964c45937a603d138 (patch)
treef97c0ea3d9ccc5b67688fa1110b972c610a65430 /src
parented1ff06867e84f197330b45168c6ebcba672e532 (diff)
downloadminetest-7cad0a2dcd817b179f82066964c45937a603d138.tar.gz
minetest-7cad0a2dcd817b179f82066964c45937a603d138.tar.bz2
minetest-7cad0a2dcd817b179f82066964c45937a603d138.zip
Reimplement authentication handler in Lua; now we have 1) infinite privilege names, 2) minetest.register_authentication_handler()
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/auth.cpp306
-rw-r--r--src/auth.h107
-rw-r--r--src/scriptapi.cpp129
-rw-r--r--src/scriptapi.h7
-rw-r--r--src/server.cpp178
-rw-r--r--src/server.h17
-rw-r--r--src/servercommand.cpp164
-rw-r--r--src/servercommand.h8
9 files changed, 202 insertions, 715 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index fce887047..0c7fc988c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -173,7 +173,6 @@ set(common_SRCS
mapgen.cpp
content_nodemeta.cpp
content_mapnode.cpp
- auth.cpp
collision.cpp
nodemetadata.cpp
serverobject.cpp
diff --git a/src/auth.cpp b/src/auth.cpp
deleted file mode 100644
index cafeb38d4..000000000
--- a/src/auth.cpp
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
-Minetest-c55
-Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-#include "auth.h"
-#include <fstream>
-#include <jmutexautolock.h>
-//#include "main.h" // for g_settings
-#include <sstream>
-#include "strfnd.h"
-#include "log.h"
-
-std::set<std::string> privsToSet(u64 privs)
-{
- std::set<std::string> s;
- if(privs & PRIV_INTERACT)
- s.insert("interact");
- if(privs & PRIV_TELEPORT)
- s.insert("teleport");
- if(privs & PRIV_SETTIME)
- s.insert("settime");
- if(privs & PRIV_PRIVS)
- s.insert("privs");
- if(privs & PRIV_SERVER)
- s.insert("server");
- if(privs & PRIV_SHOUT)
- s.insert("shout");
- if(privs & PRIV_BAN)
- s.insert("ban");
- if(privs & PRIV_GIVE)
- s.insert("give");
- if(privs & PRIV_PASSWORD)
- s.insert("password");
- return s;
-}
-
-// Convert a privileges value into a human-readable string,
-// with each component separated by a comma.
-std::string privsToString(u64 privs)
-{
- std::ostringstream os(std::ios_base::binary);
- if(privs & PRIV_INTERACT)
- os<<"interact,";
- if(privs & PRIV_TELEPORT)
- os<<"teleport,";
- if(privs & PRIV_SETTIME)
- os<<"settime,";
- if(privs & PRIV_PRIVS)
- os<<"privs,";
- if(privs & PRIV_SERVER)
- os<<"server,";
- if(privs & PRIV_SHOUT)
- os<<"shout,";
- if(privs & PRIV_BAN)
- 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
- // you truncate a C++ stream anyway???)
- std::string tmp = os.str();
- return tmp.substr(0, tmp.length() -1);
- }
- return os.str();
-}
-
-// Converts a comma-seperated list of privilege values into a
-// privileges value. The reverse of privsToString(). Returns
-// PRIV_INVALID if there is anything wrong with the input.
-u64 stringToPrivs(std::string str)
-{
- u64 privs=0;
- Strfnd f(str);
- while(f.atend() == false)
- {
- std::string s = trim(f.next(","));
- if(s == "build")
- privs |= PRIV_INTERACT;
- else if(s == "interact")
- privs |= PRIV_INTERACT;
- else if(s == "teleport")
- privs |= PRIV_TELEPORT;
- else if(s == "settime")
- privs |= PRIV_SETTIME;
- else if(s == "privs")
- privs |= PRIV_PRIVS;
- else if(s == "server")
- privs |= PRIV_SERVER;
- else if(s == "shout")
- privs |= PRIV_SHOUT;
- else if(s == "ban")
- privs |= PRIV_BAN;
- else if(s == "give")
- privs |= PRIV_GIVE;
- else if(s == "password")
- privs |= PRIV_PASSWORD;
- else
- return PRIV_INVALID;
- }
- return privs;
-}
-
-AuthManager::AuthManager(const std::string &authfilepath):
- m_authfilepath(authfilepath),
- m_modified(false)
-{
- m_mutex.Init();
-
- try{
- load();
- }
- catch(SerializationError &e)
- {
- infostream<<"WARNING: AuthManager: creating "
- <<m_authfilepath<<std::endl;
- }
-}
-
-AuthManager::~AuthManager()
-{
- save();
-}
-
-void AuthManager::load()
-{
- JMutexAutoLock lock(m_mutex);
-
- infostream<<"AuthManager: loading from "<<m_authfilepath<<std::endl;
- std::ifstream is(m_authfilepath.c_str(), std::ios::binary);
- if(is.good() == false)
- {
- infostream<<"AuthManager: failed loading from "<<m_authfilepath<<std::endl;
- throw SerializationError("AuthManager::load(): Couldn't open file");
- }
-
- for(;;)
- {
- if(is.eof() || is.good() == false)
- break;
-
- // Read a line
- std::string line;
- std::getline(is, line, '\n');
-
- std::istringstream iss(line);
-
- // Read name
- std::string name;
- std::getline(iss, name, ':');
-
- // Read password
- std::string pwd;
- std::getline(iss, pwd, ':');
-
- // Read privileges
- std::string stringprivs;
- std::getline(iss, stringprivs, ':');
- u64 privs = stringToPrivs(stringprivs);
-
- // Store it
- AuthData ad;
- ad.pwd = pwd;
- ad.privs = privs;
- m_authdata[name] = ad;
- }
-
- m_modified = false;
-}
-
-void AuthManager::save()
-{
- JMutexAutoLock lock(m_mutex);
-
- infostream<<"AuthManager: saving to "<<m_authfilepath<<std::endl;
- std::ofstream os(m_authfilepath.c_str(), std::ios::binary);
- if(os.good() == false)
- {
- infostream<<"AuthManager: failed saving to "<<m_authfilepath<<std::endl;
- throw SerializationError("AuthManager::save(): Couldn't open file");
- }
-
- for(core::map<std::string, AuthData>::Iterator
- i = m_authdata.getIterator();
- i.atEnd()==false; i++)
- {
- std::string name = i.getNode()->getKey();
- if(name == "")
- continue;
- AuthData ad = i.getNode()->getValue();
- os<<name<<":"<<ad.pwd<<":"<<privsToString(ad.privs)<<"\n";
- }
-
- m_modified = false;
-}
-
-bool AuthManager::exists(const std::string &username)
-{
- JMutexAutoLock lock(m_mutex);
-
- core::map<std::string, AuthData>::Node *n;
- n = m_authdata.find(username);
- if(n == NULL)
- return false;
- return true;
-}
-
-void AuthManager::set(const std::string &username, AuthData ad)
-{
- JMutexAutoLock lock(m_mutex);
-
- m_authdata[username] = ad;
-
- m_modified = true;
-}
-
-void AuthManager::add(const std::string &username)
-{
- JMutexAutoLock lock(m_mutex);
-
- m_authdata[username] = AuthData();
-
- m_modified = true;
-}
-
-std::string AuthManager::getPassword(const std::string &username)
-{
- JMutexAutoLock lock(m_mutex);
-
- core::map<std::string, AuthData>::Node *n;
- n = m_authdata.find(username);
- if(n == NULL)
- throw AuthNotFoundException("");
-
- return n->getValue().pwd;
-}
-
-void AuthManager::setPassword(const std::string &username,
- const std::string &password)
-{
- JMutexAutoLock lock(m_mutex);
-
- core::map<std::string, AuthData>::Node *n;
- n = m_authdata.find(username);
- if(n == NULL)
- throw AuthNotFoundException("");
-
- AuthData ad = n->getValue();
- ad.pwd = password;
- n->setValue(ad);
-
- m_modified = true;
-}
-
-u64 AuthManager::getPrivs(const std::string &username)
-{
- JMutexAutoLock lock(m_mutex);
-
- core::map<std::string, AuthData>::Node *n;
- n = m_authdata.find(username);
- if(n == NULL)
- throw AuthNotFoundException("");
-
- return n->getValue().privs;
-}
-
-void AuthManager::setPrivs(const std::string &username, u64 privs)
-{
- JMutexAutoLock lock(m_mutex);
-
- core::map<std::string, AuthData>::Node *n;
- n = m_authdata.find(username);
- if(n == NULL)
- throw AuthNotFoundException("");
-
- AuthData ad = n->getValue();
- ad.privs = privs;
- n->setValue(ad);
-
- m_modified = true;
-}
-
-bool AuthManager::isModified()
-{
- JMutexAutoLock lock(m_mutex);
- return m_modified;
-}
-
-
diff --git a/src/auth.h b/src/auth.h
deleted file mode 100644
index 6f176931a..000000000
--- a/src/auth.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
-Minetest-c55
-Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-#ifndef AUTH_HEADER
-#define AUTH_HEADER
-
-#include <set>
-#include <string>
-#include <jthread.h>
-#include <jmutex.h>
-#include "irrlichttypes.h"
-#include "exceptions.h"
-
-// Player privileges. These form a bitmask stored in the privs field
-// of the player, and define things they're allowed to do. See also
-// the static methods Player::privsToString and stringToPrivs that
-// convert these to human-readable form.
-const u64 PRIV_INTERACT = 1; // Can interact
-const u64 PRIV_TELEPORT = 2; // Can teleport
-const u64 PRIV_SETTIME = 4; // Can set the time
-const u64 PRIV_PRIVS = 8; // Can grant and revoke privileges
-const u64 PRIV_SERVER = 16; // Can manage the server (e.g. shutodwn
- // ,settings)
-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
-// players that existed before the privileges system was added.
-const u64 PRIV_DEFAULT = PRIV_INTERACT|PRIV_SHOUT;
-const u64 PRIV_ALL = 0x7FFFFFFFFFFFFFFFULL;
-const u64 PRIV_INVALID = 0x8000000000000000ULL;
-
-std::set<std::string> privsToSet(u64 privs);
-
-// Convert a privileges value into a human-readable string,
-// with each component separated by a comma.
-std::string privsToString(u64 privs);
-
-// Converts a comma-seperated list of privilege values into a
-// privileges value. The reverse of privsToString(). Returns
-// PRIV_INVALID if there is anything wrong with the input.
-u64 stringToPrivs(std::string str);
-
-struct AuthData
-{
- std::string pwd;
- u64 privs;
-
- AuthData():
- privs(PRIV_DEFAULT)
- {
- }
-};
-
-class AuthNotFoundException : public BaseException
-{
-public:
- AuthNotFoundException(const char *s):
- BaseException(s)
- {}
-};
-
-class AuthManager
-{
-public:
- AuthManager(const std::string &authfilepath);
- ~AuthManager();
- void load();
- void save();
- bool exists(const std::string &username);
- void set(const std::string &username, AuthData ad);
- void add(const std::string &username);
- std::string getPassword(const std::string &username);
- void setPassword(const std::string &username,
- const std::string &password);
- u64 getPrivs(const std::string &username);
- void setPrivs(const std::string &username, u64 privs);
- bool isModified();
-private:
- JMutex m_mutex;
- std::string m_authfilepath;
- core::map<std::string, AuthData> m_authdata;
- bool m_modified;
-};
-
-#endif
-
diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp
index 65894e284..4ca114a0c 100644
--- a/src/scriptapi.cpp
+++ b/src/scriptapi.cpp
@@ -141,14 +141,14 @@ static Server* get_server(lua_State *L)
return server;
}
-static ServerEnvironment* get_env(lua_State *L)
+/*static ServerEnvironment* get_env(lua_State *L)
{
// Get environment from registry
lua_getfield(L, LUA_REGISTRYINDEX, "minetest_env");
ServerEnvironment *env = (ServerEnvironment*)lua_touserdata(L, -1);
lua_pop(L, 1);
return env;
-}
+}*/
static void objectref_get(lua_State *L, u16 id)
{
@@ -648,6 +648,27 @@ static void read_groups(lua_State *L, int index,
}
/*
+ Privileges
+*/
+static void read_privileges(lua_State *L, int index,
+ std::set<std::string> &result)
+{
+ result.clear();
+ lua_pushnil(L);
+ if(index < 0)
+ index -= 1;
+ while(lua_next(L, index) != 0){
+ // key at index -2 and value at index -1
+ std::string key = luaL_checkstring(L, -2);
+ bool value = lua_toboolean(L, -1);
+ if(value)
+ result.insert(key);
+ // removes value, keeps key for next iteration
+ lua_pop(L, 1);
+ }
+}
+
+/*
ToolCapabilities
*/
@@ -3837,8 +3858,7 @@ static int l_get_player_privs(lua_State *L)
// Do it
lua_newtable(L);
int table = lua_gettop(L);
- u64 privs_i = server->getPlayerEffectivePrivs(name);
- std::set<std::string> privs_s = privsToSet(privs_i);
+ std::set<std::string> privs_s = server->getPlayerEffectivePrivs(name);
for(std::set<std::string>::const_iterator
i = privs_s.begin(); i != privs_s.end(); i++){
lua_pushboolean(L, true);
@@ -3954,6 +3974,17 @@ static int l_is_singleplayer(lua_State *L)
return 1;
}
+// get_password_hash(name, raw_password)
+static int l_get_password_hash(lua_State *L)
+{
+ std::string name = luaL_checkstring(L, 1);
+ std::string raw_password = luaL_checkstring(L, 2);
+ std::string hash = translatePassword(name,
+ narrow_to_wide(raw_password));
+ lua_pushstring(L, hash.c_str());
+ return 1;
+}
+
static const struct luaL_Reg minetest_f [] = {
{"debug", l_debug},
{"log", l_log},
@@ -3974,6 +4005,7 @@ static const struct luaL_Reg minetest_f [] = {
{"sound_play", l_sound_play},
{"sound_stop", l_sound_stop},
{"is_singleplayer", l_is_singleplayer},
+ {"get_password_hash", l_get_password_hash},
{NULL, NULL}
};
@@ -4421,6 +4453,10 @@ void scriptapi_on_leaveplayer(lua_State *L, ServerActiveObject *player)
void scriptapi_get_creative_inventory(lua_State *L, ServerActiveObject *player)
{
+ realitycheck(L);
+ assert(lua_checkstack(L, 20));
+ StackUnroller stack_unroller(L);
+
Inventory *inv = player->getInventory();
assert(inv);
@@ -4430,6 +4466,91 @@ void scriptapi_get_creative_inventory(lua_State *L, ServerActiveObject *player)
inventory_set_list_from_lua(inv, "main", L, -1, PLAYER_INVENTORY_SIZE);
}
+static void get_auth_handler(lua_State *L)
+{
+ lua_getglobal(L, "minetest");
+ lua_getfield(L, -1, "registered_auth_handler");
+ if(lua_isnil(L, -1)){
+ lua_pop(L, 1);
+ lua_getfield(L, -1, "builtin_auth_handler");
+ }
+ if(lua_type(L, -1) != LUA_TTABLE)
+ throw LuaError(L, "Authentication handler table not valid");
+}
+
+bool scriptapi_get_auth(lua_State *L, const std::string &playername,
+ std::string *dst_password, std::set<std::string> *dst_privs)
+{
+ realitycheck(L);
+ assert(lua_checkstack(L, 20));
+ StackUnroller stack_unroller(L);
+
+ get_auth_handler(L);
+ lua_getfield(L, -1, "get_auth");
+ if(lua_type(L, -1) != LUA_TFUNCTION)
+ throw LuaError(L, "Authentication handler missing get_auth");
+ lua_pushstring(L, playername.c_str());
+ if(lua_pcall(L, 1, 1, 0))
+ script_error(L, "error: %s", lua_tostring(L, -1));
+
+ // nil = login not allowed
+ if(lua_isnil(L, -1))
+ return false;
+ luaL_checktype(L, -1, LUA_TTABLE);
+
+ std::string password;
+ bool found = getstringfield(L, -1, "password", password);
+ if(!found)
+ throw LuaError(L, "Authentication handler didn't return password");
+ if(dst_password)
+ *dst_password = password;
+
+ lua_getfield(L, -1, "privileges");
+ if(!lua_istable(L, -1))
+ throw LuaError(L,
+ "Authentication handler didn't return privilege table");
+ if(dst_privs)
+ read_privileges(L, -1, *dst_privs);
+ lua_pop(L, 1);
+
+ return true;
+}
+
+void scriptapi_create_auth(lua_State *L, const std::string &playername,
+ const std::string &password)
+{
+ realitycheck(L);
+ assert(lua_checkstack(L, 20));
+ StackUnroller stack_unroller(L);
+
+ get_auth_handler(L);
+ lua_getfield(L, -1, "create_auth");
+ if(lua_type(L, -1) != LUA_TFUNCTION)
+ throw LuaError(L, "Authentication handler missing create_auth");
+ lua_pushstring(L, playername.c_str());
+ lua_pushstring(L, password.c_str());
+ if(lua_pcall(L, 2, 0, 0))
+ script_error(L, "error: %s", lua_tostring(L, -1));
+}
+
+bool scriptapi_set_password(lua_State *L, const std::string &playername,
+ const std::string &password)
+{
+ realitycheck(L);
+ assert(lua_checkstack(L, 20));
+ StackUnroller stack_unroller(L);
+
+ get_auth_handler(L);
+ lua_getfield(L, -1, "set_password");
+ if(lua_type(L, -1) != LUA_TFUNCTION)
+ throw LuaError(L, "Authentication handler missing set_password");
+ lua_pushstring(L, playername.c_str());
+ lua_pushstring(L, password.c_str());
+ if(lua_pcall(L, 2, 1, 0))
+ script_error(L, "error: %s", lua_tostring(L, -1));
+ return lua_toboolean(L, -1);
+}
+
/*
item callbacks and node callbacks
*/
diff --git a/src/scriptapi.h b/src/scriptapi.h
index b80039f9e..fe8b26e04 100644
--- a/src/scriptapi.h
+++ b/src/scriptapi.h
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes.h"
#include <string>
#include "mapnode.h"
+#include <set>
class Server;
class ServerEnvironment;
@@ -60,6 +61,12 @@ bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player);
void scriptapi_on_joinplayer(lua_State *L, ServerActiveObject *player);
void scriptapi_on_leaveplayer(lua_State *L, ServerActiveObject *player);
void scriptapi_get_creative_inventory(lua_State *L, ServerActiveObject *player);
+bool scriptapi_get_auth(lua_State *L, const std::string &playername,
+ std::string *dst_password, std::set<std::string> *dst_privs);
+void scriptapi_create_auth(lua_State *L, const std::string &playername,
+ const std::string &password);
+bool scriptapi_set_password(lua_State *L, const std::string &playername,
+ const std::string &password);
/* item callbacks */
bool scriptapi_item_on_drop(lua_State *L, ItemStack &item,
diff --git a/src/server.cpp b/src/server.cpp
index 4a6165f30..e9b236cc4 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -142,6 +142,10 @@ void * ServerThread::Thread()
{
m_server->setAsyncFatalError(e.what());
}
+ catch(LuaError &e)
+ {
+ m_server->setAsyncFatalError(e.what());
+ }
}
END_DEBUG_EXCEPTION_HANDLER(errorstream)
@@ -905,7 +909,6 @@ Server::Server(
m_async_fatal_error(""),
m_env(NULL),
m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
- m_authmanager(path_world+DIR_DELIM+"auth.txt"),
m_banmanager(path_world+DIR_DELIM+"ipban.txt"),
m_lua(NULL),
m_itemdef(createItemDefManager()),
@@ -1844,10 +1847,6 @@ void Server::AsyncRunStep()
ScopeProfiler sp(g_profiler, "Server: saving stuff");
- // Auth stuff
- if(m_authmanager.isModified())
- m_authmanager.save();
-
//Ban stuff
if(m_banmanager.isModified())
m_banmanager.save();
@@ -2083,34 +2082,30 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
password[PASSWORD_SIZE-1] = 0;
}
- // Add player to auth manager
- if(m_authmanager.exists(playername) == false)
- {
- std::wstring default_password =
+ std::string checkpwd;
+ bool has_auth = scriptapi_get_auth(m_lua, playername, &checkpwd, NULL);
+
+ if(!has_auth){
+ std::wstring raw_default_password =
narrow_to_wide(g_settings->get("default_password"));
- std::string translated_default_password =
- translatePassword(playername, default_password);
+ std::string use_password =
+ translatePassword(playername, raw_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();
- }
+ if (raw_default_password.length() == 0)
+ use_password = password;
- std::string checkpwd = m_authmanager.getPassword(playername);
+ scriptapi_create_auth(m_lua, playername, use_password);
+ }
+
+ has_auth = scriptapi_get_auth(m_lua, playername, &checkpwd, NULL);
- /*infostream<<"Server: Client gave password '"<<password
- <<"', the correct one is '"<<checkpwd<<"'"<<std::endl;*/
+ if(!has_auth){
+ SendAccessDenied(m_con, peer_id, L"Not allowed to login");
+ return;
+ }
- if(password != checkpwd)
- {
+ if(password != checkpwd){
infostream<<"Server: peer_id="<<peer_id
<<": supplied invalid password for "
<<playername<<std::endl;
@@ -2131,8 +2126,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
// 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|PRIV_PASSWORD)) == 0 &&
+ !checkPriv(playername, "server") &&
+ !checkPriv(playername, "ban") &&
+ !checkPriv(playername, "privs") &&
+ !checkPriv(playername, "password") &&
playername != g_settings->get("name"))
{
actionstream<<"Server: "<<playername<<" tried to join, but there"
@@ -2407,7 +2404,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
}
else if(command == TOSERVER_SIGNNODETEXT)
{
- if((getPlayerPrivs(player) & PRIV_INTERACT) == 0)
+ if(!checkPriv(player->getName(), "interact"))
return;
/*
u16 command
@@ -2519,9 +2516,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
// Disallow moving items in elsewhere than player's inventory
// if not allowed to interact
- if((getPlayerPrivs(player) & PRIV_INTERACT) == 0
- && (!from_inv_is_current_player
- || !to_inv_is_current_player))
+ if(!checkPriv(player->getName(), "interact") &&
+ (!from_inv_is_current_player ||
+ !to_inv_is_current_player))
{
infostream<<"Cannot move outside of player's inventory: "
<<"No interact privilege"<<std::endl;
@@ -2530,7 +2527,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
}
// If player is not an admin, check for ownership of src and dst
- if((getPlayerPrivs(player) & PRIV_SERVER) == 0)
+ if(!checkPriv(player->getName(), "server"))
{
std::string owner_from = getInventoryOwner(ma->from_inv);
if(owner_from != "" && owner_from != player->getName())
@@ -2565,13 +2562,13 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
setInventoryModified(da->from_inv);
// Disallow dropping items if not allowed to interact
- if((getPlayerPrivs(player) & PRIV_INTERACT) == 0)
+ if(!checkPriv(player->getName(), "interact"))
{
delete a;
return;
}
// If player is not an admin, check for ownership
- else if((getPlayerPrivs(player) & PRIV_SERVER) == 0)
+ else if(!checkPriv(player->getName(), "server"))
{
std::string owner_from = getInventoryOwner(da->from_inv);
if(owner_from != "" && owner_from != player->getName())
@@ -2600,7 +2597,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
// (ca->craft_inv.name == player->getName());
// Disallow crafting if not allowed to interact
- if((getPlayerPrivs(player) & PRIV_INTERACT) == 0)
+ if(!checkPriv(player->getName(), "interact"))
{
infostream<<"Cannot craft: "
<<"No interact privilege"<<std::endl;
@@ -2609,7 +2606,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
}
// If player is not an admin, check for ownership of inventory
- if((getPlayerPrivs(player) & PRIV_SERVER) == 0)
+ if(!checkPriv(player->getName(), "server"))
{
std::string owner_craft = getInventoryOwner(ca->craft_inv);
if(owner_craft != "" && owner_craft != player->getName())
@@ -2667,10 +2664,6 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
// Whether to send to other players
bool send_to_others = false;
- // Local player gets all privileges regardless of
- // what's set on their account.
- u64 privs = getPlayerPrivs(player);
-
// Parse commands
if(message[0] == L'/')
{
@@ -2688,8 +2681,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
paramstring,
this,
m_env,
- player,
- privs);
+ player);
std::wstring reply(processServerCommand(ctx));
send_to_sender = ctx->flags & SEND_TO_SENDER;
@@ -2705,16 +2697,13 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
}
else
{
- if(privs & PRIV_SHOUT)
- {
+ if(checkPriv(player->getName(), "shout")){
line += L"<";
line += name;
line += L"> ";
line += message;
send_to_others = true;
- }
- else
- {
+ } else {
line += L"Server: You are not allowed to shout";
send_to_sender = true;
}
@@ -2803,15 +2792,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
std::string playername = player->getName();
- if(m_authmanager.exists(playername) == false)
- {
- infostream<<"Server: playername not found in authmanager"<<std::endl;
- // Wrong old password supplied!!
- SendChatMessage(peer_id, L"playername not found in authmanager");
- return;
- }
-
- std::string checkpwd = m_authmanager.getPassword(playername);
+ std::string checkpwd;
+ scriptapi_get_auth(m_lua, playername, &checkpwd, NULL);
if(oldpwd != checkpwd)
{
@@ -2821,13 +2803,15 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
return;
}
- actionstream<<player->getName()<<" changes password"<<std::endl;
-
- m_authmanager.setPassword(playername, newpwd);
-
- infostream<<"Server: password change successful for "<<playername
- <<std::endl;
- SendChatMessage(peer_id, L"Password change successful");
+ bool success = scriptapi_set_password(m_lua, playername, newpwd);
+ if(success){
+ actionstream<<player->getName()<<" changes password"<<std::endl;
+ SendChatMessage(peer_id, L"Password change successful");
+ } else {
+ actionstream<<player->getName()<<" tries to change password but "
+ <<"it fails"<<std::endl;
+ SendChatMessage(peer_id, L"Password change failed or inavailable");
+ }
}
else if(command == TOSERVER_PLAYERITEM)
{
@@ -2970,11 +2954,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
/*
Make sure the player is allowed to do it
*/
- if((getPlayerPrivs(player) & PRIV_INTERACT) == 0)
+ if(!checkPriv(player->getName(), "interact"))
{
infostream<<"Ignoring interaction from player "<<player->getName()
- <<" because privileges are "<<getPlayerPrivs(player)
- <<std::endl;
+ <<" (no interact privilege)"<<std::endl;
return;
}
@@ -4277,54 +4260,17 @@ std::wstring Server::getStatusString()
return os.str();
}
-u64 Server::getPlayerAuthPrivs(const std::string &name)
-{
- try{
- return m_authmanager.getPrivs(name);
- }
- catch(AuthNotFoundException &e)
- {
- dstream<<"WARNING: Auth not found for "<<name<<std::endl;
- return 0;
- }
-}
-
-void Server::setPlayerAuthPrivs(const std::string &name, u64 privs)
-{
- try{
- return m_authmanager.setPrivs(name, privs);
- }
- catch(AuthNotFoundException &e)
- {
- dstream<<"WARNING: Auth not found for "<<name<<std::endl;
- }
-}
-
-u64 Server::getPlayerEffectivePrivs(const std::string &name)
+std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
{
- // Local player gets all privileges regardless of
- // what's set on their account.
- if(m_simple_singleplayer_mode)
- return PRIV_ALL;
- if(name == g_settings->get("name"))
- return PRIV_ALL;
- return getPlayerAuthPrivs(name);
+ std::set<std::string> privs;
+ scriptapi_get_auth(m_lua, name, NULL, &privs);
+ return privs;
}
-void Server::setPlayerPassword(const std::string &name, const std::wstring &password)
+bool Server::checkPriv(const std::string &name, const std::string &priv)
{
- // 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();
+ std::set<std::string> privs = getPlayerEffectivePrivs(name);
+ return (privs.count(priv) != 0);
}
// Saves g_settings to configpath given at initialization
@@ -4698,14 +4644,6 @@ void Server::handlePeerChanges()
}
}
-u64 Server::getPlayerPrivs(Player *player)
-{
- if(player==NULL)
- return 0;
- std::string playername = player->getName();
- return getPlayerEffectivePrivs(playername);
-}
-
void dedicated_server_loop(Server &server, bool &kill)
{
DSTACK(__FUNCTION_NAME);
diff --git a/src/server.h b/src/server.h
index d40c7c73e..4b04044e1 100644
--- a/src/server.h
+++ b/src/server.h
@@ -27,7 +27,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "porting.h"
#include "map.h"
#include "inventory.h"
-#include "auth.h"
#include "ban.h"
#include "gamedef.h"
#include "serialization.h" // For SER_FMT_VER_INVALID
@@ -500,15 +499,10 @@ public:
s32 playSound(const SimpleSoundSpec &spec, const ServerSoundParams &params);
void stopSound(s32 handle);
- // Thread-safe
- u64 getPlayerAuthPrivs(const std::string &name);
- void setPlayerAuthPrivs(const std::string &name, u64 privs);
- u64 getPlayerEffectivePrivs(const std::string &name);
+ // Envlock + conlock
+ std::set<std::string> getPlayerEffectivePrivs(const std::string &name);
+ bool checkPriv(const std::string &name, const std::string &priv);
- // 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();
@@ -670,8 +664,6 @@ private:
void handlePeerChange(PeerChange &c);
void handlePeerChanges();
- u64 getPlayerPrivs(Player *player);
-
/*
Variables
*/
@@ -710,9 +702,6 @@ private:
// Connected clients (behind the con mutex)
core::map<u16, RemoteClient*> m_clients;
- // User authentication
- AuthManager m_authmanager;
-
// Bann checking
BanManager m_banmanager;
diff --git a/src/servercommand.cpp b/src/servercommand.cpp
index 48ada56fe..64c43d4f5 100644
--- a/src/servercommand.cpp
+++ b/src/servercommand.cpp
@@ -38,98 +38,6 @@ void cmd_me(std::wostringstream &os,
ctx->flags |= SEND_TO_OTHERS | SEND_NO_PREFIX;
}
-void cmd_privs(std::wostringstream &os,
- ServerCommandContext *ctx)
-{
- if(ctx->parms.size() == 1)
- {
- // Show our own real privs, without any adjustments
- // made for admin status
- os<<L"-!- " + narrow_to_wide(privsToString(
- ctx->server->getPlayerAuthPrivs(ctx->player->getName())));
- return;
- }
-
- if((ctx->privs & PRIV_PRIVS) == 0)
- {
- os<<L"-!- You don't have permission to do that";
- return;
- }
-
- Player *tp = ctx->env->getPlayer(wide_to_narrow(ctx->parms[1]).c_str());
- if(tp == NULL)
- {
- os<<L"-!- No such player";
- return;
- }
-
- os<<L"-!- " + narrow_to_wide(privsToString(ctx->server->getPlayerAuthPrivs(tp->getName())));
-}
-
-void cmd_grantrevoke(std::wostringstream &os,
- ServerCommandContext *ctx)
-{
- if(ctx->parms.size() != 3)
- {
- os<<L"-!- Missing parameter";
- return;
- }
-
- if((ctx->privs & PRIV_PRIVS) == 0)
- {
- os<<L"-!- You don't have permission to do that";
- return;
- }
-
- u64 newprivs = stringToPrivs(wide_to_narrow(ctx->parms[2]));
- if(newprivs == PRIV_INVALID)
- {
- os<<L"-!- Invalid privileges specified";
- return;
- }
-
- Player *tp = ctx->env->getPlayer(wide_to_narrow(ctx->parms[1]).c_str());
- if(tp == NULL)
- {
- os<<L"-!- No such player";
- return;
- }
-
- std::string playername = wide_to_narrow(ctx->parms[1]);
- u64 privs = ctx->server->getPlayerAuthPrivs(playername);
-
- if(ctx->parms[0] == L"grant"){
- privs |= newprivs;
- actionstream<<ctx->player->getName()<<" grants "
- <<wide_to_narrow(ctx->parms[2])<<" to "
- <<playername<<std::endl;
-
- std::wstring msg;
- msg += narrow_to_wide(ctx->player->getName());
- msg += L" granted you the privilege \"";
- msg += ctx->parms[2];
- msg += L"\"";
- ctx->server->notifyPlayer(playername.c_str(), msg);
- } else {
- privs &= ~newprivs;
- actionstream<<ctx->player->getName()<<" revokes "
- <<wide_to_narrow(ctx->parms[2])<<" from "
- <<playername<<std::endl;
-
- std::wstring msg;
- msg += narrow_to_wide(ctx->player->getName());
- msg += L" revoked from you the privilege \"";
- msg += ctx->parms[2];
- msg += L"\"";
- ctx->server->notifyPlayer(playername.c_str(), msg);
- }
-
- ctx->server->setPlayerAuthPrivs(playername, privs);
-
- os<<L"-!- Privileges change to ";
- os<<narrow_to_wide(privsToString(privs));
-}
-
void cmd_time(std::wostringstream &os,
ServerCommandContext *ctx)
{
@@ -138,8 +46,8 @@ void cmd_time(std::wostringstream &os,
os<<L"-!- Missing parameter";
return;
}
-
- if((ctx->privs & PRIV_SETTIME) ==0)
+
+ if(!ctx->server->checkPriv(ctx->player->getName(), "settime"))
{
os<<L"-!- You don't have permission to do that";
return;
@@ -156,7 +64,7 @@ void cmd_time(std::wostringstream &os,
void cmd_shutdown(std::wostringstream &os,
ServerCommandContext *ctx)
{
- if((ctx->privs & PRIV_SERVER) ==0)
+ if(!ctx->server->checkPriv(ctx->player->getName(), "server"))
{
os<<L"-!- You don't have permission to do that";
return;
@@ -174,7 +82,7 @@ void cmd_shutdown(std::wostringstream &os,
void cmd_setting(std::wostringstream &os,
ServerCommandContext *ctx)
{
- if((ctx->privs & PRIV_SERVER) ==0)
+ if(!ctx->server->checkPriv(ctx->player->getName(), "server"))
{
os<<L"-!- You don't have permission to do that";
return;
@@ -198,7 +106,7 @@ void cmd_setting(std::wostringstream &os,
void cmd_teleport(std::wostringstream &os,
ServerCommandContext *ctx)
{
- if((ctx->privs & PRIV_TELEPORT) ==0)
+ if(!ctx->server->checkPriv(ctx->player->getName(), "teleport"))
{
os<<L"-!- You don't have permission to do that";
return;
@@ -241,7 +149,7 @@ void cmd_teleport(std::wostringstream &os,
void cmd_banunban(std::wostringstream &os, ServerCommandContext *ctx)
{
- if((ctx->privs & PRIV_BAN) == 0)
+ if(!ctx->server->checkPriv(ctx->player->getName(), "ban"))
{
os<<L"-!- You don't have permission to do that";
return;
@@ -288,62 +196,10 @@ 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);
-
- std::wostringstream msg;
- msg<<ctx->player->getName()<<L" changed your password";
- ctx->server->notifyPlayer(playername.c_str(), msg.str());
-
- os<<L"-!- Password change for "<<narrow_to_wide(playername)<<" successful";
-}
-
void cmd_clearobjects(std::wostringstream &os,
ServerCommandContext *ctx)
{
- if((ctx->privs & PRIV_SERVER) ==0)
+ if(!ctx->server->checkPriv(ctx->player->getName(), "server"))
{
os<<L"-!- You don't have permission to do that";
return;
@@ -378,10 +234,6 @@ std::wstring processServerCommand(ServerCommandContext *ctx)
if(ctx->parms[0] == L"status")
cmd_status(os, ctx);
- else if(ctx->parms[0] == L"privs")
- cmd_privs(os, ctx);
- else if(ctx->parms[0] == L"grant" || ctx->parms[0] == L"revoke")
- cmd_grantrevoke(os, ctx);
else if(ctx->parms[0] == L"time")
cmd_time(os, ctx);
else if(ctx->parms[0] == L"shutdown")
@@ -392,8 +244,6 @@ 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")
diff --git a/src/servercommand.h b/src/servercommand.h
index 648a57332..a3cf750da 100644
--- a/src/servercommand.h
+++ b/src/servercommand.h
@@ -36,9 +36,6 @@ struct ServerCommandContext
Server* server;
ServerEnvironment *env;
Player* player;
- // Effective privs for the player, which may be different to their
- // stored ones - e.g. if they are named in the config as an admin.
- u64 privs;
u32 flags;
ServerCommandContext(
@@ -46,10 +43,9 @@ struct ServerCommandContext
std::wstring paramstring,
Server* server,
ServerEnvironment *env,
- Player* player,
- u64 privs)
+ Player* player)
: parms(parms), paramstring(paramstring),
- server(server), env(env), player(player), privs(privs)
+ server(server), env(env), player(player)
{
}