[ Index ]

PHP Cross Reference of Eventum

title

Body

[close]

/include/ -> class.auth.php (source)

   1  <?php
   2  /* vim: set expandtab tabstop=4 shiftwidth=4 encoding=utf-8: */
   3  // +----------------------------------------------------------------------+
   4  // | Eventum - Issue Tracking System                                      |
   5  // +----------------------------------------------------------------------+
   6  // | Copyright (c) 2003, 2004, 2005, 2006, 2007 MySQL AB                  |
   7  // |                                                                      |
   8  // | This program is free software; you can redistribute it and/or modify |
   9  // | it under the terms of the GNU General Public License as published by |
  10  // | the Free Software Foundation; either version 2 of the License, or    |
  11  // | (at your option) any later version.                                  |
  12  // |                                                                      |
  13  // | This program is distributed in the hope that it will be useful,      |
  14  // | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
  15  // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
  16  // | GNU General Public License for more details.                         |
  17  // |                                                                      |
  18  // | You should have received a copy of the GNU General Public License    |
  19  // | along with this program; if not, write to:                           |
  20  // |                                                                      |
  21  // | Free Software Foundation, Inc.                                       |
  22  // | 59 Temple Place - Suite 330                                          |
  23  // | Boston, MA 02111-1307, USA.                                          |
  24  // +----------------------------------------------------------------------+
  25  // | Authors: João Prado Maia <jpm@mysql.com>                             |
  26  // +----------------------------------------------------------------------+
  27  //
  28  // @(#) $Id: class.auth.php 3394 2007-11-04 08:33:06Z balsdorf $
  29  //
  30  
  31  require_once (APP_INC_PATH . "class.error_handler.php");
  32  require_once (APP_INC_PATH . "class.project.php");
  33  require_once (APP_INC_PATH . "class.user.php");
  34  require_once (APP_INC_PATH . "class.customer.php");
  35  require_once (APP_INC_PATH . "class.date.php");
  36  require_once(APP_CONFIG_PATH . "private_key.php");
  37  
  38  /**
  39   * Class to handle authentication issues.
  40   *
  41   * @version 1.0
  42   * @author João Prado Maia <jpm@mysql.com>
  43   */
  44  class Auth
  45  {
  46      /**
  47       * Method used to save the login information into a log file. It will be
  48       * useful for administrative purposes, so we know which customers were able
  49       * to login.
  50       *
  51       * @access  public
  52       * @param   string $email The email associated with the user
  53       * @param   string $type Whether it was a successful login or not
  54       * @param   string $extra The reason for not being a successful login
  55       */
  56      function saveLoginAttempt($email, $type, $extra = false)
  57      {
  58          $msg = Date_API::getCurrentDateGMT() . " - Login attempt by '$email' was ";
  59          if ($type == 'success') {
  60              $msg .= "successful.\n";
  61          } else {
  62              $msg .= "not successful because of '$extra'.\n";
  63          }
  64          $fp = @fopen(APP_LOGIN_LOG, "a");
  65          @fwrite($fp, $msg);
  66          @fclose($fp);
  67      }
  68  
  69  
  70      /**
  71       * Method used to get the requested URI for the 'current' page the user is
  72       * trying to access. This is used to get the appropriate URL and save it
  73       * if the user does not have the login cookie.
  74       *
  75       * @access  public
  76       * @return  string The requested URI for the current page
  77       */
  78      function getRequestedURL()
  79      {
  80          return urlencode($_SERVER["REQUEST_URI"]);
  81      }
  82  
  83  
  84      /**
  85       * Method used to check for the appropriate authentication for a specific
  86       * page. It will check for the cookie name provided and redirect the user
  87       * to another page if needed.
  88       *
  89       * @access  public
  90       * @param   string $cookie_name The name of the cookie to check for
  91       * @param   string $failed_url The URL to redirect to if the user is not authenticated
  92       * @param   boolean $is_popup Flag to tell the function if the current page is a popup window or not
  93       * @return  void
  94       */
  95      function checkAuthentication($cookie_name, $failed_url = NULL, $is_popup = false)
  96      {
  97          if ($failed_url == NULL) {
  98              $failed_url = APP_RELATIVE_URL . "index.php?err=5";
  99          }
 100          $failed_url .= "&url=" . Auth::getRequestedURL();
 101          if (!isset($_COOKIE[$cookie_name])) {
 102              Auth::redirect($failed_url, $is_popup);
 103          }
 104          $cookie = $_COOKIE[$cookie_name];
 105          $cookie = unserialize(base64_decode($cookie));
 106          if (!Auth::isValidCookie($cookie)) {
 107              Auth::removeCookie($cookie_name);
 108              Auth::redirect($failed_url, $is_popup);
 109          }
 110          if (Auth::isPendingUser($cookie["email"])) {
 111              Auth::removeCookie($cookie_name);
 112              Auth::redirect(APP_RELATIVE_URL . "index.php?err=9", $is_popup);
 113          }
 114          if (!Auth::isActiveUser($cookie["email"])) {
 115              Auth::removeCookie($cookie_name);
 116              Auth::redirect(APP_RELATIVE_URL . "index.php?err=7", $is_popup);
 117          }
 118  
 119          $usr_id = Auth::getUserID();
 120  
 121          // check the session
 122          Session::verify($usr_id);
 123  
 124          if (!defined('SKIP_LANGUAGE_INIT')) {
 125              Language::setPreference();
 126          }
 127  
 128          // check whether the project selection is set or not
 129          $prj_id = Auth::getCurrentProject();
 130          if (empty($prj_id)) {
 131              // redirect to select project page
 132              Auth::redirect(APP_RELATIVE_URL . "select_project.php?url=" . Auth::getRequestedURL(), $is_popup);
 133          }
 134          // check the expiration date for a 'Customer' type user
 135          $customer_id = User::getCustomerID($usr_id);
 136          $contact_id = User::getCustomerContactID($usr_id);
 137          if ((!empty($customer_id)) && ($customer_id != -1) &&
 138                  (!empty($contact_id)) && (Customer::hasCustomerIntegration($prj_id))) {
 139  
 140              Customer::authenticateCustomer($prj_id, $customer_id, $contact_id);
 141          }
 142  
 143          // auto switch project
 144          if (isset($_GET['switch_prj_id'])) {
 145              Auth::setCurrentProject($_GET['switch_prj_id'], false);
 146              Auth::redirect($_SERVER['PHP_SELF'] . '?' . str_replace("switch_prj_id=" . $_GET['switch_prj_id'], "", $_SERVER['QUERY_STRING']));
 147          }
 148  
 149          // if the current session is still valid, then renew the expiration
 150          Auth::createLoginCookie($cookie_name, $cookie['email']);
 151          // renew the project cookie as well
 152          $prj_cookie = Auth::getCookieInfo(APP_PROJECT_COOKIE);
 153          Auth::setCurrentProject($prj_id, $prj_cookie["remember"]);
 154      }
 155  
 156  
 157      /**
 158       * Method to check whether an user is pending its confirmation
 159       * or not.
 160       *
 161       * @access  public
 162       * @param   string $email The email address to be checked
 163       * @return  boolean
 164       */
 165      function isPendingUser($email)
 166      {
 167          $status = User::getStatusByEmail($email);
 168          if ($status != 'pending') {
 169              return false;
 170          } else {
 171              return true;
 172          }
 173      }
 174  
 175  
 176      /**
 177       * Method to check whether an user is active or not.
 178       *
 179       * @access  public
 180       * @param   string $email The email address to be checked
 181       * @return  boolean
 182       */
 183      function isActiveUser($email)
 184      {
 185          $status = User::getStatusByEmail($email);
 186          if ($status != 'active') {
 187              return false;
 188          } else {
 189              return true;
 190          }
 191      }
 192  
 193  
 194      /**
 195       * Method to check if the user has cookie support enabled in his browser or
 196       * not.
 197       *
 198       * @access  public
 199       * @param   string $cookie_name The name of the cookie to check for
 200       * @return  boolean
 201       */
 202      function hasCookieSupport($cookie_name)
 203      {
 204          if (@!in_array($cookie_name, array_keys($_COOKIE))) {
 205              return false;
 206          } else {
 207              return true;
 208          }
 209      }
 210  
 211  
 212      /**
 213       * Method to check if the user has a valid cookie.
 214       *
 215       * @access  public
 216       * @param   string $cookie_name The name of the cookie to check for
 217       * @return  boolean
 218       */
 219      function hasValidCookie($cookie_name)
 220      {
 221          $cookie = @$_COOKIE[$cookie_name];
 222          $cookie = unserialize(base64_decode($cookie));
 223          if (!Auth::isValidCookie($cookie)) {
 224              return false;
 225          } else {
 226              return true;
 227          }
 228      }
 229  
 230  
 231      /**
 232       * Method used to get the unserialized contents of the specified cookie
 233       * name.
 234       *
 235       * @access  public
 236       * @param   string $cookie_name The name of the cookie to check for
 237       * @return  array The unserialized contents of the cookie
 238       */
 239      function getCookieInfo($cookie_name)
 240      {
 241          $cookie = @$_COOKIE[$cookie_name];
 242          return unserialize(base64_decode($cookie));
 243      }
 244  
 245  
 246      /**
 247       * Method used to check whether a cookie is valid or not.
 248       *
 249       * @access  public
 250       * @param   array $cookie The unserialized contents of the cookie
 251       * @return  boolean
 252       */
 253      function isValidCookie($cookie)
 254      {
 255          if ((empty($cookie["email"])) || (empty($cookie["hash"])) ||
 256                 ($cookie["hash"] != md5($GLOBALS["private_key"] . md5($cookie["login_time"]) . $cookie["email"]))) {
 257              return false;
 258          } else {
 259              $usr_id = User::getUserIDByEmail(@$cookie["email"]);
 260              if (empty($usr_id)) {
 261                  return false;
 262              } else {
 263                  return true;
 264              }
 265          }
 266      }
 267  
 268  
 269      /**
 270       * Method used to create the login cookie in the user's machine.
 271       *
 272       * @access  public
 273       * @param   string $cookie_name The cookie name to be created
 274       * @param   string $email The email address to be stored in the cookie
 275       * @return  void
 276       */
 277      function createLoginCookie($cookie_name, $email)
 278      {
 279          $time = time();
 280          $cookie = array(
 281              "email"      => $email,
 282              "login_time" => $time,
 283              "hash"       => md5($GLOBALS["private_key"] . md5($time) . $email),
 284          );
 285          $cookie = base64_encode(serialize($cookie));
 286          Auth::setCookie($cookie_name, $cookie, APP_COOKIE_EXPIRE);
 287      }
 288  
 289  
 290      /**
 291       * Method used to redirect people to another URL.
 292       *
 293       * @access  public
 294       * @param   string $new_url The URL the user should be redirected to
 295       * @param   boolean $is_popup Whether the current window is a popup or not
 296       * @return  void
 297       */
 298      function redirect($new_url, $is_popup = false)
 299      {
 300          if ($is_popup) {
 301              $html = '<script language="JavaScript">
 302                       <!--
 303                       if (window.opener) {
 304                           window.opener.location.href = "' . $new_url . '";
 305                           window.close();
 306                       } else {
 307                          location.href = "' . $new_url . '";
 308                       }
 309                       //-->
 310                       </script>';
 311              echo $html;
 312              exit;
 313          } else {
 314              // IIS 5 has problems with "Location" header so don't use it under IIS
 315              if (strstr($_SERVER['SERVER_SOFTWARE'], 'IIS')) {
 316                  // IIS
 317                  header("Refresh: 0; URL=$new_url");
 318              } else {
 319                  // all servers that work correctly
 320                  header("Location: $new_url");
 321              }
 322              exit;
 323          }
 324      }
 325  
 326  
 327      /**
 328       * Method used to remove a cookie from the user's browser.
 329       *
 330       * @access  public
 331       * @param   string $cookie_name The name of the cookie that needs to be deleted
 332       * @return  void
 333       */
 334      function removeCookie($cookie_name)
 335      {
 336          Auth::setCookie($cookie_name, '', time()-36000);
 337      }
 338  
 339  
 340      /**
 341       * Checks whether an user exists or not in the database.
 342       *
 343       * @access  public
 344       * @param   string $email The email address to check for
 345       * @return  boolean
 346       */
 347      function userExists($email)
 348      {
 349          if (empty($email)) {
 350              return false;
 351            } else {
 352              $stmt = "SELECT
 353                          usr_email
 354                       FROM
 355                          " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "user
 356                       WHERE
 357                          usr_email='" . Misc::escapeString($email) . "'";
 358              $info = $GLOBALS["db_api"]->dbh->getOne($stmt);
 359              if (PEAR::isError($info)) {
 360                  Error_Handler::logError(array($info->getMessage(), $info->getDebugInfo()), __FILE__, __LINE__);
 361                  return false;
 362              } elseif (empty($info)) {
 363                  return false;
 364              } else {
 365                  return true;
 366              }
 367          }
 368      }
 369  
 370  
 371      /**
 372       * Checks whether the provided password match against the email
 373       * address provided.
 374       *
 375       * @access  public
 376       * @param   string $email The email address to check for
 377       * @param   string $password The password of the user to check for
 378       * @return  boolean
 379       */
 380      function isCorrectPassword($email, $password)
 381      {
 382          $stmt = "SELECT
 383                      usr_password
 384                   FROM
 385                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "user
 386                   WHERE
 387                      usr_email='" . Misc::escapeString($email) . "' AND
 388                      usr_id != " . APP_SYSTEM_USER_ID;
 389          $passwd = $GLOBALS["db_api"]->dbh->getOne($stmt);
 390          if (PEAR::isError($passwd)) {
 391              Error_Handler::logError(array($passwd->getMessage(), $passwd->getDebugInfo()), __FILE__, __LINE__);
 392              return false;
 393          } else {
 394              if ($passwd != Auth::hashPassword($password)) {
 395                  return false;
 396              } else {
 397                  return true;
 398              }
 399          }
 400      }
 401  
 402  
 403      /**
 404       * Gets the current user ID.
 405       *
 406       * @access  public
 407       * @return  integer The ID of the user
 408       */
 409      function getUserID()
 410      {
 411          $info = Auth::getCookieInfo(APP_COOKIE);
 412          if (empty($info)) {
 413              return '';
 414          } else {
 415              return User::getUserIDByEmail($info["email"]);
 416          }
 417      }
 418  
 419  
 420      /**
 421       * Gets the current selected project from the project cookie.
 422       *
 423       * @access  public
 424       * @return  integer The project ID
 425       */
 426      function getCurrentProject()
 427      {
 428          $cookie = Auth::getCookieInfo(APP_PROJECT_COOKIE);
 429          if (empty($cookie)) {
 430              return "";
 431          }
 432          $usr_id = Auth::getUserID();
 433          $projects = Project::getAssocList($usr_id);
 434          if ($usr_id == APP_SYSTEM_USER_ID) {
 435              return isset($cookie['prj_id']) ? (int )$cookie['prj_id'] : null;
 436          }
 437          if (!in_array($cookie["prj_id"], array_keys($projects))) {
 438              Auth::redirect(APP_RELATIVE_URL . "select_project.php?err=1");
 439          }
 440          return $cookie["prj_id"];
 441      }
 442  
 443  
 444      /**
 445       * Gets the current project name from the user's project cookie.
 446       *
 447       * @access  public
 448       * @return  string The current project name
 449       */
 450      function getCurrentProjectName()
 451      {
 452          $proj_id = Auth::getCurrentProject();
 453          if (!empty($proj_id)) {
 454              return Project::getName($proj_id);
 455          }
 456      }
 457  
 458  
 459      /**
 460       * Gets the current role in the current project.
 461       *
 462       * @access  public
 463       * @return  integer The current role ID
 464       */
 465      function getCurrentRole()
 466      {
 467          $prj_id = Auth::getCurrentProject();
 468          $usr_id = Auth::getUserID();
 469          if ((!empty($prj_id)) && (!empty($usr_id))) {
 470              return User::getRoleByUser($usr_id, $prj_id);
 471          } else {
 472              return 1;
 473          }
 474      }
 475  
 476  
 477      /**
 478       * Sets the current selected project for the user session.
 479       *
 480       * @access  public
 481       * @param   integer $project The project ID
 482       * @param   integer $remember Whether to automatically remember the setting or not
 483       * @return  void
 484       */
 485      function setCurrentProject($project, $remember)
 486      {
 487          $cookie = array(
 488              "prj_id"   => $project,
 489              "remember" => $remember
 490          );
 491          $cookie = base64_encode(serialize($cookie));
 492          Auth::setCookie(APP_PROJECT_COOKIE, $cookie, APP_PROJECT_COOKIE_EXPIRE);
 493          Auth::createFakeCookie(Auth::getUserID(), $project);
 494      }
 495  
 496  
 497      /**
 498       * Creates a fake cookie so processes not run from a browser can access current user and project
 499       *
 500       * @param   integer $usr_id The ID of the user.
 501       * @param   integer $prj_id The ID of the project.
 502       */
 503      function createFakeCookie($usr_id, $project = false)
 504      {
 505          require_once(APP_CONFIG_PATH . "private_key.php");
 506  
 507          $user_details = User::getDetails($usr_id);
 508  
 509          $time = time();
 510          $cookie = array(
 511              "email" => $user_details['usr_email'],
 512              "login_time"    =>  $time,
 513              "hash"       => md5($GLOBALS["private_key"] . md5($time) . $user_details['usr_email']),
 514          );
 515          $_COOKIE[APP_COOKIE] = base64_encode(serialize($cookie));
 516          if ($project) {
 517              $cookie = array(
 518                  "prj_id"   => $project,
 519                  "remember" => false
 520              );
 521          }
 522          $_COOKIE[APP_PROJECT_COOKIE] = base64_encode(serialize($cookie));
 523      }
 524  
 525  
 526      /**
 527       * Hashes the password according to APP_HASH_TYPE constant
 528       *
 529       * @access  public
 530       * @param   string $password The plain text password
 531       * @return  string The hashed password
 532       */
 533      function hashPassword($password)
 534      {
 535          if (APP_HASH_TYPE == 'MD5-64') {
 536              return base64_encode(pack('H*',md5($password)));
 537          } else {
 538              // default to md5
 539              return md5($password);
 540          }
 541      }
 542  
 543  
 544      /**
 545       * Sets a cookie in the browser
 546       *
 547       * @param   string  $name The name of the cookie
 548       * @param   string  $value The value of the cookie
 549       * @param   string  $expiration The expiration data of the cookie
 550       */
 551      function setCookie($name, $value, $expiration)
 552      {
 553          if (is_null(APP_COOKIE_DOMAIN)) {
 554  
 555              setcookie($name, $value, $expiration, APP_COOKIE_URL);
 556          } else {
 557              setcookie($name, $value, $expiration, APP_COOKIE_URL, APP_COOKIE_DOMAIN);
 558          }
 559      }
 560  
 561  }
 562  
 563  // benchmarking the included file (aka setup time)
 564  if (APP_BENCHMARK) {
 565      $GLOBALS['bench']->setMarker('Included Auth Class');
 566  }


Generated: Wed Dec 19 21:21:33 2007 Cross-referenced by PHPXref 0.7