docs: fix the stdarg.configfile entity to print a "=" sign after the long option
[Samba/gebeck_regimport.git] / source3 / lib / smbldap.c
blob5dd6d8d65b39516a384a4242c56ce5c6e1bf760a
1 /*
2 Unix SMB/CIFS implementation.
3 LDAP protocol helper functions for SAMBA
4 Copyright (C) Jean François Micouleau 1998
5 Copyright (C) Gerald Carter 2001-2003
6 Copyright (C) Shahms King 2001
7 Copyright (C) Andrew Bartlett 2002-2003
8 Copyright (C) Stefan (metze) Metzmacher 2002-2003
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "smbldap.h"
27 #include "../libcli/security/security.h"
28 #include <tevent.h>
29 #include "lib/param/loadparm.h"
31 /* Try not to hit the up or down server forever */
33 #define SMBLDAP_DONT_PING_TIME 10 /* ping only all 10 seconds */
34 #define SMBLDAP_NUM_RETRIES 8 /* retry only 8 times */
36 #define SMBLDAP_IDLE_TIME 150 /* After 2.5 minutes disconnect */
39 /*******************************************************************
40 Search an attribute and return the first value found.
41 ******************************************************************/
43 bool smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
44 const char *attribute, char *value,
45 int max_len)
47 char **values;
48 size_t size = 0;
50 if ( !attribute )
51 return False;
53 value[0] = '\0';
55 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
56 DEBUG (10, ("smbldap_get_single_attribute: [%s] = [<does not exist>]\n", attribute));
58 return False;
61 if (!convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, max_len, &size)) {
62 DEBUG(1, ("smbldap_get_single_attribute: string conversion of [%s] = [%s] failed!\n",
63 attribute, values[0]));
64 ldap_value_free(values);
65 return False;
68 ldap_value_free(values);
69 #ifdef DEBUG_PASSWORDS
70 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n", attribute, value));
71 #endif
72 return True;
75 char * smbldap_talloc_single_attribute(LDAP *ldap_struct, LDAPMessage *entry,
76 const char *attribute,
77 TALLOC_CTX *mem_ctx)
79 char **values;
80 char *result;
81 size_t converted_size;
83 if (attribute == NULL) {
84 return NULL;
87 values = ldap_get_values(ldap_struct, entry, attribute);
89 if (values == NULL) {
90 DEBUG(10, ("attribute %s does not exist\n", attribute));
91 return NULL;
94 if (ldap_count_values(values) != 1) {
95 DEBUG(10, ("attribute %s has %d values, expected only one\n",
96 attribute, ldap_count_values(values)));
97 ldap_value_free(values);
98 return NULL;
101 if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
102 DEBUG(10, ("pull_utf8_talloc failed\n"));
103 ldap_value_free(values);
104 return NULL;
107 ldap_value_free(values);
109 #ifdef DEBUG_PASSWORDS
110 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
111 attribute, result));
112 #endif
113 return result;
116 char * smbldap_talloc_first_attribute(LDAP *ldap_struct, LDAPMessage *entry,
117 const char *attribute,
118 TALLOC_CTX *mem_ctx)
120 char **values;
121 char *result;
122 size_t converted_size;
124 if (attribute == NULL) {
125 return NULL;
128 values = ldap_get_values(ldap_struct, entry, attribute);
130 if (values == NULL) {
131 DEBUG(10, ("attribute %s does not exist\n", attribute));
132 return NULL;
135 if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
136 DEBUG(10, ("pull_utf8_talloc failed\n"));
137 ldap_value_free(values);
138 return NULL;
141 ldap_value_free(values);
143 #ifdef DEBUG_PASSWORDS
144 DEBUG (100, ("smbldap_get_first_attribute: [%s] = [%s]\n",
145 attribute, result));
146 #endif
147 return result;
150 char * smbldap_talloc_smallest_attribute(LDAP *ldap_struct, LDAPMessage *entry,
151 const char *attribute,
152 TALLOC_CTX *mem_ctx)
154 char **values;
155 char *result;
156 size_t converted_size;
157 int i, num_values;
159 if (attribute == NULL) {
160 return NULL;
163 values = ldap_get_values(ldap_struct, entry, attribute);
165 if (values == NULL) {
166 DEBUG(10, ("attribute %s does not exist\n", attribute));
167 return NULL;
170 if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
171 DEBUG(10, ("pull_utf8_talloc failed\n"));
172 ldap_value_free(values);
173 return NULL;
176 num_values = ldap_count_values(values);
178 for (i=1; i<num_values; i++) {
179 char *tmp;
181 if (!pull_utf8_talloc(mem_ctx, &tmp, values[i],
182 &converted_size)) {
183 DEBUG(10, ("pull_utf8_talloc failed\n"));
184 TALLOC_FREE(result);
185 ldap_value_free(values);
186 return NULL;
189 if (strcasecmp_m(tmp, result) < 0) {
190 TALLOC_FREE(result);
191 result = tmp;
192 } else {
193 TALLOC_FREE(tmp);
197 ldap_value_free(values);
199 #ifdef DEBUG_PASSWORDS
200 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
201 attribute, result));
202 #endif
203 return result;
206 bool smbldap_talloc_single_blob(TALLOC_CTX *mem_ctx, LDAP *ld,
207 LDAPMessage *msg, const char *attrib,
208 DATA_BLOB *blob)
210 struct berval **values;
212 values = ldap_get_values_len(ld, msg, attrib);
213 if (!values) {
214 return false;
217 if (ldap_count_values_len(values) != 1) {
218 DEBUG(10, ("Expected one value for %s, got %d\n", attrib,
219 ldap_count_values_len(values)));
220 return false;
223 *blob = data_blob_talloc(mem_ctx, values[0]->bv_val,
224 values[0]->bv_len);
225 ldap_value_free_len(values);
227 return (blob->data != NULL);
230 bool smbldap_pull_sid(LDAP *ld, LDAPMessage *msg, const char *attrib,
231 struct dom_sid *sid)
233 DATA_BLOB blob;
234 bool ret;
236 if (!smbldap_talloc_single_blob(talloc_tos(), ld, msg, attrib,
237 &blob)) {
238 return false;
240 ret = sid_parse((char *)blob.data, blob.length, sid);
241 TALLOC_FREE(blob.data);
242 return ret;
245 static int ldapmsg_destructor(LDAPMessage **result) {
246 ldap_msgfree(*result);
247 return 0;
250 void smbldap_talloc_autofree_ldapmsg(TALLOC_CTX *mem_ctx, LDAPMessage *result)
252 LDAPMessage **handle;
254 if (result == NULL) {
255 return;
258 handle = talloc(mem_ctx, LDAPMessage *);
259 SMB_ASSERT(handle != NULL);
261 *handle = result;
262 talloc_set_destructor(handle, ldapmsg_destructor);
265 static int ldapmod_destructor(LDAPMod ***mod) {
266 ldap_mods_free(*mod, True);
267 return 0;
270 void smbldap_talloc_autofree_ldapmod(TALLOC_CTX *mem_ctx, LDAPMod **mod)
272 LDAPMod ***handle;
274 if (mod == NULL) {
275 return;
278 handle = talloc(mem_ctx, LDAPMod **);
279 SMB_ASSERT(handle != NULL);
281 *handle = mod;
282 talloc_set_destructor(handle, ldapmod_destructor);
285 /************************************************************************
286 Routine to manage the LDAPMod structure array
287 manage memory used by the array, by each struct, and values
288 ***********************************************************************/
290 static void smbldap_set_mod_internal(LDAPMod *** modlist, int modop, const char *attribute, const char *value, const DATA_BLOB *blob)
292 LDAPMod **mods;
293 int i;
294 int j;
296 mods = *modlist;
298 /* sanity checks on the mod values */
300 if (attribute == NULL || *attribute == '\0') {
301 return;
304 #if 0 /* commented out after discussion with abartlet. Do not reenable.
305 left here so other do not re-add similar code --jerry */
306 if (value == NULL || *value == '\0')
307 return;
308 #endif
310 if (mods == NULL) {
311 mods = SMB_MALLOC_P(LDAPMod *);
312 if (mods == NULL) {
313 smb_panic("smbldap_set_mod: out of memory!");
314 /* notreached. */
316 mods[0] = NULL;
319 for (i = 0; mods[i] != NULL; ++i) {
320 if (mods[i]->mod_op == modop && strequal(mods[i]->mod_type, attribute))
321 break;
324 if (mods[i] == NULL) {
325 mods = SMB_REALLOC_ARRAY (mods, LDAPMod *, i + 2);
326 if (mods == NULL) {
327 smb_panic("smbldap_set_mod: out of memory!");
328 /* notreached. */
330 mods[i] = SMB_MALLOC_P(LDAPMod);
331 if (mods[i] == NULL) {
332 smb_panic("smbldap_set_mod: out of memory!");
333 /* notreached. */
335 mods[i]->mod_op = modop;
336 mods[i]->mod_values = NULL;
337 mods[i]->mod_type = SMB_STRDUP(attribute);
338 mods[i + 1] = NULL;
341 if (blob && (modop & LDAP_MOD_BVALUES)) {
342 j = 0;
343 if (mods[i]->mod_bvalues != NULL) {
344 for (; mods[i]->mod_bvalues[j] != NULL; j++);
346 mods[i]->mod_bvalues = SMB_REALLOC_ARRAY(mods[i]->mod_bvalues, struct berval *, j + 2);
348 if (mods[i]->mod_bvalues == NULL) {
349 smb_panic("smbldap_set_mod: out of memory!");
350 /* notreached. */
353 mods[i]->mod_bvalues[j] = SMB_MALLOC_P(struct berval);
354 SMB_ASSERT(mods[i]->mod_bvalues[j] != NULL);
356 mods[i]->mod_bvalues[j]->bv_val = (char *)memdup(blob->data, blob->length);
357 SMB_ASSERT(mods[i]->mod_bvalues[j]->bv_val != NULL);
358 mods[i]->mod_bvalues[j]->bv_len = blob->length;
360 mods[i]->mod_bvalues[j + 1] = NULL;
361 } else if (value != NULL) {
362 char *utf8_value = NULL;
363 size_t converted_size;
365 j = 0;
366 if (mods[i]->mod_values != NULL) {
367 for (; mods[i]->mod_values[j] != NULL; j++);
369 mods[i]->mod_values = SMB_REALLOC_ARRAY(mods[i]->mod_values, char *, j + 2);
371 if (mods[i]->mod_values == NULL) {
372 smb_panic("smbldap_set_mod: out of memory!");
373 /* notreached. */
376 if (!push_utf8_talloc(talloc_tos(), &utf8_value, value, &converted_size)) {
377 smb_panic("smbldap_set_mod: String conversion failure!");
378 /* notreached. */
381 mods[i]->mod_values[j] = SMB_STRDUP(utf8_value);
382 TALLOC_FREE(utf8_value);
383 SMB_ASSERT(mods[i]->mod_values[j] != NULL);
385 mods[i]->mod_values[j + 1] = NULL;
387 *modlist = mods;
390 void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
392 smbldap_set_mod_internal(modlist, modop, attribute, value, NULL);
395 void smbldap_set_mod_blob(LDAPMod *** modlist, int modop, const char *attribute, const DATA_BLOB *value)
397 smbldap_set_mod_internal(modlist, modop | LDAP_MOD_BVALUES, attribute, NULL, value);
400 /**********************************************************************
401 Set attribute to newval in LDAP, regardless of what value the
402 attribute had in LDAP before.
403 *********************************************************************/
405 static void smbldap_make_mod_internal(LDAP *ldap_struct, LDAPMessage *existing,
406 LDAPMod ***mods,
407 const char *attribute, int op,
408 const char *newval,
409 const DATA_BLOB *newblob)
411 char oldval[2048]; /* current largest allowed value is mungeddial */
412 bool existed;
413 DATA_BLOB oldblob = data_blob_null;
415 if (existing != NULL) {
416 if (op & LDAP_MOD_BVALUES) {
417 existed = smbldap_talloc_single_blob(talloc_tos(), ldap_struct, existing, attribute, &oldblob);
418 } else {
419 existed = smbldap_get_single_attribute(ldap_struct, existing, attribute, oldval, sizeof(oldval));
421 } else {
422 existed = False;
423 *oldval = '\0';
426 if (existed) {
427 bool equal = false;
428 if (op & LDAP_MOD_BVALUES) {
429 equal = (newblob && (data_blob_cmp(&oldblob, newblob) == 0));
430 } else {
431 /* all of our string attributes are case insensitive */
432 equal = (newval && (strcasecmp_m(oldval, newval) == 0));
435 if (equal) {
436 /* Believe it or not, but LDAP will deny a delete and
437 an add at the same time if the values are the
438 same... */
439 DEBUG(10,("smbldap_make_mod: attribute |%s| not changed.\n", attribute));
440 return;
443 /* There has been no value before, so don't delete it.
444 * Here's a possible race: We might end up with
445 * duplicate attributes */
446 /* By deleting exactly the value we found in the entry this
447 * should be race-free in the sense that the LDAP-Server will
448 * deny the complete operation if somebody changed the
449 * attribute behind our back. */
450 /* This will also allow modifying single valued attributes
451 * in Novell NDS. In NDS you have to first remove attribute and then
452 * you could add new value */
454 if (op & LDAP_MOD_BVALUES) {
455 DEBUG(10,("smbldap_make_mod: deleting attribute |%s| blob\n", attribute));
456 smbldap_set_mod_blob(mods, LDAP_MOD_DELETE, attribute, &oldblob);
457 } else {
458 DEBUG(10,("smbldap_make_mod: deleting attribute |%s| values |%s|\n", attribute, oldval));
459 smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, oldval);
463 /* Regardless of the real operation (add or modify)
464 we add the new value here. We rely on deleting
465 the old value, should it exist. */
467 if (op & LDAP_MOD_BVALUES) {
468 if (newblob && newblob->length) {
469 DEBUG(10,("smbldap_make_mod: adding attribute |%s| blob\n", attribute));
470 smbldap_set_mod_blob(mods, LDAP_MOD_ADD, attribute, newblob);
472 } else {
473 if ((newval != NULL) && (strlen(newval) > 0)) {
474 DEBUG(10,("smbldap_make_mod: adding attribute |%s| value |%s|\n", attribute, newval));
475 smbldap_set_mod(mods, LDAP_MOD_ADD, attribute, newval);
480 void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing,
481 LDAPMod ***mods,
482 const char *attribute, const char *newval)
484 smbldap_make_mod_internal(ldap_struct, existing, mods, attribute,
485 0, newval, NULL);
488 void smbldap_make_mod_blob(LDAP *ldap_struct, LDAPMessage *existing,
489 LDAPMod ***mods,
490 const char *attribute, const DATA_BLOB *newblob)
492 smbldap_make_mod_internal(ldap_struct, existing, mods, attribute,
493 LDAP_MOD_BVALUES, NULL, newblob);
496 /**********************************************************************
497 Some varients of the LDAP rebind code do not pass in the third 'arg'
498 pointer to a void*, so we try and work around it by assuming that the
499 value of the 'LDAP *' pointer is the same as the one we had passed in
500 **********************************************************************/
502 struct smbldap_state_lookup {
503 LDAP *ld;
504 struct smbldap_state *smbldap_state;
505 struct smbldap_state_lookup *prev, *next;
508 static struct smbldap_state_lookup *smbldap_state_lookup_list;
510 static struct smbldap_state *smbldap_find_state(LDAP *ld)
512 struct smbldap_state_lookup *t;
514 for (t = smbldap_state_lookup_list; t; t = t->next) {
515 if (t->ld == ld) {
516 return t->smbldap_state;
519 return NULL;
522 static void smbldap_delete_state(struct smbldap_state *smbldap_state)
524 struct smbldap_state_lookup *t;
526 for (t = smbldap_state_lookup_list; t; t = t->next) {
527 if (t->smbldap_state == smbldap_state) {
528 DLIST_REMOVE(smbldap_state_lookup_list, t);
529 SAFE_FREE(t);
530 return;
535 static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state)
537 struct smbldap_state *tmp_ldap_state;
538 struct smbldap_state_lookup *t;
540 if ((tmp_ldap_state = smbldap_find_state(ld))) {
541 SMB_ASSERT(tmp_ldap_state == smbldap_state);
542 return;
545 t = SMB_XMALLOC_P(struct smbldap_state_lookup);
546 ZERO_STRUCTP(t);
548 DLIST_ADD_END(smbldap_state_lookup_list, t, struct smbldap_state_lookup *);
549 t->ld = ld;
550 t->smbldap_state = smbldap_state;
553 /********************************************************************
554 start TLS on an existing LDAP connection
555 *******************************************************************/
557 int smbldap_start_tls(LDAP *ldap_struct, int version)
559 #ifdef LDAP_OPT_X_TLS
560 int rc;
561 #endif
563 if (lp_ldap_ssl() != LDAP_SSL_START_TLS) {
564 return LDAP_SUCCESS;
567 #ifdef LDAP_OPT_X_TLS
568 if (version != LDAP_VERSION3) {
569 DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
570 return LDAP_OPERATIONS_ERROR;
573 if ((rc = ldap_start_tls_s (ldap_struct, NULL, NULL)) != LDAP_SUCCESS) {
574 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
575 ldap_err2string(rc)));
576 return rc;
579 DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
580 return LDAP_SUCCESS;
581 #else
582 DEBUG(0,("StartTLS not supported by LDAP client libraries!\n"));
583 return LDAP_OPERATIONS_ERROR;
584 #endif
587 /********************************************************************
588 setup a connection to the LDAP server based on a uri
589 *******************************************************************/
591 static int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri)
593 int rc;
595 DEBUG(10, ("smb_ldap_setup_connection: %s\n", uri));
597 #ifdef HAVE_LDAP_INITIALIZE
599 rc = ldap_initialize(ldap_struct, uri);
600 if (rc) {
601 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
602 return rc;
605 if (lp_ldap_follow_referral() != Auto) {
606 rc = ldap_set_option(*ldap_struct, LDAP_OPT_REFERRALS,
607 lp_ldap_follow_referral() ? LDAP_OPT_ON : LDAP_OPT_OFF);
608 if (rc != LDAP_SUCCESS)
609 DEBUG(0, ("Failed to set LDAP_OPT_REFERRALS: %s\n",
610 ldap_err2string(rc)));
613 return LDAP_SUCCESS;
614 #else
616 /* Parse the string manually */
619 int port = 0;
620 fstring protocol;
621 fstring host;
622 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
625 /* skip leading "URL:" (if any) */
626 if ( strnequal( uri, "URL:", 4 ) ) {
627 uri += 4;
630 sscanf(uri, "%10[^:]://%254[^:/]:%d", protocol, host, &port);
632 if (port == 0) {
633 if (strequal(protocol, "ldap")) {
634 port = LDAP_PORT;
635 } else if (strequal(protocol, "ldaps")) {
636 port = LDAPS_PORT;
637 } else {
638 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
642 if ((*ldap_struct = ldap_init(host, port)) == NULL) {
643 DEBUG(0, ("ldap_init failed !\n"));
644 return LDAP_OPERATIONS_ERROR;
647 if (strequal(protocol, "ldaps")) {
648 #ifdef LDAP_OPT_X_TLS
649 int tls = LDAP_OPT_X_TLS_HARD;
650 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
652 DEBUG(0, ("Failed to setup a TLS session\n"));
655 DEBUG(3,("LDAPS option set...!\n"));
656 #else
657 DEBUG(0,("smbldap_open_connection: Secure connection not supported by LDAP client libraries!\n"));
658 return LDAP_OPERATIONS_ERROR;
659 #endif /* LDAP_OPT_X_TLS */
662 #endif /* HAVE_LDAP_INITIALIZE */
664 /* now set connection timeout */
665 #ifdef LDAP_X_OPT_CONNECT_TIMEOUT /* Netscape */
667 int ct = lp_ldap_connection_timeout()*1000;
668 rc = ldap_set_option(*ldap_struct, LDAP_X_OPT_CONNECT_TIMEOUT, &ct);
669 if (rc != LDAP_SUCCESS) {
670 DEBUG(0,("Failed to setup an ldap connection timeout %d: %s\n",
671 ct, ldap_err2string(rc)));
674 #elif defined (LDAP_OPT_NETWORK_TIMEOUT) /* OpenLDAP */
676 struct timeval ct;
677 ct.tv_usec = 0;
678 ct.tv_sec = lp_ldap_connection_timeout();
679 rc = ldap_set_option(*ldap_struct, LDAP_OPT_NETWORK_TIMEOUT, &ct);
680 if (rc != LDAP_SUCCESS) {
681 DEBUG(0,("Failed to setup an ldap connection timeout %d: %s\n",
682 (int)ct.tv_sec, ldap_err2string(rc)));
685 #endif
687 return LDAP_SUCCESS;
690 /********************************************************************
691 try to upgrade to Version 3 LDAP if not already, in either case return current
692 version
693 *******************************************************************/
695 static int smb_ldap_upgrade_conn(LDAP *ldap_struct, int *new_version)
697 int version;
698 int rc;
700 /* assume the worst */
701 *new_version = LDAP_VERSION2;
703 rc = ldap_get_option(ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
704 if (rc) {
705 return rc;
708 if (version == LDAP_VERSION3) {
709 *new_version = LDAP_VERSION3;
710 return LDAP_SUCCESS;
713 /* try upgrade */
714 version = LDAP_VERSION3;
715 rc = ldap_set_option (ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
716 if (rc) {
717 return rc;
720 *new_version = LDAP_VERSION3;
721 return LDAP_SUCCESS;
724 /*******************************************************************
725 open a connection to the ldap server (just until the bind)
726 ******************************************************************/
728 int smbldap_setup_full_conn(LDAP **ldap_struct, const char *uri)
730 int rc, version;
732 rc = smb_ldap_setup_conn(ldap_struct, uri);
733 if (rc) {
734 return rc;
737 rc = smb_ldap_upgrade_conn(*ldap_struct, &version);
738 if (rc) {
739 return rc;
742 rc = smbldap_start_tls(*ldap_struct, version);
743 if (rc) {
744 return rc;
747 return LDAP_SUCCESS;
750 /*******************************************************************
751 open a connection to the ldap server.
752 ******************************************************************/
753 static int smbldap_open_connection (struct smbldap_state *ldap_state)
756 int rc = LDAP_SUCCESS;
757 int version;
758 int deref;
759 LDAP **ldap_struct = &ldap_state->ldap_struct;
761 rc = smb_ldap_setup_conn(ldap_struct, ldap_state->uri);
762 if (rc) {
763 return rc;
766 /* Store the LDAP pointer in a lookup list */
768 smbldap_store_state(*ldap_struct, ldap_state);
770 /* Upgrade to LDAPv3 if possible */
772 rc = smb_ldap_upgrade_conn(*ldap_struct, &version);
773 if (rc) {
774 return rc;
777 /* Start TLS if required */
779 rc = smbldap_start_tls(*ldap_struct, version);
780 if (rc) {
781 return rc;
784 /* Set alias dereferencing method */
785 deref = lp_ldap_deref();
786 if (deref != -1) {
787 if (ldap_set_option (*ldap_struct, LDAP_OPT_DEREF, &deref) != LDAP_OPT_SUCCESS) {
788 DEBUG(1,("smbldap_open_connection: Failed to set dereferencing method: %d\n", deref));
789 } else {
790 DEBUG(5,("Set dereferencing method: %d\n", deref));
794 DEBUG(2, ("smbldap_open_connection: connection opened\n"));
795 return rc;
798 /*******************************************************************
799 a rebind function for authenticated referrals
800 This version takes a void* that we can shove useful stuff in :-)
801 ******************************************************************/
802 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
803 #else
804 static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
805 int *methodp, int freeit, void *arg)
807 struct smbldap_state *ldap_state = arg;
808 struct timespec ts;
810 /** @TODO Should we be doing something to check what servers we rebind to?
811 Could we get a referral to a machine that we don't want to give our
812 username and password to? */
814 if (freeit) {
815 SAFE_FREE(*whop);
816 if (*credp) {
817 memset(*credp, '\0', strlen(*credp));
819 SAFE_FREE(*credp);
820 } else {
821 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
822 ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
824 if (ldap_state->anonymous) {
825 *whop = NULL;
826 *credp = NULL;
827 } else {
828 *whop = SMB_STRDUP(ldap_state->bind_dn);
829 if (!*whop) {
830 return LDAP_NO_MEMORY;
832 *credp = SMB_STRDUP(ldap_state->bind_secret);
833 if (!*credp) {
834 SAFE_FREE(*whop);
835 return LDAP_NO_MEMORY;
838 *methodp = LDAP_AUTH_SIMPLE;
841 clock_gettime_mono(&ts);
842 ldap_state->last_rebind = convert_timespec_to_timeval(ts);
844 return 0;
846 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
848 /*******************************************************************
849 a rebind function for authenticated referrals
850 This version takes a void* that we can shove useful stuff in :-)
851 and actually does the connection.
852 ******************************************************************/
853 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
854 static int rebindproc_connect_with_state (LDAP *ldap_struct,
855 LDAP_CONST char *url,
856 ber_tag_t request,
857 ber_int_t msgid, void *arg)
859 struct smbldap_state *ldap_state =
860 (struct smbldap_state *)arg;
861 int rc;
862 struct timespec ts;
863 int version;
865 DEBUG(5,("rebindproc_connect_with_state: Rebinding to %s as \"%s\"\n",
866 url, ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
868 /* call START_TLS again (ldaps:// is handled by the OpenLDAP library
869 * itself) before rebinding to another LDAP server to avoid to expose
870 * our credentials. At least *try* to secure the connection - Guenther */
872 smb_ldap_upgrade_conn(ldap_struct, &version);
873 smbldap_start_tls(ldap_struct, version);
875 /** @TODO Should we be doing something to check what servers we rebind to?
876 Could we get a referral to a machine that we don't want to give our
877 username and password to? */
879 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
881 /* only set the last rebind timestamp when we did rebind after a
882 * non-read LDAP operation. That way we avoid the replication sleep
883 * after a simple redirected search operation - Guenther */
885 switch (request) {
887 case LDAP_REQ_MODIFY:
888 case LDAP_REQ_ADD:
889 case LDAP_REQ_DELETE:
890 case LDAP_REQ_MODDN:
891 case LDAP_REQ_EXTENDED:
892 DEBUG(10,("rebindproc_connect_with_state: "
893 "setting last_rebind timestamp "
894 "(req: 0x%02x)\n", (unsigned int)request));
895 clock_gettime_mono(&ts);
896 ldap_state->last_rebind = convert_timespec_to_timeval(ts);
897 break;
898 default:
899 ZERO_STRUCT(ldap_state->last_rebind);
900 break;
903 return rc;
905 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
907 /*******************************************************************
908 Add a rebind function for authenticated referrals
909 ******************************************************************/
910 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
911 #else
912 # if LDAP_SET_REBIND_PROC_ARGS == 2
913 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
914 int *method, int freeit )
916 struct smbldap_state *ldap_state = smbldap_find_state(ldap_struct);
918 return rebindproc_with_state(ldap_struct, whop, credp,
919 method, freeit, ldap_state);
921 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
922 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
924 /*******************************************************************
925 a rebind function for authenticated referrals
926 this also does the connection, but no void*.
927 ******************************************************************/
928 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
929 # if LDAP_SET_REBIND_PROC_ARGS == 2
930 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
931 ber_int_t msgid)
933 struct smbldap_state *ldap_state = smbldap_find_state(ld);
935 return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid,
936 ldap_state);
938 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
939 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
941 /*******************************************************************
942 connect to the ldap server under system privilege.
943 ******************************************************************/
944 static int smbldap_connect_system(struct smbldap_state *ldap_state)
946 LDAP *ldap_struct = ldap_state->ldap_struct;
947 int rc;
948 int version;
950 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
951 (OpenLDAP) doesnt' seem to support it */
953 DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
954 ldap_state->uri, ldap_state->bind_dn));
956 #ifdef HAVE_LDAP_SET_REBIND_PROC
957 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
958 # if LDAP_SET_REBIND_PROC_ARGS == 2
959 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect);
960 # endif
961 # if LDAP_SET_REBIND_PROC_ARGS == 3
962 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);
963 # endif
964 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
965 # if LDAP_SET_REBIND_PROC_ARGS == 2
966 ldap_set_rebind_proc(ldap_struct, &rebindproc);
967 # endif
968 # if LDAP_SET_REBIND_PROC_ARGS == 3
969 ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);
970 # endif
971 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
972 #endif
974 /* When there is an alternative bind callback is set,
975 attempt to use it to perform the bind */
976 if (ldap_state->bind_callback != NULL) {
977 /* We have to allow bind callback to be run under become_root/unbecome_root
978 to make sure within smbd the callback has proper write access to its resources,
979 like credential cache. This is similar to passdb case where this callback is supposed
980 to be used. When used outside smbd, become_root()/unbecome_root() are no-op.
982 become_root();
983 rc = ldap_state->bind_callback(ldap_struct, ldap_state, ldap_state->bind_callback_data);
984 unbecome_root();
985 } else {
986 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
989 if (rc != LDAP_SUCCESS) {
990 char *ld_error = NULL;
991 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
992 &ld_error);
993 DEBUG(ldap_state->num_failures ? 2 : 0,
994 ("failed to bind to server %s with dn=\"%s\" Error: %s\n\t%s\n",
995 ldap_state->uri,
996 ldap_state->bind_dn ? ldap_state->bind_dn : "[Anonymous bind]",
997 ldap_err2string(rc),
998 ld_error ? ld_error : "(unknown)"));
999 SAFE_FREE(ld_error);
1000 ldap_state->num_failures++;
1001 goto done;
1004 ldap_state->num_failures = 0;
1005 ldap_state->paged_results = False;
1007 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
1009 if (smbldap_has_control(ldap_state->ldap_struct, ADS_PAGE_CTL_OID) && version == 3) {
1010 ldap_state->paged_results = True;
1013 DEBUG(3, ("ldap_connect_system: successful connection to the LDAP server\n"));
1014 DEBUGADD(10, ("ldap_connect_system: LDAP server %s support paged results\n",
1015 ldap_state->paged_results ? "does" : "does not"));
1016 done:
1017 if (rc != 0) {
1018 ldap_unbind(ldap_struct);
1019 ldap_state->ldap_struct = NULL;
1021 return rc;
1024 static void smbldap_idle_fn(struct tevent_context *tevent_ctx,
1025 struct timed_event *te,
1026 struct timeval now_abs,
1027 void *private_data);
1029 /**********************************************************************
1030 Connect to LDAP server (called before every ldap operation)
1031 *********************************************************************/
1032 static int smbldap_open(struct smbldap_state *ldap_state)
1034 int rc, opt_rc;
1035 bool reopen = False;
1036 SMB_ASSERT(ldap_state);
1038 if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + SMBLDAP_DONT_PING_TIME) < time_mono(NULL))) {
1040 #ifdef HAVE_UNIXSOCKET
1041 struct sockaddr_un addr;
1042 #else
1043 struct sockaddr addr;
1044 #endif
1045 socklen_t len = sizeof(addr);
1046 int sd;
1048 opt_rc = ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd);
1049 if (opt_rc == 0 && (getpeername(sd, (struct sockaddr *) &addr, &len)) < 0 )
1050 reopen = True;
1052 #ifdef HAVE_UNIXSOCKET
1053 if (opt_rc == 0 && addr.sun_family == AF_UNIX)
1054 reopen = True;
1055 #endif
1056 if (reopen) {
1057 /* the other end has died. reopen. */
1058 ldap_unbind(ldap_state->ldap_struct);
1059 ldap_state->ldap_struct = NULL;
1060 ldap_state->last_ping = (time_t)0;
1061 } else {
1062 ldap_state->last_ping = time_mono(NULL);
1066 if (ldap_state->ldap_struct != NULL) {
1067 DEBUG(11,("smbldap_open: already connected to the LDAP server\n"));
1068 return LDAP_SUCCESS;
1071 if ((rc = smbldap_open_connection(ldap_state))) {
1072 return rc;
1075 if ((rc = smbldap_connect_system(ldap_state))) {
1076 return rc;
1080 ldap_state->last_ping = time_mono(NULL);
1081 ldap_state->pid = getpid();
1083 TALLOC_FREE(ldap_state->idle_event);
1085 if (ldap_state->tevent_context != NULL) {
1086 ldap_state->idle_event = tevent_add_timer(
1087 ldap_state->tevent_context, ldap_state,
1088 timeval_current_ofs(SMBLDAP_IDLE_TIME, 0),
1089 smbldap_idle_fn, ldap_state);
1092 DEBUG(4,("The LDAP server is successfully connected\n"));
1094 return LDAP_SUCCESS;
1097 /**********************************************************************
1098 Disconnect from LDAP server
1099 *********************************************************************/
1100 static NTSTATUS smbldap_close(struct smbldap_state *ldap_state)
1102 if (!ldap_state)
1103 return NT_STATUS_INVALID_PARAMETER;
1105 if (ldap_state->ldap_struct != NULL) {
1106 ldap_unbind(ldap_state->ldap_struct);
1107 ldap_state->ldap_struct = NULL;
1110 smbldap_delete_state(ldap_state);
1112 TALLOC_FREE(ldap_state->idle_event);
1114 DEBUG(5,("The connection to the LDAP server was closed\n"));
1115 /* maybe free the results here --metze */
1117 return NT_STATUS_OK;
1120 static SIG_ATOMIC_T got_alarm;
1122 static void gotalarm_sig(int dummy)
1124 got_alarm = 1;
1127 static time_t calc_ldap_abs_endtime(int ldap_to)
1129 if (ldap_to == 0) {
1130 /* No timeout - don't
1131 return a value for
1132 the alarm. */
1133 return (time_t)0;
1136 /* Make the alarm time one second beyond
1137 the timout we're setting for the
1138 remote search timeout, to allow that
1139 to fire in preference. */
1141 return time_mono(NULL)+ldap_to+1;
1144 static int end_ldap_local_alarm(time_t absolute_endtime, int rc)
1146 if (absolute_endtime) {
1147 alarm(0);
1148 CatchSignal(SIGALRM, SIG_IGN);
1149 if (got_alarm) {
1150 /* Client timeout error code. */
1151 got_alarm = 0;
1152 return LDAP_TIMEOUT;
1155 return rc;
1158 static void setup_ldap_local_alarm(struct smbldap_state *ldap_state, time_t absolute_endtime)
1160 time_t now = time_mono(NULL);
1162 if (absolute_endtime) {
1163 got_alarm = 0;
1164 CatchSignal(SIGALRM, gotalarm_sig);
1165 alarm(absolute_endtime - now);
1168 if (ldap_state->pid != getpid()) {
1169 smbldap_close(ldap_state);
1173 static void get_ldap_errs(struct smbldap_state *ldap_state, char **pp_ld_error, int *p_ld_errno)
1175 ldap_get_option(ldap_state->ldap_struct,
1176 LDAP_OPT_ERROR_NUMBER, p_ld_errno);
1178 ldap_get_option(ldap_state->ldap_struct,
1179 LDAP_OPT_ERROR_STRING, pp_ld_error);
1182 static int get_cached_ldap_connect(struct smbldap_state *ldap_state, time_t abs_endtime)
1184 int attempts = 0;
1186 while (1) {
1187 int rc;
1188 time_t now;
1190 now = time_mono(NULL);
1191 ldap_state->last_use = now;
1193 if (abs_endtime && now > abs_endtime) {
1194 smbldap_close(ldap_state);
1195 return LDAP_TIMEOUT;
1198 rc = smbldap_open(ldap_state);
1200 if (rc == LDAP_SUCCESS) {
1201 return LDAP_SUCCESS;
1204 attempts++;
1205 DEBUG(1, ("Connection to LDAP server failed for the "
1206 "%d try!\n", attempts));
1208 if (rc == LDAP_INSUFFICIENT_ACCESS) {
1209 /* The fact that we are non-root or any other
1210 * access-denied condition will not change in the next
1211 * round of trying */
1212 return rc;
1215 if (got_alarm) {
1216 smbldap_close(ldap_state);
1217 return LDAP_TIMEOUT;
1220 smb_msleep(1000);
1222 if (got_alarm) {
1223 smbldap_close(ldap_state);
1224 return LDAP_TIMEOUT;
1229 /*********************************************************************
1230 ********************************************************************/
1232 static int smbldap_search_ext(struct smbldap_state *ldap_state,
1233 const char *base, int scope, const char *filter,
1234 const char *attrs[], int attrsonly,
1235 LDAPControl **sctrls, LDAPControl **cctrls,
1236 int sizelimit, LDAPMessage **res)
1238 int rc = LDAP_SERVER_DOWN;
1239 char *utf8_filter;
1240 int to = lp_ldap_timeout();
1241 time_t abs_endtime = calc_ldap_abs_endtime(to);
1242 struct timeval timeout;
1243 struct timeval *timeout_ptr = NULL;
1244 size_t converted_size;
1246 SMB_ASSERT(ldap_state);
1248 DEBUG(5,("smbldap_search_ext: base => [%s], filter => [%s], "
1249 "scope => [%d]\n", base, filter, scope));
1251 if (ldap_state->last_rebind.tv_sec > 0) {
1252 struct timeval tval;
1253 struct timespec ts;
1254 int64_t tdiff = 0;
1255 int sleep_time = 0;
1257 clock_gettime_mono(&ts);
1258 tval = convert_timespec_to_timeval(ts);
1260 tdiff = usec_time_diff(&tval, &ldap_state->last_rebind);
1261 tdiff /= 1000; /* Convert to milliseconds. */
1263 sleep_time = lp_ldap_replication_sleep()-(int)tdiff;
1264 sleep_time = MIN(sleep_time, MAX_LDAP_REPLICATION_SLEEP_TIME);
1266 if (sleep_time > 0) {
1267 /* we wait for the LDAP replication */
1268 DEBUG(5,("smbldap_search_ext: waiting %d milliseconds "
1269 "for LDAP replication.\n",sleep_time));
1270 smb_msleep(sleep_time);
1271 DEBUG(5,("smbldap_search_ext: go on!\n"));
1273 ZERO_STRUCT(ldap_state->last_rebind);
1276 if (!push_utf8_talloc(talloc_tos(), &utf8_filter, filter, &converted_size)) {
1277 return LDAP_NO_MEMORY;
1280 /* Setup remote timeout for the ldap_search_ext_s call. */
1281 if (to) {
1282 timeout.tv_sec = to;
1283 timeout.tv_usec = 0;
1284 timeout_ptr = &timeout;
1287 setup_ldap_local_alarm(ldap_state, abs_endtime);
1289 while (1) {
1290 char *ld_error = NULL;
1291 int ld_errno;
1293 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1294 if (rc != LDAP_SUCCESS) {
1295 break;
1298 rc = ldap_search_ext_s(ldap_state->ldap_struct, base, scope,
1299 utf8_filter,
1300 discard_const_p(char *, attrs),
1301 attrsonly, sctrls, cctrls, timeout_ptr,
1302 sizelimit, res);
1303 if (rc == LDAP_SUCCESS) {
1304 break;
1307 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1309 DEBUG(10, ("Failed search for base: %s, error: %d (%s) "
1310 "(%s)\n", base, ld_errno,
1311 ldap_err2string(rc),
1312 ld_error ? ld_error : "unknown"));
1313 SAFE_FREE(ld_error);
1315 if (ld_errno != LDAP_SERVER_DOWN) {
1316 break;
1318 ldap_unbind(ldap_state->ldap_struct);
1319 ldap_state->ldap_struct = NULL;
1322 TALLOC_FREE(utf8_filter);
1323 return end_ldap_local_alarm(abs_endtime, rc);
1326 int smbldap_search(struct smbldap_state *ldap_state,
1327 const char *base, int scope, const char *filter,
1328 const char *attrs[], int attrsonly,
1329 LDAPMessage **res)
1331 return smbldap_search_ext(ldap_state, base, scope, filter, attrs,
1332 attrsonly, NULL, NULL, LDAP_NO_LIMIT, res);
1335 int smbldap_search_paged(struct smbldap_state *ldap_state,
1336 const char *base, int scope, const char *filter,
1337 const char **attrs, int attrsonly, int pagesize,
1338 LDAPMessage **res, void **cookie)
1340 LDAPControl pr;
1341 LDAPControl **rcontrols;
1342 LDAPControl *controls[2] = { NULL, NULL};
1343 BerElement *cookie_be = NULL;
1344 struct berval *cookie_bv = NULL;
1345 int tmp = 0, i, rc;
1346 bool critical = True;
1348 *res = NULL;
1350 DEBUG(3,("smbldap_search_paged: base => [%s], filter => [%s],"
1351 "scope => [%d], pagesize => [%d]\n",
1352 base, filter, scope, pagesize));
1354 cookie_be = ber_alloc_t(LBER_USE_DER);
1355 if (cookie_be == NULL) {
1356 DEBUG(0,("smbldap_create_page_control: ber_alloc_t returns "
1357 "NULL\n"));
1358 return LDAP_NO_MEMORY;
1361 /* construct cookie */
1362 if (*cookie != NULL) {
1363 ber_printf(cookie_be, "{iO}", (ber_int_t) pagesize, *cookie);
1364 ber_bvfree((struct berval *)*cookie); /* don't need it from last time */
1365 *cookie = NULL;
1366 } else {
1367 ber_printf(cookie_be, "{io}", (ber_int_t) pagesize, "", 0);
1369 ber_flatten(cookie_be, &cookie_bv);
1371 pr.ldctl_oid = discard_const_p(char, ADS_PAGE_CTL_OID);
1372 pr.ldctl_iscritical = (char) critical;
1373 pr.ldctl_value.bv_len = cookie_bv->bv_len;
1374 pr.ldctl_value.bv_val = cookie_bv->bv_val;
1376 controls[0] = &pr;
1377 controls[1] = NULL;
1379 rc = smbldap_search_ext(ldap_state, base, scope, filter, attrs,
1380 0, controls, NULL, LDAP_NO_LIMIT, res);
1382 ber_free(cookie_be, 1);
1383 ber_bvfree(cookie_bv);
1385 if (rc != 0) {
1386 DEBUG(3,("smbldap_search_paged: smbldap_search_ext(%s) "
1387 "failed with [%s]\n", filter, ldap_err2string(rc)));
1388 goto done;
1391 DEBUG(3,("smbldap_search_paged: search was successful\n"));
1393 rc = ldap_parse_result(ldap_state->ldap_struct, *res, NULL, NULL,
1394 NULL, NULL, &rcontrols, 0);
1395 if (rc != 0) {
1396 DEBUG(3,("smbldap_search_paged: ldap_parse_result failed " \
1397 "with [%s]\n", ldap_err2string(rc)));
1398 goto done;
1401 if (rcontrols == NULL)
1402 goto done;
1404 for (i=0; rcontrols[i]; i++) {
1406 if (strcmp(ADS_PAGE_CTL_OID, rcontrols[i]->ldctl_oid) != 0)
1407 continue;
1409 cookie_be = ber_init(&rcontrols[i]->ldctl_value);
1410 ber_scanf(cookie_be,"{iO}", &tmp, &cookie_bv);
1411 /* the berval is the cookie, but must be freed when it is all
1412 done */
1413 if (cookie_bv->bv_len)
1414 *cookie=ber_bvdup(cookie_bv);
1415 else
1416 *cookie=NULL;
1417 ber_bvfree(cookie_bv);
1418 ber_free(cookie_be, 1);
1419 break;
1421 ldap_controls_free(rcontrols);
1422 done:
1423 return rc;
1426 int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
1428 int rc = LDAP_SERVER_DOWN;
1429 char *utf8_dn;
1430 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1431 size_t converted_size;
1433 SMB_ASSERT(ldap_state);
1435 DEBUG(5,("smbldap_modify: dn => [%s]\n", dn ));
1437 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1438 return LDAP_NO_MEMORY;
1441 setup_ldap_local_alarm(ldap_state, abs_endtime);
1443 while (1) {
1444 char *ld_error = NULL;
1445 int ld_errno;
1447 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1448 if (rc != LDAP_SUCCESS) {
1449 break;
1452 rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs);
1453 if (rc == LDAP_SUCCESS) {
1454 break;
1457 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1459 DEBUG(10, ("Failed to modify dn: %s, error: %d (%s) "
1460 "(%s)\n", dn, ld_errno,
1461 ldap_err2string(rc),
1462 ld_error ? ld_error : "unknown"));
1463 SAFE_FREE(ld_error);
1465 if (ld_errno != LDAP_SERVER_DOWN) {
1466 break;
1468 ldap_unbind(ldap_state->ldap_struct);
1469 ldap_state->ldap_struct = NULL;
1472 TALLOC_FREE(utf8_dn);
1473 return end_ldap_local_alarm(abs_endtime, rc);
1476 int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
1478 int rc = LDAP_SERVER_DOWN;
1479 char *utf8_dn;
1480 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1481 size_t converted_size;
1483 SMB_ASSERT(ldap_state);
1485 DEBUG(5,("smbldap_add: dn => [%s]\n", dn ));
1487 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1488 return LDAP_NO_MEMORY;
1491 setup_ldap_local_alarm(ldap_state, abs_endtime);
1493 while (1) {
1494 char *ld_error = NULL;
1495 int ld_errno;
1497 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1498 if (rc != LDAP_SUCCESS) {
1499 break;
1502 rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs);
1503 if (rc == LDAP_SUCCESS) {
1504 break;
1507 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1509 DEBUG(10, ("Failed to add dn: %s, error: %d (%s) "
1510 "(%s)\n", dn, ld_errno,
1511 ldap_err2string(rc),
1512 ld_error ? ld_error : "unknown"));
1513 SAFE_FREE(ld_error);
1515 if (ld_errno != LDAP_SERVER_DOWN) {
1516 break;
1518 ldap_unbind(ldap_state->ldap_struct);
1519 ldap_state->ldap_struct = NULL;
1522 TALLOC_FREE(utf8_dn);
1523 return end_ldap_local_alarm(abs_endtime, rc);
1526 int smbldap_delete(struct smbldap_state *ldap_state, const char *dn)
1528 int rc = LDAP_SERVER_DOWN;
1529 char *utf8_dn;
1530 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1531 size_t converted_size;
1533 SMB_ASSERT(ldap_state);
1535 DEBUG(5,("smbldap_delete: dn => [%s]\n", dn ));
1537 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1538 return LDAP_NO_MEMORY;
1541 setup_ldap_local_alarm(ldap_state, abs_endtime);
1543 while (1) {
1544 char *ld_error = NULL;
1545 int ld_errno;
1547 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1548 if (rc != LDAP_SUCCESS) {
1549 break;
1552 rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn);
1553 if (rc == LDAP_SUCCESS) {
1554 break;
1557 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1559 DEBUG(10, ("Failed to delete dn: %s, error: %d (%s) "
1560 "(%s)\n", dn, ld_errno,
1561 ldap_err2string(rc),
1562 ld_error ? ld_error : "unknown"));
1563 SAFE_FREE(ld_error);
1565 if (ld_errno != LDAP_SERVER_DOWN) {
1566 break;
1568 ldap_unbind(ldap_state->ldap_struct);
1569 ldap_state->ldap_struct = NULL;
1572 TALLOC_FREE(utf8_dn);
1573 return end_ldap_local_alarm(abs_endtime, rc);
1576 int smbldap_extended_operation(struct smbldap_state *ldap_state,
1577 LDAP_CONST char *reqoid, struct berval *reqdata,
1578 LDAPControl **serverctrls, LDAPControl **clientctrls,
1579 char **retoidp, struct berval **retdatap)
1581 int rc = LDAP_SERVER_DOWN;
1582 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1584 if (!ldap_state)
1585 return (-1);
1587 setup_ldap_local_alarm(ldap_state, abs_endtime);
1589 while (1) {
1590 char *ld_error = NULL;
1591 int ld_errno;
1593 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1594 if (rc != LDAP_SUCCESS) {
1595 break;
1598 rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid,
1599 reqdata, serverctrls,
1600 clientctrls, retoidp, retdatap);
1601 if (rc == LDAP_SUCCESS) {
1602 break;
1605 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1607 DEBUG(10, ("Extended operation failed with error: "
1608 "%d (%s) (%s)\n", ld_errno,
1609 ldap_err2string(rc),
1610 ld_error ? ld_error : "unknown"));
1611 SAFE_FREE(ld_error);
1613 if (ld_errno != LDAP_SERVER_DOWN) {
1614 break;
1616 ldap_unbind(ldap_state->ldap_struct);
1617 ldap_state->ldap_struct = NULL;
1620 return end_ldap_local_alarm(abs_endtime, rc);
1623 /*******************************************************************
1624 run the search by name.
1625 ******************************************************************/
1626 int smbldap_search_suffix (struct smbldap_state *ldap_state,
1627 const char *filter, const char **search_attr,
1628 LDAPMessage ** result)
1630 return smbldap_search(ldap_state, lp_ldap_suffix(talloc_tos()),
1631 LDAP_SCOPE_SUBTREE,
1632 filter, search_attr, 0, result);
1635 static void smbldap_idle_fn(struct tevent_context *tevent_ctx,
1636 struct timed_event *te,
1637 struct timeval now_abs,
1638 void *private_data)
1640 struct smbldap_state *state = (struct smbldap_state *)private_data;
1642 TALLOC_FREE(state->idle_event);
1644 if (state->ldap_struct == NULL) {
1645 DEBUG(10,("ldap connection not connected...\n"));
1646 return;
1649 if ((state->last_use+SMBLDAP_IDLE_TIME) > time_mono(NULL)) {
1650 DEBUG(10,("ldap connection not idle...\n"));
1652 /* this needs to be made monotonic clock aware inside tevent: */
1653 state->idle_event = tevent_add_timer(
1654 tevent_ctx, state,
1655 timeval_add(&now_abs, SMBLDAP_IDLE_TIME, 0),
1656 smbldap_idle_fn,
1657 private_data);
1658 return;
1661 DEBUG(7,("ldap connection idle...closing connection\n"));
1662 smbldap_close(state);
1665 /**********************************************************************
1666 Housekeeping
1667 *********************************************************************/
1669 void smbldap_free_struct(struct smbldap_state **ldap_state)
1671 smbldap_close(*ldap_state);
1673 if ((*ldap_state)->bind_secret) {
1674 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
1677 SAFE_FREE((*ldap_state)->bind_dn);
1678 SAFE_FREE((*ldap_state)->bind_secret);
1679 (*ldap_state)->bind_callback = NULL;
1680 (*ldap_state)->bind_callback_data = NULL;
1682 TALLOC_FREE(*ldap_state);
1684 /* No need to free any further, as it is talloc()ed */
1687 static int smbldap_state_destructor(struct smbldap_state *state)
1689 smbldap_free_struct(&state);
1690 return 0;
1694 /**********************************************************************
1695 Intitalise the 'general' ldap structures, on which ldap operations may be conducted
1696 *********************************************************************/
1698 NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, struct tevent_context *tevent_ctx,
1699 const char *location,
1700 bool anon,
1701 const char *bind_dn,
1702 const char *bind_secret,
1703 struct smbldap_state **smbldap_state)
1705 *smbldap_state = talloc_zero(mem_ctx, struct smbldap_state);
1706 if (!*smbldap_state) {
1707 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
1708 return NT_STATUS_NO_MEMORY;
1711 if (location) {
1712 (*smbldap_state)->uri = talloc_strdup(mem_ctx, location);
1713 } else {
1714 (*smbldap_state)->uri = "ldap://localhost";
1717 (*smbldap_state)->tevent_context = tevent_ctx;
1719 if (bind_dn && bind_secret) {
1720 smbldap_set_creds(*smbldap_state, anon, bind_dn, bind_secret);
1723 talloc_set_destructor(*smbldap_state, smbldap_state_destructor);
1724 return NT_STATUS_OK;
1727 char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld,
1728 LDAPMessage *entry)
1730 char *utf8_dn, *unix_dn;
1731 size_t converted_size;
1733 utf8_dn = ldap_get_dn(ld, entry);
1734 if (!utf8_dn) {
1735 DEBUG (5, ("smbldap_talloc_dn: ldap_get_dn failed\n"));
1736 return NULL;
1738 if (!pull_utf8_talloc(mem_ctx, &unix_dn, utf8_dn, &converted_size)) {
1739 DEBUG (0, ("smbldap_talloc_dn: String conversion failure utf8 "
1740 "[%s]\n", utf8_dn));
1741 return NULL;
1743 ldap_memfree(utf8_dn);
1744 return unix_dn;
1747 /*******************************************************************
1748 Check if root-dse has a certain Control or Extension
1749 ********************************************************************/
1751 static bool smbldap_check_root_dse(LDAP *ld, const char **attrs, const char *value)
1753 LDAPMessage *msg = NULL;
1754 LDAPMessage *entry = NULL;
1755 char **values = NULL;
1756 int rc, num_result, num_values, i;
1757 bool result = False;
1759 if (!attrs[0]) {
1760 DEBUG(3,("smbldap_check_root_dse: nothing to look for\n"));
1761 return False;
1764 if (!strequal(attrs[0], "supportedExtension") &&
1765 !strequal(attrs[0], "supportedControl") &&
1766 !strequal(attrs[0], "namingContexts")) {
1767 DEBUG(3,("smbldap_check_root_dse: no idea what to query root-dse for: %s ?\n", attrs[0]));
1768 return False;
1771 rc = ldap_search_s(ld, "", LDAP_SCOPE_BASE,
1772 "(objectclass=*)", discard_const_p(char *, attrs), 0 , &msg);
1774 if (rc != LDAP_SUCCESS) {
1775 DEBUG(3,("smbldap_check_root_dse: Could not search rootDSE\n"));
1776 return False;
1779 num_result = ldap_count_entries(ld, msg);
1781 if (num_result != 1) {
1782 DEBUG(3,("smbldap_check_root_dse: Expected one rootDSE, got %d\n", num_result));
1783 goto done;
1786 entry = ldap_first_entry(ld, msg);
1788 if (entry == NULL) {
1789 DEBUG(3,("smbldap_check_root_dse: Could not retrieve rootDSE\n"));
1790 goto done;
1793 values = ldap_get_values(ld, entry, attrs[0]);
1795 if (values == NULL) {
1796 DEBUG(5,("smbldap_check_root_dse: LDAP Server does not support any %s\n", attrs[0]));
1797 goto done;
1800 num_values = ldap_count_values(values);
1802 if (num_values == 0) {
1803 DEBUG(5,("smbldap_check_root_dse: LDAP Server does not have any %s\n", attrs[0]));
1804 goto done;
1807 for (i=0; i<num_values; i++) {
1808 if (strcmp(values[i], value) == 0)
1809 result = True;
1813 done:
1814 if (values != NULL)
1815 ldap_value_free(values);
1816 if (msg != NULL)
1817 ldap_msgfree(msg);
1819 return result;
1823 /*******************************************************************
1824 Check if LDAP-Server supports a certain Control (OID in string format)
1825 ********************************************************************/
1827 bool smbldap_has_control(LDAP *ld, const char *control)
1829 const char *attrs[] = { "supportedControl", NULL };
1830 return smbldap_check_root_dse(ld, attrs, control);
1833 /*******************************************************************
1834 Check if LDAP-Server supports a certain Extension (OID in string format)
1835 ********************************************************************/
1837 bool smbldap_has_extension(LDAP *ld, const char *extension)
1839 const char *attrs[] = { "supportedExtension", NULL };
1840 return smbldap_check_root_dse(ld, attrs, extension);
1843 /*******************************************************************
1844 Check if LDAP-Server holds a given namingContext
1845 ********************************************************************/
1847 bool smbldap_has_naming_context(LDAP *ld, const char *naming_context)
1849 const char *attrs[] = { "namingContexts", NULL };
1850 return smbldap_check_root_dse(ld, attrs, naming_context);
1853 bool smbldap_set_creds(struct smbldap_state *ldap_state, bool anon, const char *dn, const char *secret)
1855 ldap_state->anonymous = anon;
1857 /* free any previously set credential */
1859 SAFE_FREE(ldap_state->bind_dn);
1860 ldap_state->bind_callback = NULL;
1861 ldap_state->bind_callback_data = NULL;
1863 if (ldap_state->bind_secret) {
1864 /* make sure secrets are zeroed out of memory */
1865 memset(ldap_state->bind_secret, '\0', strlen(ldap_state->bind_secret));
1866 SAFE_FREE(ldap_state->bind_secret);
1869 if ( ! anon) {
1870 ldap_state->bind_dn = SMB_STRDUP(dn);
1871 ldap_state->bind_secret = SMB_STRDUP(secret);
1874 return True;