rpc_server3: Use fdopen_keepfd()
[Samba.git] / source3 / lib / smbldap.c
blobc0d6884a7835cae1b3cfd7791822339ad8c74bb8
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
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.
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.
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/>.
25 #include "includes.h"
26 #include "smbldap.h"
27 #include "../libcli/security/security.h"
28 #include <tevent.h>
29 #include "lib/param/loadparm.h"
31 /* Try not to hit the up or down server forever */
33 #define SMBLDAP_DONT_PING_TIME 10 /* ping only all 10 seconds */
34 #define SMBLDAP_NUM_RETRIES 8 /* retry only 8 times */
36 #define SMBLDAP_IDLE_TIME 150 /* After 2.5 minutes disconnect */
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;
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;
52 bool paged_results;
54 unsigned int num_failures;
56 time_t last_use; /* monotonic */
57 struct tevent_context *tevent_context;
58 struct tevent_timer *idle_event;
60 struct timeval last_rebind; /* monotonic */
63 LDAP *smbldap_get_ldap(struct smbldap_state *state)
65 return state->ldap_struct;
68 bool smbldap_get_paged_results(struct smbldap_state *state)
70 return state->paged_results;
73 void smbldap_set_paged_results(struct smbldap_state *state,
74 bool paged_results)
76 state->paged_results = paged_results;
79 void smbldap_set_bind_callback(struct smbldap_state *state,
80 smbldap_bind_callback_fn callback,
81 void *callback_data)
83 state->bind_callback = callback;
84 state->bind_callback_data = callback_data;
86 /*******************************************************************
87 Search an attribute and return the first value found.
88 ******************************************************************/
90 bool smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
91 const char *attribute, char *value,
92 int max_len)
94 char **values;
95 size_t size = 0;
97 if ( !attribute )
98 return False;
100 value[0] = '\0';
102 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
103 DEBUG (10, ("smbldap_get_single_attribute: [%s] = [<does not exist>]\n", attribute));
105 return False;
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;
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;
122 char * smbldap_talloc_single_attribute(LDAP *ldap_struct, LDAPMessage *entry,
123 const char *attribute,
124 TALLOC_CTX *mem_ctx)
126 char **values;
127 char *result;
128 size_t converted_size;
130 if (attribute == NULL) {
131 return NULL;
134 values = ldap_get_values(ldap_struct, entry, attribute);
136 if (values == NULL) {
137 DEBUG(10, ("attribute %s does not exist\n", attribute));
138 return NULL;
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;
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;
154 ldap_value_free(values);
156 #ifdef DEBUG_PASSWORDS
157 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
158 attribute, result));
159 #endif
160 return result;
163 char * smbldap_talloc_first_attribute(LDAP *ldap_struct, LDAPMessage *entry,
164 const char *attribute,
165 TALLOC_CTX *mem_ctx)
167 char **values;
168 char *result;
169 size_t converted_size;
171 if (attribute == NULL) {
172 return NULL;
175 values = ldap_get_values(ldap_struct, entry, attribute);
177 if (values == NULL) {
178 DEBUG(10, ("attribute %s does not exist\n", attribute));
179 return NULL;
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;
188 ldap_value_free(values);
190 #ifdef DEBUG_PASSWORDS
191 DEBUG (100, ("smbldap_get_first_attribute: [%s] = [%s]\n",
192 attribute, result));
193 #endif
194 return result;
197 char * smbldap_talloc_smallest_attribute(LDAP *ldap_struct, LDAPMessage *entry,
198 const char *attribute,
199 TALLOC_CTX *mem_ctx)
201 char **values;
202 char *result;
203 size_t converted_size;
204 int i, num_values;
206 if (attribute == NULL) {
207 return NULL;
210 values = ldap_get_values(ldap_struct, entry, attribute);
212 if (values == NULL) {
213 DEBUG(10, ("attribute %s does not exist\n", attribute));
214 return NULL;
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;
223 num_values = ldap_count_values(values);
225 for (i=1; i<num_values; i++) {
226 char *tmp;
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;
236 if (strcasecmp_m(tmp, result) < 0) {
237 TALLOC_FREE(result);
238 result = tmp;
239 } else {
240 TALLOC_FREE(tmp);
244 ldap_value_free(values);
246 #ifdef DEBUG_PASSWORDS
247 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
248 attribute, result));
249 #endif
250 return result;
253 bool smbldap_talloc_single_blob(TALLOC_CTX *mem_ctx, LDAP *ld,
254 LDAPMessage *msg, const char *attrib,
255 DATA_BLOB *blob)
257 struct berval **values;
259 values = ldap_get_values_len(ld, msg, attrib);
260 if (!values) {
261 return false;
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;
270 *blob = data_blob_talloc(mem_ctx, values[0]->bv_val,
271 values[0]->bv_len);
272 ldap_value_free_len(values);
274 return (blob->data != NULL);
277 bool smbldap_pull_sid(LDAP *ld, LDAPMessage *msg, const char *attrib,
278 struct dom_sid *sid)
280 DATA_BLOB blob;
281 ssize_t ret;
283 if (!smbldap_talloc_single_blob(talloc_tos(), ld, msg, attrib,
284 &blob)) {
285 return false;
287 ret = sid_parse(blob.data, blob.length, sid);
288 TALLOC_FREE(blob.data);
289 return (ret != -1);
292 static int ldapmsg_destructor(LDAPMessage **result) {
293 ldap_msgfree(*result);
294 return 0;
297 void smbldap_talloc_autofree_ldapmsg(TALLOC_CTX *mem_ctx, LDAPMessage *result)
299 LDAPMessage **handle;
301 if (result == NULL) {
302 return;
305 handle = talloc(mem_ctx, LDAPMessage *);
306 SMB_ASSERT(handle != NULL);
308 *handle = result;
309 talloc_set_destructor(handle, ldapmsg_destructor);
312 static int ldapmod_destructor(LDAPMod ***mod) {
313 ldap_mods_free(*mod, True);
314 return 0;
317 void smbldap_talloc_autofree_ldapmod(TALLOC_CTX *mem_ctx, LDAPMod **mod)
319 LDAPMod ***handle;
321 if (mod == NULL) {
322 return;
325 handle = talloc(mem_ctx, LDAPMod **);
326 SMB_ASSERT(handle != NULL);
328 *handle = mod;
329 talloc_set_destructor(handle, ldapmod_destructor);
332 /************************************************************************
333 Routine to manage the LDAPMod structure array
334 manage memory used by the array, by each struct, and values
335 ***********************************************************************/
337 static void smbldap_set_mod_internal(LDAPMod *** modlist, int modop, const char *attribute, const char *value, const DATA_BLOB *blob)
339 LDAPMod **mods;
340 int i;
341 int j;
343 mods = *modlist;
345 /* sanity checks on the mod values */
347 if (attribute == NULL || *attribute == '\0') {
348 return;
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
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. */
363 mods[0] = NULL;
366 for (i = 0; mods[i] != NULL; ++i) {
367 if (mods[i]->mod_op == modop && strequal(mods[i]->mod_type, attribute))
368 break;
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. */
377 mods[i] = SMB_MALLOC_P(LDAPMod);
378 if (mods[i] == NULL) {
379 smb_panic("smbldap_set_mod: out of memory!");
380 /* notreached. */
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;
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++);
393 mods[i]->mod_bvalues = SMB_REALLOC_ARRAY(mods[i]->mod_bvalues, struct berval *, j + 2);
395 if (mods[i]->mod_bvalues == NULL) {
396 smb_panic("smbldap_set_mod: out of memory!");
397 /* notreached. */
400 mods[i]->mod_bvalues[j] = SMB_MALLOC_P(struct berval);
401 SMB_ASSERT(mods[i]->mod_bvalues[j] != NULL);
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;
407 mods[i]->mod_bvalues[j + 1] = NULL;
408 } else if (value != NULL) {
409 char *utf8_value = NULL;
410 size_t converted_size;
412 j = 0;
413 if (mods[i]->mod_values != NULL) {
414 for (; mods[i]->mod_values[j] != NULL; j++);
416 mods[i]->mod_values = SMB_REALLOC_ARRAY(mods[i]->mod_values, char *, j + 2);
418 if (mods[i]->mod_values == NULL) {
419 smb_panic("smbldap_set_mod: out of memory!");
420 /* notreached. */
423 if (!push_utf8_talloc(talloc_tos(), &utf8_value, value, &converted_size)) {
424 smb_panic("smbldap_set_mod: String conversion failure!");
425 /* notreached. */
428 mods[i]->mod_values[j] = SMB_STRDUP(utf8_value);
429 TALLOC_FREE(utf8_value);
430 SMB_ASSERT(mods[i]->mod_values[j] != NULL);
432 mods[i]->mod_values[j + 1] = NULL;
434 *modlist = mods;
437 void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
439 smbldap_set_mod_internal(modlist, modop, attribute, value, NULL);
442 void smbldap_set_mod_blob(LDAPMod *** modlist, int modop, const char *attribute, const DATA_BLOB *value)
444 smbldap_set_mod_internal(modlist, modop | LDAP_MOD_BVALUES, attribute, NULL, value);
447 /**********************************************************************
448 Set attribute to newval in LDAP, regardless of what value the
449 attribute had in LDAP before.
450 *********************************************************************/
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)
458 char oldval[2048]; /* current largest allowed value is mungeddial */
459 bool existed;
460 DATA_BLOB oldblob = data_blob_null;
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));
468 } else {
469 existed = False;
470 *oldval = '\0';
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));
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;
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 */
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);
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. */
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);
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);
527 void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing,
528 LDAPMod ***mods,
529 const char *attribute, const char *newval)
531 smbldap_make_mod_internal(ldap_struct, existing, mods, attribute,
532 0, newval, NULL);
535 void smbldap_make_mod_blob(LDAP *ldap_struct, LDAPMessage *existing,
536 LDAPMod ***mods,
537 const char *attribute, const DATA_BLOB *newblob)
539 smbldap_make_mod_internal(ldap_struct, existing, mods, attribute,
540 LDAP_MOD_BVALUES, NULL, newblob);
543 /**********************************************************************
544 Some variants of the LDAP rebind code do not pass in the third 'arg'
545 pointer to a void*, so we try and work around it by assuming that the
546 value of the 'LDAP *' pointer is the same as the one we had passed in
547 **********************************************************************/
549 struct smbldap_state_lookup {
550 LDAP *ld;
551 struct smbldap_state *smbldap_state;
552 struct smbldap_state_lookup *prev, *next;
555 static struct smbldap_state_lookup *smbldap_state_lookup_list;
557 static struct smbldap_state *smbldap_find_state(LDAP *ld)
559 struct smbldap_state_lookup *t;
561 for (t = smbldap_state_lookup_list; t; t = t->next) {
562 if (t->ld == ld) {
563 return t->smbldap_state;
566 return NULL;
569 static void smbldap_delete_state(struct smbldap_state *smbldap_state)
571 struct smbldap_state_lookup *t;
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;
582 static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state)
584 struct smbldap_state *tmp_ldap_state;
585 struct smbldap_state_lookup *t;
587 if ((tmp_ldap_state = smbldap_find_state(ld))) {
588 SMB_ASSERT(tmp_ldap_state == smbldap_state);
589 return;
592 t = SMB_XMALLOC_P(struct smbldap_state_lookup);
593 ZERO_STRUCTP(t);
595 DLIST_ADD_END(smbldap_state_lookup_list, t);
596 t->ld = ld;
597 t->smbldap_state = smbldap_state;
600 /********************************************************************
601 start TLS on an existing LDAP connection per config
602 *******************************************************************/
604 int smbldap_start_tls(LDAP *ldap_struct, int version)
606 if (lp_ldap_ssl() != LDAP_SSL_START_TLS) {
607 return LDAP_SUCCESS;
610 return smbldap_start_tls_start(ldap_struct, version);
613 /********************************************************************
614 start TLS on an existing LDAP connection unconditionally
615 *******************************************************************/
617 int smbldap_start_tls_start(LDAP *ldap_struct, int version)
619 #ifdef LDAP_OPT_X_TLS
620 int rc,tls;
622 /* check if we use ldaps already */
623 ldap_get_option(ldap_struct, LDAP_OPT_X_TLS, &tls);
624 if (tls == LDAP_OPT_X_TLS_HARD) {
625 return LDAP_SUCCESS;
628 if (version != LDAP_VERSION3) {
629 DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
630 return LDAP_OPERATIONS_ERROR;
633 if ((rc = ldap_start_tls_s (ldap_struct, NULL, NULL)) != LDAP_SUCCESS) {
634 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
635 ldap_err2string(rc)));
636 return rc;
639 DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
640 return LDAP_SUCCESS;
641 #else
642 DEBUG(0,("StartTLS not supported by LDAP client libraries!\n"));
643 return LDAP_OPERATIONS_ERROR;
644 #endif
647 /********************************************************************
648 setup a connection to the LDAP server based on a uri
649 *******************************************************************/
651 static int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri)
653 int rc;
655 DEBUG(10, ("smb_ldap_setup_connection: %s\n", uri));
657 #ifdef HAVE_LDAP_INITIALIZE
659 rc = ldap_initialize(ldap_struct, uri);
660 if (rc) {
661 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
662 return rc;
665 if (lp_ldap_follow_referral() != Auto) {
666 rc = ldap_set_option(*ldap_struct, LDAP_OPT_REFERRALS,
667 lp_ldap_follow_referral() ? LDAP_OPT_ON : LDAP_OPT_OFF);
668 if (rc != LDAP_SUCCESS)
669 DEBUG(0, ("Failed to set LDAP_OPT_REFERRALS: %s\n",
670 ldap_err2string(rc)));
673 #else
675 /* Parse the string manually */
678 int port = 0;
679 fstring protocol;
680 fstring host;
681 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
684 /* skip leading "URL:" (if any) */
685 if ( strnequal( uri, "URL:", 4 ) ) {
686 uri += 4;
689 sscanf(uri, "%10[^:]://%254[^:/]:%d", protocol, host, &port);
691 if (port == 0) {
692 if (strequal(protocol, "ldap")) {
693 port = LDAP_PORT;
694 } else if (strequal(protocol, "ldaps")) {
695 port = LDAPS_PORT;
696 } else {
697 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
701 if ((*ldap_struct = ldap_init(host, port)) == NULL) {
702 DEBUG(0, ("ldap_init failed !\n"));
703 return LDAP_OPERATIONS_ERROR;
706 if (strequal(protocol, "ldaps")) {
707 #ifdef LDAP_OPT_X_TLS
708 int tls = LDAP_OPT_X_TLS_HARD;
709 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
711 DEBUG(0, ("Failed to setup a TLS session\n"));
714 DEBUG(3,("LDAPS option set...!\n"));
715 #else
716 DEBUG(0,("smbldap_open_connection: Secure connection not supported by LDAP client libraries!\n"));
717 return LDAP_OPERATIONS_ERROR;
718 #endif /* LDAP_OPT_X_TLS */
722 /* now set connection timeout */
723 #ifdef LDAP_X_OPT_CONNECT_TIMEOUT /* Netscape */
725 int ct = lp_ldap_connection_timeout()*1000;
726 rc = ldap_set_option(*ldap_struct, LDAP_X_OPT_CONNECT_TIMEOUT, &ct);
727 if (rc != LDAP_SUCCESS) {
728 DEBUG(0,("Failed to setup an ldap connection timeout %d: %s\n",
729 ct, ldap_err2string(rc)));
732 #elif defined (LDAP_OPT_NETWORK_TIMEOUT) /* OpenLDAP */
734 struct timeval ct;
735 ct.tv_usec = 0;
736 ct.tv_sec = lp_ldap_connection_timeout();
737 rc = ldap_set_option(*ldap_struct, LDAP_OPT_NETWORK_TIMEOUT, &ct);
738 if (rc != LDAP_SUCCESS) {
739 DEBUG(0,("Failed to setup an ldap connection timeout %d: %s\n",
740 (int)ct.tv_sec, ldap_err2string(rc)));
743 #endif
745 #endif /* HAVE_LDAP_INITIALIZE */
746 return LDAP_SUCCESS;
749 /********************************************************************
750 try to upgrade to Version 3 LDAP if not already, in either case return current
751 version
752 *******************************************************************/
754 static int smb_ldap_upgrade_conn(LDAP *ldap_struct, int *new_version)
756 int version;
757 int rc;
759 /* assume the worst */
760 *new_version = LDAP_VERSION2;
762 rc = ldap_get_option(ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
763 if (rc) {
764 return rc;
767 if (version == LDAP_VERSION3) {
768 *new_version = LDAP_VERSION3;
769 return LDAP_SUCCESS;
772 /* try upgrade */
773 version = LDAP_VERSION3;
774 rc = ldap_set_option (ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
775 if (rc) {
776 return rc;
779 *new_version = LDAP_VERSION3;
780 return LDAP_SUCCESS;
783 /*******************************************************************
784 open a connection to the ldap server (just until the bind)
785 ******************************************************************/
787 int smbldap_setup_full_conn(LDAP **ldap_struct, const char *uri)
789 int rc, version;
791 rc = smb_ldap_setup_conn(ldap_struct, uri);
792 if (rc) {
793 return rc;
796 rc = smb_ldap_upgrade_conn(*ldap_struct, &version);
797 if (rc) {
798 return rc;
801 rc = smbldap_start_tls(*ldap_struct, version);
802 if (rc) {
803 return rc;
806 return LDAP_SUCCESS;
809 /*******************************************************************
810 open a connection to the ldap server.
811 ******************************************************************/
812 static int smbldap_open_connection (struct smbldap_state *ldap_state)
815 int rc = LDAP_SUCCESS;
816 int version;
817 int deref;
818 LDAP **ldap_struct = &ldap_state->ldap_struct;
820 rc = smb_ldap_setup_conn(ldap_struct, ldap_state->uri);
821 if (rc) {
822 return rc;
825 /* Store the LDAP pointer in a lookup list */
827 smbldap_store_state(*ldap_struct, ldap_state);
829 /* Upgrade to LDAPv3 if possible */
831 rc = smb_ldap_upgrade_conn(*ldap_struct, &version);
832 if (rc) {
833 return rc;
836 /* Start TLS if required */
838 rc = smbldap_start_tls(*ldap_struct, version);
839 if (rc) {
840 return rc;
843 /* Set alias dereferencing method */
844 deref = lp_ldap_deref();
845 if (deref != -1) {
846 if (ldap_set_option (*ldap_struct, LDAP_OPT_DEREF, &deref) != LDAP_OPT_SUCCESS) {
847 DEBUG(1,("smbldap_open_connection: Failed to set dereferencing method: %d\n", deref));
848 } else {
849 DEBUG(5,("Set dereferencing method: %d\n", deref));
853 DEBUG(2, ("smbldap_open_connection: connection opened\n"));
854 return rc;
857 /*******************************************************************
858 a rebind function for authenticated referrals
859 This version takes a void* that we can shove useful stuff in :-)
860 ******************************************************************/
861 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
862 #else
863 static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
864 int *methodp, int freeit, void *arg)
866 struct smbldap_state *ldap_state = arg;
867 struct timespec ts;
869 /** @TODO Should we be doing something to check what servers we rebind to?
870 Could we get a referral to a machine that we don't want to give our
871 username and password to? */
873 if (freeit) {
874 SAFE_FREE(*whop);
875 if (*credp) {
876 memset(*credp, '\0', strlen(*credp));
878 SAFE_FREE(*credp);
879 } else {
880 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
881 ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
883 if (ldap_state->anonymous) {
884 *whop = NULL;
885 *credp = NULL;
886 } else {
887 *whop = SMB_STRDUP(ldap_state->bind_dn);
888 if (!*whop) {
889 return LDAP_NO_MEMORY;
891 *credp = SMB_STRDUP(ldap_state->bind_secret);
892 if (!*credp) {
893 SAFE_FREE(*whop);
894 return LDAP_NO_MEMORY;
897 *methodp = LDAP_AUTH_SIMPLE;
900 clock_gettime_mono(&ts);
901 ldap_state->last_rebind = convert_timespec_to_timeval(ts);
903 return 0;
905 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
907 /*******************************************************************
908 a rebind function for authenticated referrals
909 This version takes a void* that we can shove useful stuff in :-)
910 and actually does the connection.
911 ******************************************************************/
912 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
913 static int rebindproc_connect_with_state (LDAP *ldap_struct,
914 LDAP_CONST char *url,
915 ber_tag_t request,
916 ber_int_t msgid, void *arg)
918 struct smbldap_state *ldap_state =
919 (struct smbldap_state *)arg;
920 int rc;
921 struct timespec ts;
922 int version;
924 DEBUG(5,("rebindproc_connect_with_state: Rebinding to %s as \"%s\"\n",
925 url, ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
927 /* call START_TLS again (ldaps:// is handled by the OpenLDAP library
928 * itself) before rebinding to another LDAP server to avoid to expose
929 * our credentials. At least *try* to secure the connection - Guenther */
931 smb_ldap_upgrade_conn(ldap_struct, &version);
932 smbldap_start_tls(ldap_struct, version);
934 /** @TODO Should we be doing something to check what servers we rebind to?
935 Could we get a referral to a machine that we don't want to give our
936 username and password to? */
938 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
940 /* only set the last rebind timestamp when we did rebind after a
941 * non-read LDAP operation. That way we avoid the replication sleep
942 * after a simple redirected search operation - Guenther */
944 switch (request) {
946 case LDAP_REQ_MODIFY:
947 case LDAP_REQ_ADD:
948 case LDAP_REQ_DELETE:
949 case LDAP_REQ_MODDN:
950 case LDAP_REQ_EXTENDED:
951 DEBUG(10,("rebindproc_connect_with_state: "
952 "setting last_rebind timestamp "
953 "(req: 0x%02x)\n", (unsigned int)request));
954 clock_gettime_mono(&ts);
955 ldap_state->last_rebind = convert_timespec_to_timeval(ts);
956 break;
957 default:
958 ZERO_STRUCT(ldap_state->last_rebind);
959 break;
962 return rc;
964 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
966 /*******************************************************************
967 Add a rebind function for authenticated referrals
968 ******************************************************************/
969 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
970 #else
971 # if LDAP_SET_REBIND_PROC_ARGS == 2
972 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
973 int *method, int freeit )
975 struct smbldap_state *ldap_state = smbldap_find_state(ldap_struct);
977 return rebindproc_with_state(ldap_struct, whop, credp,
978 method, freeit, ldap_state);
980 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
981 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
983 /*******************************************************************
984 a rebind function for authenticated referrals
985 this also does the connection, but no void*.
986 ******************************************************************/
987 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
988 # if LDAP_SET_REBIND_PROC_ARGS == 2
989 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
990 ber_int_t msgid)
992 struct smbldap_state *ldap_state = smbldap_find_state(ld);
994 return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid,
995 ldap_state);
997 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
998 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
1000 /*******************************************************************
1001 connect to the ldap server under system privilege.
1002 ******************************************************************/
1003 static int smbldap_connect_system(struct smbldap_state *ldap_state)
1005 LDAP *ldap_struct = smbldap_get_ldap(ldap_state);
1006 int rc;
1007 int version;
1009 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
1010 (OpenLDAP) doesn't seem to support it */
1012 DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
1013 ldap_state->uri, ldap_state->bind_dn));
1015 #ifdef HAVE_LDAP_SET_REBIND_PROC
1016 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
1017 # if LDAP_SET_REBIND_PROC_ARGS == 2
1018 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect);
1019 # endif
1020 # if LDAP_SET_REBIND_PROC_ARGS == 3
1021 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);
1022 # endif
1023 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
1024 # if LDAP_SET_REBIND_PROC_ARGS == 2
1025 ldap_set_rebind_proc(ldap_struct, &rebindproc);
1026 # endif
1027 # if LDAP_SET_REBIND_PROC_ARGS == 3
1028 ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);
1029 # endif
1030 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
1031 #endif
1033 /* When there is an alternative bind callback is set,
1034 attempt to use it to perform the bind */
1035 if (ldap_state->bind_callback != NULL) {
1036 /* We have to allow bind callback to be run under become_root/unbecome_root
1037 to make sure within smbd the callback has proper write access to its resources,
1038 like credential cache. This is similar to passdb case where this callback is supposed
1039 to be used. When used outside smbd, become_root()/unbecome_root() are no-op.
1041 become_root();
1042 rc = ldap_state->bind_callback(ldap_struct, ldap_state, ldap_state->bind_callback_data);
1043 unbecome_root();
1044 } else {
1045 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
1048 if (rc != LDAP_SUCCESS) {
1049 char *ld_error = NULL;
1050 ldap_get_option(smbldap_get_ldap(ldap_state),
1051 LDAP_OPT_ERROR_STRING,
1052 &ld_error);
1053 DEBUG(ldap_state->num_failures ? 2 : 0,
1054 ("failed to bind to server %s with dn=\"%s\" Error: %s\n\t%s\n",
1055 ldap_state->uri,
1056 ldap_state->bind_dn ? ldap_state->bind_dn : "[Anonymous bind]",
1057 ldap_err2string(rc),
1058 ld_error ? ld_error : "(unknown)"));
1059 SAFE_FREE(ld_error);
1060 ldap_state->num_failures++;
1061 goto done;
1064 ldap_state->num_failures = 0;
1065 ldap_state->paged_results = False;
1067 ldap_get_option(smbldap_get_ldap(ldap_state),
1068 LDAP_OPT_PROTOCOL_VERSION, &version);
1070 if (smbldap_has_control(smbldap_get_ldap(ldap_state), ADS_PAGE_CTL_OID)
1071 && version == 3) {
1072 ldap_state->paged_results = True;
1075 DEBUG(3, ("ldap_connect_system: successful connection to the LDAP server\n"));
1076 DEBUGADD(10, ("ldap_connect_system: LDAP server %s support paged results\n",
1077 ldap_state->paged_results ? "does" : "does not"));
1078 done:
1079 if (rc != 0) {
1080 ldap_unbind(ldap_struct);
1081 ldap_state->ldap_struct = NULL;
1083 return rc;
1086 static void smbldap_idle_fn(struct tevent_context *tevent_ctx,
1087 struct tevent_timer *te,
1088 struct timeval now_abs,
1089 void *private_data);
1091 /**********************************************************************
1092 Connect to LDAP server (called before every ldap operation)
1093 *********************************************************************/
1094 static int smbldap_open(struct smbldap_state *ldap_state)
1096 int rc, opt_rc;
1097 bool reopen = False;
1098 SMB_ASSERT(ldap_state);
1100 if ((smbldap_get_ldap(ldap_state) != NULL) &&
1101 ((ldap_state->last_ping + SMBLDAP_DONT_PING_TIME) <
1102 time_mono(NULL))) {
1104 #ifdef HAVE_UNIXSOCKET
1105 struct sockaddr_un addr;
1106 #else
1107 struct sockaddr_storage addr;
1108 #endif
1109 socklen_t len = sizeof(addr);
1110 int sd;
1112 opt_rc = ldap_get_option(smbldap_get_ldap(ldap_state),
1113 LDAP_OPT_DESC, &sd);
1114 if (opt_rc == 0 && (getpeername(sd, (struct sockaddr *) &addr, &len)) < 0 )
1115 reopen = True;
1117 #ifdef HAVE_UNIXSOCKET
1118 if (opt_rc == 0 && addr.sun_family == AF_UNIX)
1119 reopen = True;
1120 #endif
1121 if (reopen) {
1122 /* the other end has died. reopen. */
1123 ldap_unbind(smbldap_get_ldap(ldap_state));
1124 ldap_state->ldap_struct = NULL;
1125 ldap_state->last_ping = (time_t)0;
1126 } else {
1127 ldap_state->last_ping = time_mono(NULL);
1131 if (smbldap_get_ldap(ldap_state) != NULL) {
1132 DEBUG(11,("smbldap_open: already connected to the LDAP server\n"));
1133 return LDAP_SUCCESS;
1136 if ((rc = smbldap_open_connection(ldap_state))) {
1137 return rc;
1140 if ((rc = smbldap_connect_system(ldap_state))) {
1141 return rc;
1145 ldap_state->last_ping = time_mono(NULL);
1146 ldap_state->pid = getpid();
1148 TALLOC_FREE(ldap_state->idle_event);
1150 if (ldap_state->tevent_context != NULL) {
1151 ldap_state->idle_event = tevent_add_timer(
1152 ldap_state->tevent_context, ldap_state,
1153 timeval_current_ofs(SMBLDAP_IDLE_TIME, 0),
1154 smbldap_idle_fn, ldap_state);
1157 DEBUG(4,("The LDAP server is successfully connected\n"));
1159 return LDAP_SUCCESS;
1162 /**********************************************************************
1163 Disconnect from LDAP server
1164 *********************************************************************/
1165 static NTSTATUS smbldap_close(struct smbldap_state *ldap_state)
1167 if (!ldap_state)
1168 return NT_STATUS_INVALID_PARAMETER;
1170 if (smbldap_get_ldap(ldap_state) != NULL) {
1171 ldap_unbind(smbldap_get_ldap(ldap_state));
1172 ldap_state->ldap_struct = NULL;
1175 smbldap_delete_state(ldap_state);
1177 TALLOC_FREE(ldap_state->idle_event);
1179 DEBUG(5,("The connection to the LDAP server was closed\n"));
1180 /* maybe free the results here --metze */
1182 return NT_STATUS_OK;
1185 static SIG_ATOMIC_T got_alarm;
1187 static void gotalarm_sig(int dummy)
1189 got_alarm = 1;
1192 static time_t calc_ldap_abs_endtime(int ldap_to)
1194 if (ldap_to == 0) {
1195 /* No timeout - don't
1196 return a value for
1197 the alarm. */
1198 return (time_t)0;
1201 /* Make the alarm time one second beyond
1202 the timeout we're setting for the
1203 remote search timeout, to allow that
1204 to fire in preference. */
1206 return time_mono(NULL)+ldap_to+1;
1209 static int end_ldap_local_alarm(time_t absolute_endtime, int rc)
1211 if (absolute_endtime) {
1212 alarm(0);
1213 CatchSignal(SIGALRM, SIG_IGN);
1214 if (got_alarm) {
1215 /* Client timeout error code. */
1216 got_alarm = 0;
1217 return LDAP_TIMEOUT;
1220 return rc;
1223 static void setup_ldap_local_alarm(struct smbldap_state *ldap_state, time_t absolute_endtime)
1225 time_t now = time_mono(NULL);
1227 if (absolute_endtime) {
1228 got_alarm = 0;
1229 CatchSignal(SIGALRM, gotalarm_sig);
1230 alarm(absolute_endtime - now);
1233 if (ldap_state->pid != getpid()) {
1234 smbldap_close(ldap_state);
1238 static void get_ldap_errs(struct smbldap_state *ldap_state, char **pp_ld_error, int *p_ld_errno)
1240 ldap_get_option(smbldap_get_ldap(ldap_state),
1241 LDAP_OPT_ERROR_NUMBER, p_ld_errno);
1243 ldap_get_option(smbldap_get_ldap(ldap_state),
1244 LDAP_OPT_ERROR_STRING, pp_ld_error);
1247 static int get_cached_ldap_connect(struct smbldap_state *ldap_state, time_t abs_endtime)
1249 int attempts = 0;
1251 while (1) {
1252 int rc;
1253 time_t now;
1255 now = time_mono(NULL);
1256 ldap_state->last_use = now;
1258 if (abs_endtime && now > abs_endtime) {
1259 smbldap_close(ldap_state);
1260 return LDAP_TIMEOUT;
1263 rc = smbldap_open(ldap_state);
1265 if (rc == LDAP_SUCCESS) {
1266 return LDAP_SUCCESS;
1269 attempts++;
1270 DEBUG(1, ("Connection to LDAP server failed for the "
1271 "%d try!\n", attempts));
1273 if (rc == LDAP_INSUFFICIENT_ACCESS) {
1274 /* The fact that we are non-root or any other
1275 * access-denied condition will not change in the next
1276 * round of trying */
1277 return rc;
1280 if (got_alarm) {
1281 smbldap_close(ldap_state);
1282 return LDAP_TIMEOUT;
1285 smb_msleep(1000);
1287 if (got_alarm) {
1288 smbldap_close(ldap_state);
1289 return LDAP_TIMEOUT;
1294 /*********************************************************************
1295 ********************************************************************/
1297 static int smbldap_search_ext(struct smbldap_state *ldap_state,
1298 const char *base, int scope, const char *filter,
1299 const char *attrs[], int attrsonly,
1300 LDAPControl **sctrls, LDAPControl **cctrls,
1301 int sizelimit, LDAPMessage **res)
1303 int rc = LDAP_SERVER_DOWN;
1304 char *utf8_filter;
1305 int to = lp_ldap_timeout();
1306 time_t abs_endtime = calc_ldap_abs_endtime(to);
1307 struct timeval timeout;
1308 struct timeval *timeout_ptr = NULL;
1309 size_t converted_size;
1311 SMB_ASSERT(ldap_state);
1313 DEBUG(5,("smbldap_search_ext: base => [%s], filter => [%s], "
1314 "scope => [%d]\n", base, filter, scope));
1316 if (ldap_state->last_rebind.tv_sec > 0) {
1317 struct timeval tval;
1318 struct timespec ts;
1319 int64_t tdiff = 0;
1320 int sleep_time = 0;
1322 clock_gettime_mono(&ts);
1323 tval = convert_timespec_to_timeval(ts);
1325 tdiff = usec_time_diff(&tval, &ldap_state->last_rebind);
1326 tdiff /= 1000; /* Convert to milliseconds. */
1328 sleep_time = lp_ldap_replication_sleep()-(int)tdiff;
1329 sleep_time = MIN(sleep_time, MAX_LDAP_REPLICATION_SLEEP_TIME);
1331 if (sleep_time > 0) {
1332 /* we wait for the LDAP replication */
1333 DEBUG(5,("smbldap_search_ext: waiting %d milliseconds "
1334 "for LDAP replication.\n",sleep_time));
1335 smb_msleep(sleep_time);
1336 DEBUG(5,("smbldap_search_ext: go on!\n"));
1338 ZERO_STRUCT(ldap_state->last_rebind);
1341 if (!push_utf8_talloc(talloc_tos(), &utf8_filter, filter, &converted_size)) {
1342 return LDAP_NO_MEMORY;
1345 /* Setup remote timeout for the ldap_search_ext_s call. */
1346 if (to) {
1347 timeout.tv_sec = to;
1348 timeout.tv_usec = 0;
1349 timeout_ptr = &timeout;
1352 setup_ldap_local_alarm(ldap_state, abs_endtime);
1354 while (1) {
1355 char *ld_error = NULL;
1356 int ld_errno;
1358 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1359 if (rc != LDAP_SUCCESS) {
1360 break;
1363 rc = ldap_search_ext_s(smbldap_get_ldap(ldap_state),
1364 base, scope,
1365 utf8_filter,
1366 discard_const_p(char *, attrs),
1367 attrsonly, sctrls, cctrls, timeout_ptr,
1368 sizelimit, res);
1369 if (rc == LDAP_SUCCESS) {
1370 break;
1373 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1375 DEBUG(10, ("Failed search for base: %s, error: %d (%s) "
1376 "(%s)\n", base, ld_errno,
1377 ldap_err2string(rc),
1378 ld_error ? ld_error : "unknown"));
1379 SAFE_FREE(ld_error);
1381 if (ld_errno != LDAP_SERVER_DOWN) {
1382 break;
1384 ldap_unbind(smbldap_get_ldap(ldap_state));
1385 ldap_state->ldap_struct = NULL;
1388 TALLOC_FREE(utf8_filter);
1389 return end_ldap_local_alarm(abs_endtime, rc);
1392 int smbldap_search(struct smbldap_state *ldap_state,
1393 const char *base, int scope, const char *filter,
1394 const char *attrs[], int attrsonly,
1395 LDAPMessage **res)
1397 return smbldap_search_ext(ldap_state, base, scope, filter, attrs,
1398 attrsonly, NULL, NULL, LDAP_NO_LIMIT, res);
1401 int smbldap_search_paged(struct smbldap_state *ldap_state,
1402 const char *base, int scope, const char *filter,
1403 const char **attrs, int attrsonly, int pagesize,
1404 LDAPMessage **res, void **cookie)
1406 LDAPControl pr;
1407 LDAPControl **rcontrols;
1408 LDAPControl *controls[2] = { NULL, NULL};
1409 BerElement *cookie_be = NULL;
1410 struct berval *cookie_bv = NULL;
1411 int tmp = 0, i, rc;
1412 bool critical = True;
1414 *res = NULL;
1416 DEBUG(3,("smbldap_search_paged: base => [%s], filter => [%s],"
1417 "scope => [%d], pagesize => [%d]\n",
1418 base, filter, scope, pagesize));
1420 cookie_be = ber_alloc_t(LBER_USE_DER);
1421 if (cookie_be == NULL) {
1422 DEBUG(0,("smbldap_create_page_control: ber_alloc_t returns "
1423 "NULL\n"));
1424 return LDAP_NO_MEMORY;
1427 /* construct cookie */
1428 if (*cookie != NULL) {
1429 ber_printf(cookie_be, "{iO}", (ber_int_t) pagesize, *cookie);
1430 ber_bvfree((struct berval *)*cookie); /* don't need it from last time */
1431 *cookie = NULL;
1432 } else {
1433 ber_printf(cookie_be, "{io}", (ber_int_t) pagesize, "", 0);
1435 ber_flatten(cookie_be, &cookie_bv);
1437 pr.ldctl_oid = discard_const_p(char, ADS_PAGE_CTL_OID);
1438 pr.ldctl_iscritical = (char) critical;
1439 pr.ldctl_value.bv_len = cookie_bv->bv_len;
1440 pr.ldctl_value.bv_val = cookie_bv->bv_val;
1442 controls[0] = &pr;
1443 controls[1] = NULL;
1445 rc = smbldap_search_ext(ldap_state, base, scope, filter, attrs,
1446 0, controls, NULL, LDAP_NO_LIMIT, res);
1448 ber_free(cookie_be, 1);
1449 ber_bvfree(cookie_bv);
1451 if (rc != 0) {
1452 DEBUG(3,("smbldap_search_paged: smbldap_search_ext(%s) "
1453 "failed with [%s]\n", filter, ldap_err2string(rc)));
1454 goto done;
1457 DEBUG(3,("smbldap_search_paged: search was successful\n"));
1459 rc = ldap_parse_result(smbldap_get_ldap(ldap_state), *res, NULL, NULL,
1460 NULL, NULL, &rcontrols, 0);
1461 if (rc != 0) {
1462 DEBUG(3,("smbldap_search_paged: ldap_parse_result failed " \
1463 "with [%s]\n", ldap_err2string(rc)));
1464 goto done;
1467 if (rcontrols == NULL)
1468 goto done;
1470 for (i=0; rcontrols[i]; i++) {
1472 if (strcmp(ADS_PAGE_CTL_OID, rcontrols[i]->ldctl_oid) != 0)
1473 continue;
1475 cookie_be = ber_init(&rcontrols[i]->ldctl_value);
1476 ber_scanf(cookie_be,"{iO}", &tmp, &cookie_bv);
1477 /* the berval is the cookie, but must be freed when it is all
1478 done */
1479 if (cookie_bv->bv_len)
1480 *cookie=ber_bvdup(cookie_bv);
1481 else
1482 *cookie=NULL;
1483 ber_bvfree(cookie_bv);
1484 ber_free(cookie_be, 1);
1485 break;
1487 ldap_controls_free(rcontrols);
1488 done:
1489 return rc;
1492 int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
1494 int rc = LDAP_SERVER_DOWN;
1495 char *utf8_dn;
1496 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1497 size_t converted_size;
1499 SMB_ASSERT(ldap_state);
1501 DEBUG(5,("smbldap_modify: dn => [%s]\n", dn ));
1503 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1504 return LDAP_NO_MEMORY;
1507 setup_ldap_local_alarm(ldap_state, abs_endtime);
1509 while (1) {
1510 char *ld_error = NULL;
1511 int ld_errno;
1513 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1514 if (rc != LDAP_SUCCESS) {
1515 break;
1518 rc = ldap_modify_s(smbldap_get_ldap(ldap_state), utf8_dn,
1519 attrs);
1520 if (rc == LDAP_SUCCESS) {
1521 break;
1524 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1526 DEBUG(10, ("Failed to modify dn: %s, error: %d (%s) "
1527 "(%s)\n", dn, ld_errno,
1528 ldap_err2string(rc),
1529 ld_error ? ld_error : "unknown"));
1530 SAFE_FREE(ld_error);
1532 if (ld_errno != LDAP_SERVER_DOWN) {
1533 break;
1535 ldap_unbind(smbldap_get_ldap(ldap_state));
1536 ldap_state->ldap_struct = NULL;
1539 TALLOC_FREE(utf8_dn);
1540 return end_ldap_local_alarm(abs_endtime, rc);
1543 int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
1545 int rc = LDAP_SERVER_DOWN;
1546 char *utf8_dn;
1547 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1548 size_t converted_size;
1550 SMB_ASSERT(ldap_state);
1552 DEBUG(5,("smbldap_add: dn => [%s]\n", dn ));
1554 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1555 return LDAP_NO_MEMORY;
1558 setup_ldap_local_alarm(ldap_state, abs_endtime);
1560 while (1) {
1561 char *ld_error = NULL;
1562 int ld_errno;
1564 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1565 if (rc != LDAP_SUCCESS) {
1566 break;
1569 rc = ldap_add_s(smbldap_get_ldap(ldap_state), utf8_dn, attrs);
1570 if (rc == LDAP_SUCCESS) {
1571 break;
1574 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1576 DEBUG(10, ("Failed to add dn: %s, error: %d (%s) "
1577 "(%s)\n", dn, ld_errno,
1578 ldap_err2string(rc),
1579 ld_error ? ld_error : "unknown"));
1580 SAFE_FREE(ld_error);
1582 if (ld_errno != LDAP_SERVER_DOWN) {
1583 break;
1585 ldap_unbind(smbldap_get_ldap(ldap_state));
1586 ldap_state->ldap_struct = NULL;
1589 TALLOC_FREE(utf8_dn);
1590 return end_ldap_local_alarm(abs_endtime, rc);
1593 int smbldap_delete(struct smbldap_state *ldap_state, const char *dn)
1595 int rc = LDAP_SERVER_DOWN;
1596 char *utf8_dn;
1597 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1598 size_t converted_size;
1600 SMB_ASSERT(ldap_state);
1602 DEBUG(5,("smbldap_delete: dn => [%s]\n", dn ));
1604 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1605 return LDAP_NO_MEMORY;
1608 setup_ldap_local_alarm(ldap_state, abs_endtime);
1610 while (1) {
1611 char *ld_error = NULL;
1612 int ld_errno;
1614 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1615 if (rc != LDAP_SUCCESS) {
1616 break;
1619 rc = ldap_delete_s(smbldap_get_ldap(ldap_state), utf8_dn);
1620 if (rc == LDAP_SUCCESS) {
1621 break;
1624 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1626 DEBUG(10, ("Failed to delete dn: %s, error: %d (%s) "
1627 "(%s)\n", dn, ld_errno,
1628 ldap_err2string(rc),
1629 ld_error ? ld_error : "unknown"));
1630 SAFE_FREE(ld_error);
1632 if (ld_errno != LDAP_SERVER_DOWN) {
1633 break;
1635 ldap_unbind(smbldap_get_ldap(ldap_state));
1636 ldap_state->ldap_struct = NULL;
1639 TALLOC_FREE(utf8_dn);
1640 return end_ldap_local_alarm(abs_endtime, rc);
1643 int smbldap_extended_operation(struct smbldap_state *ldap_state,
1644 LDAP_CONST char *reqoid, struct berval *reqdata,
1645 LDAPControl **serverctrls, LDAPControl **clientctrls,
1646 char **retoidp, struct berval **retdatap)
1648 int rc = LDAP_SERVER_DOWN;
1649 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1651 if (!ldap_state)
1652 return (-1);
1654 setup_ldap_local_alarm(ldap_state, abs_endtime);
1656 while (1) {
1657 char *ld_error = NULL;
1658 int ld_errno;
1660 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1661 if (rc != LDAP_SUCCESS) {
1662 break;
1665 rc = ldap_extended_operation_s(smbldap_get_ldap(ldap_state),
1666 reqoid,
1667 reqdata, serverctrls,
1668 clientctrls, retoidp, retdatap);
1669 if (rc == LDAP_SUCCESS) {
1670 break;
1673 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1675 DEBUG(10, ("Extended operation failed with error: "
1676 "%d (%s) (%s)\n", ld_errno,
1677 ldap_err2string(rc),
1678 ld_error ? ld_error : "unknown"));
1679 SAFE_FREE(ld_error);
1681 if (ld_errno != LDAP_SERVER_DOWN) {
1682 break;
1684 ldap_unbind(smbldap_get_ldap(ldap_state));
1685 ldap_state->ldap_struct = NULL;
1688 return end_ldap_local_alarm(abs_endtime, rc);
1691 /*******************************************************************
1692 run the search by name.
1693 ******************************************************************/
1694 int smbldap_search_suffix (struct smbldap_state *ldap_state,
1695 const char *filter, const char **search_attr,
1696 LDAPMessage ** result)
1698 return smbldap_search(ldap_state, lp_ldap_suffix(),
1699 LDAP_SCOPE_SUBTREE,
1700 filter, search_attr, 0, result);
1703 static void smbldap_idle_fn(struct tevent_context *tevent_ctx,
1704 struct tevent_timer *te,
1705 struct timeval now_abs,
1706 void *private_data)
1708 struct smbldap_state *state = (struct smbldap_state *)private_data;
1710 TALLOC_FREE(state->idle_event);
1712 if (smbldap_get_ldap(state) == NULL) {
1713 DEBUG(10,("ldap connection not connected...\n"));
1714 return;
1717 if ((state->last_use+SMBLDAP_IDLE_TIME) > time_mono(NULL)) {
1718 DEBUG(10,("ldap connection not idle...\n"));
1720 /* this needs to be made monotonic clock aware inside tevent: */
1721 state->idle_event = tevent_add_timer(
1722 tevent_ctx, state,
1723 timeval_add(&now_abs, SMBLDAP_IDLE_TIME, 0),
1724 smbldap_idle_fn,
1725 private_data);
1726 return;
1729 DEBUG(7,("ldap connection idle...closing connection\n"));
1730 smbldap_close(state);
1733 /**********************************************************************
1734 Housekeeping
1735 *********************************************************************/
1737 void smbldap_free_struct(struct smbldap_state **ldap_state)
1739 smbldap_close(*ldap_state);
1741 if ((*ldap_state)->bind_secret) {
1742 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
1745 SAFE_FREE((*ldap_state)->bind_dn);
1746 BURN_FREE_STR((*ldap_state)->bind_secret);
1747 smbldap_set_bind_callback(*ldap_state, NULL, NULL);
1749 TALLOC_FREE(*ldap_state);
1751 /* No need to free any further, as it is talloc()ed */
1754 static int smbldap_state_destructor(struct smbldap_state *state)
1756 smbldap_free_struct(&state);
1757 return 0;
1761 /**********************************************************************
1762 Initialise the 'general' ldap structures, on which ldap operations may be conducted
1763 *********************************************************************/
1765 NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, struct tevent_context *tevent_ctx,
1766 const char *location,
1767 bool anon,
1768 const char *bind_dn,
1769 const char *bind_secret,
1770 struct smbldap_state **smbldap_state)
1772 *smbldap_state = talloc_zero(mem_ctx, struct smbldap_state);
1773 if (!*smbldap_state) {
1774 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
1775 return NT_STATUS_NO_MEMORY;
1778 if (location) {
1779 (*smbldap_state)->uri = talloc_strdup(mem_ctx, location);
1780 } else {
1781 (*smbldap_state)->uri = "ldap://localhost";
1784 (*smbldap_state)->tevent_context = tevent_ctx;
1786 if (bind_dn && bind_secret) {
1787 smbldap_set_creds(*smbldap_state, anon, bind_dn, bind_secret);
1790 talloc_set_destructor(*smbldap_state, smbldap_state_destructor);
1791 return NT_STATUS_OK;
1794 char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld,
1795 LDAPMessage *entry)
1797 char *utf8_dn, *unix_dn;
1798 size_t converted_size;
1800 utf8_dn = ldap_get_dn(ld, entry);
1801 if (!utf8_dn) {
1802 DEBUG (5, ("smbldap_talloc_dn: ldap_get_dn failed\n"));
1803 return NULL;
1805 if (!pull_utf8_talloc(mem_ctx, &unix_dn, utf8_dn, &converted_size)) {
1806 DEBUG (0, ("smbldap_talloc_dn: String conversion failure utf8 "
1807 "[%s]\n", utf8_dn));
1808 return NULL;
1810 ldap_memfree(utf8_dn);
1811 return unix_dn;
1814 /*******************************************************************
1815 Check if root-dse has a certain Control or Extension
1816 ********************************************************************/
1818 static bool smbldap_check_root_dse(LDAP *ld, const char **attrs, const char *value)
1820 LDAPMessage *msg = NULL;
1821 LDAPMessage *entry = NULL;
1822 char **values = NULL;
1823 int rc, num_result, num_values, i;
1824 bool result = False;
1826 if (!attrs[0]) {
1827 DEBUG(3,("smbldap_check_root_dse: nothing to look for\n"));
1828 return False;
1831 if (!strequal(attrs[0], "supportedExtension") &&
1832 !strequal(attrs[0], "supportedControl") &&
1833 !strequal(attrs[0], "namingContexts")) {
1834 DEBUG(3,("smbldap_check_root_dse: no idea what to query root-dse for: %s ?\n", attrs[0]));
1835 return False;
1838 rc = ldap_search_s(ld, "", LDAP_SCOPE_BASE,
1839 "(objectclass=*)", discard_const_p(char *, attrs), 0 , &msg);
1841 if (rc != LDAP_SUCCESS) {
1842 DEBUG(3,("smbldap_check_root_dse: Could not search rootDSE\n"));
1843 return False;
1846 num_result = ldap_count_entries(ld, msg);
1848 if (num_result != 1) {
1849 DEBUG(3,("smbldap_check_root_dse: Expected one rootDSE, got %d\n", num_result));
1850 goto done;
1853 entry = ldap_first_entry(ld, msg);
1855 if (entry == NULL) {
1856 DEBUG(3,("smbldap_check_root_dse: Could not retrieve rootDSE\n"));
1857 goto done;
1860 values = ldap_get_values(ld, entry, attrs[0]);
1862 if (values == NULL) {
1863 DEBUG(5,("smbldap_check_root_dse: LDAP Server does not support any %s\n", attrs[0]));
1864 goto done;
1867 num_values = ldap_count_values(values);
1869 if (num_values == 0) {
1870 DEBUG(5,("smbldap_check_root_dse: LDAP Server does not have any %s\n", attrs[0]));
1871 goto done;
1874 for (i=0; i<num_values; i++) {
1875 if (strcmp(values[i], value) == 0)
1876 result = True;
1880 done:
1881 if (values != NULL)
1882 ldap_value_free(values);
1883 if (msg != NULL)
1884 ldap_msgfree(msg);
1886 return result;
1890 /*******************************************************************
1891 Check if LDAP-Server supports a certain Control (OID in string format)
1892 ********************************************************************/
1894 bool smbldap_has_control(LDAP *ld, const char *control)
1896 const char *attrs[] = { "supportedControl", NULL };
1897 return smbldap_check_root_dse(ld, attrs, control);
1900 /*******************************************************************
1901 Check if LDAP-Server supports a certain Extension (OID in string format)
1902 ********************************************************************/
1904 bool smbldap_has_extension(LDAP *ld, const char *extension)
1906 const char *attrs[] = { "supportedExtension", NULL };
1907 return smbldap_check_root_dse(ld, attrs, extension);
1910 /*******************************************************************
1911 Check if LDAP-Server holds a given namingContext
1912 ********************************************************************/
1914 bool smbldap_has_naming_context(LDAP *ld, const char *naming_context)
1916 const char *attrs[] = { "namingContexts", NULL };
1917 return smbldap_check_root_dse(ld, attrs, naming_context);
1920 bool smbldap_set_creds(struct smbldap_state *ldap_state, bool anon, const char *dn, const char *secret)
1922 ldap_state->anonymous = anon;
1924 /* free any previously set credential */
1926 SAFE_FREE(ldap_state->bind_dn);
1927 smbldap_set_bind_callback(ldap_state, NULL, NULL);
1929 if (ldap_state->bind_secret) {
1930 /* make sure secrets are zeroed out of memory */
1931 memset(ldap_state->bind_secret, '\0', strlen(ldap_state->bind_secret));
1932 SAFE_FREE(ldap_state->bind_secret);
1935 if ( ! anon) {
1936 ldap_state->bind_dn = SMB_STRDUP(dn);
1937 ldap_state->bind_secret = SMB_STRDUP(secret);
1940 return True;