1<?php 2/** 3 * Copyright 1999-2017 Horde LLC (http://www.horde.org/) 4 * 5 * See the enclosed file COPYING for license information (LGPL). If you did 6 * not receive this file, see http://www.horde.org/licenses/lgpl21. 7 * 8 * @author Chuck Hagenbuch <chuck@horde.org> 9 * @category Horde 10 * @license http://www.horde.org/licenses/lgpl21 LGPL-2.1 11 * @package Auth 12 */ 13 14/** 15 * The Horde_Auth_Http class transparently logs users in to Horde using 16 * already present HTTP authentication headers. 17 * 18 * @author Chuck Hagenbuch <chuck@horde.org> 19 * @category Horde 20 * @copyright 1999-2017 Horde LLC 21 * @license http://www.horde.org/licenses/lgpl21 LGPL-2.1 22 * @package Auth 23 */ 24class Horde_Auth_Http extends Horde_Auth_Base 25{ 26 /** 27 * An array of capabilities, so that the driver can report which 28 * operations it supports and which it doesn't. 29 * 30 * @var array 31 */ 32 protected $_capabilities = array( 33 'transparent' => true 34 ); 35 36 /** 37 * Array of usernames and hashed passwords. 38 * 39 * @var array 40 */ 41 protected $_users = array(); 42 43 /** 44 * Constructor. 45 * 46 * @param array $params Optional parameters: 47 * <pre> 48 * 'encryption' - (string) Kind of passwords in the .htpasswd file. 49 * Either 'crypt-des' (standard crypted htpasswd entries) 50 * [DEFAULT] or 'aprmd5'. This information is used if 51 * you want to directly authenticate users with this 52 * driver, instead of relying on transparent auth. 53 * 'htpasswd_file' - (string) TODO 54 * </pre> 55 */ 56 public function __construct(array $params = array()) 57 { 58 $params = array_merge(array( 59 'encryption' => 'crypt-des' 60 ), $params); 61 62 parent::__construct($params); 63 64 if (!empty($this->_params['htpasswd_file'])) { 65 $users = file($this->_params['htpasswd_file']); 66 if (is_array($users)) { 67 // Enable the list users capability. 68 $this->_capabilities['list'] = true; 69 70 foreach ($users as $line) { 71 list($user, $pass) = explode(':', $line, 2); 72 $this->_users[trim($user)] = trim($pass); 73 } 74 } 75 } 76 } 77 78 /** 79 * Find out if a set of login credentials are valid. Only supports 80 * htpasswd files with DES passwords right now. 81 * 82 * @param string $userId The userId to check. 83 * @param array $credentials An array of login credentials. For IMAP, 84 * this must contain a password entry. 85 * 86 * @throws Horde_Auth_Exception 87 */ 88 protected function _authenticate($userId, $credentials) 89 { 90 if (empty($credentials['password']) || 91 empty($this->_users[$userId])) { 92 throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN); 93 } 94 95 $hash = Horde_Auth::getCryptedPassword($credentials['password'], $this->_users[$userId], $this->_params['encryption'], !empty($this->_params['show_encryption'])); 96 97 if ($hash != $this->_users[$userId]) { 98 throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN); 99 } 100 } 101 102 /** 103 * Lists all users in the system. 104 * 105 * @param boolean $sort Sort the users? 106 * 107 * @return array The array of userIds. 108 */ 109 public function listUsers($sort = false) 110 { 111 // this driver sorts by default 112 $users = array_keys($this->_users); 113 return $this->_sort($users, $sort); 114 } 115 116 /** 117 * Automatic authentication: Find out if the client has HTTP 118 * authentication info present. 119 * 120 * @return boolean Whether or not the client is allowed. 121 */ 122 public function transparent() 123 { 124 if (empty($_SERVER['PHP_AUTH_USER']) || 125 empty($_SERVER['PHP_AUTH_PW'])) { 126 return false; 127 } 128 129 $this->_credentials['userId'] = $_SERVER['PHP_AUTH_USER']; 130 $this->_credentials['credentials'] = array( 131 'password' => Horde_Util::dispelMagicQuotes($_SERVER['PHP_AUTH_PW']) 132 ); 133 134 return true; 135 } 136 137} 138