Commit ae61c83d398710db0eedeb6b67ddcee03a6ff580

Authored by Michael Joseph
1 parent 91a3f245

moved to lib/authentication


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