Core  3.2
PHP API documentation
 All Data Structures Namespaces Files Functions Variables Pages
Class.AuthenticatorManager.php
Go to the documentation of this file.
1 <?php
2 /*
3  * @author Anakeen
4  * @package FDL
5 */
6 /**
7  * Authenticator manager class
8  *
9  * Manage authentification method (classes)
10  *
11  * @author Anakeen
12  * @version $Id: Class.Authenticator.php,v 1.6 2009/01/16 13:33:00 jerome Exp $
13  * @package FDL
14  * @subpackage
15  */
16 /**
17  */
18 
19 include_once ('WHAT/Lib.Common.php');
20 include_once ('WHAT/Class.Authenticator.php');
21 include_once ('WHAT/Class.Session.php');
22 include_once ('WHAT/Class.User.php');
23 include_once ('WHAT/Class.Log.php');
24 
26 {
27  /**
28  * @var \Session
29  */
30  public static $session = null;
31  const AccessBug = - 1;
32  const AccessOk = 0;
38  const NeedAsk = 6;
39  /**
40  * @var Authenticator|htmlAuthenticator|openAuthenticator
41  */
42  public static $auth = null;
43  public static $provider_errno = 0;
44 
45  public static function checkAccess($authtype = null, $noask = false)
46  {
47  /*
48  * Part 1: check authentication
49  */
50  $status = self::checkAuthentication($authtype, $noask);
52  $error = 1;
53  $providerErrno = self::$auth->getProviderErrno();
54  if ($providerErrno != 0) {
55  self::$provider_errno = $providerErrno;
56  switch ($providerErrno) {
58  // User must change his password
59  $error = self::AccessBug;
60  break;
61  }
62  }
63  $remote_addr = isset($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : "";
64  $auth_user = isset($_REQUEST["auth_user"]) ? $_REQUEST["auth_user"] : "";
65  $http_user_agent = isset($_SERVER["HTTP_USER_AGENT"]) ? $_SERVER["HTTP_USER_AGENT"] : "";
66  self::secureLog("failure", "invalid credential", self::$auth->provider->parms['type'] . "/" . self::$auth->provider->parms['provider'], $remote_addr, $auth_user, $http_user_agent);
67  // count login failure
68  if (getParam("AUTHENT_FAILURECOUNT") > 0) {
69  $wu = new Account();
70  if ($wu->SetLoginName(self::$auth->getAuthUser())) {
71  if ($wu->id != 1) {
72  include_once ("FDL/freedom_util.php");
73  /**
74  * @var \Dcp\Family\IUSER $du
75  */
76  $du = new_Doc(getDbAccess() , $wu->fid);
77  if ($du->isAlive()) {
78  $du->disableEditControl();
79  $du->increaseLoginFailure();
80  $du->enableEditControl();
81  }
82  }
83  }
84  }
85  self::clearGDocs();
86  return $error;
87  }
88  // Authentication success
89  /*
90  * Part 2: check authorization
91  */
92  $ret = self::checkAuthorization();
93  if ($ret !== self::AccessOk) {
94  return $ret;
95  }
96 
97  $login = AuthenticatorManager::$auth->getAuthUser();
98  /*
99  * All authenticators are not necessarily based on sessions (i.e. 'basic')
100  */
101  if (method_exists(self::$auth, 'getAuthSession')) {
102  self::$session = self::$auth->getAuthSession();
103  /**
104  * @var self::$session Session
105  */
106  if (self::$session->read('username') == "") {
107  self::secureLog("failure", "username should exists in session", $authprovider = "", $_SERVER["REMOTE_ADDR"], $login, $_SERVER["HTTP_USER_AGENT"]);
108  exit(0);
109  }
110  }
111 
112  self::clearGDocs();
113  return self::AccessOk;
114  }
115 
116  protected static function checkAuthentication($authtype = null, $noask = false)
117  {
118  self::$provider_errno = 0;
119 
120  self::$auth = static::getAuthenticatorClass();
121  $authProviderList = static::getAuthProviderList();
122  $status = false;
123  foreach ($authProviderList as $authProvider) {
124  self::$auth = static::getAuthenticatorClass($authtype, $authProvider);
125  $status = self::$auth->checkAuthentication();
127  if ($noask) {
128  return self::NeedAsk;
129  } else {
130  self::$auth->askAuthentication(array());
131  exit(0);
132  }
133  }
135  break;
136  }
137  }
138  return $status;
139  }
140 
141  protected static function getAuthenticatorClass($authtype = null, $provider = Authenticator::nullProvider)
142  {
143 
144  if (!$authtype) {
145  $authtype = static::getAuthType();
146  }
147  if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $authtype)) {
148  throw new \Dcp\Exception(sprintf("Invalid authtype '%s'", $authtype));
149  }
150 
151  $authClass = strtolower($authtype) . "Authenticator";
152  if (!\Dcp\Autoloader::classExists($authClass)) {
153  throw new \Dcp\Exception(sprintf("Cannot find authenticator '%s'", $authtype));
154  }
155  return new $authClass($authtype, $provider);
156  }
157  /**
158  * @return string
159  */
160  public static function getAuthProvider()
161  {
162  $freedom_authprovider = getDbAccessValue('freedom_authprovider');
163 
164  if ($freedom_authprovider == "") {
165  $freedom_authprovider = "html";
166  }
167 
168  return trim($freedom_authprovider);
169  }
170  /**
171  * @return array
172  */
173  public static function getAuthProviderList()
174  {
175  return preg_split("/\\s*,\\s*/", static::getAuthProvider());
176  }
177 
178  public static function getAuthType()
179  {
180  if (array_key_exists('authtype', $_GET)) {
181  if ($_GET['authtype'] === "apache") {
182  throw new \Dcp\Exception(sprintf("apache authtype not allowed.\n"));
183  }
184  return $_GET['authtype'];
185  }
186  if (!empty($_GET[OpenAuthenticator::openGetId])) {
187  return "open";
188  }
189 
190  $scheme = self::getAuthorizationScheme();
191  if ($scheme) {
192  switch ($scheme) {
193  case OpenAuthenticator::openAuthorizationScheme:
194  return "open";
195  case \basicAuthenticator::basicAuthorizationScheme:
196  return "basic";
197  default:
198  throw new Exception(sprintf("Invalid authorization method \"%s\"", $scheme));
199  }
200  }
201 
202  $freedom_authtype = getDbAccessValue('freedom_authtype');
203 
204  if ($freedom_authtype == "") {
205  $freedom_authtype = "html";
206  }
207 
208  return trim($freedom_authtype);
209  }
210 
211  protected static function getAuthorizationScheme()
212  {
213  if (php_sapi_name() !== 'cli') {
214  $headers = apache_request_headers();
215  if (!empty($headers["Authorization"])) {
216  $hAuthorization = $headers["Authorization"];
217  } elseif (!empty($headers["authorization"])) {
218  $hAuthorization = $headers["authorization"];
219  }
220  if (!empty($hAuthorization)) {
221  if (preg_match("/^([a-z0-9]+)\\s+(.*)$/i", $hAuthorization, $reg)) {
222  return trim($reg[1]);
223  }
224  }
225  }
226  return "";
227  }
228 
229  public static function closeAccess()
230  {
231  self::$auth = static::getAuthenticatorClass();
232 
233  if (method_exists(self::$auth, 'logout')) {
234  if (is_object(self::$auth->provider)) {
235  self::secureLog("close", "see you tomorrow", self::$auth->provider->parms['type'] . "/" . self::$auth->provider->parms['provider'], $_SERVER["REMOTE_ADDR"], self::$auth->getAuthUser() , $_SERVER["HTTP_USER_AGENT"]);
236  } else {
237  self::secureLog("close", "see you tomorrow");
238  }
239  self::$auth->logout(null);
240  exit(0);
241  }
242 
243  header('HTTP/1.0 500 Internal Error');
244  print sprintf("logout method not supported by authtype '%s'", static::getAuthType());
245  exit(0);
246  }
247  /**
248  * Send a 401 Unauthorized HTTP header
249  */
250  public function authenticate(&$action)
251  {
252  // Header( "WWW-Authenticate: Basic realm=\"WHAT Connection\", stale=FALSE");
253  //Header( "WWW-Authenticate: Basic realm=\"WHAT Connection\", stale=true");
254  //Header( "HTTP/1.0 401 Unauthorized");
255  header('WWW-Authenticate: Basic realm="' . getParam("CORE_REALM", "Dynacase Platform connection") . '"');
256  header('HTTP/1.0 401 Unauthorized');
257  echo _("Vous devez entrer un nom d'utilisateur valide et un mot de passe correct pour acceder a cette ressource");
258  exit;
259  }
260 
261  public static function secureLog($status = "", $additionalMessage = "", $provider = "", $clientIp = "", $account = "", $userAgent = "")
262  {
263  global $_GET;
264  $log = new Log("", "Session", "Authentication");
265  $facility = constant(getParam("AUTHENT_LOGFACILITY", "LOG_AUTH"));
266  $log->wlog("S", sprintf("[%s] [%s] [%s] [%s] [%s] [%s]", $status, $additionalMessage, $provider, $clientIp, $account, $userAgent) , NULL, $facility);
267  return 0;
268  }
269 
270  public static function clearGDocs()
271  {
273  }
274 
275  public static function getAccount()
276  {
277  $login = self::$auth->getAuthUser();
278  $account = new Account();
279  if ($account->setLoginName($login)) {
280  return $account;
281  }
282  return false;
283  }
284  /**
285  * Get Provider's protocol version.
286  *
287  * @param Provider $provider
288  * @return int version (0, 1, etc.)
289  */
290  public static function _getProviderProtocolVersion(Provider $provider)
291  {
292  if (!isset($provider->PROTOCOL_VERSION)) {
293  return 0;
294  }
295  return $provider->PROTOCOL_VERSION;
296  }
297  /**
298  * Main authorization check entry point
299  *
300  * @return int
301  * @throws \Dcp\Exception
302  */
303  protected static function checkAuthorization()
304  {
305  $login = AuthenticatorManager::$auth->getAuthUser();
306  $wu = new Account();
307  $existu = false;
308  if ($wu->SetLoginName($login)) {
309  $existu = true;
310  }
311 
312  if (!$existu) {
313  AuthenticatorManager::secureLog("failure", "login have no Dynacase account", AuthenticatorManager::$auth->provider->parms['type'] . "/" . AuthenticatorManager::$auth->provider->parms['provider'], $_SERVER["REMOTE_ADDR"], $login, $_SERVER["HTTP_USER_AGENT"]);
315  }
316 
317  $protoVersion = self::_getProviderProtocolVersion(self::$auth->provider);
318  if (!is_integer($protoVersion)) {
319  throw new \Dcp\Exception(sprintf("Invalid provider protocol version '%s' for provider '%s'.", $protoVersion, get_class(self::$auth->provider)));
320  }
321 
322  switch ($protoVersion) {
323  case 0:
324  return self::protocol_0_authorization(array(
325  'username' => $login,
326  'dcp_account' => $wu
327  ));
328  break;
329  }
330  throw new \Dcp\Exception(sprintf("Unsupported provider protocol version '%s' for provider '%s'.", $protoVersion, get_class(self::$auth->provider)));
331  }
332  /**
333  * Protocol 0: check only Dynacase's authorization.
334  *
335  * @param array $opt
336  * @return int
337  */
338  private static function protocol_0_authorization($opt)
339  {
340  $authz = self::checkProviderAuthorization($opt);
341  if ($authz !== self::AccessOk) {
342  return $authz;
343  }
344  return self::checkDynacaseAuthorization($opt);
345  }
346  /**
347  * Check Provider's authorization.
348  *
349  * @param array $opt
350  * @return int
351  */
352  private static function checkProviderAuthorization($opt)
353  {
354  $authz = self::$auth->checkAuthorization($opt);
355  if ($authz === true) {
356  return self::AccessOk;
357  }
358  return self::AccessNotAuthorized;
359  }
360  /**
361  * Check Dynacase's authorization.
362  *
363  * @param array $opt
364  * @throws \Dcp\Exception
365  * @return int
366  */
367  private static function checkDynacaseAuthorization($opt)
368  {
369  $login = $opt['username'];
370  $wu = $opt['dcp_account'];
371  if ($wu->id != 1) {
372 
373  include_once ("FDL/freedom_util.php");
374  /**
375  * @var \Dcp\Family\IUSER $du
376  */
377  $du = new_Doc(getDbAccess() , $wu->fid);
378  // First check if account is active
379  if (!$du->isAccountActive()) {
380  AuthenticatorManager::secureLog("failure", "inactive account", AuthenticatorManager::$auth->provider->parms['type'] . "/" . AuthenticatorManager::$auth->provider->parms['provider'], $_SERVER["REMOTE_ADDR"], $login, $_SERVER["HTTP_USER_AGENT"]);
383  }
384  // check if the account expiration date is elapsed
385  if ($du->accountHasExpired()) {
386  AuthenticatorManager::secureLog("failure", "account has expired", AuthenticatorManager::$auth->provider->parms['type'] . "/" . AuthenticatorManager::$auth->provider->parms['provider'], $_SERVER["REMOTE_ADDR"], $login, $_SERVER["HTTP_USER_AGENT"]);
389  }
390  // check count of login failure
391  $maxfail = getParam("AUTHENT_FAILURECOUNT");
392  if ($maxfail > 0 && $du->getRawValue("us_loginfailure", 0) >= $maxfail) {
393  AuthenticatorManager::secureLog("failure", "max connection (" . $maxfail . ") attempts exceeded", AuthenticatorManager::$auth->provider->parms['type'] . "/" . AuthenticatorManager::$auth->provider->parms['provider'], $_SERVER["REMOTE_ADDR"], $login, $_SERVER["HTTP_USER_AGENT"]);
396  }
397  // authen OK, max login failure OK => reset count of login failure
398  $du->disableEditControl();
399  $du->resetLoginFailure();
400  $du->enableEditControl();
401  }
402 
404  }
405 }
static checkAuthentication($authtype=null, $noask=false)
$status
Definition: index.php:30
static secureLog($status="", $additionalMessage="", $provider="", $clientIp="", $account="", $userAgent="")
global $action
getDbAccessValue($varName)
Definition: Lib.Common.php:425
$ret
if(ActionRouter::inMaintenance()) $auth
Definition: authent.php:15
static getAuthenticatorClass($authtype=null, $provider=Authenticator::nullProvider)
$log
Definition: wsh.php:33
getAuthProvider($freedomctx="")
Definition: Lib.Common.php:555
global $_GET
Definition: wsh.php:37
getParam($name, $def="")
must be in core or global type
Definition: Lib.Common.php:193
getAuthType($freedomctx="")
Definition: Lib.Common.php:545
$login
Definition: dav.php:40
print
Definition: checklist.php:49
global $_SERVER
getDbAccess()
Definition: Lib.Common.php:368
static _getProviderProtocolVersion(Provider $provider)
switch($command) exit
Definition: checkVault.php:46
new_Doc($dbaccess, $id= '', $latest=false)
$account
Definition: guest.php:36
getAuthProviderList($freedomctx="")
Definition: Lib.Common.php:564
const ERRNO_BUG_639
← centre documentaire © anakeen