Projet

Général

Profil

Paste
Télécharger (18,2 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / ldap / ldap_servers / ldap_servers.tokens.inc @ 91af538d

1
<?php
2

    
3
/**
4
 * @file
5
 * Collection of functions related to ldap tokens.
6
 */
7

    
8
/**
9
 * @param string $attr_name
10
 *   such 'field_user_lname', 'name', 'mail', 'dn'.
11
 * @param string $attr_type
12
 *   such as 'field', 'property', etc.  NULL for ldap attributes.
13
 * @param string $attr_ordinal
14
 *   0, 1, 2, etc.  not used in general.
15
 *
16
 * @return string such as 'field.field_user_lname', 'samaccountname', etc.
17
 */
18
function ldap_servers_make_token($attr_name, $attr_type = NULL, $ordinal = NULL) {
19
  $inner_token = $attr_name;
20
  if ($attr_type) {
21
    $inner_token .= '.' . $attr_type;
22
  }
23
  if ($ordinal) {
24
    $inner_token .= ':' . $ordinal;
25
  }
26
  $token = LDAP_SERVERS_TOKEN_PRE . $inner_token . LDAP_SERVERS_TOKEN_POST;
27
  return $token;
28
}
29

    
30
/**
31
 * @param $user_attr_key
32
 *   of form <attr_type>.<attr_name>[:<instance>]
33
 *   such as field.lname, property.mail, field.aliases:2
34
 *
35
 * @return array array($attr_type, $attr_name, $attr_ordinal) such as array('field','field_user_lname', NULL)
36
 */
37
function ldap_servers_parse_user_attr_name($user_attr_key) {
38
  // Make sure no [] are on attribute.
39
  $user_attr_key = trim($user_attr_key, LDAP_SERVERS_TOKEN_PRE . LDAP_SERVERS_TOKEN_POST);
40
  $parts = explode('.', $user_attr_key);
41
  $attr_type = $parts[0];
42
  $attr_name = (isset($parts[1])) ? $parts[1] : FALSE;
43
  $attr_ordinal = FALSE;
44

    
45
  if ($attr_name) {
46
    $attr_name_parts = explode(':', $attr_name);
47
    if (isset($attr_name_parts[1])) {
48
      $attr_name = $attr_name_parts[0];
49
      $attr_ordinal = $attr_name_parts[1];
50
    }
51
  }
52
  return [$attr_type, $attr_name, $attr_ordinal];
53
}
54

    
55
/**
56
 * @param array
57
 * @param string $text
58
 *
59
 * @return string
60
 */
61

    
62
/**
63
 * User_account.
64
 *
65
 * @param $resource
66
 *   $ldap_entry
67
 * @param $text
68
 *   such as "[dn]", "[cn]@my.org", "[displayName] [sn]", "Drupal Provisioned"
69
 * @param string $resource_type
70
 *
71
 * @return string|string[]|null
72
 *   $text with tokens replaced or NULL if replacement not available
73
 */
74
function ldap_servers_token_replace($resource, $text, $resource_type = 'ldap_entry') {
75

    
76
  // Desired tokens are of form "cn","mail", etc.
77
  $desired_tokens = ldap_servers_token_tokens_needed_for_template($text);
78

    
79
  if (empty($desired_tokens)) {
80
    // If no tokens exist in text, return text itself.  It is literal value.
81
    return $text;
82
  }
83

    
84
  $tokens = [];
85

    
86
  // @TODO: Should really be if/else if only those two exist.
87
  switch ($resource_type) {
88
    case 'ldap_entry':
89
      $tokens = ldap_servers_token_tokenize_entry($resource, $desired_tokens, LDAP_SERVERS_TOKEN_PRE, LDAP_SERVERS_TOKEN_POST);
90
      break;
91

    
92
    case 'user_account':
93
      $tokens = ldap_servers_token_tokenize_user_account($resource, $desired_tokens, LDAP_SERVERS_TOKEN_PRE, LDAP_SERVERS_TOKEN_POST);
94
      break;
95
  }
96

    
97
  // Add lowercase tokens to avoid case sensitivity.
98
  foreach ($tokens as $attribute => $value) {
99
    $tokens[drupal_strtolower($attribute)] = $value;
100
  }
101

    
102
  // If $text is not present as an attribute key, insert it and set the key's value to an empty string.
103
  if (!array_key_exists(drupal_strtolower($text), $tokens)) {
104
    $tokens[$text] = '';
105
    $tokens[drupal_strtolower($text)] = '';
106
  }
107

    
108
  // Array of attributes (sn, givenname, etc)
109
  $attributes = array_keys($tokens);
110
  // Array of attribute values (Lincoln, Abe, etc)
111
  $values = array_values($tokens);
112
  $result = str_replace($attributes, $values, $text);
113

    
114
  // Strip out any unreplaced tokens.
115
  $result = preg_replace('/\[[^\]]*]/', '', $result);
116
  // Return NULL if $result is empty, else $result.
117
  return ($result == '') ? NULL : $result;
118
}
119

    
120
/**
121
 * @param array $attributes
122
 *   array of attributes passed by reference.
123
 * @param string $text
124
 *   with tokens in it
125
 *
126
 *   by reference return add ldap attribute triplet $attribute_maps[<attr_name>] = (<attr_name>, <ordinal>, <data_type>) to $attributes.
127
 */
128
function ldap_servers_token_extract_attributes(&$attribute_maps, $text) {
129
  $tokens = ldap_servers_token_tokens_needed_for_template($text);
130
  foreach ($tokens as $token) {
131
    $token = str_replace([LDAP_SERVERS_TOKEN_PRE, LDAP_SERVERS_TOKEN_POST], ['', ''], $token);
132
    $parts = explode(LDAP_SERVERS_TOKEN_DEL, $token);
133
    $ordinal = (isset($parts[1]) && $parts[1]) ? $parts[1] : 0;
134
    $attr_name = $parts[0];
135
    $source_data_type = NULL;
136

    
137
    $parts2 = explode(LDAP_SERVERS_TOKEN_MODIFIER_DEL, $attr_name);
138
    if (count($parts2) > 1) {
139
      $attr_name = $parts2[0];
140
      $conversion = $parts2[1];
141
    }
142
    else {
143
      $conversion = NULL;
144
    }
145
    $attribute_maps[$attr_name] = ldap_servers_set_attribute_map(@$attribute_maps[$attr_name], $conversion, [$ordinal => NULL]);
146
  }
147
}
148

    
149
/**
150
 * @param string $token
151
 *   or token expression with singular token in it, eg. [dn], [dn;binary], [titles:0;binary] [cn]@mycompany.com.
152
 *
153
 * @return array(<attr_name>, <ordinal>, <conversion>)
154
 */
155
function ldap_servers_token_extract_parts($token) {
156
  $attributes = [];
157
  ldap_servers_token_extract_attributes($attributes, $token);
158
  if (is_array($attributes)) {
159
    $keys = array_keys($attributes);
160
    $attr_name = $keys[0];
161
    $attr_data = $attributes[$attr_name];
162
    $ordinals = array_keys($attr_data['values']);
163
    $ordinal = $ordinals[0];
164
    return [$attr_name, $ordinal, $attr_data['conversion']];
165
  }
166
  else {
167
    return [NULL, NULL, NULL];
168
  }
169

    
170
}
171

    
172
/**
173
 * Turn an ldap entry into a token array suitable for the t() function.
174
 *
175
 * @param ldap entry array $ldap_entry
176
 * @param string prefix token prefix such as !,%,[
177
 * @param string suffix token suffix such as ]
178
 * @param $token_keys
179
 *   either an array of key names such as array('cn', 'dn') or string 'all' to return all tokens.
180
 *
181
 * @return token array suitable for t() functions of with lowercase keys as exemplified below
182
 *
183
 *   $ldap_entry should be in form of single entry returned from ldap_search() function:
184
 *
185
 *   'dn' => 'cn=jdoe,ou=campus accounts,ou=toledo campus,dc=ad,dc=myuniversity,dc=edu',
186
 *   'mail' => array( 0 => 'jdoe@myuniversity.edu', 'count' => 1),
187
 *   'sAMAccountName' => array( 0 => 'jdoe', 'count' => 1),
188
 *   should return tokens such as:
189
 *
190
 *   -- from dn attribute
191
 *   [cn] = jdoe
192
 *   [cn:0] = jdoe
193
 *   [cn:last] => jdoe
194
 *   [cn:reverse:0] = jdoe
195
 *   [ou] = campus accounts
196
 *   [ou:0] = campus accounts
197
 *   [ou:1] = toledo campus
198
 *   [ou:last] = toledo campus
199
 *   [ou:reverse:0] = toledo campus
200
 *   [ou:reverse:1] = campus accounts
201
 *   [dc] = ad
202
 *   [dc:0] = ad
203
 *   [dc:1] = myuniversity
204
 *   [dc:2] = edu
205
 *   [dc:last] = edu
206
 *   [dc:reverse:0] = edu
207
 *   [dc:reverse:1] = myuniversity
208
 *   [dc:reverse:2] = ad
209
 *
210
 *   -- from other attributes
211
 *   [mail] = jdoe@myuniversity.edu
212
 *   [mail:0] = jdoe@myuniversity.edu
213
 *   [mail:last] = jdoe@myuniversity.edu
214
 *   [samaccountname] = jdoe
215
 *   [samaccountname:0] = jdoe
216
 *   [samaccountname:last] = jdoe
217
 *
218
 *   [guid:0;base64_encode] = apply base64_encode() function to value
219
 *   [guid:0;bin2hex] = apply bin2hex() function to value
220
 *   [guid:0;msguid] = apply ldap_servers_msguid() function to value
221
 *   [guid:0;binary] = apply ldap_servers_binary() function to value. this is the most generic binary function
222
 */
223
function ldap_servers_token_tokenize_entry($ldap_entry, $token_keys = 'all', $pre = LDAP_SERVERS_TOKEN_PRE, $post = LDAP_SERVERS_TOKEN_POST) {
224

    
225
  $detailed_watchdog_log = variable_get('ldap_help_watchdog_detail', 0);
226
  $tokens = [];
227
  $watchdog_tokens = [];
228
  if (function_exists('debug_backtrace') && $backtrace = debug_backtrace()) {
229
    $watchdog_tokens['%calling_function'] = $backtrace[1]['function'];
230
  }
231
  if (!is_array($ldap_entry)) {
232
    if ($detailed_watchdog_log) {
233
      watchdog('ldap_servers', 'skipped tokenization of ldap entry because no ldap entry provided when called from %calling_function.', $watchdog_tokens, WATCHDOG_DEBUG);
234
    }
235
    // Empty array.
236
    return $tokens;
237
  }
238

    
239
  // Add lowercase keyed entries to ldap array.
240
  foreach ($ldap_entry as $key => $values) {
241
    $ldap_entry[drupal_strtolower($key)] = $values;
242
  }
243

    
244
  // 1. tokenize dn
245
  // escapes attribute values, need to be unescaped later.
246
  $dn_parts = ldap_explode_dn($ldap_entry['dn'], 0);
247
  unset($dn_parts['count']);
248
  $parts_count = [];
249
  $parts_last_value = [];
250
  foreach ($dn_parts as $pair) {
251
    list($attr_name, $attr_value) = explode('=', $pair);
252
    $attr_value = ldap_pear_unescape_dn_value($attr_value);
253
    try {
254
      $attr_value = check_plain($attr_value);
255
    }
256
    catch (Exception $e) {
257
      if ($detailed_watchdog_log) {
258
        $watchdog_tokens['%attr_name'] = $attr_name;
259
        watchdog('ldap_servers', 'skipped tokenization of attribute %attr_name because the value would not pass check_plain function.', $watchdog_tokens, WATCHDOG_DEBUG);
260
      }
261
      // don't tokenize data that can't pass check_plain.
262
      continue;
263
    }
264
    if (!isset($parts_count[$attr_name])) {
265
      $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . $post] = $attr_value;
266
      $parts_count[$attr_name] = 0;
267
    }
268
    $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . LDAP_SERVERS_TOKEN_DEL . (int) $parts_count[$attr_name] . $post] = $attr_value;
269

    
270
    $parts_last_value[$attr_name] = $attr_value;
271
    $parts_count[$attr_name]++;
272
  }
273

    
274
  // Add the parts in reverse order to reflect the hierarchy.
275
  foreach ($parts_count as $part => $count) {
276
    $part = strtolower($part);
277
    for ($i = 0; $i < $count; $i++) {
278
      $reverse_position = $count - $i - 1;
279
      $tokens[$pre . $part . LDAP_SERVERS_TOKEN_DEL . 'reverse' . LDAP_SERVERS_TOKEN_DEL . $reverse_position . $post] = $tokens[$pre . $part . LDAP_SERVERS_TOKEN_DEL . $i . $post];
280
    }
281
  }
282

    
283
  foreach ($parts_count as $attr_name => $count) {
284
    $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . LDAP_SERVERS_TOKEN_DEL . 'last' . $post] = $parts_last_value[$attr_name];
285
  }
286

    
287
  // Tokenize other attributes.
288
  if ($token_keys == 'all') {
289
    $token_keys = array_keys($ldap_entry);
290
    $token_keys = array_filter($token_keys, "is_string");
291
    foreach ($token_keys as $attr_name) {
292
      $attr_value = $ldap_entry[$attr_name];
293
      if (is_array($attr_value) && is_scalar($attr_value[0]) && $attr_value['count'] == 1) {
294
        $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . $post] = check_plain($attr_value[0]);
295
        $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . LDAP_SERVERS_TOKEN_DEL . '0' . $post] = check_plain($attr_value[0]);
296
        $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . LDAP_SERVERS_TOKEN_DEL . 'last' . $post] = check_plain($attr_value[0]);
297
      }
298
      elseif (is_array($attr_value) && $attr_value['count'] > 1) {
299
        $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . LDAP_SERVERS_TOKEN_DEL . 'last' . $post] = check_plain($attr_value[$attr_value['count'] - 1]);
300
        for ($i = 0; $i < $attr_value['count']; $i++) {
301
          $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . LDAP_SERVERS_TOKEN_DEL . $i . $post] = check_plain($attr_value[$i]);
302
        }
303
      }
304
      elseif (is_scalar($attr_value)) {
305
        $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . $post] = check_plain($attr_value);
306
        $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . LDAP_SERVERS_TOKEN_DEL . '0' . $post] = check_plain($attr_value);
307
        $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . LDAP_SERVERS_TOKEN_DEL . 'last' . $post] = check_plain($attr_value);
308
      }
309
    }
310
  }
311
  else {
312
    foreach ($token_keys as $full_token_key) {
313
      // Token key = 'dn', 'mail', 'mail:0', 'mail:last', 'dept:1', 'guid:0' etc.
314
      $value = NULL;
315

    
316
      $conversion = FALSE;
317
      $parts = explode(';', $full_token_key);
318
      if (count($parts) == 2) {
319
        $conversion = $parts[1];
320
        $token_key = $parts[0];
321
      }
322
      else {
323
        $token_key = $full_token_key;
324
      }
325

    
326
      $parts = explode(LDAP_SERVERS_TOKEN_DEL, $token_key);
327
      $attr_name = drupal_strtolower($parts[0]);
328
      $ordinal_key = isset($parts[1]) ? $parts[1] : 0;
329
      $i = NULL;
330

    
331
      // don't use empty() since a 0, "", etc value may be a desired value.
332
      if ($attr_name == 'dn' || !isset($ldap_entry[$attr_name])) {
333
        continue;
334
      }
335
      else {
336
        $count = $ldap_entry[$attr_name]['count'];
337
        if ($ordinal_key === 'last') {
338
          $i = ($count > 0) ? $count - 1 : 0;
339
          $value = $ldap_entry[$attr_name][$i];
340
        }
341
        elseif (is_numeric($ordinal_key) || $ordinal_key == '0') {
342
          $value = $ldap_entry[$attr_name][$ordinal_key];
343
        }
344
        else {
345
          // don't add token if case not covered.
346
          continue;
347
        }
348
      }
349

    
350
      if ($conversion) {
351
        switch ($conversion) {
352

    
353
          case 'base64_encode':
354
            $value = base64_encode($value);
355
            break;
356

    
357
          case 'bin2hex':
358
            $value = bin2hex($value);
359
            break;
360

    
361
          case 'msguid':
362
            $value = ldap_servers_msguid($value);
363
            break;
364

    
365
          case 'binary':
366
            $value = ldap_servers_binary($value);
367
            break;
368
        }
369
      }
370

    
371
      $tokens[$pre . $full_token_key . $post] = $value;
372
      if ($full_token_key != drupal_strtolower($full_token_key)) {
373
        $tokens[$pre . drupal_strtolower($full_token_key) . $post] = $value;
374
      }
375
    }
376
  }
377

    
378
  // Include the dn.  it will not be handled correctly by previous loops.
379
  $tokens[$pre . 'dn' . $post] = check_plain($ldap_entry['dn']);
380
  return $tokens;
381
}
382

    
383
/**
384
 *
385
 * @param drupal user object $user_account
386
 * @param array or 'all' $token_keys
387
 *   'all' signifies return
388
 *   all token/value pairs available; otherwise array lists
389
 *   token keys (e.g. property.name ...NOT [property.name])
390
 * @param string $pre
391
 *   prefix of token.
392
 * @param string $post
393
 *   suffix of token.
394
 *
395
 *
396
 * @return should return token/value pairs in array such as
397
 *   'status' => 1
398
 *   'uid' => 17
399
 */
400
function ldap_servers_token_tokenize_user_account($user_account, $token_keys = 'all', $pre = LDAP_SERVERS_TOKEN_PRE, $post = LDAP_SERVERS_TOKEN_POST) {
401

    
402
  $detailed_watchdog_log = variable_get('ldap_help_watchdog_detail', 0);
403
  $tokens = [];
404

    
405
  $user_entered_password_available = (boolean) ldap_user_ldap_provision_pwd('get');
406
  if ($token_keys == 'all') {
407
    // Add lowercase keyed entries to ldap array.
408
    foreach ((array) $user_account as $property_name => $value) {
409
      if (is_scalar($value) && $property_name != 'password') {
410
        $token_keys[] = 'property.' . $property_name;
411
        if (drupal_strtolower($property_name) != $property_name) {
412
          $token_keys[] = 'property.' . drupal_strtolower($property_name);
413
        }
414
      }
415
      elseif (isset($user_account->{$attr_name}[LANGUAGE_NONE][0]['value']) && is_scalar($user_account->{$attr_name}[LANGUAGE_NONE][0]['value'])) {
416
        $token_keys[] = 'field.' . $property_name;
417
        if (drupal_strtolower($property_name) != $property_name) {
418
          $token_keys[] = 'field.' . drupal_strtolower($property_name);
419
        }
420
      }
421
      else {
422
        // Field or property with no value, so no token can be generated.
423
      }
424
    }
425
    $ldap_user_conf_admin = new LdapUserConfAdmin();
426
    if ($ldap_user_conf_admin->setsLdapPassword) {
427
      $token_keys[] = 'password.random';
428
      $token_keys[] = 'password.user-random';
429
    }
430
  }
431

    
432
  foreach ($token_keys as $token_key) {
433
    $parts = explode('.', $token_key);
434
    $attr_type = $parts[0];
435
    $attr_name = $parts[1];
436
    $attr_conversion = (isset($parts[2])) ? $parts[2] : 'none';
437
    $value = FALSE;
438
    $skip = FALSE;
439

    
440
    switch ($attr_type) {
441
      case 'field':
442
        $value = @is_scalar($user_account->{$attr_name}[LANGUAGE_NONE][0]['value']) ? $user_account->{$attr_name}[LANGUAGE_NONE][0]['value'] : '';
443
        break;
444

    
445
      case 'property':
446
        $value = @is_scalar($user_account->{$attr_name}) ? $user_account->{$attr_name} : '';
447
        break;
448

    
449
      case 'password':
450

    
451
        switch ($attr_name) {
452

    
453
          case 'user':
454
          case 'user-only':
455
            $pwd = ldap_user_ldap_provision_pwd('get');
456
            $value = ($pwd) ? $pwd : NULL;
457
            break;
458

    
459
          case 'user-random':
460
            $pwd = ldap_user_ldap_provision_pwd('get');
461
            $value = ($pwd) ? $pwd : user_password();
462
            break;
463

    
464
          case 'random':
465
            $value = user_password();
466
            break;
467

    
468
        }
469
        if (empty($value)) {
470
          $skip = TRUE;
471
        }
472
        break;
473
    }
474

    
475
    if (!$skip) {
476

    
477
      switch ($attr_conversion) {
478

    
479
        case 'none':
480
          break;
481

    
482
        case 'to-md5':
483
          $value = "{MD5}" . base64_encode(pack("H*", md5($value)));
484
          break;
485

    
486
        case 'to-lowercase':
487
          $value = drupal_strtolower($value);
488
          break;
489
      }
490

    
491
      $tokens[$pre . $token_key . $post] = ($attr_type == 'password') ? $value : check_plain($value);
492
      if ($token_key != drupal_strtolower($token_key)) {
493
        $tokens[$pre . drupal_strtolower($token_key) . $post] = ($attr_type == 'password') ? $value : check_plain($value);
494
      }
495
    }
496
  }
497
  return $tokens;
498
}
499

    
500
/**
501
 * @param string $template
502
 *   in form [cn]@myuniversity.edu.
503
 * @return array of all tokens in the template such as array('cn')
504
 */
505
function ldap_servers_token_tokens_needed_for_template($template, $pre = LDAP_SERVERS_TOKEN_PRE, $post = LDAP_SERVERS_TOKEN_POST) {
506
  preg_match_all('/
507
    \[             # [ - pattern start
508
    ([^\[\]]*)  # match $type not containing whitespace : [ or ]
509
    \]             # ] - pattern end
510
    /x', $template, $matches);
511

    
512
  return @$matches[1];
513

    
514
}
515

    
516
/**
517
 *
518
 */
519
function ldap_servers_token_show_sample_user_tokens($sid) {
520

    
521
  $ldap_server = ldap_servers_get_servers($sid, 'all', TRUE);
522
  $test_username = $ldap_server->testingDrupalUsername;
523
  if (!$test_username || !(
524
    $ldap_server->bind_method == LDAP_SERVERS_BIND_METHOD_SERVICE_ACCT ||
525
    $ldap_server->bind_method == LDAP_SERVERS_BIND_METHOD_ANON
526
      )
527
    ) {
528
    return FALSE;
529
  }
530

    
531
  if ($ldap_user = $ldap_server->userUserNameToExistingLdapEntry($test_username)) {
532
    $table = theme('ldap_server_ldap_entry_table', [
533
      'entry' => $ldap_user['attr'],
534
      'username' => $test_username,
535
      'dn' => $ldap_user['dn'],
536
    ]);
537
  }
538
  else {
539
    $table = '<p>' . t('No sample user data found') . '</p>';
540
  }
541

    
542
  return $table;
543
}