4 * assigns some standard variables to smarty templates
8 $smarty->assign('USER',$_SESSION['ldapab']['username']);
12 * Uses Username and Password from Session to initialize the LDAP handle
13 * If it fails it redirects to login.php
15 function ldap_login(){
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=');
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 ($_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;
37 if(!do_ldap_bind($_SESSION['ldapab']['username'],
38 $_SESSION['ldapab']['password'],
39 $_SESSION['ldapab']['binddn'])){
40 header('Location: login.php?username=');
46 * Creates a global LDAP connection handle called $LDAP_CON
48 function do_ldap_bind($user,$pass,$dn=""){
52 //create global connection to LDAP if necessary
54 if (!empty($conf['ldapurl'])){
55 $LDAP_CON = ldap_connect($conf['ldapurl']);
57 $LDAP_CON = ldap_connect($conf['ldapserver'],$conf['ldapport']);
60 die("couldn't connect to LDAP server");
64 if($conf['ldapv3']) ldap_set_option($LDAP_CON, LDAP_OPT_PROTOCOL_VERSION, 3);
67 //anonymous bind to lookup users
68 //blank binddn or blank bindpw will result in anonymous bind
69 if(!ldap_bind($LDAP_CON,$conf['anonbinddn'],$conf['anonbindpw'])){
70 die("can not bind for user lookup");
73 //when no user was given stay connected anonymous
75 set_session('','','');
79 //get dn for given user
80 $filter = str_replace('%u',$user,$conf['userfilter']);
81 $sr = ldap_search($LDAP_CON, $conf['usertree'], $filter);;
82 $result = ldap_get_entries($LDAP_CON, $sr);
83 if($result['count'] != 1){
84 set_session('','','');
87 $dn = $result[0]['dn'];
91 if(ldap_bind($LDAP_CON,$dn,$pass)){
92 //bind successful -> set up session
93 set_session($user,$pass,$dn);
96 //bind failed -> remove session
97 set_session('','','');
102 * Builds a pseudo UID from browser and IP data
104 * This is neither unique nor unfakable - still it adds some
105 * security. Using the first part of the IP makes sure
106 * proxy farms like AOLs are stil okay.
108 * @author Andreas Gohr <andi@splitbrain.org>
110 * @return string a MD5 sum of various browser headers
112 function auth_browseruid(){
114 $uid .= $_SERVER['HTTP_USER_AGENT'];
115 $uid .= $_SERVER['HTTP_ACCEPT_ENCODING'];
116 $uid .= $_SERVER['HTTP_ACCEPT_LANGUAGE'];
117 $uid .= $_SERVER['HTTP_ACCEPT_CHARSET'];
118 $uid .= substr($_SERVER['REMOTE_ADDR'],0,strpos($_SERVER['REMOTE_ADDR'],'.'));
124 * saves user data to Session and cookies
126 function set_session($user,$pass,$dn){
130 $_SESSION['ldapab']['username'] = $user;
131 $_SESSION['ldapab']['binddn'] = $dn;
132 $_SESSION['ldapab']['password'] = $pass;
133 $_SESSION['ldapab']['browserid'] = auth_browseruid();
135 // (re)set the persistant auth cookie
137 setcookie('ldapabauth','',time()+60*60*24*365);
138 }elseif($_REQUEST['remember']){
139 $cookie = serialize(array($user,$pass));
140 $cookie = x_Encrypt($cookie,get_cookie_secret());
141 $cookie = base64_encode($cookie);
142 setcookie('ldapabauth',$cookie,time()+60*60*24*365);
147 * Creates a random string to encrypt persistant auth
148 * cookies the string is stored inside the cache dir
150 function get_cookie_secret(){
151 $file = dirname(__FILE__).'/cache/.htcookiesecret.php';
152 if(@file_exists($file)){
153 return md5(trim(file($file)));
156 $secret = '<?php #'.(rand()*time()).'?>';
157 if(!$fh = fopen($file,'w')) die("Couldn't write to $file");
158 if(fwrite($fh, $secret) === FALSE) die("Couldn't write to $file");
165 * binary safe function to get all search result data.
166 * It will use ldap_get_values_len() instead and build the array
167 * note: it's similar with the array returned by ldap_get_entries()
168 * except it has no "count" elements
170 * @author: Original code by Ovidiu Geaboc <ogeaboc@rdanet.com>
172 function ldap_get_binentries($conn,$srchRslt){
173 if(!@ldap_count_entries($conn,$srchRslt)){
176 $entry = ldap_first_entry($conn, $srchRslt);
179 $dn = ldap_get_dn($conn,$entry);
180 $attrs = ldap_get_attributes($conn, $entry);
181 for($j=0; $j<$attrs['count']; $j++) {
182 $vals = ldap_get_values_len($conn, $entry,$attrs[$j]);
183 for($k=0; $k<$vals['count']; $k++){
184 $data[$i][$attrs[$j]][$k]=$vals[$k];
189 }while ($entry = ldap_next_entry($conn, $entry));
195 * loads ldap names and their cleartext meanings from
196 * entries.conf file and returns it as hash
198 function namedentries($flip=false){
201 $entries['dn'] = 'dn';
202 $entries['sn'] = 'name';
203 $entries['givenName'] = 'givenname';
204 $entries['title'] = 'title';
205 $entries['o'] = 'organization';
206 $entries['physicalDeliveryOfficeName'] = 'office';
207 $entries['postalAddress'] = 'street';
208 $entries['postalCode'] = 'zip';
209 $entries['l'] = 'location';
210 $entries['telephoneNumber'] = 'phone';
211 $entries['facsimileTelephoneNumber'] = 'fax';
212 $entries['mobile'] = 'mobile';
213 $entries['pager'] = 'pager';
214 $entries['homePhone'] = 'homephone';
215 $entries['homePostalAddress'] = 'homestreet';
216 $entries['jpegPhoto'] = 'photo';
217 $entries['labeledURI'] = 'url';
218 $entries['description'] = 'note';
219 $entries['manager'] = 'manager';
220 $entries['cn'] = 'displayname';
222 if($conf['extended']){
223 $entries['anniversary'] = 'anniversary';
225 if($conf['openxchange']){
226 $entries['mailDomain'] = 'domain';
227 $entries['userCountry'] = 'country';
228 $entries['birthDay'] = 'birthday';
229 $entries['IPPhone'] = 'ipphone';
230 $entries['OXUserCategories'] = 'categories';
231 $entries['OXUserInstantMessenger'] = 'instantmessenger';
232 $entries['OXTimeZone'] = 'timezone';
233 $entries['OXUserPosition'] = 'position';
234 $entries['relClientCert'] = 'certificate';
238 $entries = array_reverse($entries);
239 $entries = array_flip($entries);
245 * Creates an array for submission to ldap from websitedata
247 function prepare_ldap_entry($in){
251 if(!preg_match('/\d\d\d\d-\d\d-\d\d/',$in['anniversary'])){
252 $in['anniversary']='';
255 $entries = namedentries(true);
256 foreach(array_keys($in) as $key){
257 if(empty($entries[$key])){
260 $keyname=$entries[$key];
262 if(is_array($in[$key])){
263 $out[$keyname] = $in[$key];
265 $out[$keyname][] = $in[$key];
269 //standard Objectclass
270 $out['objectclass'][] = 'inetOrgPerson';
271 if($conf['extended']){
272 $out['objectclass'][] = 'contactPerson';
274 if($conf['openxchange']){
275 $out['objectclass'][] = 'OXUserObject';
278 return clear_array($out);
282 * remove empty element from arrays recursively
284 * @author Original by <xntx@msn.com>
286 function clear_array ( $a ) {
287 if ($a !== array()) {
289 foreach ( $a as $key => $value ) {
290 if (is_array($value)) {
291 if (clear_array($value) !== false) {
292 $b[$key] = clear_array ( $value );
294 } elseif ($value !== '') {
298 if ($b !== array()) {
309 * deletes an entryfrom ldap - optional with recursion
311 * @author Original by <gabriel@hrz.uni-marburg.de>
313 function ldap_full_delete($ds,$dn,$recursive=false){
314 if($recursive == false){
315 return(ldap_delete($ds,$dn));
317 //searching for sub entries
318 $sr=ldap_list($ds,$dn,"ObjectClass=*",array(""));
319 $info = ldap_get_entries($ds, $sr);
320 for($i=0;$i<$info['count'];$i++){
321 //deleting recursively sub entries
322 $result=myldap_delete($ds,$info[$i]['dn'],$recursive);
324 //return result code, if delete fails
328 return(ldap_delete($ds,$dn));
333 * Returns all User Accounts as assoziative array
335 function get_users(){
339 $sr = ldap_list($LDAP_CON,$conf['usertree'],"ObjectClass=inetOrgPerson");
340 $result = ldap_get_binentries($LDAP_CON, $sr);
342 foreach ($result as $entry){
343 if(!empty($entry['sn'][0])){
344 $users[$entry['dn']] = $entry['givenName'][0]." ".$entry['sn'][0];
352 * makes sure the given DN contains exactly one space
355 function normalize_dn($dn){
356 $dn = preg_replace('/,/',', ',$dn);
357 $dn = preg_replace('/,\s+/',', ',$dn);
362 * Merges the given classes with the existing ones
364 function ldap_store_objectclasses($dn,$classes){
368 $sr = ldap_search($LDAP_CON,$dn,"objectClass=*",array('objectClass'));
369 $result = ldap_get_binentries($LDAP_CON, $sr);
370 $set = $result[0]['objectClass'];
371 $set = array_unique_renumber(array_merge((array)$set,(array)$classes));
372 $add['objectClass'] = $set;
374 $r = @ldap_mod_replace($LDAP_CON,$dn,$add);
383 * escape parenthesises in given string
385 function ldap_filterescape($string){
386 return strtr($string,array('('=>'\(', ')'=>'\)'));
390 * Queries public and private addressbooks, combining the
393 * @todo This function should be used where ever possible, replacing
394 * lots of duplicate code
396 function ldap_queryabooks($filter,$types){
400 // make sure $types is an array
401 if(!is_array($types)){
402 $types = explode(',',$types);
403 $types = array_map('trim',$types);
410 // public addressbook
411 $sr = ldap_list($LDAP_CON,$conf['publicbook'],
413 $result1 = ldap_get_binentries($LDAP_CON, $sr);
414 ldap_free_result($sr);
416 // private addressbook
417 if(!empty($_SESSION['ldapab']['binddn'])){
418 $sr = @ldap_list($LDAP_CON,$conf['privatebook'].
419 ','.$_SESSION['ldapab']['binddn'],
421 $result2 = ldap_get_binentries($LDAP_CON, $sr);
424 // return merged results
425 return array_merge((array)$result1,(array)$result2);
429 * Makes array unique and renumbers the entries
431 * @author <kay_rules@yahoo.com>
433 function array_unique_renumber($somearray){
434 $tmparr = array_unique($somearray);
436 foreach ($tmparr as $v) {
444 * Simple XOR encryption
446 * @author Dustin Schneider
447 * @link http://www.phpbuilder.com/tips/item.php?id=68
449 function x_Encrypt($string, $key){
450 for($i=0; $i<strlen($string); $i++){
451 for($j=0; $j<strlen($key); $j++){
452 $string[$i] = $string[$i]^$key[$j];
459 * Simple XOR decryption
461 * @author Dustin Schneider
462 * @link http://www.phpbuilder.com/tips/item.php?id=68
464 function x_Decrypt($string, $key){
465 for($i=0; $i<strlen($string); $i++){
466 for($j=0; $j<strlen($key); $j++){
467 $string[$i] = $key[$j]^$string[$i];
474 * Decodes UTF8 recursivly for the given array
478 function utf8_decode_array(&$array) {
479 trigger_error('deprecated utf8_decode_array called',E_USER_WARNING);
481 foreach (array_keys($array) as $key) {
482 if($key === 'dn') continue;
483 if($key === 'jpegPhoto') continue;
484 if (is_array($array[$key])) {
485 utf8_decode_array($array[$key]);
487 $array[$key] = utf8_decode($array[$key]);
493 * Encodes the given array to UTF8 recursively
497 function utf8_encode_array(&$array) {
498 trigger_error('deprecated utf8_encode_array called',E_USER_WARNING);
500 foreach (array_keys($array) as $key) {
501 if($key === 'dn') continue;
502 if($key === 'jpegPhoto') continue;
503 if (is_array($array[$key])) {
504 utf8_encode_array($array[$key]);
506 $array[$key] = utf8_encode($array[$key]);