~fkhan-zivios/zivios/devel

« back to all changes in this revision

Viewing changes to application/library/Ecl/Ldap/Engine.php

  • Committer: Faraz Khan
  • Date: 2008-09-15 13:29:33 UTC
  • Revision ID: fkhan@zivios.org-20080915132933-d27jml5l29xw4gsr
Initial release to bazaar, code in sync with 0.5.0-release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * Copyright (c) 2008 Zivios, LLC.
 
4
 *
 
5
 * This file is part of Zivios.
 
6
 *
 
7
 * Zivios is free software: you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as published by
 
9
 * the Free Software Foundation, either version 3 of the License, or
 
10
 * (at your option) any later version.
 
11
 *
 
12
 * Zivios is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with Zivios.  If not, see <http://www.gnu.org/licenses/>.
 
19
 *
 
20
 * @package             Zivios
 
21
 * @copyright   Copyright (c) 2008 Zivios, LLC. (http://www.zivios.org)
 
22
 * @license             http://www.zivios.org/legal/license
 
23
 * @version             $Id$
 
24
 * @subpackage  Core
 
25
 **/
 
26
 
 
27
class Ecl_Ldap_Engine
 
28
{
 
29
    /**
 
30
     * Ldap Centric Info
 
31
     */
 
32
        public $ldapConfig, $uid, $dn;
 
33
        protected $conn, $resource;
 
34
    private $eventlisteners, $params, $dirty_params,$transaction;
 
35
 
 
36
    /**
 
37
     * EMS Centric Info
 
38
     */
 
39
    public $attrs, $makedn, $isnew, $transmode, $cachetransid;
 
40
    protected $_addarray,$_delarray,$_modarray;
 
41
    private $emsaclarray,$iacllist;
 
42
 
 
43
    public function __construct($dn=null,$attrs=null,$acllist=null)
 
44
    {
 
45
        $this->ldapConfig = Zend_Registry::get('ldapConfig');
 
46
        $this->_addarray = array();
 
47
        $this->_delarray = array();
 
48
        $this->_modarray = array();
 
49
        $this->eventlisteners = array();
 
50
        $this->conn = 0;
 
51
        $this->resource = 0;
 
52
        $this->params = array();
 
53
        $this->dirty_params = array();
 
54
 
 
55
        if ($attrs == null)
 
56
            $attrs = array();
 
57
 
 
58
        $attrs[] = "dn";
 
59
        $attrs[] = "objectclass";
 
60
        $attrs[] = "emsmodelclass";
 
61
        $attrs[] = "cn";
 
62
 
 
63
        $attrs =  array_unique($attrs);
 
64
        $attrs = array_values($attrs);
 
65
 
 
66
        if ($acllist == null)
 
67
            $acllist = array();
 
68
 
 
69
        $acllist[] = 'CORE_LOAD_DN';
 
70
        $this->acllist = $acllist;
 
71
 
 
72
        $this->attrs = $attrs;
 
73
        $this->dn = $dn;
 
74
        Ecl_Log::debug("Constructed with Dn: " . $dn ." and class type: " . get_class($this) .
 
75
                " and attrs: " . implode(",",$attrs));
 
76
 
 
77
        if ($dn == null)
 
78
            $this->isnew = true;
 
79
        else
 
80
                $this->isnew = false;
 
81
 
 
82
        $this->reconnect();
 
83
    }
 
84
 
 
85
 
 
86
    public function addEventListener($eventname,$listener)
 
87
    {
 
88
        Ecl_Log::debug("Adding eventlistener on: " . $eventname . " for class: " . get_class($listener) .
 
89
                " on dn: " . $this->getdn());
 
90
 
 
91
        if (array_key_exists($eventname,$this->eventlisteners))
 
92
            $listenerobj = $this->eventlisteners[$eventname];
 
93
        else {
 
94
            $listenerobj = new StdClass();
 
95
            $listenerobj->listeners = array();
 
96
            $this->eventlisteners[$eventname] = $listenerobj;
 
97
        }
 
98
 
 
99
        $listenerobj->listeners[] = $listener;
 
100
    }
 
101
 
 
102
    public function fireEvent($eventname)
 
103
    {
 
104
        if (array_key_exists($eventname,$this->eventlisteners)) {
 
105
            $listenerobj = $this->eventlisteners[$eventname];
 
106
            foreach ($listenerobj->listeners as $listener) {
 
107
                Ecl_Log::debug("Firing Event: $eventname on listener :".get_class($listener));
 
108
                $listener->eventAction($eventname);
 
109
            }
 
110
        } else
 
111
            Ecl_Log::info("No event listeners for $eventname on dn :".$this->getdn());
 
112
    }
 
113
 
 
114
    protected function setMode()
 
115
    {
 
116
        $_userSession = new Zend_Session_Namespace("userSession");
 
117
        if (isset($_userSession->transinprocess) && $_userSession->transinprocess > 0) {
 
118
            $this->transmode = 1;
 
119
            $this->cachetransid = $_userSession->transinprocess;
 
120
            Ecl_Log::info("Cache operative in Transaction mode for id :".$_userSession->transinprocess);
 
121
        }
 
122
    }
 
123
 
 
124
    public function inTransaction()
 
125
    {
 
126
        $this->setMode();
 
127
        return ($this->transmode == 1);
 
128
    }
 
129
 
 
130
    public function getCacheTransId()
 
131
    {
 
132
        $this->setMode();
 
133
        return $this->cachetransid;
 
134
    }
 
135
 
 
136
    protected function sp_query($dn,$property)
 
137
    {
 
138
        $filter = "(objectclass=*)";
 
139
        $proparray = array();
 
140
        $proparray[] = $property;
 
141
        $entries = $this->search($filter,$proparray,$dn,"BASE");
 
142
 
 
143
        if ($entries['count'] < 1) {
 
144
            Ecl_Log::error("Special Query failed, DN not found");
 
145
            return null;
 
146
        }
 
147
 
 
148
        if ($entries[0]['count'] < 1) {
 
149
            Ecl_Log::info("Special query return no results for attrib : $property");
 
150
            return null;
 
151
        }
 
152
 
 
153
        $retval =  $entries[0][$property];
 
154
 
 
155
        if ($retval['count'] == 1)
 
156
            return $retval[0];
 
157
        else {
 
158
            return array_splice($retval,1);
 
159
        }
 
160
    }
 
161
 
 
162
    /**
 
163
     * This is a special function as its called during the INIT process
 
164
     * we need to know what plugins an object has to intialize its ATTRS
 
165
     * Intresting problem indeed
 
166
     */
 
167
    protected static function getPlugins($dn)
 
168
    {
 
169
        $obj = new Ecl_Ldap_Engine($dn);
 
170
        return $obj->sp_query($dn,'emsplugins');
 
171
    }
 
172
 
 
173
    protected function getEmsPerms()
 
174
    {
 
175
         return $this->sp_query($this->dn,'emspermission');
 
176
    }
 
177
 
 
178
    protected function getLdapAci()
 
179
    {
 
180
        return $this->sp_query($this->dn,'openldapaci');
 
181
    }
 
182
 
 
183
    protected function getModelClass()
 
184
    {
 
185
        return $this->sp_query($this->dn,'emsmodelclass');
 
186
    }
 
187
 
 
188
    protected function getModifyTime()
 
189
    {
 
190
        return $this->sp_query($this->dn,'modifytimestamp');
 
191
    }
 
192
 
 
193
    public function exists()
 
194
    {
 
195
        $filter = "(objectclass=*)";
 
196
        $entries = $this->search($filter,array('dn'),$this->dn,"BASE");
 
197
        return ($entries['count'] > 0);
 
198
    }
 
199
 
 
200
    public function init()
 
201
    {
 
202
        $dn = $this->dn;
 
203
        $attrs = $this->attrs;
 
204
        $this->dn = $dn;
 
205
 
 
206
        if ($attrs == null)
 
207
            throw new Ecl_Ldap_Exception("Cannot instantiate Ldap_Engine with zero attrs");
 
208
 
 
209
        $this->addAttrs($attrs,1);
 
210
        $this->addEmsAcls($this->acllist,1);
 
211
 
 
212
        if (!$this->isNew())
 
213
            $this->requireAcl('CORE_LOAD_DN');
 
214
    }
 
215
 
 
216
    protected function addEmsAcls($acls,$skipmerge=0)
 
217
    {
 
218
        if (!$skipmerge) {
 
219
            $newacls = array_diff($acls,$this->acllist);
 
220
            $this->acllist = array_merge($this->acllist,$newacls);
 
221
            $this->acllist = array_values($this->acllist);
 
222
        } else
 
223
            $newacls = $acls;
 
224
 
 
225
        Ecl_Log::debug("Added ACLS: ".implode(",",$newacls));
 
226
 
 
227
        if ($this instanceof EMSSecurityObject) {
 
228
                Ecl_Log::debug("Skipping ACL loading for EMSSecurityObject at dn :$dn");
 
229
            $aclreturn = array();
 
230
        } else {
 
231
            $emssec = new EMSSecurityObject($this->dn);
 
232
            $emssec->init();
 
233
            $aclreturn = $emssec->getEmsAclArray($newacls);
 
234
        }
 
235
        $this->emsaclarray = $aclreturn;
 
236
    }
 
237
 
 
238
    public function requireAcl($aclname)
 
239
    {
 
240
        if ($this->isNew())
 
241
            return true;   // This is WRONG, but necessary at the moment
 
242
 
 
243
        if (array_key_exists($aclname,$this->emsaclarray)) {
 
244
            $access = $this->emsaclarray[$aclname];
 
245
            if ($access == Ecl_Acl::ACCESS_GRANTED)
 
246
                Ecl_Log::info("Allowed access to ACL :$aclname to dn :".$this->getdn());
 
247
            else if ($access == Ecl_Acl::ACCESS_DENIED)
 
248
                throw new Ecl_AccessException("Access Denied to ACL : $aclname for dn ".$this->getdn());
 
249
            else {
 
250
                Ecl_Log::error("Acl Calculation Ambiguous! Acl :$aclname has access :$access for dn :".
 
251
                        $this->getdn());
 
252
            }
 
253
        } else
 
254
            throw new Ecl_Exception("Acl $aclname not initialized for dn :".$this->getdn());
 
255
    }
 
256
 
 
257
    protected function addAttrs($attrs,$skipmerge=0)
 
258
    {
 
259
        if ($attrs == null)
 
260
            return;
 
261
 
 
262
        if (!$skipmerge) {
 
263
            $newattrs = array_diff($attrs,$this->attrs);
 
264
            $this->attrs = array_merge($this->attrs,$newattrs);
 
265
            $this->attrs = array_values($this->attrs);
 
266
        } else
 
267
            $newattrs = $attrs;
 
268
 
 
269
        Ecl_Log::debug("****Added ATTRS: ".implode(",",$newattrs));
 
270
        if ($this instanceof EMSSecurityObject) {
 
271
                Ecl_Log::debug("Skipping ACL loading for EMSSecurityObject at dn :$this->dn");
 
272
                $acls = array();
 
273
        } else {
 
274
            $emssec = new EMSSecurityObject($this->dn);
 
275
            $emssec->init();
 
276
            $acls = $emssec->getAclArray($newattrs);
 
277
        }
 
278
 
 
279
        $entries = $this->loadLdapDn();
 
280
 
 
281
        foreach ($newattrs as $attr) {
 
282
            if ($this instanceof EMSSecurityObject || $this->isNew()) {
 
283
                $haswrite = $hasread = 1;
 
284
            } else {
 
285
                $hasread = preg_match("/\+".Ecl_Ldap_Aci::PERM_R."/",$acls[$attr]);
 
286
                $haswrite  = preg_match("/\+".Ecl_Ldap_Aci::PERM_W."/",$acls[$attr]);
 
287
            }
 
288
 
 
289
            if (is_array($entries) && array_key_exists($attr,$entries)) {
 
290
                $value = $entries[$attr];
 
291
                if ($value['count'] == 1)
 
292
                    $value = $value[0];
 
293
                else if ($value['count'] > 1)
 
294
                    $value = array_slice($value,1);
 
295
                else
 
296
                    $value = null;
 
297
            } else
 
298
                $value = null;
 
299
            $this->params[$attr] = new Ecl_Parameter($attr,$value,$hasread,$haswrite);
 
300
        }
 
301
    }
 
302
 
 
303
    public function getObject()
 
304
    {
 
305
        $dn = $this->dn;
 
306
        $modelclass = $this->getModelClass();
 
307
        Ecl_Log::debug("Found modelclass : " . $modelclass);
 
308
 
 
309
        if ($modelclass != null) {
 
310
            $obj = new $modelclass($dn);
 
311
            $obj->init();
 
312
            return $obj;
 
313
        } else
 
314
            throw new Ecl_Exception("No modelclass found for dn : ".$dn);
 
315
    }
 
316
 
 
317
    public function getProperty($name,$forcearray=0)
 
318
    {
 
319
        if (array_key_exists($name,$this->params)) {
 
320
            return $this->params[$name]->getValue($forcearray);
 
321
        } else {
 
322
            $bt = debug_backtrace();
 
323
 
 
324
            Ecl_Log::error("Parameter: " . $name . " not loaded by dn: " . $this->getdn() .
 
325
                " and classtype: " . get_class($this) . ". Called by: " . $bt[2]['class'] .
 
326
                " on line: " . $bt[1]['line']);
 
327
        }
 
328
    }
 
329
 
 
330
    public function getSecurityObject()
 
331
    {
 
332
        $emssec = new EMSSecurityObject($this->dn);
 
333
        $emssec->init();
 
334
        return $emssec;
 
335
    }
 
336
    public function getParameter($name)
 
337
    {
 
338
        if (array_key_exists($name,$this->params)) {
 
339
            return $this->params[$name];
 
340
        } else
 
341
                Ecl_Log::error("Parameter: " . $name . " not loaded.");
 
342
    }
 
343
 
 
344
    public function setProperty($name,$value)
 
345
    {
 
346
        $bt = debug_backtrace();
 
347
                $class = $bt[2]['class'];
 
348
                $line = $bt[1]['line'];
 
349
 
 
350
        Ecl_Log::debug("Set Property called with: " . $name . "=" . $value . " by " . $class . ":" . $line);
 
351
 
 
352
        if (array_key_exists($name,$this->params)){
 
353
            $retval = $this->params[$name]->setValue($value);
 
354
            if ($retval == "")
 
355
                return 0;
 
356
            else
 
357
                return $retval;
 
358
        } else
 
359
            throw new Ecl_Exception("Parameter: " . $name . " not loaded.");
 
360
    }
 
361
 
 
362
    public function addPropertyItem($name,$value)
 
363
    {
 
364
        $param = $this->getParameter($name);
 
365
        if ($param != null)
 
366
           return $param->addValue($value);
 
367
    }
 
368
 
 
369
    public function removePropertyItem($name,$value)
 
370
    {
 
371
        Ecl_Log::debug("Removing property Item: " . $name);
 
372
        $param = $this->getParameter($name);
 
373
 
 
374
        if ($param != null)
 
375
            return $param->removeValue($value);
 
376
    }
 
377
 
 
378
    public function addObjectClass($class)
 
379
    {
 
380
        $bt = debug_backtrace();
 
381
                $classcalling = $bt[2]['class'];
 
382
                $line = $bt[1]['line'];
 
383
        Ecl_Log::debug("Add objectclass called adding: " . $class . " by: " . $classcalling . ":" . $line);
 
384
        $param = $this->getParameter('objectclass');
 
385
        $param->addValue($class);
 
386
    }
 
387
 
 
388
    public function removeObjectClass($class)
 
389
    {
 
390
        $param = $this->getParameter('objectclass');
 
391
        $param->removeValue($class);
 
392
    }
 
393
 
 
394
    public static function loadDn($dn,$classname=null)
 
395
    {
 
396
        if ($dn == null) {
 
397
            $bt = debug_backtrace();
 
398
            $classcalling = $bt[2]['class'];
 
399
            $line = $bt[1]['line'];
 
400
            throw new Ecl_Exception("Attempt to load Null DN by: " . $classcalling . "::" . $line);
 
401
        }
 
402
        $testexist = new Ecl_Ldap_Engine($dn);
 
403
 
 
404
        if (!$testexist->exists())
 
405
                throw new Ecl_Exception("DN " . $dn . " does not exist in Ldap");
 
406
 
 
407
        if ($classname == null) {
 
408
            $obj = new Ecl_Ldap_Engine($dn);
 
409
            return $obj->getObject();
 
410
        } else if ($classname == 'NOMODEL') {
 
411
            $obj = new $classname($dn);
 
412
            $obj->init();
 
413
            return $obj;
 
414
        } else {
 
415
            $obj = new $classname($dn);
 
416
            $obj->init();
 
417
            return $obj;
 
418
        }
 
419
    }
 
420
 
 
421
    private function loadLdapDn()
 
422
    {
 
423
        $dn = $this->dn;
 
424
 
 
425
        if ($dn != null) {
 
426
            $filter = "(objectclass=*)";
 
427
            $entries = $this->search($filter,$this->attrs,$dn,"BASE");
 
428
 
 
429
            if ($entries['count'] < 1)
 
430
                throw new Ecl_Exception("dn: $dn does not exist in LDAP");
 
431
 
 
432
            return $entries[0];
 
433
        } else
 
434
            return null;
 
435
    }
 
436
 
 
437
    protected function reconnect($force=0)
 
438
    {
 
439
        if (!$this->conn || $force) {
 
440
            $this->connect();
 
441
        }
 
442
 
 
443
        if (!$this->resource || $force) {
 
444
            $usercreds = self::getUserCreds();
 
445
 
 
446
            if (isset($usercreds['auth']) && $usercreds['auth'] == 1) {
 
447
                if (!$this->bind($usercreds['dn'],$usercreds['password']))
 
448
                   throw new Ecl_Ldap_Exception("Reconnection as user :".$usercreds['dn']." Failed! ");
 
449
            } else
 
450
                Ecl_Log::info("Not Auth credentials, running anonymous");
 
451
        }
 
452
    }
 
453
 
 
454
    public function search($filter,$attrs=null,$base=null,$scope=null)
 
455
    {
 
456
        if ($base == null)
 
457
            $base = $this->ldapConfig->basedn;
 
458
 
 
459
        if ($scope == null)
 
460
            $scope = "SUB";
 
461
 
 
462
        if ($scope == "SUB")
 
463
                $call = 'ldap_search';
 
464
        else if ($scope == "ONE")
 
465
                $call = 'ldap_list';
 
466
        else
 
467
                $call = 'ldap_read';
 
468
 
 
469
        $attr_disp = implode(",",$attrs);
 
470
        Ecl_Log::debug("Executing search with filter : $filter, base $base and attrs $attr_disp");
 
471
 
 
472
                $results = $call($this->conn, $base, $filter, $attrs, 0, $this->ldapConfig->sizelimit,
 
473
                        $this->ldapConfig->timelimit, $this->ldapConfig->deref);
 
474
 
 
475
                return ldap_get_entries($this->conn, $results);
 
476
    }
 
477
 
 
478
        private function mod_add($data)
 
479
        {
 
480
        if (sizeof($data) > 0) {
 
481
            Ecl_Log::info("Attempting Ldap mod_add with dn: ".$this->dn);
 
482
            $debdata = print_r($data,1);
 
483
            Ecl_log::debug("mod add data : $debdata");
 
484
            $ret = ldap_mod_add($this->conn,$this->dn,$data);
 
485
 
 
486
            if (!$ret)
 
487
                            $this->getError();
 
488
            else
 
489
                Ecl_Log::info("Ldap mod_add successfull with dn: " . $this->dn);
 
490
        }
 
491
        }
 
492
 
 
493
        private function mod_del($data)
 
494
        {
 
495
        if (sizeof($data)>0) {
 
496
            $dataarr = print_r($data,1);
 
497
            Ecl_log::debug("Attempting mod del data with dn: ".$this->dn."  data : $dataarr");
 
498
            $ret = ldap_mod_del($this->conn,$this->dn,$data);
 
499
            if (!$ret)
 
500
                $this->getError();
 
501
            else
 
502
                Ecl_Log::info("Ldap mod_del successfull with dn: " . $this->dn);
 
503
        }
 
504
        }
 
505
 
 
506
        private function mod_replace($data)
 
507
        {
 
508
        if (sizeof($data) > 0) {
 
509
                Ecl_Log::info("Attempting Ldap mod_replace with dn: ".$this->dn);
 
510
            $debdata = print_r($data,1);
 
511
            Ecl_log::debug("mod replace data : $debdata");
 
512
                $ret = ldap_mod_replace($this->conn,$this->dn,$data);
 
513
            if (!$ret)
 
514
                                $this->getError();
 
515
                        else
 
516
                Ecl_Log::info("Ldap mod_replace successfull with dn: " . $this->dn);
 
517
        }
 
518
    }
 
519
 
 
520
        private function getError()
 
521
        {
 
522
                $error = ldap_error($this->conn);
 
523
                $errcode = ldap_errno($this->conn);
 
524
                throw new Ecl_Ldap_Exception("Ldap Caused Error",$error,$errcode);
 
525
        }
 
526
 
 
527
    public static function authenticate($uid=null,$dn=null,$password=null)
 
528
    {
 
529
        $engine = new Ecl_Ldap_Engine();
 
530
 
 
531
        if ($dn == null) {
 
532
            $dn = $engine->searchDn($uid);
 
533
            Ecl_Log::debug("Auth got dn :$dn");
 
534
        }
 
535
 
 
536
        if ($engine->bind($dn,$password)) {
 
537
            $_userSession = new Zend_Session_Namespace("userSession");
 
538
            $securityConfig = Zend_Registry::get('securityConfig');
 
539
                        $_userSession->password = Ecl_Security::encrypt($password);
 
540
            $_userSession->user_dn = $dn;
 
541
            $_userSession->uid = $uid;
 
542
 
 
543
            /**
 
544
             * Regenerate Session ID and Set Auth to true.
 
545
             */
 
546
            Zend_Session::regenerateId();
 
547
            $_userSession->auth = 1;
 
548
            $_userSession->setExpirationSeconds($securityConfig->inactivity_timeout, 'auth');
 
549
 
 
550
            return true;
 
551
        }
 
552
    }
 
553
 
 
554
    public function __wakeup()
 
555
    {
 
556
                $this->reconnect(1);
 
557
                $this->wakeup();
 
558
        }
 
559
 
 
560
        public function wakeup()
 
561
        {
 
562
 
 
563
        }
 
564
 
 
565
    private function connect()
 
566
    {
 
567
        if (!$this->conn = ldap_connect($this->ldapConfig->host, $this->ldapConfig->port))
 
568
                throw new Ecl_Ldap_Exception("Connection to server ".$this->ldapConfig->host." failed");
 
569
 
 
570
        if (!ldap_set_option($this->conn, LDAP_OPT_PROTOCOL_VERSION, $this->ldapConfig->protocol))
 
571
                throw new Ecl_Ldap_Exception("LDAP Protocol version failed.");
 
572
 
 
573
        if (!ldap_set_option($this->conn, LDAP_OPT_DEREF, $this->ldapConfig->deref))
 
574
                throw new Ecl_Ldap_Exception("Could not set DEREF option.");
 
575
 
 
576
        return true;
 
577
    }
 
578
 
 
579
    private function searchDn($uid)
 
580
    {
 
581
       if (isset($uid)) {
 
582
                        /**
 
583
                         * Search for user ID
 
584
                         */
 
585
                        $filter = '(uid='.$uid.')';
 
586
                        Ecl_Log::debug("LDAP Uid searching for uid = $filter");
 
587
 
 
588
                        $return = array('dn');
 
589
                        $rst = ldap_search($this->conn, $this->ldapConfig->basedn,$filter,$return);
 
590
                        $uidInfo = ldap_get_entries($this->conn, $rst);
 
591
 
 
592
                        if ($uidInfo["count"] > 1) {
 
593
                            /**
 
594
                             * More than 1 ID returned -- this is a problem unless
 
595
                             * of course deref should have been set.
 
596
                             */
 
597
                            throw new Ecl_Ldap_Exception("FATAL::More than one unique ID
 
598
                                returned. Should deref be true?");
 
599
                        } elseif ($uidInfo["count"] == 0) {
 
600
                            Ecl_Log::error("LDAP: User not found. Authentication failed");
 
601
                            throw new Ecl_Exception("User: " . $uid . " not found. Authentication Failed");
 
602
                        } else {
 
603
                            /**
 
604
                             * User found, try and bind with the established credentials
 
605
                             */
 
606
                            $dn = $uidInfo[0]["dn"];
 
607
                            return $dn;
 
608
                        }
 
609
        }
 
610
    }
 
611
 
 
612
        protected function bind($dn=null,$password=null)
 
613
        {
 
614
 
 
615
        if (isset($dn)) {
 
616
            if (!$this->resource = ldap_bind($this->conn, $dn,$password)) {
 
617
                Ecl_Log::error("LDAP: Authentication Failed as: " . $dn);
 
618
                return false;
 
619
            } else {
 
620
                Ecl_Log::debug("LDAP: Authentication Successful as: " . $dn);
 
621
               return true;
 
622
            }
 
623
        } else {
 
624
             if (ldap_bind($this->conn)) {
 
625
                                Ecl_Log::debug("LDAP: Anonymous Auth Successful");
 
626
                                return true;
 
627
             } else {
 
628
                Ecl_Log::error("LDAP: Anonymous Auth disallowed");
 
629
                return false;
 
630
             }
 
631
        }
 
632
        }
 
633
 
 
634
    private function smartupdate(&$array,$key,$val)
 
635
        {
 
636
                $value = array();
 
637
 
 
638
                if (!is_array($val))
 
639
                        $value[] = $val;
 
640
                else
 
641
                        $value = $val;
 
642
 
 
643
                if (array_key_exists($key,$array)) {
 
644
                        if (is_array($array[$key]))
 
645
                                $array[$key] = array_merge($array[$key],$value);
 
646
                        else {
 
647
                                $currvalue = $array[$key];
 
648
                                array_push($value,$currvalue);
 
649
                                $array[$key] = $value;
 
650
                        }
 
651
                } else
 
652
                        $array[$key] = $val;
 
653
 
 
654
                return $array;
 
655
        }
 
656
 
 
657
    public function addItem($name,$value)
 
658
        {
 
659
                $this->smartupdate($this->_addarray,$name,$value);
 
660
        }
 
661
 
 
662
        public function updateItem($name,$value)
 
663
        {
 
664
                $this->smartupdate($this->_modarray,$name,$value);
 
665
 
 
666
        }
 
667
 
 
668
        public function removeItem($name,$value)
 
669
        {
 
670
                $this->smartupdate($this->_delarray,$name,$value);
 
671
        }
 
672
 
 
673
        public function deleteItem($name,$value)
 
674
        {
 
675
                $this->smartupdate($this->_delarray,$name,$value);
 
676
        }
 
677
 
 
678
    private function prepare()
 
679
        {
 
680
                $paramarray = $this->params;
 
681
 
 
682
                foreach ($paramarray as $param) {
 
683
 
 
684
                        Ecl_Log::debug("Iterating for: " . $param->getId() . " and getchange is: " . $param->getChange());
 
685
                        Ecl_Log::debug($param->getValue());
 
686
                        Ecl_Log::debug("End parameter debug");
 
687
 
 
688
                        if (!$param->hasValidValue())
 
689
                                throw new Ecl_Exception("Invalid value in parameter: " . $param->getId());
 
690
 
 
691
                        if ($param->getChange() == Ecl_Parameter::CHANGE_ADDED) {
 
692
                                        $this->addItem($param->getId(),$param->getValue());
 
693
                                        $param->setPrepared();
 
694
                                        $this->dirty_params[] = $param;
 
695
                        } else if ($param->getChange() == Ecl_Parameter::CHANGE_UPDATED && $param->getValue() != null) {
 
696
                $this->updateItem($param->getId(),$param->getValue());
 
697
                $param->setPrepared();
 
698
                        $this->dirty_params[] = $param;
 
699
                        } else if (($param->getChange() == Ecl_Parameter::CHANGE_UPDATED) && $param->getValue() == null) {
 
700
                $this->deleteItem($param->getId(),$param->getOldValue());
 
701
                $param->setPrepared();
 
702
                                $this->dirty_params[] = $param;
 
703
                        } else if ($param->getChange() == Ecl_Parameter::CHANGE_MULTIVALUEDADD) {
 
704
                $this->addItem($param->getId(),$param->getMultiValuesAdded());
 
705
                $param->setPrepared();
 
706
                        $this->dirty_params[] = $param;
 
707
                        } else if ($param->getChange() == Ecl_Parameter::CHANGE_MULTIVALUEDREMOVE ) {
 
708
                $this->removeItem($param->getId(),$param->getMultiValuesRemoved());
 
709
                $param->setPrepared();
 
710
                $this->dirty_params[] = $param;
 
711
                        } else if ($param->getChange() == Ecl_Parameter::CHANGE_MULTIVALUEDADDREMOVE ) {
 
712
                $this->removeItem($param->getId(),$param->getMultiValuesRemoved());
 
713
                $this->addItem($param->getId(),$param->getMultiValuesAdded());
 
714
                $param->setPrepared();
 
715
                            $this->dirty_params[] = $param;
 
716
                        }
 
717
                }
 
718
        }
 
719
 
 
720
    public function add(Ecl_Ldap_Engine $parent,Ecl_Transaction_Handler $handler=null,$description=null)
 
721
        {
 
722
 
 
723
        $modelclass = get_class($this);
 
724
                $this->setProperty('emsmodelclass',$modelclass);
 
725
 
 
726
        if ($handler == null) {
 
727
                        $handler = $this->getTransaction();
 
728
                }
 
729
 
 
730
        $this->parent = $parent;
 
731
        $this->makedn = $this->makeDn($parent);
 
732
 
 
733
        if ($description == null)
 
734
                        $description = "Adding a: " . get_class($this) . " to LDAP with dn: " . $this->getdn();
 
735
 
 
736
                $titem = new Ecl_Transaction_Item($description);
 
737
 
 
738
                $titem->addObject('ldapobject',$this);
 
739
                $titem->addObject('parent',$parent);
 
740
                $titem->addCommitLine('$this->ldapobject->postAdd($this->parent);');
 
741
        $titem->addCommitLine('$this->ldapobject->fireParameterEvents();');
 
742
                $titem->addRollbackLine('$this->ldapobject->radd();');
 
743
                $handler->addTransactionItem($titem);
 
744
                return $handler;
 
745
    }
 
746
 
 
747
    public function fireParameterEvents()
 
748
    {
 
749
        foreach ($this->dirty_params as $param) {
 
750
            $this->fireEvent("CORE_PCHANGE_".strtoupper($param->getId()));
 
751
            $param->flush();
 
752
        }
 
753
 
 
754
        $this->flushEvents();
 
755
    }
 
756
 
 
757
 
 
758
    public function flushLdap()
 
759
    {
 
760
        $this->_addarray = array();
 
761
        $this->_delarray = array();
 
762
        $this->_modarray = array();
 
763
    }
 
764
 
 
765
    public function flushEvents()
 
766
    {
 
767
        $this->dirty_params = array();
 
768
    }
 
769
 
 
770
    public function flush()
 
771
    {
 
772
        $this->flushLdap();
 
773
        $this->flushEvents();
 
774
    }
 
775
 
 
776
 
 
777
    public function postAdd(Ecl_Ldap_Engine $parent)
 
778
    {
 
779
        $this->prepare();
 
780
                $printadd = print_r($this->_addarray,1);
 
781
 
 
782
                Ecl_Log::debug("Adding: " . $printadd);
 
783
 
 
784
        $ret = ldap_add($this->conn,$this->makedn,$this->_addarray);
 
785
        $this->flushLdap();
 
786
 
 
787
                if (!$ret)
 
788
                        $this->getError();
 
789
                else {
 
790
            Ecl_Log::info("Ldap add successfull with dn:".$this->makedn);
 
791
            $this->dn = $this->makedn;
 
792
            unset($this->makedn);
 
793
        }
 
794
        }
 
795
 
 
796
    public function update(Ecl_Transaction_Handler $handler=null,$description=null)
 
797
        {
 
798
                if ($handler == null)
 
799
                        $handler = $this->getTransaction();
 
800
 
 
801
                $transaction = $handler;
 
802
 
 
803
                if ($description == null)
 
804
                        $description = "Updating: ".get_class($this)."  in LDAP with dn::".$this->getdn();
 
805
 
 
806
                $titem = new Ecl_Transaction_Item($description);
 
807
                $titem->addObject('ldapobject',$this);
 
808
                $titem->addCommitLine('$this->ldapobject->postUpdate();');
 
809
        $titem->addCommitLine('$this->ldapobject->fireParameterEvents();');
 
810
                $titem->addRollbackLine('$this->ldapobject->rupdate();');
 
811
                $transaction->addTransactionItem($titem);
 
812
                return $transaction;
 
813
        }
 
814
 
 
815
    public function fireEventLater($eventname,Ecl_Transaction_Handler $handler=null,$description=null)
 
816
    {
 
817
        if ($handler == null) {
 
818
                        $handler = $this->getTransaction();
 
819
            Ecl_Log::info("Warning: FireEventLater called with Null transaction handler, " .
 
820
                " make sure this is what you WANT");
 
821
                }
 
822
 
 
823
                if ($description == null)
 
824
                        $description = "Event: " . $eventname . " fired on " . get_class($this) . " dn: ". $this->getdn();
 
825
 
 
826
        $titem = new Ecl_Transaction_Item($description);
 
827
                $titem->addObject('ldapobject',$this);
 
828
        $titem->addCommitLine('$this->ldapobject->fireEvent("'.$eventname.'");');
 
829
        $handler->addTransactionItem($titem);
 
830
        return $handler;
 
831
    }
 
832
 
 
833
        public function rupdate()
 
834
        {
 
835
                foreach ($this->params as $param)
 
836
                        $param->toUpdateRollbackMode();
 
837
 
 
838
                $handler = new Ecl_Transaction_Handler();
 
839
                $handler->setRollbackMode();
 
840
                $handler = $this->update($handler);
 
841
                $handler->process();
 
842
        }
 
843
 
 
844
        protected function groupPolicyCheck($paramarray)
 
845
        {
 
846
                // Check and return 1 if group policies are okay. This is
 
847
                // a generic GP check
 
848
 
 
849
        }
 
850
 
 
851
        public function isNew()
 
852
    {
 
853
        return $this->isnew;
 
854
    }
 
855
 
 
856
        public function delete(Ecl_Transaction_Handler $transaction=null,$description=null)
 
857
        {
 
858
                if ($transaction == null)
 
859
                        $transaction = $this->getTransaction();
 
860
 
 
861
                if ($description == null)
 
862
                        $description = "Deleting: " . get_class($this) . " from Ldap with dn: " . $this->getdn();
 
863
 
 
864
                $titem = new Ecl_Transaction_Item($description);
 
865
                $titem->addObject('ldapobject',$this);
 
866
                $titem->addObject('emsparent',$this->getParent());
 
867
                $titem->addCommitLine('$this->ldapobject->postDelete();');
 
868
                $titem->addRollbackLine('$this->ldapobject->rdelete($this->emsparent);');
 
869
                $transaction->addTransactionItem($titem);
 
870
 
 
871
                return $transaction;
 
872
        }
 
873
 
 
874
        public function getTransaction()
 
875
        {
 
876
                if ($this->transaction == null || $this->transaction->isCommitted())
 
877
                        $this->transaction = new Ecl_Transaction_Handler();
 
878
 
 
879
                return $this->transaction;
 
880
        }
 
881
 
 
882
    public function getdn()
 
883
        {
 
884
                $dn = $this->dn;
 
885
 
 
886
        if ($dn == '')
 
887
            return $this->makedn;
 
888
        else
 
889
                return $dn;
 
890
        }
 
891
 
 
892
        public function getParent()
 
893
        {
 
894
        $appConfig = Zend_Registry::get('ldapConfig');
 
895
 
 
896
        if ($this->getdn() == $appConfig->basedn) {
 
897
            return null;
 
898
        }
 
899
 
 
900
                $tokendn = explode(',',$this->getdn());
 
901
                $parentdnarray = array_slice($tokendn,1);
 
902
                $parentdn = implode(',',$parentdnarray);
 
903
                return Ecl_Ldap_Cache::loadDn($parentdn);
 
904
 
 
905
        }
 
906
 
 
907
        protected function getrdn()
 
908
        {
 
909
                return 'o';
 
910
        }
 
911
 
 
912
        protected function makeDn($parent)
 
913
        {
 
914
                return $this->getrdn().'='.$this->params[$this->getrdn()]->getValue().','.$parent->getdn();
 
915
        }
 
916
 
 
917
        public function postUpdate()
 
918
        {
 
919
                /**
 
920
                * We need to intelligently build a list using the add,mod and del
 
921
                * arrays for a successful ldap mod_add operation.
 
922
                * Note that update and add will function differently with the
 
923
                * _addarray and _modarray when called. This is intentional
 
924
                * You must use the functions properly. With great power comes
 
925
                * great responsibility
 
926
                */
 
927
 
 
928
                /**
 
929
                * It is assumed that the user object has correctly filled
 
930
                * the arrays. using add item means the user wants the items
 
931
                * ADDED. This applies even to multi valued arrays. To add
 
932
                * a new multi valued array item in ldap- the user object
 
933
                * MUST use additem function. to modify existing entry, use
 
934
                * the mod item function
 
935
                */
 
936
                $this->prepare();
 
937
 
 
938
                $this->mod_del($this->_delarray,$this->dn);
 
939
                $this->mod_replace($this->_modarray,$this->dn);
 
940
                $this->mod_add($this->_addarray,$this->dn);
 
941
        $this->flushLdap();
 
942
        }
 
943
 
 
944
    public function getImmediateChildren($filter=null,$emsIgnore=false)
 
945
        {
 
946
        return $this->getAllChildren($filter,'ONE',$emsIgnore);
 
947
    }
 
948
 
 
949
    public function getAllChildren($filter=null,$scope='SUB',$emsIgnore=false,$basedn=null)
 
950
    {
 
951
                /**
 
952
                 * By ignoring OBJECTCLASS emsIgnore, we ensure there is no wastage
 
953
                 * in generating tree objects which are not required for display (like
 
954
                 * plugin entries housed in ldap)
 
955
                 *
 
956
                 * @note: the filter below needs the action plugin object to ignore.
 
957
                 */
 
958
 
 
959
         if ($basedn == null)
 
960
             $basedn = $this->dn;
 
961
 
 
962
         if ($filter == null) {
 
963
            if ($emsIgnore == false)
 
964
                $filter = '(objectclass=emsobject)';
 
965
            else {
 
966
                $filter =
 
967
                '(&(!(objectclass=emsIgnore))(objectclass=emsobject))';
 
968
            }
 
969
         }
 
970
 
 
971
                Ecl_Log::debug("Calling getAllChildren with filter " .
 
972
                        $filter);
 
973
 
 
974
                /**
 
975
                 * Generate immediate children objects.
 
976
                 */
 
977
 
 
978
                $entries = $this->search($filter,array('dn'),$basedn,$scope);
 
979
 
 
980
 
 
981
                /**
 
982
                 * If a manual sort is run on the returned result, please ignore
 
983
                 * keys 0 and 1 as they (may) house EMSControl or ServiceContainer
 
984
                 * object types which should be listed before other entries appear.
 
985
                 *
 
986
                 * This is simply for a more consistent view of the tree.
 
987
                 */
 
988
                $result = array();
 
989
                $result_merge = array();
 
990
 
 
991
                $c = 0;
 
992
                $z = 1;
 
993
                for ($i=0;$i<$entries['count'];$i++) {
 
994
                        $objdn = $entries[$i]['dn'];
 
995
            if ($objdn != $this->dn) {
 
996
                try {
 
997
                        $objiter = Ecl_Ldap_Cache::loadDn($objdn);
 
998
 
 
999
                        $tmp_get = $objiter;
 
1000
 
 
1001
                        if ($tmp_get->getProperty('emstype') == 'ZiviosContainer') {
 
1002
                            $result_merge[0] = $tmp_get;
 
1003
                        } else if ($tmp_get->getProperty('emstype') == 'ServiceContainer') {
 
1004
                            $result_merge[$z] = $tmp_get;
 
1005
                            $z++;
 
1006
                        } else {
 
1007
                            $result[$c] = $tmp_get;
 
1008
                            $c++;
 
1009
                        }
 
1010
                } catch (Ecl_AccessException $e) {
 
1011
                        Ecl_Log::info("Loading " .$objdn. " threw Exception : " .
 
1012
                                        $e->getTraceAsString() . " ::: Ignoring");
 
1013
                }
 
1014
            }
 
1015
                }
 
1016
                ksort(&$result_merge);
 
1017
                return array_merge($result_merge, $result);
 
1018
        }
 
1019
 
 
1020
        public function postDelete()
 
1021
        {
 
1022
                $ret = ldap_delete($this->conn,$this->dn);
 
1023
                if (!$ret)
 
1024
                        $this->getError();
 
1025
        }
 
1026
 
 
1027
    public static function getUserCreds()
 
1028
        {
 
1029
                /**
 
1030
                 * @return array (with user credentials)
 
1031
                 */
 
1032
                $userSession = new Zend_Session_Namespace("userSession");
 
1033
                return array(
 
1034
                        'password' => Ecl_Security::decrypt($userSession->password),
 
1035
                        'dn' => $userSession->user_dn,
 
1036
                        'uid' => $userSession->uid,
 
1037
            'auth' => $userSession->auth);
 
1038
        }
 
1039
}