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