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