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