Tune mapgen
[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 "log.h"
27
28 std::set<std::string> privsToSet(u64 privs)
29 {
30         std::set<std::string> s;
31         if(privs & PRIV_INTERACT)
32                 s.insert("interact");
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_INTERACT)
56                 os<<"interact,";
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_INTERACT;
93                 else if(s == "interact")
94                         privs |= PRIV_INTERACT;
95                 else if(s == "teleport")
96                         privs |= PRIV_TELEPORT;
97                 else if(s == "settime")
98                         privs |= PRIV_SETTIME;
99                 else if(s == "privs")
100                         privs |= PRIV_PRIVS;
101                 else if(s == "shout")
102                         privs |= PRIV_SHOUT;
103                 else if(s == "ban")
104                         privs |= PRIV_BAN;
105                 else if(s == "give")
106                         privs |= PRIV_GIVE;
107                 else if(s == "password")
108                         privs |= PRIV_PASSWORD;
109                 else
110                         return PRIV_INVALID;
111         }
112         return privs;
113 }
114
115 AuthManager::AuthManager(const std::string &authfilepath):
116                 m_authfilepath(authfilepath),
117                 m_modified(false)
118 {
119         m_mutex.Init();
120         
121         try{
122                 load();
123         }
124         catch(SerializationError &e)
125         {
126                 infostream<<"WARNING: AuthManager: creating "
127                                 <<m_authfilepath<<std::endl;
128         }
129 }
130
131 AuthManager::~AuthManager()
132 {
133         save();
134 }
135
136 void AuthManager::load()
137 {
138         JMutexAutoLock lock(m_mutex);
139         
140         infostream<<"AuthManager: loading from "<<m_authfilepath<<std::endl;
141         std::ifstream is(m_authfilepath.c_str(), std::ios::binary);
142         if(is.good() == false)
143         {
144                 infostream<<"AuthManager: failed loading from "<<m_authfilepath<<std::endl;
145                 throw SerializationError("AuthManager::load(): Couldn't open file");
146         }
147
148         for(;;)
149         {
150                 if(is.eof() || is.good() == false)
151                         break;
152
153                 // Read a line
154                 std::string line;
155                 std::getline(is, line, '\n');
156
157                 std::istringstream iss(line);
158                 
159                 // Read name
160                 std::string name;
161                 std::getline(iss, name, ':');
162
163                 // Read password
164                 std::string pwd;
165                 std::getline(iss, pwd, ':');
166
167                 // Read privileges
168                 std::string stringprivs;
169                 std::getline(iss, stringprivs, ':');
170                 u64 privs = stringToPrivs(stringprivs);
171                 
172                 // Store it
173                 AuthData ad;
174                 ad.pwd = pwd;
175                 ad.privs = privs;
176                 m_authdata[name] = ad;
177         }
178
179         m_modified = false;
180 }
181
182 void AuthManager::save()
183 {
184         JMutexAutoLock lock(m_mutex);
185         
186         infostream<<"AuthManager: saving to "<<m_authfilepath<<std::endl;
187         std::ofstream os(m_authfilepath.c_str(), std::ios::binary);
188         if(os.good() == false)
189         {
190                 infostream<<"AuthManager: failed saving to "<<m_authfilepath<<std::endl;
191                 throw SerializationError("AuthManager::save(): Couldn't open file");
192         }
193         
194         for(core::map<std::string, AuthData>::Iterator
195                         i = m_authdata.getIterator();
196                         i.atEnd()==false; i++)
197         {
198                 std::string name = i.getNode()->getKey();
199                 if(name == "")
200                         continue;
201                 AuthData ad = i.getNode()->getValue();
202                 os<<name<<":"<<ad.pwd<<":"<<privsToString(ad.privs)<<"\n";
203         }
204
205         m_modified = false;
206 }
207
208 bool AuthManager::exists(const std::string &username)
209 {
210         JMutexAutoLock lock(m_mutex);
211         
212         core::map<std::string, AuthData>::Node *n;
213         n = m_authdata.find(username);
214         if(n == NULL)
215                 return false;
216         return true;
217 }
218
219 void AuthManager::set(const std::string &username, AuthData ad)
220 {
221         JMutexAutoLock lock(m_mutex);
222         
223         m_authdata[username] = ad;
224
225         m_modified = true;
226 }
227
228 void AuthManager::add(const std::string &username)
229 {
230         JMutexAutoLock lock(m_mutex);
231         
232         m_authdata[username] = AuthData();
233
234         m_modified = true;
235 }
236
237 std::string AuthManager::getPassword(const std::string &username)
238 {
239         JMutexAutoLock lock(m_mutex);
240         
241         core::map<std::string, AuthData>::Node *n;
242         n = m_authdata.find(username);
243         if(n == NULL)
244                 throw AuthNotFoundException("");
245         
246         return n->getValue().pwd;
247 }
248
249 void AuthManager::setPassword(const std::string &username,
250                 const std::string &password)
251 {
252         JMutexAutoLock lock(m_mutex);
253         
254         core::map<std::string, AuthData>::Node *n;
255         n = m_authdata.find(username);
256         if(n == NULL)
257                 throw AuthNotFoundException("");
258         
259         AuthData ad = n->getValue();
260         ad.pwd = password;
261         n->setValue(ad);
262
263         m_modified = true;
264 }
265
266 u64 AuthManager::getPrivs(const std::string &username)
267 {
268         JMutexAutoLock lock(m_mutex);
269         
270         core::map<std::string, AuthData>::Node *n;
271         n = m_authdata.find(username);
272         if(n == NULL)
273                 throw AuthNotFoundException("");
274         
275         return n->getValue().privs;
276 }
277
278 void AuthManager::setPrivs(const std::string &username, u64 privs)
279 {
280         JMutexAutoLock lock(m_mutex);
281         
282         core::map<std::string, AuthData>::Node *n;
283         n = m_authdata.find(username);
284         if(n == NULL)
285                 throw AuthNotFoundException("");
286         
287         AuthData ad = n->getValue();
288         ad.privs = privs;
289         n->setValue(ad);
290
291         m_modified = true;
292 }
293
294 bool AuthManager::isModified()
295 {
296         JMutexAutoLock lock(m_mutex);
297         return m_modified;
298 }
299
300