Fix processing of the default_password setting. It is now actually used as the plaint...
[oweals/minetest.git] / src / auth.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "auth.h"
21 #include <fstream>
22 #include <jmutexautolock.h>
23 //#include "main.h" // for g_settings
24 #include <sstream>
25 #include "strfnd.h"
26 #include "debug.h"
27
28 std::set<std::string> privsToSet(u64 privs)
29 {
30         std::set<std::string> s;
31         if(privs & PRIV_BUILD)
32                 s.insert("build");
33         if(privs & PRIV_TELEPORT)
34                 s.insert("teleport");
35         if(privs & PRIV_SETTIME)
36                 s.insert("settime");
37         if(privs & PRIV_PRIVS)
38                 s.insert("privs");
39         if(privs & PRIV_SHOUT)
40                 s.insert("shout");
41         if(privs & PRIV_BAN)
42                 s.insert("ban");
43         if(privs & PRIV_GIVE)
44                 s.insert("give");
45         if(privs & PRIV_PASSWORD)
46                 s.insert("password");
47         return s;
48 }
49
50 // Convert a privileges value into a human-readable string,
51 // with each component separated by a comma.
52 std::string privsToString(u64 privs)
53 {
54         std::ostringstream os(std::ios_base::binary);
55         if(privs & PRIV_BUILD)
56                 os<<"build,";
57         if(privs & PRIV_TELEPORT)
58                 os<<"teleport,";
59         if(privs & PRIV_SETTIME)
60                 os<<"settime,";
61         if(privs & PRIV_PRIVS)
62                 os<<"privs,";
63         if(privs & PRIV_SHOUT)
64                 os<<"shout,";
65         if(privs & PRIV_BAN)
66                 os<<"ban,";
67         if(privs & PRIV_GIVE)
68                 os<<"give,";
69         if(privs & PRIV_PASSWORD)
70                 os<<"password,";
71         if(os.tellp())
72         {
73                 // Drop the trailing comma. (Why on earth can't
74                 // you truncate a C++ stream anyway???)
75                 std::string tmp = os.str();
76                 return tmp.substr(0, tmp.length() -1);
77         }
78         return os.str();
79 }
80
81 // Converts a comma-seperated list of privilege values into a
82 // privileges value. The reverse of privsToString(). Returns
83 // PRIV_INVALID if there is anything wrong with the input.
84 u64 stringToPrivs(std::string str)
85 {
86         u64 privs=0;
87         Strfnd f(str);
88         while(f.atend() == false)
89         {
90                 std::string s = trim(f.next(","));
91                 if(s == "build")
92                         privs |= PRIV_BUILD;
93                 else if(s == "teleport")
94                         privs |= PRIV_TELEPORT;
95                 else if(s == "settime")
96                         privs |= PRIV_SETTIME;
97                 else if(s == "privs")
98                         privs |= PRIV_PRIVS;
99                 else if(s == "shout")
100                         privs |= PRIV_SHOUT;
101                 else if(s == "ban")
102                         privs |= PRIV_BAN;
103                 else if(s == "give")
104                         privs |= PRIV_GIVE;
105                 else if(s == "password")
106                         privs |= PRIV_PASSWORD;
107                 else
108                         return PRIV_INVALID;
109         }
110         return privs;
111 }
112
113 AuthManager::AuthManager(const std::string &authfilepath):
114                 m_authfilepath(authfilepath),
115                 m_modified(false)
116 {
117         m_mutex.Init();
118         
119         try{
120                 load();
121         }
122         catch(SerializationError &e)
123         {
124                 dstream<<"WARNING: AuthManager: creating "
125                                 <<m_authfilepath<<std::endl;
126         }
127 }
128
129 AuthManager::~AuthManager()
130 {
131         save();
132 }
133
134 void AuthManager::load()
135 {
136         JMutexAutoLock lock(m_mutex);
137         
138         dstream<<"AuthManager: loading from "<<m_authfilepath<<std::endl;
139         std::ifstream is(m_authfilepath.c_str(), std::ios::binary);
140         if(is.good() == false)
141         {
142                 dstream<<"AuthManager: failed loading from "<<m_authfilepath<<std::endl;
143                 throw SerializationError("AuthManager::load(): Couldn't open file");
144         }
145
146         for(;;)
147         {
148                 if(is.eof() || is.good() == false)
149                         break;
150
151                 // Read a line
152                 std::string line;
153                 std::getline(is, line, '\n');
154
155                 std::istringstream iss(line);
156                 
157                 // Read name
158                 std::string name;
159                 std::getline(iss, name, ':');
160
161                 // Read password
162                 std::string pwd;
163                 std::getline(iss, pwd, ':');
164
165                 // Read privileges
166                 std::string stringprivs;
167                 std::getline(iss, stringprivs, ':');
168                 u64 privs = stringToPrivs(stringprivs);
169                 
170                 // Store it
171                 AuthData ad;
172                 ad.pwd = pwd;
173                 ad.privs = privs;
174                 m_authdata[name] = ad;
175         }
176
177         m_modified = false;
178 }
179
180 void AuthManager::save()
181 {
182         JMutexAutoLock lock(m_mutex);
183         
184         dstream<<"AuthManager: saving to "<<m_authfilepath<<std::endl;
185         std::ofstream os(m_authfilepath.c_str(), std::ios::binary);
186         if(os.good() == false)
187         {
188                 dstream<<"AuthManager: failed saving to "<<m_authfilepath<<std::endl;
189                 throw SerializationError("AuthManager::save(): Couldn't open file");
190         }
191         
192         for(core::map<std::string, AuthData>::Iterator
193                         i = m_authdata.getIterator();
194                         i.atEnd()==false; i++)
195         {
196                 std::string name = i.getNode()->getKey();
197                 if(name == "")
198                         continue;
199                 AuthData ad = i.getNode()->getValue();
200                 os<<name<<":"<<ad.pwd<<":"<<privsToString(ad.privs)<<"\n";
201         }
202
203         m_modified = false;
204 }
205
206 bool AuthManager::exists(const std::string &username)
207 {
208         JMutexAutoLock lock(m_mutex);
209         
210         core::map<std::string, AuthData>::Node *n;
211         n = m_authdata.find(username);
212         if(n == NULL)
213                 return false;
214         return true;
215 }
216
217 void AuthManager::set(const std::string &username, AuthData ad)
218 {
219         JMutexAutoLock lock(m_mutex);
220         
221         m_authdata[username] = ad;
222
223         m_modified = true;
224 }
225
226 void AuthManager::add(const std::string &username)
227 {
228         JMutexAutoLock lock(m_mutex);
229         
230         m_authdata[username] = AuthData();
231
232         m_modified = true;
233 }
234
235 std::string AuthManager::getPassword(const std::string &username)
236 {
237         JMutexAutoLock lock(m_mutex);
238         
239         core::map<std::string, AuthData>::Node *n;
240         n = m_authdata.find(username);
241         if(n == NULL)
242                 throw AuthNotFoundException("");
243         
244         return n->getValue().pwd;
245 }
246
247 void AuthManager::setPassword(const std::string &username,
248                 const std::string &password)
249 {
250         JMutexAutoLock lock(m_mutex);
251         
252         core::map<std::string, AuthData>::Node *n;
253         n = m_authdata.find(username);
254         if(n == NULL)
255                 throw AuthNotFoundException("");
256         
257         AuthData ad = n->getValue();
258         ad.pwd = password;
259         n->setValue(ad);
260
261         m_modified = true;
262 }
263
264 u64 AuthManager::getPrivs(const std::string &username)
265 {
266         JMutexAutoLock lock(m_mutex);
267         
268         core::map<std::string, AuthData>::Node *n;
269         n = m_authdata.find(username);
270         if(n == NULL)
271                 throw AuthNotFoundException("");
272         
273         return n->getValue().privs;
274 }
275
276 void AuthManager::setPrivs(const std::string &username, u64 privs)
277 {
278         JMutexAutoLock lock(m_mutex);
279         
280         core::map<std::string, AuthData>::Node *n;
281         n = m_authdata.find(username);
282         if(n == NULL)
283                 throw AuthNotFoundException("");
284         
285         AuthData ad = n->getValue();
286         ad.privs = privs;
287         n->setValue(ad);
288
289         m_modified = true;
290 }
291
292 bool AuthManager::isModified()
293 {
294         JMutexAutoLock lock(m_mutex);
295         return m_modified;
296 }
297
298