is_exclusive argument added to all lock_data() functions, (exclusivity is always...
[brisk.git] / web / Obj / hardban.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(HBAN_SHM_DIMS_MIN, 16384);
26 define(HBAN_SHM_DIMS_MAX, 65536);
27 define(HBAN_SHM_DIMS_DLT, 16384);
28 define(HBAN_VALID_TIME,      15);
29 define(HBAN_GARBAGE_TIMEOUT,  5);
30
31 class Hardban {
32   var $login;
33   var $ip;
34   var $session;
35   var $timeout;
36
37   function Hardban($login, $ip, $session, $timeout)
38   {
39     $this->login  = $login;
40     $this->ip     = $ip;
41     $this->session  = $session;
42     $this->timeout = $timeout;
43   }
44 }
45
46 class Hardbans {
47     static $delta_t;
48
49   var $item;
50   var $item_n;
51   var $mod;
52   var $shm_sz;
53
54   var $garbage_timeout;
55
56
57   function Hardbans()
58   {
59     $this->item = array();
60     $this->item_n = 0;
61     $this->garbage_timeout = 0;
62     $this->mod = FALSE;
63   }
64
65   function add_item($login, $ip, $session, $timeout)
66   {
67     $chal = null;
68
69     log_auth("xxx", sprintf("Hardbans::add [%s]\n", $login));
70
71     if (($chal = new Hardban($login, $ip, $session, $timeout)) == FALSE) {
72       return (FALSE);
73     }
74
75     $this->item[$this->item_n] = $chal;
76     $this->item_n++;
77
78     $this->mod = TRUE;
79
80     return ($chal);
81   }
82
83
84   /* remove all istances related to $login */
85
86   function rem($login)
87   {
88     $ismod  = FALSE;
89     $curtime = time();
90
91     for ($i = 0 ; $i < $this->item_n ; $i++) {
92       if ($this->item[$i]->timeout < $curtime || strcasecmp($this->item[$i]->login, $login) == 0) {
93         $ismod = TRUE;
94         for ($e = $i ; $e  < ($this->item_n - 1) ; $e++) {
95           $this->item[$e] = $this->item[$e + 1];
96         }
97         
98         $i--;
99         $this->item_n--;
100         unset($this->item[$this->item_n]);
101         $this->mod = TRUE;
102       }
103     }
104
105     return ($ismod);
106   }
107
108   function garbage_manager($force)
109   {
110     $curtime = time();
111
112     // FIXME remove set to 0
113     $this->garbage_timeout = 0;
114     if ($this->garbage_timeout > $curtime && $force == FALSE)
115       return (FALSE);
116
117     $ismod = FALSE;
118     
119     for ($i = 0 ; $i < $this->item_n ; $i++) {
120       log_auth("xxx", "LOOPI item: ".$i." timeout: ".$this->item[$i]->timeout."  curtime: ".$curtime);
121       if ($this->item[$i]->timeout < $curtime) {
122         for ($e = $i ; $e  < ($this->item_n - 1) ; $e++) {
123           $this->item[$e] = $this->item[$e + 1];
124         }
125         
126         $i--;
127         $this->item_n--;
128         log_auth("xxx", "LOOPI unset: ".$this->item_n);
129         unset($this->item[$this->item_n]);
130         $ismod = TRUE;
131         $this->mod = TRUE;
132       }
133     }
134     
135     log_auth("xxx", "LOOPI AFTER: ".count($this->item)." _n:" .$this->item_n );
136     
137     $this->garbage_timeout = $curtime + HBAN_GARBAGE_TIMEOUT;
138     
139     return ($ismod);
140   }
141   
142   function ismod()
143   {
144     return ($this->mod);
145   }
146
147   // Static functions
148   static function create()
149   {
150     $chal =& new Hardbans();
151     
152     $chal->mod = TRUE;
153
154     return $chal;
155   }
156
157   function load_data() 
158   {
159     GLOBAL $sess;
160
161     do {
162       if (($tok = @ftok(FTOK_PATH."/hardbans", "B")) == -1) {
163         log_main("ftok failed");
164         break;
165       }
166     
167       if (($shm_sz = sharedmem_sz($tok)) == -1) {
168         log_main("shmop_open failed");
169       }
170         
171       if ($shm_sz == -1)
172         $shm_sz = HBAN_SHM_DIMS_MIN;
173
174       if ($shm = shm_attach($tok, $shm_sz)) {
175           $hban = @shm_get_var($shm, $tok); // CHECKED BELOW
176         
177         log_only("hardban ==  ".($hban == FALSE ?   "FALSE" : "TRUE")."  hardban ===  ".($hban === FALSE ? "FALSE" : "TRUE")."  hardban isset ".(isset($hban) ?   "TRUE" : "FALSE"));
178         
179         if ($hban == FALSE) {
180           log_only("INIT HARDBAN DATA");
181           
182           $hban =& Hardbans::create();
183           if (@shm_put_var($shm, $tok, $hban) == FALSE) {
184             log_only("PUT_VAR FALLITA ".strlen(serialize($hban)));
185             log_only(serialize($hban));
186           }
187           log_shme("Hardban::save_data2");
188
189         }
190         $hban->shm_sz = $shm_sz;
191         
192         shm_detach($shm);
193       }
194
195       $hban->garbage_manager(TRUE);
196
197       return ($hban);
198     } while (0);
199     
200     return (FALSE);
201   }
202   
203
204   function save_data($hban) 
205   {
206     $shm =   FALSE;
207     $oldmod = $hban->mod;
208
209     if (($tok = @ftok(FTOK_PATH."/hardbans", "B")) == -1) 
210       return (FALSE);
211     
212     while ($hban->shm_sz < HBAN_SHM_DIMS_MAX) {
213       if (($shm = shm_attach($tok, $hban->shm_sz)) == FALSE)
214         break;
215       
216       if (isset($hban)) 
217         log_only("hardban count ".count($hban->item)."  _n: ".$hban->item_n);
218
219       $hban->mod = FALSE;
220       if (@shm_put_var($shm, $tok, $hban) != FALSE) {
221         shm_detach($shm);
222         log_shme("Hardban::save_data");
223         return (TRUE);
224       }
225       $hban->mod = $oldmod;
226
227       if (shm_remove($shm) === FALSE) {
228         log_only("REMOVE FALLITA");
229         break;
230       }
231       shm_detach($shm);
232       $hban->shm_sz += HBAN_SHM_DIMS_DLT;
233     } 
234
235     if ($shm)
236       shm_detach($shm);
237     
238     return (FALSE);
239   }
240
241   static function lock_data($is_exclusive)
242   {
243     if (($tok = @ftok(FTOK_PATH."/hardbans", "B")) == -1) {
244       return (FALSE);
245     }
246     // echo "FTOK ".$tok."<br>";
247     if (($res = sem_get($tok, ($is_exclusive ? 1 : LOCK_SHARE_MAX) )) == FALSE) {
248       return (FALSE);
249     }
250     if (sem_acquire($res)) {   
251         self::$delta_t = microtime(TRUE);
252         log_lock("LOCK   hardbans     [".self::$delta_t."]");
253       return ($res);
254     }
255     else
256       return (FALSE);
257   }
258   
259   static function unlock_data($res)
260   {
261     GLOBAL $sess; 
262     
263     log_lock("UNLOCK hardbans     [".(microtime(TRUE) - (self::$delta_t))."]");
264
265     return (sem_release($res));
266   }
267
268
269   function check($login, $ip, $session)
270   {
271     $bantime = -1;
272     /* if it exists check for a valid challenge */
273     if (($a_sem = Hardbans::lock_data(TRUE)) != FALSE) { 
274       
275       if (($hban = &Hardbans::load_data()) != FALSE) {
276         for ($e = 0 ; $e < $hban->item_n ; $e++) {
277           if ($login != FALSE) {
278             if (strcasecmp($login, $hban->item[$e]->login) == 0 || $hban->item[$e]->session == $session) {
279               $bantime = $hban->item[$e]->timeout;
280               break;
281             }
282           }
283           else {
284             /* check on ip and sess */
285             if ($hban->item[$e]->ip == $ip || $hban->item[$e]->session == $session) {
286               $bantime = $hban->item[$e]->timeout;
287               break;
288             }
289           }
290         } // for (...
291         if ($hban->ismod()) {
292           Hardbans::save_data(&$hban);
293         }
294       } // if (load_data
295       Hardbans::unlock_data($a_sem);
296     } // if (lock_data
297     
298     return ($bantime);
299   } // func
300
301
302
303   function add($login, $ip, $session, $timeout)
304   {
305     $found = FALSE;
306     /* if it exists check for a valid challenge */
307     if (($a_sem = Hardbans::lock_data(TRUE)) != FALSE) { 
308       
309       if (($hban = &Hardbans::load_data()) != FALSE) {
310
311         $hban->add_item($login, $ip, $session, $timeout);
312
313         if ($hban->ismod()) {
314           Hardbans::save_data(&$hban);
315         }
316       } // if (load_data
317       Hardbans::unlock_data($a_sem);
318     } // if (lock_data
319     
320     return ($found);
321   } // func
322
323 } // End CLASS Hardbans
324
325 ?>