Overview

Packages

  • Auth

Classes

  • Horde_Auth
  • Horde_Auth_Auto
  • Horde_Auth_Base
  • Horde_Auth_Composite
  • Horde_Auth_Customsql
  • Horde_Auth_Cyrsql
  • Horde_Auth_Exception
  • Horde_Auth_Ftp
  • Horde_Auth_Http
  • Horde_Auth_Http_Remote
  • Horde_Auth_Imap
  • Horde_Auth_Ipbasic
  • Horde_Auth_Kolab
  • Horde_Auth_Ldap
  • Horde_Auth_Login
  • Horde_Auth_Msad
  • Horde_Auth_Pam
  • Horde_Auth_Passwd
  • Horde_Auth_Peclsasl
  • Horde_Auth_Radius
  • Horde_Auth_Shibboleth
  • Horde_Auth_Smb
  • Horde_Auth_Smbclient
  • Horde_Auth_Sql
  • Horde_Auth_Translation
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * The Horde_Auth_Msad class provides an experimental MSAD extension of the
  4:  * LDAP implementation of the Horde authentication system.
  5:  *
  6:  * Copyright 2007-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:  * @todo Use Horde_Ldap
 12:  *
 13:  * @author   Francois Helly <fhelly@bebop-design.net>
 14:  * @category Horde
 15:  * @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
 16:  * @package  Auth
 17:  */
 18: class Horde_Auth_Msad extends Horde_Auth_Ldap
 19: {
 20:     /**
 21:      * Constructor.
 22:      *
 23:      * @param array $params  A hash containing connection parameters.
 24:      *
 25:      * @throws Horde_Auth_Exception
 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:         /* Ensure we've been provided with all of the necessary parameters. */
 45:         //Horde::assertDriverConfig($params, 'auth',
 46:         //    array('hostspec', 'basedn'), 'authentication MSAD');
 47: 
 48:         /* Adjust capabilities: depending on if SSL encryption is
 49:          * enabled or not */
 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:      * Add a set of authentication credentials.
 63:      *
 64:      * @param string $accountName  The user sAMAccountName to find.
 65:      * @param array $credentials   The credentials to be set.
 66:      *
 67:      * @throws Horde_Auth_Exception
 68:      */
 69:     public function addUser($accountName, $credentials)
 70:     {
 71:         /* Connect to the MSAD server. */
 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:             /* Set a default CN */
 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:      * Remove a set of authentication credentials.
119:      *
120:      * @param string $accountName  The user sAMAccountName to remove.
121:      * @param string $dn           TODO
122:      *
123:      * @throws Horde_Auth_Exception
124:      */
125:     public function removeUser($accountName, $dn = null)
126:     {
127:         /* Connect to the MSAD server. */
128:         $this->_connect();
129: 
130:         if (is_null($dn)) {
131:             /* Search for the user's full DN. */
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:      * Update a set of authentication credentials.
143:      *
144:      * @param string $oldID       The old userId.
145:      * @param string $newID       The new userId.
146:      * @param array $credentials  The new credentials
147:      *
148:      * @throws Horde_Auth_Exception
149:      */
150:     public function updateUser($oldId, $newId, $credentials, $olddn = null,
151:                                $newdn = null)
152:     {
153:         /* Connect to the MSAD server. */
154:         $this->_connect();
155: 
156:         if (isset($credentials['ldap'])) {
157:             $olddn = $credentials['ldap']['dn'];
158:         } else {
159:             /* Search for the user's full DN. */
160:             $dn = $this->_findDN($oldId);
161: 
162:             /* Encrypt the new password */
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:      * Reset a user's password. Used for example when the user does not
187:      * remember the existing password.
188:      *
189:      * @param string $user_id  The user id for which to reset the password.
190:      *
191:      * @return string  The new password on success.
192:      * @throws Horde_Auth_Exception
193:      */
194:     public function resetPassword($user_id)
195:     {
196:         /* Get a new random password. */
197:         $password = Horde_Auth::genRandomPassword() . '/';
198:         $this->updateUser($user_id, $user_id, array('userPassword' => $password));
199: 
200:         return $password;
201:     }
202: 
203:     /**
204:      * Does an ldap connect and binds as the guest user.
205:      *
206:      * @throws Horde_Auth_Exception
207:      */
208:     protected function _connect()
209:     {
210:         /* Connect to the MSAD server. */
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:      * Find the user dn
241:      *
242:      * @param string $userId  The user UID to find.
243:      *
244:      * @return string  The user's full DN
245:      */
246:     protected function _findDN($userId)
247:     {
248:         /* Search for the user's full DN. */
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:             /* Searching the tree is not successful */
259:             if (!$search) {
260:                 throw new Horde_Auth_Exception('Could not search the MSAD server.');
261:             }
262: 
263:             /* Fetch the search result */
264:             $result = @ldap_get_entries($this->_ds, $search);
265:             /* The result isn't empty: the DN was found */
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:         /* Be sure the horde userId is the configured one */
276:         $this->_credentials['userId'] = $result[0][$this->_params['authId']][0];
277: 
278:         return $result[0]['dn'];
279:     }
280: 
281: }
282: 
API documentation generated by ApiGen