xref: /dokuwiki/lib/plugins/authad/adLDAP/classes/adLDAPGroups.php (revision 76ce1169a0c8cbb18423b1581800b9aa1050ccd5)
1*76ce1169SAndreas Gohr<?php
2*76ce1169SAndreas Gohr/**
3*76ce1169SAndreas Gohr * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
4*76ce1169SAndreas Gohr * Version 4.0.4
5*76ce1169SAndreas Gohr *
6*76ce1169SAndreas Gohr * PHP Version 5 with SSL and LDAP support
7*76ce1169SAndreas Gohr *
8*76ce1169SAndreas Gohr * Written by Scott Barnett, Richard Hyland
9*76ce1169SAndreas Gohr *   email: scott@wiggumworld.com, adldap@richardhyland.com
10*76ce1169SAndreas Gohr *   http://adldap.sourceforge.net/
11*76ce1169SAndreas Gohr *
12*76ce1169SAndreas Gohr * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
13*76ce1169SAndreas Gohr *
14*76ce1169SAndreas Gohr * We'd appreciate any improvements or additions to be submitted back
15*76ce1169SAndreas Gohr * to benefit the entire community :)
16*76ce1169SAndreas Gohr *
17*76ce1169SAndreas Gohr * This library is free software; you can redistribute it and/or
18*76ce1169SAndreas Gohr * modify it under the terms of the GNU Lesser General Public
19*76ce1169SAndreas Gohr * License as published by the Free Software Foundation; either
20*76ce1169SAndreas Gohr * version 2.1 of the License.
21*76ce1169SAndreas Gohr *
22*76ce1169SAndreas Gohr * This library is distributed in the hope that it will be useful,
23*76ce1169SAndreas Gohr * but WITHOUT ANY WARRANTY; without even the implied warranty of
24*76ce1169SAndreas Gohr * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25*76ce1169SAndreas Gohr * Lesser General Public License for more details.
26*76ce1169SAndreas Gohr *
27*76ce1169SAndreas Gohr * @category ToolsAndUtilities
28*76ce1169SAndreas Gohr * @package adLDAP
29*76ce1169SAndreas Gohr * @subpackage Groups
30*76ce1169SAndreas Gohr * @author Scott Barnett, Richard Hyland
31*76ce1169SAndreas Gohr * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
32*76ce1169SAndreas Gohr * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
33*76ce1169SAndreas Gohr * @revision $Revision: 97 $
34*76ce1169SAndreas Gohr * @version 4.0.4
35*76ce1169SAndreas Gohr * @link http://adldap.sourceforge.net/
36*76ce1169SAndreas Gohr */
37*76ce1169SAndreas Gohrrequire_once(dirname(__FILE__) . '/../adLDAP.php');
38*76ce1169SAndreas Gohrrequire_once(dirname(__FILE__) . '/../collections/adLDAPGroupCollection.php');
39*76ce1169SAndreas Gohr
40*76ce1169SAndreas Gohr/**
41*76ce1169SAndreas Gohr* GROUP FUNCTIONS
42*76ce1169SAndreas Gohr*/
43*76ce1169SAndreas Gohrclass adLDAPGroups {
44*76ce1169SAndreas Gohr    /**
45*76ce1169SAndreas Gohr    * The current adLDAP connection via dependency injection
46*76ce1169SAndreas Gohr    *
47*76ce1169SAndreas Gohr    * @var adLDAP
48*76ce1169SAndreas Gohr    */
49*76ce1169SAndreas Gohr    protected $adldap;
50*76ce1169SAndreas Gohr
51*76ce1169SAndreas Gohr    public function __construct(adLDAP $adldap) {
52*76ce1169SAndreas Gohr        $this->adldap = $adldap;
53*76ce1169SAndreas Gohr    }
54*76ce1169SAndreas Gohr
55*76ce1169SAndreas Gohr    /**
56*76ce1169SAndreas Gohr    * Add a group to a group
57*76ce1169SAndreas Gohr    *
58*76ce1169SAndreas Gohr    * @param string $parent The parent group name
59*76ce1169SAndreas Gohr    * @param string $child The child group name
60*76ce1169SAndreas Gohr    * @return bool
61*76ce1169SAndreas Gohr    */
62*76ce1169SAndreas Gohr    public function addGroup($parent,$child){
63*76ce1169SAndreas Gohr
64*76ce1169SAndreas Gohr        // Find the parent group's dn
65*76ce1169SAndreas Gohr        $parentGroup = $this->ginfo($parent, array("cn"));
66*76ce1169SAndreas Gohr        if ($parentGroup[0]["dn"] === NULL){
67*76ce1169SAndreas Gohr            return false;
68*76ce1169SAndreas Gohr        }
69*76ce1169SAndreas Gohr        $parentDn = $parentGroup[0]["dn"];
70*76ce1169SAndreas Gohr
71*76ce1169SAndreas Gohr        // Find the child group's dn
72*76ce1169SAndreas Gohr        $childGroup = $this->info($child, array("cn"));
73*76ce1169SAndreas Gohr        if ($childGroup[0]["dn"] === NULL){
74*76ce1169SAndreas Gohr            return false;
75*76ce1169SAndreas Gohr        }
76*76ce1169SAndreas Gohr        $childDn = $childGroup[0]["dn"];
77*76ce1169SAndreas Gohr
78*76ce1169SAndreas Gohr        $add = array();
79*76ce1169SAndreas Gohr        $add["member"] = $childDn;
80*76ce1169SAndreas Gohr
81*76ce1169SAndreas Gohr        $result = @ldap_mod_add($this->adldap->getLdapConnection(), $parentDn, $add);
82*76ce1169SAndreas Gohr        if ($result == false) {
83*76ce1169SAndreas Gohr            return false;
84*76ce1169SAndreas Gohr        }
85*76ce1169SAndreas Gohr        return true;
86*76ce1169SAndreas Gohr    }
87*76ce1169SAndreas Gohr
88*76ce1169SAndreas Gohr    /**
89*76ce1169SAndreas Gohr    * Add a user to a group
90*76ce1169SAndreas Gohr    *
91*76ce1169SAndreas Gohr    * @param string $group The group to add the user to
92*76ce1169SAndreas Gohr    * @param string $user The user to add to the group
93*76ce1169SAndreas Gohr    * @param bool $isGUID Is the username passed a GUID or a samAccountName
94*76ce1169SAndreas Gohr    * @return bool
95*76ce1169SAndreas Gohr    */
96*76ce1169SAndreas Gohr    public function addUser($group, $user, $isGUID = false)
97*76ce1169SAndreas Gohr    {
98*76ce1169SAndreas Gohr        // Adding a user is a bit fiddly, we need to get the full DN of the user
99*76ce1169SAndreas Gohr        // and add it using the full DN of the group
100*76ce1169SAndreas Gohr
101*76ce1169SAndreas Gohr        // Find the user's dn
102*76ce1169SAndreas Gohr        $userDn = $this->adldap->user()->dn($user, $isGUID);
103*76ce1169SAndreas Gohr        if ($userDn === false) {
104*76ce1169SAndreas Gohr            return false;
105*76ce1169SAndreas Gohr        }
106*76ce1169SAndreas Gohr
107*76ce1169SAndreas Gohr        // Find the group's dn
108*76ce1169SAndreas Gohr        $groupInfo = $this->info($group, array("cn"));
109*76ce1169SAndreas Gohr        if ($groupInfo[0]["dn"] === NULL) {
110*76ce1169SAndreas Gohr            return false;
111*76ce1169SAndreas Gohr        }
112*76ce1169SAndreas Gohr        $groupDn = $groupInfo[0]["dn"];
113*76ce1169SAndreas Gohr
114*76ce1169SAndreas Gohr        $add = array();
115*76ce1169SAndreas Gohr        $add["member"] = $userDn;
116*76ce1169SAndreas Gohr
117*76ce1169SAndreas Gohr        $result = @ldap_mod_add($this->adldap->getLdapConnection(), $groupDn, $add);
118*76ce1169SAndreas Gohr        if ($result == false) {
119*76ce1169SAndreas Gohr            return false;
120*76ce1169SAndreas Gohr        }
121*76ce1169SAndreas Gohr        return true;
122*76ce1169SAndreas Gohr    }
123*76ce1169SAndreas Gohr
124*76ce1169SAndreas Gohr    /**
125*76ce1169SAndreas Gohr    * Add a contact to a group
126*76ce1169SAndreas Gohr    *
127*76ce1169SAndreas Gohr    * @param string $group The group to add the contact to
128*76ce1169SAndreas Gohr    * @param string $contactDn The DN of the contact to add
129*76ce1169SAndreas Gohr    * @return bool
130*76ce1169SAndreas Gohr    */
131*76ce1169SAndreas Gohr    public function addContact($group, $contactDn)
132*76ce1169SAndreas Gohr    {
133*76ce1169SAndreas Gohr        // To add a contact we take the contact's DN
134*76ce1169SAndreas Gohr        // and add it using the full DN of the group
135*76ce1169SAndreas Gohr
136*76ce1169SAndreas Gohr        // Find the group's dn
137*76ce1169SAndreas Gohr        $groupInfo = $this->info($group, array("cn"));
138*76ce1169SAndreas Gohr        if ($groupInfo[0]["dn"] === NULL) {
139*76ce1169SAndreas Gohr            return false;
140*76ce1169SAndreas Gohr        }
141*76ce1169SAndreas Gohr        $groupDn = $groupInfo[0]["dn"];
142*76ce1169SAndreas Gohr
143*76ce1169SAndreas Gohr        $add = array();
144*76ce1169SAndreas Gohr        $add["member"] = $contactDn;
145*76ce1169SAndreas Gohr
146*76ce1169SAndreas Gohr        $result = @ldap_mod_add($this->adldap->getLdapConnection(), $groupDn, $add);
147*76ce1169SAndreas Gohr        if ($result == false) {
148*76ce1169SAndreas Gohr            return false;
149*76ce1169SAndreas Gohr        }
150*76ce1169SAndreas Gohr        return true;
151*76ce1169SAndreas Gohr    }
152*76ce1169SAndreas Gohr
153*76ce1169SAndreas Gohr    /**
154*76ce1169SAndreas Gohr    * Create a group
155*76ce1169SAndreas Gohr    *
156*76ce1169SAndreas Gohr    * @param array $attributes Default attributes of the group
157*76ce1169SAndreas Gohr    * @return bool
158*76ce1169SAndreas Gohr    */
159*76ce1169SAndreas Gohr    public function create($attributes)
160*76ce1169SAndreas Gohr    {
161*76ce1169SAndreas Gohr        if (!is_array($attributes)){ return "Attributes must be an array"; }
162*76ce1169SAndreas Gohr        if (!array_key_exists("group_name", $attributes)){ return "Missing compulsory field [group_name]"; }
163*76ce1169SAndreas Gohr        if (!array_key_exists("container", $attributes)){ return "Missing compulsory field [container]"; }
164*76ce1169SAndreas Gohr        if (!array_key_exists("description", $attributes)){ return "Missing compulsory field [description]"; }
165*76ce1169SAndreas Gohr        if (!is_array($attributes["container"])){ return "Container attribute must be an array."; }
166*76ce1169SAndreas Gohr        $attributes["container"] = array_reverse($attributes["container"]);
167*76ce1169SAndreas Gohr
168*76ce1169SAndreas Gohr        //$member_array = array();
169*76ce1169SAndreas Gohr        //$member_array[0] = "cn=user1,cn=Users,dc=yourdomain,dc=com";
170*76ce1169SAndreas Gohr        //$member_array[1] = "cn=administrator,cn=Users,dc=yourdomain,dc=com";
171*76ce1169SAndreas Gohr
172*76ce1169SAndreas Gohr        $add = array();
173*76ce1169SAndreas Gohr        $add["cn"] = $attributes["group_name"];
174*76ce1169SAndreas Gohr        $add["samaccountname"] = $attributes["group_name"];
175*76ce1169SAndreas Gohr        $add["objectClass"] = "Group";
176*76ce1169SAndreas Gohr        $add["description"] = $attributes["description"];
177*76ce1169SAndreas Gohr        //$add["member"] = $member_array; UNTESTED
178*76ce1169SAndreas Gohr
179*76ce1169SAndreas Gohr        $container = "OU=" . implode(",OU=", $attributes["container"]);
180*76ce1169SAndreas Gohr        $result = ldap_add($this->adldap->getLdapConnection(), "CN=" . $add["cn"] . ", " . $container . "," . $this->adldap->getBaseDn(), $add);
181*76ce1169SAndreas Gohr        if ($result != true) {
182*76ce1169SAndreas Gohr            return false;
183*76ce1169SAndreas Gohr        }
184*76ce1169SAndreas Gohr        return true;
185*76ce1169SAndreas Gohr    }
186*76ce1169SAndreas Gohr
187*76ce1169SAndreas Gohr    /**
188*76ce1169SAndreas Gohr    * Delete a group account
189*76ce1169SAndreas Gohr    *
190*76ce1169SAndreas Gohr    * @param string $group The group to delete (please be careful here!)
191*76ce1169SAndreas Gohr    *
192*76ce1169SAndreas Gohr    * @return array
193*76ce1169SAndreas Gohr    */
194*76ce1169SAndreas Gohr    public function delete($group) {
195*76ce1169SAndreas Gohr        if (!$this->adldap->getLdapBind()){ return false; }
196*76ce1169SAndreas Gohr        if ($group === null){ return "Missing compulsory field [group]"; }
197*76ce1169SAndreas Gohr
198*76ce1169SAndreas Gohr        $groupInfo = $this->info($group, array("*"));
199*76ce1169SAndreas Gohr        $dn = $groupInfo[0]['distinguishedname'][0];
200*76ce1169SAndreas Gohr        $result = $this->adldap->folder()->delete($dn);
201*76ce1169SAndreas Gohr        if ($result !== true) {
202*76ce1169SAndreas Gohr            return false;
203*76ce1169SAndreas Gohr        } return true;
204*76ce1169SAndreas Gohr    }
205*76ce1169SAndreas Gohr
206*76ce1169SAndreas Gohr    /**
207*76ce1169SAndreas Gohr    * Remove a group from a group
208*76ce1169SAndreas Gohr    *
209*76ce1169SAndreas Gohr    * @param string $parent The parent group name
210*76ce1169SAndreas Gohr    * @param string $child The child group name
211*76ce1169SAndreas Gohr    * @return bool
212*76ce1169SAndreas Gohr    */
213*76ce1169SAndreas Gohr    public function removeGroup($parent , $child)
214*76ce1169SAndreas Gohr    {
215*76ce1169SAndreas Gohr
216*76ce1169SAndreas Gohr        // Find the parent dn
217*76ce1169SAndreas Gohr        $parentGroup = $this->info($parent, array("cn"));
218*76ce1169SAndreas Gohr        if ($parentGroup[0]["dn"] === NULL) {
219*76ce1169SAndreas Gohr            return false;
220*76ce1169SAndreas Gohr        }
221*76ce1169SAndreas Gohr        $parentDn = $parentGroup[0]["dn"];
222*76ce1169SAndreas Gohr
223*76ce1169SAndreas Gohr        // Find the child dn
224*76ce1169SAndreas Gohr        $childGroup = $this->info($child, array("cn"));
225*76ce1169SAndreas Gohr        if ($childGroup[0]["dn"] === NULL) {
226*76ce1169SAndreas Gohr            return false;
227*76ce1169SAndreas Gohr        }
228*76ce1169SAndreas Gohr        $childDn = $childGroup[0]["dn"];
229*76ce1169SAndreas Gohr
230*76ce1169SAndreas Gohr        $del = array();
231*76ce1169SAndreas Gohr        $del["member"] = $childDn;
232*76ce1169SAndreas Gohr
233*76ce1169SAndreas Gohr        $result = @ldap_mod_del($this->adldap->getLdapConnection(), $parentDn, $del);
234*76ce1169SAndreas Gohr        if ($result == false) {
235*76ce1169SAndreas Gohr            return false;
236*76ce1169SAndreas Gohr        }
237*76ce1169SAndreas Gohr        return true;
238*76ce1169SAndreas Gohr    }
239*76ce1169SAndreas Gohr
240*76ce1169SAndreas Gohr    /**
241*76ce1169SAndreas Gohr    * Remove a user from a group
242*76ce1169SAndreas Gohr    *
243*76ce1169SAndreas Gohr    * @param string $group The group to remove a user from
244*76ce1169SAndreas Gohr    * @param string $user The AD user to remove from the group
245*76ce1169SAndreas Gohr    * @param bool $isGUID Is the username passed a GUID or a samAccountName
246*76ce1169SAndreas Gohr    * @return bool
247*76ce1169SAndreas Gohr    */
248*76ce1169SAndreas Gohr    public function removeUser($group, $user, $isGUID = false)
249*76ce1169SAndreas Gohr    {
250*76ce1169SAndreas Gohr
251*76ce1169SAndreas Gohr        // Find the parent dn
252*76ce1169SAndreas Gohr        $groupInfo = $this->info($group, array("cn"));
253*76ce1169SAndreas Gohr        if ($groupInfo[0]["dn"] === NULL){
254*76ce1169SAndreas Gohr            return false;
255*76ce1169SAndreas Gohr        }
256*76ce1169SAndreas Gohr        $groupDn = $groupInfo[0]["dn"];
257*76ce1169SAndreas Gohr
258*76ce1169SAndreas Gohr        // Find the users dn
259*76ce1169SAndreas Gohr        $userDn = $this->adldap->user()->dn($user, $isGUID);
260*76ce1169SAndreas Gohr        if ($userDn === false) {
261*76ce1169SAndreas Gohr            return false;
262*76ce1169SAndreas Gohr        }
263*76ce1169SAndreas Gohr
264*76ce1169SAndreas Gohr        $del = array();
265*76ce1169SAndreas Gohr        $del["member"] = $userDn;
266*76ce1169SAndreas Gohr
267*76ce1169SAndreas Gohr        $result = @ldap_mod_del($this->adldap->getLdapConnection(), $groupDn, $del);
268*76ce1169SAndreas Gohr        if ($result == false) {
269*76ce1169SAndreas Gohr            return false;
270*76ce1169SAndreas Gohr        }
271*76ce1169SAndreas Gohr        return true;
272*76ce1169SAndreas Gohr    }
273*76ce1169SAndreas Gohr
274*76ce1169SAndreas Gohr    /**
275*76ce1169SAndreas Gohr    * Remove a contact from a group
276*76ce1169SAndreas Gohr    *
277*76ce1169SAndreas Gohr    * @param string $group The group to remove a user from
278*76ce1169SAndreas Gohr    * @param string $contactDn The DN of a contact to remove from the group
279*76ce1169SAndreas Gohr    * @return bool
280*76ce1169SAndreas Gohr    */
281*76ce1169SAndreas Gohr    public function removeContact($group, $contactDn)
282*76ce1169SAndreas Gohr    {
283*76ce1169SAndreas Gohr
284*76ce1169SAndreas Gohr        // Find the parent dn
285*76ce1169SAndreas Gohr        $groupInfo = $this->info($group, array("cn"));
286*76ce1169SAndreas Gohr        if ($groupInfo[0]["dn"] === NULL) {
287*76ce1169SAndreas Gohr            return false;
288*76ce1169SAndreas Gohr        }
289*76ce1169SAndreas Gohr        $groupDn = $groupInfo[0]["dn"];
290*76ce1169SAndreas Gohr
291*76ce1169SAndreas Gohr        $del = array();
292*76ce1169SAndreas Gohr        $del["member"] = $contactDn;
293*76ce1169SAndreas Gohr
294*76ce1169SAndreas Gohr        $result = @ldap_mod_del($this->adldap->getLdapConnection(), $groupDn, $del);
295*76ce1169SAndreas Gohr        if ($result == false) {
296*76ce1169SAndreas Gohr            return false;
297*76ce1169SAndreas Gohr        }
298*76ce1169SAndreas Gohr        return true;
299*76ce1169SAndreas Gohr    }
300*76ce1169SAndreas Gohr
301*76ce1169SAndreas Gohr    /**
302*76ce1169SAndreas Gohr    * Return a list of groups in a group
303*76ce1169SAndreas Gohr    *
304*76ce1169SAndreas Gohr    * @param string $group The group to query
305*76ce1169SAndreas Gohr    * @param bool $recursive Recursively get groups
306*76ce1169SAndreas Gohr    * @return array
307*76ce1169SAndreas Gohr    */
308*76ce1169SAndreas Gohr    public function inGroup($group, $recursive = NULL)
309*76ce1169SAndreas Gohr    {
310*76ce1169SAndreas Gohr        if (!$this->adldap->getLdapBind()){ return false; }
311*76ce1169SAndreas Gohr        if ($recursive === NULL){ $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it
312*76ce1169SAndreas Gohr
313*76ce1169SAndreas Gohr        // Search the directory for the members of a group
314*76ce1169SAndreas Gohr        $info = $this->info($group, array("member","cn"));
315*76ce1169SAndreas Gohr        $groups = $info[0]["member"];
316*76ce1169SAndreas Gohr        if (!is_array($groups)) {
317*76ce1169SAndreas Gohr            return false;
318*76ce1169SAndreas Gohr        }
319*76ce1169SAndreas Gohr
320*76ce1169SAndreas Gohr        $groupArray = array();
321*76ce1169SAndreas Gohr
322*76ce1169SAndreas Gohr        for ($i=0; $i<$groups["count"]; $i++){
323*76ce1169SAndreas Gohr             $filter = "(&(objectCategory=group)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($groups[$i]) . "))";
324*76ce1169SAndreas Gohr             $fields = array("samaccountname", "distinguishedname", "objectClass");
325*76ce1169SAndreas Gohr             $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
326*76ce1169SAndreas Gohr             $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
327*76ce1169SAndreas Gohr
328*76ce1169SAndreas Gohr             // not a person, look for a group
329*76ce1169SAndreas Gohr             if ($entries['count'] == 0 && $recursive == true) {
330*76ce1169SAndreas Gohr                $filter = "(&(objectCategory=group)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($groups[$i]) . "))";
331*76ce1169SAndreas Gohr                $fields = array("distinguishedname");
332*76ce1169SAndreas Gohr                $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
333*76ce1169SAndreas Gohr                $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
334*76ce1169SAndreas Gohr                if (!isset($entries[0]['distinguishedname'][0])) {
335*76ce1169SAndreas Gohr                    continue;
336*76ce1169SAndreas Gohr                }
337*76ce1169SAndreas Gohr                $subGroups = $this->inGroup($entries[0]['distinguishedname'][0], $recursive);
338*76ce1169SAndreas Gohr                if (is_array($subGroups)) {
339*76ce1169SAndreas Gohr                    $groupArray = array_merge($groupArray, $subGroups);
340*76ce1169SAndreas Gohr                    $groupArray = array_unique($groupArray);
341*76ce1169SAndreas Gohr                }
342*76ce1169SAndreas Gohr                continue;
343*76ce1169SAndreas Gohr             }
344*76ce1169SAndreas Gohr
345*76ce1169SAndreas Gohr             $groupArray[] = $entries[0]['distinguishedname'][0];
346*76ce1169SAndreas Gohr        }
347*76ce1169SAndreas Gohr        return $groupArray;
348*76ce1169SAndreas Gohr    }
349*76ce1169SAndreas Gohr
350*76ce1169SAndreas Gohr    /**
351*76ce1169SAndreas Gohr    * Return a list of members in a group
352*76ce1169SAndreas Gohr    *
353*76ce1169SAndreas Gohr    * @param string $group The group to query
354*76ce1169SAndreas Gohr    * @param bool $recursive Recursively get group members
355*76ce1169SAndreas Gohr    * @return array
356*76ce1169SAndreas Gohr    */
357*76ce1169SAndreas Gohr    public function members($group, $recursive = NULL)
358*76ce1169SAndreas Gohr    {
359*76ce1169SAndreas Gohr        if (!$this->adldap->getLdapBind()){ return false; }
360*76ce1169SAndreas Gohr        if ($recursive === NULL){ $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it
361*76ce1169SAndreas Gohr        // Search the directory for the members of a group
362*76ce1169SAndreas Gohr        $info = $this->info($group, array("member","cn"));
363*76ce1169SAndreas Gohr        $users = $info[0]["member"];
364*76ce1169SAndreas Gohr        if (!is_array($users)) {
365*76ce1169SAndreas Gohr            return false;
366*76ce1169SAndreas Gohr        }
367*76ce1169SAndreas Gohr
368*76ce1169SAndreas Gohr        $userArray = array();
369*76ce1169SAndreas Gohr
370*76ce1169SAndreas Gohr        for ($i=0; $i<$users["count"]; $i++){
371*76ce1169SAndreas Gohr             $filter = "(&(objectCategory=person)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($users[$i]) . "))";
372*76ce1169SAndreas Gohr             $fields = array("samaccountname", "distinguishedname", "objectClass");
373*76ce1169SAndreas Gohr             $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
374*76ce1169SAndreas Gohr             $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
375*76ce1169SAndreas Gohr
376*76ce1169SAndreas Gohr             // not a person, look for a group
377*76ce1169SAndreas Gohr             if ($entries['count'] == 0 && $recursive == true) {
378*76ce1169SAndreas Gohr                $filter = "(&(objectCategory=group)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($users[$i]) . "))";
379*76ce1169SAndreas Gohr                $fields = array("samaccountname");
380*76ce1169SAndreas Gohr                $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
381*76ce1169SAndreas Gohr                $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
382*76ce1169SAndreas Gohr                if (!isset($entries[0]['samaccountname'][0])) {
383*76ce1169SAndreas Gohr                    continue;
384*76ce1169SAndreas Gohr                }
385*76ce1169SAndreas Gohr                $subUsers = $this->members($entries[0]['samaccountname'][0], $recursive);
386*76ce1169SAndreas Gohr                if (is_array($subUsers)) {
387*76ce1169SAndreas Gohr                    $userArray = array_merge($userArray, $subUsers);
388*76ce1169SAndreas Gohr                    $userArray = array_unique($userArray);
389*76ce1169SAndreas Gohr                }
390*76ce1169SAndreas Gohr                continue;
391*76ce1169SAndreas Gohr             }
392*76ce1169SAndreas Gohr             else if ($entries['count'] == 0) {
393*76ce1169SAndreas Gohr                continue;
394*76ce1169SAndreas Gohr             }
395*76ce1169SAndreas Gohr
396*76ce1169SAndreas Gohr             if ((!isset($entries[0]['samaccountname'][0]) || $entries[0]['samaccountname'][0] === NULL) && $entries[0]['distinguishedname'][0] !== NULL) {
397*76ce1169SAndreas Gohr                 $userArray[] = $entries[0]['distinguishedname'][0];
398*76ce1169SAndreas Gohr             }
399*76ce1169SAndreas Gohr             else if ($entries[0]['samaccountname'][0] !== NULL) {
400*76ce1169SAndreas Gohr                $userArray[] = $entries[0]['samaccountname'][0];
401*76ce1169SAndreas Gohr             }
402*76ce1169SAndreas Gohr        }
403*76ce1169SAndreas Gohr        return $userArray;
404*76ce1169SAndreas Gohr    }
405*76ce1169SAndreas Gohr
406*76ce1169SAndreas Gohr    /**
407*76ce1169SAndreas Gohr    * Group Information.  Returns an array of raw information about a group.
408*76ce1169SAndreas Gohr    * The group name is case sensitive
409*76ce1169SAndreas Gohr    *
410*76ce1169SAndreas Gohr    * @param string $groupName The group name to retrieve info about
411*76ce1169SAndreas Gohr    * @param array $fields Fields to retrieve
412*76ce1169SAndreas Gohr    * @return array
413*76ce1169SAndreas Gohr    */
414*76ce1169SAndreas Gohr    public function info($groupName, $fields = NULL)
415*76ce1169SAndreas Gohr    {
416*76ce1169SAndreas Gohr        if ($groupName === NULL) { return false; }
417*76ce1169SAndreas Gohr        if (!$this->adldap->getLdapBind()) { return false; }
418*76ce1169SAndreas Gohr
419*76ce1169SAndreas Gohr        if (stristr($groupName, '+')) {
420*76ce1169SAndreas Gohr            $groupName = stripslashes($groupName);
421*76ce1169SAndreas Gohr        }
422*76ce1169SAndreas Gohr
423*76ce1169SAndreas Gohr        $filter = "(&(objectCategory=group)(name=" . $this->adldap->utilities()->ldapSlashes($groupName) . "))";
424*76ce1169SAndreas Gohr        if ($fields === NULL) {
425*76ce1169SAndreas Gohr            $fields = array("member","memberof","cn","description","distinguishedname","objectcategory","samaccountname");
426*76ce1169SAndreas Gohr        }
427*76ce1169SAndreas Gohr        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
428*76ce1169SAndreas Gohr        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
429*76ce1169SAndreas Gohr
430*76ce1169SAndreas Gohr        return $entries;
431*76ce1169SAndreas Gohr    }
432*76ce1169SAndreas Gohr
433*76ce1169SAndreas Gohr    /**
434*76ce1169SAndreas Gohr    * Group Information.  Returns an collection
435*76ce1169SAndreas Gohr    * The group name is case sensitive
436*76ce1169SAndreas Gohr    *
437*76ce1169SAndreas Gohr    * @param string $groupName The group name to retrieve info about
438*76ce1169SAndreas Gohr    * @param array $fields Fields to retrieve
439*76ce1169SAndreas Gohr    * @return adLDAPGroupCollection
440*76ce1169SAndreas Gohr    */
441*76ce1169SAndreas Gohr    public function infoCollection($groupName, $fields = NULL)
442*76ce1169SAndreas Gohr    {
443*76ce1169SAndreas Gohr        if ($groupName === NULL) { return false; }
444*76ce1169SAndreas Gohr        if (!$this->adldap->getLdapBind()) { return false; }
445*76ce1169SAndreas Gohr
446*76ce1169SAndreas Gohr        $info = $this->info($groupName, $fields);
447*76ce1169SAndreas Gohr        if ($info !== false) {
448*76ce1169SAndreas Gohr            $collection = new adLDAPGroupCollection($info, $this->adldap);
449*76ce1169SAndreas Gohr            return $collection;
450*76ce1169SAndreas Gohr        }
451*76ce1169SAndreas Gohr        return false;
452*76ce1169SAndreas Gohr    }
453*76ce1169SAndreas Gohr
454*76ce1169SAndreas Gohr    /**
455*76ce1169SAndreas Gohr    * Return a complete list of "groups in groups"
456*76ce1169SAndreas Gohr    *
457*76ce1169SAndreas Gohr    * @param string $group The group to get the list from
458*76ce1169SAndreas Gohr    * @return array
459*76ce1169SAndreas Gohr    */
460*76ce1169SAndreas Gohr    public function recursiveGroups($group)
461*76ce1169SAndreas Gohr    {
462*76ce1169SAndreas Gohr        if ($group === NULL) { return false; }
463*76ce1169SAndreas Gohr
464*76ce1169SAndreas Gohr        $stack = array();
465*76ce1169SAndreas Gohr        $processed = array();
466*76ce1169SAndreas Gohr        $retGroups = array();
467*76ce1169SAndreas Gohr
468*76ce1169SAndreas Gohr        array_push($stack, $group); // Initial Group to Start with
469*76ce1169SAndreas Gohr        while (count($stack) > 0) {
470*76ce1169SAndreas Gohr            $parent = array_pop($stack);
471*76ce1169SAndreas Gohr            array_push($processed, $parent);
472*76ce1169SAndreas Gohr
473*76ce1169SAndreas Gohr            $info = $this->info($parent, array("memberof"));
474*76ce1169SAndreas Gohr
475*76ce1169SAndreas Gohr            if (isset($info[0]["memberof"]) && is_array($info[0]["memberof"])) {
476*76ce1169SAndreas Gohr                $groups = $info[0]["memberof"];
477*76ce1169SAndreas Gohr                if ($groups) {
478*76ce1169SAndreas Gohr                    $groupNames = $this->adldap->utilities()->niceNames($groups);
479*76ce1169SAndreas Gohr                    $retGroups = array_merge($retGroups, $groupNames); //final groups to return
480*76ce1169SAndreas Gohr                    foreach ($groupNames as $id => $groupName) {
481*76ce1169SAndreas Gohr                        if (!in_array($groupName, $processed)) {
482*76ce1169SAndreas Gohr                            array_push($stack, $groupName);
483*76ce1169SAndreas Gohr                        }
484*76ce1169SAndreas Gohr                    }
485*76ce1169SAndreas Gohr                }
486*76ce1169SAndreas Gohr            }
487*76ce1169SAndreas Gohr        }
488*76ce1169SAndreas Gohr
489*76ce1169SAndreas Gohr        return $retGroups;
490*76ce1169SAndreas Gohr    }
491*76ce1169SAndreas Gohr
492*76ce1169SAndreas Gohr    /**
493*76ce1169SAndreas Gohr    * Returns a complete list of the groups in AD based on a SAM Account Type
494*76ce1169SAndreas Gohr    *
495*76ce1169SAndreas Gohr    * @param string $sAMAaccountType The account type to return
496*76ce1169SAndreas Gohr    * @param bool $includeDescription Whether to return a description
497*76ce1169SAndreas Gohr    * @param string $search Search parameters
498*76ce1169SAndreas Gohr    * @param bool $sorted Whether to sort the results
499*76ce1169SAndreas Gohr    * @return array
500*76ce1169SAndreas Gohr    */
501*76ce1169SAndreas Gohr    public function search($sAMAaccountType = adLDAP::ADLDAP_SECURITY_GLOBAL_GROUP, $includeDescription = false, $search = "*", $sorted = true) {
502*76ce1169SAndreas Gohr        if (!$this->adldap->getLdapBind()) { return false; }
503*76ce1169SAndreas Gohr
504*76ce1169SAndreas Gohr        $filter = '(&(objectCategory=group)';
505*76ce1169SAndreas Gohr        if ($sAMAaccountType !== null) {
506*76ce1169SAndreas Gohr            $filter .= '(samaccounttype='. $sAMAaccountType .')';
507*76ce1169SAndreas Gohr        }
508*76ce1169SAndreas Gohr        $filter .= '(cn=' . $search . '))';
509*76ce1169SAndreas Gohr        // Perform the search and grab all their details
510*76ce1169SAndreas Gohr        $fields = array("samaccountname", "description");
511*76ce1169SAndreas Gohr        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
512*76ce1169SAndreas Gohr        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
513*76ce1169SAndreas Gohr
514*76ce1169SAndreas Gohr        $groupsArray = array();
515*76ce1169SAndreas Gohr        for ($i=0; $i<$entries["count"]; $i++){
516*76ce1169SAndreas Gohr            if ($includeDescription && strlen($entries[$i]["description"][0]) > 0 ) {
517*76ce1169SAndreas Gohr                $groupsArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["description"][0];
518*76ce1169SAndreas Gohr            }
519*76ce1169SAndreas Gohr            else if ($includeDescription){
520*76ce1169SAndreas Gohr                $groupsArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["samaccountname"][0];
521*76ce1169SAndreas Gohr            }
522*76ce1169SAndreas Gohr            else {
523*76ce1169SAndreas Gohr                array_push($groupsArray, $entries[$i]["samaccountname"][0]);
524*76ce1169SAndreas Gohr            }
525*76ce1169SAndreas Gohr        }
526*76ce1169SAndreas Gohr        if ($sorted) {
527*76ce1169SAndreas Gohr            asort($groupsArray);
528*76ce1169SAndreas Gohr        }
529*76ce1169SAndreas Gohr        return $groupsArray;
530*76ce1169SAndreas Gohr    }
531*76ce1169SAndreas Gohr
532*76ce1169SAndreas Gohr    /**
533*76ce1169SAndreas Gohr    * Returns a complete list of all groups in AD
534*76ce1169SAndreas Gohr    *
535*76ce1169SAndreas Gohr    * @param bool $includeDescription Whether to return a description
536*76ce1169SAndreas Gohr    * @param string $search Search parameters
537*76ce1169SAndreas Gohr    * @param bool $sorted Whether to sort the results
538*76ce1169SAndreas Gohr    * @return array
539*76ce1169SAndreas Gohr    */
540*76ce1169SAndreas Gohr    public function all($includeDescription = false, $search = "*", $sorted = true){
541*76ce1169SAndreas Gohr        $groupsArray = $this->search(null, $includeDescription, $search, $sorted);
542*76ce1169SAndreas Gohr        return $groupsArray;
543*76ce1169SAndreas Gohr    }
544*76ce1169SAndreas Gohr
545*76ce1169SAndreas Gohr    /**
546*76ce1169SAndreas Gohr    * Returns a complete list of security groups in AD
547*76ce1169SAndreas Gohr    *
548*76ce1169SAndreas Gohr    * @param bool $includeDescription Whether to return a description
549*76ce1169SAndreas Gohr    * @param string $search Search parameters
550*76ce1169SAndreas Gohr    * @param bool $sorted Whether to sort the results
551*76ce1169SAndreas Gohr    * @return array
552*76ce1169SAndreas Gohr    */
553*76ce1169SAndreas Gohr    public function allSecurity($includeDescription = false, $search = "*", $sorted = true){
554*76ce1169SAndreas Gohr        $groupsArray = $this->search(adLDAP::ADLDAP_SECURITY_GLOBAL_GROUP, $includeDescription, $search, $sorted);
555*76ce1169SAndreas Gohr        return $groupsArray;
556*76ce1169SAndreas Gohr    }
557*76ce1169SAndreas Gohr
558*76ce1169SAndreas Gohr    /**
559*76ce1169SAndreas Gohr    * Returns a complete list of distribution lists in AD
560*76ce1169SAndreas Gohr    *
561*76ce1169SAndreas Gohr    * @param bool $includeDescription Whether to return a description
562*76ce1169SAndreas Gohr    * @param string $search Search parameters
563*76ce1169SAndreas Gohr    * @param bool $sorted Whether to sort the results
564*76ce1169SAndreas Gohr    * @return array
565*76ce1169SAndreas Gohr    */
566*76ce1169SAndreas Gohr    public function allDistribution($includeDescription = false, $search = "*", $sorted = true){
567*76ce1169SAndreas Gohr        $groupsArray = $this->search(adLDAP::ADLDAP_DISTRIBUTION_GROUP, $includeDescription, $search, $sorted);
568*76ce1169SAndreas Gohr        return $groupsArray;
569*76ce1169SAndreas Gohr    }
570*76ce1169SAndreas Gohr
571*76ce1169SAndreas Gohr    /**
572*76ce1169SAndreas Gohr    * Coping with AD not returning the primary group
573*76ce1169SAndreas Gohr    * http://support.microsoft.com/?kbid=321360
574*76ce1169SAndreas Gohr    *
575*76ce1169SAndreas Gohr    * This is a re-write based on code submitted by Bruce which prevents the
576*76ce1169SAndreas Gohr    * need to search each security group to find the true primary group
577*76ce1169SAndreas Gohr    *
578*76ce1169SAndreas Gohr    * @param string $gid Group ID
579*76ce1169SAndreas Gohr    * @param string $usersid User's Object SID
580*76ce1169SAndreas Gohr    * @return mixed
581*76ce1169SAndreas Gohr    */
582*76ce1169SAndreas Gohr    public function getPrimaryGroup($gid, $usersid)
583*76ce1169SAndreas Gohr    {
584*76ce1169SAndreas Gohr        if ($gid === NULL || $usersid === NULL) { return false; }
585*76ce1169SAndreas Gohr        $sr = false;
586*76ce1169SAndreas Gohr
587*76ce1169SAndreas Gohr        $gsid = substr_replace($usersid, pack('V',$gid), strlen($usersid)-4,4);
588*76ce1169SAndreas Gohr        $filter = '(objectsid=' . $this->adldap->utilities()->getTextSID($gsid).')';
589*76ce1169SAndreas Gohr        $fields = array("samaccountname","distinguishedname");
590*76ce1169SAndreas Gohr        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
591*76ce1169SAndreas Gohr        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
592*76ce1169SAndreas Gohr
593*76ce1169SAndreas Gohr        if (isset($entries[0]['distinguishedname'][0])) {
594*76ce1169SAndreas Gohr            return $entries[0]['distinguishedname'][0];
595*76ce1169SAndreas Gohr        }
596*76ce1169SAndreas Gohr        return false;
597*76ce1169SAndreas Gohr     }
598*76ce1169SAndreas Gohr
599*76ce1169SAndreas Gohr     /**
600*76ce1169SAndreas Gohr    * Coping with AD not returning the primary group
601*76ce1169SAndreas Gohr    * http://support.microsoft.com/?kbid=321360
602*76ce1169SAndreas Gohr    *
603*76ce1169SAndreas Gohr    * For some reason it's not possible to search on primarygrouptoken=XXX
604*76ce1169SAndreas Gohr    * If someone can show otherwise, I'd like to know about it :)
605*76ce1169SAndreas Gohr    * this way is resource intensive and generally a pain in the @#%^
606*76ce1169SAndreas Gohr    *
607*76ce1169SAndreas Gohr    * @deprecated deprecated since version 3.1, see get get_primary_group
608*76ce1169SAndreas Gohr    * @param string $gid Group ID
609*76ce1169SAndreas Gohr    * @return string
610*76ce1169SAndreas Gohr    */
611*76ce1169SAndreas Gohr    public function cn($gid){
612*76ce1169SAndreas Gohr        if ($gid === NULL) { return false; }
613*76ce1169SAndreas Gohr        $sr = false;
614*76ce1169SAndreas Gohr        $r = '';
615*76ce1169SAndreas Gohr
616*76ce1169SAndreas Gohr        $filter = "(&(objectCategory=group)(samaccounttype=" . adLDAP::ADLDAP_SECURITY_GLOBAL_GROUP . "))";
617*76ce1169SAndreas Gohr        $fields = array("primarygrouptoken", "samaccountname", "distinguishedname");
618*76ce1169SAndreas Gohr        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
619*76ce1169SAndreas Gohr        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
620*76ce1169SAndreas Gohr
621*76ce1169SAndreas Gohr        for ($i=0; $i<$entries["count"]; $i++){
622*76ce1169SAndreas Gohr            if ($entries[$i]["primarygrouptoken"][0] == $gid) {
623*76ce1169SAndreas Gohr                $r = $entries[$i]["distinguishedname"][0];
624*76ce1169SAndreas Gohr                $i = $entries["count"];
625*76ce1169SAndreas Gohr            }
626*76ce1169SAndreas Gohr        }
627*76ce1169SAndreas Gohr
628*76ce1169SAndreas Gohr        return $r;
629*76ce1169SAndreas Gohr    }
630*76ce1169SAndreas Gohr}
631*76ce1169SAndreas Gohr?>
632