Coverage Report

Created: 2026-02-14 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/lib/smbldap.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
   LDAP protocol helper functions for SAMBA
4
   Copyright (C) Jean François Micouleau 1998
5
   Copyright (C) Gerald Carter      2001-2003
6
   Copyright (C) Shahms King      2001
7
   Copyright (C) Andrew Bartlett    2002-2003
8
   Copyright (C) Stefan (metze) Metzmacher  2002-2003
9
10
   This program is free software; you can redistribute it and/or modify
11
   it under the terms of the GNU General Public License as published by
12
   the Free Software Foundation; either version 3 of the License, or
13
   (at your option) any later version.
14
15
   This program is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
   GNU General Public License for more details.
19
20
   You should have received a copy of the GNU General Public License
21
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
23
*/
24
25
#include "includes.h"
26
#include "smbldap.h"
27
#include "../libcli/security/security.h"
28
#include <tevent.h>
29
#include "lib/param/loadparm.h"
30
31
/* Try not to hit the up or down server forever */
32
33
0
#define SMBLDAP_DONT_PING_TIME 10  /* ping only all 10 seconds */
34
#define SMBLDAP_NUM_RETRIES 8         /* retry only 8 times */
35
36
0
#define SMBLDAP_IDLE_TIME 150    /* After 2.5 minutes disconnect */
37
38
struct smbldap_state {
39
  LDAP *ldap_struct;
40
  pid_t pid;
41
  time_t last_ping; /* monotonic */
42
  /* retrieve-once info */
43
  const char *uri;
44
45
  /* credentials */
46
  bool anonymous;
47
  char *bind_dn;
48
  char *bind_secret;
49
  smbldap_bind_callback_fn bind_callback;
50
  void *bind_callback_data;
51
52
  bool paged_results;
53
54
  unsigned int num_failures;
55
56
  time_t last_use; /* monotonic */
57
  struct tevent_context *tevent_context;
58
  struct tevent_timer *idle_event;
59
60
  struct timeval last_rebind; /* monotonic */
61
};
62
63
LDAP *smbldap_get_ldap(struct smbldap_state *state)
64
0
{
65
0
  return state->ldap_struct;
66
0
}
67
68
bool smbldap_get_paged_results(struct smbldap_state *state)
69
0
{
70
0
  return state->paged_results;
71
0
}
72
73
void smbldap_set_paged_results(struct smbldap_state *state,
74
             bool paged_results)
75
0
{
76
0
  state->paged_results = paged_results;
77
0
}
78
79
void smbldap_set_bind_callback(struct smbldap_state *state,
80
             smbldap_bind_callback_fn callback,
81
             void *callback_data)
82
0
{
83
0
  state->bind_callback = callback;
84
0
  state->bind_callback_data = callback_data;
85
0
}
86
/*******************************************************************
87
 Search an attribute and return the first value found.
88
******************************************************************/
89
90
 bool smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
91
            const char *attribute, char *value,
92
            int max_len)
93
0
{
94
0
  char **values;
95
0
  size_t size = 0;
96
97
0
  if ( !attribute )
98
0
    return False;
99
100
0
  value[0] = '\0';
101
102
0
  if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
103
0
    DEBUG (10, ("smbldap_get_single_attribute: [%s] = [<does not exist>]\n", attribute));
104
105
0
    return False;
106
0
  }
107
108
0
  if (!convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, max_len, &size)) {
109
0
    DEBUG(1, ("smbldap_get_single_attribute: string conversion of [%s] = [%s] failed!\n",
110
0
        attribute, values[0]));
111
0
    ldap_value_free(values);
112
0
    return False;
113
0
  }
114
115
0
  ldap_value_free(values);
116
0
#ifdef DEBUG_PASSWORD
117
0
  DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n", attribute, value));
118
0
#endif
119
0
  return True;
120
0
}
121
122
 char * smbldap_talloc_single_attribute(LDAP *ldap_struct, LDAPMessage *entry,
123
          const char *attribute,
124
          TALLOC_CTX *mem_ctx)
125
0
{
126
0
  char **values;
127
0
  char *result;
128
0
  size_t converted_size;
129
130
0
  if (attribute == NULL) {
131
0
    return NULL;
132
0
  }
133
134
0
  values = ldap_get_values(ldap_struct, entry, attribute);
135
136
0
  if (values == NULL) {
137
0
    DEBUG(10, ("attribute %s does not exist\n", attribute));
138
0
    return NULL;
139
0
  }
140
141
0
  if (ldap_count_values(values) != 1) {
142
0
    DEBUG(10, ("attribute %s has %d values, expected only one\n",
143
0
         attribute, ldap_count_values(values)));
144
0
    ldap_value_free(values);
145
0
    return NULL;
146
0
  }
147
148
0
  if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
149
0
    DEBUG(10, ("pull_utf8_talloc failed\n"));
150
0
    ldap_value_free(values);
151
0
    return NULL;
152
0
  }
153
154
0
  ldap_value_free(values);
155
156
0
#ifdef DEBUG_PASSWORD
157
0
  DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
158
0
         attribute, result));
159
0
#endif
160
0
  return result;
161
0
}
162
163
 char * smbldap_talloc_first_attribute(LDAP *ldap_struct, LDAPMessage *entry,
164
               const char *attribute,
165
               TALLOC_CTX *mem_ctx)
166
0
{
167
0
  char **values;
168
0
  char *result;
169
0
  size_t converted_size;
170
171
0
  if (attribute == NULL) {
172
0
    return NULL;
173
0
  }
174
175
0
  values = ldap_get_values(ldap_struct, entry, attribute);
176
177
0
  if (values == NULL) {
178
0
    DEBUG(10, ("attribute %s does not exist\n", attribute));
179
0
    return NULL;
180
0
  }
181
182
0
  if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
183
0
    DEBUG(10, ("pull_utf8_talloc failed\n"));
184
0
    ldap_value_free(values);
185
0
    return NULL;
186
0
  }
187
188
0
  ldap_value_free(values);
189
190
0
#ifdef DEBUG_PASSWORD
191
0
  DEBUG (100, ("smbldap_get_first_attribute: [%s] = [%s]\n",
192
0
         attribute, result));
193
0
#endif
194
0
  return result;
195
0
}
196
197
 char * smbldap_talloc_smallest_attribute(LDAP *ldap_struct, LDAPMessage *entry,
198
            const char *attribute,
199
            TALLOC_CTX *mem_ctx)
200
0
{
201
0
  char **values;
202
0
  char *result;
203
0
  size_t converted_size;
204
0
  int i, num_values;
205
206
0
  if (attribute == NULL) {
207
0
    return NULL;
208
0
  }
209
210
0
  values = ldap_get_values(ldap_struct, entry, attribute);
211
212
0
  if (values == NULL) {
213
0
    DEBUG(10, ("attribute %s does not exist\n", attribute));
214
0
    return NULL;
215
0
  }
216
217
0
  if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
218
0
    DEBUG(10, ("pull_utf8_talloc failed\n"));
219
0
    ldap_value_free(values);
220
0
    return NULL;
221
0
  }
222
223
0
  num_values = ldap_count_values(values);
224
225
0
  for (i=1; i<num_values; i++) {
226
0
    char *tmp;
227
228
0
    if (!pull_utf8_talloc(mem_ctx, &tmp, values[i],
229
0
              &converted_size)) {
230
0
      DEBUG(10, ("pull_utf8_talloc failed\n"));
231
0
      TALLOC_FREE(result);
232
0
      ldap_value_free(values);
233
0
      return NULL;
234
0
    }
235
236
0
    if (strcasecmp_m(tmp, result) < 0) {
237
0
      TALLOC_FREE(result);
238
0
      result = tmp;
239
0
    } else {
240
0
      TALLOC_FREE(tmp);
241
0
    }
242
0
  }
243
244
0
  ldap_value_free(values);
245
246
0
#ifdef DEBUG_PASSWORD
247
0
  DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
248
0
         attribute, result));
249
0
#endif
250
0
  return result;
251
0
}
252
253
 bool smbldap_talloc_single_blob(TALLOC_CTX *mem_ctx, LDAP *ld,
254
         LDAPMessage *msg, const char *attrib,
255
         DATA_BLOB *blob)
256
0
{
257
0
  struct berval **values;
258
259
0
  values = ldap_get_values_len(ld, msg, attrib);
260
0
  if (!values) {
261
0
    return false;
262
0
  }
263
264
0
  if (ldap_count_values_len(values) != 1) {
265
0
    DEBUG(10, ("Expected one value for %s, got %d\n", attrib,
266
0
         ldap_count_values_len(values)));
267
0
    return false;
268
0
  }
269
270
0
  *blob = data_blob_talloc(mem_ctx, values[0]->bv_val,
271
0
         values[0]->bv_len);
272
0
  ldap_value_free_len(values);
273
274
0
  return (blob->data != NULL);
275
0
}
276
277
 bool smbldap_pull_sid(LDAP *ld, LDAPMessage *msg, const char *attrib,
278
           struct dom_sid *sid)
279
0
{
280
0
  DATA_BLOB blob;
281
0
  ssize_t ret;
282
283
0
  if (!smbldap_talloc_single_blob(talloc_tos(), ld, msg, attrib,
284
0
          &blob)) {
285
0
    return false;
286
0
  }
287
0
  ret = sid_parse(blob.data, blob.length, sid);
288
0
  TALLOC_FREE(blob.data);
289
0
  return (ret != -1);
290
0
}
291
292
0
 static int ldapmsg_destructor(LDAPMessage **result) {
293
0
  ldap_msgfree(*result);
294
0
  return 0;
295
0
}
296
297
 void smbldap_talloc_autofree_ldapmsg(TALLOC_CTX *mem_ctx, LDAPMessage *result)
298
0
{
299
0
  LDAPMessage **handle;
300
301
0
  if (result == NULL) {
302
0
    return;
303
0
  }
304
305
0
  handle = talloc(mem_ctx, LDAPMessage *);
306
0
  SMB_ASSERT(handle != NULL);
307
308
0
  *handle = result;
309
0
  talloc_set_destructor(handle, ldapmsg_destructor);
310
0
}
311
312
0
 static int ldapmod_destructor(LDAPMod ***mod) {
313
0
  ldap_mods_free(*mod, True);
314
0
  return 0;
315
0
}
316
317
 void smbldap_talloc_autofree_ldapmod(TALLOC_CTX *mem_ctx, LDAPMod **mod)
318
0
{
319
0
  LDAPMod ***handle;
320
321
0
  if (mod == NULL) {
322
0
    return;
323
0
  }
324
325
0
  handle = talloc(mem_ctx, LDAPMod **);
326
0
  SMB_ASSERT(handle != NULL);
327
328
0
  *handle = mod;
329
0
  talloc_set_destructor(handle, ldapmod_destructor);
330
0
}
331
332
/************************************************************************
333
 Routine to manage the LDAPMod structure array
334
 manage memory used by the array, by each struct, and values
335
 ***********************************************************************/
336
337
static void smbldap_set_mod_internal(LDAPMod *** modlist, int modop, const char *attribute, const char *value, const DATA_BLOB *blob)
338
0
{
339
0
  LDAPMod **mods;
340
0
  int i;
341
0
  int j;
342
343
0
  mods = *modlist;
344
345
  /* sanity checks on the mod values */
346
347
0
  if (attribute == NULL || *attribute == '\0') {
348
0
    return;
349
0
  }
350
351
#if 0 /* commented out after discussion with abartlet.  Do not re-enable.
352
     left here so other do not re-add similar code   --jerry */
353
        if (value == NULL || *value == '\0')
354
    return;
355
#endif
356
357
0
  if (mods == NULL) {
358
0
    mods = SMB_MALLOC_P(LDAPMod *);
359
0
    if (mods == NULL) {
360
0
      smb_panic("smbldap_set_mod: out of memory!");
361
      /* notreached. */
362
0
    }
363
0
    mods[0] = NULL;
364
0
  }
365
366
0
  for (i = 0; mods[i] != NULL; ++i) {
367
0
    if (mods[i]->mod_op == modop && strequal(mods[i]->mod_type, attribute))
368
0
      break;
369
0
  }
370
371
0
  if (mods[i] == NULL) {
372
0
    mods = SMB_REALLOC_ARRAY (mods, LDAPMod *, i + 2);
373
0
    if (mods == NULL) {
374
0
      smb_panic("smbldap_set_mod: out of memory!");
375
      /* notreached. */
376
0
    }
377
0
    mods[i] = SMB_MALLOC_P(LDAPMod);
378
0
    if (mods[i] == NULL) {
379
0
      smb_panic("smbldap_set_mod: out of memory!");
380
      /* notreached. */
381
0
    }
382
0
    mods[i]->mod_op = modop;
383
0
    mods[i]->mod_values = NULL;
384
0
    mods[i]->mod_type = SMB_STRDUP(attribute);
385
0
    mods[i + 1] = NULL;
386
0
  }
387
388
0
  if (blob && (modop & LDAP_MOD_BVALUES)) {
389
0
    j = 0;
390
0
    if (mods[i]->mod_bvalues != NULL) {
391
0
      for (; mods[i]->mod_bvalues[j] != NULL; j++);
392
0
    }
393
0
    mods[i]->mod_bvalues = SMB_REALLOC_ARRAY(mods[i]->mod_bvalues, struct berval *, j + 2);
394
395
0
    if (mods[i]->mod_bvalues == NULL) {
396
0
      smb_panic("smbldap_set_mod: out of memory!");
397
      /* notreached. */
398
0
    }
399
400
0
    mods[i]->mod_bvalues[j] = SMB_MALLOC_P(struct berval);
401
0
    SMB_ASSERT(mods[i]->mod_bvalues[j] != NULL);
402
403
0
    mods[i]->mod_bvalues[j]->bv_val = (char *)smb_memdup(blob->data, blob->length);
404
0
    SMB_ASSERT(mods[i]->mod_bvalues[j]->bv_val != NULL);
405
0
    mods[i]->mod_bvalues[j]->bv_len = blob->length;
406
407
0
    mods[i]->mod_bvalues[j + 1] = NULL;
408
0
  } else if (value != NULL) {
409
0
    char *utf8_value = NULL;
410
0
    size_t converted_size;
411
412
0
    j = 0;
413
0
    if (mods[i]->mod_values != NULL) {
414
0
      for (; mods[i]->mod_values[j] != NULL; j++);
415
0
    }
416
0
    mods[i]->mod_values = SMB_REALLOC_ARRAY(mods[i]->mod_values, char *, j + 2);
417
418
0
    if (mods[i]->mod_values == NULL) {
419
0
      smb_panic("smbldap_set_mod: out of memory!");
420
      /* notreached. */
421
0
    }
422
423
0
    if (!push_utf8_talloc(talloc_tos(), &utf8_value, value, &converted_size)) {
424
0
      smb_panic("smbldap_set_mod: String conversion failure!");
425
      /* notreached. */
426
0
    }
427
428
0
    mods[i]->mod_values[j] = SMB_STRDUP(utf8_value);
429
0
    TALLOC_FREE(utf8_value);
430
0
    SMB_ASSERT(mods[i]->mod_values[j] != NULL);
431
432
0
    mods[i]->mod_values[j + 1] = NULL;
433
0
  }
434
0
  *modlist = mods;
435
0
}
436
437
 void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
438
0
{
439
0
  smbldap_set_mod_internal(modlist, modop, attribute, value, NULL);
440
0
}
441
442
 void smbldap_set_mod_blob(LDAPMod *** modlist, int modop, const char *attribute, const DATA_BLOB *value)
443
0
{
444
0
  smbldap_set_mod_internal(modlist, modop | LDAP_MOD_BVALUES, attribute, NULL, value);
445
0
}
446
447
/**********************************************************************
448
  Set attribute to newval in LDAP, regardless of what value the
449
  attribute had in LDAP before.
450
*********************************************************************/
451
452
static void smbldap_make_mod_internal(LDAP *ldap_struct, LDAPMessage *existing,
453
              LDAPMod ***mods,
454
              const char *attribute, int op,
455
              const char *newval,
456
              const DATA_BLOB *newblob)
457
0
{
458
0
  char oldval[2048]; /* current largest allowed value is mungeddial */
459
0
  bool existed;
460
0
  DATA_BLOB oldblob = data_blob_null;
461
462
0
  if (existing != NULL) {
463
0
    if (op & LDAP_MOD_BVALUES) {
464
0
      existed = smbldap_talloc_single_blob(talloc_tos(), ldap_struct, existing, attribute, &oldblob);
465
0
    } else {
466
0
      existed = smbldap_get_single_attribute(ldap_struct, existing, attribute, oldval, sizeof(oldval));
467
0
    }
468
0
  } else {
469
0
    existed = False;
470
0
    *oldval = '\0';
471
0
  }
472
473
0
  if (existed) {
474
0
    bool equal = false;
475
0
    if (op & LDAP_MOD_BVALUES) {
476
0
      equal = (newblob && (data_blob_cmp(&oldblob, newblob) == 0));
477
0
    } else {
478
      /* all of our string attributes are case insensitive */
479
0
      equal = (newval && (strcasecmp_m(oldval, newval) == 0));
480
0
    }
481
482
0
    if (equal) {
483
      /* Believe it or not, but LDAP will deny a delete and
484
         an add at the same time if the values are the
485
         same... */
486
0
      DEBUG(10,("smbldap_make_mod: attribute |%s| not changed.\n", attribute));
487
0
      return;
488
0
    }
489
490
    /* There has been no value before, so don't delete it.
491
     * Here's a possible race: We might end up with
492
     * duplicate attributes */
493
    /* By deleting exactly the value we found in the entry this
494
     * should be race-free in the sense that the LDAP-Server will
495
     * deny the complete operation if somebody changed the
496
     * attribute behind our back. */
497
    /* This will also allow modifying single valued attributes
498
     * in Novell NDS. In NDS you have to first remove attribute and then
499
     * you could add new value */
500
501
0
    if (op & LDAP_MOD_BVALUES) {
502
0
      DEBUG(10,("smbldap_make_mod: deleting attribute |%s| blob\n", attribute));
503
0
      smbldap_set_mod_blob(mods, LDAP_MOD_DELETE, attribute, &oldblob);
504
0
    } else {
505
0
      DEBUG(10,("smbldap_make_mod: deleting attribute |%s| values |%s|\n", attribute, oldval));
506
0
      smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, oldval);
507
0
    }
508
0
  }
509
510
  /* Regardless of the real operation (add or modify)
511
     we add the new value here. We rely on deleting
512
     the old value, should it exist. */
513
514
0
  if (op & LDAP_MOD_BVALUES) {
515
0
    if (newblob && newblob->length) {
516
0
      DEBUG(10,("smbldap_make_mod: adding attribute |%s| blob\n", attribute));
517
0
      smbldap_set_mod_blob(mods, LDAP_MOD_ADD, attribute, newblob);
518
0
    }
519
0
  } else {
520
0
    if ((newval != NULL) && (strlen(newval) > 0)) {
521
0
      DEBUG(10,("smbldap_make_mod: adding attribute |%s| value |%s|\n", attribute, newval));
522
0
      smbldap_set_mod(mods, LDAP_MOD_ADD, attribute, newval);
523
0
    }
524
0
  }
525
0
}
526
527
 void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing,
528
          LDAPMod ***mods,
529
          const char *attribute, const char *newval)
530
0
{
531
0
  smbldap_make_mod_internal(ldap_struct, existing, mods, attribute,
532
0
          0, newval, NULL);
533
0
}
534
535
 void smbldap_make_mod_blob(LDAP *ldap_struct, LDAPMessage *existing,
536
          LDAPMod ***mods,
537
          const char *attribute, const DATA_BLOB *newblob)
538
0
{
539
0
  smbldap_make_mod_internal(ldap_struct, existing, mods, attribute,
540
0
          LDAP_MOD_BVALUES, NULL, newblob);
541
0
}
542
543
/**********************************************************************
544
 Some variants of the LDAP rebind code do not pass in the third 'arg'
545
 pointer to a void*, so we try and work around it by assuming that the
546
 value of the 'LDAP *' pointer is the same as the one we had passed in
547
 **********************************************************************/
548
549
struct smbldap_state_lookup {
550
  LDAP *ld;
551
  struct smbldap_state *smbldap_state;
552
  struct smbldap_state_lookup *prev, *next;
553
};
554
555
static struct smbldap_state_lookup *smbldap_state_lookup_list;
556
557
static struct smbldap_state *smbldap_find_state(LDAP *ld)
558
0
{
559
0
  struct smbldap_state_lookup *t;
560
561
0
  for (t = smbldap_state_lookup_list; t; t = t->next) {
562
0
    if (t->ld == ld) {
563
0
      return t->smbldap_state;
564
0
    }
565
0
  }
566
0
  return NULL;
567
0
}
568
569
static void smbldap_delete_state(struct smbldap_state *smbldap_state)
570
0
{
571
0
  struct smbldap_state_lookup *t;
572
573
0
  for (t = smbldap_state_lookup_list; t; t = t->next) {
574
0
    if (t->smbldap_state == smbldap_state) {
575
0
      DLIST_REMOVE(smbldap_state_lookup_list, t);
576
0
      SAFE_FREE(t);
577
0
      return;
578
0
    }
579
0
  }
580
0
}
581
582
static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state)
583
0
{
584
0
  struct smbldap_state *tmp_ldap_state;
585
0
  struct smbldap_state_lookup *t;
586
587
0
  if ((tmp_ldap_state = smbldap_find_state(ld))) {
588
0
    SMB_ASSERT(tmp_ldap_state == smbldap_state);
589
0
    return;
590
0
  }
591
592
0
  t = SMB_XMALLOC_P(struct smbldap_state_lookup);
593
0
  ZERO_STRUCTP(t);
594
595
0
  DLIST_ADD_END(smbldap_state_lookup_list, t);
596
0
  t->ld = ld;
597
0
  t->smbldap_state = smbldap_state;
598
0
}
599
600
/********************************************************************
601
 start TLS on an existing LDAP connection per config
602
*******************************************************************/
603
604
int smbldap_start_tls(LDAP *ldap_struct, int version)
605
0
{
606
0
  if (lp_ldap_ssl() != LDAP_SSL_START_TLS) {
607
0
    return LDAP_SUCCESS;
608
0
  }
609
610
0
  return smbldap_start_tls_start(ldap_struct, version);
611
0
}
612
613
/********************************************************************
614
 start TLS on an existing LDAP connection unconditionally
615
*******************************************************************/
616
617
int smbldap_start_tls_start(LDAP *ldap_struct, int version)
618
0
{
619
0
#ifdef LDAP_OPT_X_TLS
620
0
  int rc,tls;
621
622
  /* check if we use ldaps already */
623
0
  ldap_get_option(ldap_struct, LDAP_OPT_X_TLS, &tls);
624
0
  if (tls == LDAP_OPT_X_TLS_HARD) {
625
0
    return LDAP_SUCCESS;
626
0
  }
627
628
0
  if (version != LDAP_VERSION3) {
629
0
    DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
630
0
    return LDAP_OPERATIONS_ERROR;
631
0
  }
632
633
0
  if ((rc = ldap_start_tls_s (ldap_struct, NULL, NULL)) != LDAP_SUCCESS) {
634
0
    DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
635
0
       ldap_err2string(rc)));
636
0
    return rc;
637
0
  }
638
639
0
  DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
640
0
  return LDAP_SUCCESS;
641
#else
642
  DEBUG(0,("StartTLS not supported by LDAP client libraries!\n"));
643
  return LDAP_OPERATIONS_ERROR;
644
#endif
645
0
}
646
647
/********************************************************************
648
 setup a connection to the LDAP server based on a uri
649
*******************************************************************/
650
651
static int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri)
652
0
{
653
0
  int rc;
654
655
0
  DEBUG(10, ("smb_ldap_setup_connection: %s\n", uri));
656
657
0
#ifdef HAVE_LDAP_INITIALIZE
658
659
0
  rc = ldap_initialize(ldap_struct, uri);
660
0
  if (rc) {
661
0
    DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
662
0
    return rc;
663
0
  }
664
665
0
  if (lp_ldap_follow_referral() != Auto) {
666
0
    rc = ldap_set_option(*ldap_struct, LDAP_OPT_REFERRALS,
667
0
         lp_ldap_follow_referral() ? LDAP_OPT_ON : LDAP_OPT_OFF);
668
0
    if (rc != LDAP_SUCCESS)
669
0
      DEBUG(0, ("Failed to set LDAP_OPT_REFERRALS: %s\n",
670
0
        ldap_err2string(rc)));
671
0
  }
672
673
#else
674
675
  /* Parse the string manually */
676
677
  {
678
    int port = 0;
679
    fstring protocol;
680
    fstring host;
681
    SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
682
683
684
    /* skip leading "URL:" (if any) */
685
    if ( strnequal( uri, "URL:", 4 ) ) {
686
      uri += 4;
687
    }
688
689
    sscanf(uri, "%10[^:]://%254[^:/]:%d", protocol, host, &port);
690
691
    if (port == 0) {
692
      if (strequal(protocol, "ldap")) {
693
        port = LDAP_PORT;
694
      } else if (strequal(protocol, "ldaps")) {
695
        port = LDAPS_PORT;
696
      } else {
697
        DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
698
      }
699
    }
700
701
    if ((*ldap_struct = ldap_init(host, port)) == NULL) {
702
      DEBUG(0, ("ldap_init failed !\n"));
703
      return LDAP_OPERATIONS_ERROR;
704
    }
705
706
          if (strequal(protocol, "ldaps")) {
707
#ifdef LDAP_OPT_X_TLS
708
      int tls = LDAP_OPT_X_TLS_HARD;
709
      if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
710
      {
711
        DEBUG(0, ("Failed to setup a TLS session\n"));
712
      }
713
714
      DEBUG(3,("LDAPS option set...!\n"));
715
#else
716
      DEBUG(0,("smbldap_open_connection: Secure connection not supported by LDAP client libraries!\n"));
717
      return LDAP_OPERATIONS_ERROR;
718
#endif /* LDAP_OPT_X_TLS */
719
    }
720
  }
721
722
  /* now set connection timeout */
723
#ifdef LDAP_X_OPT_CONNECT_TIMEOUT /* Netscape */
724
  {
725
    int ct = lp_ldap_connection_timeout()*1000;
726
    rc = ldap_set_option(*ldap_struct, LDAP_X_OPT_CONNECT_TIMEOUT, &ct);
727
    if (rc != LDAP_SUCCESS) {
728
      DEBUG(0,("Failed to setup an ldap connection timeout %d: %s\n",
729
        ct, ldap_err2string(rc)));
730
    }
731
  }
732
#elif defined (LDAP_OPT_NETWORK_TIMEOUT) /* OpenLDAP */
733
  {
734
    struct timeval ct;
735
    ct.tv_usec = 0;
736
    ct.tv_sec = lp_ldap_connection_timeout();
737
    rc = ldap_set_option(*ldap_struct, LDAP_OPT_NETWORK_TIMEOUT, &ct);
738
    if (rc != LDAP_SUCCESS) {
739
      DEBUG(0,("Failed to setup an ldap connection timeout %d: %s\n",
740
        (int)ct.tv_sec, ldap_err2string(rc)));
741
    }
742
  }
743
#endif
744
745
#endif /* HAVE_LDAP_INITIALIZE */
746
0
  return LDAP_SUCCESS;
747
0
}
748
749
/********************************************************************
750
 try to upgrade to Version 3 LDAP if not already, in either case return current
751
 version
752
 *******************************************************************/
753
754
static int smb_ldap_upgrade_conn(LDAP *ldap_struct, int *new_version)
755
0
{
756
0
  int version;
757
0
  int rc;
758
759
  /* assume the worst */
760
0
  *new_version = LDAP_VERSION2;
761
762
0
  rc = ldap_get_option(ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
763
0
  if (rc) {
764
0
    return rc;
765
0
  }
766
767
0
  if (version == LDAP_VERSION3) {
768
0
    *new_version = LDAP_VERSION3;
769
0
    return LDAP_SUCCESS;
770
0
  }
771
772
  /* try upgrade */
773
0
  version = LDAP_VERSION3;
774
0
  rc = ldap_set_option (ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
775
0
  if (rc) {
776
0
    return rc;
777
0
  }
778
779
0
  *new_version = LDAP_VERSION3;
780
0
  return LDAP_SUCCESS;
781
0
}
782
783
/*******************************************************************
784
 open a connection to the ldap server (just until the bind)
785
 ******************************************************************/
786
787
int smbldap_setup_full_conn(LDAP **ldap_struct, const char *uri)
788
0
{
789
0
  int rc, version;
790
791
0
  rc = smb_ldap_setup_conn(ldap_struct, uri);
792
0
  if (rc) {
793
0
    return rc;
794
0
  }
795
796
0
  rc = smb_ldap_upgrade_conn(*ldap_struct, &version);
797
0
  if (rc) {
798
0
    return rc;
799
0
  }
800
801
0
  rc = smbldap_start_tls(*ldap_struct, version);
802
0
  if (rc) {
803
0
    return rc;
804
0
  }
805
806
0
  return LDAP_SUCCESS;
807
0
}
808
809
/*******************************************************************
810
 open a connection to the ldap server.
811
******************************************************************/
812
static int smbldap_open_connection (struct smbldap_state *ldap_state)
813
814
0
{
815
0
  int rc = LDAP_SUCCESS;
816
0
  int version;
817
0
  int deref;
818
0
  LDAP **ldap_struct = &ldap_state->ldap_struct;
819
820
0
  rc = smb_ldap_setup_conn(ldap_struct, ldap_state->uri);
821
0
  if (rc) {
822
0
    return rc;
823
0
  }
824
825
  /* Store the LDAP pointer in a lookup list */
826
827
0
  smbldap_store_state(*ldap_struct, ldap_state);
828
829
  /* Upgrade to LDAPv3 if possible */
830
831
0
  rc = smb_ldap_upgrade_conn(*ldap_struct, &version);
832
0
  if (rc) {
833
0
    return rc;
834
0
  }
835
836
  /* Start TLS if required */
837
838
0
  rc = smbldap_start_tls(*ldap_struct, version);
839
0
  if (rc) {
840
0
    return rc;
841
0
  }
842
843
  /* Set alias dereferencing method */
844
0
  deref = lp_ldap_deref();
845
0
  if (deref != -1) {
846
0
    if (ldap_set_option (*ldap_struct, LDAP_OPT_DEREF, &deref) != LDAP_OPT_SUCCESS) {
847
0
      DEBUG(1,("smbldap_open_connection: Failed to set dereferencing method: %d\n", deref));
848
0
    } else {
849
0
      DEBUG(5,("Set dereferencing method: %d\n", deref));
850
0
    }
851
0
  }
852
853
0
  DEBUG(2, ("smbldap_open_connection: connection opened\n"));
854
0
  return rc;
855
0
}
856
857
/*******************************************************************
858
 a rebind function for authenticated referrals
859
 This version takes a void* that we can shove useful stuff in :-)
860
******************************************************************/
861
#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
862
#else
863
static int rebindproc_with_state  (LDAP * ld, char **whop, char **credp,
864
           int *methodp, int freeit, void *arg)
865
{
866
  struct smbldap_state *ldap_state = arg;
867
  struct timespec ts;
868
869
  /** @TODO Should we be doing something to check what servers we rebind to?
870
      Could we get a referral to a machine that we don't want to give our
871
      username and password to? */
872
873
  if (freeit) {
874
    SAFE_FREE(*whop);
875
    if (*credp) {
876
      memset(*credp, '\0', strlen(*credp));
877
    }
878
    SAFE_FREE(*credp);
879
  } else {
880
    DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
881
        ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
882
883
    if (ldap_state->anonymous) {
884
      *whop = NULL;
885
      *credp = NULL;
886
    } else {
887
      *whop = SMB_STRDUP(ldap_state->bind_dn);
888
      if (!*whop) {
889
        return LDAP_NO_MEMORY;
890
      }
891
      *credp = SMB_STRDUP(ldap_state->bind_secret);
892
      if (!*credp) {
893
        SAFE_FREE(*whop);
894
        return LDAP_NO_MEMORY;
895
      }
896
    }
897
    *methodp = LDAP_AUTH_SIMPLE;
898
  }
899
900
  clock_gettime_mono(&ts);
901
  ldap_state->last_rebind = convert_timespec_to_timeval(ts);
902
903
  return 0;
904
}
905
#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
906
907
/*******************************************************************
908
 a rebind function for authenticated referrals
909
 This version takes a void* that we can shove useful stuff in :-)
910
 and actually does the connection.
911
******************************************************************/
912
#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
913
static int rebindproc_connect_with_state (LDAP *ldap_struct,
914
            LDAP_CONST char *url,
915
            ber_tag_t request,
916
            ber_int_t msgid, void *arg)
917
0
{
918
0
  struct smbldap_state *ldap_state =
919
0
    (struct smbldap_state *)arg;
920
0
  int rc;
921
0
  struct timespec ts;
922
0
  int version;
923
924
0
  DEBUG(5,("rebindproc_connect_with_state: Rebinding to %s as \"%s\"\n",
925
0
     url, ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
926
927
  /* call START_TLS again (ldaps:// is handled by the OpenLDAP library
928
   * itself) before rebinding to another LDAP server to avoid to expose
929
   * our credentials. At least *try* to secure the connection - Guenther */
930
931
0
  smb_ldap_upgrade_conn(ldap_struct, &version);
932
0
  smbldap_start_tls(ldap_struct, version);
933
934
  /** @TODO Should we be doing something to check what servers we rebind to?
935
      Could we get a referral to a machine that we don't want to give our
936
      username and password to? */
937
938
0
  rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
939
940
  /* only set the last rebind timestamp when we did rebind after a
941
   * non-read LDAP operation. That way we avoid the replication sleep
942
   * after a simple redirected search operation - Guenther */
943
944
0
  switch (request) {
945
946
0
    case LDAP_REQ_MODIFY:
947
0
    case LDAP_REQ_ADD:
948
0
    case LDAP_REQ_DELETE:
949
0
    case LDAP_REQ_MODDN:
950
0
    case LDAP_REQ_EXTENDED:
951
0
      DEBUG(10,("rebindproc_connect_with_state: "
952
0
        "setting last_rebind timestamp "
953
0
        "(req: 0x%02x)\n", (unsigned int)request));
954
0
      clock_gettime_mono(&ts);
955
0
      ldap_state->last_rebind = convert_timespec_to_timeval(ts);
956
0
      break;
957
0
    default:
958
0
      ZERO_STRUCT(ldap_state->last_rebind);
959
0
      break;
960
0
  }
961
962
0
  return rc;
963
0
}
964
#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
965
966
/*******************************************************************
967
 Add a rebind function for authenticated referrals
968
******************************************************************/
969
#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
970
#else
971
# if LDAP_SET_REBIND_PROC_ARGS == 2
972
static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
973
           int *method, int freeit )
974
{
975
  struct smbldap_state *ldap_state = smbldap_find_state(ldap_struct);
976
977
  return rebindproc_with_state(ldap_struct, whop, credp,
978
             method, freeit, ldap_state);
979
}
980
# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
981
#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
982
983
/*******************************************************************
984
 a rebind function for authenticated referrals
985
 this also does the connection, but no void*.
986
******************************************************************/
987
#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
988
# if LDAP_SET_REBIND_PROC_ARGS == 2
989
static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
990
             ber_int_t msgid)
991
{
992
  struct smbldap_state *ldap_state = smbldap_find_state(ld);
993
994
  return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid,
995
               ldap_state);
996
}
997
# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
998
#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
999
1000
/*******************************************************************
1001
 connect to the ldap server under system privilege.
1002
******************************************************************/
1003
static int smbldap_connect_system(struct smbldap_state *ldap_state)
1004
0
{
1005
0
  LDAP *ldap_struct = smbldap_get_ldap(ldap_state);
1006
0
  int rc;
1007
0
  int version;
1008
1009
  /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
1010
     (OpenLDAP) doesn't seem to support it */
1011
1012
0
  DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
1013
0
      ldap_state->uri, ldap_state->bind_dn));
1014
1015
0
#ifdef HAVE_LDAP_SET_REBIND_PROC
1016
0
#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
1017
# if LDAP_SET_REBIND_PROC_ARGS == 2
1018
  ldap_set_rebind_proc(ldap_struct, &rebindproc_connect);
1019
# endif
1020
0
# if LDAP_SET_REBIND_PROC_ARGS == 3
1021
0
  ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);
1022
0
# endif
1023
#else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
1024
# if LDAP_SET_REBIND_PROC_ARGS == 2
1025
  ldap_set_rebind_proc(ldap_struct, &rebindproc);
1026
# endif
1027
# if LDAP_SET_REBIND_PROC_ARGS == 3
1028
  ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);
1029
# endif
1030
#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
1031
0
#endif
1032
1033
  /* When there is an alternative bind callback is set,
1034
     attempt to use it to perform the bind */
1035
0
  if (ldap_state->bind_callback != NULL) {
1036
    /* We have to allow bind callback to be run under become_root/unbecome_root
1037
       to make sure within smbd the callback has proper write access to its resources,
1038
       like credential cache. This is similar to passdb case where this callback is supposed
1039
       to be used. When used outside smbd, become_root()/unbecome_root() are no-op.
1040
    */
1041
0
    become_root();
1042
0
    rc = ldap_state->bind_callback(ldap_struct, ldap_state, ldap_state->bind_callback_data);
1043
0
    unbecome_root();
1044
0
  } else {
1045
0
    rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
1046
0
  }
1047
1048
0
  if (rc != LDAP_SUCCESS) {
1049
0
    char *ld_error = NULL;
1050
0
    ldap_get_option(smbldap_get_ldap(ldap_state),
1051
0
        LDAP_OPT_ERROR_STRING,
1052
0
        &ld_error);
1053
0
    DEBUG(ldap_state->num_failures ? 2 : 0,
1054
0
          ("failed to bind to server %s with dn=\"%s\" Error: %s\n\t%s\n",
1055
0
             ldap_state->uri,
1056
0
             ldap_state->bind_dn ? ldap_state->bind_dn : "[Anonymous bind]",
1057
0
             ldap_err2string(rc),
1058
0
             ld_error ? ld_error : "(unknown)"));
1059
0
    SAFE_FREE(ld_error);
1060
0
    ldap_state->num_failures++;
1061
0
    goto done;
1062
0
  }
1063
1064
0
  ldap_state->num_failures = 0;
1065
0
  ldap_state->paged_results = False;
1066
1067
0
  ldap_get_option(smbldap_get_ldap(ldap_state),
1068
0
      LDAP_OPT_PROTOCOL_VERSION, &version);
1069
1070
0
  if (smbldap_has_control(smbldap_get_ldap(ldap_state), ADS_PAGE_CTL_OID)
1071
0
      && version == 3) {
1072
0
    ldap_state->paged_results = True;
1073
0
  }
1074
1075
0
  DEBUG(3, ("ldap_connect_system: successful connection to the LDAP server\n"));
1076
0
  DEBUGADD(10, ("ldap_connect_system: LDAP server %s support paged results\n",
1077
0
    ldap_state->paged_results ? "does" : "does not"));
1078
0
done:
1079
0
  if (rc != 0) {
1080
0
    ldap_unbind(ldap_struct);
1081
0
    ldap_state->ldap_struct = NULL;
1082
0
  }
1083
0
  return rc;
1084
0
}
1085
1086
static void smbldap_idle_fn(struct tevent_context *tevent_ctx,
1087
          struct tevent_timer *te,
1088
          struct timeval now_abs,
1089
          void *private_data);
1090
1091
/**********************************************************************
1092
 Connect to LDAP server (called before every ldap operation)
1093
*********************************************************************/
1094
static int smbldap_open(struct smbldap_state *ldap_state)
1095
0
{
1096
0
  int rc, opt_rc;
1097
0
  bool reopen = False;
1098
0
  SMB_ASSERT(ldap_state);
1099
1100
0
  if ((smbldap_get_ldap(ldap_state) != NULL) &&
1101
0
      ((ldap_state->last_ping + SMBLDAP_DONT_PING_TIME) <
1102
0
       time_mono(NULL))) {
1103
1104
0
#ifdef HAVE_UNIXSOCKET
1105
0
    struct sockaddr_un addr;
1106
#else
1107
    struct sockaddr_storage addr;
1108
#endif
1109
0
    socklen_t len = sizeof(addr);
1110
0
    int sd;
1111
1112
0
    opt_rc = ldap_get_option(smbldap_get_ldap(ldap_state),
1113
0
           LDAP_OPT_DESC, &sd);
1114
0
    if (opt_rc == 0 && (getpeername(sd, (struct sockaddr *) &addr, &len)) < 0 )
1115
0
      reopen = True;
1116
1117
0
#ifdef HAVE_UNIXSOCKET
1118
0
    if (opt_rc == 0 && addr.sun_family == AF_UNIX)
1119
0
      reopen = True;
1120
0
#endif
1121
0
    if (reopen) {
1122
          /* the other end has died. reopen. */
1123
0
      ldap_unbind(smbldap_get_ldap(ldap_state));
1124
0
      ldap_state->ldap_struct = NULL;
1125
0
          ldap_state->last_ping = (time_t)0;
1126
0
    } else {
1127
0
      ldap_state->last_ping = time_mono(NULL);
1128
0
    }
1129
0
      }
1130
1131
0
  if (smbldap_get_ldap(ldap_state) != NULL) {
1132
0
    DEBUG(11,("smbldap_open: already connected to the LDAP server\n"));
1133
0
    return LDAP_SUCCESS;
1134
0
  }
1135
1136
0
  if ((rc = smbldap_open_connection(ldap_state))) {
1137
0
    return rc;
1138
0
  }
1139
1140
0
  if ((rc = smbldap_connect_system(ldap_state))) {
1141
0
    return rc;
1142
0
  }
1143
1144
1145
0
  ldap_state->last_ping = time_mono(NULL);
1146
0
  ldap_state->pid = getpid();
1147
1148
0
  TALLOC_FREE(ldap_state->idle_event);
1149
1150
0
  if (ldap_state->tevent_context != NULL) {
1151
0
    ldap_state->idle_event = tevent_add_timer(
1152
0
      ldap_state->tevent_context, ldap_state,
1153
0
      timeval_current_ofs(SMBLDAP_IDLE_TIME, 0),
1154
0
      smbldap_idle_fn, ldap_state);
1155
0
  }
1156
1157
0
  DEBUG(4,("The LDAP server is successfully connected\n"));
1158
1159
0
  return LDAP_SUCCESS;
1160
0
}
1161
1162
/**********************************************************************
1163
Disconnect from LDAP server
1164
*********************************************************************/
1165
static NTSTATUS smbldap_close(struct smbldap_state *ldap_state)
1166
0
{
1167
0
  if (!ldap_state)
1168
0
    return NT_STATUS_INVALID_PARAMETER;
1169
1170
0
  if (smbldap_get_ldap(ldap_state) != NULL) {
1171
0
    ldap_unbind(smbldap_get_ldap(ldap_state));
1172
0
    ldap_state->ldap_struct = NULL;
1173
0
  }
1174
1175
0
  smbldap_delete_state(ldap_state);
1176
1177
0
  TALLOC_FREE(ldap_state->idle_event);
1178
1179
0
  DEBUG(5,("The connection to the LDAP server was closed\n"));
1180
  /* maybe free the results here --metze */
1181
1182
0
  return NT_STATUS_OK;
1183
0
}
1184
1185
static SIG_ATOMIC_T got_alarm;
1186
1187
static void gotalarm_sig(int dummy)
1188
0
{
1189
0
  got_alarm = 1;
1190
0
}
1191
1192
static time_t calc_ldap_abs_endtime(int ldap_to)
1193
0
{
1194
0
  if (ldap_to == 0) {
1195
    /* No timeout - don't
1196
       return a value for
1197
       the alarm. */
1198
0
    return (time_t)0;
1199
0
  }
1200
1201
  /* Make the alarm time one second beyond
1202
     the timeout we're setting for the
1203
     remote search timeout, to allow that
1204
     to fire in preference. */
1205
1206
0
  return time_mono(NULL)+ldap_to+1;
1207
0
}
1208
1209
static int end_ldap_local_alarm(time_t absolute_endtime, int rc)
1210
0
{
1211
0
  if (absolute_endtime) {
1212
0
    alarm(0);
1213
0
    CatchSignal(SIGALRM, SIG_IGN);
1214
0
    if (got_alarm) {
1215
      /* Client timeout error code. */
1216
0
      got_alarm = 0;
1217
0
      return LDAP_TIMEOUT;
1218
0
    }
1219
0
  }
1220
0
  return rc;
1221
0
}
1222
1223
static void setup_ldap_local_alarm(struct smbldap_state *ldap_state, time_t absolute_endtime)
1224
0
{
1225
0
  time_t now = time_mono(NULL);
1226
1227
0
  if (absolute_endtime) {
1228
0
    got_alarm = 0;
1229
0
    CatchSignal(SIGALRM, gotalarm_sig);
1230
0
    alarm(absolute_endtime - now);
1231
0
  }
1232
1233
0
  if (ldap_state->pid != getpid()) {
1234
0
    smbldap_close(ldap_state);
1235
0
  }
1236
0
}
1237
1238
static void get_ldap_errs(struct smbldap_state *ldap_state, char **pp_ld_error, int *p_ld_errno)
1239
0
{
1240
0
  ldap_get_option(smbldap_get_ldap(ldap_state),
1241
0
      LDAP_OPT_ERROR_NUMBER, p_ld_errno);
1242
1243
0
  ldap_get_option(smbldap_get_ldap(ldap_state),
1244
0
      LDAP_OPT_ERROR_STRING, pp_ld_error);
1245
0
}
1246
1247
static int get_cached_ldap_connect(struct smbldap_state *ldap_state, time_t abs_endtime)
1248
0
{
1249
0
  int attempts = 0;
1250
1251
0
  while (1) {
1252
0
    int rc;
1253
0
    time_t now;
1254
1255
0
    now = time_mono(NULL);
1256
0
    ldap_state->last_use = now;
1257
1258
0
    if (abs_endtime && now > abs_endtime) {
1259
0
      smbldap_close(ldap_state);
1260
0
      return LDAP_TIMEOUT;
1261
0
    }
1262
1263
0
    rc = smbldap_open(ldap_state);
1264
1265
0
    if (rc == LDAP_SUCCESS) {
1266
0
      return LDAP_SUCCESS;
1267
0
    }
1268
1269
0
    attempts++;
1270
0
    DEBUG(1, ("Connection to LDAP server failed for the "
1271
0
      "%d try!\n", attempts));
1272
1273
0
    if (rc == LDAP_INSUFFICIENT_ACCESS) {
1274
      /* The fact that we are non-root or any other
1275
       * access-denied condition will not change in the next
1276
       * round of trying */
1277
0
      return rc;
1278
0
    }
1279
1280
0
    if (got_alarm) {
1281
0
      smbldap_close(ldap_state);
1282
0
      return LDAP_TIMEOUT;
1283
0
    }
1284
1285
0
    smb_msleep(1000);
1286
1287
0
    if (got_alarm) {
1288
0
      smbldap_close(ldap_state);
1289
0
      return LDAP_TIMEOUT;
1290
0
    }
1291
0
  }
1292
0
}
1293
1294
/*********************************************************************
1295
 ********************************************************************/
1296
1297
static int smbldap_search_ext(struct smbldap_state *ldap_state,
1298
            const char *base, int scope, const char *filter,
1299
            const char *attrs[], int attrsonly,
1300
            LDAPControl **sctrls, LDAPControl **cctrls,
1301
            int sizelimit, LDAPMessage **res)
1302
0
{
1303
0
  int     rc = LDAP_SERVER_DOWN;
1304
0
  char           *utf8_filter;
1305
0
  int   to = lp_ldap_timeout();
1306
0
  time_t    abs_endtime = calc_ldap_abs_endtime(to);
1307
0
  struct    timeval timeout;
1308
0
  struct    timeval *timeout_ptr = NULL;
1309
0
  size_t    converted_size;
1310
1311
0
  SMB_ASSERT(ldap_state);
1312
1313
0
  DEBUG(5,("smbldap_search_ext: base => [%s], filter => [%s], "
1314
0
     "scope => [%d]\n", base, filter, scope));
1315
1316
0
  if (ldap_state->last_rebind.tv_sec > 0) {
1317
0
    struct timeval  tval;
1318
0
    struct timespec ts;
1319
0
    int64_t tdiff = 0;
1320
0
    int   sleep_time = 0;
1321
1322
0
    clock_gettime_mono(&ts);
1323
0
    tval = convert_timespec_to_timeval(ts);
1324
1325
0
    tdiff = usec_time_diff(&tval, &ldap_state->last_rebind);
1326
0
    tdiff /= 1000; /* Convert to milliseconds. */
1327
1328
0
    sleep_time = lp_ldap_replication_sleep()-(int)tdiff;
1329
0
    sleep_time = MIN(sleep_time, MAX_LDAP_REPLICATION_SLEEP_TIME);
1330
1331
0
    if (sleep_time > 0) {
1332
      /* we wait for the LDAP replication */
1333
0
      DEBUG(5,("smbldap_search_ext: waiting %d milliseconds "
1334
0
         "for LDAP replication.\n",sleep_time));
1335
0
      smb_msleep(sleep_time);
1336
0
      DEBUG(5,("smbldap_search_ext: go on!\n"));
1337
0
    }
1338
0
    ZERO_STRUCT(ldap_state->last_rebind);
1339
0
  }
1340
1341
0
  if (!push_utf8_talloc(talloc_tos(), &utf8_filter, filter, &converted_size)) {
1342
0
    return LDAP_NO_MEMORY;
1343
0
  }
1344
1345
  /* Setup remote timeout for the ldap_search_ext_s call. */
1346
0
  if (to) {
1347
0
    timeout.tv_sec = to;
1348
0
    timeout.tv_usec = 0;
1349
0
    timeout_ptr = &timeout;
1350
0
  }
1351
1352
0
  setup_ldap_local_alarm(ldap_state, abs_endtime);
1353
1354
0
  while (1) {
1355
0
    char *ld_error = NULL;
1356
0
    int ld_errno;
1357
1358
0
    rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1359
0
    if (rc != LDAP_SUCCESS) {
1360
0
      break;
1361
0
    }
1362
1363
0
    rc = ldap_search_ext_s(smbldap_get_ldap(ldap_state),
1364
0
               base, scope,
1365
0
               utf8_filter,
1366
0
               discard_const_p(char *, attrs),
1367
0
               attrsonly, sctrls, cctrls, timeout_ptr,
1368
0
               sizelimit, res);
1369
0
    if (rc == LDAP_SUCCESS) {
1370
0
      break;
1371
0
    }
1372
1373
0
    get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1374
1375
0
    DEBUG(10, ("Failed search for base: %s, error: %d (%s) "
1376
0
         "(%s)\n", base, ld_errno,
1377
0
         ldap_err2string(rc),
1378
0
         ld_error ? ld_error : "unknown"));
1379
0
    SAFE_FREE(ld_error);
1380
1381
0
    if (ld_errno != LDAP_SERVER_DOWN) {
1382
0
      break;
1383
0
    }
1384
0
    ldap_unbind(smbldap_get_ldap(ldap_state));
1385
0
    ldap_state->ldap_struct = NULL;
1386
0
  }
1387
1388
0
  TALLOC_FREE(utf8_filter);
1389
0
  return end_ldap_local_alarm(abs_endtime, rc);
1390
0
}
1391
1392
int smbldap_search(struct smbldap_state *ldap_state,
1393
       const char *base, int scope, const char *filter,
1394
       const char *attrs[], int attrsonly,
1395
       LDAPMessage **res)
1396
0
{
1397
0
  return smbldap_search_ext(ldap_state, base, scope, filter, attrs,
1398
0
          attrsonly, NULL, NULL, LDAP_NO_LIMIT, res);
1399
0
}
1400
1401
int smbldap_search_paged(struct smbldap_state *ldap_state,
1402
       const char *base, int scope, const char *filter,
1403
       const char **attrs, int attrsonly, int pagesize,
1404
       LDAPMessage **res, void **cookie)
1405
0
{
1406
0
  LDAPControl     pr;
1407
0
  LDAPControl   **rcontrols;
1408
0
  LDAPControl   *controls[2] = { NULL, NULL};
1409
0
  BerElement  *cookie_be = NULL;
1410
0
  struct berval   *cookie_bv = NULL;
1411
0
  int   tmp = 0, i, rc;
1412
0
  bool    critical = True;
1413
1414
0
  *res = NULL;
1415
1416
0
  DEBUG(3,("smbldap_search_paged: base => [%s], filter => [%s],"
1417
0
     "scope => [%d], pagesize => [%d]\n",
1418
0
     base, filter, scope, pagesize));
1419
1420
0
  cookie_be = ber_alloc_t(LBER_USE_DER);
1421
0
  if (cookie_be == NULL) {
1422
0
    DEBUG(0,("smbldap_create_page_control: ber_alloc_t returns "
1423
0
       "NULL\n"));
1424
0
    return LDAP_NO_MEMORY;
1425
0
  }
1426
1427
  /* construct cookie */
1428
0
  if (*cookie != NULL) {
1429
0
    ber_printf(cookie_be, "{iO}", (ber_int_t) pagesize, *cookie);
1430
0
    ber_bvfree((struct berval *)*cookie); /* don't need it from last time */
1431
0
    *cookie = NULL;
1432
0
  } else {
1433
0
    ber_printf(cookie_be, "{io}", (ber_int_t) pagesize, "", 0);
1434
0
  }
1435
0
  ber_flatten(cookie_be, &cookie_bv);
1436
1437
0
  pr.ldctl_oid = discard_const_p(char, ADS_PAGE_CTL_OID);
1438
0
  pr.ldctl_iscritical = (char) critical;
1439
0
  pr.ldctl_value.bv_len = cookie_bv->bv_len;
1440
0
  pr.ldctl_value.bv_val = cookie_bv->bv_val;
1441
1442
0
  controls[0] = &pr;
1443
0
  controls[1] = NULL;
1444
1445
0
  rc = smbldap_search_ext(ldap_state, base, scope, filter, attrs,
1446
0
         0, controls, NULL, LDAP_NO_LIMIT, res);
1447
1448
0
  ber_free(cookie_be, 1);
1449
0
  ber_bvfree(cookie_bv);
1450
1451
0
  if (rc != 0) {
1452
0
    DEBUG(3,("smbldap_search_paged: smbldap_search_ext(%s) "
1453
0
       "failed with [%s]\n", filter, ldap_err2string(rc)));
1454
0
    goto done;
1455
0
  }
1456
1457
0
  DEBUG(3,("smbldap_search_paged: search was successful\n"));
1458
1459
0
  rc = ldap_parse_result(smbldap_get_ldap(ldap_state), *res, NULL, NULL,
1460
0
             NULL, NULL, &rcontrols,  0);
1461
0
  if (rc != 0) {
1462
0
    DEBUG(3,("smbldap_search_paged: ldap_parse_result failed " \
1463
0
       "with [%s]\n", ldap_err2string(rc)));
1464
0
    goto done;
1465
0
  }
1466
1467
0
  if (rcontrols == NULL)
1468
0
    goto done;
1469
1470
0
  for (i=0; rcontrols[i]; i++) {
1471
1472
0
    if (strcmp(ADS_PAGE_CTL_OID, rcontrols[i]->ldctl_oid) != 0)
1473
0
      continue;
1474
1475
0
    cookie_be = ber_init(&rcontrols[i]->ldctl_value);
1476
0
    ber_scanf(cookie_be,"{iO}", &tmp, &cookie_bv);
1477
    /* the berval is the cookie, but must be freed when it is all
1478
       done */
1479
0
    if (cookie_bv->bv_len)
1480
0
      *cookie=ber_bvdup(cookie_bv);
1481
0
    else
1482
0
      *cookie=NULL;
1483
0
    ber_bvfree(cookie_bv);
1484
0
    ber_free(cookie_be, 1);
1485
0
    break;
1486
0
  }
1487
0
  ldap_controls_free(rcontrols);
1488
0
done:
1489
0
  return rc;
1490
0
}
1491
1492
int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
1493
0
{
1494
0
  int     rc = LDAP_SERVER_DOWN;
1495
0
  char           *utf8_dn;
1496
0
  time_t    abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1497
0
  size_t    converted_size;
1498
1499
0
  SMB_ASSERT(ldap_state);
1500
1501
0
  DEBUG(5,("smbldap_modify: dn => [%s]\n", dn ));
1502
1503
0
  if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1504
0
    return LDAP_NO_MEMORY;
1505
0
  }
1506
1507
0
  setup_ldap_local_alarm(ldap_state, abs_endtime);
1508
1509
0
  while (1) {
1510
0
    char *ld_error = NULL;
1511
0
    int ld_errno;
1512
1513
0
    rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1514
0
    if (rc != LDAP_SUCCESS) {
1515
0
      break;
1516
0
    }
1517
1518
0
    rc = ldap_modify_s(smbldap_get_ldap(ldap_state), utf8_dn,
1519
0
           attrs);
1520
0
    if (rc == LDAP_SUCCESS) {
1521
0
      break;
1522
0
    }
1523
1524
0
    get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1525
1526
0
    DEBUG(10, ("Failed to modify dn: %s, error: %d (%s) "
1527
0
         "(%s)\n", dn, ld_errno,
1528
0
         ldap_err2string(rc),
1529
0
         ld_error ? ld_error : "unknown"));
1530
0
    SAFE_FREE(ld_error);
1531
1532
0
    if (ld_errno != LDAP_SERVER_DOWN) {
1533
0
      break;
1534
0
    }
1535
0
    ldap_unbind(smbldap_get_ldap(ldap_state));
1536
0
    ldap_state->ldap_struct = NULL;
1537
0
  }
1538
1539
0
  TALLOC_FREE(utf8_dn);
1540
0
  return end_ldap_local_alarm(abs_endtime, rc);
1541
0
}
1542
1543
int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
1544
0
{
1545
0
  int     rc = LDAP_SERVER_DOWN;
1546
0
  char           *utf8_dn;
1547
0
  time_t    abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1548
0
  size_t    converted_size;
1549
1550
0
  SMB_ASSERT(ldap_state);
1551
1552
0
  DEBUG(5,("smbldap_add: dn => [%s]\n", dn ));
1553
1554
0
  if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1555
0
    return LDAP_NO_MEMORY;
1556
0
  }
1557
1558
0
  setup_ldap_local_alarm(ldap_state, abs_endtime);
1559
1560
0
  while (1) {
1561
0
    char *ld_error = NULL;
1562
0
    int ld_errno;
1563
1564
0
    rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1565
0
    if (rc != LDAP_SUCCESS) {
1566
0
      break;
1567
0
    }
1568
1569
0
    rc = ldap_add_s(smbldap_get_ldap(ldap_state), utf8_dn, attrs);
1570
0
    if (rc == LDAP_SUCCESS) {
1571
0
      break;
1572
0
    }
1573
1574
0
    get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1575
1576
0
    DEBUG(10, ("Failed to add dn: %s, error: %d (%s) "
1577
0
         "(%s)\n", dn, ld_errno,
1578
0
         ldap_err2string(rc),
1579
0
         ld_error ? ld_error : "unknown"));
1580
0
    SAFE_FREE(ld_error);
1581
1582
0
    if (ld_errno != LDAP_SERVER_DOWN) {
1583
0
      break;
1584
0
    }
1585
0
    ldap_unbind(smbldap_get_ldap(ldap_state));
1586
0
    ldap_state->ldap_struct = NULL;
1587
0
  }
1588
1589
0
  TALLOC_FREE(utf8_dn);
1590
0
  return end_ldap_local_alarm(abs_endtime, rc);
1591
0
}
1592
1593
int smbldap_delete(struct smbldap_state *ldap_state, const char *dn)
1594
0
{
1595
0
  int     rc = LDAP_SERVER_DOWN;
1596
0
  char           *utf8_dn;
1597
0
  time_t    abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1598
0
  size_t    converted_size;
1599
1600
0
  SMB_ASSERT(ldap_state);
1601
1602
0
  DEBUG(5,("smbldap_delete: dn => [%s]\n", dn ));
1603
1604
0
  if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1605
0
    return LDAP_NO_MEMORY;
1606
0
  }
1607
1608
0
  setup_ldap_local_alarm(ldap_state, abs_endtime);
1609
1610
0
  while (1) {
1611
0
    char *ld_error = NULL;
1612
0
    int ld_errno;
1613
1614
0
    rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1615
0
    if (rc != LDAP_SUCCESS) {
1616
0
      break;
1617
0
    }
1618
1619
0
    rc = ldap_delete_s(smbldap_get_ldap(ldap_state), utf8_dn);
1620
0
    if (rc == LDAP_SUCCESS) {
1621
0
      break;
1622
0
    }
1623
1624
0
    get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1625
1626
0
    DEBUG(10, ("Failed to delete dn: %s, error: %d (%s) "
1627
0
         "(%s)\n", dn, ld_errno,
1628
0
         ldap_err2string(rc),
1629
0
         ld_error ? ld_error : "unknown"));
1630
0
    SAFE_FREE(ld_error);
1631
1632
0
    if (ld_errno != LDAP_SERVER_DOWN) {
1633
0
      break;
1634
0
    }
1635
0
    ldap_unbind(smbldap_get_ldap(ldap_state));
1636
0
    ldap_state->ldap_struct = NULL;
1637
0
  }
1638
1639
0
  TALLOC_FREE(utf8_dn);
1640
0
  return end_ldap_local_alarm(abs_endtime, rc);
1641
0
}
1642
1643
int smbldap_extended_operation(struct smbldap_state *ldap_state,
1644
             LDAP_CONST char *reqoid, struct berval *reqdata,
1645
             LDAPControl **serverctrls, LDAPControl **clientctrls,
1646
             char **retoidp, struct berval **retdatap)
1647
0
{
1648
0
  int     rc = LDAP_SERVER_DOWN;
1649
0
  time_t    abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1650
1651
0
  if (!ldap_state)
1652
0
    return (-1);
1653
1654
0
  setup_ldap_local_alarm(ldap_state, abs_endtime);
1655
1656
0
  while (1) {
1657
0
    char *ld_error = NULL;
1658
0
    int ld_errno;
1659
1660
0
    rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1661
0
    if (rc != LDAP_SUCCESS) {
1662
0
      break;
1663
0
    }
1664
1665
0
    rc = ldap_extended_operation_s(smbldap_get_ldap(ldap_state),
1666
0
                 reqoid,
1667
0
                 reqdata, serverctrls,
1668
0
                 clientctrls, retoidp, retdatap);
1669
0
    if (rc == LDAP_SUCCESS) {
1670
0
      break;
1671
0
    }
1672
1673
0
    get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1674
1675
0
    DEBUG(10, ("Extended operation failed with error: "
1676
0
         "%d (%s) (%s)\n", ld_errno,
1677
0
         ldap_err2string(rc),
1678
0
         ld_error ? ld_error : "unknown"));
1679
0
    SAFE_FREE(ld_error);
1680
1681
0
    if (ld_errno != LDAP_SERVER_DOWN) {
1682
0
      break;
1683
0
    }
1684
0
    ldap_unbind(smbldap_get_ldap(ldap_state));
1685
0
    ldap_state->ldap_struct = NULL;
1686
0
  }
1687
1688
0
  return end_ldap_local_alarm(abs_endtime, rc);
1689
0
}
1690
1691
/*******************************************************************
1692
 run the search by name.
1693
******************************************************************/
1694
int smbldap_search_suffix (struct smbldap_state *ldap_state,
1695
         const char *filter, const char **search_attr,
1696
         LDAPMessage ** result)
1697
0
{
1698
0
  return smbldap_search(ldap_state, lp_ldap_suffix(),
1699
0
            LDAP_SCOPE_SUBTREE,
1700
0
            filter, search_attr, 0, result);
1701
0
}
1702
1703
static void smbldap_idle_fn(struct tevent_context *tevent_ctx,
1704
          struct tevent_timer *te,
1705
          struct timeval now_abs,
1706
          void *private_data)
1707
0
{
1708
0
  struct smbldap_state *state = (struct smbldap_state *)private_data;
1709
1710
0
  TALLOC_FREE(state->idle_event);
1711
1712
0
  if (smbldap_get_ldap(state) == NULL) {
1713
0
    DEBUG(10,("ldap connection not connected...\n"));
1714
0
    return;
1715
0
  }
1716
1717
0
  if ((state->last_use+SMBLDAP_IDLE_TIME) > time_mono(NULL)) {
1718
0
    DEBUG(10,("ldap connection not idle...\n"));
1719
1720
    /* this needs to be made monotonic clock aware inside tevent: */
1721
0
    state->idle_event = tevent_add_timer(
1722
0
      tevent_ctx, state,
1723
0
      timeval_add(&now_abs, SMBLDAP_IDLE_TIME, 0),
1724
0
      smbldap_idle_fn,
1725
0
      private_data);
1726
0
    return;
1727
0
  }
1728
1729
0
  DEBUG(7,("ldap connection idle...closing connection\n"));
1730
0
  smbldap_close(state);
1731
0
}
1732
1733
/**********************************************************************
1734
 Housekeeping
1735
 *********************************************************************/
1736
1737
void smbldap_free_struct(struct smbldap_state **ldap_state)
1738
0
{
1739
0
  smbldap_close(*ldap_state);
1740
1741
0
  if ((*ldap_state)->bind_secret) {
1742
0
    memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
1743
0
  }
1744
1745
0
  SAFE_FREE((*ldap_state)->bind_dn);
1746
0
  BURN_FREE_STR((*ldap_state)->bind_secret);
1747
0
  smbldap_set_bind_callback(*ldap_state, NULL, NULL);
1748
1749
0
  TALLOC_FREE(*ldap_state);
1750
1751
  /* No need to free any further, as it is talloc()ed */
1752
0
}
1753
1754
static int smbldap_state_destructor(struct smbldap_state *state)
1755
0
{
1756
0
  smbldap_free_struct(&state);
1757
0
  return 0;
1758
0
}
1759
1760
1761
/**********************************************************************
1762
 Initialise the 'general' ldap structures, on which ldap operations may be conducted
1763
 *********************************************************************/
1764
1765
NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, struct tevent_context *tevent_ctx,
1766
          const char *location,
1767
          bool anon,
1768
          const char *bind_dn,
1769
          const char *bind_secret,
1770
          struct smbldap_state **smbldap_state)
1771
0
{
1772
0
  *smbldap_state = talloc_zero(mem_ctx, struct smbldap_state);
1773
0
  if (!*smbldap_state) {
1774
0
    DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
1775
0
    return NT_STATUS_NO_MEMORY;
1776
0
  }
1777
1778
0
  if (location) {
1779
0
    (*smbldap_state)->uri = talloc_strdup(mem_ctx, location);
1780
0
  } else {
1781
0
    (*smbldap_state)->uri = "ldap://localhost";
1782
0
  }
1783
1784
0
  (*smbldap_state)->tevent_context = tevent_ctx;
1785
1786
0
  if (bind_dn && bind_secret) {
1787
0
    smbldap_set_creds(*smbldap_state, anon, bind_dn, bind_secret);
1788
0
  }
1789
1790
0
  talloc_set_destructor(*smbldap_state, smbldap_state_destructor);
1791
0
  return NT_STATUS_OK;
1792
0
}
1793
1794
 char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld,
1795
       LDAPMessage *entry)
1796
0
{
1797
0
  char *utf8_dn, *unix_dn;
1798
0
  size_t converted_size;
1799
1800
0
  utf8_dn = ldap_get_dn(ld, entry);
1801
0
  if (!utf8_dn) {
1802
0
    DEBUG (5, ("smbldap_talloc_dn: ldap_get_dn failed\n"));
1803
0
    return NULL;
1804
0
  }
1805
0
  if (!pull_utf8_talloc(mem_ctx, &unix_dn, utf8_dn, &converted_size)) {
1806
0
    DEBUG (0, ("smbldap_talloc_dn: String conversion failure utf8 "
1807
0
         "[%s]\n", utf8_dn));
1808
0
    return NULL;
1809
0
  }
1810
0
  ldap_memfree(utf8_dn);
1811
0
  return unix_dn;
1812
0
}
1813
1814
/*******************************************************************
1815
 Check if root-dse has a certain Control or Extension
1816
********************************************************************/
1817
1818
static bool smbldap_check_root_dse(LDAP *ld, const char **attrs, const char *value)
1819
0
{
1820
0
  LDAPMessage *msg = NULL;
1821
0
  LDAPMessage *entry = NULL;
1822
0
  char **values = NULL;
1823
0
  int rc, num_result, num_values, i;
1824
0
  bool result = False;
1825
1826
0
  if (!attrs[0]) {
1827
0
    DEBUG(3,("smbldap_check_root_dse: nothing to look for\n"));
1828
0
    return False;
1829
0
  }
1830
1831
0
  if (!strequal(attrs[0], "supportedExtension") &&
1832
0
      !strequal(attrs[0], "supportedControl") &&
1833
0
      !strequal(attrs[0], "namingContexts")) {
1834
0
    DEBUG(3,("smbldap_check_root_dse: no idea what to query root-dse for: %s ?\n", attrs[0]));
1835
0
    return False;
1836
0
  }
1837
1838
0
  rc = ldap_search_s(ld, "", LDAP_SCOPE_BASE,
1839
0
         "(objectclass=*)", discard_const_p(char *, attrs), 0 , &msg);
1840
1841
0
  if (rc != LDAP_SUCCESS) {
1842
0
    DEBUG(3,("smbldap_check_root_dse: Could not search rootDSE\n"));
1843
0
    return False;
1844
0
  }
1845
1846
0
  num_result = ldap_count_entries(ld, msg);
1847
1848
0
  if (num_result != 1) {
1849
0
    DEBUG(3,("smbldap_check_root_dse: Expected one rootDSE, got %d\n", num_result));
1850
0
    goto done;
1851
0
  }
1852
1853
0
  entry = ldap_first_entry(ld, msg);
1854
1855
0
  if (entry == NULL) {
1856
0
    DEBUG(3,("smbldap_check_root_dse: Could not retrieve rootDSE\n"));
1857
0
    goto done;
1858
0
  }
1859
1860
0
  values = ldap_get_values(ld, entry, attrs[0]);
1861
1862
0
  if (values == NULL) {
1863
0
    DEBUG(5,("smbldap_check_root_dse: LDAP Server does not support any %s\n", attrs[0]));
1864
0
    goto done;
1865
0
  }
1866
1867
0
  num_values = ldap_count_values(values);
1868
1869
0
  if (num_values == 0) {
1870
0
    DEBUG(5,("smbldap_check_root_dse: LDAP Server does not have any %s\n", attrs[0]));
1871
0
    goto done;
1872
0
  }
1873
1874
0
  for (i=0; i<num_values; i++) {
1875
0
    if (strcmp(values[i], value) == 0)
1876
0
      result = True;
1877
0
  }
1878
1879
1880
0
 done:
1881
0
  if (values != NULL)
1882
0
    ldap_value_free(values);
1883
0
  if (msg != NULL)
1884
0
    ldap_msgfree(msg);
1885
1886
0
  return result;
1887
1888
0
}
1889
1890
/*******************************************************************
1891
 Check if LDAP-Server supports a certain Control (OID in string format)
1892
********************************************************************/
1893
1894
bool smbldap_has_control(LDAP *ld, const char *control)
1895
0
{
1896
0
  const char *attrs[] = { "supportedControl", NULL };
1897
0
  return smbldap_check_root_dse(ld, attrs, control);
1898
0
}
1899
1900
/*******************************************************************
1901
 Check if LDAP-Server supports a certain Extension (OID in string format)
1902
********************************************************************/
1903
1904
bool smbldap_has_extension(LDAP *ld, const char *extension)
1905
0
{
1906
0
  const char *attrs[] = { "supportedExtension", NULL };
1907
0
  return smbldap_check_root_dse(ld, attrs, extension);
1908
0
}
1909
1910
/*******************************************************************
1911
 Check if LDAP-Server holds a given namingContext
1912
********************************************************************/
1913
1914
bool smbldap_has_naming_context(LDAP *ld, const char *naming_context)
1915
0
{
1916
0
  const char *attrs[] = { "namingContexts", NULL };
1917
0
  return smbldap_check_root_dse(ld, attrs, naming_context);
1918
0
}
1919
1920
bool smbldap_set_creds(struct smbldap_state *ldap_state, bool anon, const char *dn, const char *secret)
1921
0
{
1922
0
  ldap_state->anonymous = anon;
1923
1924
  /* free any previously set credential */
1925
1926
0
  SAFE_FREE(ldap_state->bind_dn);
1927
0
  smbldap_set_bind_callback(ldap_state, NULL, NULL);
1928
1929
0
  if (ldap_state->bind_secret) {
1930
    /* make sure secrets are zeroed out of memory */
1931
0
    memset(ldap_state->bind_secret, '\0', strlen(ldap_state->bind_secret));
1932
0
    SAFE_FREE(ldap_state->bind_secret);
1933
0
  }
1934
1935
0
  if ( ! anon) {
1936
0
    ldap_state->bind_dn = SMB_STRDUP(dn);
1937
0
    ldap_state->bind_secret = SMB_STRDUP(secret);
1938
0
  }
1939
1940
  return True;
1941
0
}