1: <?php
2: /**
3: * The Horde_Auth_Imap:: class provides an IMAP implementation of the Horde
4: * authentication system.
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: * @author Gaudenz Steinlin <gaudenz@soziologie.ch>
13: * @author Jan Schneider <jan@horde.org>
14: * @category Horde
15: * @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
16: * @package Auth
17: */
18: class Horde_Auth_Imap extends Horde_Auth_Base
19: {
20: /**
21: * Imap client objects.
22: *
23: * @var array()
24: */
25: protected $_imap = array();
26:
27: /**
28: * Constructor.
29: *
30: * @param array $params Optional parameters:
31: * <pre>
32: * 'admin_password' - (string) The password of the adminstrator.
33: * DEFAULT: null
34: * 'admin_user' - (string) The name of a user with admin privileges.
35: * DEFAULT: null
36: * 'charset' - (string) Default charset.
37: * DEFAULT: NONE
38: * 'hostspec' - (string) The hostname or IP address of the server.
39: * DEFAULT: 'localhost'
40: * 'port' - (integer) The server port to which we will connect.
41: * IMAP is generally 143, while IMAP-SSL is generally 993.
42: * DEFAULT: Encryption port default
43: * 'secure' - (string) The encryption to use. Either 'none', 'ssl', or
44: * 'tls'.
45: * DEFAULT: 'none'
46: * 'userhierarchy' - (string) The hierarchy where user mailboxes are
47: * stored.
48: * DEFAULT: 'user.'
49: * </pre>
50: */
51: public function __construct(array $params = array())
52: {
53: $params = array_merge(array(
54: 'admin_password' => null,
55: 'admin_user' => null,
56: 'charset' => null,
57: 'hostspec' => '',
58: 'port' => null,
59: 'secure' => 'none',
60: 'userhierarchy' => 'user.'
61: ), $params);
62:
63: parent::__construct($params);
64:
65: if (!empty($this->_params['admin_user'])) {
66: $this->_capabilities = array_merge($this->_capabilities, array(
67: 'add' => true,
68: 'list' => true,
69: 'remove' => true
70: ));
71: }
72: }
73:
74: /**
75: * Find out if a set of login credentials are valid.
76: *
77: * @param string $userId The userId to check.
78: * @param array $credentials An array of login credentials. For IMAP,
79: * this must contain a password entry.
80: *
81: * @throws Horde_Auth_Exception
82: */
83: protected function _authenticate($userId, $credentials)
84: {
85: try {
86: $ob = $this->_getOb($userId, $credentials['password']);
87: $ob->login();
88: } catch (Horde_Imap_Client_Exception $e) {
89: throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
90: }
91: }
92:
93: /**
94: * Add a set of authentication credentials.
95: *
96: * @param string $userId The userId to add.
97: * @param array $credentials The credentials to use.
98: *
99: * @throws Horde_Auth_Exception
100: */
101: public function addUser($userId, $credentials)
102: {
103: $mailbox = Horde_String::convertCharset($this->_params['userhierarchy'] . $userId, $this->_params['charset'], 'utf7-imap');
104:
105: try {
106: $ob = $this->_getOb($this->_params['admin_user'], $this->_params['admin_password']);
107: $ob->createMailbox($mailbox);
108: $ob->setACL($mailbox, $this->_params['admin_user'], 'lrswipcda');
109: } catch (Horde_Imap_Client_Exception $e) {
110: throw new Horde_Auth_Exception($e);
111: }
112: }
113:
114: /**
115: * Delete a set of authentication credentials.
116: *
117: * @param string $userId The userId to delete.
118: *
119: * @throws Horde_Auth_Exception
120: */
121: public function removeUser($userId)
122: {
123: $mailbox = Horde_String::convertCharset($this->_params['userhierarchy'] . $userId, $this->_params['charset'], 'utf7-imap');
124:
125: try {
126: $ob = $this->_getOb($this->_params['admin_user'], $this->_params['admin_password']);
127: $ob->setACL($mailbox, $this->_params['admin_user'], 'lrswipcda');
128: $ob->deleteMailbox($mailbox);
129: } catch (Horde_Imap_Client_Exception $e) {
130: throw new Horde_Auth_Exception($e);
131: }
132: }
133:
134: /**
135: * List all users in the system.
136: *
137: * @return array The array of userIds.
138: * @throws Horde_Auth_Exception
139: */
140: public function listUsers($sort = false)
141: {
142: try {
143: $ob = $this->_getOb($this->_params['admin_user'], $this->_params['admin_password']);
144: $list = $ob->listMailboxes($this->_params['userhierarchy'] . '%', Horde_Imap_Client::MBOX_ALL, array('flat' => true));
145: } catch (Horde_Imap_Client_Exception $e) {
146: throw new Horde_Auth_Exception($e);
147: }
148:
149: $users = empty($list)
150: ? array()
151: : preg_replace('/.*' . preg_quote($this->_params['userhierarchy'], '/') . '(.*)/', '\\1', $list);
152: return $this->_sort($users, $sort);
153: }
154:
155: /**
156: * Get Horde_Imap_Client object.
157: *
158: * @param string $user Username.
159: * @param string $pass Password.
160: *
161: * @return Horde_Imap_Client_Base IMAP client object.
162: * @throws Horde_Auth_Exception
163: */
164: protected function _getOb($user, $pass)
165: {
166: $sig = hash('md5', serialize(array($user, $pass)));
167:
168: if (!isset($this->_ob[$sig])) {
169: $imap_config = array(
170: 'hostspec' => empty($this->_params['hostspec']) ? null : $this->_params['hostspec'],
171: 'password' => $pass,
172: 'port' => empty($this->_params['port']) ? null : $this->_params['port'],
173: 'secure' => ($this->_params['secure'] == 'none') ? null : $this->_params['secure'],
174: 'username' => $user
175: );
176:
177: try {
178: $this->_ob[$sig] = Horde_Imap_Client::factory('Socket', $imap_config);
179: } catch (InvalidArgumentException $e) {
180: throw new Horde_Auth_Exception($e);
181: }
182: }
183:
184: return $this->_ob[$sig];
185: }
186:
187: }
188: