Projet

Général

Profil

Paste
Télécharger (43,4 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / ldap / ldap_servers / LdapServerAdmin.class.php @ bc175c27

1
<?php
2

    
3
/**
4
 * @file
5
 * LDAP Server Admin Class
6
 *
7
 *
8
 */
9

    
10
module_load_include('php', 'ldap_servers', 'LdapServer.class');
11

    
12
class LdapServerAdmin extends LdapServer {
13

    
14
  public $bindpw_new = FALSE;
15
  public $bindpw_clear = FALSE;
16

    
17
  /**
18
   * @param $type = 'all', 'enabled'
19
   */
20
  public static function getLdapServerObjects($sid = NULL, $type = NULL, $class = 'LdapServer', $reset = FALSE) {
21
    $servers = array();
22
    if (module_exists('ctools')) {
23
      ctools_include('export');
24
      if ($reset) {
25
        ctools_export_load_object_reset('ldap_servers');
26
      }
27
      $select = ctools_export_load_object('ldap_servers', 'all');
28
    }
29
    else {
30
      try {
31
        $select = db_select('ldap_servers', 'ldap_servers')
32
          ->fields('ldap_servers')
33
          ->execute();
34
      }
35
      catch (Exception $e) {
36
        drupal_set_message(t('server index query failed. Message = %message, query= %query',
37
          array('%message' => $e->getMessage(), '%query' => $e->query_string)), 'error');
38
        return array();
39
      }
40
    }
41
    foreach ($select as $result) {
42
      $servers[$result->sid] = ($class == 'LdapServer') ? new LdapServer($result->sid) : new LdapServerAdmin($result->sid);
43
    }
44
    return $servers;
45

    
46
  }
47

    
48
  function __construct($sid) {
49
    parent::__construct($sid);
50
  }
51

    
52
  protected function populateFromDrupalForm($op, $values) {
53
    $this->inDatabase = ($op == 'edit');
54
    $this->sid = trim($values['sid']);
55
    $this->name = trim($values['name']);
56
    $this->status = ($values['status']) ? 1 : 0;
57
    $this->ldap_type = trim($values['ldap_type']);
58
    $this->address = trim($values['address']);
59
    $this->port = trim($values['port']);
60
    $this->tls = trim($values['tls']);
61
    $this->followrefs = trim($values['followrefs']);
62
    $this->bind_method = trim($values['bind_method']);
63
    $this->binddn = trim($values['binddn']);
64
    if (trim($values['bindpw'])) {
65
      $this->bindpw_new = trim($values['bindpw']);
66
    }
67
    $this->user_dn_expression = trim($values['user_dn_expression']);
68
    $this->basedn = $this->linesToArray(trim($values['basedn']));
69
    $this->user_attr = drupal_strtolower(trim($values['user_attr']));
70
    $this->picture_attr = drupal_strtolower(trim($values['picture_attr']));
71
    $this->account_name_attr = drupal_strtolower(trim($values['account_name_attr']));
72
    $this->mail_attr = drupal_strtolower(trim($values['mail_attr']));
73
    $this->mail_template = trim($values['mail_template']);
74
    $this->unique_persistent_attr = drupal_strtolower(trim($values['unique_persistent_attr']));
75
    $this->unique_persistent_attr_binary = trim($values['unique_persistent_attr_binary']);
76
    $this->ldapToDrupalUserPhp = $values['ldap_to_drupal_user'];
77
    $this->testingDrupalUsername = trim($values['testing_drupal_username']);
78
    $this->testingDrupalUserDn = trim($values['testing_drupal_user_dn']);
79
    $this->groupFunctionalityUnused = $values['grp_unused'];
80
    $this->groupObjectClass = drupal_strtolower(trim($values['grp_object_cat']));
81
    $this->groupNested = trim($values['grp_nested']);
82

    
83
    $this->groupUserMembershipsAttrExists = trim($values['grp_user_memb_attr_exists']);
84
    $this->groupUserMembershipsAttr = drupal_strtolower(trim($values['grp_user_memb_attr']));
85

    
86
    $this->groupMembershipsAttr = drupal_strtolower(trim($values['grp_memb_attr']));
87

    
88
    $this->groupMembershipsAttrMatchingUserAttr = drupal_strtolower(trim($values['grp_memb_attr_match_user_attr']));
89

    
90
    $this->groupDeriveFromDn = trim($values['grp_derive_from_dn']);
91
    $this->groupDeriveFromDnAttr = drupal_strtolower(trim($values['grp_derive_from_dn_attr']));
92
    $this->groupTestGroupDn = trim($values['grp_test_grp_dn']);
93
    $this->groupTestGroupDnWriteable = trim($values['grp_test_grp_dn_writeable']);
94

    
95

    
96
    $this->searchPagination = ($values['search_pagination']) ? 1 : 0;
97
    $this->searchPageSize = trim($values['search_page_size']);
98

    
99
  }
100

    
101
  /**
102
   * @param string enum $op 'add', 'update'
103
   */
104

    
105
  public function save($op) {
106

    
107
    $values = new stdClass();
108

    
109
    foreach ($this->field_to_properties_map() as $field_name => $property_name) {
110
      $field_name_lcase = drupal_strtolower($field_name);
111
      $values->{$field_name_lcase} = $this->{$property_name};
112
    }
113
    if (isset($this->bindpw) && $this->bindpw) {
114
      $values->bindpw = ldap_servers_encrypt($this->bindpw);
115
    }
116
    if ($this->bindpw_new) {
117
      $values->bindpw = ldap_servers_encrypt($this->bindpw_new);
118
    }
119
    elseif ($this->bindpw_clear) {
120
      $values->bindpw = NULL;
121
    }
122

    
123
    $values->tls = (int)$this->tls;
124
    $values->followrefs = (int)$this->followrefs;
125

    
126
    if (module_exists('ctools')) {
127
      ctools_include('export');
128
      // Populate our object with ctool's properties
129
      $object = ctools_export_crud_new('ldap_servers');
130

    
131
      foreach ($object as $property => $value) {
132
        $property_lcase = drupal_strtolower($property);
133
        if (!isset($values->$property) || !isset($values->$property_lcase)) {
134
          $values->$property_lcase = $value;
135
        }
136
      }
137

    
138
      try {
139
        $values->export_type = NULL;
140
        $result = ctools_export_crud_save('ldap_servers', $values);
141
      } catch (Exception $e) {
142
        $values->export_type = EXPORT_IN_DATABASE;
143
        $result = ctools_export_crud_save('ldap_servers', $values);
144
      }
145
      
146
      ctools_export_load_object_reset('ldap_servers'); // ctools_export_crud_save doesn't invalidate cache
147

    
148
    }
149
    else { // directly via db
150
      unset($values->numeric_sid);
151
      if ($op == 'add') {
152
        $result = drupal_write_record('ldap_servers', $values);
153
      }
154
      else {
155
        $result = drupal_write_record('ldap_servers', $values, 'sid');
156
      }
157
      ldap_servers_cache_clear();
158

    
159
    }
160

    
161
    if ($result) {
162
      $this->inDatabase = TRUE;
163
    }
164
    else {
165
      drupal_set_message(t('Failed to write LDAP Server to the database.'));
166
    }
167
  }
168

    
169
  public function delete($sid) {
170
    if ($sid == $this->sid) {
171
      $result = db_delete('ldap_servers')->condition('sid', $sid)->execute();
172
      if (module_exists('ctools')) {
173
        ctools_include('export');
174
        ctools_export_load_object_reset('ldap_servers'); // invalidate cache
175
      }
176
      $this->inDatabase = FALSE;
177
      return $result;
178
    }
179
    else {
180
      return FALSE;
181
    }
182
  }
183
  public function getLdapServerActions() {
184
    $switch = ($this->status ) ? 'disable' : 'enable';
185
    $actions = array();
186
    $actions[] = l(t('edit'), LDAP_SERVERS_MENU_BASE_PATH . '/servers/edit/' . $this->sid);
187
    if (property_exists($this, 'type')) {
188
      if ($this->type == 'Overridden') {
189
          $actions[] = l(t('revert'), LDAP_SERVERS_MENU_BASE_PATH . '/servers/delete/' . $this->sid);
190
      }
191
      if ($this->type == 'Normal') {
192
          $actions[] = l(t('delete'), LDAP_SERVERS_MENU_BASE_PATH . '/servers/delete/' . $this->sid);
193
      }
194
    }
195
    else {
196
        $actions[] = l(t('delete'), LDAP_SERVERS_MENU_BASE_PATH . '/servers/delete/' . $this->sid);
197
    }
198
    $actions[] = l(t('test'), LDAP_SERVERS_MENU_BASE_PATH . '/servers/test/' . $this->sid);
199
    $actions[] = l($switch, LDAP_SERVERS_MENU_BASE_PATH . '/servers/' . $switch . '/' . $this->sid);
200
    return $actions;
201
  }
202

    
203
  public function drupalForm($op) {
204

    
205
  $form['server'] = array(
206
    '#type' => 'fieldset',
207
    '#title' => t('Connection settings'),
208
    '#collapsible' => TRUE,
209
    '#collapsed' => TRUE,
210
  );
211

    
212
  $form['bind_method'] = array(
213
    '#type' => 'fieldset',
214
    '#title' => t('Binding Method'),
215
    '#description' => t('How the Drupal system is authenticated by the LDAP server.'),
216
    '#collapsible' => TRUE,
217
    '#collapsed' => TRUE,
218
  );
219

    
220
  $form['users'] = array(
221
    '#type' => 'fieldset',
222
    '#title' => t('LDAP User to Drupal User Relationship'),
223
    '#description' => t('How are LDAP user entries found based on Drupal username or email?  And vice-versa?
224
       Needed for LDAP Authentication and Authorization functionality.'),
225
    '#collapsible' => TRUE,
226
    '#collapsed' => TRUE,
227
  );
228

    
229
  $form['groups'] = array(
230
    '#type' => 'fieldset',
231
    '#title' => t('LDAP Group Configuration'),
232
    '#description' => t('How are groups defined on your LDAP server?  This varies slightly from one LDAP implementation to another
233
      such as Active Directory, Novell, OpenLDAP, etc. Check everything that is true and enter all the values you know.'),
234
    '#collapsible' => TRUE,
235
    '#collapsed' => TRUE,
236
  );
237

    
238
  $supports = (ldap_servers_php_supports_pagination()) ? t('support pagination!') : t('NOT support pagination.');
239
  $form['pagination'] = array(
240
    '#type' => 'fieldset',
241
    '#title' => t('LDAP Pagination'),
242
    '#description' => t('In PHP 5.4, pagination is supported in ldap queries.
243
      A patch to earlier versions of PHP also supports this.')
244
      . ' <strong>' . t('This PHP installation appears to') . ' ' . $supports . '</strong> '
245
      . '<p>' . t('The advantage to pagination support is that if an ldap server is setup to return only
246
      1000 entries at a time,
247
      you can use page through 1000 records at a time;
248
      without pagination you would never see more than the first 1000 entries.
249
      Pagination is most useful when large queries for batch creating or
250
      synching accounts are used.  If you are not using this server for such
251
      tasks, its recommended to leave pagination disabled.') . '</p>',
252
    '#collapsible' => TRUE,
253
    '#collapsed' => !ldap_servers_php_supports_pagination(),
254
  );
255

    
256

    
257
  $field_to_prop_maps = $this->field_to_properties_map();
258
  foreach ($this->fields() as $field_id => $field) {
259
    if (isset($field['form'])) {
260

    
261
      if (!isset($field['form']['required']) && isset($field['schema']['not null']) && $field['form']['#type'] != 'checkbox') {
262
        $field['form']['#required'] = (boolean)$field['schema']['not null'];
263
      }
264
      if (isset($field['schema']['length']) && !isset($field['form']['#maxlength'])) {
265
        $field['form']['#maxlength'] = $field['schema']['length'];
266
      }
267
      if (isset($field_to_prop_maps[$field_id])) {
268
        $field['form']['#default_value'] = $this->{$field_to_prop_maps[$field_id]};
269
      }
270
      $fieldset = @$field['form']['fieldset'];
271
      if ($fieldset) {
272
        unset($field['form']['fieldset']);
273
        $form[$fieldset][$field_id] = $field['form'];
274
      }
275
      else {
276
        $form[$field_id] = $field['form'];
277
      }
278
    }
279
  }
280

    
281
  $form['server']['sid']['#disabled'] = ($op == 'edit');
282

    
283
  if (!function_exists('ldap_set_rebind_proc')) {
284
    $form['server']['followrefs']['#disabled'] = TRUE;
285
    $form['server']['followrefs']['#description'] = t('This functionality is disabled because the function ldap_set_rebind_proc can not be found on this server.  Perhaps your version of php does not have this function.  See php.net/manual/en/function.ldap-set-rebind-proc.php') . $form['server']['followrefs']['#description'];
286
  }
287

    
288
  $form['server']['tls']['#required'] = FALSE;
289
  $form['server']['followrefs']['#required'] = FALSE;
290
  $form['bind_method']['bind_method']['#default_value'] = ($this->bind_method) ? $this->bind_method : LDAP_SERVERS_BIND_METHOD_DEFAULT;
291
  $form['users']['basedn']['#default_value'] = $this->arrayToLines($this->basedn);
292

    
293
  if ($this->bindpw) {
294
    $pwd_directions = t('You currently have a password stored in the database.
295
      Leave password field empty to leave password unchanged.  Enter a new password
296
      to replace the current password.  Check the checkbox below to simply
297
      remove it from the database.');
298
    $pwd_class = 'ldap-pwd-present';
299
  }
300
  else {
301
    $pwd_directions = t('No password is currently stored in the database.
302
      If you are using a service account, enter one.');
303
    if ($this->bind_method == LDAP_SERVERS_BIND_METHOD_SERVICE_ACCT) {
304
      $pwd_class = 'ldap-pwd-abscent';
305
    }
306
    else {
307
      $pwd_class = 'ldap-pwd-not-applicable';
308
    }
309
  }
310

    
311
  $action = ($op == 'add') ? 'Add' : 'Update';
312
  $form['submit'] = array(
313
    '#type' => 'submit',
314
    '#value' => $action,
315
    '#weight' => 100,
316
  );
317

    
318
  return $form;
319

    
320
  }
321

    
322

    
323
  public function drupalFormValidate($op, $values)  {
324
    $errors = array();
325

    
326
    if ($op == 'delete') {
327
      if (!$this->sid) {
328
        $errors['server_id_missing'] = 'Server id missing from delete form.';
329
      }
330
      $warnings = module_invoke_all('ldap_server_in_use', $this->sid, $this->name);
331
      if (count($warnings)) {
332
        $errors['status'] = join("<br/>", array_values($warnings));
333
      }
334

    
335

    
336
    }
337
    else {
338
      $this->populateFromDrupalForm($op, $values);
339
      $errors = $this->validate($op);
340
    }
341
    return $errors;
342
  }
343

    
344
  protected function validate($op) {
345
    $errors = array();
346
    if ($op == 'add') {
347
      $ldap_servers = $this->getLdapServerObjects(NULL, 'all');
348
      if (count($ldap_servers)) {
349
        foreach ($ldap_servers as $sid => $ldap_server) {
350
          if ($this->name == $ldap_server->name) {
351
            $errors['name'] = t('An LDAP server configuration with the  name %name already exists.', array('%name' => $this->name));
352
          }
353
          elseif ($this->sid == $ldap_server->sid) {
354
            $errors['sid'] = t('An LDAP server configuration with the  id %sid  already exists.', array('%sid' => $this->sid));
355
          }
356
        }
357
      }
358
    }
359

    
360
    if ($this->status == 0) { // check that no modules use this server
361
      $warnings = module_invoke_all('ldap_server_in_use', $this->sid, $this->name);
362
      if (count($warnings)) {
363
        $errors['status'] = join("<br/>", array_values($warnings));
364
      }
365
    }
366

    
367

    
368
    if (!is_numeric($this->port)) {
369
      $errors['port'] = t('The TCP/IP port must be an integer.');
370
    }
371

    
372
    if ($this->bind_method == LDAP_SERVERS_BIND_METHOD_USER && !$this->user_dn_expression) {
373
      $errors['user_dn_expression'] = t('When using "Bind with Users Credentials", Expression for user DN is required');
374
    }
375

    
376
    if ($this->mail_attr && $this->mail_template) {
377
      $errors['mail_attr'] = t('Mail attribute or Mail Template may be used.  Not both.');
378
    }
379

    
380
    if ($this->bind_method == LDAP_SERVERS_BIND_METHOD_SERVICE_ACCT && !$this->binddn) {
381
      $errors['binddn'] = t('When using "Bind with Service Account", Bind DN is required.');
382
    }
383
    if ($op == 'add') {
384
      if ($this->bind_method == LDAP_SERVERS_BIND_METHOD_SERVICE_ACCT &&
385
        (($op == 'add' && !$this->bindpw_new) || ($op != 'add' && !$this->bindpw))
386
      ) {
387
        $errors['bindpw'] = t('When using "Bind with Service Account", Bind password is required.');
388
      }
389
    }
390

    
391
    return $errors;
392
  }
393

    
394
public function drupalFormWarnings($op, $values, $has_errors = NULL)  {
395
    $errors = array();
396

    
397
    if ($op == 'delete') {
398
      if (!$this->sid) {
399
        $errors['server_id_missing'] = t('Server id missing from delete form.');
400
      }
401
    }
402
    else {
403
      $this->populateFromDrupalForm($op, $values);
404
      $warnings = $this->warnings($op, $has_errors);
405
    }
406
    return $warnings;
407
  }
408

    
409

    
410
protected function warnings($op, $has_errors = NULL) {
411

    
412
    $warnings = array();
413
    if ($this->ldap_type) {
414
      $defaults = ldap_servers_ldaps_option_array();
415
      if (isset($defaults['user']['user_attr']) && ($this->user_attr != $defaults['user']['user_attr'])) {
416
        $tokens = array('%name' => $defaults['name'], '%default' => $defaults['user']['user_attr'], '%user_attr' => $this->user_attr);
417
        $warnings['user_attr'] = t('The standard UserName attribute in %name is %default.  You have %user_attr. This may be correct
418
          for your particular LDAP.', $tokens);
419
      }
420

    
421
      if (isset($defaults['user']['mail_attr']) && $this->mail_attr && ($this->mail_attr != $defaults['user']['mail_attr'])) {
422
        $tokens = array('%name' => $defaults['name'], '%default' => $defaults['user']['mail_attr'], '%mail_attr' => $this->mail_attr);
423
        $warnings['mail_attr'] = t('The standard mail attribute in %name is %default.  You have %mail_attr.  This may be correct
424
          for your particular LDAP.', $tokens);
425
      }
426
    }
427
  //  if (!$this->status && $has_errors != TRUE) {
428
    //  $warnings['status'] =  t('This server configuration is currently disabled.');
429
   // }
430

    
431
    if (!$this->mail_attr && !$this->mail_template) {
432
      $warnings['mail_attr'] = t('Mail attribute or Mail Template should be used for most user account functionality.');
433
    }
434

    
435
   // commented out validation because too many false positives present usability errors.
436
   // if ($this->bind_method == LDAP_SERVERS_BIND_METHOD_SERVICE_ACCT) { // Only for service account
437
     // $result = ldap_baddn($this->binddn, t('Service Account DN'));
438
     // if ($result['boolean'] == FALSE) {
439
     //   $warnings['binddn'] =  $result['text'];
440
     // }
441
   // }
442

    
443
   // foreach ($this->basedn as $basedn) {
444
    //  $result = ldap_baddn($basedn, t('User Base DN'));
445
     // if ($result['boolean'] == FALSE) {
446
     //   $warnings['basedn'] =  $result['text'];
447
    //  }
448
   // }
449

    
450
   // $result = ldap_badattr($this->user_attr, t('User attribute'));
451
   // if ($result['boolean'] == FALSE) {
452
    //  $warnings['user_attr'] =  $result['text'];
453
   // }
454

    
455
   // if ($this->mail_attr) {
456
  //    $result = ldap_badattr($this->mail_attr, t('Mail attribute'));
457
   //   if ($result['boolean'] == FALSE) {
458
    //    $warnings['mail_attr'] =  $result['text'];
459
   //   }
460
  //  }
461

    
462
   // $result = ldap_badattr($this->unique_persistent_attr, t('Unique Persistent Attribute'));
463
   // if ($result['boolean'] == FALSE) {
464
    //  $warnings['unique_persistent_attr'] =  $result['text'];
465
   // }
466

    
467
    return $warnings;
468
  }
469

    
470
public function drupalFormSubmit($op, $values) {
471

    
472
  $this->populateFromDrupalForm($op, $values);
473

    
474
  if ($values['clear_bindpw']) {
475
    $this->bindpw_clear = TRUE;
476
  }
477

    
478
  if ($op == 'delete') {
479
    $this->delete($this);
480
  }
481
  else { // add or edit
482
    try {
483
      $save_result = $this->save($op);
484
    }
485
    catch (Exception $e) {
486
      $this->setError('Save Error',
487
        t('Failed to save object.  Your form data was not saved.'));
488
    }
489
  }
490
}
491

    
492

    
493

    
494
  protected function arrayToLines($array) {
495
    $lines = "";
496
    if (is_array($array)) {
497
      $lines = join("\n", $array);
498
    }
499
    elseif (is_array(@unserialize($array))) {
500
      $lines = join("\n", unserialize($array));
501
    }
502
    return $lines;
503
  }
504

    
505
  protected function linesToArray($lines) {
506
    $lines = trim($lines);
507

    
508
    if ($lines) {
509
      $array = preg_split('/[\n\r]+/', $lines);
510
      foreach ($array as $i => $value) {
511
        $array[$i] = trim($value);
512
      }
513
    }
514
    else {
515
      $array = array();
516
    }
517
    return $array;
518
  }
519

    
520

    
521
  public static function fields() {
522

    
523
     /**
524
     * consumer_type is tag (unique alphanumeric id) of consuming authorization such as
525
     *   drupal_roles, og_groups, civicrm_memberships
526
     */
527
    $fields = array(
528

    
529
      'sid' => array(
530
        'form' => array(
531
          'fieldset' => 'server',
532
          '#type' => 'textfield',
533
          '#size' => 20,
534
          '#title' => t('Machine name for this server configuration.'),
535
          '#description' => t('May only contain alphanumeric characters (a-z, A-Z, 0-9, and _)'),
536
          '#required' => TRUE,
537
        ),
538
        'schema' => array(
539
          'type' => 'varchar',
540
          'length' => 20,
541
          'not null' => TRUE,
542
        )
543
      ),
544

    
545
     'numeric_sid' => array(
546
        'schema' => array(
547
          'type' => 'serial',
548
          'unsigned' => TRUE,
549
          'not null' => TRUE,
550
          'description' => 'Primary ID field for the table.  Only used internally.',
551
          'no export' => TRUE,
552
        ),
553
      ),
554

    
555
      'name' => array(
556
        'form' => array(
557
          'fieldset' => 'server',
558
          '#type' => 'textfield',
559
          '#size' => 50,
560
          '#title' => 'Name',
561
          '#description' => t('Choose a <em><strong>unique</strong></em> name for this server configuration.'),
562
        ),
563
        'schema' => array(
564
          'type' => 'varchar',
565
          'length' => 255,
566
          'not null' => FALSE,
567
        ),
568
      ),
569

    
570
      'status' => array(
571
        'form' => array(
572
          'fieldset' => 'server',
573
          '#type' => 'checkbox',
574
          '#title' => t('Enabled'),
575
          '#description' => t('Disable in order to keep configuration without having it active.'),
576
          '#required' => FALSE,
577
        ),
578
        'schema' => array(
579
          'type' => 'int',
580
          'size' => 'tiny',
581
          'not null' => FALSE,
582
          'default' => 0,
583
        ),
584
      ),
585

    
586
      'ldap_type' => array(
587
        'form' => array(
588
          'fieldset' => 'server',
589
          '#type' => 'select',
590
          '#options' => ldap_servers_ldaps_option_array(),
591
          '#title' => t('LDAP Server Type'),
592
          '#description' => t('This field is informative.  It\'s purpose is to assist with default values and give validation warnings.'),
593
        ),
594
        'schema' => array(
595
          'type' => 'varchar',
596
          'length' => 20,
597
          'not null' => FALSE,
598
        ),
599
      ),
600

    
601
      'address' => array(
602
        'form' => array(
603
          'fieldset' => 'server',
604
          '#type' => 'textfield',
605
          '#title' => t('LDAP server'),
606
          '#description' => t('The domain name or IP address of your LDAP Server such as "ad.unm.edu". For SSL
607
        use the form ldaps://DOMAIN such as "ldaps://ad.unm.edu"'),
608
          '#size' => 50,
609
        ),
610
        'schema' => array(
611
          'type' => 'varchar',
612
          'length' => 255,
613
          'not null' => FALSE,
614
        ),
615
      ),
616

    
617
      'port' => array(
618
        'form' => array(
619
          'fieldset' => 'server',
620
          '#type' => 'textfield',
621
          '#title' => t('LDAP port'),
622
          '#size' => 5,
623
          '#description' => t('The TCP/IP port on the above server which accepts LDAP connections. Must be an integer.'),
624
        ),
625
        'schema' => array(
626
          'type' => 'int',
627
          'not null' => FALSE,
628
          'default' => 389,
629
        ),
630
      ),
631

    
632
      'tls' => array(
633
        'form' => array(
634
          'fieldset' => 'server',
635
          '#type' => 'checkbox',
636
          '#title' => t('Use Start-TLS'),
637
          '#description' => t('Secure the connection between the Drupal and the LDAP servers using TLS.<br /><em>Note: To use START-TLS, you must set the LDAP Port to 389.</em>'),
638
        ),
639
        'schema' => array(
640
          'type' => 'int',
641
          'size' => 'tiny',
642
          'not null' => FALSE,
643
          'default' => 0,
644
        ),
645
      ),
646

    
647
      'followrefs' => array(
648
        'form' => array(
649
           'fieldset' => 'server',
650
           '#type' => 'checkbox',
651
           '#title' => t('Follow LDAP Referrals'),
652
           '#description' => t('Makes the LDAP client follow referrals (in the responses from the LDAP server) to other LDAP servers. This requires that the Bind Settings you give, is ALSO valid on these other servers.'),
653
          ),
654
        'schema' => array(
655
           'type' => 'int',
656
           'size' => 'tiny',
657
           'not null' => FALSE,
658
           'default' => 0,
659
        ),
660
      ),
661

    
662
      'bind_method' => array(
663
        'form' => array(
664
          'fieldset' => 'bind_method',
665
          '#type' => 'radios',
666
          '#title' => t('Binding Method for Searches (such as finding user object or their group memberships)'),
667
          '#options' => array(
668
            LDAP_SERVERS_BIND_METHOD_SERVICE_ACCT => t('Service Account Bind: Use credentials in the
669
            <strong>Service Account</strong> field to bind to LDAP.  <em>This option is usually a best practice.</em>'),
670

    
671
            LDAP_SERVERS_BIND_METHOD_USER => t('Bind with Users Credentials: Use user\'s entered credentials
672
            to bind to LDAP.<br/> This is only useful for modules that execute during user logon such
673
            as LDAP Authentication and LDAP Authorization.  <em>This option is not a best practice in most cases.</em>
674
            This option skips the initial anonymous bind and anonymous search to determine the LDAP user DN, but you
675
            can only use this option if your user DNs follow a consistent pattern, for example all of them being of
676
            the form "cn=[username],[base dn]", or all of them being of the form "uid=[username],ou=accounts,[base dn]".
677
            You specify the pattern under "Expression for user DN" in the next configuration block below.'),
678

    
679
            LDAP_SERVERS_BIND_METHOD_ANON_USER => t('Anonymous Bind for search, then Bind with Users Credentials:
680
            Searches for user dn then uses user\'s entered credentials to bind to LDAP.<br/> This is only useful for
681
            modules that work during user logon such as LDAP Authentication and LDAP Authorization.
682
            The user\'s dn must be discovered by an anonymous search for this option to work.'),
683

    
684
            LDAP_SERVERS_BIND_METHOD_ANON => t('Anonymous Bind: Use no credentials to bind to LDAP server.<br/>
685
            <em>This option will not work on most LDAPS connections.</em>'),
686
          ),
687
        ),
688
        'schema' => array(
689
          'type' => 'int',
690
          'size' => 'small',
691
          'not null' => FALSE,
692
          'default' => 0,
693
          'boolean' => FALSE,
694
        ),
695
      ),
696

    
697
    'binding_service_acct' => array(
698
      'form' => array(
699
        'fieldset' => 'bind_method',
700
        '#type' => 'markup',
701
        '#markup' => t('<label>Service Account</label> Some LDAP configurations
702
          prohibit or restrict the results of anonymous searches. These LDAPs require a DN//password pair
703
          for binding. For security reasons, this pair should belong to an
704
          LDAP account with stripped down permissions.
705
          This is also required for provisioning LDAP accounts and groups!'),
706
        ),
707
      ),
708

    
709

    
710
      'binddn' => array(
711
        'form' => array(
712
          'fieldset' => 'bind_method',
713
          '#type' => 'textfield',
714
          '#title' => t('DN for non-anonymous search'),
715
          '#size' => 80,
716
          '#states' => array(
717
             'enabled' => array(   // action to take.
718
               ':input[name=bind_method]' => array('value' => (string)LDAP_SERVERS_BIND_METHOD_SERVICE_ACCT),
719
              ),
720
            ),
721
        ),
722
        'schema' => array(
723
          'type' => 'varchar',
724
          'length' => 511,
725
        ),
726
      ),
727

    
728
      'bindpw' => array(
729
        'form' => array(
730
          'fieldset' => 'bind_method',
731
          '#type' => 'password',
732
          '#title' => t('Password for non-anonymous search'),
733
          '#size' => 20,
734
          '#states' => array(
735
             'enabled' => array(   // action to take.
736
               ':input[name=bind_method]' => array('value' => (string)LDAP_SERVERS_BIND_METHOD_SERVICE_ACCT),
737
              ),
738
            ),
739
        ),
740
        'schema' => array(
741
          'type' => 'varchar',
742
          'length' => 255,
743
        ),
744
      ),
745

    
746
      'clear_bindpw' => array(
747
        'form' => array(
748
          'fieldset' => 'bind_method',
749
          '#type' => 'checkbox',
750
          '#title' => t('Clear existing password from database.  Check this when switching away from Service Account Binding.'),
751
          '#default_value' => 0,
752
        ),
753
      ),
754

    
755
      'basedn' => array(
756
        'form' => array(
757
          'fieldset' => 'users',
758
          '#type' => 'textarea',
759
          '#cols' => 50,
760
          '#rows' => 6,
761
          '#title' => t('Base DNs for LDAP users, groups, and other entries.'),
762
          '#description' => '<div>' . t('What DNs have entries relavant to this configuration?
763
            e.g. <code>ou=campus accounts,dc=ad,dc=uiuc,dc=edu</code>
764
            Keep in mind that every additional basedn likely doubles the number of queries.  Place the
765
            more heavily used one first and consider using one higher base DN rather than 2 or more lower base DNs.
766
            Enter one per line in case if you need more than one.') . '</div>',
767
        ),
768
        'schema' => array(
769
          'type' => 'text',
770
          'serialize' => TRUE,
771
        ),
772
      ),
773

    
774
      'user_attr' => array(
775
        'form' => array(
776
          'fieldset' => 'users',
777
          '#type' => 'textfield',
778
          '#size' => 30,
779
          '#title' => t('AuthName attribute'),
780
          '#description' => t('The attribute that holds the users\' login name. (eg. <code>cn</code> for eDir or <code>sAMAccountName</code> for Active Directory).'),
781
        ),
782
        'schema' => array(
783
          'type' => 'varchar',
784
          'length' => 255,
785
          'not null' => FALSE,
786
        ),
787
      ),
788

    
789
      'account_name_attr' => array(
790
        'form' => array(
791
          'fieldset' => 'users',
792
          '#type' => 'textfield',
793
          '#size' => 30,
794
          '#title' => t('AccountName attribute'),
795
          '#description' => t('The attribute that holds the unique account name. Defaults to the same as the AuthName attribute.'),
796
        ),
797
        'schema' => array(
798
          'type' => 'varchar',
799
          'length' => 255,
800
          'not null' => FALSE,
801
          'default' => '',
802
        ),
803
      ),
804

    
805
      'mail_attr' => array(
806
        'form' => array(
807
          'fieldset' => 'users',
808
          '#type' => 'textfield',
809
          '#size' => 30,
810
          '#title' => t('Email attribute'),
811
          '#description' => t('The attribute that holds the users\' email address. (eg. <code>mail</code>). Leave empty if no such attribute exists'),
812
        ),
813
        'schema' => array(
814
          'type' => 'varchar',
815
          'length' => 255,
816
          'not null' => FALSE,
817
        ),
818
      ),
819

    
820
      'mail_template' => array(
821
        'form' => array(
822
          'fieldset' => 'users',
823
          '#type' => 'textfield',
824
          '#size' => 30,
825
          '#title' => t('Email template'),
826
          '#description' => t('If no attribute contains the user\'s email address, but it can be derived from other attributes,
827
            enter an email "template" here.
828
            Templates should have the user\'s attribute name in form such as [cn], [uin], etc.
829
            such as <code>[cn]@mycompany.com</code>.
830
            See http://drupal.org/node/997082 for additional documentation on ldap tokens.
831
            '),
832
        ),
833
        'schema' => array(
834
          'type' => 'varchar',
835
          'length' => 255,
836
          'not null' => FALSE,
837
        ),
838
      ),
839

    
840
    'picture_attr' => array(
841
                      'form' => array(
842
                                      'fieldset' => 'users',
843
                                      '#type' => 'textfield',
844
                                      '#size' => 30,
845
                                      '#title' => t('Thumbnail attribute'),
846
                                      '#description' => t('The attribute that holds the users\' thumnail image. (eg. <code>thumbnailPhoto</code>). Leave empty if no such attribute exists'),
847
                      ),
848
                      'schema' => array(
849
                                      'type' => 'varchar',
850
                                      'length' => 255,
851
                                      'not null' => FALSE,
852
                      ),
853
      ),
854
  
855
      'unique_persistent_attr' => array(
856
        'form' => array(
857
          'fieldset' => 'users',
858
          '#type' => 'textfield',
859
          '#size' => 30,
860
          '#title' => t('Persistent and Unique User ID Attribute'),
861
          '#description' => t('In some LDAPs, a user\'s DN, CN, or mail value may
862
            change when a user\'s name changes or for other reasons.
863
            In order to avoid creation of multiple accounts for that user or other ambiguities,
864
            enter a unique and persistent ldap attribute for users.  In cases
865
            where DN does not change, enter "dn" here.
866
            If no such attribute exists, leave this blank.'
867
            ),
868
        ),
869
        'schema' => array(
870
          'type' => 'varchar',
871
          'length' => 64,
872
          'not null' => FALSE,
873
        ),
874
      ),
875

    
876
      'unique_persistent_attr_binary' => array(
877
        'form' => array(
878
          'fieldset' => 'users',
879
          '#type' => 'checkbox',
880
          '#title' => t('Does the <em>Persistent and Unique User ID
881
            Attribute</em> hold a binary value?'),
882
          '#description' => t('You need to set this if you are using a binary
883
             attribute such as objectSid in ActiveDirectory for the PUID.<br>
884
             If you don\'t want this consider switching to another attribute,
885
             such as samaccountname.'),
886
        ),
887
        'schema' => array(
888
          'type' => 'int',
889
          'size' => 'tiny',
890
          'not null' => FALSE,
891
          'default' => 0,
892
        ),
893
      ),
894

    
895
      'user_dn_expression' => array(
896
        'form' => array(
897
          'fieldset' => 'users',
898
          '#type' => 'textfield',
899
          '#size' => 80,
900
          '#title' => t('Expression for user DN. Required when "Bind with Users Credentials" method selected.'),
901
          '#description' => t('%username and %basedn are valid tokens in the expression.
902
            Typically it will be:<br/> <code>cn=%username,%basedn</code>
903
             which might evaluate to <code>cn=jdoe,ou=campus accounts,dc=ad,dc=mycampus,dc=edu</code>
904
             Base DNs are entered above.'),
905
        ),
906
        'schema' => array(
907
          'type' => 'varchar',
908
          'length' => 255,
909
          'not null' => FALSE,
910
        ),
911
      ),
912

    
913
      'ldap_to_drupal_user' => array(
914
        'form' => array(
915
          'fieldset' => 'users',
916
          '#disabled' => (!module_exists('php')),
917
          '#type' => 'textarea',
918
          '#cols' => 25,
919
          '#rows' => 5,
920
          '#title' => t('PHP to transform Drupal login username to LDAP UserName attribute.'),
921
          '#description' => t('This will appear as disabled unless the "PHP filter" core module is enabled. Enter PHP to transform Drupal username to the value of the UserName attribute.
922
            The code should print the UserName attribute.
923
            PHP filter module must be enabled for this to work.
924
            The variable $name is available and is the user\'s login username.
925
            Careful, bad PHP code here will break your site. If left empty, no name transformation will be done.
926
            <br/>Example:<br/>Given the user will logon with jdoe@xyz.com and you want the ldap UserName attribute to be
927
            jdoe.<br/><code>$parts = explode(\'@\', $name); if (count($parts) == 2) {print $parts[0]};</code>'),
928
          ),
929
        'schema' => array(
930
          'type' => 'varchar',
931
          'length' => 1024,
932
          'not null' => FALSE,
933
        ),
934
      ),
935

    
936
     'testing_drupal_username' => array(
937
        'form' => array(
938
          'fieldset' => 'users',
939
          '#type' => 'textfield',
940
          '#size' => 30,
941
          '#title' => t('Testing Drupal Username'),
942
          '#description' => t('This is optional and used for testing this server\'s configuration against an actual username.  The user need not exist in Drupal and testing will not affect the user\'s LDAP or Drupal Account.'),
943
        ),
944
        'schema' => array(
945
          'type' => 'varchar',
946
          'length' => 255,
947
          'not null' => FALSE,
948
        ),
949
      ),
950

    
951
     'testing_drupal_user_dn' => array(
952
        'form' => array(
953
          'fieldset' => 'users',
954
          '#type' => 'textfield',
955
          '#size' => 120,
956
          '#title' => t('DN of testing username, e.g. cn=hpotter,ou=people,dc=hogwarts,dc=edu'),
957
          '#description' => t('This is optional and used for testing this server\'s configuration against an actual username.  The user need not exist in Drupal and testing will not affect the user\'s LDAP or Drupal Account.'),
958
        ),
959
        'schema' => array(
960
          'type' => 'varchar',
961
          'length' => 255,
962
          'not null' => FALSE,
963
        ),
964
      ),
965

    
966
      'grp_unused' => array(
967
        'form' => array(
968
          'fieldset' => 'groups',
969
          '#type' => 'checkbox',
970
          '#title' => t('Groups are not relevant to this Drupal site.  This is generally true if LDAP Groups, LDAP Authorization, etc are not it use.'),
971
          '#disabled' => FALSE,
972
        ),
973
        'schema' => array(
974
          'type' => 'int',
975
          'size' => 'tiny',
976
          'not null' => FALSE,
977
          'default' => 0,
978
        ),
979
      ),
980

    
981
     'grp_object_cat' => array(
982
        'form' => array(
983
          'fieldset' => 'groups',
984
          '#type' => 'textfield',
985
          '#size' => 30,
986
          '#title' => t('Name of Group Object Class'),
987
          '#description' => t('e.g. groupOfNames, groupOfUniqueNames, group.'),
988
          '#states' => array(
989
              'visible' => array(   // action to take.
990
                ':input[name=grp_unused]' => array('checked' => FALSE),
991
              ),
992
            ),
993
        ),
994
        'schema' => array(
995
          'type' => 'varchar',
996
          'length' => 64,
997
          'not null' => FALSE,
998
        ),
999
      ),
1000

    
1001
      'grp_nested' => array(
1002
        'form' => array(
1003
          'fieldset' => 'groups',
1004
          '#type' => 'checkbox',
1005
          '#title' => t('Nested groups are used in my LDAP'),
1006
          '#disabled' => FALSE,
1007
          '#description' => t('If a user is a member of group A and group A is a member of group B,
1008
             user should be considered to be in group A and B.  If your LDAP has nested groups, but you
1009
             want to ignore nesting, leave this unchecked.'),
1010
          '#states' => array(
1011
              'visible' => array(   // action to take.
1012
                ':input[name=grp_unused]' => array('checked' => FALSE),
1013
              ),
1014
            ),
1015
        ),
1016
        'schema' => array(
1017
          'type' => 'int',
1018
          'size' => 'tiny',
1019
          'not null' => FALSE,
1020
          'default' => 0,
1021
        ),
1022
      ),
1023

    
1024
      'grp_user_memb_attr_exists' => array(
1025
        'form' => array(
1026
          'fieldset' => 'groups',
1027
          '#type' => 'checkbox',
1028
          '#title' => t('A user LDAP attribute such as <code>memberOf</code> exists that contains a list of their groups.
1029
            Active Directory and openLdap with memberOf overlay fit this model.'),
1030
          '#disabled' => FALSE,
1031
          '#states' => array(
1032
             'visible' => array(   // action to take.
1033
               ':input[name=grp_unused]' => array('checked' => FALSE),
1034
              ),
1035
            ),
1036
        ),
1037
        'schema' => array(
1038
          'type' => 'int',
1039
          'size' => 'tiny',
1040
          'not null' => FALSE,
1041
          'default' => 0,
1042
        ),
1043
      ),
1044

    
1045
      'grp_user_memb_attr' => array(
1046
        'form' => array(
1047
          'fieldset' => 'groups',
1048
          '#type' => 'textfield',
1049
          '#size' => 30,
1050
          '#title' => t('Attribute in User Entry Containing Groups'),
1051
          '#description' => t('e.g. memberOf'),
1052
          '#states' => array(
1053
            'enabled' => array(   // action to take.
1054
              ':input[name=grp_user_memb_attr_exists]' => array('checked' => TRUE),
1055
            ),
1056
              'visible' => array(   // action to take.
1057
              ':input[name=grp_unused]' => array('checked' => FALSE),
1058
            ),
1059
          ),
1060
        ),
1061
        'schema' => array(
1062
          'type' => 'varchar',
1063
          'length' => 255,
1064
          'not null' => FALSE,
1065
        ),
1066
      ),
1067

    
1068
      'grp_memb_attr' => array(
1069
        'form' => array(
1070
          'fieldset' => 'groups',
1071
          '#type' => 'textfield',
1072
          '#size' => 30,
1073
          '#title' => t('LDAP Group Entry Attribute Holding User\'s DN, CN, etc.'),
1074
          '#description' => t('e.g uniquemember, memberUid'),
1075
          '#states' => array(
1076
              'visible' => array(   // action to take.
1077
                ':input[name=grp_unused]' => array('checked' => FALSE),
1078
              ),
1079
            ),
1080
        ),
1081
        'schema' => array(
1082
          'type' => 'varchar',
1083
          'length' => 255,
1084
          'not null' => FALSE,
1085
        ),
1086
      ),
1087

    
1088
      'grp_memb_attr_match_user_attr' => array(
1089
        'form' => array(
1090
          'fieldset' => 'groups',
1091
          '#type' => 'textfield',
1092
          '#size' => 30,
1093
          '#title' => t('User attribute held in "LDAP Group Entry Attribute Holding..."'),
1094
          '#description' => t('This is almost always "dn" (which technically isn\'t an attribute).  Sometimes its "cn".'),
1095
          '#states' => array(
1096
              'visible' => array(   // action to take.
1097
                ':input[name=grp_unused]' => array('checked' => FALSE),
1098
              ),
1099
            ),
1100
        ),
1101
        'schema' => array(
1102
          'type' => 'varchar',
1103
          'length' => 255,
1104
          'not null' => FALSE,
1105
        ),
1106
      ),
1107

    
1108
      'grp_derive_from_dn' => array(
1109
        'form' => array(
1110
          'fieldset' => 'groups',
1111
          '#type' => 'checkbox',
1112
          '#title' => t('Groups are derived from user\'s LDAP entry DN.') . '<em>' .
1113
            t('This
1114
            group definition has very limited functionality and most modules will
1115
            not take this into account.  LDAP Authorization will.') . '</em>',
1116
          '#disabled' => FALSE,
1117
          '#states' => array(
1118
              'visible' => array(   // action to take.
1119
                ':input[name=grp_unused]' => array('checked' => FALSE),
1120
              ),
1121
            ),
1122
        ),
1123
        'schema' => array(
1124
          'type' => 'int',
1125
          'size' => 'tiny',
1126
          'not null' => FALSE,
1127
          'default' => 0,
1128
        ),
1129
      ),
1130

    
1131
      'grp_derive_from_dn_attr' => array(
1132
        'form' => array(
1133
          'fieldset' => 'groups',
1134
          '#type' => 'textfield',
1135
          '#size' => 30,
1136
          '#title' => t('Attribute of the User\'s LDAP Entry DN which contains the group'),
1137
          '#description' => t('e.g. ou'),
1138
          '#states' => array(
1139
            'enabled' => array(   // action to take.
1140
              ':input[name=grp_derive_from_dn]' => array('checked' => TRUE),
1141
            ),
1142
              'visible' => array(   // action to take.
1143
              ':input[name=grp_unused]' => array('checked' => FALSE),
1144
            ),
1145
          ),
1146
        ),
1147
        'schema' => array(
1148
          'type' => 'varchar',
1149
          'length' => 255,
1150
          'not null' => FALSE,
1151
        ),
1152
      ),
1153

    
1154
     'grp_test_grp_dn' => array(
1155
        'form' => array(
1156
          'fieldset' => 'groups',
1157
          '#type' => 'textfield',
1158
          '#size' => 120,
1159
          '#title' => t('Testing LDAP Group DN'),
1160
          '#description' => t('This is optional and can be useful for debugging and validating forms.'),
1161
          '#states' => array(
1162
              'visible' => array(   // action to take.
1163
                ':input[name=grp_unused]' => array('checked' => FALSE),
1164
              ),
1165
            ),
1166
        ),
1167
        'schema' => array(
1168
          'type' => 'varchar',
1169
          'length' => 255,
1170
          'not null' => FALSE,
1171
        ),
1172
      ),
1173

    
1174
     'grp_test_grp_dn_writeable' => array(
1175
        'form' => array(
1176
          'fieldset' => 'groups',
1177
          '#type' => 'textfield',
1178
          '#size' => 120,
1179
          '#title' => t('Testing LDAP Group DN that is writable.  WARNING the test script for the server will create, delete, and add members to this group!'),
1180
          '#description' => t('This is optional and can be useful for debugging and validating forms.'),
1181
          '#states' => array(
1182
              'visible' => array(   // action to take.
1183
                ':input[name=grp_unused]' => array('checked' => FALSE),
1184
              ),
1185
            ),
1186
        ),
1187
        'schema' => array(
1188
          'type' => 'varchar',
1189
          'length' => 255,
1190
          'not null' => FALSE,
1191
        ),
1192
      ),
1193

    
1194
      'search_pagination' => array(
1195
        'form' => array(
1196
          'fieldset' => 'pagination',
1197
          '#type' => 'checkbox',
1198
          '#title' => t('Use LDAP Pagination.'),
1199
          '#disabled' => !ldap_servers_php_supports_pagination(),
1200
        ),
1201
        'schema' => array(
1202
          'type' => 'int',
1203
          'size' => 'tiny',
1204
          'not null' => FALSE,
1205
          'default' => 0,
1206
        ),
1207
      ),
1208

    
1209
     'search_page_size' => array(
1210
        'form' => array(
1211
          'fieldset' => 'pagination',
1212
          '#type' => 'textfield',
1213
          '#size' => 10,
1214
          '#disabled' => !ldap_servers_php_supports_pagination(),
1215
          '#title' => t('Pagination size limit.'),
1216
          '#description' => t('This should be equal to or smaller than the max
1217
            number of entries returned at a time by your ldap server.
1218
            1000 is a good guess when unsure. Other modules such as LDAP Query
1219
            or LDAP Feeds will be allowed to set a smaller page size, but not
1220
            a larger one.'),
1221
          '#states' => array(
1222
            'visible' => array(   // action to take.
1223
              ':input[name="search_pagination"]' => array('checked' => TRUE),
1224
            ),
1225
      ),
1226
        ),
1227
        'schema' => array(
1228
          'type' => 'int',
1229
          'size' => 'medium',
1230
          'not null' => FALSE,
1231
          'default' => 1000,
1232
        ),
1233
      ),
1234

    
1235
      'weight' => array(
1236
        'schema' => array(
1237
          'type' => 'int',
1238
          'not null' => FALSE,
1239
          'default' => 0,
1240
        ),
1241
      ),
1242

    
1243
    );
1244

    
1245
  return $fields;
1246

    
1247
  }
1248
}