build: reduce printf() calls in generated build_options.c
[Samba.git] / source3 / lib / smbldap.c
blob4815dd81fc38d852a4c21f167a8f2545f075bc8c
1 /*
2 Unix SMB/CIFS implementation.
3 LDAP protocol helper functions for SAMBA
4 Copyright (C) Jean François Micouleau 1998
5 Copyright (C) Gerald Carter 2001-2003
6 Copyright (C) Shahms King 2001
7 Copyright (C) Andrew Bartlett 2002-2003
8 Copyright (C) Stefan (metze) Metzmacher 2002-2003
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "smbldap.h"
27 #include "../libcli/security/security.h"
28 #include <tevent.h>
29 #include "lib/param/loadparm.h"
31 /* Try not to hit the up or down server forever */
33 #define SMBLDAP_DONT_PING_TIME 10 /* ping only all 10 seconds */
34 #define SMBLDAP_NUM_RETRIES 8 /* retry only 8 times */
36 #define SMBLDAP_IDLE_TIME 150 /* After 2.5 minutes disconnect */
38 struct smbldap_state {
39 LDAP *ldap_struct;
40 pid_t pid;
41 time_t last_ping; /* monotonic */
42 /* retrieve-once info */
43 const char *uri;
45 /* credentials */
46 bool anonymous;
47 char *bind_dn;
48 char *bind_secret;
49 smbldap_bind_callback_fn bind_callback;
50 void *bind_callback_data;
52 bool paged_results;
54 unsigned int num_failures;
56 time_t last_use; /* monotonic */
57 struct tevent_context *tevent_context;
58 struct tevent_timer *idle_event;
60 struct timeval last_rebind; /* monotonic */
63 LDAP *smbldap_get_ldap(struct smbldap_state *state)
65 return state->ldap_struct;
68 bool smbldap_get_paged_results(struct smbldap_state *state)
70 return state->paged_results;
73 void smbldap_set_paged_results(struct smbldap_state *state,
74 bool paged_results)
76 state->paged_results = paged_results;
79 void smbldap_set_bind_callback(struct smbldap_state *state,
80 smbldap_bind_callback_fn callback,
81 void *callback_data)
83 state->bind_callback = callback;
84 state->bind_callback_data = callback_data;
86 /*******************************************************************
87 Search an attribute and return the first value found.
88 ******************************************************************/
90 bool smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
91 const char *attribute, char *value,
92 int max_len)
94 char **values;
95 size_t size = 0;
97 if ( !attribute )
98 return False;
100 value[0] = '\0';
102 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
103 DEBUG (10, ("smbldap_get_single_attribute: [%s] = [<does not exist>]\n", attribute));
105 return False;
108 if (!convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, max_len, &size)) {
109 DEBUG(1, ("smbldap_get_single_attribute: string conversion of [%s] = [%s] failed!\n",
110 attribute, values[0]));
111 ldap_value_free(values);
112 return False;
115 ldap_value_free(values);
116 #ifdef DEBUG_PASSWORDS
117 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n", attribute, value));
118 #endif
119 return True;
122 char * smbldap_talloc_single_attribute(LDAP *ldap_struct, LDAPMessage *entry,
123 const char *attribute,
124 TALLOC_CTX *mem_ctx)
126 char **values;
127 char *result;
128 size_t converted_size;
130 if (attribute == NULL) {
131 return NULL;
134 values = ldap_get_values(ldap_struct, entry, attribute);
136 if (values == NULL) {
137 DEBUG(10, ("attribute %s does not exist\n", attribute));
138 return NULL;
141 if (ldap_count_values(values) != 1) {
142 DEBUG(10, ("attribute %s has %d values, expected only one\n",
143 attribute, ldap_count_values(values)));
144 ldap_value_free(values);
145 return NULL;
148 if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
149 DEBUG(10, ("pull_utf8_talloc failed\n"));
150 ldap_value_free(values);
151 return NULL;
154 ldap_value_free(values);
156 #ifdef DEBUG_PASSWORDS
157 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
158 attribute, result));
159 #endif
160 return result;
163 char * smbldap_talloc_first_attribute(LDAP *ldap_struct, LDAPMessage *entry,
164 const char *attribute,
165 TALLOC_CTX *mem_ctx)
167 char **values;
168 char *result;
169 size_t converted_size;
171 if (attribute == NULL) {
172 return NULL;
175 values = ldap_get_values(ldap_struct, entry, attribute);
177 if (values == NULL) {
178 DEBUG(10, ("attribute %s does not exist\n", attribute));
179 return NULL;
182 if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
183 DEBUG(10, ("pull_utf8_talloc failed\n"));
184 ldap_value_free(values);
185 return NULL;
188 ldap_value_free(values);
190 #ifdef DEBUG_PASSWORDS
191 DEBUG (100, ("smbldap_get_first_attribute: [%s] = [%s]\n",
192 attribute, result));
193 #endif
194 return result;
197 char * smbldap_talloc_smallest_attribute(LDAP *ldap_struct, LDAPMessage *entry,
198 const char *attribute,
199 TALLOC_CTX *mem_ctx)
201 char **values;
202 char *result;
203 size_t converted_size;
204 int i, num_values;
206 if (attribute == NULL) {
207 return NULL;
210 values = ldap_get_values(ldap_struct, entry, attribute);
212 if (values == NULL) {
213 DEBUG(10, ("attribute %s does not exist\n", attribute));
214 return NULL;
217 if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
218 DEBUG(10, ("pull_utf8_talloc failed\n"));
219 ldap_value_free(values);
220 return NULL;
223 num_values = ldap_count_values(values);
225 for (i=1; i<num_values; i++) {
226 char *tmp;
228 if (!pull_utf8_talloc(mem_ctx, &tmp, values[i],
229 &converted_size)) {
230 DEBUG(10, ("pull_utf8_talloc failed\n"));
231 TALLOC_FREE(result);
232 ldap_value_free(values);
233 return NULL;
236 if (strcasecmp_m(tmp, result) < 0) {
237 TALLOC_FREE(result);
238 result = tmp;
239 } else {
240 TALLOC_FREE(tmp);
244 ldap_value_free(values);
246 #ifdef DEBUG_PASSWORDS
247 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
248 attribute, result));
249 #endif
250 return result;
253 bool smbldap_talloc_single_blob(TALLOC_CTX *mem_ctx, LDAP *ld,
254 LDAPMessage *msg, const char *attrib,
255 DATA_BLOB *blob)
257 struct berval **values;
259 values = ldap_get_values_len(ld, msg, attrib);
260 if (!values) {
261 return false;
264 if (ldap_count_values_len(values) != 1) {
265 DEBUG(10, ("Expected one value for %s, got %d\n", attrib,
266 ldap_count_values_len(values)));
267 return false;
270 *blob = data_blob_talloc(mem_ctx, values[0]->bv_val,
271 values[0]->bv_len);
272 ldap_value_free_len(values);
274 return (blob->data != NULL);
277 bool smbldap_pull_sid(LDAP *ld, LDAPMessage *msg, const char *attrib,
278 struct dom_sid *sid)
280 DATA_BLOB blob;
281 ssize_t ret;
283 if (!smbldap_talloc_single_blob(talloc_tos(), ld, msg, attrib,
284 &blob)) {
285 return false;
287 ret = sid_parse(blob.data, blob.length, sid);
288 TALLOC_FREE(blob.data);
289 return (ret != -1);
292 static int ldapmsg_destructor(LDAPMessage **result) {
293 ldap_msgfree(*result);
294 return 0;
297 void smbldap_talloc_autofree_ldapmsg(TALLOC_CTX *mem_ctx, LDAPMessage *result)
299 LDAPMessage **handle;
301 if (result == NULL) {
302 return;
305 handle = talloc(mem_ctx, LDAPMessage *);
306 SMB_ASSERT(handle != NULL);
308 *handle = result;
309 talloc_set_destructor(handle, ldapmsg_destructor);
312 static int ldapmod_destructor(LDAPMod ***mod) {
313 ldap_mods_free(*mod, True);
314 return 0;
317 void smbldap_talloc_autofree_ldapmod(TALLOC_CTX *mem_ctx, LDAPMod **mod)
319 LDAPMod ***handle;
321 if (mod == NULL) {
322 return;
325 handle = talloc(mem_ctx, LDAPMod **);
326 SMB_ASSERT(handle != NULL);
328 *handle = mod;
329 talloc_set_destructor(handle, ldapmod_destructor);
332 /************************************************************************
333 Routine to manage the LDAPMod structure array
334 manage memory used by the array, by each struct, and values
335 ***********************************************************************/
337 static void smbldap_set_mod_internal(LDAPMod *** modlist, int modop, const char *attribute, const char *value, const DATA_BLOB *blob)
339 LDAPMod **mods;
340 int i;
341 int j;
343 mods = *modlist;
345 /* sanity checks on the mod values */
347 if (attribute == NULL || *attribute == '\0') {
348 return;
351 #if 0 /* commented out after discussion with abartlet. Do not re-enable.
352 left here so other do not re-add similar code --jerry */
353 if (value == NULL || *value == '\0')
354 return;
355 #endif
357 if (mods == NULL) {
358 mods = SMB_MALLOC_P(LDAPMod *);
359 if (mods == NULL) {
360 smb_panic("smbldap_set_mod: out of memory!");
361 /* notreached. */
363 mods[0] = NULL;
366 for (i = 0; mods[i] != NULL; ++i) {
367 if (mods[i]->mod_op == modop && strequal(mods[i]->mod_type, attribute))
368 break;
371 if (mods[i] == NULL) {
372 mods = SMB_REALLOC_ARRAY (mods, LDAPMod *, i + 2);
373 if (mods == NULL) {
374 smb_panic("smbldap_set_mod: out of memory!");
375 /* notreached. */
377 mods[i] = SMB_MALLOC_P(LDAPMod);
378 if (mods[i] == NULL) {
379 smb_panic("smbldap_set_mod: out of memory!");
380 /* notreached. */
382 mods[i]->mod_op = modop;
383 mods[i]->mod_values = NULL;
384 mods[i]->mod_type = SMB_STRDUP(attribute);
385 mods[i + 1] = NULL;
388 if (blob && (modop & LDAP_MOD_BVALUES)) {
389 j = 0;
390 if (mods[i]->mod_bvalues != NULL) {
391 for (; mods[i]->mod_bvalues[j] != NULL; j++);
393 mods[i]->mod_bvalues = SMB_REALLOC_ARRAY(mods[i]->mod_bvalues, struct berval *, j + 2);
395 if (mods[i]->mod_bvalues == NULL) {
396 smb_panic("smbldap_set_mod: out of memory!");
397 /* notreached. */
400 mods[i]->mod_bvalues[j] = SMB_MALLOC_P(struct berval);
401 SMB_ASSERT(mods[i]->mod_bvalues[j] != NULL);
403 mods[i]->mod_bvalues[j]->bv_val = (char *)smb_memdup(blob->data, blob->length);
404 SMB_ASSERT(mods[i]->mod_bvalues[j]->bv_val != NULL);
405 mods[i]->mod_bvalues[j]->bv_len = blob->length;
407 mods[i]->mod_bvalues[j + 1] = NULL;
408 } else if (value != NULL) {
409 char *utf8_value = NULL;
410 size_t converted_size;
412 j = 0;
413 if (mods[i]->mod_values != NULL) {
414 for (; mods[i]->mod_values[j] != NULL; j++);
416 mods[i]->mod_values = SMB_REALLOC_ARRAY(mods[i]->mod_values, char *, j + 2);
418 if (mods[i]->mod_values == NULL) {
419 smb_panic("smbldap_set_mod: out of memory!");
420 /* notreached. */
423 if (!push_utf8_talloc(talloc_tos(), &utf8_value, value, &converted_size)) {
424 smb_panic("smbldap_set_mod: String conversion failure!");
425 /* notreached. */
428 mods[i]->mod_values[j] = SMB_STRDUP(utf8_value);
429 TALLOC_FREE(utf8_value);
430 SMB_ASSERT(mods[i]->mod_values[j] != NULL);
432 mods[i]->mod_values[j + 1] = NULL;
434 *modlist = mods;
437 void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
439 smbldap_set_mod_internal(modlist, modop, attribute, value, NULL);
442 void smbldap_set_mod_blob(LDAPMod *** modlist, int modop, const char *attribute, const DATA_BLOB *value)
444 smbldap_set_mod_internal(modlist, modop | LDAP_MOD_BVALUES, attribute, NULL, value);
447 /**********************************************************************
448 Set attribute to newval in LDAP, regardless of what value the
449 attribute had in LDAP before.
450 *********************************************************************/
452 static void smbldap_make_mod_internal(LDAP *ldap_struct, LDAPMessage *existing,
453 LDAPMod ***mods,
454 const char *attribute, int op,
455 const char *newval,
456 const DATA_BLOB *newblob)
458 char oldval[2048]; /* current largest allowed value is mungeddial */
459 bool existed;
460 DATA_BLOB oldblob = data_blob_null;
462 if (existing != NULL) {
463 if (op & LDAP_MOD_BVALUES) {
464 existed = smbldap_talloc_single_blob(talloc_tos(), ldap_struct, existing, attribute, &oldblob);
465 } else {
466 existed = smbldap_get_single_attribute(ldap_struct, existing, attribute, oldval, sizeof(oldval));
468 } else {
469 existed = False;
470 *oldval = '\0';
473 if (existed) {
474 bool equal = false;
475 if (op & LDAP_MOD_BVALUES) {
476 equal = (newblob && (data_blob_cmp(&oldblob, newblob) == 0));
477 } else {
478 /* all of our string attributes are case insensitive */
479 equal = (newval && (strcasecmp_m(oldval, newval) == 0));
482 if (equal) {
483 /* Believe it or not, but LDAP will deny a delete and
484 an add at the same time if the values are the
485 same... */
486 DEBUG(10,("smbldap_make_mod: attribute |%s| not changed.\n", attribute));
487 return;
490 /* There has been no value before, so don't delete it.
491 * Here's a possible race: We might end up with
492 * duplicate attributes */
493 /* By deleting exactly the value we found in the entry this
494 * should be race-free in the sense that the LDAP-Server will
495 * deny the complete operation if somebody changed the
496 * attribute behind our back. */
497 /* This will also allow modifying single valued attributes
498 * in Novell NDS. In NDS you have to first remove attribute and then
499 * you could add new value */
501 if (op & LDAP_MOD_BVALUES) {
502 DEBUG(10,("smbldap_make_mod: deleting attribute |%s| blob\n", attribute));
503 smbldap_set_mod_blob(mods, LDAP_MOD_DELETE, attribute, &oldblob);
504 } else {
505 DEBUG(10,("smbldap_make_mod: deleting attribute |%s| values |%s|\n", attribute, oldval));
506 smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, oldval);
510 /* Regardless of the real operation (add or modify)
511 we add the new value here. We rely on deleting
512 the old value, should it exist. */
514 if (op & LDAP_MOD_BVALUES) {
515 if (newblob && newblob->length) {
516 DEBUG(10,("smbldap_make_mod: adding attribute |%s| blob\n", attribute));
517 smbldap_set_mod_blob(mods, LDAP_MOD_ADD, attribute, newblob);
519 } else {
520 if ((newval != NULL) && (strlen(newval) > 0)) {
521 DEBUG(10,("smbldap_make_mod: adding attribute |%s| value |%s|\n", attribute, newval));
522 smbldap_set_mod(mods, LDAP_MOD_ADD, attribute, newval);
527 void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing,
528 LDAPMod ***mods,
529 const char *attribute, const char *newval)
531 smbldap_make_mod_internal(ldap_struct, existing, mods, attribute,
532 0, newval, NULL);
535 void smbldap_make_mod_blob(LDAP *ldap_struct, LDAPMessage *existing,
536 LDAPMod ***mods,
537 const char *attribute, const DATA_BLOB *newblob)
539 smbldap_make_mod_internal(ldap_struct, existing, mods, attribute,
540 LDAP_MOD_BVALUES, NULL, newblob);
543 /**********************************************************************
544 Some varients of the LDAP rebind code do not pass in the third 'arg'
545 pointer to a void*, so we try and work around it by assuming that the
546 value of the 'LDAP *' pointer is the same as the one we had passed in
547 **********************************************************************/
549 struct smbldap_state_lookup {
550 LDAP *ld;
551 struct smbldap_state *smbldap_state;
552 struct smbldap_state_lookup *prev, *next;
555 static struct smbldap_state_lookup *smbldap_state_lookup_list;
557 static struct smbldap_state *smbldap_find_state(LDAP *ld)
559 struct smbldap_state_lookup *t;
561 for (t = smbldap_state_lookup_list; t; t = t->next) {
562 if (t->ld == ld) {
563 return t->smbldap_state;
566 return NULL;
569 static void smbldap_delete_state(struct smbldap_state *smbldap_state)
571 struct smbldap_state_lookup *t;
573 for (t = smbldap_state_lookup_list; t; t = t->next) {
574 if (t->smbldap_state == smbldap_state) {
575 DLIST_REMOVE(smbldap_state_lookup_list, t);
576 SAFE_FREE(t);
577 return;
582 static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state)
584 struct smbldap_state *tmp_ldap_state;
585 struct smbldap_state_lookup *t;
587 if ((tmp_ldap_state = smbldap_find_state(ld))) {
588 SMB_ASSERT(tmp_ldap_state == smbldap_state);
589 return;
592 t = SMB_XMALLOC_P(struct smbldap_state_lookup);
593 ZERO_STRUCTP(t);
595 DLIST_ADD_END(smbldap_state_lookup_list, t);
596 t->ld = ld;
597 t->smbldap_state = smbldap_state;
600 /********************************************************************
601 start TLS on an existing LDAP connection per config
602 *******************************************************************/
604 int smbldap_start_tls(LDAP *ldap_struct, int version)
606 if (lp_ldap_ssl() != LDAP_SSL_START_TLS) {
607 return LDAP_SUCCESS;
610 return smbldap_start_tls_start(ldap_struct, version);
613 /********************************************************************
614 start TLS on an existing LDAP connection unconditionally
615 *******************************************************************/
617 int smbldap_start_tls_start(LDAP *ldap_struct, int version)
619 #ifdef LDAP_OPT_X_TLS
620 int rc,tls;
622 /* check if we use ldaps already */
623 ldap_get_option(ldap_struct, LDAP_OPT_X_TLS, &tls);
624 if (tls == LDAP_OPT_X_TLS_HARD) {
625 return LDAP_SUCCESS;
628 if (version != LDAP_VERSION3) {
629 DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
630 return LDAP_OPERATIONS_ERROR;
633 if ((rc = ldap_start_tls_s (ldap_struct, NULL, NULL)) != LDAP_SUCCESS) {
634 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
635 ldap_err2string(rc)));
636 return rc;
639 DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
640 return LDAP_SUCCESS;
641 #else
642 DEBUG(0,("StartTLS not supported by LDAP client libraries!\n"));
643 return LDAP_OPERATIONS_ERROR;
644 #endif
647 /********************************************************************
648 setup a connection to the LDAP server based on a uri
649 *******************************************************************/
651 static int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri)
653 int rc;
655 DEBUG(10, ("smb_ldap_setup_connection: %s\n", uri));
657 #ifdef HAVE_LDAP_INITIALIZE
659 rc = ldap_initialize(ldap_struct, uri);
660 if (rc) {
661 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
662 return rc;
665 if (lp_ldap_follow_referral() != Auto) {
666 rc = ldap_set_option(*ldap_struct, LDAP_OPT_REFERRALS,
667 lp_ldap_follow_referral() ? LDAP_OPT_ON : LDAP_OPT_OFF);
668 if (rc != LDAP_SUCCESS)
669 DEBUG(0, ("Failed to set LDAP_OPT_REFERRALS: %s\n",
670 ldap_err2string(rc)));
673 return LDAP_SUCCESS;
674 #else
676 /* Parse the string manually */
679 int port = 0;
680 fstring protocol;
681 fstring host;
682 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
685 /* skip leading "URL:" (if any) */
686 if ( strnequal( uri, "URL:", 4 ) ) {
687 uri += 4;
690 sscanf(uri, "%10[^:]://%254[^:/]:%d", protocol, host, &port);
692 if (port == 0) {
693 if (strequal(protocol, "ldap")) {
694 port = LDAP_PORT;
695 } else if (strequal(protocol, "ldaps")) {
696 port = LDAPS_PORT;
697 } else {
698 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
702 if ((*ldap_struct = ldap_init(host, port)) == NULL) {
703 DEBUG(0, ("ldap_init failed !\n"));
704 return LDAP_OPERATIONS_ERROR;
707 if (strequal(protocol, "ldaps")) {
708 #ifdef LDAP_OPT_X_TLS
709 int tls = LDAP_OPT_X_TLS_HARD;
710 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
712 DEBUG(0, ("Failed to setup a TLS session\n"));
715 DEBUG(3,("LDAPS option set...!\n"));
716 #else
717 DEBUG(0,("smbldap_open_connection: Secure connection not supported by LDAP client libraries!\n"));
718 return LDAP_OPERATIONS_ERROR;
719 #endif /* LDAP_OPT_X_TLS */
722 #endif /* HAVE_LDAP_INITIALIZE */
724 /* now set connection timeout */
725 #ifdef LDAP_X_OPT_CONNECT_TIMEOUT /* Netscape */
727 int ct = lp_ldap_connection_timeout()*1000;
728 rc = ldap_set_option(*ldap_struct, LDAP_X_OPT_CONNECT_TIMEOUT, &ct);
729 if (rc != LDAP_SUCCESS) {
730 DEBUG(0,("Failed to setup an ldap connection timeout %d: %s\n",
731 ct, ldap_err2string(rc)));
734 #elif defined (LDAP_OPT_NETWORK_TIMEOUT) /* OpenLDAP */
736 struct timeval ct;
737 ct.tv_usec = 0;
738 ct.tv_sec = lp_ldap_connection_timeout();
739 rc = ldap_set_option(*ldap_struct, LDAP_OPT_NETWORK_TIMEOUT, &ct);
740 if (rc != LDAP_SUCCESS) {
741 DEBUG(0,("Failed to setup an ldap connection timeout %d: %s\n",
742 (int)ct.tv_sec, ldap_err2string(rc)));
745 #endif
747 return LDAP_SUCCESS;
750 /********************************************************************
751 try to upgrade to Version 3 LDAP if not already, in either case return current
752 version
753 *******************************************************************/
755 static int smb_ldap_upgrade_conn(LDAP *ldap_struct, int *new_version)
757 int version;
758 int rc;
760 /* assume the worst */
761 *new_version = LDAP_VERSION2;
763 rc = ldap_get_option(ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
764 if (rc) {
765 return rc;
768 if (version == LDAP_VERSION3) {
769 *new_version = LDAP_VERSION3;
770 return LDAP_SUCCESS;
773 /* try upgrade */
774 version = LDAP_VERSION3;
775 rc = ldap_set_option (ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
776 if (rc) {
777 return rc;
780 *new_version = LDAP_VERSION3;
781 return LDAP_SUCCESS;
784 /*******************************************************************
785 open a connection to the ldap server (just until the bind)
786 ******************************************************************/
788 int smbldap_setup_full_conn(LDAP **ldap_struct, const char *uri)
790 int rc, version;
792 rc = smb_ldap_setup_conn(ldap_struct, uri);
793 if (rc) {
794 return rc;
797 rc = smb_ldap_upgrade_conn(*ldap_struct, &version);
798 if (rc) {
799 return rc;
802 rc = smbldap_start_tls(*ldap_struct, version);
803 if (rc) {
804 return rc;
807 return LDAP_SUCCESS;
810 /*******************************************************************
811 open a connection to the ldap server.
812 ******************************************************************/
813 static int smbldap_open_connection (struct smbldap_state *ldap_state)
816 int rc = LDAP_SUCCESS;
817 int version;
818 int deref;
819 LDAP **ldap_struct = &ldap_state->ldap_struct;
821 rc = smb_ldap_setup_conn(ldap_struct, ldap_state->uri);
822 if (rc) {
823 return rc;
826 /* Store the LDAP pointer in a lookup list */
828 smbldap_store_state(*ldap_struct, ldap_state);
830 /* Upgrade to LDAPv3 if possible */
832 rc = smb_ldap_upgrade_conn(*ldap_struct, &version);
833 if (rc) {
834 return rc;
837 /* Start TLS if required */
839 rc = smbldap_start_tls(*ldap_struct, version);
840 if (rc) {
841 return rc;
844 /* Set alias dereferencing method */
845 deref = lp_ldap_deref();
846 if (deref != -1) {
847 if (ldap_set_option (*ldap_struct, LDAP_OPT_DEREF, &deref) != LDAP_OPT_SUCCESS) {
848 DEBUG(1,("smbldap_open_connection: Failed to set dereferencing method: %d\n", deref));
849 } else {
850 DEBUG(5,("Set dereferencing method: %d\n", deref));
854 DEBUG(2, ("smbldap_open_connection: connection opened\n"));
855 return rc;
858 /*******************************************************************
859 a rebind function for authenticated referrals
860 This version takes a void* that we can shove useful stuff in :-)
861 ******************************************************************/
862 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
863 #else
864 static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
865 int *methodp, int freeit, void *arg)
867 struct smbldap_state *ldap_state = arg;
868 struct timespec ts;
870 /** @TODO Should we be doing something to check what servers we rebind to?
871 Could we get a referral to a machine that we don't want to give our
872 username and password to? */
874 if (freeit) {
875 SAFE_FREE(*whop);
876 if (*credp) {
877 memset(*credp, '\0', strlen(*credp));
879 SAFE_FREE(*credp);
880 } else {
881 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
882 ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
884 if (ldap_state->anonymous) {
885 *whop = NULL;
886 *credp = NULL;
887 } else {
888 *whop = SMB_STRDUP(ldap_state->bind_dn);
889 if (!*whop) {
890 return LDAP_NO_MEMORY;
892 *credp = SMB_STRDUP(ldap_state->bind_secret);
893 if (!*credp) {
894 SAFE_FREE(*whop);
895 return LDAP_NO_MEMORY;
898 *methodp = LDAP_AUTH_SIMPLE;
901 clock_gettime_mono(&ts);
902 ldap_state->last_rebind = convert_timespec_to_timeval(ts);
904 return 0;
906 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
908 /*******************************************************************
909 a rebind function for authenticated referrals
910 This version takes a void* that we can shove useful stuff in :-)
911 and actually does the connection.
912 ******************************************************************/
913 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
914 static int rebindproc_connect_with_state (LDAP *ldap_struct,
915 LDAP_CONST char *url,
916 ber_tag_t request,
917 ber_int_t msgid, void *arg)
919 struct smbldap_state *ldap_state =
920 (struct smbldap_state *)arg;
921 int rc;
922 struct timespec ts;
923 int version;
925 DEBUG(5,("rebindproc_connect_with_state: Rebinding to %s as \"%s\"\n",
926 url, ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
928 /* call START_TLS again (ldaps:// is handled by the OpenLDAP library
929 * itself) before rebinding to another LDAP server to avoid to expose
930 * our credentials. At least *try* to secure the connection - Guenther */
932 smb_ldap_upgrade_conn(ldap_struct, &version);
933 smbldap_start_tls(ldap_struct, version);
935 /** @TODO Should we be doing something to check what servers we rebind to?
936 Could we get a referral to a machine that we don't want to give our
937 username and password to? */
939 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
941 /* only set the last rebind timestamp when we did rebind after a
942 * non-read LDAP operation. That way we avoid the replication sleep
943 * after a simple redirected search operation - Guenther */
945 switch (request) {
947 case LDAP_REQ_MODIFY:
948 case LDAP_REQ_ADD:
949 case LDAP_REQ_DELETE:
950 case LDAP_REQ_MODDN:
951 case LDAP_REQ_EXTENDED:
952 DEBUG(10,("rebindproc_connect_with_state: "
953 "setting last_rebind timestamp "
954 "(req: 0x%02x)\n", (unsigned int)request));
955 clock_gettime_mono(&ts);
956 ldap_state->last_rebind = convert_timespec_to_timeval(ts);
957 break;
958 default:
959 ZERO_STRUCT(ldap_state->last_rebind);
960 break;
963 return rc;
965 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
967 /*******************************************************************
968 Add a rebind function for authenticated referrals
969 ******************************************************************/
970 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
971 #else
972 # if LDAP_SET_REBIND_PROC_ARGS == 2
973 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
974 int *method, int freeit )
976 struct smbldap_state *ldap_state = smbldap_find_state(ldap_struct);
978 return rebindproc_with_state(ldap_struct, whop, credp,
979 method, freeit, ldap_state);
981 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
982 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
984 /*******************************************************************
985 a rebind function for authenticated referrals
986 this also does the connection, but no void*.
987 ******************************************************************/
988 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
989 # if LDAP_SET_REBIND_PROC_ARGS == 2
990 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
991 ber_int_t msgid)
993 struct smbldap_state *ldap_state = smbldap_find_state(ld);
995 return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid,
996 ldap_state);
998 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
999 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
1001 /*******************************************************************
1002 connect to the ldap server under system privilege.
1003 ******************************************************************/
1004 static int smbldap_connect_system(struct smbldap_state *ldap_state)
1006 LDAP *ldap_struct = smbldap_get_ldap(ldap_state);
1007 int rc;
1008 int version;
1010 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
1011 (OpenLDAP) doesn't seem to support it */
1013 DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
1014 ldap_state->uri, ldap_state->bind_dn));
1016 #ifdef HAVE_LDAP_SET_REBIND_PROC
1017 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
1018 # if LDAP_SET_REBIND_PROC_ARGS == 2
1019 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect);
1020 # endif
1021 # if LDAP_SET_REBIND_PROC_ARGS == 3
1022 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);
1023 # endif
1024 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
1025 # if LDAP_SET_REBIND_PROC_ARGS == 2
1026 ldap_set_rebind_proc(ldap_struct, &rebindproc);
1027 # endif
1028 # if LDAP_SET_REBIND_PROC_ARGS == 3
1029 ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);
1030 # endif
1031 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
1032 #endif
1034 /* When there is an alternative bind callback is set,
1035 attempt to use it to perform the bind */
1036 if (ldap_state->bind_callback != NULL) {
1037 /* We have to allow bind callback to be run under become_root/unbecome_root
1038 to make sure within smbd the callback has proper write access to its resources,
1039 like credential cache. This is similar to passdb case where this callback is supposed
1040 to be used. When used outside smbd, become_root()/unbecome_root() are no-op.
1042 become_root();
1043 rc = ldap_state->bind_callback(ldap_struct, ldap_state, ldap_state->bind_callback_data);
1044 unbecome_root();
1045 } else {
1046 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
1049 if (rc != LDAP_SUCCESS) {
1050 char *ld_error = NULL;
1051 ldap_get_option(smbldap_get_ldap(ldap_state),
1052 LDAP_OPT_ERROR_STRING,
1053 &ld_error);
1054 DEBUG(ldap_state->num_failures ? 2 : 0,
1055 ("failed to bind to server %s with dn=\"%s\" Error: %s\n\t%s\n",
1056 ldap_state->uri,
1057 ldap_state->bind_dn ? ldap_state->bind_dn : "[Anonymous bind]",
1058 ldap_err2string(rc),
1059 ld_error ? ld_error : "(unknown)"));
1060 SAFE_FREE(ld_error);
1061 ldap_state->num_failures++;
1062 goto done;
1065 ldap_state->num_failures = 0;
1066 ldap_state->paged_results = False;
1068 ldap_get_option(smbldap_get_ldap(ldap_state),
1069 LDAP_OPT_PROTOCOL_VERSION, &version);
1071 if (smbldap_has_control(smbldap_get_ldap(ldap_state), ADS_PAGE_CTL_OID)
1072 && version == 3) {
1073 ldap_state->paged_results = True;
1076 DEBUG(3, ("ldap_connect_system: successful connection to the LDAP server\n"));
1077 DEBUGADD(10, ("ldap_connect_system: LDAP server %s support paged results\n",
1078 ldap_state->paged_results ? "does" : "does not"));
1079 done:
1080 if (rc != 0) {
1081 ldap_unbind(ldap_struct);
1082 ldap_state->ldap_struct = NULL;
1084 return rc;
1087 static void smbldap_idle_fn(struct tevent_context *tevent_ctx,
1088 struct tevent_timer *te,
1089 struct timeval now_abs,
1090 void *private_data);
1092 /**********************************************************************
1093 Connect to LDAP server (called before every ldap operation)
1094 *********************************************************************/
1095 static int smbldap_open(struct smbldap_state *ldap_state)
1097 int rc, opt_rc;
1098 bool reopen = False;
1099 SMB_ASSERT(ldap_state);
1101 if ((smbldap_get_ldap(ldap_state) != NULL) &&
1102 ((ldap_state->last_ping + SMBLDAP_DONT_PING_TIME) <
1103 time_mono(NULL))) {
1105 #ifdef HAVE_UNIXSOCKET
1106 struct sockaddr_un addr;
1107 #else
1108 struct sockaddr_storage addr;
1109 #endif
1110 socklen_t len = sizeof(addr);
1111 int sd;
1113 opt_rc = ldap_get_option(smbldap_get_ldap(ldap_state),
1114 LDAP_OPT_DESC, &sd);
1115 if (opt_rc == 0 && (getpeername(sd, (struct sockaddr *) &addr, &len)) < 0 )
1116 reopen = True;
1118 #ifdef HAVE_UNIXSOCKET
1119 if (opt_rc == 0 && addr.sun_family == AF_UNIX)
1120 reopen = True;
1121 #endif
1122 if (reopen) {
1123 /* the other end has died. reopen. */
1124 ldap_unbind(smbldap_get_ldap(ldap_state));
1125 ldap_state->ldap_struct = NULL;
1126 ldap_state->last_ping = (time_t)0;
1127 } else {
1128 ldap_state->last_ping = time_mono(NULL);
1132 if (smbldap_get_ldap(ldap_state) != NULL) {
1133 DEBUG(11,("smbldap_open: already connected to the LDAP server\n"));
1134 return LDAP_SUCCESS;
1137 if ((rc = smbldap_open_connection(ldap_state))) {
1138 return rc;
1141 if ((rc = smbldap_connect_system(ldap_state))) {
1142 return rc;
1146 ldap_state->last_ping = time_mono(NULL);
1147 ldap_state->pid = getpid();
1149 TALLOC_FREE(ldap_state->idle_event);
1151 if (ldap_state->tevent_context != NULL) {
1152 ldap_state->idle_event = tevent_add_timer(
1153 ldap_state->tevent_context, ldap_state,
1154 timeval_current_ofs(SMBLDAP_IDLE_TIME, 0),
1155 smbldap_idle_fn, ldap_state);
1158 DEBUG(4,("The LDAP server is successfully connected\n"));
1160 return LDAP_SUCCESS;
1163 /**********************************************************************
1164 Disconnect from LDAP server
1165 *********************************************************************/
1166 static NTSTATUS smbldap_close(struct smbldap_state *ldap_state)
1168 if (!ldap_state)
1169 return NT_STATUS_INVALID_PARAMETER;
1171 if (smbldap_get_ldap(ldap_state) != NULL) {
1172 ldap_unbind(smbldap_get_ldap(ldap_state));
1173 ldap_state->ldap_struct = NULL;
1176 smbldap_delete_state(ldap_state);
1178 TALLOC_FREE(ldap_state->idle_event);
1180 DEBUG(5,("The connection to the LDAP server was closed\n"));
1181 /* maybe free the results here --metze */
1183 return NT_STATUS_OK;
1186 static SIG_ATOMIC_T got_alarm;
1188 static void gotalarm_sig(int dummy)
1190 got_alarm = 1;
1193 static time_t calc_ldap_abs_endtime(int ldap_to)
1195 if (ldap_to == 0) {
1196 /* No timeout - don't
1197 return a value for
1198 the alarm. */
1199 return (time_t)0;
1202 /* Make the alarm time one second beyond
1203 the timout we're setting for the
1204 remote search timeout, to allow that
1205 to fire in preference. */
1207 return time_mono(NULL)+ldap_to+1;
1210 static int end_ldap_local_alarm(time_t absolute_endtime, int rc)
1212 if (absolute_endtime) {
1213 alarm(0);
1214 CatchSignal(SIGALRM, SIG_IGN);
1215 if (got_alarm) {
1216 /* Client timeout error code. */
1217 got_alarm = 0;
1218 return LDAP_TIMEOUT;
1221 return rc;
1224 static void setup_ldap_local_alarm(struct smbldap_state *ldap_state, time_t absolute_endtime)
1226 time_t now = time_mono(NULL);
1228 if (absolute_endtime) {
1229 got_alarm = 0;
1230 CatchSignal(SIGALRM, gotalarm_sig);
1231 alarm(absolute_endtime - now);
1234 if (ldap_state->pid != getpid()) {
1235 smbldap_close(ldap_state);
1239 static void get_ldap_errs(struct smbldap_state *ldap_state, char **pp_ld_error, int *p_ld_errno)
1241 ldap_get_option(smbldap_get_ldap(ldap_state),
1242 LDAP_OPT_ERROR_NUMBER, p_ld_errno);
1244 ldap_get_option(smbldap_get_ldap(ldap_state),
1245 LDAP_OPT_ERROR_STRING, pp_ld_error);
1248 static int get_cached_ldap_connect(struct smbldap_state *ldap_state, time_t abs_endtime)
1250 int attempts = 0;
1252 while (1) {
1253 int rc;
1254 time_t now;
1256 now = time_mono(NULL);
1257 ldap_state->last_use = now;
1259 if (abs_endtime && now > abs_endtime) {
1260 smbldap_close(ldap_state);
1261 return LDAP_TIMEOUT;
1264 rc = smbldap_open(ldap_state);
1266 if (rc == LDAP_SUCCESS) {
1267 return LDAP_SUCCESS;
1270 attempts++;
1271 DEBUG(1, ("Connection to LDAP server failed for the "
1272 "%d try!\n", attempts));
1274 if (rc == LDAP_INSUFFICIENT_ACCESS) {
1275 /* The fact that we are non-root or any other
1276 * access-denied condition will not change in the next
1277 * round of trying */
1278 return rc;
1281 if (got_alarm) {
1282 smbldap_close(ldap_state);
1283 return LDAP_TIMEOUT;
1286 smb_msleep(1000);
1288 if (got_alarm) {
1289 smbldap_close(ldap_state);
1290 return LDAP_TIMEOUT;
1295 /*********************************************************************
1296 ********************************************************************/
1298 static int smbldap_search_ext(struct smbldap_state *ldap_state,
1299 const char *base, int scope, const char *filter,
1300 const char *attrs[], int attrsonly,
1301 LDAPControl **sctrls, LDAPControl **cctrls,
1302 int sizelimit, LDAPMessage **res)
1304 int rc = LDAP_SERVER_DOWN;
1305 char *utf8_filter;
1306 int to = lp_ldap_timeout();
1307 time_t abs_endtime = calc_ldap_abs_endtime(to);
1308 struct timeval timeout;
1309 struct timeval *timeout_ptr = NULL;
1310 size_t converted_size;
1312 SMB_ASSERT(ldap_state);
1314 DEBUG(5,("smbldap_search_ext: base => [%s], filter => [%s], "
1315 "scope => [%d]\n", base, filter, scope));
1317 if (ldap_state->last_rebind.tv_sec > 0) {
1318 struct timeval tval;
1319 struct timespec ts;
1320 int64_t tdiff = 0;
1321 int sleep_time = 0;
1323 clock_gettime_mono(&ts);
1324 tval = convert_timespec_to_timeval(ts);
1326 tdiff = usec_time_diff(&tval, &ldap_state->last_rebind);
1327 tdiff /= 1000; /* Convert to milliseconds. */
1329 sleep_time = lp_ldap_replication_sleep()-(int)tdiff;
1330 sleep_time = MIN(sleep_time, MAX_LDAP_REPLICATION_SLEEP_TIME);
1332 if (sleep_time > 0) {
1333 /* we wait for the LDAP replication */
1334 DEBUG(5,("smbldap_search_ext: waiting %d milliseconds "
1335 "for LDAP replication.\n",sleep_time));
1336 smb_msleep(sleep_time);
1337 DEBUG(5,("smbldap_search_ext: go on!\n"));
1339 ZERO_STRUCT(ldap_state->last_rebind);
1342 if (!push_utf8_talloc(talloc_tos(), &utf8_filter, filter, &converted_size)) {
1343 return LDAP_NO_MEMORY;
1346 /* Setup remote timeout for the ldap_search_ext_s call. */
1347 if (to) {
1348 timeout.tv_sec = to;
1349 timeout.tv_usec = 0;
1350 timeout_ptr = &timeout;
1353 setup_ldap_local_alarm(ldap_state, abs_endtime);
1355 while (1) {
1356 char *ld_error = NULL;
1357 int ld_errno;
1359 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1360 if (rc != LDAP_SUCCESS) {
1361 break;
1364 rc = ldap_search_ext_s(smbldap_get_ldap(ldap_state),
1365 base, scope,
1366 utf8_filter,
1367 discard_const_p(char *, attrs),
1368 attrsonly, sctrls, cctrls, timeout_ptr,
1369 sizelimit, res);
1370 if (rc == LDAP_SUCCESS) {
1371 break;
1374 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1376 DEBUG(10, ("Failed search for base: %s, error: %d (%s) "
1377 "(%s)\n", base, ld_errno,
1378 ldap_err2string(rc),
1379 ld_error ? ld_error : "unknown"));
1380 SAFE_FREE(ld_error);
1382 if (ld_errno != LDAP_SERVER_DOWN) {
1383 break;
1385 ldap_unbind(smbldap_get_ldap(ldap_state));
1386 ldap_state->ldap_struct = NULL;
1389 TALLOC_FREE(utf8_filter);
1390 return end_ldap_local_alarm(abs_endtime, rc);
1393 int smbldap_search(struct smbldap_state *ldap_state,
1394 const char *base, int scope, const char *filter,
1395 const char *attrs[], int attrsonly,
1396 LDAPMessage **res)
1398 return smbldap_search_ext(ldap_state, base, scope, filter, attrs,
1399 attrsonly, NULL, NULL, LDAP_NO_LIMIT, res);
1402 int smbldap_search_paged(struct smbldap_state *ldap_state,
1403 const char *base, int scope, const char *filter,
1404 const char **attrs, int attrsonly, int pagesize,
1405 LDAPMessage **res, void **cookie)
1407 LDAPControl pr;
1408 LDAPControl **rcontrols;
1409 LDAPControl *controls[2] = { NULL, NULL};
1410 BerElement *cookie_be = NULL;
1411 struct berval *cookie_bv = NULL;
1412 int tmp = 0, i, rc;
1413 bool critical = True;
1415 *res = NULL;
1417 DEBUG(3,("smbldap_search_paged: base => [%s], filter => [%s],"
1418 "scope => [%d], pagesize => [%d]\n",
1419 base, filter, scope, pagesize));
1421 cookie_be = ber_alloc_t(LBER_USE_DER);
1422 if (cookie_be == NULL) {
1423 DEBUG(0,("smbldap_create_page_control: ber_alloc_t returns "
1424 "NULL\n"));
1425 return LDAP_NO_MEMORY;
1428 /* construct cookie */
1429 if (*cookie != NULL) {
1430 ber_printf(cookie_be, "{iO}", (ber_int_t) pagesize, *cookie);
1431 ber_bvfree((struct berval *)*cookie); /* don't need it from last time */
1432 *cookie = NULL;
1433 } else {
1434 ber_printf(cookie_be, "{io}", (ber_int_t) pagesize, "", 0);
1436 ber_flatten(cookie_be, &cookie_bv);
1438 pr.ldctl_oid = discard_const_p(char, ADS_PAGE_CTL_OID);
1439 pr.ldctl_iscritical = (char) critical;
1440 pr.ldctl_value.bv_len = cookie_bv->bv_len;
1441 pr.ldctl_value.bv_val = cookie_bv->bv_val;
1443 controls[0] = &pr;
1444 controls[1] = NULL;
1446 rc = smbldap_search_ext(ldap_state, base, scope, filter, attrs,
1447 0, controls, NULL, LDAP_NO_LIMIT, res);
1449 ber_free(cookie_be, 1);
1450 ber_bvfree(cookie_bv);
1452 if (rc != 0) {
1453 DEBUG(3,("smbldap_search_paged: smbldap_search_ext(%s) "
1454 "failed with [%s]\n", filter, ldap_err2string(rc)));
1455 goto done;
1458 DEBUG(3,("smbldap_search_paged: search was successful\n"));
1460 rc = ldap_parse_result(smbldap_get_ldap(ldap_state), *res, NULL, NULL,
1461 NULL, NULL, &rcontrols, 0);
1462 if (rc != 0) {
1463 DEBUG(3,("smbldap_search_paged: ldap_parse_result failed " \
1464 "with [%s]\n", ldap_err2string(rc)));
1465 goto done;
1468 if (rcontrols == NULL)
1469 goto done;
1471 for (i=0; rcontrols[i]; i++) {
1473 if (strcmp(ADS_PAGE_CTL_OID, rcontrols[i]->ldctl_oid) != 0)
1474 continue;
1476 cookie_be = ber_init(&rcontrols[i]->ldctl_value);
1477 ber_scanf(cookie_be,"{iO}", &tmp, &cookie_bv);
1478 /* the berval is the cookie, but must be freed when it is all
1479 done */
1480 if (cookie_bv->bv_len)
1481 *cookie=ber_bvdup(cookie_bv);
1482 else
1483 *cookie=NULL;
1484 ber_bvfree(cookie_bv);
1485 ber_free(cookie_be, 1);
1486 break;
1488 ldap_controls_free(rcontrols);
1489 done:
1490 return rc;
1493 int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
1495 int rc = LDAP_SERVER_DOWN;
1496 char *utf8_dn;
1497 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1498 size_t converted_size;
1500 SMB_ASSERT(ldap_state);
1502 DEBUG(5,("smbldap_modify: dn => [%s]\n", dn ));
1504 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1505 return LDAP_NO_MEMORY;
1508 setup_ldap_local_alarm(ldap_state, abs_endtime);
1510 while (1) {
1511 char *ld_error = NULL;
1512 int ld_errno;
1514 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1515 if (rc != LDAP_SUCCESS) {
1516 break;
1519 rc = ldap_modify_s(smbldap_get_ldap(ldap_state), utf8_dn,
1520 attrs);
1521 if (rc == LDAP_SUCCESS) {
1522 break;
1525 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1527 DEBUG(10, ("Failed to modify dn: %s, error: %d (%s) "
1528 "(%s)\n", dn, ld_errno,
1529 ldap_err2string(rc),
1530 ld_error ? ld_error : "unknown"));
1531 SAFE_FREE(ld_error);
1533 if (ld_errno != LDAP_SERVER_DOWN) {
1534 break;
1536 ldap_unbind(smbldap_get_ldap(ldap_state));
1537 ldap_state->ldap_struct = NULL;
1540 TALLOC_FREE(utf8_dn);
1541 return end_ldap_local_alarm(abs_endtime, rc);
1544 int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
1546 int rc = LDAP_SERVER_DOWN;
1547 char *utf8_dn;
1548 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1549 size_t converted_size;
1551 SMB_ASSERT(ldap_state);
1553 DEBUG(5,("smbldap_add: dn => [%s]\n", dn ));
1555 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1556 return LDAP_NO_MEMORY;
1559 setup_ldap_local_alarm(ldap_state, abs_endtime);
1561 while (1) {
1562 char *ld_error = NULL;
1563 int ld_errno;
1565 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1566 if (rc != LDAP_SUCCESS) {
1567 break;
1570 rc = ldap_add_s(smbldap_get_ldap(ldap_state), utf8_dn, attrs);
1571 if (rc == LDAP_SUCCESS) {
1572 break;
1575 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1577 DEBUG(10, ("Failed to add dn: %s, error: %d (%s) "
1578 "(%s)\n", dn, ld_errno,
1579 ldap_err2string(rc),
1580 ld_error ? ld_error : "unknown"));
1581 SAFE_FREE(ld_error);
1583 if (ld_errno != LDAP_SERVER_DOWN) {
1584 break;
1586 ldap_unbind(smbldap_get_ldap(ldap_state));
1587 ldap_state->ldap_struct = NULL;
1590 TALLOC_FREE(utf8_dn);
1591 return end_ldap_local_alarm(abs_endtime, rc);
1594 int smbldap_delete(struct smbldap_state *ldap_state, const char *dn)
1596 int rc = LDAP_SERVER_DOWN;
1597 char *utf8_dn;
1598 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1599 size_t converted_size;
1601 SMB_ASSERT(ldap_state);
1603 DEBUG(5,("smbldap_delete: dn => [%s]\n", dn ));
1605 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1606 return LDAP_NO_MEMORY;
1609 setup_ldap_local_alarm(ldap_state, abs_endtime);
1611 while (1) {
1612 char *ld_error = NULL;
1613 int ld_errno;
1615 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1616 if (rc != LDAP_SUCCESS) {
1617 break;
1620 rc = ldap_delete_s(smbldap_get_ldap(ldap_state), utf8_dn);
1621 if (rc == LDAP_SUCCESS) {
1622 break;
1625 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1627 DEBUG(10, ("Failed to delete dn: %s, error: %d (%s) "
1628 "(%s)\n", dn, ld_errno,
1629 ldap_err2string(rc),
1630 ld_error ? ld_error : "unknown"));
1631 SAFE_FREE(ld_error);
1633 if (ld_errno != LDAP_SERVER_DOWN) {
1634 break;
1636 ldap_unbind(smbldap_get_ldap(ldap_state));
1637 ldap_state->ldap_struct = NULL;
1640 TALLOC_FREE(utf8_dn);
1641 return end_ldap_local_alarm(abs_endtime, rc);
1644 int smbldap_extended_operation(struct smbldap_state *ldap_state,
1645 LDAP_CONST char *reqoid, struct berval *reqdata,
1646 LDAPControl **serverctrls, LDAPControl **clientctrls,
1647 char **retoidp, struct berval **retdatap)
1649 int rc = LDAP_SERVER_DOWN;
1650 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1652 if (!ldap_state)
1653 return (-1);
1655 setup_ldap_local_alarm(ldap_state, abs_endtime);
1657 while (1) {
1658 char *ld_error = NULL;
1659 int ld_errno;
1661 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1662 if (rc != LDAP_SUCCESS) {
1663 break;
1666 rc = ldap_extended_operation_s(smbldap_get_ldap(ldap_state),
1667 reqoid,
1668 reqdata, serverctrls,
1669 clientctrls, retoidp, retdatap);
1670 if (rc == LDAP_SUCCESS) {
1671 break;
1674 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1676 DEBUG(10, ("Extended operation failed with error: "
1677 "%d (%s) (%s)\n", ld_errno,
1678 ldap_err2string(rc),
1679 ld_error ? ld_error : "unknown"));
1680 SAFE_FREE(ld_error);
1682 if (ld_errno != LDAP_SERVER_DOWN) {
1683 break;
1685 ldap_unbind(smbldap_get_ldap(ldap_state));
1686 ldap_state->ldap_struct = NULL;
1689 return end_ldap_local_alarm(abs_endtime, rc);
1692 /*******************************************************************
1693 run the search by name.
1694 ******************************************************************/
1695 int smbldap_search_suffix (struct smbldap_state *ldap_state,
1696 const char *filter, const char **search_attr,
1697 LDAPMessage ** result)
1699 return smbldap_search(ldap_state, lp_ldap_suffix(),
1700 LDAP_SCOPE_SUBTREE,
1701 filter, search_attr, 0, result);
1704 static void smbldap_idle_fn(struct tevent_context *tevent_ctx,
1705 struct tevent_timer *te,
1706 struct timeval now_abs,
1707 void *private_data)
1709 struct smbldap_state *state = (struct smbldap_state *)private_data;
1711 TALLOC_FREE(state->idle_event);
1713 if (smbldap_get_ldap(state) == NULL) {
1714 DEBUG(10,("ldap connection not connected...\n"));
1715 return;
1718 if ((state->last_use+SMBLDAP_IDLE_TIME) > time_mono(NULL)) {
1719 DEBUG(10,("ldap connection not idle...\n"));
1721 /* this needs to be made monotonic clock aware inside tevent: */
1722 state->idle_event = tevent_add_timer(
1723 tevent_ctx, state,
1724 timeval_add(&now_abs, SMBLDAP_IDLE_TIME, 0),
1725 smbldap_idle_fn,
1726 private_data);
1727 return;
1730 DEBUG(7,("ldap connection idle...closing connection\n"));
1731 smbldap_close(state);
1734 /**********************************************************************
1735 Housekeeping
1736 *********************************************************************/
1738 void smbldap_free_struct(struct smbldap_state **ldap_state)
1740 smbldap_close(*ldap_state);
1742 if ((*ldap_state)->bind_secret) {
1743 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
1746 SAFE_FREE((*ldap_state)->bind_dn);
1747 SAFE_FREE((*ldap_state)->bind_secret);
1748 smbldap_set_bind_callback(*ldap_state, NULL, NULL);
1750 TALLOC_FREE(*ldap_state);
1752 /* No need to free any further, as it is talloc()ed */
1755 static int smbldap_state_destructor(struct smbldap_state *state)
1757 smbldap_free_struct(&state);
1758 return 0;
1762 /**********************************************************************
1763 Intitalise the 'general' ldap structures, on which ldap operations may be conducted
1764 *********************************************************************/
1766 NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, struct tevent_context *tevent_ctx,
1767 const char *location,
1768 bool anon,
1769 const char *bind_dn,
1770 const char *bind_secret,
1771 struct smbldap_state **smbldap_state)
1773 *smbldap_state = talloc_zero(mem_ctx, struct smbldap_state);
1774 if (!*smbldap_state) {
1775 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
1776 return NT_STATUS_NO_MEMORY;
1779 if (location) {
1780 (*smbldap_state)->uri = talloc_strdup(mem_ctx, location);
1781 } else {
1782 (*smbldap_state)->uri = "ldap://localhost";
1785 (*smbldap_state)->tevent_context = tevent_ctx;
1787 if (bind_dn && bind_secret) {
1788 smbldap_set_creds(*smbldap_state, anon, bind_dn, bind_secret);
1791 talloc_set_destructor(*smbldap_state, smbldap_state_destructor);
1792 return NT_STATUS_OK;
1795 char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld,
1796 LDAPMessage *entry)
1798 char *utf8_dn, *unix_dn;
1799 size_t converted_size;
1801 utf8_dn = ldap_get_dn(ld, entry);
1802 if (!utf8_dn) {
1803 DEBUG (5, ("smbldap_talloc_dn: ldap_get_dn failed\n"));
1804 return NULL;
1806 if (!pull_utf8_talloc(mem_ctx, &unix_dn, utf8_dn, &converted_size)) {
1807 DEBUG (0, ("smbldap_talloc_dn: String conversion failure utf8 "
1808 "[%s]\n", utf8_dn));
1809 return NULL;
1811 ldap_memfree(utf8_dn);
1812 return unix_dn;
1815 /*******************************************************************
1816 Check if root-dse has a certain Control or Extension
1817 ********************************************************************/
1819 static bool smbldap_check_root_dse(LDAP *ld, const char **attrs, const char *value)
1821 LDAPMessage *msg = NULL;
1822 LDAPMessage *entry = NULL;
1823 char **values = NULL;
1824 int rc, num_result, num_values, i;
1825 bool result = False;
1827 if (!attrs[0]) {
1828 DEBUG(3,("smbldap_check_root_dse: nothing to look for\n"));
1829 return False;
1832 if (!strequal(attrs[0], "supportedExtension") &&
1833 !strequal(attrs[0], "supportedControl") &&
1834 !strequal(attrs[0], "namingContexts")) {
1835 DEBUG(3,("smbldap_check_root_dse: no idea what to query root-dse for: %s ?\n", attrs[0]));
1836 return False;
1839 rc = ldap_search_s(ld, "", LDAP_SCOPE_BASE,
1840 "(objectclass=*)", discard_const_p(char *, attrs), 0 , &msg);
1842 if (rc != LDAP_SUCCESS) {
1843 DEBUG(3,("smbldap_check_root_dse: Could not search rootDSE\n"));
1844 return False;
1847 num_result = ldap_count_entries(ld, msg);
1849 if (num_result != 1) {
1850 DEBUG(3,("smbldap_check_root_dse: Expected one rootDSE, got %d\n", num_result));
1851 goto done;
1854 entry = ldap_first_entry(ld, msg);
1856 if (entry == NULL) {
1857 DEBUG(3,("smbldap_check_root_dse: Could not retrieve rootDSE\n"));
1858 goto done;
1861 values = ldap_get_values(ld, entry, attrs[0]);
1863 if (values == NULL) {
1864 DEBUG(5,("smbldap_check_root_dse: LDAP Server does not support any %s\n", attrs[0]));
1865 goto done;
1868 num_values = ldap_count_values(values);
1870 if (num_values == 0) {
1871 DEBUG(5,("smbldap_check_root_dse: LDAP Server does not have any %s\n", attrs[0]));
1872 goto done;
1875 for (i=0; i<num_values; i++) {
1876 if (strcmp(values[i], value) == 0)
1877 result = True;
1881 done:
1882 if (values != NULL)
1883 ldap_value_free(values);
1884 if (msg != NULL)
1885 ldap_msgfree(msg);
1887 return result;
1891 /*******************************************************************
1892 Check if LDAP-Server supports a certain Control (OID in string format)
1893 ********************************************************************/
1895 bool smbldap_has_control(LDAP *ld, const char *control)
1897 const char *attrs[] = { "supportedControl", NULL };
1898 return smbldap_check_root_dse(ld, attrs, control);
1901 /*******************************************************************
1902 Check if LDAP-Server supports a certain Extension (OID in string format)
1903 ********************************************************************/
1905 bool smbldap_has_extension(LDAP *ld, const char *extension)
1907 const char *attrs[] = { "supportedExtension", NULL };
1908 return smbldap_check_root_dse(ld, attrs, extension);
1911 /*******************************************************************
1912 Check if LDAP-Server holds a given namingContext
1913 ********************************************************************/
1915 bool smbldap_has_naming_context(LDAP *ld, const char *naming_context)
1917 const char *attrs[] = { "namingContexts", NULL };
1918 return smbldap_check_root_dse(ld, attrs, naming_context);
1921 bool smbldap_set_creds(struct smbldap_state *ldap_state, bool anon, const char *dn, const char *secret)
1923 ldap_state->anonymous = anon;
1925 /* free any previously set credential */
1927 SAFE_FREE(ldap_state->bind_dn);
1928 smbldap_set_bind_callback(ldap_state, NULL, NULL);
1930 if (ldap_state->bind_secret) {
1931 /* make sure secrets are zeroed out of memory */
1932 memset(ldap_state->bind_secret, '\0', strlen(ldap_state->bind_secret));
1933 SAFE_FREE(ldap_state->bind_secret);
1936 if ( ! anon) {
1937 ldap_state->bind_dn = SMB_STRDUP(dn);
1938 ldap_state->bind_secret = SMB_STRDUP(secret);
1941 return True;