ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
AttributeAddUsersGroups.php
Go to the documentation of this file.
1 <?php
2 
12 {
22  public function process(&$request)
23  {
24  assert(is_array($request));
25  assert(array_key_exists('Attributes', $request));
26 
27  // Log the process
29  $this->title . 'Attempting to get the users groups...'
30  );
31 
32  // Reference the attributes, just to make the names shorter
33  $attributes =& $request['Attributes'];
35 
36  // Get the users groups from LDAP
37  $groups = $this->getGroups($attributes);
38 
39  // Make the array if it is not set already
40  if (!isset($attributes[$map['groups']])) {
41  $attributes[$map['groups']] = array();
42  }
43 
44  // Must be an array, else cannot merge groups
45  if (!is_array($attributes[$map['groups']])) {
47  $this->title . 'The group attribute [' . $map['groups'] .
48  '] is not an array of group DNs. ' . $this->var_export($attributes[$map['groups']])
49  );
50  }
51 
52  // Add the users group(s)
53  $group_attribute =& $attributes[$map['groups']];
54  $group_attribute = array_merge($group_attribute, $groups);
55  $group_attribute = array_unique($group_attribute);
56 
57  // All done
59  $this->title . 'Added users groups to the group attribute [' .
60  $map['groups'] . ']: ' . implode('; ', $groups)
61  );
62  }
63 
64 
76  protected function getGroups($attributes)
77  {
78  // Log the request
80  $this->title . 'Checking for groups based on the best method for the LDAP product.'
81  );
82 
83  // Based on the directory service, search LDAP for groups
84  // If any attributes are needed, prepare them before calling search method
85  switch ($this->product) {
86  case 'ACTIVEDIRECTORY':
87  $groups = $this->getGroupsActiveDirectory($attributes);
88  break;
89  case 'OPENLDAP':
90  $groups = $this->getGroupsOpenLdap($attributes);
91  break;
92  default:
93  // Reference the map, just to make the name shorter
95 
96  // Log the general search
98  $this->title . 'Searching LDAP using the default search method.'
99  );
100 
101  // Make sure the defined memberOf attribute exists
102  if (!isset($attributes[$map['memberof']])) {
103  throw new SimpleSAML_Error_Exception(
104  $this->title . 'The memberof attribute [' . $map['memberof'] .
105  '] is not defined in the user\'s Attributes: ' . implode(', ', array_keys($attributes)));
106  }
107 
108  // MemberOf must be an array of group DN's
109  if (!is_array($attributes[$map['memberof']])) {
110  throw new SimpleSAML_Error_Exception(
111  $this->title . 'The memberof attribute [' . $map['memberof'] .
112  '] is not an array of group DNs. ' . $this->var_export($attributes[$map['memberof']])
113  );
114  }
115 
116  // Search for the users group membership, recursively
117  $groups = $this->search($attributes[$map['memberof']]);
118  }
119 
120  // All done
122  $this->title . 'User found to be a member of the groups:' . implode('; ', $groups)
123  );
124  return $groups;
125  }
126 
127 
137  protected function getGroupsOpenLdap($attributes)
138  {
139  // Log the OpenLDAP specific search
141  $this->title . 'Searching LDAP using OpenLDAP specific method.'
142  );
143 
144  // Reference the map, just to make the name shorter
146 
147  // Print group search string and search for all group names
148  $openldap_base = $this->config->getString('ldap.basedn','ou=groups,dc=example,dc=com');
150  $this->title . "Searching for groups in ldap.basedn ".$openldap_base." with filter (".$map['memberof']."=".$attributes[$map['username']][0].") and attributes ".$map['member']
151  );
152 
153  $groups = array();
154  try {
155  // Intention is to filter in 'ou=groups,dc=example,dc=com' for '(memberUid = <value of attribute.username>)' and take only the attributes 'cn' (=name of the group)
156  $all_groups = $this->getLdap()->searchformultiple($openldap_base, array($map['memberof'] => $attributes[$map['username']][0]) , array($map['member']));
157  } catch (SimpleSAML_Error_UserNotFound $e) {
158  return $groups; // if no groups found return with empty (still just initialized) groups array
159  }
160 
161  // run through all groups and add each to our groups array
162  foreach ($all_groups as $group_entry) {
163  $groups[] .= $group_entry[$map['member']][0];
164  }
165 
166  return $groups;
167  }
168 
169 
180  {
181  // Log the AD specific search
183  $this->title . 'Searching LDAP using ActiveDirectory specific method.'
184  );
185 
186  // Reference the map, just to make the name shorter
188 
189  // Make sure the defined dn attribute exists
190  if (!isset($attributes[$map['dn']])) {
191  throw new SimpleSAML_Error_Exception(
192  $this->title . 'The DN attribute [' . $map['dn'] .
193  '] is not defined in the user\'s Attributes: ' . implode(', ', array_keys($attributes)));
194  }
195 
196  // DN attribute must have a value
197  if (!isset($attributes[$map['dn']][0]) || !$attributes[$map['dn']][0]) {
198  throw new SimpleSAML_Error_Exception(
199  $this->title . 'The DN attribute [' . $map['dn'] .
200  '] does not have a [0] value defined. ' . $this->var_export($attributes[$map['dn']])
201  );
202  }
203 
204  // Pass to the AD specific search
205  return $this->searchActiveDirectory($attributes[$map['dn']][0]);
206  }
207 
217  protected function search($memberof)
218  {
219  assert(is_array($memberof));
220 
221  // Used to determine what DN's have already been searched
222  static $searched = array();
223 
224  // Init the groups variable
225  $groups = array();
226 
227  // Shorten the variable name
229 
230  // Log the search
232  $this->title . 'Checking DNs for groups.' .
233  ' DNs: '. implode('; ', $memberof) .
234  ' Attributes: ' . $map['memberof'] . ', ' . $map['type'] .
235  ' Group Type: ' . $this->type_map['group']
236  );
237 
238  // Work out what attributes to get for a group
239  $use_group_name = FALSE;
240  $get_attributes = array($map['memberof'], $map['type']);
241  if (isset($map['name']) && $map['name']) {
242  $get_attributes[] = $map['name'];
243  $use_group_name = TRUE;
244  }
245 
246  // Check each DN of the passed memberOf
247  foreach ($memberof as $dn) {
248 
249  // Avoid infinite loops, only need to check a DN once
250  if (isset($searched[$dn])) {
251  continue;
252  }
253 
254  // Track all DN's that are searched
255  // Use DN for key as well, isset() is faster than in_array()
256  $searched[$dn] = $dn;
257 
258  // Query LDAP for the attribute values for the DN
259  try {
260  $attributes = $this->getLdap()->getAttributes($dn, $get_attributes);
261  } catch (SimpleSAML_Error_AuthSource $e) {
262  continue; // DN must not exist, just continue. Logged by the LDAP object
263  }
264 
265  // Only look for groups
266  if (!in_array($this->type_map['group'], $attributes[$map['type']], true)) {
267  continue;
268  }
269 
270  // Add to found groups array
271  if ($use_group_name && isset($attributes[$map['name']]) && is_array($attributes[$map['name']])) {
272  $groups[] = $attributes[$map['name']][0];
273  } else {
274  $groups[] = $dn;
275  }
276 
277  // Recursively search "sub" groups
278  if (!empty($attributes[$map['memberof']])) {
279  $groups = array_merge($groups, $this->search($attributes[$map['memberof']]));
280  }
281  }
282 
283  // Return only the unique group names
284  return array_unique($groups);
285  }
286 
287 
296  protected function searchActiveDirectory($dn)
297  {
298  assert(is_string($dn) && $dn != '');
299 
300  // Shorten the variable name
302 
303  // Log the search
305  $this->title . 'Searching ActiveDirectory group membership.' .
306  ' DN: ' . $dn .
307  ' DN Attribute: ' . $map['dn'] .
308  ' Member Attribute: ' . $map['member'] .
309  ' Type Attribute: ' . $map['type'] .
310  ' Type Value: ' . $this->type_map['group'] .
311  ' Base: ' . implode('; ', $this->base_dn)
312  );
313 
314  // AD connections should have this set
315  $this->getLdap()->setOption(LDAP_OPT_REFERRALS, 0);
316 
317  // Search AD with the specific recursive flag
318  try {
319  $entries = $this->getLdap()->searchformultiple(
320  $this->base_dn,
321  array($map['type'] => $this->type_map['group'], $map['member'] . ':1.2.840.113556.1.4.1941:' => $dn),
322  array($map['dn'])
323  );
324 
325  // The search may throw an exception if no entries
326  // are found, unlikely but possible.
327  } catch (SimpleSAML_Error_UserNotFound $e) {
328  return array();
329  }
330 
331  //Init the groups
332  $groups = array();
333 
334  // Check each entry..
335  foreach ($entries as $entry) {
336  // Check for the DN using the original attribute name
337  if (isset($entry[$map['dn']][0])) {
338  $groups[] = $entry[$map['dn']][0];
339  continue;
340  }
341 
342  // Sometimes the returned attribute names are lowercase
343  if (isset($entry[strtolower($map['dn'])][0])) {
344  $groups[] = $entry[strtolower($map['dn'])][0];
345  continue;
346  }
347 
348  // AD queries also seem to return the objects dn by default
349  if (isset($entry['dn'])) {
350  $groups[] = $entry['dn'];
351  continue;
352  }
353 
354  // Could not find DN, log and continue
356  $this->title . 'The DN attribute [' .
357  implode(', ', array($map['dn'], strtolower($map['dn']), 'dn')) .
358  '] could not be found in the entry. ' . $this->var_export($entry)
359  );
360  }
361 
362  // All done
363  return $groups;
364  }
365 }
getGroups($attributes)
This section of code was broken out because the child filter AuthorizeByGroup can use this method as ...
foreach($paths as $path) $request
Definition: asyncclient.php:32
getGroupsActiveDirectory($attributes)
Active Directory optimized search using the required attribute values from the user to get their grou...
static debug($string)
Definition: Logger.php:211
searchActiveDirectory($dn)
Searches LDAP using a ActiveDirectory specific filter, looking for group membership for the users DN...
var_export($value)
Local utility function to get details about a variable, basically converting it to a string to be use...
Definition: BaseFilter.php:306
getGroupsOpenLdap($attributes)
OpenLDAP optimized search using the required attribute values from the user to get their group member...
static notice($string)
Definition: Logger.php:188
if(array_key_exists('yes', $_REQUEST)) $attributes
Definition: getconsent.php:85
process(&$request)
This is run when the filter is processed by SimpleSAML.
getLdap()
Getter for the LDAP connection object.
Definition: BaseFilter.php:259
search($memberof)
Looks for groups from the list of DN&#39;s passed.