PageRenderTime 237ms CodeModel.GetById 187ms app.highlight 25ms RepoModel.GetById 8ms app.codeStats 0ms

/tine20/Tinebase/Auth.php

https://github.com/testruby/Tine-2.0-Open-Source-Groupware-and-CRM
PHP | 397 lines | 176 code | 45 blank | 176 comment | 32 complexity | e286cde03494baa1cb2f9127d95c8e1b MD5 | raw file
  1<?php
  2/**
  3 * Tine 2.0
  4 * 
  5 * @package     Tinebase
  6 * @subpackage  Auth
  7 * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
  8 * @copyright   Copyright (c) 2007-2010 Metaways Infosystems GmbH (http://www.metaways.de)
  9 * @author      Lars Kneschke <l.kneschke@metaways.de>
 10 */
 11
 12/**
 13 * main authentication class
 14 * 
 15 * @todo 2010-05-20 cweiss: the default option handling looks like a big mess -> someone needs to tidy up here!
 16 * 
 17 * @package     Tinebase
 18 * @subpackage  Auth 
 19 */
 20
 21class Tinebase_Auth
 22{
 23    /**
 24     * constant for Sql auth
 25     *
 26     */
 27    const SQL = 'Sql';
 28    
 29    /**
 30     * constant for LDAP auth
 31     *
 32     */
 33    const LDAP = 'Ldap';
 34
 35    /**
 36     * constant for IMAP auth
 37     *
 38     */
 39    const IMAP = 'Imap';
 40
 41    /**
 42     * General Failure
 43     */
 44    const FAILURE                       =  Zend_Auth_Result::FAILURE;
 45
 46    /**
 47     * Failure due to identity not being found.
 48     */
 49    const FAILURE_IDENTITY_NOT_FOUND    = Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND;
 50
 51    /**
 52     * Failure due to identity being ambiguous.
 53     */
 54    const FAILURE_IDENTITY_AMBIGUOUS    = Zend_Auth_Result::FAILURE_IDENTITY_AMBIGUOUS;
 55
 56    /**
 57     * Failure due to invalid credential being supplied.
 58     */
 59    const FAILURE_CREDENTIAL_INVALID    = Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID;
 60
 61    /**
 62     * Failure due to uncategorized reasons.
 63     */
 64    const FAILURE_UNCATEGORIZED         = Zend_Auth_Result::FAILURE_UNCATEGORIZED;
 65    
 66    /**
 67     * Failure due the account is disabled
 68     */
 69    const FAILURE_DISABLED              = -100;
 70
 71    /**
 72     * Failure due the account is expired
 73     */
 74    const FAILURE_PASSWORD_EXPIRED      = -101;
 75    
 76    /**
 77     * Failure due the account is temporarly blocked
 78     */
 79    const FAILURE_BLOCKED               = -102;
 80        
 81    /**
 82     * database connection failure
 83     */
 84    const FAILURE_DATABASE_CONNECTION   = -103;
 85        
 86    /**
 87     * Authentication success.
 88     */
 89    const SUCCESS                        =  Zend_Auth_Result::SUCCESS;
 90
 91    /**
 92     * the name of the authenticationbackend
 93     *
 94     * @var string
 95     */
 96    protected static $_backendType;
 97    
 98    /**
 99     * Holds the backend configuration options.
100     * Property is lazy loaded from {@see Tinebase_Config} on first access via
101     * getter {@see getBackendConfiguration()}
102     * 
103     * @var array | optional
104     */
105    private static $_backendConfiguration;
106    
107    /**
108     * Holds the backend configuration options.
109     * Property is lazy loaded from {@see Tinebase_Config} on first access via
110     * getter {@see getBackendConfiguration()}
111     * 
112     * @var array | optional
113     */
114    private static $_backendConfigurationDefaults = array(
115        self::SQL => array(
116        	'tryUsernameSplit' => '1',
117            'accountCanonicalForm' => '2',
118            'accountDomainName' => '',
119            'accountDomainNameShort' => '',
120        ),
121        self::LDAP => array(
122            'host' => '',
123            'username' => '',
124            'password' => '',
125            'bindRequiresDn' => true,
126            'baseDn' => '',
127            'accountFilterFormat' => NULL,
128            'accountCanonicalForm' => '2',
129            'accountDomainName' => '',
130            'accountDomainNameShort' => '',
131         ),
132         self::IMAP => array(
133            'host'      => '',
134            'port'      => 143,
135            'ssl'       => 'tls',
136            'domain'    => '',
137         ),
138     );
139    
140    /**
141     * the instance of the authenticationbackend
142     *
143     * @var Tinebase_Auth_Interface
144     */
145    protected $_backend;
146    
147    /**
148     * the constructor
149     *
150     * don't use the constructor. use the singleton 
151     */
152    private function __construct() {
153        $this->setBackend();
154    }
155    
156    /**
157     * don't clone. Use the singleton.
158     *
159     */
160    private function __clone() {}
161
162    /**
163     * holds the instance of the singleton
164     *
165     * @var Tinebase_Auth
166     */
167    private static $_instance = NULL;
168    
169    /**
170     * the singleton pattern
171     *
172     * @return Tinebase_Auth
173     */
174    public static function getInstance() 
175    {
176        if (self::$_instance === NULL) {
177            self::$_instance = new Tinebase_Auth;
178        }
179        
180        return self::$_instance;
181    }
182    
183    /**
184     * authenticate user
185     *
186     * @param string $_username
187     * @param string $_password
188     * @return Zend_Auth_Result
189     */
190    public function authenticate($_username, $_password)
191    {
192        if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Trying to authenticate '. $_username);
193        
194        $this->_backend->setIdentity($_username);
195        $this->_backend->setCredential($_password);
196        
197        $result = Zend_Auth::getInstance()->authenticate($this->_backend);
198        
199        if($result->isValid()) {
200            if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Authentication of '. $_username . ' succeeded');
201        } else {
202            if (Tinebase_Core::isLogLevel(Zend_Log::WARN)) Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' Authentication of '. $_username . ' failed');
203        }
204        
205        return $result;
206    }
207    
208    /**
209     * check if password is valid
210     *
211     * @param string $_username
212     * @param string $_password
213     * @return boolean
214     */
215    public function isValidPassword($_username, $_password)
216    {
217        $this->_backend->setIdentity($_username);
218        $this->_backend->setCredential($_password);
219        
220        $result = $this->_backend->authenticate();
221
222        if ($result->isValid()) {
223            return true;
224        }
225        
226        return false;
227    }
228    
229    /**
230     * returns the configured rs backend
231     * 
232     * @return string
233     */
234    public static function getConfiguredBackend()
235    {
236        if (!isset(self::$_backendType)) {
237            if (Setup_Controller::getInstance()->isInstalled('Tinebase')) {
238                self::setBackendType(Tinebase_Config::getInstance()->getConfig(Tinebase_Config::AUTHENTICATIONBACKENDTYPE, null, self::SQL)->value);
239            } else {
240                self::setBackendType(self::SQL); 
241            }
242        }
243        
244        return self::$_backendType;
245    }
246    
247    /**
248     * set the auth backend
249     */
250    public function setBackend()
251    {
252        $backendType = self::getConfiguredBackend();
253        if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ .' authentication backend: ' . $backendType);
254        $this->_backend = Tinebase_Auth_Factory::factory($backendType);        
255    }
256    
257    /**
258     * setter for {@see $_backendType}
259     * 
260     * @todo persist in db
261     * 
262     * @param string $_backendType
263     * @return void
264     */
265    public static function setBackendType($_backendType)
266    {
267        self::$_backendType = ucfirst($_backendType);
268    }
269    
270    /**
271     * Setter for {@see $_backendConfiguration}
272     * 
273     * NOTE:
274     * Setting will not be written to Database or Filesystem.
275     * To persist the change call {@see saveBackendConfiguration()}
276     * 
277     * @param mixed $_value
278     * @param string  optional $_key
279     * @return void
280     */
281    public static function setBackendConfiguration($_value, $_key = null)
282    {
283        $defaultValues = self::$_backendConfigurationDefaults[self::getConfiguredBackend()];
284
285        if (is_null($_key) && !is_array($_value)) {
286            throw new Tinebase_Exception_InvalidArgument('To set backend configuration either a key and value parameter are required or the value parameter should be a hash');
287        } elseif (is_null($_key) && is_array($_value)) {
288            foreach ($_value as $key=> $value) {
289                self::setBackendConfiguration($value, $key);
290            }
291        } else {
292            if ( ! array_key_exists($_key, $defaultValues)) {
293                throw new Tinebase_Exception_InvalidArgument("Cannot set backend configuration option '$_key' for authentication provider " . self::getConfiguredBackend());
294            }
295            self::$_backendConfiguration[$_key] = $_value;
296        }
297    }
298    
299    /**
300     * Delete the given config setting or all config settings if {@param $_key} is not specified
301     * 
302     * @param string | optional $_key
303     * @return void
304     */
305    public static function deleteBackendConfiguration($_key = null)
306    {
307        if (is_null($_key)) {
308            self::$_backendConfiguration = array();
309        } elseif (array_key_exists($_key, self::$_backendConfiguration)) {
310            unset(self::$_backendConfiguration[$_key]);
311        } else {
312            Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' configuration option does not exist: ' . $_key);
313        }
314    }
315    
316    /**
317     * Write backend configuration setting {@see $_backendConfigurationSettings} and {@see $_backendType} to
318     * db config table.
319     * 
320     * @return void
321     */
322    public static function saveBackendConfiguration()
323    {
324        Tinebase_Config::getInstance()->setConfigForApplication(Tinebase_Config::AUTHENTICATIONBACKEND, Zend_Json::encode(self::getBackendConfiguration()));
325        Tinebase_Config::getInstance()->setConfigForApplication(Tinebase_Config::AUTHENTICATIONBACKENDTYPE, self::getConfiguredBackend());
326    }
327    
328    /**
329     * Getter for {@see $_backendConfiguration}
330     * 
331     * @param boolean $_getConfiguredBackend
332     * @return mixed [If {@param $_key} is set then only the specified option is returned, otherwise the whole options hash]
333     */
334    public static function getBackendConfiguration($_key = null, $_default = null)
335    {
336        //lazy loading for $_backendConfiguration
337        if (!isset(self::$_backendConfiguration)) {
338            if (Setup_Controller::getInstance()->isInstalled('Tinebase')) {
339                $rawBackendConfiguration = Tinebase_Config::getInstance()->getConfig(Tinebase_Config::AUTHENTICATIONBACKEND, null, array())->value;
340            } else {
341                $rawBackendConfiguration = array();
342            }
343            self::$_backendConfiguration = is_array($rawBackendConfiguration) ? $rawBackendConfiguration : Zend_Json::decode($rawBackendConfiguration);
344        }
345
346        if (isset($_key)) {
347            return array_key_exists($_key, self::$_backendConfiguration) ? self::$_backendConfiguration[$_key] : $_default; 
348        } else {
349            return self::$_backendConfiguration;
350        }
351    }
352    
353    /**
354     * Returns default configuration for all supported backends 
355     * and overrides the defaults with concrete values stored in this configuration 
356     * 
357     * @param String | optional $_key
358     * @return mixed [If {@param $_key} is set then only the specified option is returned, otherwise the whole options hash]
359     */
360    public static function getBackendConfigurationWithDefaults($_getConfiguredBackend = TRUE)
361    {
362        $config = array();
363        $defaultConfig = self::getBackendConfigurationDefaults();
364        foreach ($defaultConfig as $backendType => $backendConfig) {
365            $config[$backendType] = ($_getConfiguredBackend && $backendType == self::getConfiguredBackend() ? self::getBackendConfiguration() : array());
366            if (is_array($config[$backendType])) {
367                foreach ($backendConfig as $key => $value) {
368                    // 2010-05-20 cweiss Zend_Ldap changed and does not longer throw exceptions
369                    // on unsupported values, we might skip this cleanup here.
370                    if (! array_key_exists($key, $config[$backendType])) {
371                        $config[$backendType][$key] = $value;
372                    }
373                }
374            } else {
375                $config[$backendType] = $backendConfig;
376            }
377        }
378        return $config;
379    }
380    
381    /**
382     * Getter for {@see $_backendConfigurationDefaults}
383     * @param String | optional $_backendType
384     * @return array
385     */
386    public static function getBackendConfigurationDefaults($_backendType = null) {
387        if ($_backendType) {
388            if (!array_key_exists($_backendType, self::$_backendConfigurationDefaults)) {
389                throw new Tinebase_Exception_InvalidArgument("Unknown backend type '$_backendType'");
390            }
391            return self::$_backendConfigurationDefaults[$_backendType]; 
392        } else {
393            return self::$_backendConfigurationDefaults;
394        }
395    }
396    
397}