292ab0c0f7f7909d69e4ce670d9c45b1736320d4
[brisk.git] / web / Obj / auth.phh
1 <?php
2 /*
3  *  brisk - auth.phh
4  *
5  *  Copyright (C) 2006-2008 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
31 class Challenge {
32   var $login;
33   var $token;
34   var $ip;
35   var $tstamp;
36
37   function Challenge($login, $token, $ip, $tstamp)
38   {
39     $this->login  = $login;
40     $this->token  = $token;
41     $this->ip     = $ip;
42     $this->tstamp = $tstamp + CHAL_VALID_TIME;
43   }
44 }
45
46 class Challenges {
47   var $item;
48   var $item_n;
49   var $mod;
50   var $shm_sz;
51
52   var $garbage_timeout;
53
54
55   function Challenges()
56   {
57     $this->item = array();
58     $this->item_n = 0;
59     $this->garbage_timeout = 0;
60     $this->mod = FALSE;
61   }
62
63   function add($login, $token, $ip, $tstamp) 
64   {
65     $chal = null;
66
67     log_auth("xxx", sprintf("Challenges::add [%s]\n", $login));
68     // FIXME Checks here
69     if ($login == '') {
70       return ($G_false);
71     }
72
73       log_auth("xxx", "LOOPI item: ".$i." tstamp: ".$this->item[$i]->tstamp."  curtime: ".$curtime);
74
75     if (($chal = new Challenge($login, $token, $ip, $tstamp)) == null) {
76       return ($G_false);
77     }
78
79     $this->item[$this->item_n] = $chal;
80     $this->item_n++;
81
82     $this->mod = TRUE;
83
84     return ($chal);
85   }
86
87
88   /* remove all istances related to $login */
89
90   function rem($login)
91   {
92     $ismod  = FALSE;
93
94     for ($i = 0 ; $i < $this->item_n ; $i++) {
95       if ($this->item[$i]->login == $login) {
96         $ismod = TRUE;
97         for ($e = $i ; $e  < ($this->item_n - 1) ; $e++) {
98           $this->item[$e] = $this->item[$e + 1];
99         }
100         
101         $i--;
102         $this->item_n--;
103         unset($this->item[$this->item_n]);
104         $this->mod = TRUE;
105       }
106     }
107
108     return ($ismod);
109   }
110
111   function garbage_manager()
112   {
113     $curtime = time();
114
115     // FIXME remove set to 0
116     $this->garbage_timeout = 0;
117     if ($this->garbage_timeout > $curtime)
118       return (FALSE);
119
120     $ismod = FALSE;
121     
122     for ($i = 0 ; $i < $this->item_n ; $i++) {
123       log_auth("xxx", "LOOPI item: ".$i." tstamp: ".$this->item[$i]->tstamp."  curtime: ".$curtime);
124       if ($this->item[$i]->tstamp < $curtime) {
125         for ($e = $i ; $e  < ($this->item_n - 1) ; $e++) {
126           $this->item[$e] = $this->item[$e + 1];
127         }
128         
129         $i--;
130         $this->item_n--;
131         log_auth("xxx", "LOOPI unset: ".$this->item_n);
132         unset($this->item[$this->item_n]);
133         $ismod = TRUE;
134         $this->mod = TRUE;
135       }
136     }
137     
138     log_auth("xxx", "LOOPI AFTER: ".count($this->item)." _n:" .$this->item_n );
139     
140     $this->garbage_timeout = $curtime + CHAL_GARBAGE_TIMEOUT;
141     
142     return ($ismod);
143   }
144   
145   function ismod()
146   {
147     return ($this->mod);
148   }
149
150   // Static functions
151   function &init_data()
152   {
153     $chal =& new Challenges();
154     
155     $chal->mod = TRUE;
156
157     return $chal;
158   }
159
160   function &load_data() 
161   {
162     GLOBAL $G_false, $sess;
163     $doexit = FALSE;
164     do {
165       if (($tok = @ftok(FTOK_PATH."/challenges", "B")) == -1) {
166         log_main("ftok failed");
167         $doexit = TRUE;
168         break;
169       }
170     
171       if (($shm_sz = sharedmem_sz($tok)) == -1) {
172         log_main("shmop_open failed");
173       }
174         
175       if ($shm_sz == -1)
176         $shm_sz = CHAL_SHM_DIMS_MIN;
177
178       if ($shm = shm_attach($tok, $shm_sz)) {
179         $chals = @shm_get_var($shm, $tok);
180         
181         log_only("challenges ==  ".($chals == FALSE ?   "FALSE" : "TRUE")."  challenges ===  ".($chals === FALSE ? "FALSE" : "TRUE")."  challenges isset ".(isset($chals) ?   "TRUE" : "FALSE"));
182         
183         if ($chals == FALSE) {
184           log_only("INIT CHALLENGES DATA");
185           
186           $chals =& Challenges::init_data();
187           if (@shm_put_var($shm, $tok, $chals) == FALSE) {
188             log_only("PUT_VAR FALLITA ".strlen(serialize($chals)));
189             log_only(serialize($chals));
190           }
191         }
192         $chals->shm_sz = $shm_sz;
193         
194         shm_detach($shm);
195       }
196
197       $chals->garbage_manager();
198
199       $ret = &$chals;
200       return ($ret);
201     } while (0);
202     
203     if ($doexit)
204       exit();
205     
206     return ($G_false);
207   }
208   
209
210   function save_data(&$chals) 
211   {
212     $shm =   FALSE;
213     $oldmod = $chals->mod;
214
215     if (($tok = @ftok(FTOK_PATH."/challenges", "B")) == -1) 
216       return (FALSE);
217     
218     while ($chals->shm_sz < CHAL_SHM_DIMS_MAX) {
219       if (($shm = shm_attach($tok, $chals->shm_sz)) == FALSE)
220         break;
221       
222       if (isset($chals)) 
223         log_only("challenges count ".count($chals->item)."  _n: ".$chals->item_n);
224
225       $chals->mod = FALSE;
226       if (shm_put_var($shm, $tok, $chals) != FALSE) {
227         shm_detach($shm);
228         return (TRUE);
229       }
230       $chals->mod = $oldmod;
231
232       if (shm_remove($shm) === FALSE) {
233         log_only("REMOVE FALLITA");
234         break;
235       }
236       shm_detach($shm);
237       $chals->shm_sz += CHAL_SHM_DIMS_DLT;
238     } 
239
240     if ($shm)
241       shm_detach($shm);
242     
243     return (FALSE);
244   }
245
246   function lock_data()
247   {
248     if (($tok = @ftok(FTOK_PATH."/challenges", "B")) == -1) {
249       echo "FTOK FAILED";
250       exit;
251     }
252     // echo "FTOK ".$tok."<br>";
253     if (($res = sem_get($tok)) == FALSE) {
254       echo "SEM_GET FAILED";
255       exit;
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
280   function LoginDBItem($login, $pass)
281   {
282     $this->login = $login;
283     $this->pass  = $pass;
284   }
285 }
286
287 class LoginDB {
288   var $item;
289   var $item_n;
290
291   
292   function LoginDB()
293   {
294     GLOBAL $DOCUMENT_ROOT;
295     log_main("LoginDB create:start");
296
297     if (file_exists("$DOCUMENT_ROOT/Etc/brisk_auth.conf.pho")) {
298       require("$DOCUMENT_ROOT/Etc/brisk_auth.conf.pho");
299     }
300     else {
301       $this->item = array( new LoginDBItem("uno", md5("one")),
302                            new LoginDBItem("due", md5("two")),
303                            new LoginDBItem("a_b", md5("abb")),
304                            new LoginDBItem("tre", md5("three")) );
305     }
306     $this->item_n = count($this->item);
307     log_main("LoginDB create:end");
308   }
309
310   function login_exists($login)
311   {
312     log_main("login_verify");
313     
314     /* check the existence of the nick in the LoginDB */
315     for ($i = 0 ; $i < $this->item_n ; $i++) {
316       if (strcasecmp($this->item[$i]->login, $login) == 0) {
317         log_main("login[".$i."]: ".$this->item[$i]->login);
318         return (TRUE);
319       }
320     }
321     return (FALSE);
322   }
323
324   function login_verify($login, $pass)
325   {
326     $ret = FALSE;
327
328     log_main("login_verify");
329         
330     /* check the existence of the nick in the LoginDB */
331     for ($i = 0 ; $i < $this->item_n ; $i++) {
332       if (strcasecmp($this->item[$i]->login, $login) == 0) {
333         log_main("login[".$i."]: ".$this->item[$i]->login);
334
335         /* if it exists check for a valid challenge */
336         if (($a_sem = Challenges::lock_data()) != FALSE) { 
337           
338           if (($chals = &Challenges::load_data()) != FALSE) {
339             for ($e = 0 ; $e < $chals->item_n ; $e++) {
340               
341               log_main("challenge[".$i."]: ".$chals->item[$e]->login);
342               if (strcmp($login, $chals->item[$e]->login) == 0) {
343                 log_main("login_verify [".$pass."] with [".md5($chals->item[$e]->token.$this->item[$i]->pass)."]");
344                   
345                 if (strcmp($pass , md5($chals->item[$e]->token.$this->item[$i]->pass)) == 0) {
346                   log_main("login_verify SUCCESS for ".$login);
347    
348                   $chals->rem($login);
349                   $ret = TRUE;
350                   break;
351                 }
352               }
353             } // end for ($e = 0 ...
354           }
355
356           if ($chals->ismod()) {
357             Challenges::save_data(&$chals);
358           }
359           
360           Challenges::unlock_data($a_sem);
361         }
362         break;
363       } //  if (strcasecmp($this->item[$i]->login, ...
364     }
365
366     return ($ret);
367   }
368 } // End class LoginDB
369
370
371 ?>