ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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'];
34  $map =& $this->attribute_map;
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(array $attributes)
77  {
78  // Reference the map, just to make the name shorter
79  $map =& $this->attribute_map;
80 
81  // Log the request
83  $this->title . 'Checking for groups based on the best method for the LDAP product.'
84  );
85 
86  // Based on the directory service, search LDAP for groups
87  // If any attributes are needed, prepare them before calling search method
88  switch ($this->product) {
89 
90  case 'ACTIVEDIRECTORY':
91 
92  // Log the AD specific search
94  $this->title . 'Searching LDAP using ActiveDirectory specific method.'
95  );
96 
97  // Make sure the defined dn attribute exists
98  if (!isset($attributes[$map['dn']])) {
100  $this->title . 'The DN attribute [' . $map['dn'] .
101  '] is not defined in the users Attributes: ' . implode(', ', array_keys($attributes))
102  );
103  }
104 
105  // DN attribute must have a value
106  if (!isset($attributes[$map['dn']][0]) || !$attributes[$map['dn']][0]) {
107  throw new SimpleSAML_Error_Exception(
108  $this->title . 'The DN attribute [' . $map['dn'] .
109  '] does not have a [0] value defined. ' . $this->var_export($attributes[$map['dn']])
110  );
111  }
112 
113  // Pass to the AD specific search
114  $groups = $this->searchActiveDirectory($attributes[$map['dn']][0]);
115  break;
116 
117  case 'OPENLDAP':
118  // Log the OpenLDAP specific search
120  $this->title . 'Searching LDAP using OpenLDAP specific method.'
121  );
122  // Print group search string and search for all group names
123  $openldap_base = $this->config->getString('ldap.basedn','ou=groups,dc=example,dc=com');
125  $this->title . "Searching for groups in ldap.basedn ".$openldap_base." with filter (".$map['memberof']."=".$attributes[$map['username']][0].") and attributes ".$map['member']
126  );
127  $groups = array();
128  try {
129  // 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)
130  $all_groups = $this->getLdap()->searchformultiple( $openldap_base, array($map['memberof'] => $attributes[$map['username']][0]) , array($map['member']));
131  } catch (SimpleSAML_Error_UserNotFound $e) {
132  break; // if no groups found return with empty (still just initialized) groups array
133  }
134  // run through all groups and add each to our groups array
135  foreach ($all_groups as $group_entry) {
136  $groups[] .= $group_entry[$map['member']][0];
137  }
138  break;
139 
140  default:
141 
142  // Log the general search
144  $this->title . 'Searching LDAP using the default search method.'
145  );
146 
147  // Make sure the defined memberOf attribute exists
148  if (!isset($attributes[$map['memberof']])) {
149  throw new SimpleSAML_Error_Exception(
150  $this->title . 'The memberof attribute [' . $map['memberof'] .
151  '] is not defined in the users Attributes: ' . implode(', ', array_keys($attributes))
152  );
153  }
154 
155  // MemberOf must be an array of group DN's
156  if (!is_array($attributes[$map['memberof']])) {
157  throw new SimpleSAML_Error_Exception(
158  $this->title . 'The memberof attribute [' . $map['memberof'] .
159  '] is not an array of group DNs. ' . $this->var_export($attributes[$map['memberof']])
160  );
161  }
162 
163  // Search for the users group membership, recursively
164  $groups = $this->search($attributes[$map['memberof']]);
165  }
166 
167  // All done
169  $this->title . 'User found to be a member of the groups:' . implode('; ', $groups)
170  );
171  return $groups;
172  }
173 
174 
184  protected function search($memberof)
185  {
186  assert('is_array($memberof)');
187 
188  // Used to determine what DN's have already been searched
189  static $searched = array();
190 
191  // Init the groups variable
192  $groups = array();
193 
194  // Shorten the variable name
195  $map =& $this->attribute_map;
196 
197  // Log the search
199  $this->title . 'Checking DNs for groups.' .
200  ' DNs: '. implode('; ', $memberof) .
201  ' Attributes: ' . $map['memberof'] . ', ' . $map['type'] .
202  ' Group Type: ' . $this->type_map['group']
203  );
204 
205  // Check each DN of the passed memberOf
206  foreach ($memberof as $dn) {
207 
208  // Avoid infinite loops, only need to check a DN once
209  if (isset($searched[$dn])) {
210  continue;
211  }
212 
213  // Track all DN's that are searched
214  // Use DN for key as well, isset() is faster than in_array()
215  $searched[$dn] = $dn;
216 
217  // Query LDAP for the attribute values for the DN
218  try {
219  $attributes = $this->getLdap()->getAttributes($dn, array($map['memberof'], $map['type']));
220  } catch (SimpleSAML_Error_AuthSource $e) {
221  continue; // DN must not exist, just continue. Logged by the LDAP object
222  }
223 
224  // Only look for groups
225  if (!in_array($this->type_map['group'], $attributes[$map['type']], true)) {
226  continue;
227  }
228 
229  // Add to found groups array
230  $groups[] = $dn;
231 
232  // Recursively search "sub" groups
233  $groups = array_merge($groups, $this->search($attributes[$map['memberof']]));
234  }
235 
236  // Return only the unique group names
237  return array_unique($groups);
238  }
239 
240 
249  protected function searchActiveDirectory($dn)
250  {
251  assert('is_string($dn) && $dn != ""');
252 
253  // Shorten the variable name
254  $map =& $this->attribute_map;
255 
256  // Log the search
258  $this->title . 'Searching ActiveDirectory group membership.' .
259  ' DN: ' . $dn .
260  ' DN Attribute: ' . $map['dn'] .
261  ' Member Attribute: ' . $map['member'] .
262  ' Type Attribute: ' . $map['type'] .
263  ' Type Value: ' . $this->type_map['group'] .
264  ' Base: ' . implode('; ', $this->base_dn)
265  );
266 
267  // AD connections should have this set
268  $this->getLdap()->setOption(LDAP_OPT_REFERRALS, 0);
269 
270  // Search AD with the specific recursive flag
271  try {
272  $entries = $this->getLdap()->searchformultiple(
273  $this->base_dn,
274  array($map['type'] => $this->type_map['group'], $map['member'] . ':1.2.840.113556.1.4.1941:' => $dn),
275  array($map['dn'])
276  );
277 
278  // The search may throw an exception if no entries
279  // are found, unlikely but possible.
280  } catch (SimpleSAML_Error_UserNotFound $e) {
281  return array();
282  }
283 
284  //Init the groups
285  $groups = array();
286 
287  // Check each entry..
288  foreach ($entries as $entry) {
289 
290  // Check for the DN using the original attribute name
291  if (isset($entry[$map['dn']][0])) {
292  $groups[] = $entry[$map['dn']][0];
293  continue;
294  }
295 
296  // Sometimes the returned attribute names are lowercase
297  if (isset($entry[strtolower($map['dn'])][0])) {
298  $groups[] = $entry[strtolower($map['dn'])][0];
299  continue;
300  }
301 
302  // AD queries also seem to return the objects dn by default
303  if (isset($entry['dn'])) {
304  $groups[] = $entry['dn'];
305  continue;
306  }
307 
308  // Could not find DN, log and continue
310  $this->title . 'The DN attribute [' .
311  implode(', ', array($map['dn'], strtolower($map['dn']), 'dn')) .
312  '] could not be found in the entry. ' . $this->var_export($entry)
313  );
314  }
315 
316  // All done
317  return $groups;
318  }
319 }
static debug($string)
Definition: Logger.php:213
$attributes
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:303
static notice($string)
Definition: Logger.php:190
Create styles array
The data for the language used.
process(&$request)
This is run when the filter is processed by SimpleSAML.
getLdap()
Getter for the LDAP connection object.
Definition: BaseFilter.php:256
getGroups(array $attributes)
This section of code was broken out because the child filter AuthorizeByGroup can use this method as ...
search($memberof)
Looks for groups from the list of DN&#39;s passed.