1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
18: class Horde_Auth_Msad extends Horde_Auth_Ldap
19: {
20: 21: 22: 23: 24: 25: 26:
27: public function __construct($params = array())
28: {
29: $params = array_merge(array(
30: 'adduser' => true,
31: 'authId' => 'initials',
32: 'encryption' => 'msad',
33: 'newuser_objectclass' => 'user',
34: 'password_expiration' => 'no',
35: 'port' => 389,
36: 'ssl' => false,
37: 'uid' => array('samaccountname')
38: ), $params);
39:
40: if (!is_array($params['uid'])) {
41: $params['uid'] = array($params['uid']);
42: }
43:
44:
45:
46:
47:
48: 49:
50: $this->_capabilities = array(
51: 'add' => ($params['ssl'] || $params['adduser']),
52: 'list' => true,
53: 'remove' => true,
54: 'resetpassword' => $params['ssl'],
55: 'update' => $params['ssl']
56: );
57:
58: parent::__construct($params);
59: }
60:
61: 62: 63: 64: 65: 66: 67: 68:
69: public function addUser($accountName, $credentials)
70: {
71:
72: $this->_connect();
73:
74: if (isset($credentials['ldap'])) {
75: $dn = $credentials['ldap']['dn'];
76: } else {
77: $basedn = isset($credentials['basedn'])
78: ? $credentials['basedn']
79: : $this->_params['basedn'];
80:
81:
82: $dn = 'cn=' . $accountName . ',' . $basedn;
83:
84: $entry['cn'] = $accountName;
85: $entry['samaccountname'] = $accountName;
86:
87: $entry['objectclass'][0] = "top";
88: $entry['objectclass'][1] = "person";
89: $entry['objectclass'][2] = "organizationalPerson";
90: $entry['objectclass'][3] = "user";
91:
92: $entry['description'] = (isset($credentials['description'])) ?
93: $credentials['description'] : 'New horde user';
94:
95: if ($this->_params['ssl']) {
96: $entry["AccountDisabled"] = false;
97: }
98: $entry['userPassword'] = Horde_Auth::getCryptedPassword($credentials['password'],'',
99: $this->_params['encryption'],
100: false);
101:
102: if (isset($this->_params['binddn'])) {
103: $entry['manager'] = $this->_params['binddn'];
104: }
105:
106: }
107:
108: $success = @ldap_add($this->_ds, $dn, $entry);
109:
110: if (!$success) {
111: throw new Horde_Auth_Exception(sprintf(__CLASS__ . ': Unable to add user "%s". This is what the server said: ', $accountName) . ldap_error($this->_ds));
112: }
113:
114: @ldap_close($this->_ds);
115: }
116:
117: 118: 119: 120: 121: 122: 123: 124:
125: public function removeUser($accountName, $dn = null)
126: {
127:
128: $this->_connect();
129:
130: if (is_null($dn)) {
131:
132: $dn = $this->_findDN($accountName);
133: }
134:
135: if (!@ldap_delete($this->_ds, $dn)) {
136: throw new Horde_Auth_Exception(sprintf(__CLASS__ . ': Unable to remove user "%s"', $accountName));
137: }
138: @ldap_close($this->_ds);
139: }
140:
141: 142: 143: 144: 145: 146: 147: 148: 149:
150: public function updateUser($oldId, $newId, $credentials, $olddn = null,
151: $newdn = null)
152: {
153:
154: $this->_connect();
155:
156: if (isset($credentials['ldap'])) {
157: $olddn = $credentials['ldap']['dn'];
158: } else {
159:
160: $dn = $this->_findDN($oldId);
161:
162:
163: if (isset($credentials['password'])) {
164: $entry['userpassword'] = Horde_Auth::getCryptedPassword($credentials['password'],'',
165: $this->_params['encryption'],
166: true);
167: }
168: }
169:
170: if ($oldID != $newID) {
171: $newdn = str_replace($oldId, $newID, $dn);
172: ldap_rename($this->_ds, $olddn, $newdn, $this->_params['basedn'], true);
173: $success = @ldap_modify($this->_ds, $newdn, $entry);
174: } else {
175: $success = @ldap_modify($this->_ds, $olddn, $entry);
176: }
177:
178: if (!$success) {
179: throw new Horde_Auth_Exception(sprintf(__CLASS__ . ': Unable to update user "%s"', $newID));
180: }
181:
182: @ldap_close($this->_ds);
183: }
184:
185: 186: 187: 188: 189: 190: 191: 192: 193:
194: public function resetPassword($user_id)
195: {
196:
197: $password = Horde_Auth::genRandomPassword() . '/';
198: $this->updateUser($user_id, $user_id, array('userPassword' => $password));
199:
200: return $password;
201: }
202:
203: 204: 205: 206: 207:
208: protected function _connect()
209: {
210:
211: $ssl = ($this->_params['ssl']) ? 'ldaps://' : '';
212: $this->_ds = ldap_connect($ssl . $this->_params['hostspec'], $this->_params['port']);
213: if (!$this->_ds) {
214: throw new Horde_Auth_Exception('Failed to connect to MSAD server.');
215: }
216:
217: if ($this->_logger) {
218: if (!ldap_set_option($this->_ds, LDAP_OPT_PROTOCOL_VERSION, 3)) {
219: $this->_logger->log(sprintf('Set MSAD protocol version to %d failed: [%d] %s', 3, ldap_errno($conn), ldap_error($conn)));
220: }
221: if (!ldap_set_option($this->_ds, LDAP_OPT_REFERRALS, 0)) {
222: $this->_logger->log(sprintf('Set MSAD referrals option to %d failed: [%d] %s', 0, ldap_errno($conn), ldap_error($conn)));
223: }
224: }
225:
226: if (isset($this->_params['binddn'])) {
227: $bind = ldap_bind($this->_ds,
228: $this->_params['binddn'],
229: $this->_params['password']);
230: } else {
231: $bind = ldap_bind($this->_ds);
232: }
233:
234: if (!$bind) {
235: throw new Horde_Auth_Exception('Could not bind to MSAD server.');
236: }
237: }
238:
239: 240: 241: 242: 243: 244: 245:
246: protected function _findDN($userId)
247: {
248:
249: foreach ($this->_params['uid'] as $uid) {
250: $entries = array($uid);
251: if ($uid != $this->_params['authId']) {
252: array_push($entries, $this->_params['authId']);
253: }
254: $search = @ldap_search($this->_ds, $this->_params['basedn'],
255: $uid . '=' . $userId,
256: $entries
257: );
258:
259: if (!$search) {
260: throw new Horde_Auth_Exception('Could not search the MSAD server.');
261: }
262:
263:
264: $result = @ldap_get_entries($this->_ds, $search);
265:
266: if (is_array($result) && (count($result) > 1)) {
267: break;
268: }
269: }
270:
271: if (!is_array($result) || (count($result) <= 1)) {
272: throw new Horde_Auth_Exception('Empty result.');
273: }
274:
275:
276: $this->_credentials['userId'] = $result[0][$this->_params['authId']][0];
277:
278: return $result[0]['dn'];
279: }
280:
281: }
282: