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