s3: Add vfs_aio_posix
[Samba/gebeck_regimport.git] / source3 / lib / smbldap.c
blob85a9ac557f94b5e56ccdea151f3fdfe56af78d1d
1 /*
2 Unix SMB/CIFS implementation.
3 LDAP protocol helper functions for SAMBA
4 Copyright (C) Jean François Micouleau 1998
5 Copyright (C) Gerald Carter 2001-2003
6 Copyright (C) Shahms King 2001
7 Copyright (C) Andrew Bartlett 2002-2003
8 Copyright (C) Stefan (metze) Metzmacher 2002-2003
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "smbldap.h"
27 #include "../libcli/security/security.h"
28 #include <tevent.h>
30 /* Try not to hit the up or down server forever */
32 #define SMBLDAP_DONT_PING_TIME 10 /* ping only all 10 seconds */
33 #define SMBLDAP_NUM_RETRIES 8 /* retry only 8 times */
35 #define SMBLDAP_IDLE_TIME 150 /* After 2.5 minutes disconnect */
38 /*******************************************************************
39 Search an attribute and return the first value found.
40 ******************************************************************/
42 bool smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
43 const char *attribute, char *value,
44 int max_len)
46 char **values;
47 size_t size = 0;
49 if ( !attribute )
50 return False;
52 value[0] = '\0';
54 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
55 DEBUG (10, ("smbldap_get_single_attribute: [%s] = [<does not exist>]\n", attribute));
57 return False;
60 if (!convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, max_len, &size)) {
61 DEBUG(1, ("smbldap_get_single_attribute: string conversion of [%s] = [%s] failed!\n",
62 attribute, values[0]));
63 ldap_value_free(values);
64 return False;
67 ldap_value_free(values);
68 #ifdef DEBUG_PASSWORDS
69 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n", attribute, value));
70 #endif
71 return True;
74 char * smbldap_talloc_single_attribute(LDAP *ldap_struct, LDAPMessage *entry,
75 const char *attribute,
76 TALLOC_CTX *mem_ctx)
78 char **values;
79 char *result;
80 size_t converted_size;
82 if (attribute == NULL) {
83 return NULL;
86 values = ldap_get_values(ldap_struct, entry, attribute);
88 if (values == NULL) {
89 DEBUG(10, ("attribute %s does not exist\n", attribute));
90 return NULL;
93 if (ldap_count_values(values) != 1) {
94 DEBUG(10, ("attribute %s has %d values, expected only one\n",
95 attribute, ldap_count_values(values)));
96 ldap_value_free(values);
97 return NULL;
100 if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
101 DEBUG(10, ("pull_utf8_talloc failed\n"));
102 ldap_value_free(values);
103 return NULL;
106 ldap_value_free(values);
108 #ifdef DEBUG_PASSWORDS
109 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
110 attribute, result));
111 #endif
112 return result;
115 char * smbldap_talloc_first_attribute(LDAP *ldap_struct, LDAPMessage *entry,
116 const char *attribute,
117 TALLOC_CTX *mem_ctx)
119 char **values;
120 char *result;
121 size_t converted_size;
123 if (attribute == NULL) {
124 return NULL;
127 values = ldap_get_values(ldap_struct, entry, attribute);
129 if (values == NULL) {
130 DEBUG(10, ("attribute %s does not exist\n", attribute));
131 return NULL;
134 if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
135 DEBUG(10, ("pull_utf8_talloc failed\n"));
136 ldap_value_free(values);
137 return NULL;
140 ldap_value_free(values);
142 #ifdef DEBUG_PASSWORDS
143 DEBUG (100, ("smbldap_get_first_attribute: [%s] = [%s]\n",
144 attribute, result));
145 #endif
146 return result;
149 char * smbldap_talloc_smallest_attribute(LDAP *ldap_struct, LDAPMessage *entry,
150 const char *attribute,
151 TALLOC_CTX *mem_ctx)
153 char **values;
154 char *result;
155 size_t converted_size;
156 int i, num_values;
158 if (attribute == NULL) {
159 return NULL;
162 values = ldap_get_values(ldap_struct, entry, attribute);
164 if (values == NULL) {
165 DEBUG(10, ("attribute %s does not exist\n", attribute));
166 return NULL;
169 if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
170 DEBUG(10, ("pull_utf8_talloc failed\n"));
171 ldap_value_free(values);
172 return NULL;
175 num_values = ldap_count_values(values);
177 for (i=1; i<num_values; i++) {
178 char *tmp;
180 if (!pull_utf8_talloc(mem_ctx, &tmp, values[i],
181 &converted_size)) {
182 DEBUG(10, ("pull_utf8_talloc failed\n"));
183 TALLOC_FREE(result);
184 ldap_value_free(values);
185 return NULL;
188 if (strcasecmp_m(tmp, result) < 0) {
189 TALLOC_FREE(result);
190 result = tmp;
191 } else {
192 TALLOC_FREE(tmp);
196 ldap_value_free(values);
198 #ifdef DEBUG_PASSWORDS
199 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
200 attribute, result));
201 #endif
202 return result;
205 bool smbldap_talloc_single_blob(TALLOC_CTX *mem_ctx, LDAP *ld,
206 LDAPMessage *msg, const char *attrib,
207 DATA_BLOB *blob)
209 struct berval **values;
211 values = ldap_get_values_len(ld, msg, attrib);
212 if (!values) {
213 return false;
216 if (ldap_count_values_len(values) != 1) {
217 DEBUG(10, ("Expected one value for %s, got %d\n", attrib,
218 ldap_count_values_len(values)));
219 return false;
222 *blob = data_blob_talloc(mem_ctx, values[0]->bv_val,
223 values[0]->bv_len);
224 ldap_value_free_len(values);
226 return (blob->data != NULL);
229 bool smbldap_pull_sid(LDAP *ld, LDAPMessage *msg, const char *attrib,
230 struct dom_sid *sid)
232 DATA_BLOB blob;
233 bool ret;
235 if (!smbldap_talloc_single_blob(talloc_tos(), ld, msg, attrib,
236 &blob)) {
237 return false;
239 ret = sid_parse((char *)blob.data, blob.length, sid);
240 TALLOC_FREE(blob.data);
241 return ret;
244 static int ldapmsg_destructor(LDAPMessage **result) {
245 ldap_msgfree(*result);
246 return 0;
249 void talloc_autofree_ldapmsg(TALLOC_CTX *mem_ctx, LDAPMessage *result)
251 LDAPMessage **handle;
253 if (result == NULL) {
254 return;
257 handle = talloc(mem_ctx, LDAPMessage *);
258 SMB_ASSERT(handle != NULL);
260 *handle = result;
261 talloc_set_destructor(handle, ldapmsg_destructor);
264 static int ldapmod_destructor(LDAPMod ***mod) {
265 ldap_mods_free(*mod, True);
266 return 0;
269 void talloc_autofree_ldapmod(TALLOC_CTX *mem_ctx, LDAPMod **mod)
271 LDAPMod ***handle;
273 if (mod == NULL) {
274 return;
277 handle = talloc(mem_ctx, LDAPMod **);
278 SMB_ASSERT(handle != NULL);
280 *handle = mod;
281 talloc_set_destructor(handle, ldapmod_destructor);
284 /************************************************************************
285 Routine to manage the LDAPMod structure array
286 manage memory used by the array, by each struct, and values
287 ***********************************************************************/
289 static void smbldap_set_mod_internal(LDAPMod *** modlist, int modop, const char *attribute, const char *value, const DATA_BLOB *blob)
291 LDAPMod **mods;
292 int i;
293 int j;
295 mods = *modlist;
297 /* sanity checks on the mod values */
299 if (attribute == NULL || *attribute == '\0') {
300 return;
303 #if 0 /* commented out after discussion with abartlet. Do not reenable.
304 left here so other do not re-add similar code --jerry */
305 if (value == NULL || *value == '\0')
306 return;
307 #endif
309 if (mods == NULL) {
310 mods = SMB_MALLOC_P(LDAPMod *);
311 if (mods == NULL) {
312 smb_panic("smbldap_set_mod: out of memory!");
313 /* notreached. */
315 mods[0] = NULL;
318 for (i = 0; mods[i] != NULL; ++i) {
319 if (mods[i]->mod_op == modop && strequal(mods[i]->mod_type, attribute))
320 break;
323 if (mods[i] == NULL) {
324 mods = SMB_REALLOC_ARRAY (mods, LDAPMod *, i + 2);
325 if (mods == NULL) {
326 smb_panic("smbldap_set_mod: out of memory!");
327 /* notreached. */
329 mods[i] = SMB_MALLOC_P(LDAPMod);
330 if (mods[i] == NULL) {
331 smb_panic("smbldap_set_mod: out of memory!");
332 /* notreached. */
334 mods[i]->mod_op = modop;
335 mods[i]->mod_values = NULL;
336 mods[i]->mod_type = SMB_STRDUP(attribute);
337 mods[i + 1] = NULL;
340 if (blob && (modop & LDAP_MOD_BVALUES)) {
341 j = 0;
342 if (mods[i]->mod_bvalues != NULL) {
343 for (; mods[i]->mod_bvalues[j] != NULL; j++);
345 mods[i]->mod_bvalues = SMB_REALLOC_ARRAY(mods[i]->mod_bvalues, struct berval *, j + 2);
347 if (mods[i]->mod_bvalues == NULL) {
348 smb_panic("smbldap_set_mod: out of memory!");
349 /* notreached. */
352 mods[i]->mod_bvalues[j] = SMB_MALLOC_P(struct berval);
353 SMB_ASSERT(mods[i]->mod_bvalues[j] != NULL);
355 mods[i]->mod_bvalues[j]->bv_val = (char *)memdup(blob->data, blob->length);
356 SMB_ASSERT(mods[i]->mod_bvalues[j]->bv_val != NULL);
357 mods[i]->mod_bvalues[j]->bv_len = blob->length;
359 mods[i]->mod_bvalues[j + 1] = NULL;
360 } else if (value != NULL) {
361 char *utf8_value = NULL;
362 size_t converted_size;
364 j = 0;
365 if (mods[i]->mod_values != NULL) {
366 for (; mods[i]->mod_values[j] != NULL; j++);
368 mods[i]->mod_values = SMB_REALLOC_ARRAY(mods[i]->mod_values, char *, j + 2);
370 if (mods[i]->mod_values == NULL) {
371 smb_panic("smbldap_set_mod: out of memory!");
372 /* notreached. */
375 if (!push_utf8_talloc(talloc_tos(), &utf8_value, value, &converted_size)) {
376 smb_panic("smbldap_set_mod: String conversion failure!");
377 /* notreached. */
380 mods[i]->mod_values[j] = SMB_STRDUP(utf8_value);
381 TALLOC_FREE(utf8_value);
382 SMB_ASSERT(mods[i]->mod_values[j] != NULL);
384 mods[i]->mod_values[j + 1] = NULL;
386 *modlist = mods;
389 void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
391 smbldap_set_mod_internal(modlist, modop, attribute, value, NULL);
394 void smbldap_set_mod_blob(LDAPMod *** modlist, int modop, const char *attribute, const DATA_BLOB *value)
396 smbldap_set_mod_internal(modlist, modop | LDAP_MOD_BVALUES, attribute, NULL, value);
399 /**********************************************************************
400 Set attribute to newval in LDAP, regardless of what value the
401 attribute had in LDAP before.
402 *********************************************************************/
404 static void smbldap_make_mod_internal(LDAP *ldap_struct, LDAPMessage *existing,
405 LDAPMod ***mods,
406 const char *attribute, int op,
407 const char *newval,
408 const DATA_BLOB *newblob)
410 char oldval[2048]; /* current largest allowed value is mungeddial */
411 bool existed;
412 DATA_BLOB oldblob = data_blob_null;
414 if (existing != NULL) {
415 if (op & LDAP_MOD_BVALUES) {
416 existed = smbldap_talloc_single_blob(talloc_tos(), ldap_struct, existing, attribute, &oldblob);
417 } else {
418 existed = smbldap_get_single_attribute(ldap_struct, existing, attribute, oldval, sizeof(oldval));
420 } else {
421 existed = False;
422 *oldval = '\0';
425 if (existed) {
426 bool equal = false;
427 if (op & LDAP_MOD_BVALUES) {
428 equal = (newblob && (data_blob_cmp(&oldblob, newblob) == 0));
429 } else {
430 /* all of our string attributes are case insensitive */
431 equal = (newval && (strcasecmp_m(oldval, newval) == 0));
434 if (equal) {
435 /* Believe it or not, but LDAP will deny a delete and
436 an add at the same time if the values are the
437 same... */
438 DEBUG(10,("smbldap_make_mod: attribute |%s| not changed.\n", attribute));
439 return;
442 /* There has been no value before, so don't delete it.
443 * Here's a possible race: We might end up with
444 * duplicate attributes */
445 /* By deleting exactly the value we found in the entry this
446 * should be race-free in the sense that the LDAP-Server will
447 * deny the complete operation if somebody changed the
448 * attribute behind our back. */
449 /* This will also allow modifying single valued attributes
450 * in Novell NDS. In NDS you have to first remove attribute and then
451 * you could add new value */
453 if (op & LDAP_MOD_BVALUES) {
454 DEBUG(10,("smbldap_make_mod: deleting attribute |%s| blob\n", attribute));
455 smbldap_set_mod_blob(mods, LDAP_MOD_DELETE, attribute, &oldblob);
456 } else {
457 DEBUG(10,("smbldap_make_mod: deleting attribute |%s| values |%s|\n", attribute, oldval));
458 smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, oldval);
462 /* Regardless of the real operation (add or modify)
463 we add the new value here. We rely on deleting
464 the old value, should it exist. */
466 if (op & LDAP_MOD_BVALUES) {
467 if (newblob && newblob->length) {
468 DEBUG(10,("smbldap_make_mod: adding attribute |%s| blob\n", attribute));
469 smbldap_set_mod_blob(mods, LDAP_MOD_ADD, attribute, newblob);
471 } else {
472 if ((newval != NULL) && (strlen(newval) > 0)) {
473 DEBUG(10,("smbldap_make_mod: adding attribute |%s| value |%s|\n", attribute, newval));
474 smbldap_set_mod(mods, LDAP_MOD_ADD, attribute, newval);
479 void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing,
480 LDAPMod ***mods,
481 const char *attribute, const char *newval)
483 smbldap_make_mod_internal(ldap_struct, existing, mods, attribute,
484 0, newval, NULL);
487 void smbldap_make_mod_blob(LDAP *ldap_struct, LDAPMessage *existing,
488 LDAPMod ***mods,
489 const char *attribute, const DATA_BLOB *newblob)
491 smbldap_make_mod_internal(ldap_struct, existing, mods, attribute,
492 LDAP_MOD_BVALUES, NULL, newblob);
495 /**********************************************************************
496 Some varients of the LDAP rebind code do not pass in the third 'arg'
497 pointer to a void*, so we try and work around it by assuming that the
498 value of the 'LDAP *' pointer is the same as the one we had passed in
499 **********************************************************************/
501 struct smbldap_state_lookup {
502 LDAP *ld;
503 struct smbldap_state *smbldap_state;
504 struct smbldap_state_lookup *prev, *next;
507 static struct smbldap_state_lookup *smbldap_state_lookup_list;
509 static struct smbldap_state *smbldap_find_state(LDAP *ld)
511 struct smbldap_state_lookup *t;
513 for (t = smbldap_state_lookup_list; t; t = t->next) {
514 if (t->ld == ld) {
515 return t->smbldap_state;
518 return NULL;
521 static void smbldap_delete_state(struct smbldap_state *smbldap_state)
523 struct smbldap_state_lookup *t;
525 for (t = smbldap_state_lookup_list; t; t = t->next) {
526 if (t->smbldap_state == smbldap_state) {
527 DLIST_REMOVE(smbldap_state_lookup_list, t);
528 SAFE_FREE(t);
529 return;
534 static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state)
536 struct smbldap_state *tmp_ldap_state;
537 struct smbldap_state_lookup *t;
539 if ((tmp_ldap_state = smbldap_find_state(ld))) {
540 SMB_ASSERT(tmp_ldap_state == smbldap_state);
541 return;
544 t = SMB_XMALLOC_P(struct smbldap_state_lookup);
545 ZERO_STRUCTP(t);
547 DLIST_ADD_END(smbldap_state_lookup_list, t, struct smbldap_state_lookup *);
548 t->ld = ld;
549 t->smbldap_state = smbldap_state;
552 /********************************************************************
553 start TLS on an existing LDAP connection
554 *******************************************************************/
556 int smb_ldap_start_tls(LDAP *ldap_struct, int version)
558 #ifdef LDAP_OPT_X_TLS
559 int rc;
560 #endif
562 if (lp_ldap_ssl() != LDAP_SSL_START_TLS) {
563 return LDAP_SUCCESS;
566 #ifdef LDAP_OPT_X_TLS
567 if (version != LDAP_VERSION3) {
568 DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
569 return LDAP_OPERATIONS_ERROR;
572 if ((rc = ldap_start_tls_s (ldap_struct, NULL, NULL)) != LDAP_SUCCESS) {
573 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
574 ldap_err2string(rc)));
575 return rc;
578 DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
579 return LDAP_SUCCESS;
580 #else
581 DEBUG(0,("StartTLS not supported by LDAP client libraries!\n"));
582 return LDAP_OPERATIONS_ERROR;
583 #endif
586 /********************************************************************
587 setup a connection to the LDAP server based on a uri
588 *******************************************************************/
590 static int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri)
592 int rc;
594 DEBUG(10, ("smb_ldap_setup_connection: %s\n", uri));
596 #ifdef HAVE_LDAP_INITIALIZE
598 rc = ldap_initialize(ldap_struct, uri);
599 if (rc) {
600 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
601 return rc;
604 if (lp_ldap_follow_referral() != Auto) {
605 rc = ldap_set_option(*ldap_struct, LDAP_OPT_REFERRALS,
606 lp_ldap_follow_referral() ? LDAP_OPT_ON : LDAP_OPT_OFF);
607 if (rc != LDAP_SUCCESS)
608 DEBUG(0, ("Failed to set LDAP_OPT_REFERRALS: %s\n",
609 ldap_err2string(rc)));
612 return LDAP_SUCCESS;
613 #else
615 /* Parse the string manually */
618 int port = 0;
619 fstring protocol;
620 fstring host;
621 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
624 /* skip leading "URL:" (if any) */
625 if ( strnequal( uri, "URL:", 4 ) ) {
626 uri += 4;
629 sscanf(uri, "%10[^:]://%254[^:/]:%d", protocol, host, &port);
631 if (port == 0) {
632 if (strequal(protocol, "ldap")) {
633 port = LDAP_PORT;
634 } else if (strequal(protocol, "ldaps")) {
635 port = LDAPS_PORT;
636 } else {
637 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
641 if ((*ldap_struct = ldap_init(host, port)) == NULL) {
642 DEBUG(0, ("ldap_init failed !\n"));
643 return LDAP_OPERATIONS_ERROR;
646 if (strequal(protocol, "ldaps")) {
647 #ifdef LDAP_OPT_X_TLS
648 int tls = LDAP_OPT_X_TLS_HARD;
649 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
651 DEBUG(0, ("Failed to setup a TLS session\n"));
654 DEBUG(3,("LDAPS option set...!\n"));
655 #else
656 DEBUG(0,("smbldap_open_connection: Secure connection not supported by LDAP client libraries!\n"));
657 return LDAP_OPERATIONS_ERROR;
658 #endif /* LDAP_OPT_X_TLS */
661 #endif /* HAVE_LDAP_INITIALIZE */
663 /* now set connection timeout */
664 #ifdef LDAP_X_OPT_CONNECT_TIMEOUT /* Netscape */
666 int ct = lp_ldap_connection_timeout()*1000;
667 rc = ldap_set_option(*ldap_struct, LDAP_X_OPT_CONNECT_TIMEOUT, &ct);
668 if (rc != LDAP_SUCCESS) {
669 DEBUG(0,("Failed to setup an ldap connection timeout %d: %s\n",
670 ct, ldap_err2string(rc)));
673 #elif defined (LDAP_OPT_NETWORK_TIMEOUT) /* OpenLDAP */
675 struct timeval ct;
676 ct.tv_usec = 0;
677 ct.tv_sec = lp_ldap_connection_timeout();
678 rc = ldap_set_option(*ldap_struct, LDAP_OPT_NETWORK_TIMEOUT, &ct);
679 if (rc != LDAP_SUCCESS) {
680 DEBUG(0,("Failed to setup an ldap connection timeout %d: %s\n",
681 (int)ct.tv_sec, ldap_err2string(rc)));
684 #endif
686 return LDAP_SUCCESS;
689 /********************************************************************
690 try to upgrade to Version 3 LDAP if not already, in either case return current
691 version
692 *******************************************************************/
694 static int smb_ldap_upgrade_conn(LDAP *ldap_struct, int *new_version)
696 int version;
697 int rc;
699 /* assume the worst */
700 *new_version = LDAP_VERSION2;
702 rc = ldap_get_option(ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
703 if (rc) {
704 return rc;
707 if (version == LDAP_VERSION3) {
708 *new_version = LDAP_VERSION3;
709 return LDAP_SUCCESS;
712 /* try upgrade */
713 version = LDAP_VERSION3;
714 rc = ldap_set_option (ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
715 if (rc) {
716 return rc;
719 *new_version = LDAP_VERSION3;
720 return LDAP_SUCCESS;
723 /*******************************************************************
724 open a connection to the ldap server (just until the bind)
725 ******************************************************************/
727 int smb_ldap_setup_full_conn(LDAP **ldap_struct, const char *uri)
729 int rc, version;
731 rc = smb_ldap_setup_conn(ldap_struct, uri);
732 if (rc) {
733 return rc;
736 rc = smb_ldap_upgrade_conn(*ldap_struct, &version);
737 if (rc) {
738 return rc;
741 rc = smb_ldap_start_tls(*ldap_struct, version);
742 if (rc) {
743 return rc;
746 return LDAP_SUCCESS;
749 /*******************************************************************
750 open a connection to the ldap server.
751 ******************************************************************/
752 static int smbldap_open_connection (struct smbldap_state *ldap_state)
755 int rc = LDAP_SUCCESS;
756 int version;
757 int deref;
758 LDAP **ldap_struct = &ldap_state->ldap_struct;
760 rc = smb_ldap_setup_conn(ldap_struct, ldap_state->uri);
761 if (rc) {
762 return rc;
765 /* Store the LDAP pointer in a lookup list */
767 smbldap_store_state(*ldap_struct, ldap_state);
769 /* Upgrade to LDAPv3 if possible */
771 rc = smb_ldap_upgrade_conn(*ldap_struct, &version);
772 if (rc) {
773 return rc;
776 /* Start TLS if required */
778 rc = smb_ldap_start_tls(*ldap_struct, version);
779 if (rc) {
780 return rc;
783 /* Set alias dereferencing method */
784 deref = lp_ldap_deref();
785 if (deref != -1) {
786 if (ldap_set_option (*ldap_struct, LDAP_OPT_DEREF, &deref) != LDAP_OPT_SUCCESS) {
787 DEBUG(1,("smbldap_open_connection: Failed to set dereferencing method: %d\n", deref));
788 } else {
789 DEBUG(5,("Set dereferencing method: %d\n", deref));
793 DEBUG(2, ("smbldap_open_connection: connection opened\n"));
794 return rc;
797 /*******************************************************************
798 a rebind function for authenticated referrals
799 This version takes a void* that we can shove useful stuff in :-)
800 ******************************************************************/
801 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
802 #else
803 static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
804 int *methodp, int freeit, void *arg)
806 struct smbldap_state *ldap_state = arg;
807 struct timespec ts;
809 /** @TODO Should we be doing something to check what servers we rebind to?
810 Could we get a referral to a machine that we don't want to give our
811 username and password to? */
813 if (freeit) {
814 SAFE_FREE(*whop);
815 if (*credp) {
816 memset(*credp, '\0', strlen(*credp));
818 SAFE_FREE(*credp);
819 } else {
820 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
821 ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
823 if (ldap_state->anonymous) {
824 *whop = NULL;
825 *credp = NULL;
826 } else {
827 *whop = SMB_STRDUP(ldap_state->bind_dn);
828 if (!*whop) {
829 return LDAP_NO_MEMORY;
831 *credp = SMB_STRDUP(ldap_state->bind_secret);
832 if (!*credp) {
833 SAFE_FREE(*whop);
834 return LDAP_NO_MEMORY;
837 *methodp = LDAP_AUTH_SIMPLE;
840 clock_gettime_mono(&ts);
841 ldap_state->last_rebind = convert_timespec_to_timeval(ts);
843 return 0;
845 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
847 /*******************************************************************
848 a rebind function for authenticated referrals
849 This version takes a void* that we can shove useful stuff in :-)
850 and actually does the connection.
851 ******************************************************************/
852 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
853 static int rebindproc_connect_with_state (LDAP *ldap_struct,
854 LDAP_CONST char *url,
855 ber_tag_t request,
856 ber_int_t msgid, void *arg)
858 struct smbldap_state *ldap_state =
859 (struct smbldap_state *)arg;
860 int rc;
861 struct timespec ts;
862 int version;
864 DEBUG(5,("rebindproc_connect_with_state: Rebinding to %s as \"%s\"\n",
865 url, ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
867 /* call START_TLS again (ldaps:// is handled by the OpenLDAP library
868 * itself) before rebinding to another LDAP server to avoid to expose
869 * our credentials. At least *try* to secure the connection - Guenther */
871 smb_ldap_upgrade_conn(ldap_struct, &version);
872 smb_ldap_start_tls(ldap_struct, version);
874 /** @TODO Should we be doing something to check what servers we rebind to?
875 Could we get a referral to a machine that we don't want to give our
876 username and password to? */
878 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
880 /* only set the last rebind timestamp when we did rebind after a
881 * non-read LDAP operation. That way we avoid the replication sleep
882 * after a simple redirected search operation - Guenther */
884 switch (request) {
886 case LDAP_REQ_MODIFY:
887 case LDAP_REQ_ADD:
888 case LDAP_REQ_DELETE:
889 case LDAP_REQ_MODDN:
890 case LDAP_REQ_EXTENDED:
891 DEBUG(10,("rebindproc_connect_with_state: "
892 "setting last_rebind timestamp "
893 "(req: 0x%02x)\n", (unsigned int)request));
894 clock_gettime_mono(&ts);
895 ldap_state->last_rebind = convert_timespec_to_timeval(ts);
896 break;
897 default:
898 ZERO_STRUCT(ldap_state->last_rebind);
899 break;
902 return rc;
904 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
906 /*******************************************************************
907 Add a rebind function for authenticated referrals
908 ******************************************************************/
909 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
910 #else
911 # if LDAP_SET_REBIND_PROC_ARGS == 2
912 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
913 int *method, int freeit )
915 struct smbldap_state *ldap_state = smbldap_find_state(ldap_struct);
917 return rebindproc_with_state(ldap_struct, whop, credp,
918 method, freeit, ldap_state);
920 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
921 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
923 /*******************************************************************
924 a rebind function for authenticated referrals
925 this also does the connection, but no void*.
926 ******************************************************************/
927 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
928 # if LDAP_SET_REBIND_PROC_ARGS == 2
929 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
930 ber_int_t msgid)
932 struct smbldap_state *ldap_state = smbldap_find_state(ld);
934 return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid,
935 ldap_state);
937 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
938 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
940 /*******************************************************************
941 connect to the ldap server under system privilege.
942 ******************************************************************/
943 static int smbldap_connect_system(struct smbldap_state *ldap_state)
945 LDAP *ldap_struct = ldap_state->ldap_struct;
946 int rc;
947 int version;
949 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
950 (OpenLDAP) doesnt' seem to support it */
952 DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
953 ldap_state->uri, ldap_state->bind_dn));
955 #ifdef HAVE_LDAP_SET_REBIND_PROC
956 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
957 # if LDAP_SET_REBIND_PROC_ARGS == 2
958 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect);
959 # endif
960 # if LDAP_SET_REBIND_PROC_ARGS == 3
961 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);
962 # endif
963 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
964 # if LDAP_SET_REBIND_PROC_ARGS == 2
965 ldap_set_rebind_proc(ldap_struct, &rebindproc);
966 # endif
967 # if LDAP_SET_REBIND_PROC_ARGS == 3
968 ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);
969 # endif
970 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
971 #endif
973 /* When there is an alternative bind callback is set,
974 attempt to use it to perform the bind */
975 if (ldap_state->bind_callback != NULL) {
976 /* We have to allow bind callback to be run under become_root/unbecome_root
977 to make sure within smbd the callback has proper write access to its resources,
978 like credential cache. This is similar to passdb case where this callback is supposed
979 to be used. When used outside smbd, become_root()/unbecome_root() are no-op.
981 become_root();
982 rc = ldap_state->bind_callback(ldap_struct, ldap_state, ldap_state->bind_callback_data);
983 unbecome_root();
984 } else {
985 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
988 if (rc != LDAP_SUCCESS) {
989 char *ld_error = NULL;
990 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
991 &ld_error);
992 DEBUG(ldap_state->num_failures ? 2 : 0,
993 ("failed to bind to server %s with dn=\"%s\" Error: %s\n\t%s\n",
994 ldap_state->uri,
995 ldap_state->bind_dn ? ldap_state->bind_dn : "[Anonymous bind]",
996 ldap_err2string(rc),
997 ld_error ? ld_error : "(unknown)"));
998 SAFE_FREE(ld_error);
999 ldap_state->num_failures++;
1000 goto done;
1003 ldap_state->num_failures = 0;
1004 ldap_state->paged_results = False;
1006 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
1008 if (smbldap_has_control(ldap_state->ldap_struct, ADS_PAGE_CTL_OID) && version == 3) {
1009 ldap_state->paged_results = True;
1012 DEBUG(3, ("ldap_connect_system: successful connection to the LDAP server\n"));
1013 DEBUGADD(10, ("ldap_connect_system: LDAP server %s support paged results\n",
1014 ldap_state->paged_results ? "does" : "does not"));
1015 done:
1016 if (rc != 0) {
1017 ldap_unbind(ldap_struct);
1018 ldap_state->ldap_struct = NULL;
1020 return rc;
1023 static void smbldap_idle_fn(struct tevent_context *tevent_ctx,
1024 struct timed_event *te,
1025 struct timeval now_abs,
1026 void *private_data);
1028 /**********************************************************************
1029 Connect to LDAP server (called before every ldap operation)
1030 *********************************************************************/
1031 static int smbldap_open(struct smbldap_state *ldap_state)
1033 int rc, opt_rc;
1034 bool reopen = False;
1035 SMB_ASSERT(ldap_state);
1037 if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + SMBLDAP_DONT_PING_TIME) < time_mono(NULL))) {
1039 #ifdef HAVE_UNIXSOCKET
1040 struct sockaddr_un addr;
1041 #else
1042 struct sockaddr addr;
1043 #endif
1044 socklen_t len = sizeof(addr);
1045 int sd;
1047 opt_rc = ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd);
1048 if (opt_rc == 0 && (getpeername(sd, (struct sockaddr *) &addr, &len)) < 0 )
1049 reopen = True;
1051 #ifdef HAVE_UNIXSOCKET
1052 if (opt_rc == 0 && addr.sun_family == AF_UNIX)
1053 reopen = True;
1054 #endif
1055 if (reopen) {
1056 /* the other end has died. reopen. */
1057 ldap_unbind(ldap_state->ldap_struct);
1058 ldap_state->ldap_struct = NULL;
1059 ldap_state->last_ping = (time_t)0;
1060 } else {
1061 ldap_state->last_ping = time_mono(NULL);
1065 if (ldap_state->ldap_struct != NULL) {
1066 DEBUG(11,("smbldap_open: already connected to the LDAP server\n"));
1067 return LDAP_SUCCESS;
1070 if ((rc = smbldap_open_connection(ldap_state))) {
1071 return rc;
1074 if ((rc = smbldap_connect_system(ldap_state))) {
1075 return rc;
1079 ldap_state->last_ping = time_mono(NULL);
1080 ldap_state->pid = getpid();
1082 TALLOC_FREE(ldap_state->idle_event);
1084 if (ldap_state->tevent_context != NULL) {
1085 ldap_state->idle_event = tevent_add_timer(
1086 ldap_state->tevent_context, ldap_state,
1087 timeval_current_ofs(SMBLDAP_IDLE_TIME, 0),
1088 smbldap_idle_fn, ldap_state);
1091 DEBUG(4,("The LDAP server is successfully connected\n"));
1093 return LDAP_SUCCESS;
1096 /**********************************************************************
1097 Disconnect from LDAP server
1098 *********************************************************************/
1099 static NTSTATUS smbldap_close(struct smbldap_state *ldap_state)
1101 if (!ldap_state)
1102 return NT_STATUS_INVALID_PARAMETER;
1104 if (ldap_state->ldap_struct != NULL) {
1105 ldap_unbind(ldap_state->ldap_struct);
1106 ldap_state->ldap_struct = NULL;
1109 smbldap_delete_state(ldap_state);
1111 TALLOC_FREE(ldap_state->idle_event);
1113 DEBUG(5,("The connection to the LDAP server was closed\n"));
1114 /* maybe free the results here --metze */
1116 return NT_STATUS_OK;
1119 static SIG_ATOMIC_T got_alarm;
1121 static void gotalarm_sig(int dummy)
1123 got_alarm = 1;
1126 static time_t calc_ldap_abs_endtime(int ldap_to)
1128 if (ldap_to == 0) {
1129 /* No timeout - don't
1130 return a value for
1131 the alarm. */
1132 return (time_t)0;
1135 /* Make the alarm time one second beyond
1136 the timout we're setting for the
1137 remote search timeout, to allow that
1138 to fire in preference. */
1140 return time_mono(NULL)+ldap_to+1;
1143 static int end_ldap_local_alarm(time_t absolute_endtime, int rc)
1145 if (absolute_endtime) {
1146 alarm(0);
1147 CatchSignal(SIGALRM, SIG_IGN);
1148 if (got_alarm) {
1149 /* Client timeout error code. */
1150 got_alarm = 0;
1151 return LDAP_TIMEOUT;
1154 return rc;
1157 static void setup_ldap_local_alarm(struct smbldap_state *ldap_state, time_t absolute_endtime)
1159 time_t now = time_mono(NULL);
1161 if (absolute_endtime) {
1162 got_alarm = 0;
1163 CatchSignal(SIGALRM, gotalarm_sig);
1164 alarm(absolute_endtime - now);
1167 if (ldap_state->pid != getpid()) {
1168 smbldap_close(ldap_state);
1172 static void get_ldap_errs(struct smbldap_state *ldap_state, char **pp_ld_error, int *p_ld_errno)
1174 ldap_get_option(ldap_state->ldap_struct,
1175 LDAP_OPT_ERROR_NUMBER, p_ld_errno);
1177 ldap_get_option(ldap_state->ldap_struct,
1178 LDAP_OPT_ERROR_STRING, pp_ld_error);
1181 static int get_cached_ldap_connect(struct smbldap_state *ldap_state, time_t abs_endtime)
1183 int attempts = 0;
1185 while (1) {
1186 int rc;
1187 time_t now;
1189 now = time_mono(NULL);
1190 ldap_state->last_use = now;
1192 if (abs_endtime && now > abs_endtime) {
1193 smbldap_close(ldap_state);
1194 return LDAP_TIMEOUT;
1197 rc = smbldap_open(ldap_state);
1199 if (rc == LDAP_SUCCESS) {
1200 return LDAP_SUCCESS;
1203 attempts++;
1204 DEBUG(1, ("Connection to LDAP server failed for the "
1205 "%d try!\n", attempts));
1207 if (rc == LDAP_INSUFFICIENT_ACCESS) {
1208 /* The fact that we are non-root or any other
1209 * access-denied condition will not change in the next
1210 * round of trying */
1211 return rc;
1214 if (got_alarm) {
1215 smbldap_close(ldap_state);
1216 return LDAP_TIMEOUT;
1219 smb_msleep(1000);
1221 if (got_alarm) {
1222 smbldap_close(ldap_state);
1223 return LDAP_TIMEOUT;
1228 /*********************************************************************
1229 ********************************************************************/
1231 static int smbldap_search_ext(struct smbldap_state *ldap_state,
1232 const char *base, int scope, const char *filter,
1233 const char *attrs[], int attrsonly,
1234 LDAPControl **sctrls, LDAPControl **cctrls,
1235 int sizelimit, LDAPMessage **res)
1237 int rc = LDAP_SERVER_DOWN;
1238 char *utf8_filter;
1239 int to = lp_ldap_timeout();
1240 time_t abs_endtime = calc_ldap_abs_endtime(to);
1241 struct timeval timeout;
1242 struct timeval *timeout_ptr = NULL;
1243 size_t converted_size;
1245 SMB_ASSERT(ldap_state);
1247 DEBUG(5,("smbldap_search_ext: base => [%s], filter => [%s], "
1248 "scope => [%d]\n", base, filter, scope));
1250 if (ldap_state->last_rebind.tv_sec > 0) {
1251 struct timeval tval;
1252 struct timespec ts;
1253 int64_t tdiff = 0;
1254 int sleep_time = 0;
1256 clock_gettime_mono(&ts);
1257 tval = convert_timespec_to_timeval(ts);
1259 tdiff = usec_time_diff(&tval, &ldap_state->last_rebind);
1260 tdiff /= 1000; /* Convert to milliseconds. */
1262 sleep_time = lp_ldap_replication_sleep()-(int)tdiff;
1263 sleep_time = MIN(sleep_time, MAX_LDAP_REPLICATION_SLEEP_TIME);
1265 if (sleep_time > 0) {
1266 /* we wait for the LDAP replication */
1267 DEBUG(5,("smbldap_search_ext: waiting %d milliseconds "
1268 "for LDAP replication.\n",sleep_time));
1269 smb_msleep(sleep_time);
1270 DEBUG(5,("smbldap_search_ext: go on!\n"));
1272 ZERO_STRUCT(ldap_state->last_rebind);
1275 if (!push_utf8_talloc(talloc_tos(), &utf8_filter, filter, &converted_size)) {
1276 return LDAP_NO_MEMORY;
1279 /* Setup remote timeout for the ldap_search_ext_s call. */
1280 if (to) {
1281 timeout.tv_sec = to;
1282 timeout.tv_usec = 0;
1283 timeout_ptr = &timeout;
1286 setup_ldap_local_alarm(ldap_state, abs_endtime);
1288 while (1) {
1289 char *ld_error = NULL;
1290 int ld_errno;
1292 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1293 if (rc != LDAP_SUCCESS) {
1294 break;
1297 rc = ldap_search_ext_s(ldap_state->ldap_struct, base, scope,
1298 utf8_filter,
1299 discard_const_p(char *, attrs),
1300 attrsonly, sctrls, cctrls, timeout_ptr,
1301 sizelimit, res);
1302 if (rc == LDAP_SUCCESS) {
1303 break;
1306 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1308 DEBUG(10, ("Failed search for base: %s, error: %d (%s) "
1309 "(%s)\n", base, ld_errno,
1310 ldap_err2string(rc),
1311 ld_error ? ld_error : "unknown"));
1312 SAFE_FREE(ld_error);
1314 if (ld_errno != LDAP_SERVER_DOWN) {
1315 break;
1317 ldap_unbind(ldap_state->ldap_struct);
1318 ldap_state->ldap_struct = NULL;
1321 TALLOC_FREE(utf8_filter);
1322 return end_ldap_local_alarm(abs_endtime, rc);
1325 int smbldap_search(struct smbldap_state *ldap_state,
1326 const char *base, int scope, const char *filter,
1327 const char *attrs[], int attrsonly,
1328 LDAPMessage **res)
1330 return smbldap_search_ext(ldap_state, base, scope, filter, attrs,
1331 attrsonly, NULL, NULL, LDAP_NO_LIMIT, res);
1334 int smbldap_search_paged(struct smbldap_state *ldap_state,
1335 const char *base, int scope, const char *filter,
1336 const char **attrs, int attrsonly, int pagesize,
1337 LDAPMessage **res, void **cookie)
1339 LDAPControl pr;
1340 LDAPControl **rcontrols;
1341 LDAPControl *controls[2] = { NULL, NULL};
1342 BerElement *cookie_be = NULL;
1343 struct berval *cookie_bv = NULL;
1344 int tmp = 0, i, rc;
1345 bool critical = True;
1347 *res = NULL;
1349 DEBUG(3,("smbldap_search_paged: base => [%s], filter => [%s],"
1350 "scope => [%d], pagesize => [%d]\n",
1351 base, filter, scope, pagesize));
1353 cookie_be = ber_alloc_t(LBER_USE_DER);
1354 if (cookie_be == NULL) {
1355 DEBUG(0,("smbldap_create_page_control: ber_alloc_t returns "
1356 "NULL\n"));
1357 return LDAP_NO_MEMORY;
1360 /* construct cookie */
1361 if (*cookie != NULL) {
1362 ber_printf(cookie_be, "{iO}", (ber_int_t) pagesize, *cookie);
1363 ber_bvfree((struct berval *)*cookie); /* don't need it from last time */
1364 *cookie = NULL;
1365 } else {
1366 ber_printf(cookie_be, "{io}", (ber_int_t) pagesize, "", 0);
1368 ber_flatten(cookie_be, &cookie_bv);
1370 pr.ldctl_oid = discard_const_p(char, ADS_PAGE_CTL_OID);
1371 pr.ldctl_iscritical = (char) critical;
1372 pr.ldctl_value.bv_len = cookie_bv->bv_len;
1373 pr.ldctl_value.bv_val = cookie_bv->bv_val;
1375 controls[0] = &pr;
1376 controls[1] = NULL;
1378 rc = smbldap_search_ext(ldap_state, base, scope, filter, attrs,
1379 0, controls, NULL, LDAP_NO_LIMIT, res);
1381 ber_free(cookie_be, 1);
1382 ber_bvfree(cookie_bv);
1384 if (rc != 0) {
1385 DEBUG(3,("smbldap_search_paged: smbldap_search_ext(%s) "
1386 "failed with [%s]\n", filter, ldap_err2string(rc)));
1387 goto done;
1390 DEBUG(3,("smbldap_search_paged: search was successful\n"));
1392 rc = ldap_parse_result(ldap_state->ldap_struct, *res, NULL, NULL,
1393 NULL, NULL, &rcontrols, 0);
1394 if (rc != 0) {
1395 DEBUG(3,("smbldap_search_paged: ldap_parse_result failed " \
1396 "with [%s]\n", ldap_err2string(rc)));
1397 goto done;
1400 if (rcontrols == NULL)
1401 goto done;
1403 for (i=0; rcontrols[i]; i++) {
1405 if (strcmp(ADS_PAGE_CTL_OID, rcontrols[i]->ldctl_oid) != 0)
1406 continue;
1408 cookie_be = ber_init(&rcontrols[i]->ldctl_value);
1409 ber_scanf(cookie_be,"{iO}", &tmp, &cookie_bv);
1410 /* the berval is the cookie, but must be freed when it is all
1411 done */
1412 if (cookie_bv->bv_len)
1413 *cookie=ber_bvdup(cookie_bv);
1414 else
1415 *cookie=NULL;
1416 ber_bvfree(cookie_bv);
1417 ber_free(cookie_be, 1);
1418 break;
1420 ldap_controls_free(rcontrols);
1421 done:
1422 return rc;
1425 int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
1427 int rc = LDAP_SERVER_DOWN;
1428 char *utf8_dn;
1429 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1430 size_t converted_size;
1432 SMB_ASSERT(ldap_state);
1434 DEBUG(5,("smbldap_modify: dn => [%s]\n", dn ));
1436 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1437 return LDAP_NO_MEMORY;
1440 setup_ldap_local_alarm(ldap_state, abs_endtime);
1442 while (1) {
1443 char *ld_error = NULL;
1444 int ld_errno;
1446 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1447 if (rc != LDAP_SUCCESS) {
1448 break;
1451 rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs);
1452 if (rc == LDAP_SUCCESS) {
1453 break;
1456 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1458 DEBUG(10, ("Failed to modify dn: %s, error: %d (%s) "
1459 "(%s)\n", dn, ld_errno,
1460 ldap_err2string(rc),
1461 ld_error ? ld_error : "unknown"));
1462 SAFE_FREE(ld_error);
1464 if (ld_errno != LDAP_SERVER_DOWN) {
1465 break;
1467 ldap_unbind(ldap_state->ldap_struct);
1468 ldap_state->ldap_struct = NULL;
1471 TALLOC_FREE(utf8_dn);
1472 return end_ldap_local_alarm(abs_endtime, rc);
1475 int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
1477 int rc = LDAP_SERVER_DOWN;
1478 char *utf8_dn;
1479 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1480 size_t converted_size;
1482 SMB_ASSERT(ldap_state);
1484 DEBUG(5,("smbldap_add: dn => [%s]\n", dn ));
1486 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1487 return LDAP_NO_MEMORY;
1490 setup_ldap_local_alarm(ldap_state, abs_endtime);
1492 while (1) {
1493 char *ld_error = NULL;
1494 int ld_errno;
1496 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1497 if (rc != LDAP_SUCCESS) {
1498 break;
1501 rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs);
1502 if (rc == LDAP_SUCCESS) {
1503 break;
1506 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1508 DEBUG(10, ("Failed to add dn: %s, error: %d (%s) "
1509 "(%s)\n", dn, ld_errno,
1510 ldap_err2string(rc),
1511 ld_error ? ld_error : "unknown"));
1512 SAFE_FREE(ld_error);
1514 if (ld_errno != LDAP_SERVER_DOWN) {
1515 break;
1517 ldap_unbind(ldap_state->ldap_struct);
1518 ldap_state->ldap_struct = NULL;
1521 TALLOC_FREE(utf8_dn);
1522 return end_ldap_local_alarm(abs_endtime, rc);
1525 int smbldap_delete(struct smbldap_state *ldap_state, const char *dn)
1527 int rc = LDAP_SERVER_DOWN;
1528 char *utf8_dn;
1529 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1530 size_t converted_size;
1532 SMB_ASSERT(ldap_state);
1534 DEBUG(5,("smbldap_delete: dn => [%s]\n", dn ));
1536 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1537 return LDAP_NO_MEMORY;
1540 setup_ldap_local_alarm(ldap_state, abs_endtime);
1542 while (1) {
1543 char *ld_error = NULL;
1544 int ld_errno;
1546 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1547 if (rc != LDAP_SUCCESS) {
1548 break;
1551 rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn);
1552 if (rc == LDAP_SUCCESS) {
1553 break;
1556 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1558 DEBUG(10, ("Failed to delete dn: %s, error: %d (%s) "
1559 "(%s)\n", dn, ld_errno,
1560 ldap_err2string(rc),
1561 ld_error ? ld_error : "unknown"));
1562 SAFE_FREE(ld_error);
1564 if (ld_errno != LDAP_SERVER_DOWN) {
1565 break;
1567 ldap_unbind(ldap_state->ldap_struct);
1568 ldap_state->ldap_struct = NULL;
1571 TALLOC_FREE(utf8_dn);
1572 return end_ldap_local_alarm(abs_endtime, rc);
1575 int smbldap_extended_operation(struct smbldap_state *ldap_state,
1576 LDAP_CONST char *reqoid, struct berval *reqdata,
1577 LDAPControl **serverctrls, LDAPControl **clientctrls,
1578 char **retoidp, struct berval **retdatap)
1580 int rc = LDAP_SERVER_DOWN;
1581 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1583 if (!ldap_state)
1584 return (-1);
1586 setup_ldap_local_alarm(ldap_state, abs_endtime);
1588 while (1) {
1589 char *ld_error = NULL;
1590 int ld_errno;
1592 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1593 if (rc != LDAP_SUCCESS) {
1594 break;
1597 rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid,
1598 reqdata, serverctrls,
1599 clientctrls, retoidp, retdatap);
1600 if (rc == LDAP_SUCCESS) {
1601 break;
1604 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1606 DEBUG(10, ("Extended operation failed with error: "
1607 "%d (%s) (%s)\n", ld_errno,
1608 ldap_err2string(rc),
1609 ld_error ? ld_error : "unknown"));
1610 SAFE_FREE(ld_error);
1612 if (ld_errno != LDAP_SERVER_DOWN) {
1613 break;
1615 ldap_unbind(ldap_state->ldap_struct);
1616 ldap_state->ldap_struct = NULL;
1619 return end_ldap_local_alarm(abs_endtime, rc);
1622 /*******************************************************************
1623 run the search by name.
1624 ******************************************************************/
1625 int smbldap_search_suffix (struct smbldap_state *ldap_state,
1626 const char *filter, const char **search_attr,
1627 LDAPMessage ** result)
1629 return smbldap_search(ldap_state, lp_ldap_suffix(talloc_tos()),
1630 LDAP_SCOPE_SUBTREE,
1631 filter, search_attr, 0, result);
1634 static void smbldap_idle_fn(struct tevent_context *tevent_ctx,
1635 struct timed_event *te,
1636 struct timeval now_abs,
1637 void *private_data)
1639 struct smbldap_state *state = (struct smbldap_state *)private_data;
1641 TALLOC_FREE(state->idle_event);
1643 if (state->ldap_struct == NULL) {
1644 DEBUG(10,("ldap connection not connected...\n"));
1645 return;
1648 if ((state->last_use+SMBLDAP_IDLE_TIME) > time_mono(NULL)) {
1649 DEBUG(10,("ldap connection not idle...\n"));
1651 /* this needs to be made monotonic clock aware inside tevent: */
1652 state->idle_event = tevent_add_timer(
1653 tevent_ctx, state,
1654 timeval_add(&now_abs, SMBLDAP_IDLE_TIME, 0),
1655 smbldap_idle_fn,
1656 private_data);
1657 return;
1660 DEBUG(7,("ldap connection idle...closing connection\n"));
1661 smbldap_close(state);
1664 /**********************************************************************
1665 Housekeeping
1666 *********************************************************************/
1668 void smbldap_free_struct(struct smbldap_state **ldap_state)
1670 smbldap_close(*ldap_state);
1672 if ((*ldap_state)->bind_secret) {
1673 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
1676 SAFE_FREE((*ldap_state)->bind_dn);
1677 SAFE_FREE((*ldap_state)->bind_secret);
1678 (*ldap_state)->bind_callback = NULL;
1679 (*ldap_state)->bind_callback_data = NULL;
1681 TALLOC_FREE(*ldap_state);
1683 /* No need to free any further, as it is talloc()ed */
1686 static int smbldap_state_destructor(struct smbldap_state *state)
1688 smbldap_free_struct(&state);
1689 return 0;
1693 /**********************************************************************
1694 Intitalise the 'general' ldap structures, on which ldap operations may be conducted
1695 *********************************************************************/
1697 NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, struct tevent_context *tevent_ctx,
1698 const char *location,
1699 bool anon,
1700 const char *bind_dn,
1701 const char *bind_secret,
1702 struct smbldap_state **smbldap_state)
1704 *smbldap_state = talloc_zero(mem_ctx, struct smbldap_state);
1705 if (!*smbldap_state) {
1706 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
1707 return NT_STATUS_NO_MEMORY;
1710 if (location) {
1711 (*smbldap_state)->uri = talloc_strdup(mem_ctx, location);
1712 } else {
1713 (*smbldap_state)->uri = "ldap://localhost";
1716 (*smbldap_state)->tevent_context = tevent_ctx;
1718 if (bind_dn && bind_secret) {
1719 smbldap_set_creds(*smbldap_state, anon, bind_dn, bind_secret);
1722 talloc_set_destructor(*smbldap_state, smbldap_state_destructor);
1723 return NT_STATUS_OK;
1726 char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld,
1727 LDAPMessage *entry)
1729 char *utf8_dn, *unix_dn;
1730 size_t converted_size;
1732 utf8_dn = ldap_get_dn(ld, entry);
1733 if (!utf8_dn) {
1734 DEBUG (5, ("smbldap_talloc_dn: ldap_get_dn failed\n"));
1735 return NULL;
1737 if (!pull_utf8_talloc(mem_ctx, &unix_dn, utf8_dn, &converted_size)) {
1738 DEBUG (0, ("smbldap_talloc_dn: String conversion failure utf8 "
1739 "[%s]\n", utf8_dn));
1740 return NULL;
1742 ldap_memfree(utf8_dn);
1743 return unix_dn;
1746 /*******************************************************************
1747 Check if root-dse has a certain Control or Extension
1748 ********************************************************************/
1750 static bool smbldap_check_root_dse(LDAP *ld, const char **attrs, const char *value)
1752 LDAPMessage *msg = NULL;
1753 LDAPMessage *entry = NULL;
1754 char **values = NULL;
1755 int rc, num_result, num_values, i;
1756 bool result = False;
1758 if (!attrs[0]) {
1759 DEBUG(3,("smbldap_check_root_dse: nothing to look for\n"));
1760 return False;
1763 if (!strequal(attrs[0], "supportedExtension") &&
1764 !strequal(attrs[0], "supportedControl") &&
1765 !strequal(attrs[0], "namingContexts")) {
1766 DEBUG(3,("smbldap_check_root_dse: no idea what to query root-dse for: %s ?\n", attrs[0]));
1767 return False;
1770 rc = ldap_search_s(ld, "", LDAP_SCOPE_BASE,
1771 "(objectclass=*)", discard_const_p(char *, attrs), 0 , &msg);
1773 if (rc != LDAP_SUCCESS) {
1774 DEBUG(3,("smbldap_check_root_dse: Could not search rootDSE\n"));
1775 return False;
1778 num_result = ldap_count_entries(ld, msg);
1780 if (num_result != 1) {
1781 DEBUG(3,("smbldap_check_root_dse: Expected one rootDSE, got %d\n", num_result));
1782 goto done;
1785 entry = ldap_first_entry(ld, msg);
1787 if (entry == NULL) {
1788 DEBUG(3,("smbldap_check_root_dse: Could not retrieve rootDSE\n"));
1789 goto done;
1792 values = ldap_get_values(ld, entry, attrs[0]);
1794 if (values == NULL) {
1795 DEBUG(5,("smbldap_check_root_dse: LDAP Server does not support any %s\n", attrs[0]));
1796 goto done;
1799 num_values = ldap_count_values(values);
1801 if (num_values == 0) {
1802 DEBUG(5,("smbldap_check_root_dse: LDAP Server does not have any %s\n", attrs[0]));
1803 goto done;
1806 for (i=0; i<num_values; i++) {
1807 if (strcmp(values[i], value) == 0)
1808 result = True;
1812 done:
1813 if (values != NULL)
1814 ldap_value_free(values);
1815 if (msg != NULL)
1816 ldap_msgfree(msg);
1818 return result;
1822 /*******************************************************************
1823 Check if LDAP-Server supports a certain Control (OID in string format)
1824 ********************************************************************/
1826 bool smbldap_has_control(LDAP *ld, const char *control)
1828 const char *attrs[] = { "supportedControl", NULL };
1829 return smbldap_check_root_dse(ld, attrs, control);
1832 /*******************************************************************
1833 Check if LDAP-Server supports a certain Extension (OID in string format)
1834 ********************************************************************/
1836 bool smbldap_has_extension(LDAP *ld, const char *extension)
1838 const char *attrs[] = { "supportedExtension", NULL };
1839 return smbldap_check_root_dse(ld, attrs, extension);
1842 /*******************************************************************
1843 Check if LDAP-Server holds a given namingContext
1844 ********************************************************************/
1846 bool smbldap_has_naming_context(LDAP *ld, const char *naming_context)
1848 const char *attrs[] = { "namingContexts", NULL };
1849 return smbldap_check_root_dse(ld, attrs, naming_context);
1852 bool smbldap_set_creds(struct smbldap_state *ldap_state, bool anon, const char *dn, const char *secret)
1854 ldap_state->anonymous = anon;
1856 /* free any previously set credential */
1858 SAFE_FREE(ldap_state->bind_dn);
1859 ldap_state->bind_callback = NULL;
1860 ldap_state->bind_callback_data = NULL;
1862 if (ldap_state->bind_secret) {
1863 /* make sure secrets are zeroed out of memory */
1864 memset(ldap_state->bind_secret, '\0', strlen(ldap_state->bind_secret));
1865 SAFE_FREE(ldap_state->bind_secret);
1868 if ( ! anon) {
1869 ldap_state->bind_dn = SMB_STRDUP(dn);
1870 ldap_state->bind_secret = SMB_STRDUP(secret);
1873 return True;