Commit 0540bd75aee7915728beba66945feddf8add1204

Authored by Neil Blakey-Milner
1 parent 52ad2632

Remove unused class.AuthLdap.php


git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@5032 c91229c3-7414-0410-bfa2-8a42b809f60b
lib/authentication/class.AuthLdap.php deleted
1   -<?php
2   -/**
3   - * class.AuthLdap.php , version 0.1
4   - * Mark Round, December 2002 - http://www.markround.com/unix
5   - * Provides LDAP authentication and user functions.
6   - *
7   - * Not intended as a full-blown LDAP access class - but it does provide
8   - * several useful functions for dealing with users.
9   - * Note - this works out of the box on Sun's iPlanet Directory Server - but
10   - * an ACL has to be defined giving all users the ability to change their
11   - * password (userPassword attribute).
12   - * See the README file for more information and examples.
13   - *
14   - * This program is free software; you can redistribute it and/or modify
15   - * it under the terms of the GNU General Public License as published by
16   - * the Free Software Foundation; using version 2 of the License.
17   - *
18   - *
19   - * This program is distributed in the hope that it will be useful,
20   - * but WITHOUT ANY WARRANTY; without even the implied warranty of
21   - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22   - * GNU General Public License for more details.
23   - *
24   - * You should have received a copy of the GNU General Public License
25   - * along with this program; if not, write to the Free Software
26   - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27   - *
28   - * ChangeLog
29   - * ---------
30   - * version 0.2, 11.04.2003, Michael Joseph <michael@jamwarehouse.com>
31   - * - Added switches and workarounds for Active Directory integration
32   - * - Change documentation to phpdoc style (http://phpdocu.sourceforge.net)
33   - * - Added a constructor
34   - * - Added an attribute array parameter to the getUsers method
35   - * 20040909, Daniel Patrick <daniel@geekmobile.biz>
36   - * - Added server type OpenLDAP2
37   - * - Added support for OpenLDAP2 servers that deny Anonymous Bind
38   - * - Added support for OpenLDAP2 servers that deny LDAPv2 protocol
39   - */
40   -
41   -class AuthLdap {
42   -
43   - // 1.1 Public properties -----------------------------------------------------
44   - /**
45   - * Array of server IP address or hostnames
46   - */
47   - var $server;
48   - /**
49   - * The base DN (e.g. "dc=foo,dc=com")
50   - */
51   - var $dn;
52   - /**
53   - * the directory server, currently supports iPlanet and Active Directory
54   - */
55   - var $serverType;
56   - /**
57   - * Active Directory authenticates using user@domain
58   - */
59   - var $domain;
60   - /**
61   - * The user to authenticate with when searching
62   - * Active Directory doesn't support anonymous access
63   - */
64   - var $searchUser;
65   - /**
66   - * The password to authenticate with when searching
67   - * Active Directory doesn't support anonymous access
68   - */
69   - var $searchPassword;
70   - /**
71   - * Where the user records are kept
72   - */
73   - var $people;
74   - /**
75   - * Where the group definitions are kept
76   - */
77   - var $groups;
78   - /**
79   - * The last error code returned by the LDAP server
80   - */
81   - var $ldapErrorCode;
82   - /**
83   - * Text of the error message
84   - */
85   - var $ldapErrorText;
86   -
87   - // 1.2 Private properties ----------------------------------------------------
88   - /**
89   - * The internal LDAP connection handle
90   - */
91   - var $connection;
92   - /**
93   - * Result of any connections etc.
94   - */
95   - var $result;
96   -
97   - /**
98   - * Constructor- creates a new instance of the authentication class
99   - *
100   - * @param string the ldap server to connect to
101   - * @param string the base dn
102   - * @param string the server type- current supports iPlanet and ActiveDirectory
103   - * @param string the domain to use when authenticating against Active Directory
104   - * @param string the username to authenticate with when searching if anonymous binding is not supported
105   - * @param string the password to authenticate with when searching if anonymous binding is not supported
106   - */
107   - function AuthLdap ($aLdapServers, $sBaseDN, $sServerType, $sDomain = "", $searchUser = "", $searchPassword = "") {
108   - if (is_string($aLdapServers)) {
109   - $this->server = array($aLdapServers);
110   - } elseif (is_array($aLdapServers)) {
111   - $this->server = $aLdapServers;
112   - }
113   - $this->dn = $sBaseDN;
114   - $this->serverType = $sServerType;
115   - $this->domain = $sDomain;
116   - $this->searchUser = $searchUser;
117   - $this->searchPassword = $searchPassword;
118   - }
119   -
120   - // 2.1 Connection handling methods -------------------------------------------
121   -
122   - /**
123   - * 2.1.1 : Connects to the server. Just creates a connection which is used
124   - * in all later access to the LDAP server. If it can't connect and bind
125   - * anonymously, it creates an error code of -1. Returns true if connected,
126   - * false if failed. Takes an array of possible servers - if one doesn't work,
127   - * it tries the next and so on.
128   - */
129   - function connect() {
130   - foreach ($this->server as $key => $host) {
131   - $this->connection = ldap_connect( $host);
132   - if ( $this->serverType == "OpenLDAP2" ) {
133   - ldap_set_option($this->connection, LDAP_OPT_PROTOCOL_VERSION, 3);
134   - }
135   - if ( $this->connection) {
136   - if (($this->serverType == "ActiveDirectory") ||
137   - (($this->serverType == "OpenLDAP2") &&
138   - (!$this->searchUser == "") &&
139   - (!$this->searchPassword == ""))) {
140   - return true;
141   - } else {
142   - // Connected, now try binding anonymously
143   - $this->result=@ldap_bind( $this->connection);
144   - }
145   - return true;
146   - }
147   - }
148   -
149   - $this->ldapErrorCode = -1;
150   - $this->ldapErrorText = "Unable to connect to any server";
151   - return false;
152   - }
153   -
154   - /**
155   - * 2.1.2 : Simply closes the connection set up earlier.
156   - * Returns true if OK, false if there was an error.
157   - */
158   - function close() {
159   - if ( !@ldap_close( $this->connection)) {
160   - $this->ldapErrorCode = ldap_errno( $this->connection);
161   - $this->ldapErrorText = ldap_error( $this->connection);
162   - return false;
163   - } else {
164   - return true;
165   - }
166   - }
167   -
168   - /**
169   - * 2.1.3 : Anonymously binds to the connection. After this is done,
170   - * queries and searches can be done - but read-only.
171   - */
172   - function bind() {
173   - if ( !$this->result=@ldap_bind( $this->connection)) {
174   - $this->ldapErrorCode = ldap_errno( $this->connection);
175   - $this->ldapErrorText = ldap_error( $this->connection);
176   - return false;
177   - } else {
178   - return true;
179   - }
180   - }
181   -
182   -
183   -
184   - /**
185   - * 2.1.4 : Binds as an authenticated user, which usually allows for write
186   - * access. The FULL dn must be passed. For a directory manager, this is
187   - * "cn=Directory Manager" under iPlanet. For a user, it will be something
188   - * like "uid=jbloggs,ou=People,dc=foo,dc=com".
189   - */
190   - function authBind( $bindDn,$pass) {
191   - if ( !$this->result = @ldap_bind( $this->connection,$bindDn,$pass)) {
192   - $this->ldapErrorCode = ldap_errno( $this->connection);
193   - $this->ldapErrorText = ldap_error( $this->connection);
194   - return false;
195   - } else {
196   - return true;
197   - }
198   - }
199   -
200   - // 2.2 Password methods ------------------------------------------------------
201   -
202   - /**
203   - * 2.2.1 : Checks a username and password - does this by logging on to the
204   - * server as a user - specified in the DN. There are several reasons why
205   - * this login could fail - these are listed below.
206   - */
207   - function checkPass( $uname,$pass) {
208   - /* Construct the full DN, eg:-
209   - ** "uid=username, ou=People, dc=orgname,dc=com"
210   - */
211   - if ($this->serverType == "ActiveDirectory") {
212   - $checkDn = "$uname@$this->domain";
213   - } else {
214   - $checkDn = $this->getUserIdentifier() . "=$uname, " . $this->setDn(true);
215   - }
216   - // Try and connect...
217   - $this->result = @ldap_bind( $this->connection,$checkDn,$pass);
218   - if ( $this->result) {
219   - // Connected OK - login credentials are fine!
220   - return true;
221   - } else {
222   - /* Login failed. Return false, together with the error code and text from
223   - ** the LDAP server. The common error codes and reasons are listed below :
224   - ** (for iPlanet, other servers may differ)
225   - ** 19 - Account locked out (too many invalid login attempts)
226   - ** 32 - User does not exist
227   - ** 49 - Wrong password
228   - ** 53 - Account inactive (manually locked out by administrator)
229   - */
230   - $this->ldapErrorCode = ldap_errno( $this->connection);
231   - $this->ldapErrorText = ldap_error( $this->connection);
232   - return false;
233   - }
234   - }
235   -
236   -
237   - /**
238   - * 2.2.2 : Allows a password to be changed. Note that on most LDAP servers,
239   - * a new ACL must be defined giving users the ability to modify their
240   - * password attribute (userPassword). Otherwise this will fail.
241   - */
242   - function changePass( $uname,$oldPass,$newPass) {
243   - // builds the appropriate dn, based on whether $this->people and/or $this->group is set
244   - if ($this->serverType == "ActiveDirectory") {
245   - $checkDn = "$uname@$this->domain";
246   - } else {
247   - $checkDn = $this->getUserIdentifier() . "=$uname, " . $this->setDn(true);
248   - }
249   - $this->result = @ldap_bind( $this->connection,$checkDn,$oldPass);
250   -
251   - if ( $this->result) {
252   - // Connected OK - Now modify the password...
253   - $info["userPassword"] = $newPass;
254   - $this->result = @ldap_modify( $this->connection, $checkDn, $info);
255   - if ( $this->result) {
256   - // Change went OK
257   - return true;
258   - } else {
259   - // Couldn't change password...
260   - $this->ldapErrorCode = ldap_errno( $this->connection);
261   - $this->ldapErrorText = ldap_error( $this->connection);
262   - return false;
263   - }
264   - } else {
265   - // Login failed - see checkPass method for common error codes
266   - $this->ldapErrorCode = ldap_errno( $this->connection);
267   - $this->ldapErrorText = ldap_error( $this->connection);
268   - return false;
269   - }
270   - }
271   -
272   -
273   - /**
274   - * 2.2.3 : Returns days until the password will expire.
275   - * We have to explicitly state this is what we want returned from the
276   - * LDAP server - by default, it will only send back the "basic"
277   - * attributes.
278   - */
279   - function checkPassAge ( $uname) {
280   -
281   - $results[0] = "passwordexpirationtime";
282   - // builds the appropriate dn, based on whether $this->people and/or $this->group is set
283   - $checkDn = $this->setDn(true);
284   - $this->result = @ldap_search( $this->connection,$checkDn,$this->getUserIdentifier()."=$uname",$results);
285   -
286   - if ( !$info=@ldap_get_entries( $this->connection, $this->result)) {
287   - $this->ldapErrorCode = ldap_errno( $this->connection);
288   - $this->ldapErrorText = ldap_error( $this->connection);
289   - return false;
290   - } else {
291   - /* Now work out how many days remaining....
292   - ** Yes, it's very verbose code but I left it like this so it can easily
293   - ** be modified for your needs.
294   - */
295   - $date = $info[0]["passwordexpirationtime"][0];
296   - $year = substr( $date,0,4);
297   - $month = substr( $date,4,2);
298   - $day = substr( $date,6,2);
299   - $hour = substr( $date,8,2);
300   - $min = substr( $date,10,2);
301   - $sec = substr( $date,12,2);
302   -
303   - $timestamp = mktime( $hour,$min,$sec,$month,$day,$year);
304   - $today = mktime();
305   - $diff = $timestamp-$today;
306   - return round( ( ( ( $diff/60)/60)/24));
307   - }
308   - }
309   -
310   - // 2.3 Group methods ---------------------------------------------------------
311   -
312   - /**
313   - * 2.3.1 : Checks to see if a user is in a given group. If so, it returns
314   - * true, and returns false if the user isn't in the group, or any other
315   - * error occurs (eg:- no such user, no group by that name etc.)
316   - */
317   - function checkGroup ( $uname,$group) {
318   - // builds the appropriate dn, based on whether $this->people and/or $this->group is set
319   - $checkDn = $this->setDn(false);
320   -
321   - // We need to search for the group in order to get it's entry.
322   - $this->result = @ldap_search( $this->connection, $checkDn, "cn=" .$group);
323   - $info = @ldap_get_entries( $this->connection, $this->result);
324   -
325   - // Only one entry should be returned(no groups will have the same name)
326   - $entry = ldap_first_entry( $this->connection,$this->result);
327   -
328   - if ( !$entry) {
329   - $this->ldapErrorCode = ldap_errno( $this->connection);
330   - $this->ldapErrorText = ldap_error( $this->connection);
331   - return false; // Couldn't find the group...
332   - }
333   - // Get all the member DNs
334   - if ( !$values = @ldap_get_values( $this->connection, $entry, "uniqueMember")) {
335   - $this->ldapErrorCode = ldap_errno( $this->connection);
336   - $this->ldapErrorText = ldap_error( $this->connection);
337   - return false; // No users in the group
338   - }
339   -
340   - foreach ( $values as $key => $value) {
341   - /* Loop through all members - see if the uname is there...
342   - ** Also check for sub-groups - this allows us to define a group as
343   - ** having membership of another group.
344   - ** FIXME:- This is pretty ugly code and unoptimised. It takes ages
345   - ** to search if you have sub-groups.
346   - */
347   - list( $cn,$ou) = explode( ",",$value);
348   - list( $ou_l,$ou_r) = explode( "=",$ou);
349   -
350   - if ( $this->groups==$ou_r) {
351   - list( $cn_l,$cn_r) = explode( "=",$cn);
352   - // OK, So we now check the sub-group...
353   - if ( $this->checkGroup ( $uname,$cn_r)) {
354   - return true;
355   - }
356   - }
357   -
358   - if ( preg_match( "/$uname/i",$value)) {
359   - return true;
360   - }
361   - }
362   - }
363   -
364   - // 2.4 Attribute methods -----------------------------------------------------
365   - /**
366   - * 2.4.1 : Returns an array containing a set of attribute values.
367   - * For most searches, this will just be one row, but sometimes multiple
368   - * results are returned (eg:- multiple email addresses)
369   - */
370   - function getAttribute ( $uname,$attribute) {
371   - // builds the appropriate dn, based on whether $this->people and/or $this->group is set
372   - $checkDn = $this->setDn( true);
373   - $results[0] = $attribute;
374   -
375   - // We need to search for this user in order to get their entry.
376   - $this->result = @ldap_search( $this->connection,$checkDn,$this->getUserIdentifier()."=$uname",$results);
377   - $info = ldap_get_entries( $this->connection, $this->result);
378   -
379   - // Only one entry should ever be returned (no user will have the same uid)
380   - $entry = ldap_first_entry( $this->connection, $this->result);
381   -
382   - if ( !$entry) {
383   - $this->ldapErrorCode = -1;
384   - $this->ldapErrorText = "Couldn't find user";
385   - return false; // Couldn't find the user...
386   - }
387   -
388   - // Get all the member DNs
389   - if ( !$values = @ldap_get_values( $this->connection, $entry, $attribute)) {
390   - $this->ldapErrorCode = ldap_errno( $this->connection);
391   - $this->ldapErrorText = ldap_error( $this->connection);
392   - return false; // No matching attributes
393   - }
394   -
395   - // Return an array containing the attributes.
396   - return $values;
397   - }
398   -
399   - /**
400   - * 2.4.2 : Allows an attribute value to be set.
401   - * This can only usually be done after an authenticated bind as a
402   - * directory manager - otherwise, read/write access will not be granted.
403   - */
404   - function setAttribute( $uname, $attribute, $value) {
405   - // Construct a full DN...
406   - // builds the appropriate dn, based on whether $this->people and/or $this->group is set
407   - $attrib_dn = $this->getUserIdentifier()."=$uname," . $this->setDn(true);
408   -
409   - $info[$attribute] = $value;
410   - // Change attribute
411   - $this->result = ldap_modify( $this->connection, $attrib_dn, $info);
412   - if ( $this->result) {
413   - // Change went OK
414   - return true;
415   - } else {
416   - // Couldn't change password...
417   - $this->ldapErrorCode = ldap_errno( $this->connection);
418   - $this->ldapErrorText = ldap_error( $this->connection);
419   - return false;
420   - }
421   - }
422   -
423   - // 2.5 User methods ----------------------------------------------------------
424   - /**
425   - * 2.5.1 : Returns an array containing a details of users, sorted by
426   - * username. The search criteria is a standard LDAP query - * returns all
427   - * users. The $attributeArray variable contains the required user detail field names
428   - */
429   - function getUsers( $search, $attributeArray) {
430   - // builds the appropriate dn, based on whether $this->people and/or $this->group is set
431   - $checkDn = $this->setDn( true);
432   -
433   - // Perform the search and get the entry handles
434   -
435   - // if the directory is AD, then bind first with the search user first
436   - if (($this->serverType == "ActiveDirectory") ||
437   - (($this->serverType == "OpenLDAP2") &&
438   - (!$this->searchUser == "") &&
439   - (!$this->searchPassword == ""))) {
440   - $this->authBind($this->searchUser, $this->searchPassword);
441   - }
442   - $this->result = ldap_search( $this->connection, $checkDn, $this->getUserIdentifier() . "=$search");
443   -
444   - $info = ldap_get_entries( $this->connection, $this->result);
445   - for( $i = 0; $i < $info["count"]; $i++) {
446   - // Get the username, and create an array indexed by it...
447   - // Modify these as you see fit.
448   - $uname = $info[$i][$this->getUserIdentifier()][0];
449   - // add to the array for each attribute in my list
450   - for ( $j = 0; $j < count( $attributeArray); $j++) {
451   - if (strtolower($attributeArray[$j]) == "dn") {
452   - $userslist["$uname"]["$attributeArray[$j]"] = $info[$i][strtolower($attributeArray[$j])];
453   - } else {
454   - $userslist["$uname"]["$attributeArray[$j]"] = $info[$i][strtolower($attributeArray[$j])][0];
455   - }
456   - }
457   - }
458   -
459   - if ( !@asort( $userslist)) {
460   - /* Sort into alphabetical order. If this fails, it's because there
461   - ** were no results returned (array is empty) - so just return false.
462   - */
463   - $this->ldapErrorCode = -1;
464   - $this->ldapErrorText = "No users found matching search criteria ".$search;
465   - return false;
466   - }
467   - return $userslist;
468   - }
469   -
470   - // 2.6 helper methods
471   -
472   - /**
473   - * Sets and returns the appropriate dn, based on whether there
474   - * are values in $this->people and $this->groups.
475   - *
476   - * @param boolean specifies whether to build a groups dn or a people dn
477   - * @return string if true ou=$this->people,$this->dn, else ou=$this->groups,$this->dn
478   - */
479   - function setDn($peopleOrGroups) {
480   -
481   - if ($peopleOrGroups) {
482   - if ( isset($this->people) && (strlen($this->people) > 0) ) {
483   - $checkDn = "ou=" .$this->people. ", " .$this->dn;
484   - }
485   - } else {
486   - if ( isset($this->groups) && (strlen($this->groups) > 0) ) {
487   - $checkDn = "ou=" .$this->groups. ", " .$this->dn;
488   - }
489   - }
490   -
491   - if ( !isset($checkDn) ) {
492   - $checkDn = $this->dn;
493   - }
494   - return $checkDn;
495   - }
496   -
497   - /**
498   - * Returns the correct user identifier to use, based on the ldap server type
499   - */
500   - function getUserIdentifier() {
501   - if ($this->serverType == "ActiveDirectory") {
502   - return "samaccountname";
503   - } else {
504   - return "uid";
505   - }
506   - }
507   -} // End of class
508   -?>