copyright updated and mop user status added
[brisk.git] / web / Obj / auth.phh
1 <?php
2 /*
3  *  brisk - auth.phh
4  *
5  *  Copyright (C) 2006-2011 Matteo Nastasi
6  *                          mailto: nastasi@alternativeoutput.it 
7  *                                  matteo.nastasi@milug.org
8  *                          web: http://www.alternativeoutput.it
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABLILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * General Public License for more details. You should have received a
19  * copy of the GNU General Public License along with this program; if
20  * not, write to the Free Software Foundation, Inc, 59 Temple Place -
21  * Suite 330, Boston, MA 02111-1307, USA.
22  *
23  */
24
25 define(CHAL_SHM_DIMS_MIN, 16384);
26 define(CHAL_SHM_DIMS_MAX, 65536);
27 define(CHAL_SHM_DIMS_DLT, 16384);
28 define(CHAL_VALID_TIME,      15);
29 define(CHAL_GARBAGE_TIMEOUT,  5);
30 define(BRISK_AUTH_CONF,   "brisk_auth.conf.pho");
31
32
33 class Challenge {
34   var $login;
35   var $token;
36   var $ip;
37   var $tstamp;
38
39   function Challenge($login, $token, $ip, $tstamp)
40   {
41     $this->login  = $login;
42     $this->token  = $token;
43     $this->ip     = $ip;
44     $this->tstamp = $tstamp + CHAL_VALID_TIME;
45   }
46 }
47
48 class Challenges {
49   var $item;
50   var $item_n;
51   var $mod;
52   var $shm_sz;
53
54   var $garbage_timeout;
55
56
57   function Challenges()
58   {
59     $this->item = array();
60     $this->item_n = 0;
61     $this->garbage_timeout = 0;
62     $this->mod = FALSE;
63   }
64
65   function add($login, $token, $ip, $tstamp) 
66   {
67     $chal = null;
68
69     log_auth("xxx", sprintf("Challenges::add [%s]\n", $login));
70     // FIXME Checks here
71     if ($login == '') {
72       return ($G_false);
73     }
74
75     // log_auth("xxx", "LOOPI tstamp: ".$this->item[$i]->tstamp."  curtime: ".$curtime);
76
77     if (($chal = new Challenge($login, $token, $ip, $tstamp)) == null) {
78       return ($G_false);
79     }
80
81     $this->item[$this->item_n] = $chal;
82     $this->item_n++;
83
84     $this->mod = TRUE;
85
86     return ($chal);
87   }
88
89
90   /* remove all istances related to $login */
91
92   function rem($login)
93   {
94     $ismod  = FALSE;
95
96     for ($i = 0 ; $i < $this->item_n ; $i++) {
97       if ($this->item[$i]->login == $login) {
98         $ismod = TRUE;
99         for ($e = $i ; $e  < ($this->item_n - 1) ; $e++) {
100           $this->item[$e] = $this->item[$e + 1];
101         }
102         
103         $i--;
104         $this->item_n--;
105         unset($this->item[$this->item_n]);
106         $this->mod = TRUE;
107       }
108     }
109
110     return ($ismod);
111   }
112
113   function garbage_manager()
114   {
115     $curtime = time();
116
117     // FIXME remove set to 0
118     $this->garbage_timeout = 0;
119     if ($this->garbage_timeout > $curtime)
120       return (FALSE);
121
122     $ismod = FALSE;
123     
124     for ($i = 0 ; $i < $this->item_n ; $i++) {
125       log_auth("xxx", "LOOPI item: ".$i." tstamp: ".$this->item[$i]->tstamp."  curtime: ".$curtime);
126       if ($this->item[$i]->tstamp < $curtime) {
127         for ($e = $i ; $e  < ($this->item_n - 1) ; $e++) {
128           $this->item[$e] = $this->item[$e + 1];
129         }
130         
131         $i--;
132         $this->item_n--;
133         log_auth("xxx", "LOOPI unset: ".$this->item_n);
134         unset($this->item[$this->item_n]);
135         $ismod = TRUE;
136         $this->mod = TRUE;
137       }
138     }
139     
140     log_auth("xxx", "LOOPI AFTER: ".count($this->item)." _n:" .$this->item_n );
141     
142     $this->garbage_timeout = $curtime + CHAL_GARBAGE_TIMEOUT;
143     
144     return ($ismod);
145   }
146   
147   function ismod()
148   {
149     return ($this->mod);
150   }
151
152   // Static functions
153   function &init_data()
154   {
155     $chal =& new Challenges();
156     
157     $chal->mod = TRUE;
158
159     return $chal;
160   }
161
162   function &load_data() 
163   {
164     GLOBAL $G_false, $sess;
165     $doexit = FALSE;
166     do {
167       if (($tok = @ftok(FTOK_PATH."/challenges", "B")) == -1) {
168         log_main("ftok failed");
169         $doexit = TRUE;
170         break;
171       }
172     
173       if (($shm_sz = sharedmem_sz($tok)) == -1) {
174         log_main("shmop_open failed");
175       }
176         
177       if ($shm_sz == -1)
178         $shm_sz = CHAL_SHM_DIMS_MIN;
179
180       if ($shm = shm_attach($tok, $shm_sz)) {
181         $chals = @shm_get_var($shm, $tok);
182         
183         log_only("challenges ==  ".($chals == FALSE ?   "FALSE" : "TRUE")."  challenges ===  ".($chals === FALSE ? "FALSE" : "TRUE")."  challenges isset ".(isset($chals) ?   "TRUE" : "FALSE"));
184         
185         if ($chals == FALSE) {
186           log_only("INIT CHALLENGES DATA");
187           
188           $chals =& Challenges::init_data();
189           if (@shm_put_var($shm, $tok, $chals) == FALSE) {
190             log_only("PUT_VAR FALLITA ".strlen(serialize($chals)));
191             log_only(serialize($chals));
192           }
193         }
194         $chals->shm_sz = $shm_sz;
195         
196         shm_detach($shm);
197       }
198
199       $chals->garbage_manager();
200
201       $ret = &$chals;
202       return ($ret);
203     } while (0);
204     
205     if ($doexit)
206       exit();
207     
208     return ($G_false);
209   }
210   
211
212   function save_data(&$chals) 
213   {
214     $shm =   FALSE;
215     $oldmod = $chals->mod;
216
217     if (($tok = @ftok(FTOK_PATH."/challenges", "B")) == -1) 
218       return (FALSE);
219     
220     while ($chals->shm_sz < CHAL_SHM_DIMS_MAX) {
221       if (($shm = shm_attach($tok, $chals->shm_sz)) == FALSE)
222         break;
223       
224       if (isset($chals)) 
225         log_only("challenges count ".count($chals->item)."  _n: ".$chals->item_n);
226
227       $chals->mod = FALSE;
228       if (shm_put_var($shm, $tok, $chals) != FALSE) {
229         shm_detach($shm);
230         return (TRUE);
231       }
232       $chals->mod = $oldmod;
233
234       if (shm_remove($shm) === FALSE) {
235         log_only("REMOVE FALLITA");
236         break;
237       }
238       shm_detach($shm);
239       $chals->shm_sz += CHAL_SHM_DIMS_DLT;
240     } 
241
242     if ($shm)
243       shm_detach($shm);
244     
245     return (FALSE);
246   }
247
248   function lock_data()
249   {
250     if (($tok = @ftok(FTOK_PATH."/challenges", "B")) == -1) {
251       return (FALSE);
252     }
253     // echo "FTOK ".$tok."<br>";
254     if (($res = sem_get($tok)) == FALSE) {
255       return (FALSE);
256     }
257     if (sem_acquire($res)) {   
258       log_lock("LOCK challenges");
259       return ($res);
260     }
261     else
262       return (FALSE);
263   }
264   
265   function unlock_data($res)
266   {
267     GLOBAL $sess; 
268     
269     log_lock("UNLOCK challenges");
270
271     return (sem_release($res));
272   }
273 } // End CLASS Challenges
274
275
276 class LoginDBItem {
277   var $login;
278   var $pass;
279   var $email;
280   var $type;
281
282   function LoginDBItem($login, $pass, $email, $type)
283   {
284     $this->login = $login;
285     $this->pass  = $pass;
286     $this->email = $email;
287     $this->type  = $type;
288   }
289
290   function loginget()
291   {
292       return $this->login;
293   }
294
295   function passget()
296   {
297       return $this->pass;
298   }
299
300   function emailget()
301   {
302       return $this->email;
303   }
304
305   function typeget()
306   {
307       return $this->type;
308   }
309
310 }
311
312 class LoginDB {
313   var $item;
314   var $item_n;
315
316   
317   function LoginDB()
318   {
319     GLOBAL $DOCUMENT_ROOT;
320     log_main("LoginDB create:start");
321
322     if (file_exists("$DOCUMENT_ROOT/Etc/".BRISK_AUTH_CONF)) {
323       require("$DOCUMENT_ROOT/Etc/".BRISK_AUTH_CONF);
324     }
325     else {
326       $this->item = array( new LoginDBItem("uno", md5("one"),   "pippo@pluto.com"),
327                            new LoginDBItem("due", md5("two"),   "pippo@pluto.com"),
328                            new LoginDBItem("a_b", md5("abb"),   "pippo@pluto.com"),
329                            new LoginDBItem("tre", md5("three"), "pippo@pluto.com") );
330     }
331     $this->item_n = count($this->item);
332     log_main("LoginDB create:end");
333   }
334
335   function count()
336   {
337     return ($this->item_n);
338   }
339
340   function login_exists($login)
341   {
342     log_main("login_exists: ".$login);
343     
344     /* check the existence of the nick in the LoginDB */
345     for ($i = 0 ; $i < $this->item_n ; $i++) {
346       if (strcasecmp($this->item[$i]->login, $login) == 0) {
347         log_main("login[".$i."]: ".$this->item[$i]->login);
348         return (TRUE);
349       }
350     }
351     return (FALSE);
352   }
353
354   function getlogin_byidx($idx)
355   {
356     if ($idx >= $this->item_n)
357       return FALSE;
358     return ($this->item[$idx]->login);
359   }
360
361   function &getitem_bylogin($login, &$id)
362   {
363     GLOBAL $G_false;
364
365     log_main("login_exists: ".$login);
366     
367     /* check the existence of the nick in the LoginDB */
368     for ($i = 0 ; $i < $this->item_n ; $i++) {
369       if (strcasecmp($this->item[$i]->login, $login) == 0) {
370         log_main("login[".$i."]: ".$this->item[$i]->login);
371         $ret = &$this->item[$i];
372         $id = $i;
373         return ($ret);
374       }
375     }
376     $id = -1;
377     return ($G_false);
378   }
379
380   function getmail($login)
381   {
382     log_main("getmail");
383     
384     /* check the existence of the nick in the LoginDB */
385     for ($i = 0 ; $i < $this->item_n ; $i++) {
386       if (strcasecmp($this->item[$i]->login, $login) == 0) {
387         log_main("login[".$i."]: ".$this->item[$i]->login);
388         return ($this->item[$i]->email);
389       }
390     }
391     return (FALSE);
392   }
393
394   function gettype($login)
395   {
396     log_main("getmail");
397     
398     /* check the existence of the nick in the LoginDB */
399     for ($i = 0 ; $i < $this->item_n ; $i++) {
400       if (strcasecmp($this->item[$i]->login, $login) == 0) {
401         log_main("login[".$i."]: ".$this->item[$i]->login);
402         return ($this->item[$i]->type);
403       }
404     }
405     return (FALSE);
406   }
407
408   function &login_verify($login, $pass)
409   {
410     GLOBAL $G_false;
411
412     $ret = &$G_false;
413
414     log_main("login_verify: ".$login);
415         
416     /* check the existence of the nick in the LoginDB */
417     for ($i = 0 ; $i < $this->item_n ; $i++) {
418       log_main("login_verify: LOOP");
419       if (strcasecmp($this->item[$i]->login, $login) == 0) {
420         log_main("login[".$i."]: ".$this->item[$i]->login);
421
422         /* if it exists check for a valid challenge */
423         if (($a_sem = Challenges::lock_data()) != FALSE) { 
424           
425           if (($chals = &Challenges::load_data()) != FALSE) {
426             for ($e = 0 ; $e < $chals->item_n ; $e++) {
427               
428               log_main("challenge[".$i."]: ".$chals->item[$e]->login);
429               if (strcmp($login, $chals->item[$e]->login) == 0) {
430                 log_main("login_verify [".$pass."] with [".md5($chals->item[$e]->token.$this->item[$i]->pass)."]");
431                   
432                 if (strcmp($pass , md5($chals->item[$e]->token.$this->item[$i]->pass)) == 0) {
433                   log_main("login_verify SUCCESS for ".$login);
434    
435                   $chals->rem($login);
436                   $ret = &$this->item[$i];
437                   break;
438                 }
439               }
440             } // end for ($e = 0 ...
441           }
442
443           if ($chals->ismod()) {
444             Challenges::save_data(&$chals);
445           }
446           
447           Challenges::unlock_data($a_sem);
448         }
449         break;
450       } //  if (strcasecmp($this->item[$i]->login, ...
451     }
452
453     return ($ret);
454   }
455 } // End class LoginDB
456
457
458 ?>