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;
44 /*******************************************************************
45 Search an attribute and return the first value found.
46 ******************************************************************/
48 bool smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
49 const char *attribute, char *value,
60 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
61 DEBUG (10, ("smbldap_get_single_attribute: [%s] = [<does not exist>]\n", attribute));
66 if (!convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, max_len, &size)) {
67 DEBUG(1, ("smbldap_get_single_attribute: string conversion of [%s] = [%s] failed!\n",
68 attribute, values[0]));
69 ldap_value_free(values);
73 ldap_value_free(values);
74 #ifdef DEBUG_PASSWORDS
75 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n", attribute, value));
80 char * smbldap_talloc_single_attribute(LDAP *ldap_struct, LDAPMessage *entry,
81 const char *attribute,
86 size_t converted_size;
88 if (attribute == NULL) {
92 values = ldap_get_values(ldap_struct, entry, attribute);
95 DEBUG(10, ("attribute %s does not exist\n", attribute));
99 if (ldap_count_values(values) != 1) {
100 DEBUG(10, ("attribute %s has %d values, expected only one\n",
101 attribute, ldap_count_values(values)));
102 ldap_value_free(values);
106 if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
107 DEBUG(10, ("pull_utf8_talloc failed\n"));
108 ldap_value_free(values);
112 ldap_value_free(values);
114 #ifdef DEBUG_PASSWORDS
115 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
121 char * smbldap_talloc_first_attribute(LDAP *ldap_struct, LDAPMessage *entry,
122 const char *attribute,
127 size_t converted_size;
129 if (attribute == NULL) {
133 values = ldap_get_values(ldap_struct, entry, attribute);
135 if (values == NULL) {
136 DEBUG(10, ("attribute %s does not exist\n", attribute));
140 if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
141 DEBUG(10, ("pull_utf8_talloc failed\n"));
142 ldap_value_free(values);
146 ldap_value_free(values);
148 #ifdef DEBUG_PASSWORDS
149 DEBUG (100, ("smbldap_get_first_attribute: [%s] = [%s]\n",
155 char * smbldap_talloc_smallest_attribute(LDAP *ldap_struct, LDAPMessage *entry,
156 const char *attribute,
161 size_t converted_size;
164 if (attribute == NULL) {
168 values = ldap_get_values(ldap_struct, entry, attribute);
170 if (values == NULL) {
171 DEBUG(10, ("attribute %s does not exist\n", attribute));
175 if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
176 DEBUG(10, ("pull_utf8_talloc failed\n"));
177 ldap_value_free(values);
181 num_values = ldap_count_values(values);
183 for (i=1; i<num_values; i++) {
186 if (!pull_utf8_talloc(mem_ctx, &tmp, values[i],
188 DEBUG(10, ("pull_utf8_talloc failed\n"));
190 ldap_value_free(values);
194 if (strcasecmp_m(tmp, result) < 0) {
202 ldap_value_free(values);
204 #ifdef DEBUG_PASSWORDS
205 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
211 bool smbldap_talloc_single_blob(TALLOC_CTX *mem_ctx, LDAP *ld,
212 LDAPMessage *msg, const char *attrib,
215 struct berval **values;
217 values = ldap_get_values_len(ld, msg, attrib);
222 if (ldap_count_values_len(values) != 1) {
223 DEBUG(10, ("Expected one value for %s, got %d\n", attrib,
224 ldap_count_values_len(values)));
228 *blob = data_blob_talloc(mem_ctx, values[0]->bv_val,
230 ldap_value_free_len(values);
232 return (blob->data != NULL);
235 bool smbldap_pull_sid(LDAP *ld, LDAPMessage *msg, const char *attrib,
241 if (!smbldap_talloc_single_blob(talloc_tos(), ld, msg, attrib,
245 ret = sid_parse(blob.data, blob.length, sid);
246 TALLOC_FREE(blob.data);
250 static int ldapmsg_destructor(LDAPMessage **result) {
251 ldap_msgfree(*result);
255 void smbldap_talloc_autofree_ldapmsg(TALLOC_CTX *mem_ctx, LDAPMessage *result)
257 LDAPMessage **handle;
259 if (result == NULL) {
263 handle = talloc(mem_ctx, LDAPMessage *);
264 SMB_ASSERT(handle != NULL);
267 talloc_set_destructor(handle, ldapmsg_destructor);
270 static int ldapmod_destructor(LDAPMod ***mod) {
271 ldap_mods_free(*mod, True);
275 void smbldap_talloc_autofree_ldapmod(TALLOC_CTX *mem_ctx, LDAPMod **mod)
283 handle = talloc(mem_ctx, LDAPMod **);
284 SMB_ASSERT(handle != NULL);
287 talloc_set_destructor(handle, ldapmod_destructor);
290 /************************************************************************
291 Routine to manage the LDAPMod structure array
292 manage memory used by the array, by each struct, and values
293 ***********************************************************************/
295 static void smbldap_set_mod_internal(LDAPMod *** modlist, int modop, const char *attribute, const char *value, const DATA_BLOB *blob)
303 /* sanity checks on the mod values */
305 if (attribute == NULL || *attribute == '\0') {
309 #if 0 /* commented out after discussion with abartlet. Do not re-enable.
310 left here so other do not re-add similar code --jerry */
311 if (value == NULL || *value == '\0')
316 mods = SMB_MALLOC_P(LDAPMod *);
318 smb_panic("smbldap_set_mod: out of memory!");
324 for (i = 0; mods[i] != NULL; ++i) {
325 if (mods[i]->mod_op == modop && strequal(mods[i]->mod_type, attribute))
329 if (mods[i] == NULL) {
330 mods = SMB_REALLOC_ARRAY (mods, LDAPMod *, i + 2);
332 smb_panic("smbldap_set_mod: out of memory!");
335 mods[i] = SMB_MALLOC_P(LDAPMod);
336 if (mods[i] == NULL) {
337 smb_panic("smbldap_set_mod: out of memory!");
340 mods[i]->mod_op = modop;
341 mods[i]->mod_values = NULL;
342 mods[i]->mod_type = SMB_STRDUP(attribute);
346 if (blob && (modop & LDAP_MOD_BVALUES)) {
348 if (mods[i]->mod_bvalues != NULL) {
349 for (; mods[i]->mod_bvalues[j] != NULL; j++);
351 mods[i]->mod_bvalues = SMB_REALLOC_ARRAY(mods[i]->mod_bvalues, struct berval *, j + 2);
353 if (mods[i]->mod_bvalues == NULL) {
354 smb_panic("smbldap_set_mod: out of memory!");
358 mods[i]->mod_bvalues[j] = SMB_MALLOC_P(struct berval);
359 SMB_ASSERT(mods[i]->mod_bvalues[j] != NULL);
361 mods[i]->mod_bvalues[j]->bv_val = (char *)smb_memdup(blob->data, blob->length);
362 SMB_ASSERT(mods[i]->mod_bvalues[j]->bv_val != NULL);
363 mods[i]->mod_bvalues[j]->bv_len = blob->length;
365 mods[i]->mod_bvalues[j + 1] = NULL;
366 } else if (value != NULL) {
367 char *utf8_value = NULL;
368 size_t converted_size;
371 if (mods[i]->mod_values != NULL) {
372 for (; mods[i]->mod_values[j] != NULL; j++);
374 mods[i]->mod_values = SMB_REALLOC_ARRAY(mods[i]->mod_values, char *, j + 2);
376 if (mods[i]->mod_values == NULL) {
377 smb_panic("smbldap_set_mod: out of memory!");
381 if (!push_utf8_talloc(talloc_tos(), &utf8_value, value, &converted_size)) {
382 smb_panic("smbldap_set_mod: String conversion failure!");
386 mods[i]->mod_values[j] = SMB_STRDUP(utf8_value);
387 TALLOC_FREE(utf8_value);
388 SMB_ASSERT(mods[i]->mod_values[j] != NULL);
390 mods[i]->mod_values[j + 1] = NULL;
395 void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
397 smbldap_set_mod_internal(modlist, modop, attribute, value, NULL);
400 void smbldap_set_mod_blob(LDAPMod *** modlist, int modop, const char *attribute, const DATA_BLOB *value)
402 smbldap_set_mod_internal(modlist, modop | LDAP_MOD_BVALUES, attribute, NULL, value);
405 /**********************************************************************
406 Set attribute to newval in LDAP, regardless of what value the
407 attribute had in LDAP before.
408 *********************************************************************/
410 static void smbldap_make_mod_internal(LDAP *ldap_struct, LDAPMessage *existing,
412 const char *attribute, int op,
414 const DATA_BLOB *newblob)
416 char oldval[2048]; /* current largest allowed value is mungeddial */
418 DATA_BLOB oldblob = data_blob_null;
420 if (existing != NULL) {
421 if (op & LDAP_MOD_BVALUES) {
422 existed = smbldap_talloc_single_blob(talloc_tos(), ldap_struct, existing, attribute, &oldblob);
424 existed = smbldap_get_single_attribute(ldap_struct, existing, attribute, oldval, sizeof(oldval));
433 if (op & LDAP_MOD_BVALUES) {
434 equal = (newblob && (data_blob_cmp(&oldblob, newblob) == 0));
436 /* all of our string attributes are case insensitive */
437 equal = (newval && (strcasecmp_m(oldval, newval) == 0));
441 /* Believe it or not, but LDAP will deny a delete and
442 an add at the same time if the values are the
444 DEBUG(10,("smbldap_make_mod: attribute |%s| not changed.\n", attribute));
448 /* There has been no value before, so don't delete it.
449 * Here's a possible race: We might end up with
450 * duplicate attributes */
451 /* By deleting exactly the value we found in the entry this
452 * should be race-free in the sense that the LDAP-Server will
453 * deny the complete operation if somebody changed the
454 * attribute behind our back. */
455 /* This will also allow modifying single valued attributes
456 * in Novell NDS. In NDS you have to first remove attribute and then
457 * you could add new value */
459 if (op & LDAP_MOD_BVALUES) {
460 DEBUG(10,("smbldap_make_mod: deleting attribute |%s| blob\n", attribute));
461 smbldap_set_mod_blob(mods, LDAP_MOD_DELETE, attribute, &oldblob);
463 DEBUG(10,("smbldap_make_mod: deleting attribute |%s| values |%s|\n", attribute, oldval));
464 smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, oldval);
468 /* Regardless of the real operation (add or modify)
469 we add the new value here. We rely on deleting
470 the old value, should it exist. */
472 if (op & LDAP_MOD_BVALUES) {
473 if (newblob && newblob->length) {
474 DEBUG(10,("smbldap_make_mod: adding attribute |%s| blob\n", attribute));
475 smbldap_set_mod_blob(mods, LDAP_MOD_ADD, attribute, newblob);
478 if ((newval != NULL) && (strlen(newval) > 0)) {
479 DEBUG(10,("smbldap_make_mod: adding attribute |%s| value |%s|\n", attribute, newval));
480 smbldap_set_mod(mods, LDAP_MOD_ADD, attribute, newval);
485 void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing,
487 const char *attribute, const char *newval)
489 smbldap_make_mod_internal(ldap_struct, existing, mods, attribute,
493 void smbldap_make_mod_blob(LDAP *ldap_struct, LDAPMessage *existing,
495 const char *attribute, const DATA_BLOB *newblob)
497 smbldap_make_mod_internal(ldap_struct, existing, mods, attribute,
498 LDAP_MOD_BVALUES, NULL, newblob);
501 /**********************************************************************
502 Some varients of the LDAP rebind code do not pass in the third 'arg'
503 pointer to a void*, so we try and work around it by assuming that the
504 value of the 'LDAP *' pointer is the same as the one we had passed in
505 **********************************************************************/
507 struct smbldap_state_lookup {
509 struct smbldap_state *smbldap_state;
510 struct smbldap_state_lookup *prev, *next;
513 static struct smbldap_state_lookup *smbldap_state_lookup_list;
515 static struct smbldap_state *smbldap_find_state(LDAP *ld)
517 struct smbldap_state_lookup *t;
519 for (t = smbldap_state_lookup_list; t; t = t->next) {
521 return t->smbldap_state;
527 static void smbldap_delete_state(struct smbldap_state *smbldap_state)
529 struct smbldap_state_lookup *t;
531 for (t = smbldap_state_lookup_list; t; t = t->next) {
532 if (t->smbldap_state == smbldap_state) {
533 DLIST_REMOVE(smbldap_state_lookup_list, t);
540 static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state)
542 struct smbldap_state *tmp_ldap_state;
543 struct smbldap_state_lookup *t;
545 if ((tmp_ldap_state = smbldap_find_state(ld))) {
546 SMB_ASSERT(tmp_ldap_state == smbldap_state);
550 t = SMB_XMALLOC_P(struct smbldap_state_lookup);
553 DLIST_ADD_END(smbldap_state_lookup_list, t);
555 t->smbldap_state = smbldap_state;
558 /********************************************************************
559 start TLS on an existing LDAP connection
560 *******************************************************************/
562 int smbldap_start_tls(LDAP *ldap_struct, int version)
564 #ifdef LDAP_OPT_X_TLS
568 if (lp_ldap_ssl() != LDAP_SSL_START_TLS) {
572 #ifdef LDAP_OPT_X_TLS
573 if (version != LDAP_VERSION3) {
574 DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
575 return LDAP_OPERATIONS_ERROR;
578 if ((rc = ldap_start_tls_s (ldap_struct, NULL, NULL)) != LDAP_SUCCESS) {
579 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
580 ldap_err2string(rc)));
584 DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
587 DEBUG(0,("StartTLS not supported by LDAP client libraries!\n"));
588 return LDAP_OPERATIONS_ERROR;
592 /********************************************************************
593 setup a connection to the LDAP server based on a uri
594 *******************************************************************/
596 static int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri)
600 DEBUG(10, ("smb_ldap_setup_connection: %s\n", uri));
602 #ifdef HAVE_LDAP_INITIALIZE
604 rc = ldap_initialize(ldap_struct, uri);
606 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
610 if (lp_ldap_follow_referral() != Auto) {
611 rc = ldap_set_option(*ldap_struct, LDAP_OPT_REFERRALS,
612 lp_ldap_follow_referral() ? LDAP_OPT_ON : LDAP_OPT_OFF);
613 if (rc != LDAP_SUCCESS)
614 DEBUG(0, ("Failed to set LDAP_OPT_REFERRALS: %s\n",
615 ldap_err2string(rc)));
621 /* Parse the string manually */
627 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
630 /* skip leading "URL:" (if any) */
631 if ( strnequal( uri, "URL:", 4 ) ) {
635 sscanf(uri, "%10[^:]://%254[^:/]:%d", protocol, host, &port);
638 if (strequal(protocol, "ldap")) {
640 } else if (strequal(protocol, "ldaps")) {
643 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
647 if ((*ldap_struct = ldap_init(host, port)) == NULL) {
648 DEBUG(0, ("ldap_init failed !\n"));
649 return LDAP_OPERATIONS_ERROR;
652 if (strequal(protocol, "ldaps")) {
653 #ifdef LDAP_OPT_X_TLS
654 int tls = LDAP_OPT_X_TLS_HARD;
655 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
657 DEBUG(0, ("Failed to setup a TLS session\n"));
660 DEBUG(3,("LDAPS option set...!\n"));
662 DEBUG(0,("smbldap_open_connection: Secure connection not supported by LDAP client libraries!\n"));
663 return LDAP_OPERATIONS_ERROR;
664 #endif /* LDAP_OPT_X_TLS */
667 #endif /* HAVE_LDAP_INITIALIZE */
669 /* now set connection timeout */
670 #ifdef LDAP_X_OPT_CONNECT_TIMEOUT /* Netscape */
672 int ct = lp_ldap_connection_timeout()*1000;
673 rc = ldap_set_option(*ldap_struct, LDAP_X_OPT_CONNECT_TIMEOUT, &ct);
674 if (rc != LDAP_SUCCESS) {
675 DEBUG(0,("Failed to setup an ldap connection timeout %d: %s\n",
676 ct, ldap_err2string(rc)));
679 #elif defined (LDAP_OPT_NETWORK_TIMEOUT) /* OpenLDAP */
683 ct.tv_sec = lp_ldap_connection_timeout();
684 rc = ldap_set_option(*ldap_struct, LDAP_OPT_NETWORK_TIMEOUT, &ct);
685 if (rc != LDAP_SUCCESS) {
686 DEBUG(0,("Failed to setup an ldap connection timeout %d: %s\n",
687 (int)ct.tv_sec, ldap_err2string(rc)));
695 /********************************************************************
696 try to upgrade to Version 3 LDAP if not already, in either case return current
698 *******************************************************************/
700 static int smb_ldap_upgrade_conn(LDAP *ldap_struct, int *new_version)
705 /* assume the worst */
706 *new_version = LDAP_VERSION2;
708 rc = ldap_get_option(ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
713 if (version == LDAP_VERSION3) {
714 *new_version = LDAP_VERSION3;
719 version = LDAP_VERSION3;
720 rc = ldap_set_option (ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
725 *new_version = LDAP_VERSION3;
729 /*******************************************************************
730 open a connection to the ldap server (just until the bind)
731 ******************************************************************/
733 int smbldap_setup_full_conn(LDAP **ldap_struct, const char *uri)
737 rc = smb_ldap_setup_conn(ldap_struct, uri);
742 rc = smb_ldap_upgrade_conn(*ldap_struct, &version);
747 rc = smbldap_start_tls(*ldap_struct, version);
755 /*******************************************************************
756 open a connection to the ldap server.
757 ******************************************************************/
758 static int smbldap_open_connection (struct smbldap_state *ldap_state)
761 int rc = LDAP_SUCCESS;
764 LDAP **ldap_struct = &ldap_state->ldap_struct;
766 rc = smb_ldap_setup_conn(ldap_struct, ldap_state->uri);
771 /* Store the LDAP pointer in a lookup list */
773 smbldap_store_state(*ldap_struct, ldap_state);
775 /* Upgrade to LDAPv3 if possible */
777 rc = smb_ldap_upgrade_conn(*ldap_struct, &version);
782 /* Start TLS if required */
784 rc = smbldap_start_tls(*ldap_struct, version);
789 /* Set alias dereferencing method */
790 deref = lp_ldap_deref();
792 if (ldap_set_option (*ldap_struct, LDAP_OPT_DEREF, &deref) != LDAP_OPT_SUCCESS) {
793 DEBUG(1,("smbldap_open_connection: Failed to set dereferencing method: %d\n", deref));
795 DEBUG(5,("Set dereferencing method: %d\n", deref));
799 DEBUG(2, ("smbldap_open_connection: connection opened\n"));
803 /*******************************************************************
804 a rebind function for authenticated referrals
805 This version takes a void* that we can shove useful stuff in :-)
806 ******************************************************************/
807 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
809 static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
810 int *methodp, int freeit, void *arg)
812 struct smbldap_state *ldap_state = arg;
815 /** @TODO Should we be doing something to check what servers we rebind to?
816 Could we get a referral to a machine that we don't want to give our
817 username and password to? */
822 memset(*credp, '\0', strlen(*credp));
826 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
827 ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
829 if (ldap_state->anonymous) {
833 *whop = SMB_STRDUP(ldap_state->bind_dn);
835 return LDAP_NO_MEMORY;
837 *credp = SMB_STRDUP(ldap_state->bind_secret);
840 return LDAP_NO_MEMORY;
843 *methodp = LDAP_AUTH_SIMPLE;
846 clock_gettime_mono(&ts);
847 ldap_state->last_rebind = convert_timespec_to_timeval(ts);
851 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
853 /*******************************************************************
854 a rebind function for authenticated referrals
855 This version takes a void* that we can shove useful stuff in :-)
856 and actually does the connection.
857 ******************************************************************/
858 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
859 static int rebindproc_connect_with_state (LDAP *ldap_struct,
860 LDAP_CONST char *url,
862 ber_int_t msgid, void *arg)
864 struct smbldap_state *ldap_state =
865 (struct smbldap_state *)arg;
870 DEBUG(5,("rebindproc_connect_with_state: Rebinding to %s as \"%s\"\n",
871 url, ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
873 /* call START_TLS again (ldaps:// is handled by the OpenLDAP library
874 * itself) before rebinding to another LDAP server to avoid to expose
875 * our credentials. At least *try* to secure the connection - Guenther */
877 smb_ldap_upgrade_conn(ldap_struct, &version);
878 smbldap_start_tls(ldap_struct, version);
880 /** @TODO Should we be doing something to check what servers we rebind to?
881 Could we get a referral to a machine that we don't want to give our
882 username and password to? */
884 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
886 /* only set the last rebind timestamp when we did rebind after a
887 * non-read LDAP operation. That way we avoid the replication sleep
888 * after a simple redirected search operation - Guenther */
892 case LDAP_REQ_MODIFY:
894 case LDAP_REQ_DELETE:
896 case LDAP_REQ_EXTENDED:
897 DEBUG(10,("rebindproc_connect_with_state: "
898 "setting last_rebind timestamp "
899 "(req: 0x%02x)\n", (unsigned int)request));
900 clock_gettime_mono(&ts);
901 ldap_state->last_rebind = convert_timespec_to_timeval(ts);
904 ZERO_STRUCT(ldap_state->last_rebind);
910 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
912 /*******************************************************************
913 Add a rebind function for authenticated referrals
914 ******************************************************************/
915 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
917 # if LDAP_SET_REBIND_PROC_ARGS == 2
918 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
919 int *method, int freeit )
921 struct smbldap_state *ldap_state = smbldap_find_state(ldap_struct);
923 return rebindproc_with_state(ldap_struct, whop, credp,
924 method, freeit, ldap_state);
926 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
927 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
929 /*******************************************************************
930 a rebind function for authenticated referrals
931 this also does the connection, but no void*.
932 ******************************************************************/
933 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
934 # if LDAP_SET_REBIND_PROC_ARGS == 2
935 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
938 struct smbldap_state *ldap_state = smbldap_find_state(ld);
940 return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid,
943 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
944 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
946 /*******************************************************************
947 connect to the ldap server under system privilege.
948 ******************************************************************/
949 static int smbldap_connect_system(struct smbldap_state *ldap_state)
951 LDAP *ldap_struct = smbldap_get_ldap(ldap_state);
955 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
956 (OpenLDAP) doesn't seem to support it */
958 DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
959 ldap_state->uri, ldap_state->bind_dn));
961 #ifdef HAVE_LDAP_SET_REBIND_PROC
962 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
963 # if LDAP_SET_REBIND_PROC_ARGS == 2
964 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect);
966 # if LDAP_SET_REBIND_PROC_ARGS == 3
967 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);
969 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
970 # if LDAP_SET_REBIND_PROC_ARGS == 2
971 ldap_set_rebind_proc(ldap_struct, &rebindproc);
973 # if LDAP_SET_REBIND_PROC_ARGS == 3
974 ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);
976 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
979 /* When there is an alternative bind callback is set,
980 attempt to use it to perform the bind */
981 if (ldap_state->bind_callback != NULL) {
982 /* We have to allow bind callback to be run under become_root/unbecome_root
983 to make sure within smbd the callback has proper write access to its resources,
984 like credential cache. This is similar to passdb case where this callback is supposed
985 to be used. When used outside smbd, become_root()/unbecome_root() are no-op.
988 rc = ldap_state->bind_callback(ldap_struct, ldap_state, ldap_state->bind_callback_data);
991 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
994 if (rc != LDAP_SUCCESS) {
995 char *ld_error = NULL;
996 ldap_get_option(smbldap_get_ldap(ldap_state),
997 LDAP_OPT_ERROR_STRING,
999 DEBUG(ldap_state->num_failures ? 2 : 0,
1000 ("failed to bind to server %s with dn=\"%s\" Error: %s\n\t%s\n",
1002 ldap_state->bind_dn ? ldap_state->bind_dn : "[Anonymous bind]",
1003 ldap_err2string(rc),
1004 ld_error ? ld_error : "(unknown)"));
1005 SAFE_FREE(ld_error);
1006 ldap_state->num_failures++;
1010 ldap_state->num_failures = 0;
1011 ldap_state->paged_results = False;
1013 ldap_get_option(smbldap_get_ldap(ldap_state),
1014 LDAP_OPT_PROTOCOL_VERSION, &version);
1016 if (smbldap_has_control(smbldap_get_ldap(ldap_state), ADS_PAGE_CTL_OID)
1018 ldap_state->paged_results = True;
1021 DEBUG(3, ("ldap_connect_system: successful connection to the LDAP server\n"));
1022 DEBUGADD(10, ("ldap_connect_system: LDAP server %s support paged results\n",
1023 ldap_state->paged_results ? "does" : "does not"));
1026 ldap_unbind(ldap_struct);
1027 ldap_state->ldap_struct = NULL;
1032 static void smbldap_idle_fn(struct tevent_context *tevent_ctx,
1033 struct tevent_timer *te,
1034 struct timeval now_abs,
1035 void *private_data);
1037 /**********************************************************************
1038 Connect to LDAP server (called before every ldap operation)
1039 *********************************************************************/
1040 static int smbldap_open(struct smbldap_state *ldap_state)
1043 bool reopen = False;
1044 SMB_ASSERT(ldap_state);
1046 if ((smbldap_get_ldap(ldap_state) != NULL) &&
1047 ((ldap_state->last_ping + SMBLDAP_DONT_PING_TIME) <
1050 #ifdef HAVE_UNIXSOCKET
1051 struct sockaddr_un addr;
1053 struct sockaddr_storage addr;
1055 socklen_t len = sizeof(addr);
1058 opt_rc = ldap_get_option(smbldap_get_ldap(ldap_state),
1059 LDAP_OPT_DESC, &sd);
1060 if (opt_rc == 0 && (getpeername(sd, (struct sockaddr *) &addr, &len)) < 0 )
1063 #ifdef HAVE_UNIXSOCKET
1064 if (opt_rc == 0 && addr.sun_family == AF_UNIX)
1068 /* the other end has died. reopen. */
1069 ldap_unbind(smbldap_get_ldap(ldap_state));
1070 ldap_state->ldap_struct = NULL;
1071 ldap_state->last_ping = (time_t)0;
1073 ldap_state->last_ping = time_mono(NULL);
1077 if (smbldap_get_ldap(ldap_state) != NULL) {
1078 DEBUG(11,("smbldap_open: already connected to the LDAP server\n"));
1079 return LDAP_SUCCESS;
1082 if ((rc = smbldap_open_connection(ldap_state))) {
1086 if ((rc = smbldap_connect_system(ldap_state))) {
1091 ldap_state->last_ping = time_mono(NULL);
1092 ldap_state->pid = getpid();
1094 TALLOC_FREE(ldap_state->idle_event);
1096 if (ldap_state->tevent_context != NULL) {
1097 ldap_state->idle_event = tevent_add_timer(
1098 ldap_state->tevent_context, ldap_state,
1099 timeval_current_ofs(SMBLDAP_IDLE_TIME, 0),
1100 smbldap_idle_fn, ldap_state);
1103 DEBUG(4,("The LDAP server is successfully connected\n"));
1105 return LDAP_SUCCESS;
1108 /**********************************************************************
1109 Disconnect from LDAP server
1110 *********************************************************************/
1111 static NTSTATUS smbldap_close(struct smbldap_state *ldap_state)
1114 return NT_STATUS_INVALID_PARAMETER;
1116 if (smbldap_get_ldap(ldap_state) != NULL) {
1117 ldap_unbind(smbldap_get_ldap(ldap_state));
1118 ldap_state->ldap_struct = NULL;
1121 smbldap_delete_state(ldap_state);
1123 TALLOC_FREE(ldap_state->idle_event);
1125 DEBUG(5,("The connection to the LDAP server was closed\n"));
1126 /* maybe free the results here --metze */
1128 return NT_STATUS_OK;
1131 static SIG_ATOMIC_T got_alarm;
1133 static void gotalarm_sig(int dummy)
1138 static time_t calc_ldap_abs_endtime(int ldap_to)
1141 /* No timeout - don't
1147 /* Make the alarm time one second beyond
1148 the timout we're setting for the
1149 remote search timeout, to allow that
1150 to fire in preference. */
1152 return time_mono(NULL)+ldap_to+1;
1155 static int end_ldap_local_alarm(time_t absolute_endtime, int rc)
1157 if (absolute_endtime) {
1159 CatchSignal(SIGALRM, SIG_IGN);
1161 /* Client timeout error code. */
1163 return LDAP_TIMEOUT;
1169 static void setup_ldap_local_alarm(struct smbldap_state *ldap_state, time_t absolute_endtime)
1171 time_t now = time_mono(NULL);
1173 if (absolute_endtime) {
1175 CatchSignal(SIGALRM, gotalarm_sig);
1176 alarm(absolute_endtime - now);
1179 if (ldap_state->pid != getpid()) {
1180 smbldap_close(ldap_state);
1184 static void get_ldap_errs(struct smbldap_state *ldap_state, char **pp_ld_error, int *p_ld_errno)
1186 ldap_get_option(smbldap_get_ldap(ldap_state),
1187 LDAP_OPT_ERROR_NUMBER, p_ld_errno);
1189 ldap_get_option(smbldap_get_ldap(ldap_state),
1190 LDAP_OPT_ERROR_STRING, pp_ld_error);
1193 static int get_cached_ldap_connect(struct smbldap_state *ldap_state, time_t abs_endtime)
1201 now = time_mono(NULL);
1202 ldap_state->last_use = now;
1204 if (abs_endtime && now > abs_endtime) {
1205 smbldap_close(ldap_state);
1206 return LDAP_TIMEOUT;
1209 rc = smbldap_open(ldap_state);
1211 if (rc == LDAP_SUCCESS) {
1212 return LDAP_SUCCESS;
1216 DEBUG(1, ("Connection to LDAP server failed for the "
1217 "%d try!\n", attempts));
1219 if (rc == LDAP_INSUFFICIENT_ACCESS) {
1220 /* The fact that we are non-root or any other
1221 * access-denied condition will not change in the next
1222 * round of trying */
1227 smbldap_close(ldap_state);
1228 return LDAP_TIMEOUT;
1234 smbldap_close(ldap_state);
1235 return LDAP_TIMEOUT;
1240 /*********************************************************************
1241 ********************************************************************/
1243 static int smbldap_search_ext(struct smbldap_state *ldap_state,
1244 const char *base, int scope, const char *filter,
1245 const char *attrs[], int attrsonly,
1246 LDAPControl **sctrls, LDAPControl **cctrls,
1247 int sizelimit, LDAPMessage **res)
1249 int rc = LDAP_SERVER_DOWN;
1251 int to = lp_ldap_timeout();
1252 time_t abs_endtime = calc_ldap_abs_endtime(to);
1253 struct timeval timeout;
1254 struct timeval *timeout_ptr = NULL;
1255 size_t converted_size;
1257 SMB_ASSERT(ldap_state);
1259 DEBUG(5,("smbldap_search_ext: base => [%s], filter => [%s], "
1260 "scope => [%d]\n", base, filter, scope));
1262 if (ldap_state->last_rebind.tv_sec > 0) {
1263 struct timeval tval;
1268 clock_gettime_mono(&ts);
1269 tval = convert_timespec_to_timeval(ts);
1271 tdiff = usec_time_diff(&tval, &ldap_state->last_rebind);
1272 tdiff /= 1000; /* Convert to milliseconds. */
1274 sleep_time = lp_ldap_replication_sleep()-(int)tdiff;
1275 sleep_time = MIN(sleep_time, MAX_LDAP_REPLICATION_SLEEP_TIME);
1277 if (sleep_time > 0) {
1278 /* we wait for the LDAP replication */
1279 DEBUG(5,("smbldap_search_ext: waiting %d milliseconds "
1280 "for LDAP replication.\n",sleep_time));
1281 smb_msleep(sleep_time);
1282 DEBUG(5,("smbldap_search_ext: go on!\n"));
1284 ZERO_STRUCT(ldap_state->last_rebind);
1287 if (!push_utf8_talloc(talloc_tos(), &utf8_filter, filter, &converted_size)) {
1288 return LDAP_NO_MEMORY;
1291 /* Setup remote timeout for the ldap_search_ext_s call. */
1293 timeout.tv_sec = to;
1294 timeout.tv_usec = 0;
1295 timeout_ptr = &timeout;
1298 setup_ldap_local_alarm(ldap_state, abs_endtime);
1301 char *ld_error = NULL;
1304 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1305 if (rc != LDAP_SUCCESS) {
1309 rc = ldap_search_ext_s(smbldap_get_ldap(ldap_state),
1312 discard_const_p(char *, attrs),
1313 attrsonly, sctrls, cctrls, timeout_ptr,
1315 if (rc == LDAP_SUCCESS) {
1319 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1321 DEBUG(10, ("Failed search for base: %s, error: %d (%s) "
1322 "(%s)\n", base, ld_errno,
1323 ldap_err2string(rc),
1324 ld_error ? ld_error : "unknown"));
1325 SAFE_FREE(ld_error);
1327 if (ld_errno != LDAP_SERVER_DOWN) {
1330 ldap_unbind(smbldap_get_ldap(ldap_state));
1331 ldap_state->ldap_struct = NULL;
1334 TALLOC_FREE(utf8_filter);
1335 return end_ldap_local_alarm(abs_endtime, rc);
1338 int smbldap_search(struct smbldap_state *ldap_state,
1339 const char *base, int scope, const char *filter,
1340 const char *attrs[], int attrsonly,
1343 return smbldap_search_ext(ldap_state, base, scope, filter, attrs,
1344 attrsonly, NULL, NULL, LDAP_NO_LIMIT, res);
1347 int smbldap_search_paged(struct smbldap_state *ldap_state,
1348 const char *base, int scope, const char *filter,
1349 const char **attrs, int attrsonly, int pagesize,
1350 LDAPMessage **res, void **cookie)
1353 LDAPControl **rcontrols;
1354 LDAPControl *controls[2] = { NULL, NULL};
1355 BerElement *cookie_be = NULL;
1356 struct berval *cookie_bv = NULL;
1358 bool critical = True;
1362 DEBUG(3,("smbldap_search_paged: base => [%s], filter => [%s],"
1363 "scope => [%d], pagesize => [%d]\n",
1364 base, filter, scope, pagesize));
1366 cookie_be = ber_alloc_t(LBER_USE_DER);
1367 if (cookie_be == NULL) {
1368 DEBUG(0,("smbldap_create_page_control: ber_alloc_t returns "
1370 return LDAP_NO_MEMORY;
1373 /* construct cookie */
1374 if (*cookie != NULL) {
1375 ber_printf(cookie_be, "{iO}", (ber_int_t) pagesize, *cookie);
1376 ber_bvfree((struct berval *)*cookie); /* don't need it from last time */
1379 ber_printf(cookie_be, "{io}", (ber_int_t) pagesize, "", 0);
1381 ber_flatten(cookie_be, &cookie_bv);
1383 pr.ldctl_oid = discard_const_p(char, ADS_PAGE_CTL_OID);
1384 pr.ldctl_iscritical = (char) critical;
1385 pr.ldctl_value.bv_len = cookie_bv->bv_len;
1386 pr.ldctl_value.bv_val = cookie_bv->bv_val;
1391 rc = smbldap_search_ext(ldap_state, base, scope, filter, attrs,
1392 0, controls, NULL, LDAP_NO_LIMIT, res);
1394 ber_free(cookie_be, 1);
1395 ber_bvfree(cookie_bv);
1398 DEBUG(3,("smbldap_search_paged: smbldap_search_ext(%s) "
1399 "failed with [%s]\n", filter, ldap_err2string(rc)));
1403 DEBUG(3,("smbldap_search_paged: search was successful\n"));
1405 rc = ldap_parse_result(smbldap_get_ldap(ldap_state), *res, NULL, NULL,
1406 NULL, NULL, &rcontrols, 0);
1408 DEBUG(3,("smbldap_search_paged: ldap_parse_result failed " \
1409 "with [%s]\n", ldap_err2string(rc)));
1413 if (rcontrols == NULL)
1416 for (i=0; rcontrols[i]; i++) {
1418 if (strcmp(ADS_PAGE_CTL_OID, rcontrols[i]->ldctl_oid) != 0)
1421 cookie_be = ber_init(&rcontrols[i]->ldctl_value);
1422 ber_scanf(cookie_be,"{iO}", &tmp, &cookie_bv);
1423 /* the berval is the cookie, but must be freed when it is all
1425 if (cookie_bv->bv_len)
1426 *cookie=ber_bvdup(cookie_bv);
1429 ber_bvfree(cookie_bv);
1430 ber_free(cookie_be, 1);
1433 ldap_controls_free(rcontrols);
1438 int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
1440 int rc = LDAP_SERVER_DOWN;
1442 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1443 size_t converted_size;
1445 SMB_ASSERT(ldap_state);
1447 DEBUG(5,("smbldap_modify: dn => [%s]\n", dn ));
1449 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1450 return LDAP_NO_MEMORY;
1453 setup_ldap_local_alarm(ldap_state, abs_endtime);
1456 char *ld_error = NULL;
1459 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1460 if (rc != LDAP_SUCCESS) {
1464 rc = ldap_modify_s(smbldap_get_ldap(ldap_state), utf8_dn,
1466 if (rc == LDAP_SUCCESS) {
1470 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1472 DEBUG(10, ("Failed to modify dn: %s, error: %d (%s) "
1473 "(%s)\n", dn, ld_errno,
1474 ldap_err2string(rc),
1475 ld_error ? ld_error : "unknown"));
1476 SAFE_FREE(ld_error);
1478 if (ld_errno != LDAP_SERVER_DOWN) {
1481 ldap_unbind(smbldap_get_ldap(ldap_state));
1482 ldap_state->ldap_struct = NULL;
1485 TALLOC_FREE(utf8_dn);
1486 return end_ldap_local_alarm(abs_endtime, rc);
1489 int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
1491 int rc = LDAP_SERVER_DOWN;
1493 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1494 size_t converted_size;
1496 SMB_ASSERT(ldap_state);
1498 DEBUG(5,("smbldap_add: dn => [%s]\n", dn ));
1500 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1501 return LDAP_NO_MEMORY;
1504 setup_ldap_local_alarm(ldap_state, abs_endtime);
1507 char *ld_error = NULL;
1510 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1511 if (rc != LDAP_SUCCESS) {
1515 rc = ldap_add_s(smbldap_get_ldap(ldap_state), utf8_dn, attrs);
1516 if (rc == LDAP_SUCCESS) {
1520 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1522 DEBUG(10, ("Failed to add dn: %s, error: %d (%s) "
1523 "(%s)\n", dn, ld_errno,
1524 ldap_err2string(rc),
1525 ld_error ? ld_error : "unknown"));
1526 SAFE_FREE(ld_error);
1528 if (ld_errno != LDAP_SERVER_DOWN) {
1531 ldap_unbind(smbldap_get_ldap(ldap_state));
1532 ldap_state->ldap_struct = NULL;
1535 TALLOC_FREE(utf8_dn);
1536 return end_ldap_local_alarm(abs_endtime, rc);
1539 int smbldap_delete(struct smbldap_state *ldap_state, const char *dn)
1541 int rc = LDAP_SERVER_DOWN;
1543 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1544 size_t converted_size;
1546 SMB_ASSERT(ldap_state);
1548 DEBUG(5,("smbldap_delete: dn => [%s]\n", dn ));
1550 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1551 return LDAP_NO_MEMORY;
1554 setup_ldap_local_alarm(ldap_state, abs_endtime);
1557 char *ld_error = NULL;
1560 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1561 if (rc != LDAP_SUCCESS) {
1565 rc = ldap_delete_s(smbldap_get_ldap(ldap_state), utf8_dn);
1566 if (rc == LDAP_SUCCESS) {
1570 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1572 DEBUG(10, ("Failed to delete dn: %s, error: %d (%s) "
1573 "(%s)\n", dn, ld_errno,
1574 ldap_err2string(rc),
1575 ld_error ? ld_error : "unknown"));
1576 SAFE_FREE(ld_error);
1578 if (ld_errno != LDAP_SERVER_DOWN) {
1581 ldap_unbind(smbldap_get_ldap(ldap_state));
1582 ldap_state->ldap_struct = NULL;
1585 TALLOC_FREE(utf8_dn);
1586 return end_ldap_local_alarm(abs_endtime, rc);
1589 int smbldap_extended_operation(struct smbldap_state *ldap_state,
1590 LDAP_CONST char *reqoid, struct berval *reqdata,
1591 LDAPControl **serverctrls, LDAPControl **clientctrls,
1592 char **retoidp, struct berval **retdatap)
1594 int rc = LDAP_SERVER_DOWN;
1595 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1600 setup_ldap_local_alarm(ldap_state, abs_endtime);
1603 char *ld_error = NULL;
1606 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1607 if (rc != LDAP_SUCCESS) {
1611 rc = ldap_extended_operation_s(smbldap_get_ldap(ldap_state),
1613 reqdata, serverctrls,
1614 clientctrls, retoidp, retdatap);
1615 if (rc == LDAP_SUCCESS) {
1619 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1621 DEBUG(10, ("Extended operation failed with error: "
1622 "%d (%s) (%s)\n", ld_errno,
1623 ldap_err2string(rc),
1624 ld_error ? ld_error : "unknown"));
1625 SAFE_FREE(ld_error);
1627 if (ld_errno != LDAP_SERVER_DOWN) {
1630 ldap_unbind(smbldap_get_ldap(ldap_state));
1631 ldap_state->ldap_struct = NULL;
1634 return end_ldap_local_alarm(abs_endtime, rc);
1637 /*******************************************************************
1638 run the search by name.
1639 ******************************************************************/
1640 int smbldap_search_suffix (struct smbldap_state *ldap_state,
1641 const char *filter, const char **search_attr,
1642 LDAPMessage ** result)
1644 return smbldap_search(ldap_state, lp_ldap_suffix(talloc_tos()),
1646 filter, search_attr, 0, result);
1649 static void smbldap_idle_fn(struct tevent_context *tevent_ctx,
1650 struct tevent_timer *te,
1651 struct timeval now_abs,
1654 struct smbldap_state *state = (struct smbldap_state *)private_data;
1656 TALLOC_FREE(state->idle_event);
1658 if (smbldap_get_ldap(state) == NULL) {
1659 DEBUG(10,("ldap connection not connected...\n"));
1663 if ((state->last_use+SMBLDAP_IDLE_TIME) > time_mono(NULL)) {
1664 DEBUG(10,("ldap connection not idle...\n"));
1666 /* this needs to be made monotonic clock aware inside tevent: */
1667 state->idle_event = tevent_add_timer(
1669 timeval_add(&now_abs, SMBLDAP_IDLE_TIME, 0),
1675 DEBUG(7,("ldap connection idle...closing connection\n"));
1676 smbldap_close(state);
1679 /**********************************************************************
1681 *********************************************************************/
1683 void smbldap_free_struct(struct smbldap_state **ldap_state)
1685 smbldap_close(*ldap_state);
1687 if ((*ldap_state)->bind_secret) {
1688 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
1691 SAFE_FREE((*ldap_state)->bind_dn);
1692 SAFE_FREE((*ldap_state)->bind_secret);
1693 (*ldap_state)->bind_callback = NULL;
1694 (*ldap_state)->bind_callback_data = NULL;
1696 TALLOC_FREE(*ldap_state);
1698 /* No need to free any further, as it is talloc()ed */
1701 static int smbldap_state_destructor(struct smbldap_state *state)
1703 smbldap_free_struct(&state);
1708 /**********************************************************************
1709 Intitalise the 'general' ldap structures, on which ldap operations may be conducted
1710 *********************************************************************/
1712 NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, struct tevent_context *tevent_ctx,
1713 const char *location,
1715 const char *bind_dn,
1716 const char *bind_secret,
1717 struct smbldap_state **smbldap_state)
1719 *smbldap_state = talloc_zero(mem_ctx, struct smbldap_state);
1720 if (!*smbldap_state) {
1721 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
1722 return NT_STATUS_NO_MEMORY;
1726 (*smbldap_state)->uri = talloc_strdup(mem_ctx, location);
1728 (*smbldap_state)->uri = "ldap://localhost";
1731 (*smbldap_state)->tevent_context = tevent_ctx;
1733 if (bind_dn && bind_secret) {
1734 smbldap_set_creds(*smbldap_state, anon, bind_dn, bind_secret);
1737 talloc_set_destructor(*smbldap_state, smbldap_state_destructor);
1738 return NT_STATUS_OK;
1741 char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld,
1744 char *utf8_dn, *unix_dn;
1745 size_t converted_size;
1747 utf8_dn = ldap_get_dn(ld, entry);
1749 DEBUG (5, ("smbldap_talloc_dn: ldap_get_dn failed\n"));
1752 if (!pull_utf8_talloc(mem_ctx, &unix_dn, utf8_dn, &converted_size)) {
1753 DEBUG (0, ("smbldap_talloc_dn: String conversion failure utf8 "
1754 "[%s]\n", utf8_dn));
1757 ldap_memfree(utf8_dn);
1761 /*******************************************************************
1762 Check if root-dse has a certain Control or Extension
1763 ********************************************************************/
1765 static bool smbldap_check_root_dse(LDAP *ld, const char **attrs, const char *value)
1767 LDAPMessage *msg = NULL;
1768 LDAPMessage *entry = NULL;
1769 char **values = NULL;
1770 int rc, num_result, num_values, i;
1771 bool result = False;
1774 DEBUG(3,("smbldap_check_root_dse: nothing to look for\n"));
1778 if (!strequal(attrs[0], "supportedExtension") &&
1779 !strequal(attrs[0], "supportedControl") &&
1780 !strequal(attrs[0], "namingContexts")) {
1781 DEBUG(3,("smbldap_check_root_dse: no idea what to query root-dse for: %s ?\n", attrs[0]));
1785 rc = ldap_search_s(ld, "", LDAP_SCOPE_BASE,
1786 "(objectclass=*)", discard_const_p(char *, attrs), 0 , &msg);
1788 if (rc != LDAP_SUCCESS) {
1789 DEBUG(3,("smbldap_check_root_dse: Could not search rootDSE\n"));
1793 num_result = ldap_count_entries(ld, msg);
1795 if (num_result != 1) {
1796 DEBUG(3,("smbldap_check_root_dse: Expected one rootDSE, got %d\n", num_result));
1800 entry = ldap_first_entry(ld, msg);
1802 if (entry == NULL) {
1803 DEBUG(3,("smbldap_check_root_dse: Could not retrieve rootDSE\n"));
1807 values = ldap_get_values(ld, entry, attrs[0]);
1809 if (values == NULL) {
1810 DEBUG(5,("smbldap_check_root_dse: LDAP Server does not support any %s\n", attrs[0]));
1814 num_values = ldap_count_values(values);
1816 if (num_values == 0) {
1817 DEBUG(5,("smbldap_check_root_dse: LDAP Server does not have any %s\n", attrs[0]));
1821 for (i=0; i<num_values; i++) {
1822 if (strcmp(values[i], value) == 0)
1829 ldap_value_free(values);
1837 /*******************************************************************
1838 Check if LDAP-Server supports a certain Control (OID in string format)
1839 ********************************************************************/
1841 bool smbldap_has_control(LDAP *ld, const char *control)
1843 const char *attrs[] = { "supportedControl", NULL };
1844 return smbldap_check_root_dse(ld, attrs, control);
1847 /*******************************************************************
1848 Check if LDAP-Server supports a certain Extension (OID in string format)
1849 ********************************************************************/
1851 bool smbldap_has_extension(LDAP *ld, const char *extension)
1853 const char *attrs[] = { "supportedExtension", NULL };
1854 return smbldap_check_root_dse(ld, attrs, extension);
1857 /*******************************************************************
1858 Check if LDAP-Server holds a given namingContext
1859 ********************************************************************/
1861 bool smbldap_has_naming_context(LDAP *ld, const char *naming_context)
1863 const char *attrs[] = { "namingContexts", NULL };
1864 return smbldap_check_root_dse(ld, attrs, naming_context);
1867 bool smbldap_set_creds(struct smbldap_state *ldap_state, bool anon, const char *dn, const char *secret)
1869 ldap_state->anonymous = anon;
1871 /* free any previously set credential */
1873 SAFE_FREE(ldap_state->bind_dn);
1874 ldap_state->bind_callback = NULL;
1875 ldap_state->bind_callback_data = NULL;
1877 if (ldap_state->bind_secret) {
1878 /* make sure secrets are zeroed out of memory */
1879 memset(ldap_state->bind_secret, '\0', strlen(ldap_state->bind_secret));
1880 SAFE_FREE(ldap_state->bind_secret);
1884 ldap_state->bind_dn = SMB_STRDUP(dn);
1885 ldap_state->bind_secret = SMB_STRDUP(secret);