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/>.
27 #include "../libcli/security/security.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 LDAP *smbldap_get_ldap(struct smbldap_state *state)
40 return state->ldap_struct;
43 bool smbldap_get_paged_results(struct smbldap_state *state)
45 return state->paged_results;
48 /*******************************************************************
49 Search an attribute and return the first value found.
50 ******************************************************************/
52 bool smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
53 const char *attribute, char *value,
64 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
65 DEBUG (10, ("smbldap_get_single_attribute: [%s] = [<does not exist>]\n", attribute));
70 if (!convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, max_len, &size)) {
71 DEBUG(1, ("smbldap_get_single_attribute: string conversion of [%s] = [%s] failed!\n",
72 attribute, values[0]));
73 ldap_value_free(values);
77 ldap_value_free(values);
78 #ifdef DEBUG_PASSWORDS
79 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n", attribute, value));
84 char * smbldap_talloc_single_attribute(LDAP *ldap_struct, LDAPMessage *entry,
85 const char *attribute,
90 size_t converted_size;
92 if (attribute == NULL) {
96 values = ldap_get_values(ldap_struct, entry, attribute);
99 DEBUG(10, ("attribute %s does not exist\n", attribute));
103 if (ldap_count_values(values) != 1) {
104 DEBUG(10, ("attribute %s has %d values, expected only one\n",
105 attribute, ldap_count_values(values)));
106 ldap_value_free(values);
110 if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
111 DEBUG(10, ("pull_utf8_talloc failed\n"));
112 ldap_value_free(values);
116 ldap_value_free(values);
118 #ifdef DEBUG_PASSWORDS
119 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
125 char * smbldap_talloc_first_attribute(LDAP *ldap_struct, LDAPMessage *entry,
126 const char *attribute,
131 size_t converted_size;
133 if (attribute == NULL) {
137 values = ldap_get_values(ldap_struct, entry, attribute);
139 if (values == NULL) {
140 DEBUG(10, ("attribute %s does not exist\n", attribute));
144 if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
145 DEBUG(10, ("pull_utf8_talloc failed\n"));
146 ldap_value_free(values);
150 ldap_value_free(values);
152 #ifdef DEBUG_PASSWORDS
153 DEBUG (100, ("smbldap_get_first_attribute: [%s] = [%s]\n",
159 char * smbldap_talloc_smallest_attribute(LDAP *ldap_struct, LDAPMessage *entry,
160 const char *attribute,
165 size_t converted_size;
168 if (attribute == NULL) {
172 values = ldap_get_values(ldap_struct, entry, attribute);
174 if (values == NULL) {
175 DEBUG(10, ("attribute %s does not exist\n", attribute));
179 if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
180 DEBUG(10, ("pull_utf8_talloc failed\n"));
181 ldap_value_free(values);
185 num_values = ldap_count_values(values);
187 for (i=1; i<num_values; i++) {
190 if (!pull_utf8_talloc(mem_ctx, &tmp, values[i],
192 DEBUG(10, ("pull_utf8_talloc failed\n"));
194 ldap_value_free(values);
198 if (strcasecmp_m(tmp, result) < 0) {
206 ldap_value_free(values);
208 #ifdef DEBUG_PASSWORDS
209 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
215 bool smbldap_talloc_single_blob(TALLOC_CTX *mem_ctx, LDAP *ld,
216 LDAPMessage *msg, const char *attrib,
219 struct berval **values;
221 values = ldap_get_values_len(ld, msg, attrib);
226 if (ldap_count_values_len(values) != 1) {
227 DEBUG(10, ("Expected one value for %s, got %d\n", attrib,
228 ldap_count_values_len(values)));
232 *blob = data_blob_talloc(mem_ctx, values[0]->bv_val,
234 ldap_value_free_len(values);
236 return (blob->data != NULL);
239 bool smbldap_pull_sid(LDAP *ld, LDAPMessage *msg, const char *attrib,
245 if (!smbldap_talloc_single_blob(talloc_tos(), ld, msg, attrib,
249 ret = sid_parse(blob.data, blob.length, sid);
250 TALLOC_FREE(blob.data);
254 static int ldapmsg_destructor(LDAPMessage **result) {
255 ldap_msgfree(*result);
259 void smbldap_talloc_autofree_ldapmsg(TALLOC_CTX *mem_ctx, LDAPMessage *result)
261 LDAPMessage **handle;
263 if (result == NULL) {
267 handle = talloc(mem_ctx, LDAPMessage *);
268 SMB_ASSERT(handle != NULL);
271 talloc_set_destructor(handle, ldapmsg_destructor);
274 static int ldapmod_destructor(LDAPMod ***mod) {
275 ldap_mods_free(*mod, True);
279 void smbldap_talloc_autofree_ldapmod(TALLOC_CTX *mem_ctx, LDAPMod **mod)
287 handle = talloc(mem_ctx, LDAPMod **);
288 SMB_ASSERT(handle != NULL);
291 talloc_set_destructor(handle, ldapmod_destructor);
294 /************************************************************************
295 Routine to manage the LDAPMod structure array
296 manage memory used by the array, by each struct, and values
297 ***********************************************************************/
299 static void smbldap_set_mod_internal(LDAPMod *** modlist, int modop, const char *attribute, const char *value, const DATA_BLOB *blob)
307 /* sanity checks on the mod values */
309 if (attribute == NULL || *attribute == '\0') {
313 #if 0 /* commented out after discussion with abartlet. Do not re-enable.
314 left here so other do not re-add similar code --jerry */
315 if (value == NULL || *value == '\0')
320 mods = SMB_MALLOC_P(LDAPMod *);
322 smb_panic("smbldap_set_mod: out of memory!");
328 for (i = 0; mods[i] != NULL; ++i) {
329 if (mods[i]->mod_op == modop && strequal(mods[i]->mod_type, attribute))
333 if (mods[i] == NULL) {
334 mods = SMB_REALLOC_ARRAY (mods, LDAPMod *, i + 2);
336 smb_panic("smbldap_set_mod: out of memory!");
339 mods[i] = SMB_MALLOC_P(LDAPMod);
340 if (mods[i] == NULL) {
341 smb_panic("smbldap_set_mod: out of memory!");
344 mods[i]->mod_op = modop;
345 mods[i]->mod_values = NULL;
346 mods[i]->mod_type = SMB_STRDUP(attribute);
350 if (blob && (modop & LDAP_MOD_BVALUES)) {
352 if (mods[i]->mod_bvalues != NULL) {
353 for (; mods[i]->mod_bvalues[j] != NULL; j++);
355 mods[i]->mod_bvalues = SMB_REALLOC_ARRAY(mods[i]->mod_bvalues, struct berval *, j + 2);
357 if (mods[i]->mod_bvalues == NULL) {
358 smb_panic("smbldap_set_mod: out of memory!");
362 mods[i]->mod_bvalues[j] = SMB_MALLOC_P(struct berval);
363 SMB_ASSERT(mods[i]->mod_bvalues[j] != NULL);
365 mods[i]->mod_bvalues[j]->bv_val = (char *)smb_memdup(blob->data, blob->length);
366 SMB_ASSERT(mods[i]->mod_bvalues[j]->bv_val != NULL);
367 mods[i]->mod_bvalues[j]->bv_len = blob->length;
369 mods[i]->mod_bvalues[j + 1] = NULL;
370 } else if (value != NULL) {
371 char *utf8_value = NULL;
372 size_t converted_size;
375 if (mods[i]->mod_values != NULL) {
376 for (; mods[i]->mod_values[j] != NULL; j++);
378 mods[i]->mod_values = SMB_REALLOC_ARRAY(mods[i]->mod_values, char *, j + 2);
380 if (mods[i]->mod_values == NULL) {
381 smb_panic("smbldap_set_mod: out of memory!");
385 if (!push_utf8_talloc(talloc_tos(), &utf8_value, value, &converted_size)) {
386 smb_panic("smbldap_set_mod: String conversion failure!");
390 mods[i]->mod_values[j] = SMB_STRDUP(utf8_value);
391 TALLOC_FREE(utf8_value);
392 SMB_ASSERT(mods[i]->mod_values[j] != NULL);
394 mods[i]->mod_values[j + 1] = NULL;
399 void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
401 smbldap_set_mod_internal(modlist, modop, attribute, value, NULL);
404 void smbldap_set_mod_blob(LDAPMod *** modlist, int modop, const char *attribute, const DATA_BLOB *value)
406 smbldap_set_mod_internal(modlist, modop | LDAP_MOD_BVALUES, attribute, NULL, value);
409 /**********************************************************************
410 Set attribute to newval in LDAP, regardless of what value the
411 attribute had in LDAP before.
412 *********************************************************************/
414 static void smbldap_make_mod_internal(LDAP *ldap_struct, LDAPMessage *existing,
416 const char *attribute, int op,
418 const DATA_BLOB *newblob)
420 char oldval[2048]; /* current largest allowed value is mungeddial */
422 DATA_BLOB oldblob = data_blob_null;
424 if (existing != NULL) {
425 if (op & LDAP_MOD_BVALUES) {
426 existed = smbldap_talloc_single_blob(talloc_tos(), ldap_struct, existing, attribute, &oldblob);
428 existed = smbldap_get_single_attribute(ldap_struct, existing, attribute, oldval, sizeof(oldval));
437 if (op & LDAP_MOD_BVALUES) {
438 equal = (newblob && (data_blob_cmp(&oldblob, newblob) == 0));
440 /* all of our string attributes are case insensitive */
441 equal = (newval && (strcasecmp_m(oldval, newval) == 0));
445 /* Believe it or not, but LDAP will deny a delete and
446 an add at the same time if the values are the
448 DEBUG(10,("smbldap_make_mod: attribute |%s| not changed.\n", attribute));
452 /* There has been no value before, so don't delete it.
453 * Here's a possible race: We might end up with
454 * duplicate attributes */
455 /* By deleting exactly the value we found in the entry this
456 * should be race-free in the sense that the LDAP-Server will
457 * deny the complete operation if somebody changed the
458 * attribute behind our back. */
459 /* This will also allow modifying single valued attributes
460 * in Novell NDS. In NDS you have to first remove attribute and then
461 * you could add new value */
463 if (op & LDAP_MOD_BVALUES) {
464 DEBUG(10,("smbldap_make_mod: deleting attribute |%s| blob\n", attribute));
465 smbldap_set_mod_blob(mods, LDAP_MOD_DELETE, attribute, &oldblob);
467 DEBUG(10,("smbldap_make_mod: deleting attribute |%s| values |%s|\n", attribute, oldval));
468 smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, oldval);
472 /* Regardless of the real operation (add or modify)
473 we add the new value here. We rely on deleting
474 the old value, should it exist. */
476 if (op & LDAP_MOD_BVALUES) {
477 if (newblob && newblob->length) {
478 DEBUG(10,("smbldap_make_mod: adding attribute |%s| blob\n", attribute));
479 smbldap_set_mod_blob(mods, LDAP_MOD_ADD, attribute, newblob);
482 if ((newval != NULL) && (strlen(newval) > 0)) {
483 DEBUG(10,("smbldap_make_mod: adding attribute |%s| value |%s|\n", attribute, newval));
484 smbldap_set_mod(mods, LDAP_MOD_ADD, attribute, newval);
489 void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing,
491 const char *attribute, const char *newval)
493 smbldap_make_mod_internal(ldap_struct, existing, mods, attribute,
497 void smbldap_make_mod_blob(LDAP *ldap_struct, LDAPMessage *existing,
499 const char *attribute, const DATA_BLOB *newblob)
501 smbldap_make_mod_internal(ldap_struct, existing, mods, attribute,
502 LDAP_MOD_BVALUES, NULL, newblob);
505 /**********************************************************************
506 Some varients of the LDAP rebind code do not pass in the third 'arg'
507 pointer to a void*, so we try and work around it by assuming that the
508 value of the 'LDAP *' pointer is the same as the one we had passed in
509 **********************************************************************/
511 struct smbldap_state_lookup {
513 struct smbldap_state *smbldap_state;
514 struct smbldap_state_lookup *prev, *next;
517 static struct smbldap_state_lookup *smbldap_state_lookup_list;
519 static struct smbldap_state *smbldap_find_state(LDAP *ld)
521 struct smbldap_state_lookup *t;
523 for (t = smbldap_state_lookup_list; t; t = t->next) {
525 return t->smbldap_state;
531 static void smbldap_delete_state(struct smbldap_state *smbldap_state)
533 struct smbldap_state_lookup *t;
535 for (t = smbldap_state_lookup_list; t; t = t->next) {
536 if (t->smbldap_state == smbldap_state) {
537 DLIST_REMOVE(smbldap_state_lookup_list, t);
544 static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state)
546 struct smbldap_state *tmp_ldap_state;
547 struct smbldap_state_lookup *t;
549 if ((tmp_ldap_state = smbldap_find_state(ld))) {
550 SMB_ASSERT(tmp_ldap_state == smbldap_state);
554 t = SMB_XMALLOC_P(struct smbldap_state_lookup);
557 DLIST_ADD_END(smbldap_state_lookup_list, t);
559 t->smbldap_state = smbldap_state;
562 /********************************************************************
563 start TLS on an existing LDAP connection
564 *******************************************************************/
566 int smbldap_start_tls(LDAP *ldap_struct, int version)
568 #ifdef LDAP_OPT_X_TLS
572 if (lp_ldap_ssl() != LDAP_SSL_START_TLS) {
576 #ifdef LDAP_OPT_X_TLS
577 if (version != LDAP_VERSION3) {
578 DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
579 return LDAP_OPERATIONS_ERROR;
582 if ((rc = ldap_start_tls_s (ldap_struct, NULL, NULL)) != LDAP_SUCCESS) {
583 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
584 ldap_err2string(rc)));
588 DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
591 DEBUG(0,("StartTLS not supported by LDAP client libraries!\n"));
592 return LDAP_OPERATIONS_ERROR;
596 /********************************************************************
597 setup a connection to the LDAP server based on a uri
598 *******************************************************************/
600 static int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri)
604 DEBUG(10, ("smb_ldap_setup_connection: %s\n", uri));
606 #ifdef HAVE_LDAP_INITIALIZE
608 rc = ldap_initialize(ldap_struct, uri);
610 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
614 if (lp_ldap_follow_referral() != Auto) {
615 rc = ldap_set_option(*ldap_struct, LDAP_OPT_REFERRALS,
616 lp_ldap_follow_referral() ? LDAP_OPT_ON : LDAP_OPT_OFF);
617 if (rc != LDAP_SUCCESS)
618 DEBUG(0, ("Failed to set LDAP_OPT_REFERRALS: %s\n",
619 ldap_err2string(rc)));
625 /* Parse the string manually */
631 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
634 /* skip leading "URL:" (if any) */
635 if ( strnequal( uri, "URL:", 4 ) ) {
639 sscanf(uri, "%10[^:]://%254[^:/]:%d", protocol, host, &port);
642 if (strequal(protocol, "ldap")) {
644 } else if (strequal(protocol, "ldaps")) {
647 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
651 if ((*ldap_struct = ldap_init(host, port)) == NULL) {
652 DEBUG(0, ("ldap_init failed !\n"));
653 return LDAP_OPERATIONS_ERROR;
656 if (strequal(protocol, "ldaps")) {
657 #ifdef LDAP_OPT_X_TLS
658 int tls = LDAP_OPT_X_TLS_HARD;
659 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
661 DEBUG(0, ("Failed to setup a TLS session\n"));
664 DEBUG(3,("LDAPS option set...!\n"));
666 DEBUG(0,("smbldap_open_connection: Secure connection not supported by LDAP client libraries!\n"));
667 return LDAP_OPERATIONS_ERROR;
668 #endif /* LDAP_OPT_X_TLS */
671 #endif /* HAVE_LDAP_INITIALIZE */
673 /* now set connection timeout */
674 #ifdef LDAP_X_OPT_CONNECT_TIMEOUT /* Netscape */
676 int ct = lp_ldap_connection_timeout()*1000;
677 rc = ldap_set_option(*ldap_struct, LDAP_X_OPT_CONNECT_TIMEOUT, &ct);
678 if (rc != LDAP_SUCCESS) {
679 DEBUG(0,("Failed to setup an ldap connection timeout %d: %s\n",
680 ct, ldap_err2string(rc)));
683 #elif defined (LDAP_OPT_NETWORK_TIMEOUT) /* OpenLDAP */
687 ct.tv_sec = lp_ldap_connection_timeout();
688 rc = ldap_set_option(*ldap_struct, LDAP_OPT_NETWORK_TIMEOUT, &ct);
689 if (rc != LDAP_SUCCESS) {
690 DEBUG(0,("Failed to setup an ldap connection timeout %d: %s\n",
691 (int)ct.tv_sec, ldap_err2string(rc)));
699 /********************************************************************
700 try to upgrade to Version 3 LDAP if not already, in either case return current
702 *******************************************************************/
704 static int smb_ldap_upgrade_conn(LDAP *ldap_struct, int *new_version)
709 /* assume the worst */
710 *new_version = LDAP_VERSION2;
712 rc = ldap_get_option(ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
717 if (version == LDAP_VERSION3) {
718 *new_version = LDAP_VERSION3;
723 version = LDAP_VERSION3;
724 rc = ldap_set_option (ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
729 *new_version = LDAP_VERSION3;
733 /*******************************************************************
734 open a connection to the ldap server (just until the bind)
735 ******************************************************************/
737 int smbldap_setup_full_conn(LDAP **ldap_struct, const char *uri)
741 rc = smb_ldap_setup_conn(ldap_struct, uri);
746 rc = smb_ldap_upgrade_conn(*ldap_struct, &version);
751 rc = smbldap_start_tls(*ldap_struct, version);
759 /*******************************************************************
760 open a connection to the ldap server.
761 ******************************************************************/
762 static int smbldap_open_connection (struct smbldap_state *ldap_state)
765 int rc = LDAP_SUCCESS;
768 LDAP **ldap_struct = &ldap_state->ldap_struct;
770 rc = smb_ldap_setup_conn(ldap_struct, ldap_state->uri);
775 /* Store the LDAP pointer in a lookup list */
777 smbldap_store_state(*ldap_struct, ldap_state);
779 /* Upgrade to LDAPv3 if possible */
781 rc = smb_ldap_upgrade_conn(*ldap_struct, &version);
786 /* Start TLS if required */
788 rc = smbldap_start_tls(*ldap_struct, version);
793 /* Set alias dereferencing method */
794 deref = lp_ldap_deref();
796 if (ldap_set_option (*ldap_struct, LDAP_OPT_DEREF, &deref) != LDAP_OPT_SUCCESS) {
797 DEBUG(1,("smbldap_open_connection: Failed to set dereferencing method: %d\n", deref));
799 DEBUG(5,("Set dereferencing method: %d\n", deref));
803 DEBUG(2, ("smbldap_open_connection: connection opened\n"));
807 /*******************************************************************
808 a rebind function for authenticated referrals
809 This version takes a void* that we can shove useful stuff in :-)
810 ******************************************************************/
811 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
813 static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
814 int *methodp, int freeit, void *arg)
816 struct smbldap_state *ldap_state = arg;
819 /** @TODO Should we be doing something to check what servers we rebind to?
820 Could we get a referral to a machine that we don't want to give our
821 username and password to? */
826 memset(*credp, '\0', strlen(*credp));
830 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
831 ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
833 if (ldap_state->anonymous) {
837 *whop = SMB_STRDUP(ldap_state->bind_dn);
839 return LDAP_NO_MEMORY;
841 *credp = SMB_STRDUP(ldap_state->bind_secret);
844 return LDAP_NO_MEMORY;
847 *methodp = LDAP_AUTH_SIMPLE;
850 clock_gettime_mono(&ts);
851 ldap_state->last_rebind = convert_timespec_to_timeval(ts);
855 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
857 /*******************************************************************
858 a rebind function for authenticated referrals
859 This version takes a void* that we can shove useful stuff in :-)
860 and actually does the connection.
861 ******************************************************************/
862 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
863 static int rebindproc_connect_with_state (LDAP *ldap_struct,
864 LDAP_CONST char *url,
866 ber_int_t msgid, void *arg)
868 struct smbldap_state *ldap_state =
869 (struct smbldap_state *)arg;
874 DEBUG(5,("rebindproc_connect_with_state: Rebinding to %s as \"%s\"\n",
875 url, ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
877 /* call START_TLS again (ldaps:// is handled by the OpenLDAP library
878 * itself) before rebinding to another LDAP server to avoid to expose
879 * our credentials. At least *try* to secure the connection - Guenther */
881 smb_ldap_upgrade_conn(ldap_struct, &version);
882 smbldap_start_tls(ldap_struct, version);
884 /** @TODO Should we be doing something to check what servers we rebind to?
885 Could we get a referral to a machine that we don't want to give our
886 username and password to? */
888 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
890 /* only set the last rebind timestamp when we did rebind after a
891 * non-read LDAP operation. That way we avoid the replication sleep
892 * after a simple redirected search operation - Guenther */
896 case LDAP_REQ_MODIFY:
898 case LDAP_REQ_DELETE:
900 case LDAP_REQ_EXTENDED:
901 DEBUG(10,("rebindproc_connect_with_state: "
902 "setting last_rebind timestamp "
903 "(req: 0x%02x)\n", (unsigned int)request));
904 clock_gettime_mono(&ts);
905 ldap_state->last_rebind = convert_timespec_to_timeval(ts);
908 ZERO_STRUCT(ldap_state->last_rebind);
914 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
916 /*******************************************************************
917 Add a rebind function for authenticated referrals
918 ******************************************************************/
919 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
921 # if LDAP_SET_REBIND_PROC_ARGS == 2
922 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
923 int *method, int freeit )
925 struct smbldap_state *ldap_state = smbldap_find_state(ldap_struct);
927 return rebindproc_with_state(ldap_struct, whop, credp,
928 method, freeit, ldap_state);
930 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
931 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
933 /*******************************************************************
934 a rebind function for authenticated referrals
935 this also does the connection, but no void*.
936 ******************************************************************/
937 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
938 # if LDAP_SET_REBIND_PROC_ARGS == 2
939 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
942 struct smbldap_state *ldap_state = smbldap_find_state(ld);
944 return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid,
947 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
948 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
950 /*******************************************************************
951 connect to the ldap server under system privilege.
952 ******************************************************************/
953 static int smbldap_connect_system(struct smbldap_state *ldap_state)
955 LDAP *ldap_struct = smbldap_get_ldap(ldap_state);
959 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
960 (OpenLDAP) doesn't seem to support it */
962 DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
963 ldap_state->uri, ldap_state->bind_dn));
965 #ifdef HAVE_LDAP_SET_REBIND_PROC
966 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
967 # if LDAP_SET_REBIND_PROC_ARGS == 2
968 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect);
970 # if LDAP_SET_REBIND_PROC_ARGS == 3
971 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);
973 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
974 # if LDAP_SET_REBIND_PROC_ARGS == 2
975 ldap_set_rebind_proc(ldap_struct, &rebindproc);
977 # if LDAP_SET_REBIND_PROC_ARGS == 3
978 ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);
980 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
983 /* When there is an alternative bind callback is set,
984 attempt to use it to perform the bind */
985 if (ldap_state->bind_callback != NULL) {
986 /* We have to allow bind callback to be run under become_root/unbecome_root
987 to make sure within smbd the callback has proper write access to its resources,
988 like credential cache. This is similar to passdb case where this callback is supposed
989 to be used. When used outside smbd, become_root()/unbecome_root() are no-op.
992 rc = ldap_state->bind_callback(ldap_struct, ldap_state, ldap_state->bind_callback_data);
995 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
998 if (rc != LDAP_SUCCESS) {
999 char *ld_error = NULL;
1000 ldap_get_option(smbldap_get_ldap(ldap_state),
1001 LDAP_OPT_ERROR_STRING,
1003 DEBUG(ldap_state->num_failures ? 2 : 0,
1004 ("failed to bind to server %s with dn=\"%s\" Error: %s\n\t%s\n",
1006 ldap_state->bind_dn ? ldap_state->bind_dn : "[Anonymous bind]",
1007 ldap_err2string(rc),
1008 ld_error ? ld_error : "(unknown)"));
1009 SAFE_FREE(ld_error);
1010 ldap_state->num_failures++;
1014 ldap_state->num_failures = 0;
1015 ldap_state->paged_results = False;
1017 ldap_get_option(smbldap_get_ldap(ldap_state),
1018 LDAP_OPT_PROTOCOL_VERSION, &version);
1020 if (smbldap_has_control(smbldap_get_ldap(ldap_state), ADS_PAGE_CTL_OID)
1022 ldap_state->paged_results = True;
1025 DEBUG(3, ("ldap_connect_system: successful connection to the LDAP server\n"));
1026 DEBUGADD(10, ("ldap_connect_system: LDAP server %s support paged results\n",
1027 ldap_state->paged_results ? "does" : "does not"));
1030 ldap_unbind(ldap_struct);
1031 ldap_state->ldap_struct = NULL;
1036 static void smbldap_idle_fn(struct tevent_context *tevent_ctx,
1037 struct tevent_timer *te,
1038 struct timeval now_abs,
1039 void *private_data);
1041 /**********************************************************************
1042 Connect to LDAP server (called before every ldap operation)
1043 *********************************************************************/
1044 static int smbldap_open(struct smbldap_state *ldap_state)
1047 bool reopen = False;
1048 SMB_ASSERT(ldap_state);
1050 if ((smbldap_get_ldap(ldap_state) != NULL) &&
1051 ((ldap_state->last_ping + SMBLDAP_DONT_PING_TIME) <
1054 #ifdef HAVE_UNIXSOCKET
1055 struct sockaddr_un addr;
1057 struct sockaddr_storage addr;
1059 socklen_t len = sizeof(addr);
1062 opt_rc = ldap_get_option(smbldap_get_ldap(ldap_state),
1063 LDAP_OPT_DESC, &sd);
1064 if (opt_rc == 0 && (getpeername(sd, (struct sockaddr *) &addr, &len)) < 0 )
1067 #ifdef HAVE_UNIXSOCKET
1068 if (opt_rc == 0 && addr.sun_family == AF_UNIX)
1072 /* the other end has died. reopen. */
1073 ldap_unbind(smbldap_get_ldap(ldap_state));
1074 ldap_state->ldap_struct = NULL;
1075 ldap_state->last_ping = (time_t)0;
1077 ldap_state->last_ping = time_mono(NULL);
1081 if (smbldap_get_ldap(ldap_state) != NULL) {
1082 DEBUG(11,("smbldap_open: already connected to the LDAP server\n"));
1083 return LDAP_SUCCESS;
1086 if ((rc = smbldap_open_connection(ldap_state))) {
1090 if ((rc = smbldap_connect_system(ldap_state))) {
1095 ldap_state->last_ping = time_mono(NULL);
1096 ldap_state->pid = getpid();
1098 TALLOC_FREE(ldap_state->idle_event);
1100 if (ldap_state->tevent_context != NULL) {
1101 ldap_state->idle_event = tevent_add_timer(
1102 ldap_state->tevent_context, ldap_state,
1103 timeval_current_ofs(SMBLDAP_IDLE_TIME, 0),
1104 smbldap_idle_fn, ldap_state);
1107 DEBUG(4,("The LDAP server is successfully connected\n"));
1109 return LDAP_SUCCESS;
1112 /**********************************************************************
1113 Disconnect from LDAP server
1114 *********************************************************************/
1115 static NTSTATUS smbldap_close(struct smbldap_state *ldap_state)
1118 return NT_STATUS_INVALID_PARAMETER;
1120 if (smbldap_get_ldap(ldap_state) != NULL) {
1121 ldap_unbind(smbldap_get_ldap(ldap_state));
1122 ldap_state->ldap_struct = NULL;
1125 smbldap_delete_state(ldap_state);
1127 TALLOC_FREE(ldap_state->idle_event);
1129 DEBUG(5,("The connection to the LDAP server was closed\n"));
1130 /* maybe free the results here --metze */
1132 return NT_STATUS_OK;
1135 static SIG_ATOMIC_T got_alarm;
1137 static void gotalarm_sig(int dummy)
1142 static time_t calc_ldap_abs_endtime(int ldap_to)
1145 /* No timeout - don't
1151 /* Make the alarm time one second beyond
1152 the timout we're setting for the
1153 remote search timeout, to allow that
1154 to fire in preference. */
1156 return time_mono(NULL)+ldap_to+1;
1159 static int end_ldap_local_alarm(time_t absolute_endtime, int rc)
1161 if (absolute_endtime) {
1163 CatchSignal(SIGALRM, SIG_IGN);
1165 /* Client timeout error code. */
1167 return LDAP_TIMEOUT;
1173 static void setup_ldap_local_alarm(struct smbldap_state *ldap_state, time_t absolute_endtime)
1175 time_t now = time_mono(NULL);
1177 if (absolute_endtime) {
1179 CatchSignal(SIGALRM, gotalarm_sig);
1180 alarm(absolute_endtime - now);
1183 if (ldap_state->pid != getpid()) {
1184 smbldap_close(ldap_state);
1188 static void get_ldap_errs(struct smbldap_state *ldap_state, char **pp_ld_error, int *p_ld_errno)
1190 ldap_get_option(smbldap_get_ldap(ldap_state),
1191 LDAP_OPT_ERROR_NUMBER, p_ld_errno);
1193 ldap_get_option(smbldap_get_ldap(ldap_state),
1194 LDAP_OPT_ERROR_STRING, pp_ld_error);
1197 static int get_cached_ldap_connect(struct smbldap_state *ldap_state, time_t abs_endtime)
1205 now = time_mono(NULL);
1206 ldap_state->last_use = now;
1208 if (abs_endtime && now > abs_endtime) {
1209 smbldap_close(ldap_state);
1210 return LDAP_TIMEOUT;
1213 rc = smbldap_open(ldap_state);
1215 if (rc == LDAP_SUCCESS) {
1216 return LDAP_SUCCESS;
1220 DEBUG(1, ("Connection to LDAP server failed for the "
1221 "%d try!\n", attempts));
1223 if (rc == LDAP_INSUFFICIENT_ACCESS) {
1224 /* The fact that we are non-root or any other
1225 * access-denied condition will not change in the next
1226 * round of trying */
1231 smbldap_close(ldap_state);
1232 return LDAP_TIMEOUT;
1238 smbldap_close(ldap_state);
1239 return LDAP_TIMEOUT;
1244 /*********************************************************************
1245 ********************************************************************/
1247 static int smbldap_search_ext(struct smbldap_state *ldap_state,
1248 const char *base, int scope, const char *filter,
1249 const char *attrs[], int attrsonly,
1250 LDAPControl **sctrls, LDAPControl **cctrls,
1251 int sizelimit, LDAPMessage **res)
1253 int rc = LDAP_SERVER_DOWN;
1255 int to = lp_ldap_timeout();
1256 time_t abs_endtime = calc_ldap_abs_endtime(to);
1257 struct timeval timeout;
1258 struct timeval *timeout_ptr = NULL;
1259 size_t converted_size;
1261 SMB_ASSERT(ldap_state);
1263 DEBUG(5,("smbldap_search_ext: base => [%s], filter => [%s], "
1264 "scope => [%d]\n", base, filter, scope));
1266 if (ldap_state->last_rebind.tv_sec > 0) {
1267 struct timeval tval;
1272 clock_gettime_mono(&ts);
1273 tval = convert_timespec_to_timeval(ts);
1275 tdiff = usec_time_diff(&tval, &ldap_state->last_rebind);
1276 tdiff /= 1000; /* Convert to milliseconds. */
1278 sleep_time = lp_ldap_replication_sleep()-(int)tdiff;
1279 sleep_time = MIN(sleep_time, MAX_LDAP_REPLICATION_SLEEP_TIME);
1281 if (sleep_time > 0) {
1282 /* we wait for the LDAP replication */
1283 DEBUG(5,("smbldap_search_ext: waiting %d milliseconds "
1284 "for LDAP replication.\n",sleep_time));
1285 smb_msleep(sleep_time);
1286 DEBUG(5,("smbldap_search_ext: go on!\n"));
1288 ZERO_STRUCT(ldap_state->last_rebind);
1291 if (!push_utf8_talloc(talloc_tos(), &utf8_filter, filter, &converted_size)) {
1292 return LDAP_NO_MEMORY;
1295 /* Setup remote timeout for the ldap_search_ext_s call. */
1297 timeout.tv_sec = to;
1298 timeout.tv_usec = 0;
1299 timeout_ptr = &timeout;
1302 setup_ldap_local_alarm(ldap_state, abs_endtime);
1305 char *ld_error = NULL;
1308 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1309 if (rc != LDAP_SUCCESS) {
1313 rc = ldap_search_ext_s(smbldap_get_ldap(ldap_state),
1316 discard_const_p(char *, attrs),
1317 attrsonly, sctrls, cctrls, timeout_ptr,
1319 if (rc == LDAP_SUCCESS) {
1323 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1325 DEBUG(10, ("Failed search for base: %s, error: %d (%s) "
1326 "(%s)\n", base, ld_errno,
1327 ldap_err2string(rc),
1328 ld_error ? ld_error : "unknown"));
1329 SAFE_FREE(ld_error);
1331 if (ld_errno != LDAP_SERVER_DOWN) {
1334 ldap_unbind(smbldap_get_ldap(ldap_state));
1335 ldap_state->ldap_struct = NULL;
1338 TALLOC_FREE(utf8_filter);
1339 return end_ldap_local_alarm(abs_endtime, rc);
1342 int smbldap_search(struct smbldap_state *ldap_state,
1343 const char *base, int scope, const char *filter,
1344 const char *attrs[], int attrsonly,
1347 return smbldap_search_ext(ldap_state, base, scope, filter, attrs,
1348 attrsonly, NULL, NULL, LDAP_NO_LIMIT, res);
1351 int smbldap_search_paged(struct smbldap_state *ldap_state,
1352 const char *base, int scope, const char *filter,
1353 const char **attrs, int attrsonly, int pagesize,
1354 LDAPMessage **res, void **cookie)
1357 LDAPControl **rcontrols;
1358 LDAPControl *controls[2] = { NULL, NULL};
1359 BerElement *cookie_be = NULL;
1360 struct berval *cookie_bv = NULL;
1362 bool critical = True;
1366 DEBUG(3,("smbldap_search_paged: base => [%s], filter => [%s],"
1367 "scope => [%d], pagesize => [%d]\n",
1368 base, filter, scope, pagesize));
1370 cookie_be = ber_alloc_t(LBER_USE_DER);
1371 if (cookie_be == NULL) {
1372 DEBUG(0,("smbldap_create_page_control: ber_alloc_t returns "
1374 return LDAP_NO_MEMORY;
1377 /* construct cookie */
1378 if (*cookie != NULL) {
1379 ber_printf(cookie_be, "{iO}", (ber_int_t) pagesize, *cookie);
1380 ber_bvfree((struct berval *)*cookie); /* don't need it from last time */
1383 ber_printf(cookie_be, "{io}", (ber_int_t) pagesize, "", 0);
1385 ber_flatten(cookie_be, &cookie_bv);
1387 pr.ldctl_oid = discard_const_p(char, ADS_PAGE_CTL_OID);
1388 pr.ldctl_iscritical = (char) critical;
1389 pr.ldctl_value.bv_len = cookie_bv->bv_len;
1390 pr.ldctl_value.bv_val = cookie_bv->bv_val;
1395 rc = smbldap_search_ext(ldap_state, base, scope, filter, attrs,
1396 0, controls, NULL, LDAP_NO_LIMIT, res);
1398 ber_free(cookie_be, 1);
1399 ber_bvfree(cookie_bv);
1402 DEBUG(3,("smbldap_search_paged: smbldap_search_ext(%s) "
1403 "failed with [%s]\n", filter, ldap_err2string(rc)));
1407 DEBUG(3,("smbldap_search_paged: search was successful\n"));
1409 rc = ldap_parse_result(smbldap_get_ldap(ldap_state), *res, NULL, NULL,
1410 NULL, NULL, &rcontrols, 0);
1412 DEBUG(3,("smbldap_search_paged: ldap_parse_result failed " \
1413 "with [%s]\n", ldap_err2string(rc)));
1417 if (rcontrols == NULL)
1420 for (i=0; rcontrols[i]; i++) {
1422 if (strcmp(ADS_PAGE_CTL_OID, rcontrols[i]->ldctl_oid) != 0)
1425 cookie_be = ber_init(&rcontrols[i]->ldctl_value);
1426 ber_scanf(cookie_be,"{iO}", &tmp, &cookie_bv);
1427 /* the berval is the cookie, but must be freed when it is all
1429 if (cookie_bv->bv_len)
1430 *cookie=ber_bvdup(cookie_bv);
1433 ber_bvfree(cookie_bv);
1434 ber_free(cookie_be, 1);
1437 ldap_controls_free(rcontrols);
1442 int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
1444 int rc = LDAP_SERVER_DOWN;
1446 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1447 size_t converted_size;
1449 SMB_ASSERT(ldap_state);
1451 DEBUG(5,("smbldap_modify: dn => [%s]\n", dn ));
1453 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1454 return LDAP_NO_MEMORY;
1457 setup_ldap_local_alarm(ldap_state, abs_endtime);
1460 char *ld_error = NULL;
1463 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1464 if (rc != LDAP_SUCCESS) {
1468 rc = ldap_modify_s(smbldap_get_ldap(ldap_state), utf8_dn,
1470 if (rc == LDAP_SUCCESS) {
1474 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1476 DEBUG(10, ("Failed to modify dn: %s, error: %d (%s) "
1477 "(%s)\n", dn, ld_errno,
1478 ldap_err2string(rc),
1479 ld_error ? ld_error : "unknown"));
1480 SAFE_FREE(ld_error);
1482 if (ld_errno != LDAP_SERVER_DOWN) {
1485 ldap_unbind(smbldap_get_ldap(ldap_state));
1486 ldap_state->ldap_struct = NULL;
1489 TALLOC_FREE(utf8_dn);
1490 return end_ldap_local_alarm(abs_endtime, rc);
1493 int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
1495 int rc = LDAP_SERVER_DOWN;
1497 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1498 size_t converted_size;
1500 SMB_ASSERT(ldap_state);
1502 DEBUG(5,("smbldap_add: dn => [%s]\n", dn ));
1504 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1505 return LDAP_NO_MEMORY;
1508 setup_ldap_local_alarm(ldap_state, abs_endtime);
1511 char *ld_error = NULL;
1514 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1515 if (rc != LDAP_SUCCESS) {
1519 rc = ldap_add_s(smbldap_get_ldap(ldap_state), utf8_dn, attrs);
1520 if (rc == LDAP_SUCCESS) {
1524 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1526 DEBUG(10, ("Failed to add 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) {
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_delete(struct smbldap_state *ldap_state, const char *dn)
1545 int rc = LDAP_SERVER_DOWN;
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_delete: 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);
1561 char *ld_error = NULL;
1564 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1565 if (rc != LDAP_SUCCESS) {
1569 rc = ldap_delete_s(smbldap_get_ldap(ldap_state), utf8_dn);
1570 if (rc == LDAP_SUCCESS) {
1574 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1576 DEBUG(10, ("Failed to delete 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) {
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_extended_operation(struct smbldap_state *ldap_state,
1594 LDAP_CONST char *reqoid, struct berval *reqdata,
1595 LDAPControl **serverctrls, LDAPControl **clientctrls,
1596 char **retoidp, struct berval **retdatap)
1598 int rc = LDAP_SERVER_DOWN;
1599 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1604 setup_ldap_local_alarm(ldap_state, abs_endtime);
1607 char *ld_error = NULL;
1610 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1611 if (rc != LDAP_SUCCESS) {
1615 rc = ldap_extended_operation_s(smbldap_get_ldap(ldap_state),
1617 reqdata, serverctrls,
1618 clientctrls, retoidp, retdatap);
1619 if (rc == LDAP_SUCCESS) {
1623 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1625 DEBUG(10, ("Extended operation failed with error: "
1626 "%d (%s) (%s)\n", ld_errno,
1627 ldap_err2string(rc),
1628 ld_error ? ld_error : "unknown"));
1629 SAFE_FREE(ld_error);
1631 if (ld_errno != LDAP_SERVER_DOWN) {
1634 ldap_unbind(smbldap_get_ldap(ldap_state));
1635 ldap_state->ldap_struct = NULL;
1638 return end_ldap_local_alarm(abs_endtime, rc);
1641 /*******************************************************************
1642 run the search by name.
1643 ******************************************************************/
1644 int smbldap_search_suffix (struct smbldap_state *ldap_state,
1645 const char *filter, const char **search_attr,
1646 LDAPMessage ** result)
1648 return smbldap_search(ldap_state, lp_ldap_suffix(talloc_tos()),
1650 filter, search_attr, 0, result);
1653 static void smbldap_idle_fn(struct tevent_context *tevent_ctx,
1654 struct tevent_timer *te,
1655 struct timeval now_abs,
1658 struct smbldap_state *state = (struct smbldap_state *)private_data;
1660 TALLOC_FREE(state->idle_event);
1662 if (smbldap_get_ldap(state) == NULL) {
1663 DEBUG(10,("ldap connection not connected...\n"));
1667 if ((state->last_use+SMBLDAP_IDLE_TIME) > time_mono(NULL)) {
1668 DEBUG(10,("ldap connection not idle...\n"));
1670 /* this needs to be made monotonic clock aware inside tevent: */
1671 state->idle_event = tevent_add_timer(
1673 timeval_add(&now_abs, SMBLDAP_IDLE_TIME, 0),
1679 DEBUG(7,("ldap connection idle...closing connection\n"));
1680 smbldap_close(state);
1683 /**********************************************************************
1685 *********************************************************************/
1687 void smbldap_free_struct(struct smbldap_state **ldap_state)
1689 smbldap_close(*ldap_state);
1691 if ((*ldap_state)->bind_secret) {
1692 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
1695 SAFE_FREE((*ldap_state)->bind_dn);
1696 SAFE_FREE((*ldap_state)->bind_secret);
1697 (*ldap_state)->bind_callback = NULL;
1698 (*ldap_state)->bind_callback_data = NULL;
1700 TALLOC_FREE(*ldap_state);
1702 /* No need to free any further, as it is talloc()ed */
1705 static int smbldap_state_destructor(struct smbldap_state *state)
1707 smbldap_free_struct(&state);
1712 /**********************************************************************
1713 Intitalise the 'general' ldap structures, on which ldap operations may be conducted
1714 *********************************************************************/
1716 NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, struct tevent_context *tevent_ctx,
1717 const char *location,
1719 const char *bind_dn,
1720 const char *bind_secret,
1721 struct smbldap_state **smbldap_state)
1723 *smbldap_state = talloc_zero(mem_ctx, struct smbldap_state);
1724 if (!*smbldap_state) {
1725 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
1726 return NT_STATUS_NO_MEMORY;
1730 (*smbldap_state)->uri = talloc_strdup(mem_ctx, location);
1732 (*smbldap_state)->uri = "ldap://localhost";
1735 (*smbldap_state)->tevent_context = tevent_ctx;
1737 if (bind_dn && bind_secret) {
1738 smbldap_set_creds(*smbldap_state, anon, bind_dn, bind_secret);
1741 talloc_set_destructor(*smbldap_state, smbldap_state_destructor);
1742 return NT_STATUS_OK;
1745 char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld,
1748 char *utf8_dn, *unix_dn;
1749 size_t converted_size;
1751 utf8_dn = ldap_get_dn(ld, entry);
1753 DEBUG (5, ("smbldap_talloc_dn: ldap_get_dn failed\n"));
1756 if (!pull_utf8_talloc(mem_ctx, &unix_dn, utf8_dn, &converted_size)) {
1757 DEBUG (0, ("smbldap_talloc_dn: String conversion failure utf8 "
1758 "[%s]\n", utf8_dn));
1761 ldap_memfree(utf8_dn);
1765 /*******************************************************************
1766 Check if root-dse has a certain Control or Extension
1767 ********************************************************************/
1769 static bool smbldap_check_root_dse(LDAP *ld, const char **attrs, const char *value)
1771 LDAPMessage *msg = NULL;
1772 LDAPMessage *entry = NULL;
1773 char **values = NULL;
1774 int rc, num_result, num_values, i;
1775 bool result = False;
1778 DEBUG(3,("smbldap_check_root_dse: nothing to look for\n"));
1782 if (!strequal(attrs[0], "supportedExtension") &&
1783 !strequal(attrs[0], "supportedControl") &&
1784 !strequal(attrs[0], "namingContexts")) {
1785 DEBUG(3,("smbldap_check_root_dse: no idea what to query root-dse for: %s ?\n", attrs[0]));
1789 rc = ldap_search_s(ld, "", LDAP_SCOPE_BASE,
1790 "(objectclass=*)", discard_const_p(char *, attrs), 0 , &msg);
1792 if (rc != LDAP_SUCCESS) {
1793 DEBUG(3,("smbldap_check_root_dse: Could not search rootDSE\n"));
1797 num_result = ldap_count_entries(ld, msg);
1799 if (num_result != 1) {
1800 DEBUG(3,("smbldap_check_root_dse: Expected one rootDSE, got %d\n", num_result));
1804 entry = ldap_first_entry(ld, msg);
1806 if (entry == NULL) {
1807 DEBUG(3,("smbldap_check_root_dse: Could not retrieve rootDSE\n"));
1811 values = ldap_get_values(ld, entry, attrs[0]);
1813 if (values == NULL) {
1814 DEBUG(5,("smbldap_check_root_dse: LDAP Server does not support any %s\n", attrs[0]));
1818 num_values = ldap_count_values(values);
1820 if (num_values == 0) {
1821 DEBUG(5,("smbldap_check_root_dse: LDAP Server does not have any %s\n", attrs[0]));
1825 for (i=0; i<num_values; i++) {
1826 if (strcmp(values[i], value) == 0)
1833 ldap_value_free(values);
1841 /*******************************************************************
1842 Check if LDAP-Server supports a certain Control (OID in string format)
1843 ********************************************************************/
1845 bool smbldap_has_control(LDAP *ld, const char *control)
1847 const char *attrs[] = { "supportedControl", NULL };
1848 return smbldap_check_root_dse(ld, attrs, control);
1851 /*******************************************************************
1852 Check if LDAP-Server supports a certain Extension (OID in string format)
1853 ********************************************************************/
1855 bool smbldap_has_extension(LDAP *ld, const char *extension)
1857 const char *attrs[] = { "supportedExtension", NULL };
1858 return smbldap_check_root_dse(ld, attrs, extension);
1861 /*******************************************************************
1862 Check if LDAP-Server holds a given namingContext
1863 ********************************************************************/
1865 bool smbldap_has_naming_context(LDAP *ld, const char *naming_context)
1867 const char *attrs[] = { "namingContexts", NULL };
1868 return smbldap_check_root_dse(ld, attrs, naming_context);
1871 bool smbldap_set_creds(struct smbldap_state *ldap_state, bool anon, const char *dn, const char *secret)
1873 ldap_state->anonymous = anon;
1875 /* free any previously set credential */
1877 SAFE_FREE(ldap_state->bind_dn);
1878 ldap_state->bind_callback = NULL;
1879 ldap_state->bind_callback_data = NULL;
1881 if (ldap_state->bind_secret) {
1882 /* make sure secrets are zeroed out of memory */
1883 memset(ldap_state->bind_secret, '\0', strlen(ldap_state->bind_secret));
1884 SAFE_FREE(ldap_state->bind_secret);
1888 ldap_state->bind_dn = SMB_STRDUP(dn);
1889 ldap_state->bind_secret = SMB_STRDUP(secret);