…aaand add PREFIX to the freebsd makefile too
[voxelands-alt.git] / src / auth.c
blob4104db7ce1cf0f83fd435974d7d43ef6f20143d4
1 /************************************************************************
2 * auth.c
3 * voxelands - 3d voxel world sandbox game
4 * Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
18 ************************************************************************/
20 #include "common.h"
21 #include "auth.h"
23 #include "thread.h"
24 #include "nvp.h"
25 #include "file.h"
26 #include "path.h"
28 #include <stdlib.h>
29 #include <string.h>
31 static struct {
32 char* file;
33 mutex_t *mutex;
34 nvp_t *data;
35 char modified;
36 char* privstr[PRIV_COUNT];
37 } auth = {
38 NULL,
39 NULL,
40 NULL,
43 "build",
44 "teleport",
45 "settime",
46 "privs",
47 "server"
48 "shout",
49 "ban"
53 /* convert privs into a human readable csv string */
54 int auth_priv2str(uint64_t privs, char* buff, int size)
56 int i;
57 int r = 0;
58 int l;
59 int o = 0;
60 uint64_t p = 1;
62 if (!buff || !size)
63 return -1;
65 buff[0] = 0;
67 for (i=0; i<PRIV_COUNT; i++) {
68 p = (1<<i);
69 if ((privs&p) != p)
70 continue;
71 l = strlen(auth.privstr[i]);
72 if ((o+l+2) < size)
73 continue;
74 if (r) {
75 strcat(buff,",");
76 o++;
78 strcat(buff,auth.privstr[i]);
79 o += l;
80 r++;
83 return r;
86 /* convert a string to privs */
87 uint64_t auth_str2privs(char* str)
89 uint64_t privs = 0;
90 char buff[256];
91 char* b;
92 char* e;
93 int i;
95 if (!str)
96 return 0;
98 if (!strcpy(buff,str))
99 return 0;
100 b = buff;
101 while (1) {
102 e = strchr(b,',');
103 if (e)
104 *e = 0;
105 for (i=0; i<PRIV_COUNT; i++) {
106 if (strcmp(auth.privstr[i],b))
107 continue;
108 privs |= (1<<i);
109 break;
111 if (i == PRIV_COUNT)
112 return PRIV_INVALID;
113 if (e) {
114 b = e+1;
115 continue;
117 break;
120 return privs;
123 /* init auth system for the given file */
124 int auth_init(char* file)
126 char* path;
127 if (!auth.mutex) {
128 auth.mutex = mutex_create();
129 if (!auth.mutex)
130 return -1;
133 path = path_get("game",file,0,NULL,0);
134 if (!path)
135 return -1;
137 if (auth.file) {
138 if (!strcmp(auth.file,path)) {
139 free(path);
140 auth_load();
141 return 0;
143 if (auth.file)
144 free(auth.file);
145 auth.file = NULL;
147 nvp_free(&auth.data,1);
148 auth.data = NULL;
151 auth.file = path;
152 auth.modified = 0;
154 auth_load();
156 return 0;
159 /* free auth memory, reset auth struct */
160 void auth_exit()
162 if (auth.modified)
163 auth_save();
165 mutex_free(auth.mutex);
166 auth.mutex = NULL;
168 if (auth.file)
169 free(auth.file);
170 auth.file = NULL;
172 nvp_free(&auth.data,1);
173 auth.data = NULL;
175 auth.modified = 0;
178 /* load auth data from file */
179 void auth_load()
181 file_t *f;
182 char line[512];
183 char* n;
184 char* p;
185 char* s;
186 uint64_t privs;
187 authdata_t *d;
189 mutex_lock(auth.mutex);
191 f = file_load(NULL,auth.file);
192 if (!f)
193 return;
195 while (file_readline(f,line,512)) {
197 n = line;
198 p = strchr(n,':');
199 if (!p)
200 continue;
201 *p = 0;
202 p++;
203 s = strchr(p,':');
204 if (!s)
205 continue;
206 *s = 0;
207 s++;
209 privs = auth_str2privs(s);
211 d = malloc(sizeof(authdata_t));
212 if (!d)
213 continue;
215 strcpy(d->pwd,p);
216 d->privs = privs;
217 nvp_set(&auth.data,n,"",d);
220 mutex_unlock(auth.mutex);
222 file_free(f);
224 auth.modified = 0;
227 /* save auth data to file */
228 void auth_save()
230 file_t *f;
231 nvp_t *n;
232 char s[512];
234 if (!auth.modified)
235 return;
237 mutex_lock(auth.mutex);
239 f = file_create(NULL,auth.file);
240 if (!f)
241 return;
243 for (n=auth.data; n; n = n->next) {
244 if (!n->name || !n->name[0])
245 continue;
246 if (auth_priv2str(((authdata_t*)n->data)->privs,s,512) < 0)
247 s[0] = 0;
248 file_writef(f,"%s:%s:%s\n",n->name,((authdata_t*)n->data)->pwd,s);
251 file_flush(f);
253 mutex_unlock(auth.mutex);
255 file_free(f);
257 auth.modified = 0;
260 int auth_exists(char* name)
262 nvp_t *n;
263 if (!name)
264 return 0;
266 mutex_lock(auth.mutex);
268 n = nvp_get(&auth.data,name);
270 mutex_unlock(auth.mutex);
272 if (!n)
273 return 0;
274 return 1;
277 void auth_set(char* name, authdata_t data)
279 nvp_t *n;
280 if (!name)
281 return;
283 mutex_lock(auth.mutex);
285 n = nvp_get(&auth.data,name);
287 if (n) {
288 strcpy(((authdata_t*)n->data)->pwd,data.pwd);
289 ((authdata_t*)n->data)->privs = data.privs;
290 }else{
291 authdata_t *d = malloc(sizeof(authdata_t));
292 if (!d) {
293 mutex_unlock(auth.mutex);
294 return;
297 strcpy(d->pwd,data.pwd);
298 d->privs = data.privs;
299 nvp_set(&auth.data,name,"",d);
302 mutex_unlock(auth.mutex);
304 auth.modified = 1;
307 void auth_add(char* name)
309 authdata_t d;
310 d.pwd[0] = 0;
311 d.privs = PRIV_DEFAULT;
313 auth_set(name,d);
316 int auth_getpwd(char* name, char buff[64])
318 nvp_t *n;
320 buff[0] = 0;
322 if (!name)
323 return -1;
325 mutex_lock(auth.mutex);
327 n = nvp_get(&auth.data,name);
329 if (!n) {
330 mutex_unlock(auth.mutex);
331 return -1;
334 strcpy(buff,((authdata_t*)n->data)->pwd);
336 mutex_unlock(auth.mutex);
338 return 0;
341 void auth_setpwd(char* name, char* pwd)
343 nvp_t *n;
344 if (!name)
345 return;
347 mutex_lock(auth.mutex);
349 n = nvp_get(&auth.data,name);
351 if (n) {
352 strcpy(((authdata_t*)n->data)->pwd,pwd);
353 }else{
354 authdata_t *d = malloc(sizeof(authdata_t));
355 if (!d) {
356 mutex_unlock(auth.mutex);
357 return;
360 strcpy(d->pwd,pwd);
361 d->privs = PRIV_DEFAULT;
362 nvp_set(&auth.data,name,"",d);
365 mutex_unlock(auth.mutex);
367 auth.modified = 1;
370 uint64_t auth_getprivs(char* name)
372 nvp_t *n;
373 uint64_t privs = PRIV_INVALID;
375 if (!name)
376 return PRIV_INVALID;
378 mutex_lock(auth.mutex);
380 n = nvp_get(&auth.data,name);
382 if (!n) {
383 mutex_unlock(auth.mutex);
384 return PRIV_INVALID;
387 privs = ((authdata_t*)n->data)->privs;
389 mutex_unlock(auth.mutex);
391 return privs;
394 void auth_setprivs(char* name, uint64_t privs)
396 nvp_t *n;
397 if (!name)
398 return;
400 mutex_lock(auth.mutex);
402 n = nvp_get(&auth.data,name);
404 if (n) {
405 ((authdata_t*)n->data)->privs = privs;
406 }else{
407 authdata_t *d = malloc(sizeof(authdata_t));
408 if (!d) {
409 mutex_unlock(auth.mutex);
410 return;
413 d->pwd[0] = 0;
414 d->privs = privs;
415 nvp_set(&auth.data,name,"",d);
418 mutex_unlock(auth.mutex);
420 auth.modified = 1;