]> git.sur5r.net Git - contagged/blob - functions.php
weighted tagcloud
[contagged] / functions.php
1 <?
2
3 /**
4  * assigns some standard variables to smarty templates
5  */
6 function smarty_std(){
7   global $smarty;
8   $smarty->assign('USER',$_SESSION['ldapab']['username']);
9 }
10
11 /**
12  * Uses Username and Password from Session to initialize the LDAP handle
13  * If it fails it redirects to login.php
14  */
15 function ldap_login(){
16   global $conf;
17   if(!empty($_SESSION['ldapab']['username'])){
18     // existing session! Check if valid
19     if($_SESSION['ldapab']['browserid'] != auth_browseruid()){
20       //session hijacking detected
21       header('Location: login.php?username=');
22       exit;
23     }
24   } elseif ($conf['httpd_auth'] && !empty($_SERVER['PHP_AUTH_USER'])) {
25     // use HTTP auth if wanted and possible
26     $_SESSION['ldapab']['username'] = $_SERVER['PHP_AUTH_USER'];
27     $_SESSION['ldapab']['password'] = $_SERVER['PHP_AUTH_PW'];
28   } elseif (!empty($_COOKIE['ldapabauth'])) {
29     // check persistent cookie
30     $cookie = base64_decode($_COOKIE['ldapabauth']);
31     $cookie = x_Decrypt($cookie,get_cookie_secret());
32     list($u,$p) = unserialize($cookie);
33     $_SESSION['ldapab']['username'] = $u;
34     $_SESSION['ldapab']['password'] = $p;
35   }
36
37   if(empty($_SESSION['ldapab']) ||
38      !do_ldap_bind($_SESSION['ldapab']['username'],
39                    $_SESSION['ldapab']['password'],
40                    $_SESSION['ldapab']['binddn'])){
41     header('Location: login.php?username=');
42     exit;
43   }
44 }
45
46 /**
47  * Creates a global LDAP connection handle called $LDAP_CON
48  */
49 function do_ldap_bind($user,$pass,$dn=""){
50   global $conf;
51   global $LDAP_CON;
52
53   //create global connection to LDAP if necessary
54   if(!$LDAP_CON){
55     if (!empty($conf['ldapurl'])){
56       $LDAP_CON = ldap_connect($conf['ldapurl']);
57     }else{
58       $LDAP_CON = ldap_connect($conf['ldapserver'],$conf['ldapport']);
59     }
60     if(!$LDAP_CON){
61       die("couldn't connect to LDAP server");
62     }
63   }
64
65   if($conf['ldapv3']) ldap_set_option($LDAP_CON, LDAP_OPT_PROTOCOL_VERSION, 3);
66
67   if(empty($dn)){
68     //anonymous bind to lookup users
69     //blank binddn or blank bindpw will result in anonymous bind
70     if(!ldap_bind($LDAP_CON,$conf['anonbinddn'],$conf['anonbindpw'])){
71       die("can not bind for user lookup");
72     }
73
74     //when no user was given stay connected anonymous
75     if(empty($user)){
76       set_session('','','');
77       return true;
78     }
79
80     //get dn for given user
81     $filter = str_replace('%u',$user,$conf['userfilter']);
82     $sr = ldap_search($LDAP_CON, $conf['usertree'], $filter);;
83     $result = ldap_get_entries($LDAP_CON, $sr);
84     if($result['count'] != 1){
85       set_session('','','');
86       return false;
87     }
88     $dn = $result[0]['dn'];
89   }
90
91   //bind with dn
92   if(ldap_bind($LDAP_CON,$dn,$pass)){
93     //bind successful -> set up session
94     set_session($user,$pass,$dn);
95     return true;
96   }
97   //bind failed -> remove session
98   set_session('','','');
99   return false;
100 }
101
102 /**
103  * Builds a pseudo UID from browser and IP data
104  *
105  * This is neither unique nor unfakable - still it adds some
106  * security. Using the first part of the IP makes sure
107  * proxy farms like AOLs are stil okay.
108  *
109  * @author  Andreas Gohr <andi@splitbrain.org>
110  *
111  * @return  string  a MD5 sum of various browser headers
112  */
113 function auth_browseruid(){
114   $uid  = '';
115   if (empty($_SERVER['HTTP_USER_AGENT']))      { $_SERVER['HTTP_USER_AGENT']='USER_AGENT'; }
116   if (empty($_SERVER['HTTP_ACCEPT_ENCODING'])) { $_SERVER['HTTP_ACCEPT_ENCODING']='ACCEPT_ENCODING'; }
117   if (empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { $_SERVER['HTTP_ACCEPT_LANGUAGE']='ACCEPT_LANGUAGE'; }
118   if (empty($_SERVER['HTTP_ACCEPT_CHARSET']))  { $_SERVER['HTTP_ACCEPT_CHARSET']='ACCEPT_CHARSET'; }
119   $uid .= $_SERVER['HTTP_USER_AGENT'];
120   $uid .= $_SERVER['HTTP_ACCEPT_ENCODING'];
121   $uid .= $_SERVER['HTTP_ACCEPT_LANGUAGE'];
122   $uid .= $_SERVER['HTTP_ACCEPT_CHARSET'];
123   $uid .= substr($_SERVER['REMOTE_ADDR'],0,strpos($_SERVER['REMOTE_ADDR'],'.'));
124   return md5($uid);
125 }
126
127
128 /**
129  * saves user data to Session and cookies
130  */
131 function set_session($user,$pass,$dn){
132   global $conf;
133
134   $rand = rand();
135   $_SESSION['ldapab']['username']  = $user;
136   $_SESSION['ldapab']['binddn']    = $dn;
137   $_SESSION['ldapab']['password']  = $pass;
138   $_SESSION['ldapab']['browserid'] = auth_browseruid();
139
140   // (re)set the persistent auth cookie
141   if($user == ''){
142     setcookie('ldapabauth','',time()+60*60*24*365);
143   }elseif(!empty($_REQUEST['remember'])){
144     $cookie = serialize(array($user,$pass));
145     $cookie = x_Encrypt($cookie,get_cookie_secret());
146     $cookie = base64_encode($cookie);
147     setcookie('ldapabauth',$cookie,time()+60*60*24*365);
148   }
149 }
150
151 /**
152  * Creates a random string to encrypt persistent auth
153  * cookies; the string is stored inside the cache dir
154  */
155 function get_cookie_secret(){
156   $file = dirname(__FILE__).'/cache/.htcookiesecret.php';
157   if(@file_exists($file)){
158     return md5(trim(file($file)));
159   }
160
161   $secret = '<?php #'.(rand()*time()).'?>';
162   if(!$fh = fopen($file,'w')) die("Couldn't write to $file");
163   if(fwrite($fh, $secret) === FALSE) die("Couldn't write to $file");
164   fclose($fh);
165
166   return md5($secret);
167 }
168
169 /**
170  * binary safe function to get all search result data.
171  * It will use ldap_get_values_len() instead and build the array
172  * note: it's similar with the array returned by ldap_get_entries()
173  * except it has no "count" elements
174  *
175  * @author: Original code by Ovidiu Geaboc <ogeaboc@rdanet.com>
176  */
177 function ldap_get_binentries($conn,$srchRslt){
178   if(!@ldap_count_entries($conn,$srchRslt)){
179     return null;
180   }
181   $entry = ldap_first_entry($conn, $srchRslt);
182   $i=0;
183   do {
184     $dn = ldap_get_dn($conn,$entry);
185     $attrs = ldap_get_attributes($conn, $entry);
186     for($j=0; $j<$attrs['count']; $j++) {
187       $vals = ldap_get_values_len($conn, $entry,$attrs[$j]);
188       for($k=0; $k<$vals['count']; $k++){
189         $data[$i][$attrs[$j]][$k]=$vals[$k];
190       }
191     }
192     $data[$i]['dn']=$dn;
193     $i++;
194   }while ($entry = ldap_next_entry($conn, $entry));
195
196   return $data;
197 }
198
199 /**
200  * loads ldap names and their cleartext meanings from
201  * entries.conf file and returns it as hash
202  */
203 function namedentries($flip=false){
204   global $conf;
205
206   $entries['dn']                         = 'dn';
207   $entries['sn']                         = 'name';
208   $entries['givenName']                  = 'givenname';
209   $entries['title']                      = 'title';
210   $entries['o']                          = 'organization';
211   $entries['physicalDeliveryOfficeName'] = 'office';
212   $entries['postalAddress']              = 'street';
213   $entries['postalCode']                 = 'zip';
214   $entries['l']                          = 'location';
215   $entries['telephoneNumber']            = 'phone';
216   $entries['facsimileTelephoneNumber']   = 'fax';
217   $entries['mobile']                     = 'mobile';
218   $entries['pager']                      = 'pager';
219   $entries['homePhone']                  = 'homephone';
220   $entries['homePostalAddress']          = 'homestreet';
221   $entries['jpegPhoto']                  = 'photo';
222   $entries['labeledURI']                 = 'url';
223   $entries['description']                = 'note';
224   $entries['manager']                    = 'manager';
225   $entries['cn']                         = 'displayname';
226
227   if($conf['extended']){
228     $entries['anniversary']              = 'anniversary';
229   }
230   if($conf['openxchange']){
231     $entries['mailDomain']               = 'domain';
232     $entries['userCountry']              = 'country';
233     $entries['birthDay']                 = 'birthday';
234     $entries['IPPhone']                  = 'ipphone';
235     $entries['OXUserCategories']         = 'categories';
236     $entries['OXUserInstantMessenger']   = 'instantmessenger';
237     $entries['OXTimeZone']               = 'timezone';
238     $entries['OXUserPosition']           = 'position';
239     $entries['relClientCert']            = 'certificate';
240   }
241
242   if($flip){
243     $entries = array_reverse($entries);
244     $entries = array_flip($entries);
245   }
246   return $entries;
247 }
248
249 /**
250  * Creates an array for submission to ldap from websitedata
251  */
252 function prepare_ldap_entry($in){
253   global $conf;
254
255   //check dateformat
256   if(!preg_match('/\d\d\d\d-\d\d-\d\d/',$in['anniversary'])){
257     $in['anniversary']='';
258   }
259
260   $entries = namedentries(true);
261   foreach(array_keys($in) as $key){
262     if(empty($entries[$key])){
263       $keyname=$key;
264     }else{
265       $keyname=$entries[$key];
266     }
267     if(is_array($in[$key])){
268       $out[$keyname] = $in[$key];
269     }else{
270       $out[$keyname][] = $in[$key];
271     }
272   }
273
274   //standard Objectclass
275   $out['objectclass'][] = 'inetOrgPerson';
276   if($conf['extended']){
277     $out['objectclass'][] = 'contactPerson';
278   }
279   if($conf['openxchange']){
280     $out['objectclass'][] = 'OXUserObject';
281   }
282
283   return clear_array($out);
284 }
285
286 /**
287  * remove empty element from arrays recursively
288  *
289  * @author Original by <xntx@msn.com>
290  */
291 function clear_array ( $a ) {
292   if ($a !== array()) {
293     $b = array();
294     foreach ( $a as $key => $value ) {
295         if (is_array($value)) {
296           if (clear_array($value) !== false) {
297             $b[$key] = clear_array ( $value );
298           }
299         } elseif ($value !== '') {
300           $b[$key] = $value;
301         }
302     }
303     if ($b !== array()) {
304         return $b;
305     } else {
306         return false;
307     }
308   } else {
309     return false;
310   }
311 }
312
313 /**
314  * deletes an entryfrom ldap - optional with recursion
315  *
316  * @author Original by <gabriel@hrz.uni-marburg.de>
317  */
318 function ldap_full_delete($ds,$dn,$recursive=false){
319   if($recursive == false){
320     return(ldap_delete($ds,$dn));
321   }else{
322     //searching for sub entries
323     $sr=ldap_list($ds,$dn,"ObjectClass=*",array(""));
324     $info = ldap_get_entries($ds, $sr);
325     for($i=0;$i<$info['count'];$i++){
326       //deleting recursively sub entries
327       $result=myldap_delete($ds,$info[$i]['dn'],$recursive);
328       if(!$result){
329         //return result code, if delete fails
330         return($result);
331       }
332     }
333     return(ldap_delete($ds,$dn));
334   }
335 }
336
337 /**
338  * Returns all User Accounts as assoziative array
339  */
340 function get_users(){
341   global $conf;
342   global $LDAP_CON;
343
344   $sr = ldap_list($LDAP_CON,$conf['usertree'],"ObjectClass=inetOrgPerson");
345   $result = ldap_get_binentries($LDAP_CON, $sr);
346   $users = array();
347   if(count($result)){
348     foreach ($result as $entry){
349       if(!empty($entry['sn'][0])){
350         $users[$entry['dn']] = $entry['givenName'][0]." ".$entry['sn'][0];
351       }
352     }
353   }
354   return $users;
355 }
356
357 /**
358  * makes sure the given DN contains exactly one space
359  * after each ,
360  */
361 function normalize_dn($dn){
362   $dn = preg_replace('/,/',', ',$dn);
363   $dn = preg_replace('/,\s+/',', ',$dn);
364   return $dn;
365 }
366
367 /**
368  * Merges the given classes with the existing ones
369  */
370 function ldap_store_objectclasses($dn,$classes){
371   global $conf;
372   global $LDAP_CON;
373
374   $sr     = ldap_search($LDAP_CON,$dn,"objectClass=*",array('objectClass'));
375   $result = ldap_get_binentries($LDAP_CON, $sr);
376   $set    = $result[0]['objectClass'];
377   $set    = array_unique_renumber(array_merge((array)$set,(array)$classes));
378   $add['objectClass'] = $set;
379
380   $r = @ldap_mod_replace($LDAP_CON,$dn,$add);
381   tpl_ldaperror();
382
383 /*  print '<pre>';
384   print_r($set);
385   print '</pre>';*/
386 }
387
388 /**
389  * escape parenthesises in given string
390  */
391 function ldap_filterescape($string){
392   return strtr($string,array('('=>'\(', ')'=>'\)'));
393 }
394
395 /**
396  * Queries public and private addressbooks, combining the
397  * results
398  *
399  * @todo This function should be used where ever possible, replacing
400  *       lots of duplicate code
401  */
402 function ldap_queryabooks($filter,$types){
403   global $conf;
404   global $LDAP_CON;
405
406   // make sure $types is an array
407   if(!is_array($types)){
408     $types = explode(',',$types);
409     $types = array_map('trim',$types);
410   }
411
412   $results = array();
413   $result1 = array();
414   $result2 = array();
415
416   // public addressbook
417   $sr      = ldap_list($LDAP_CON,$conf['publicbook'],
418                        $filter,$types);
419   $result1 = ldap_get_binentries($LDAP_CON, $sr);
420   ldap_free_result($sr);
421
422   // private addressbook
423   if(!empty($_SESSION['ldapab']['binddn'])){
424     $sr      = @ldap_list($LDAP_CON,$conf['privatebook'].
425                           ','.$_SESSION['ldapab']['binddn'],
426                           $filter,$types);
427     $result2 = ldap_get_binentries($LDAP_CON, $sr);
428   }
429
430   // return merged results
431   return array_merge((array)$result1,(array)$result2);
432 }
433
434 /**
435  * Makes array unique and renumbers the entries
436  *
437  * @author <kay_rules@yahoo.com>
438  */
439 function array_unique_renumber($somearray){
440    $tmparr = array_unique($somearray);
441    $i=0;
442    foreach ($tmparr as $v) {
443        $newarr[$i] = $v;
444        $i++;
445    }
446    return $newarr;
447 }
448
449 /**
450  * Simple XOR encryption
451  *
452  * @author Dustin Schneider
453  * @link http://www.phpbuilder.com/tips/item.php?id=68
454  */
455 function x_Encrypt($string, $key){
456     for($i=0; $i<strlen($string); $i++){
457         for($j=0; $j<strlen($key); $j++){
458             $string[$i] = $string[$i]^$key[$j];
459         }
460     }
461     return $string;
462 }
463
464 /**
465  * Simple XOR decryption
466  *
467  * @author Dustin Schneider
468  * @link http://www.phpbuilder.com/tips/item.php?id=68
469  */
470 function x_Decrypt($string, $key){
471     for($i=0; $i<strlen($string); $i++){
472         for($j=0; $j<strlen($key); $j++){
473             $string[$i] = $key[$j]^$string[$i];
474         }
475     }
476     return $string;
477 }
478
479 /**
480  * Decodes UTF8 recursivly for the given array
481  *
482  * @deprecated
483  */
484 function utf8_decode_array(&$array) {
485   trigger_error('deprecated utf8_decode_array called',E_USER_WARNING);
486
487   foreach (array_keys($array) as $key) {
488     if($key === 'dn') continue;
489     if($key === 'jpegPhoto') continue;
490     if (is_array($array[$key])) {
491       utf8_decode_array($array[$key]);
492     }else {
493       $array[$key] = utf8_decode($array[$key]);
494     }
495   }
496 }
497
498 /**
499  * Encodes the given array to UTF8 recursively
500  *
501  * @deprecated
502  */
503 function utf8_encode_array(&$array) {
504   trigger_error('deprecated utf8_encode_array called',E_USER_WARNING);
505
506   foreach (array_keys($array) as $key) {
507     if($key === 'dn') continue;
508     if($key === 'jpegPhoto') continue;
509     if (is_array($array[$key])) {
510       utf8_encode_array($array[$key]);
511     }else {
512       $array[$key] = utf8_encode($array[$key]);
513     }
514   }
515 }
516
517
518 ?>