PageRenderTime 58ms CodeModel.GetById 24ms RepoModel.GetById 4ms app.codeStats 1ms

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