s3:smbd: make typedef write_cache private to fileio.c
[Samba/gebeck_regimport.git] / source3 / lib / smbldap.c
blob43ddaff53a67c5d5fc81f2cddb5160283bd8709c
1 /*
2 Unix SMB/CIFS implementation.
3 LDAP protocol helper functions for SAMBA
4 Copyright (C) Jean François Micouleau 1998
5 Copyright (C) Gerald Carter 2001-2003
6 Copyright (C) Shahms King 2001
7 Copyright (C) Andrew Bartlett 2002-2003
8 Copyright (C) Stefan (metze) Metzmacher 2002-2003
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "smbldap.h"
27 #include "../libcli/security/security.h"
28 #include <tevent.h>
30 /* Try not to hit the up or down server forever */
32 #define SMBLDAP_DONT_PING_TIME 10 /* ping only all 10 seconds */
33 #define SMBLDAP_NUM_RETRIES 8 /* retry only 8 times */
35 #define SMBLDAP_IDLE_TIME 150 /* After 2.5 minutes disconnect */
38 /*******************************************************************
39 Search an attribute and return the first value found.
40 ******************************************************************/
42 bool smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
43 const char *attribute, char *value,
44 int max_len)
46 char **values;
47 size_t size = 0;
49 if ( !attribute )
50 return False;
52 value[0] = '\0';
54 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
55 DEBUG (10, ("smbldap_get_single_attribute: [%s] = [<does not exist>]\n", attribute));
57 return False;
60 if (!convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, max_len, &size)) {
61 DEBUG(1, ("smbldap_get_single_attribute: string conversion of [%s] = [%s] failed!\n",
62 attribute, values[0]));
63 ldap_value_free(values);
64 return False;
67 ldap_value_free(values);
68 #ifdef DEBUG_PASSWORDS
69 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n", attribute, value));
70 #endif
71 return True;
74 char * smbldap_talloc_single_attribute(LDAP *ldap_struct, LDAPMessage *entry,
75 const char *attribute,
76 TALLOC_CTX *mem_ctx)
78 char **values;
79 char *result;
80 size_t converted_size;
82 if (attribute == NULL) {
83 return NULL;
86 values = ldap_get_values(ldap_struct, entry, attribute);
88 if (values == NULL) {
89 DEBUG(10, ("attribute %s does not exist\n", attribute));
90 return NULL;
93 if (ldap_count_values(values) != 1) {
94 DEBUG(10, ("attribute %s has %d values, expected only one\n",
95 attribute, ldap_count_values(values)));
96 ldap_value_free(values);
97 return NULL;
100 if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
101 DEBUG(10, ("pull_utf8_talloc failed\n"));
102 ldap_value_free(values);
103 return NULL;
106 ldap_value_free(values);
108 #ifdef DEBUG_PASSWORDS
109 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
110 attribute, result));
111 #endif
112 return result;
115 char * smbldap_talloc_first_attribute(LDAP *ldap_struct, LDAPMessage *entry,
116 const char *attribute,
117 TALLOC_CTX *mem_ctx)
119 char **values;
120 char *result;
121 size_t converted_size;
123 if (attribute == NULL) {
124 return NULL;
127 values = ldap_get_values(ldap_struct, entry, attribute);
129 if (values == NULL) {
130 DEBUG(10, ("attribute %s does not exist\n", attribute));
131 return NULL;
134 if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
135 DEBUG(10, ("pull_utf8_talloc failed\n"));
136 ldap_value_free(values);
137 return NULL;
140 ldap_value_free(values);
142 #ifdef DEBUG_PASSWORDS
143 DEBUG (100, ("smbldap_get_first_attribute: [%s] = [%s]\n",
144 attribute, result));
145 #endif
146 return result;
149 char * smbldap_talloc_smallest_attribute(LDAP *ldap_struct, LDAPMessage *entry,
150 const char *attribute,
151 TALLOC_CTX *mem_ctx)
153 char **values;
154 char *result;
155 size_t converted_size;
156 int i, num_values;
158 if (attribute == NULL) {
159 return NULL;
162 values = ldap_get_values(ldap_struct, entry, attribute);
164 if (values == NULL) {
165 DEBUG(10, ("attribute %s does not exist\n", attribute));
166 return NULL;
169 if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
170 DEBUG(10, ("pull_utf8_talloc failed\n"));
171 ldap_value_free(values);
172 return NULL;
175 num_values = ldap_count_values(values);
177 for (i=1; i<num_values; i++) {
178 char *tmp;
180 if (!pull_utf8_talloc(mem_ctx, &tmp, values[i],
181 &converted_size)) {
182 DEBUG(10, ("pull_utf8_talloc failed\n"));
183 TALLOC_FREE(result);
184 ldap_value_free(values);
185 return NULL;
188 if (strcasecmp_m(tmp, result) < 0) {
189 TALLOC_FREE(result);
190 result = tmp;
191 } else {
192 TALLOC_FREE(tmp);
196 ldap_value_free(values);
198 #ifdef DEBUG_PASSWORDS
199 DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
200 attribute, result));
201 #endif
202 return result;
205 bool smbldap_talloc_single_blob(TALLOC_CTX *mem_ctx, LDAP *ld,
206 LDAPMessage *msg, const char *attrib,
207 DATA_BLOB *blob)
209 struct berval **values;
211 values = ldap_get_values_len(ld, msg, attrib);
212 if (!values) {
213 return false;
216 if (ldap_count_values_len(values) != 1) {
217 DEBUG(10, ("Expected one value for %s, got %d\n", attrib,
218 ldap_count_values_len(values)));
219 return false;
222 *blob = data_blob_talloc(mem_ctx, values[0]->bv_val,
223 values[0]->bv_len);
224 ldap_value_free_len(values);
226 return (blob->data != NULL);
229 bool smbldap_pull_sid(LDAP *ld, LDAPMessage *msg, const char *attrib,
230 struct dom_sid *sid)
232 DATA_BLOB blob;
233 bool ret;
235 if (!smbldap_talloc_single_blob(talloc_tos(), ld, msg, attrib,
236 &blob)) {
237 return false;
239 ret = sid_parse((char *)blob.data, blob.length, sid);
240 TALLOC_FREE(blob.data);
241 return ret;
244 static int ldapmsg_destructor(LDAPMessage **result) {
245 ldap_msgfree(*result);
246 return 0;
249 void talloc_autofree_ldapmsg(TALLOC_CTX *mem_ctx, LDAPMessage *result)
251 LDAPMessage **handle;
253 if (result == NULL) {
254 return;
257 handle = talloc(mem_ctx, LDAPMessage *);
258 SMB_ASSERT(handle != NULL);
260 *handle = result;
261 talloc_set_destructor(handle, ldapmsg_destructor);
264 static int ldapmod_destructor(LDAPMod ***mod) {
265 ldap_mods_free(*mod, True);
266 return 0;
269 void talloc_autofree_ldapmod(TALLOC_CTX *mem_ctx, LDAPMod **mod)
271 LDAPMod ***handle;
273 if (mod == NULL) {
274 return;
277 handle = talloc(mem_ctx, LDAPMod **);
278 SMB_ASSERT(handle != NULL);
280 *handle = mod;
281 talloc_set_destructor(handle, ldapmod_destructor);
284 /************************************************************************
285 Routine to manage the LDAPMod structure array
286 manage memory used by the array, by each struct, and values
287 ***********************************************************************/
289 static void smbldap_set_mod_internal(LDAPMod *** modlist, int modop, const char *attribute, const char *value, const DATA_BLOB *blob)
291 LDAPMod **mods;
292 int i;
293 int j;
295 mods = *modlist;
297 /* sanity checks on the mod values */
299 if (attribute == NULL || *attribute == '\0') {
300 return;
303 #if 0 /* commented out after discussion with abartlet. Do not reenable.
304 left here so other do not re-add similar code --jerry */
305 if (value == NULL || *value == '\0')
306 return;
307 #endif
309 if (mods == NULL) {
310 mods = SMB_MALLOC_P(LDAPMod *);
311 if (mods == NULL) {
312 smb_panic("smbldap_set_mod: out of memory!");
313 /* notreached. */
315 mods[0] = NULL;
318 for (i = 0; mods[i] != NULL; ++i) {
319 if (mods[i]->mod_op == modop && strequal(mods[i]->mod_type, attribute))
320 break;
323 if (mods[i] == NULL) {
324 mods = SMB_REALLOC_ARRAY (mods, LDAPMod *, i + 2);
325 if (mods == NULL) {
326 smb_panic("smbldap_set_mod: out of memory!");
327 /* notreached. */
329 mods[i] = SMB_MALLOC_P(LDAPMod);
330 if (mods[i] == NULL) {
331 smb_panic("smbldap_set_mod: out of memory!");
332 /* notreached. */
334 mods[i]->mod_op = modop;
335 mods[i]->mod_values = NULL;
336 mods[i]->mod_type = SMB_STRDUP(attribute);
337 mods[i + 1] = NULL;
340 if (blob && (modop & LDAP_MOD_BVALUES)) {
341 j = 0;
342 if (mods[i]->mod_bvalues != NULL) {
343 for (; mods[i]->mod_bvalues[j] != NULL; j++);
345 mods[i]->mod_bvalues = SMB_REALLOC_ARRAY(mods[i]->mod_bvalues, struct berval *, j + 2);
347 if (mods[i]->mod_bvalues == NULL) {
348 smb_panic("smbldap_set_mod: out of memory!");
349 /* notreached. */
352 mods[i]->mod_bvalues[j] = SMB_MALLOC_P(struct berval);
353 SMB_ASSERT(mods[i]->mod_bvalues[j] != NULL);
355 mods[i]->mod_bvalues[j]->bv_val = (char *)memdup(blob->data, blob->length);
356 SMB_ASSERT(mods[i]->mod_bvalues[j]->bv_val != NULL);
357 mods[i]->mod_bvalues[j]->bv_len = blob->length;
359 mods[i]->mod_bvalues[j + 1] = NULL;
360 } else if (value != NULL) {
361 char *utf8_value = NULL;
362 size_t converted_size;
364 j = 0;
365 if (mods[i]->mod_values != NULL) {
366 for (; mods[i]->mod_values[j] != NULL; j++);
368 mods[i]->mod_values = SMB_REALLOC_ARRAY(mods[i]->mod_values, char *, j + 2);
370 if (mods[i]->mod_values == NULL) {
371 smb_panic("smbldap_set_mod: out of memory!");
372 /* notreached. */
375 if (!push_utf8_talloc(talloc_tos(), &utf8_value, value, &converted_size)) {
376 smb_panic("smbldap_set_mod: String conversion failure!");
377 /* notreached. */
380 mods[i]->mod_values[j] = SMB_STRDUP(utf8_value);
381 TALLOC_FREE(utf8_value);
382 SMB_ASSERT(mods[i]->mod_values[j] != NULL);
384 mods[i]->mod_values[j + 1] = NULL;
386 *modlist = mods;
389 void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
391 smbldap_set_mod_internal(modlist, modop, attribute, value, NULL);
394 void smbldap_set_mod_blob(LDAPMod *** modlist, int modop, const char *attribute, const DATA_BLOB *value)
396 smbldap_set_mod_internal(modlist, modop | LDAP_MOD_BVALUES, attribute, NULL, value);
399 /**********************************************************************
400 Set attribute to newval in LDAP, regardless of what value the
401 attribute had in LDAP before.
402 *********************************************************************/
404 static void smbldap_make_mod_internal(LDAP *ldap_struct, LDAPMessage *existing,
405 LDAPMod ***mods,
406 const char *attribute, int op,
407 const char *newval,
408 const DATA_BLOB *newblob)
410 char oldval[2048]; /* current largest allowed value is mungeddial */
411 bool existed;
412 DATA_BLOB oldblob = data_blob_null;
414 if (attribute == NULL) {
415 /* This can actually happen for ldapsam_compat where we for
416 * example don't have a password history */
417 return;
420 if (existing != NULL) {
421 if (op & LDAP_MOD_BVALUES) {
422 existed = smbldap_talloc_single_blob(talloc_tos(), ldap_struct, existing, attribute, &oldblob);
423 } else {
424 existed = smbldap_get_single_attribute(ldap_struct, existing, attribute, oldval, sizeof(oldval));
426 } else {
427 existed = False;
428 *oldval = '\0';
431 if (existed) {
432 bool equal = false;
433 if (op & LDAP_MOD_BVALUES) {
434 equal = (newblob && (data_blob_cmp(&oldblob, newblob) == 0));
435 } else {
436 /* all of our string attributes are case insensitive */
437 equal = (newval && (strcasecmp_m(oldval, newval) == 0));
440 if (equal) {
441 /* Believe it or not, but LDAP will deny a delete and
442 an add at the same time if the values are the
443 same... */
444 DEBUG(10,("smbldap_make_mod: attribute |%s| not changed.\n", attribute));
445 return;
448 /* There has been no value before, so don't delete it.
449 * Here's a possible race: We might end up with
450 * duplicate attributes */
451 /* By deleting exactly the value we found in the entry this
452 * should be race-free in the sense that the LDAP-Server will
453 * deny the complete operation if somebody changed the
454 * attribute behind our back. */
455 /* This will also allow modifying single valued attributes
456 * in Novell NDS. In NDS you have to first remove attribute and then
457 * you could add new value */
459 if (op & LDAP_MOD_BVALUES) {
460 DEBUG(10,("smbldap_make_mod: deleting attribute |%s| blob\n", attribute));
461 smbldap_set_mod_blob(mods, LDAP_MOD_DELETE, attribute, &oldblob);
462 } else {
463 DEBUG(10,("smbldap_make_mod: deleting attribute |%s| values |%s|\n", attribute, oldval));
464 smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, oldval);
468 /* Regardless of the real operation (add or modify)
469 we add the new value here. We rely on deleting
470 the old value, should it exist. */
472 if (op & LDAP_MOD_BVALUES) {
473 if (newblob && newblob->length) {
474 DEBUG(10,("smbldap_make_mod: adding attribute |%s| blob\n", attribute));
475 smbldap_set_mod_blob(mods, LDAP_MOD_ADD, attribute, newblob);
477 } else {
478 if ((newval != NULL) && (strlen(newval) > 0)) {
479 DEBUG(10,("smbldap_make_mod: adding attribute |%s| value |%s|\n", attribute, newval));
480 smbldap_set_mod(mods, LDAP_MOD_ADD, attribute, newval);
485 void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing,
486 LDAPMod ***mods,
487 const char *attribute, const char *newval)
489 smbldap_make_mod_internal(ldap_struct, existing, mods, attribute,
490 0, newval, NULL);
493 void smbldap_make_mod_blob(LDAP *ldap_struct, LDAPMessage *existing,
494 LDAPMod ***mods,
495 const char *attribute, const DATA_BLOB *newblob)
497 smbldap_make_mod_internal(ldap_struct, existing, mods, attribute,
498 LDAP_MOD_BVALUES, NULL, newblob);
501 /**********************************************************************
502 Some varients of the LDAP rebind code do not pass in the third 'arg'
503 pointer to a void*, so we try and work around it by assuming that the
504 value of the 'LDAP *' pointer is the same as the one we had passed in
505 **********************************************************************/
507 struct smbldap_state_lookup {
508 LDAP *ld;
509 struct smbldap_state *smbldap_state;
510 struct smbldap_state_lookup *prev, *next;
513 static struct smbldap_state_lookup *smbldap_state_lookup_list;
515 static struct smbldap_state *smbldap_find_state(LDAP *ld)
517 struct smbldap_state_lookup *t;
519 for (t = smbldap_state_lookup_list; t; t = t->next) {
520 if (t->ld == ld) {
521 return t->smbldap_state;
524 return NULL;
527 static void smbldap_delete_state(struct smbldap_state *smbldap_state)
529 struct smbldap_state_lookup *t;
531 for (t = smbldap_state_lookup_list; t; t = t->next) {
532 if (t->smbldap_state == smbldap_state) {
533 DLIST_REMOVE(smbldap_state_lookup_list, t);
534 SAFE_FREE(t);
535 return;
540 static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state)
542 struct smbldap_state *tmp_ldap_state;
543 struct smbldap_state_lookup *t;
545 if ((tmp_ldap_state = smbldap_find_state(ld))) {
546 SMB_ASSERT(tmp_ldap_state == smbldap_state);
547 return;
550 t = SMB_XMALLOC_P(struct smbldap_state_lookup);
551 ZERO_STRUCTP(t);
553 DLIST_ADD_END(smbldap_state_lookup_list, t, struct smbldap_state_lookup *);
554 t->ld = ld;
555 t->smbldap_state = smbldap_state;
558 /********************************************************************
559 start TLS on an existing LDAP connection
560 *******************************************************************/
562 int smb_ldap_start_tls(LDAP *ldap_struct, int version)
564 #ifdef LDAP_OPT_X_TLS
565 int rc;
566 #endif
568 if (lp_ldap_ssl() != LDAP_SSL_START_TLS) {
569 return LDAP_SUCCESS;
572 #ifdef LDAP_OPT_X_TLS
573 if (version != LDAP_VERSION3) {
574 DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
575 return LDAP_OPERATIONS_ERROR;
578 if ((rc = ldap_start_tls_s (ldap_struct, NULL, NULL)) != LDAP_SUCCESS) {
579 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
580 ldap_err2string(rc)));
581 return rc;
584 DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
585 return LDAP_SUCCESS;
586 #else
587 DEBUG(0,("StartTLS not supported by LDAP client libraries!\n"));
588 return LDAP_OPERATIONS_ERROR;
589 #endif
592 /********************************************************************
593 setup a connection to the LDAP server based on a uri
594 *******************************************************************/
596 static int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri)
598 int rc;
600 DEBUG(10, ("smb_ldap_setup_connection: %s\n", uri));
602 #ifdef HAVE_LDAP_INITIALIZE
604 rc = ldap_initialize(ldap_struct, uri);
605 if (rc) {
606 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
607 return rc;
610 if (lp_ldap_follow_referral() != Auto) {
611 rc = ldap_set_option(*ldap_struct, LDAP_OPT_REFERRALS,
612 lp_ldap_follow_referral() ? LDAP_OPT_ON : LDAP_OPT_OFF);
613 if (rc != LDAP_SUCCESS)
614 DEBUG(0, ("Failed to set LDAP_OPT_REFERRALS: %s\n",
615 ldap_err2string(rc)));
618 return LDAP_SUCCESS;
619 #else
621 /* Parse the string manually */
624 int port = 0;
625 fstring protocol;
626 fstring host;
627 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
630 /* skip leading "URL:" (if any) */
631 if ( strnequal( uri, "URL:", 4 ) ) {
632 uri += 4;
635 sscanf(uri, "%10[^:]://%254[^:/]:%d", protocol, host, &port);
637 if (port == 0) {
638 if (strequal(protocol, "ldap")) {
639 port = LDAP_PORT;
640 } else if (strequal(protocol, "ldaps")) {
641 port = LDAPS_PORT;
642 } else {
643 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
647 if ((*ldap_struct = ldap_init(host, port)) == NULL) {
648 DEBUG(0, ("ldap_init failed !\n"));
649 return LDAP_OPERATIONS_ERROR;
652 if (strequal(protocol, "ldaps")) {
653 #ifdef LDAP_OPT_X_TLS
654 int tls = LDAP_OPT_X_TLS_HARD;
655 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
657 DEBUG(0, ("Failed to setup a TLS session\n"));
660 DEBUG(3,("LDAPS option set...!\n"));
661 #else
662 DEBUG(0,("smbldap_open_connection: Secure connection not supported by LDAP client libraries!\n"));
663 return LDAP_OPERATIONS_ERROR;
664 #endif /* LDAP_OPT_X_TLS */
667 #endif /* HAVE_LDAP_INITIALIZE */
669 /* now set connection timeout */
670 #ifdef LDAP_X_OPT_CONNECT_TIMEOUT /* Netscape */
672 int ct = lp_ldap_connection_timeout()*1000;
673 rc = ldap_set_option(*ldap_struct, LDAP_X_OPT_CONNECT_TIMEOUT, &ct);
674 if (rc != LDAP_SUCCESS) {
675 DEBUG(0,("Failed to setup an ldap connection timeout %d: %s\n",
676 ct, ldap_err2string(rc)));
679 #elif defined (LDAP_OPT_NETWORK_TIMEOUT) /* OpenLDAP */
681 struct timeval ct;
682 ct.tv_usec = 0;
683 ct.tv_sec = lp_ldap_connection_timeout();
684 rc = ldap_set_option(*ldap_struct, LDAP_OPT_NETWORK_TIMEOUT, &ct);
685 if (rc != LDAP_SUCCESS) {
686 DEBUG(0,("Failed to setup an ldap connection timeout %d: %s\n",
687 (int)ct.tv_sec, ldap_err2string(rc)));
690 #endif
692 return LDAP_SUCCESS;
695 /********************************************************************
696 try to upgrade to Version 3 LDAP if not already, in either case return current
697 version
698 *******************************************************************/
700 static int smb_ldap_upgrade_conn(LDAP *ldap_struct, int *new_version)
702 int version;
703 int rc;
705 /* assume the worst */
706 *new_version = LDAP_VERSION2;
708 rc = ldap_get_option(ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
709 if (rc) {
710 return rc;
713 if (version == LDAP_VERSION3) {
714 *new_version = LDAP_VERSION3;
715 return LDAP_SUCCESS;
718 /* try upgrade */
719 version = LDAP_VERSION3;
720 rc = ldap_set_option (ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
721 if (rc) {
722 return rc;
725 *new_version = LDAP_VERSION3;
726 return LDAP_SUCCESS;
729 /*******************************************************************
730 open a connection to the ldap server (just until the bind)
731 ******************************************************************/
733 int smb_ldap_setup_full_conn(LDAP **ldap_struct, const char *uri)
735 int rc, version;
737 rc = smb_ldap_setup_conn(ldap_struct, uri);
738 if (rc) {
739 return rc;
742 rc = smb_ldap_upgrade_conn(*ldap_struct, &version);
743 if (rc) {
744 return rc;
747 rc = smb_ldap_start_tls(*ldap_struct, version);
748 if (rc) {
749 return rc;
752 return LDAP_SUCCESS;
755 /*******************************************************************
756 open a connection to the ldap server.
757 ******************************************************************/
758 static int smbldap_open_connection (struct smbldap_state *ldap_state)
761 int rc = LDAP_SUCCESS;
762 int version;
763 int deref;
764 LDAP **ldap_struct = &ldap_state->ldap_struct;
766 rc = smb_ldap_setup_conn(ldap_struct, ldap_state->uri);
767 if (rc) {
768 return rc;
771 /* Store the LDAP pointer in a lookup list */
773 smbldap_store_state(*ldap_struct, ldap_state);
775 /* Upgrade to LDAPv3 if possible */
777 rc = smb_ldap_upgrade_conn(*ldap_struct, &version);
778 if (rc) {
779 return rc;
782 /* Start TLS if required */
784 rc = smb_ldap_start_tls(*ldap_struct, version);
785 if (rc) {
786 return rc;
789 /* Set alias dereferencing method */
790 deref = lp_ldap_deref();
791 if (deref != -1) {
792 if (ldap_set_option (*ldap_struct, LDAP_OPT_DEREF, &deref) != LDAP_OPT_SUCCESS) {
793 DEBUG(1,("smbldap_open_connection: Failed to set dereferencing method: %d\n", deref));
794 } else {
795 DEBUG(5,("Set dereferencing method: %d\n", deref));
799 DEBUG(2, ("smbldap_open_connection: connection opened\n"));
800 return rc;
803 /*******************************************************************
804 a rebind function for authenticated referrals
805 This version takes a void* that we can shove useful stuff in :-)
806 ******************************************************************/
807 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
808 #else
809 static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
810 int *methodp, int freeit, void *arg)
812 struct smbldap_state *ldap_state = arg;
813 struct timespec ts;
815 /** @TODO Should we be doing something to check what servers we rebind to?
816 Could we get a referral to a machine that we don't want to give our
817 username and password to? */
819 if (freeit) {
820 SAFE_FREE(*whop);
821 if (*credp) {
822 memset(*credp, '\0', strlen(*credp));
824 SAFE_FREE(*credp);
825 } else {
826 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
827 ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
829 if (ldap_state->anonymous) {
830 *whop = NULL;
831 *credp = NULL;
832 } else {
833 *whop = SMB_STRDUP(ldap_state->bind_dn);
834 if (!*whop) {
835 return LDAP_NO_MEMORY;
837 *credp = SMB_STRDUP(ldap_state->bind_secret);
838 if (!*credp) {
839 SAFE_FREE(*whop);
840 return LDAP_NO_MEMORY;
843 *methodp = LDAP_AUTH_SIMPLE;
846 clock_gettime_mono(&ts);
847 ldap_state->last_rebind = convert_timespec_to_timeval(ts);
849 return 0;
851 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
853 /*******************************************************************
854 a rebind function for authenticated referrals
855 This version takes a void* that we can shove useful stuff in :-)
856 and actually does the connection.
857 ******************************************************************/
858 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
859 static int rebindproc_connect_with_state (LDAP *ldap_struct,
860 LDAP_CONST char *url,
861 ber_tag_t request,
862 ber_int_t msgid, void *arg)
864 struct smbldap_state *ldap_state =
865 (struct smbldap_state *)arg;
866 int rc;
867 struct timespec ts;
868 int version;
870 DEBUG(5,("rebindproc_connect_with_state: Rebinding to %s as \"%s\"\n",
871 url, ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
873 /* call START_TLS again (ldaps:// is handled by the OpenLDAP library
874 * itself) before rebinding to another LDAP server to avoid to expose
875 * our credentials. At least *try* to secure the connection - Guenther */
877 smb_ldap_upgrade_conn(ldap_struct, &version);
878 smb_ldap_start_tls(ldap_struct, version);
880 /** @TODO Should we be doing something to check what servers we rebind to?
881 Could we get a referral to a machine that we don't want to give our
882 username and password to? */
884 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
886 /* only set the last rebind timestamp when we did rebind after a
887 * non-read LDAP operation. That way we avoid the replication sleep
888 * after a simple redirected search operation - Guenther */
890 switch (request) {
892 case LDAP_REQ_MODIFY:
893 case LDAP_REQ_ADD:
894 case LDAP_REQ_DELETE:
895 case LDAP_REQ_MODDN:
896 case LDAP_REQ_EXTENDED:
897 DEBUG(10,("rebindproc_connect_with_state: "
898 "setting last_rebind timestamp "
899 "(req: 0x%02x)\n", (unsigned int)request));
900 clock_gettime_mono(&ts);
901 ldap_state->last_rebind = convert_timespec_to_timeval(ts);
902 break;
903 default:
904 ZERO_STRUCT(ldap_state->last_rebind);
905 break;
908 return rc;
910 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
912 /*******************************************************************
913 Add a rebind function for authenticated referrals
914 ******************************************************************/
915 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
916 #else
917 # if LDAP_SET_REBIND_PROC_ARGS == 2
918 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
919 int *method, int freeit )
921 struct smbldap_state *ldap_state = smbldap_find_state(ldap_struct);
923 return rebindproc_with_state(ldap_struct, whop, credp,
924 method, freeit, ldap_state);
926 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
927 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
929 /*******************************************************************
930 a rebind function for authenticated referrals
931 this also does the connection, but no void*.
932 ******************************************************************/
933 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
934 # if LDAP_SET_REBIND_PROC_ARGS == 2
935 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
936 ber_int_t msgid)
938 struct smbldap_state *ldap_state = smbldap_find_state(ld);
940 return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid,
941 ldap_state);
943 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
944 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
946 /*******************************************************************
947 connect to the ldap server under system privilege.
948 ******************************************************************/
949 static int smbldap_connect_system(struct smbldap_state *ldap_state)
951 LDAP *ldap_struct = ldap_state->ldap_struct;
952 int rc;
953 int version;
955 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
956 (OpenLDAP) doesnt' seem to support it */
958 DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
959 ldap_state->uri, ldap_state->bind_dn));
961 #ifdef HAVE_LDAP_SET_REBIND_PROC
962 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
963 # if LDAP_SET_REBIND_PROC_ARGS == 2
964 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect);
965 # endif
966 # if LDAP_SET_REBIND_PROC_ARGS == 3
967 ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);
968 # endif
969 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
970 # if LDAP_SET_REBIND_PROC_ARGS == 2
971 ldap_set_rebind_proc(ldap_struct, &rebindproc);
972 # endif
973 # if LDAP_SET_REBIND_PROC_ARGS == 3
974 ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);
975 # endif
976 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
977 #endif
979 /* When there is an alternative bind callback is set,
980 attempt to use it to perform the bind */
981 if (ldap_state->bind_callback != NULL) {
982 /* We have to allow bind callback to be run under become_root/unbecome_root
983 to make sure within smbd the callback has proper write access to its resources,
984 like credential cache. This is similar to passdb case where this callback is supposed
985 to be used. When used outside smbd, become_root()/unbecome_root() are no-op.
987 become_root();
988 rc = ldap_state->bind_callback(ldap_struct, ldap_state, ldap_state->bind_callback_data);
989 unbecome_root();
990 } else {
991 rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
994 if (rc != LDAP_SUCCESS) {
995 char *ld_error = NULL;
996 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
997 &ld_error);
998 DEBUG(ldap_state->num_failures ? 2 : 0,
999 ("failed to bind to server %s with dn=\"%s\" Error: %s\n\t%s\n",
1000 ldap_state->uri,
1001 ldap_state->bind_dn ? ldap_state->bind_dn : "[Anonymous bind]",
1002 ldap_err2string(rc),
1003 ld_error ? ld_error : "(unknown)"));
1004 SAFE_FREE(ld_error);
1005 ldap_state->num_failures++;
1006 goto done;
1009 ldap_state->num_failures = 0;
1010 ldap_state->paged_results = False;
1012 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
1014 if (smbldap_has_control(ldap_state->ldap_struct, ADS_PAGE_CTL_OID) && version == 3) {
1015 ldap_state->paged_results = True;
1018 DEBUG(3, ("ldap_connect_system: successful connection to the LDAP server\n"));
1019 DEBUGADD(10, ("ldap_connect_system: LDAP server %s support paged results\n",
1020 ldap_state->paged_results ? "does" : "does not"));
1021 done:
1022 if (rc != 0) {
1023 ldap_unbind(ldap_struct);
1024 ldap_state->ldap_struct = NULL;
1026 return rc;
1029 static void smbldap_idle_fn(struct tevent_context *tevent_ctx,
1030 struct timed_event *te,
1031 struct timeval now_abs,
1032 void *private_data);
1034 /**********************************************************************
1035 Connect to LDAP server (called before every ldap operation)
1036 *********************************************************************/
1037 static int smbldap_open(struct smbldap_state *ldap_state)
1039 int rc, opt_rc;
1040 bool reopen = False;
1041 SMB_ASSERT(ldap_state);
1043 if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + SMBLDAP_DONT_PING_TIME) < time_mono(NULL))) {
1045 #ifdef HAVE_UNIXSOCKET
1046 struct sockaddr_un addr;
1047 #else
1048 struct sockaddr addr;
1049 #endif
1050 socklen_t len = sizeof(addr);
1051 int sd;
1053 opt_rc = ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd);
1054 if (opt_rc == 0 && (getpeername(sd, (struct sockaddr *) &addr, &len)) < 0 )
1055 reopen = True;
1057 #ifdef HAVE_UNIXSOCKET
1058 if (opt_rc == 0 && addr.sun_family == AF_UNIX)
1059 reopen = True;
1060 #endif
1061 if (reopen) {
1062 /* the other end has died. reopen. */
1063 ldap_unbind(ldap_state->ldap_struct);
1064 ldap_state->ldap_struct = NULL;
1065 ldap_state->last_ping = (time_t)0;
1066 } else {
1067 ldap_state->last_ping = time_mono(NULL);
1071 if (ldap_state->ldap_struct != NULL) {
1072 DEBUG(11,("smbldap_open: already connected to the LDAP server\n"));
1073 return LDAP_SUCCESS;
1076 if ((rc = smbldap_open_connection(ldap_state))) {
1077 return rc;
1080 if ((rc = smbldap_connect_system(ldap_state))) {
1081 return rc;
1085 ldap_state->last_ping = time_mono(NULL);
1086 ldap_state->pid = getpid();
1088 TALLOC_FREE(ldap_state->idle_event);
1090 if (ldap_state->tevent_context != NULL) {
1091 ldap_state->idle_event = tevent_add_timer(
1092 ldap_state->tevent_context, ldap_state,
1093 timeval_current_ofs(SMBLDAP_IDLE_TIME, 0),
1094 smbldap_idle_fn, ldap_state);
1097 DEBUG(4,("The LDAP server is successfully connected\n"));
1099 return LDAP_SUCCESS;
1102 /**********************************************************************
1103 Disconnect from LDAP server
1104 *********************************************************************/
1105 static NTSTATUS smbldap_close(struct smbldap_state *ldap_state)
1107 if (!ldap_state)
1108 return NT_STATUS_INVALID_PARAMETER;
1110 if (ldap_state->ldap_struct != NULL) {
1111 ldap_unbind(ldap_state->ldap_struct);
1112 ldap_state->ldap_struct = NULL;
1115 smbldap_delete_state(ldap_state);
1117 TALLOC_FREE(ldap_state->idle_event);
1119 DEBUG(5,("The connection to the LDAP server was closed\n"));
1120 /* maybe free the results here --metze */
1122 return NT_STATUS_OK;
1125 static SIG_ATOMIC_T got_alarm;
1127 static void gotalarm_sig(int dummy)
1129 got_alarm = 1;
1132 static time_t calc_ldap_abs_endtime(int ldap_to)
1134 if (ldap_to == 0) {
1135 /* No timeout - don't
1136 return a value for
1137 the alarm. */
1138 return (time_t)0;
1141 /* Make the alarm time one second beyond
1142 the timout we're setting for the
1143 remote search timeout, to allow that
1144 to fire in preference. */
1146 return time_mono(NULL)+ldap_to+1;
1149 static int end_ldap_local_alarm(time_t absolute_endtime, int rc)
1151 if (absolute_endtime) {
1152 alarm(0);
1153 CatchSignal(SIGALRM, SIG_IGN);
1154 if (got_alarm) {
1155 /* Client timeout error code. */
1156 got_alarm = 0;
1157 return LDAP_TIMEOUT;
1160 return rc;
1163 static void setup_ldap_local_alarm(struct smbldap_state *ldap_state, time_t absolute_endtime)
1165 time_t now = time_mono(NULL);
1167 if (absolute_endtime) {
1168 got_alarm = 0;
1169 CatchSignal(SIGALRM, gotalarm_sig);
1170 alarm(absolute_endtime - now);
1173 if (ldap_state->pid != getpid()) {
1174 smbldap_close(ldap_state);
1178 static void get_ldap_errs(struct smbldap_state *ldap_state, char **pp_ld_error, int *p_ld_errno)
1180 ldap_get_option(ldap_state->ldap_struct,
1181 LDAP_OPT_ERROR_NUMBER, p_ld_errno);
1183 ldap_get_option(ldap_state->ldap_struct,
1184 LDAP_OPT_ERROR_STRING, pp_ld_error);
1187 static int get_cached_ldap_connect(struct smbldap_state *ldap_state, time_t abs_endtime)
1189 int attempts = 0;
1191 while (1) {
1192 int rc;
1193 time_t now;
1195 now = time_mono(NULL);
1196 ldap_state->last_use = now;
1198 if (abs_endtime && now > abs_endtime) {
1199 smbldap_close(ldap_state);
1200 return LDAP_TIMEOUT;
1203 rc = smbldap_open(ldap_state);
1205 if (rc == LDAP_SUCCESS) {
1206 return LDAP_SUCCESS;
1209 attempts++;
1210 DEBUG(1, ("Connection to LDAP server failed for the "
1211 "%d try!\n", attempts));
1213 if (rc == LDAP_INSUFFICIENT_ACCESS) {
1214 /* The fact that we are non-root or any other
1215 * access-denied condition will not change in the next
1216 * round of trying */
1217 return rc;
1220 if (got_alarm) {
1221 smbldap_close(ldap_state);
1222 return LDAP_TIMEOUT;
1225 smb_msleep(1000);
1227 if (got_alarm) {
1228 smbldap_close(ldap_state);
1229 return LDAP_TIMEOUT;
1234 /*********************************************************************
1235 ********************************************************************/
1237 static int smbldap_search_ext(struct smbldap_state *ldap_state,
1238 const char *base, int scope, const char *filter,
1239 const char *attrs[], int attrsonly,
1240 LDAPControl **sctrls, LDAPControl **cctrls,
1241 int sizelimit, LDAPMessage **res)
1243 int rc = LDAP_SERVER_DOWN;
1244 char *utf8_filter;
1245 int to = lp_ldap_timeout();
1246 time_t abs_endtime = calc_ldap_abs_endtime(to);
1247 struct timeval timeout;
1248 struct timeval *timeout_ptr = NULL;
1249 size_t converted_size;
1251 SMB_ASSERT(ldap_state);
1253 DEBUG(5,("smbldap_search_ext: base => [%s], filter => [%s], "
1254 "scope => [%d]\n", base, filter, scope));
1256 if (ldap_state->last_rebind.tv_sec > 0) {
1257 struct timeval tval;
1258 struct timespec ts;
1259 int64_t tdiff = 0;
1260 int sleep_time = 0;
1262 clock_gettime_mono(&ts);
1263 tval = convert_timespec_to_timeval(ts);
1265 tdiff = usec_time_diff(&tval, &ldap_state->last_rebind);
1266 tdiff /= 1000; /* Convert to milliseconds. */
1268 sleep_time = lp_ldap_replication_sleep()-(int)tdiff;
1269 sleep_time = MIN(sleep_time, MAX_LDAP_REPLICATION_SLEEP_TIME);
1271 if (sleep_time > 0) {
1272 /* we wait for the LDAP replication */
1273 DEBUG(5,("smbldap_search_ext: waiting %d milliseconds "
1274 "for LDAP replication.\n",sleep_time));
1275 smb_msleep(sleep_time);
1276 DEBUG(5,("smbldap_search_ext: go on!\n"));
1278 ZERO_STRUCT(ldap_state->last_rebind);
1281 if (!push_utf8_talloc(talloc_tos(), &utf8_filter, filter, &converted_size)) {
1282 return LDAP_NO_MEMORY;
1285 /* Setup remote timeout for the ldap_search_ext_s call. */
1286 if (to) {
1287 timeout.tv_sec = to;
1288 timeout.tv_usec = 0;
1289 timeout_ptr = &timeout;
1292 setup_ldap_local_alarm(ldap_state, abs_endtime);
1294 while (1) {
1295 char *ld_error = NULL;
1296 int ld_errno;
1298 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1299 if (rc != LDAP_SUCCESS) {
1300 break;
1303 rc = ldap_search_ext_s(ldap_state->ldap_struct, base, scope,
1304 utf8_filter,
1305 discard_const_p(char *, attrs),
1306 attrsonly, sctrls, cctrls, timeout_ptr,
1307 sizelimit, res);
1308 if (rc == LDAP_SUCCESS) {
1309 break;
1312 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1314 DEBUG(10, ("Failed search for base: %s, error: %d (%s) "
1315 "(%s)\n", base, ld_errno,
1316 ldap_err2string(rc),
1317 ld_error ? ld_error : "unknown"));
1318 SAFE_FREE(ld_error);
1320 if (ld_errno != LDAP_SERVER_DOWN) {
1321 break;
1323 ldap_unbind(ldap_state->ldap_struct);
1324 ldap_state->ldap_struct = NULL;
1327 TALLOC_FREE(utf8_filter);
1328 return end_ldap_local_alarm(abs_endtime, rc);
1331 int smbldap_search(struct smbldap_state *ldap_state,
1332 const char *base, int scope, const char *filter,
1333 const char *attrs[], int attrsonly,
1334 LDAPMessage **res)
1336 return smbldap_search_ext(ldap_state, base, scope, filter, attrs,
1337 attrsonly, NULL, NULL, LDAP_NO_LIMIT, res);
1340 int smbldap_search_paged(struct smbldap_state *ldap_state,
1341 const char *base, int scope, const char *filter,
1342 const char **attrs, int attrsonly, int pagesize,
1343 LDAPMessage **res, void **cookie)
1345 LDAPControl pr;
1346 LDAPControl **rcontrols;
1347 LDAPControl *controls[2] = { NULL, NULL};
1348 BerElement *cookie_be = NULL;
1349 struct berval *cookie_bv = NULL;
1350 int tmp = 0, i, rc;
1351 bool critical = True;
1353 *res = NULL;
1355 DEBUG(3,("smbldap_search_paged: base => [%s], filter => [%s],"
1356 "scope => [%d], pagesize => [%d]\n",
1357 base, filter, scope, pagesize));
1359 cookie_be = ber_alloc_t(LBER_USE_DER);
1360 if (cookie_be == NULL) {
1361 DEBUG(0,("smbldap_create_page_control: ber_alloc_t returns "
1362 "NULL\n"));
1363 return LDAP_NO_MEMORY;
1366 /* construct cookie */
1367 if (*cookie != NULL) {
1368 ber_printf(cookie_be, "{iO}", (ber_int_t) pagesize, *cookie);
1369 ber_bvfree((struct berval *)*cookie); /* don't need it from last time */
1370 *cookie = NULL;
1371 } else {
1372 ber_printf(cookie_be, "{io}", (ber_int_t) pagesize, "", 0);
1374 ber_flatten(cookie_be, &cookie_bv);
1376 pr.ldctl_oid = discard_const_p(char, ADS_PAGE_CTL_OID);
1377 pr.ldctl_iscritical = (char) critical;
1378 pr.ldctl_value.bv_len = cookie_bv->bv_len;
1379 pr.ldctl_value.bv_val = cookie_bv->bv_val;
1381 controls[0] = &pr;
1382 controls[1] = NULL;
1384 rc = smbldap_search_ext(ldap_state, base, scope, filter, attrs,
1385 0, controls, NULL, LDAP_NO_LIMIT, res);
1387 ber_free(cookie_be, 1);
1388 ber_bvfree(cookie_bv);
1390 if (rc != 0) {
1391 DEBUG(3,("smbldap_search_paged: smbldap_search_ext(%s) "
1392 "failed with [%s]\n", filter, ldap_err2string(rc)));
1393 goto done;
1396 DEBUG(3,("smbldap_search_paged: search was successful\n"));
1398 rc = ldap_parse_result(ldap_state->ldap_struct, *res, NULL, NULL,
1399 NULL, NULL, &rcontrols, 0);
1400 if (rc != 0) {
1401 DEBUG(3,("smbldap_search_paged: ldap_parse_result failed " \
1402 "with [%s]\n", ldap_err2string(rc)));
1403 goto done;
1406 if (rcontrols == NULL)
1407 goto done;
1409 for (i=0; rcontrols[i]; i++) {
1411 if (strcmp(ADS_PAGE_CTL_OID, rcontrols[i]->ldctl_oid) != 0)
1412 continue;
1414 cookie_be = ber_init(&rcontrols[i]->ldctl_value);
1415 ber_scanf(cookie_be,"{iO}", &tmp, &cookie_bv);
1416 /* the berval is the cookie, but must be freed when it is all
1417 done */
1418 if (cookie_bv->bv_len)
1419 *cookie=ber_bvdup(cookie_bv);
1420 else
1421 *cookie=NULL;
1422 ber_bvfree(cookie_bv);
1423 ber_free(cookie_be, 1);
1424 break;
1426 ldap_controls_free(rcontrols);
1427 done:
1428 return rc;
1431 int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
1433 int rc = LDAP_SERVER_DOWN;
1434 char *utf8_dn;
1435 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1436 size_t converted_size;
1438 SMB_ASSERT(ldap_state);
1440 DEBUG(5,("smbldap_modify: dn => [%s]\n", dn ));
1442 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1443 return LDAP_NO_MEMORY;
1446 setup_ldap_local_alarm(ldap_state, abs_endtime);
1448 while (1) {
1449 char *ld_error = NULL;
1450 int ld_errno;
1452 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1453 if (rc != LDAP_SUCCESS) {
1454 break;
1457 rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs);
1458 if (rc == LDAP_SUCCESS) {
1459 break;
1462 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1464 DEBUG(10, ("Failed to modify dn: %s, error: %d (%s) "
1465 "(%s)\n", dn, ld_errno,
1466 ldap_err2string(rc),
1467 ld_error ? ld_error : "unknown"));
1468 SAFE_FREE(ld_error);
1470 if (ld_errno != LDAP_SERVER_DOWN) {
1471 break;
1473 ldap_unbind(ldap_state->ldap_struct);
1474 ldap_state->ldap_struct = NULL;
1477 TALLOC_FREE(utf8_dn);
1478 return end_ldap_local_alarm(abs_endtime, rc);
1481 int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
1483 int rc = LDAP_SERVER_DOWN;
1484 char *utf8_dn;
1485 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1486 size_t converted_size;
1488 SMB_ASSERT(ldap_state);
1490 DEBUG(5,("smbldap_add: dn => [%s]\n", dn ));
1492 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1493 return LDAP_NO_MEMORY;
1496 setup_ldap_local_alarm(ldap_state, abs_endtime);
1498 while (1) {
1499 char *ld_error = NULL;
1500 int ld_errno;
1502 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1503 if (rc != LDAP_SUCCESS) {
1504 break;
1507 rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs);
1508 if (rc == LDAP_SUCCESS) {
1509 break;
1512 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1514 DEBUG(10, ("Failed to add dn: %s, error: %d (%s) "
1515 "(%s)\n", dn, ld_errno,
1516 ldap_err2string(rc),
1517 ld_error ? ld_error : "unknown"));
1518 SAFE_FREE(ld_error);
1520 if (ld_errno != LDAP_SERVER_DOWN) {
1521 break;
1523 ldap_unbind(ldap_state->ldap_struct);
1524 ldap_state->ldap_struct = NULL;
1527 TALLOC_FREE(utf8_dn);
1528 return end_ldap_local_alarm(abs_endtime, rc);
1531 int smbldap_delete(struct smbldap_state *ldap_state, const char *dn)
1533 int rc = LDAP_SERVER_DOWN;
1534 char *utf8_dn;
1535 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1536 size_t converted_size;
1538 SMB_ASSERT(ldap_state);
1540 DEBUG(5,("smbldap_delete: dn => [%s]\n", dn ));
1542 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1543 return LDAP_NO_MEMORY;
1546 setup_ldap_local_alarm(ldap_state, abs_endtime);
1548 while (1) {
1549 char *ld_error = NULL;
1550 int ld_errno;
1552 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1553 if (rc != LDAP_SUCCESS) {
1554 break;
1557 rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn);
1558 if (rc == LDAP_SUCCESS) {
1559 break;
1562 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1564 DEBUG(10, ("Failed to delete dn: %s, error: %d (%s) "
1565 "(%s)\n", dn, ld_errno,
1566 ldap_err2string(rc),
1567 ld_error ? ld_error : "unknown"));
1568 SAFE_FREE(ld_error);
1570 if (ld_errno != LDAP_SERVER_DOWN) {
1571 break;
1573 ldap_unbind(ldap_state->ldap_struct);
1574 ldap_state->ldap_struct = NULL;
1577 TALLOC_FREE(utf8_dn);
1578 return end_ldap_local_alarm(abs_endtime, rc);
1581 int smbldap_extended_operation(struct smbldap_state *ldap_state,
1582 LDAP_CONST char *reqoid, struct berval *reqdata,
1583 LDAPControl **serverctrls, LDAPControl **clientctrls,
1584 char **retoidp, struct berval **retdatap)
1586 int rc = LDAP_SERVER_DOWN;
1587 time_t abs_endtime = calc_ldap_abs_endtime(lp_ldap_timeout());
1589 if (!ldap_state)
1590 return (-1);
1592 setup_ldap_local_alarm(ldap_state, abs_endtime);
1594 while (1) {
1595 char *ld_error = NULL;
1596 int ld_errno;
1598 rc = get_cached_ldap_connect(ldap_state, abs_endtime);
1599 if (rc != LDAP_SUCCESS) {
1600 break;
1603 rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid,
1604 reqdata, serverctrls,
1605 clientctrls, retoidp, retdatap);
1606 if (rc == LDAP_SUCCESS) {
1607 break;
1610 get_ldap_errs(ldap_state, &ld_error, &ld_errno);
1612 DEBUG(10, ("Extended operation failed with error: "
1613 "%d (%s) (%s)\n", ld_errno,
1614 ldap_err2string(rc),
1615 ld_error ? ld_error : "unknown"));
1616 SAFE_FREE(ld_error);
1618 if (ld_errno != LDAP_SERVER_DOWN) {
1619 break;
1621 ldap_unbind(ldap_state->ldap_struct);
1622 ldap_state->ldap_struct = NULL;
1625 return end_ldap_local_alarm(abs_endtime, rc);
1628 /*******************************************************************
1629 run the search by name.
1630 ******************************************************************/
1631 int smbldap_search_suffix (struct smbldap_state *ldap_state,
1632 const char *filter, const char **search_attr,
1633 LDAPMessage ** result)
1635 return smbldap_search(ldap_state, lp_ldap_suffix(), LDAP_SCOPE_SUBTREE,
1636 filter, search_attr, 0, result);
1639 static void smbldap_idle_fn(struct tevent_context *tevent_ctx,
1640 struct timed_event *te,
1641 struct timeval now_abs,
1642 void *private_data)
1644 struct smbldap_state *state = (struct smbldap_state *)private_data;
1646 TALLOC_FREE(state->idle_event);
1648 if (state->ldap_struct == NULL) {
1649 DEBUG(10,("ldap connection not connected...\n"));
1650 return;
1653 if ((state->last_use+SMBLDAP_IDLE_TIME) > time_mono(NULL)) {
1654 DEBUG(10,("ldap connection not idle...\n"));
1656 /* this needs to be made monotonic clock aware inside tevent: */
1657 state->idle_event = tevent_add_timer(
1658 tevent_ctx, state,
1659 timeval_add(&now_abs, SMBLDAP_IDLE_TIME, 0),
1660 smbldap_idle_fn,
1661 private_data);
1662 return;
1665 DEBUG(7,("ldap connection idle...closing connection\n"));
1666 smbldap_close(state);
1669 /**********************************************************************
1670 Housekeeping
1671 *********************************************************************/
1673 void smbldap_free_struct(struct smbldap_state **ldap_state)
1675 smbldap_close(*ldap_state);
1677 if ((*ldap_state)->bind_secret) {
1678 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
1681 SAFE_FREE((*ldap_state)->bind_dn);
1682 SAFE_FREE((*ldap_state)->bind_secret);
1683 (*ldap_state)->bind_callback = NULL;
1684 (*ldap_state)->bind_callback_data = NULL;
1686 TALLOC_FREE(*ldap_state);
1688 /* No need to free any further, as it is talloc()ed */
1691 static int smbldap_state_destructor(struct smbldap_state *state)
1693 smbldap_free_struct(&state);
1694 return 0;
1698 /**********************************************************************
1699 Intitalise the 'general' ldap structures, on which ldap operations may be conducted
1700 *********************************************************************/
1702 NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, struct tevent_context *tevent_ctx,
1703 const char *location,
1704 bool anon,
1705 const char *bind_dn,
1706 const char *bind_secret,
1707 struct smbldap_state **smbldap_state)
1709 *smbldap_state = talloc_zero(mem_ctx, struct smbldap_state);
1710 if (!*smbldap_state) {
1711 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
1712 return NT_STATUS_NO_MEMORY;
1715 if (location) {
1716 (*smbldap_state)->uri = talloc_strdup(mem_ctx, location);
1717 } else {
1718 (*smbldap_state)->uri = "ldap://localhost";
1721 (*smbldap_state)->tevent_context = tevent_ctx;
1723 if (bind_dn && bind_secret) {
1724 smbldap_set_creds(*smbldap_state, anon, bind_dn, bind_secret);
1727 talloc_set_destructor(*smbldap_state, smbldap_state_destructor);
1728 return NT_STATUS_OK;
1731 char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld,
1732 LDAPMessage *entry)
1734 char *utf8_dn, *unix_dn;
1735 size_t converted_size;
1737 utf8_dn = ldap_get_dn(ld, entry);
1738 if (!utf8_dn) {
1739 DEBUG (5, ("smbldap_talloc_dn: ldap_get_dn failed\n"));
1740 return NULL;
1742 if (!pull_utf8_talloc(mem_ctx, &unix_dn, utf8_dn, &converted_size)) {
1743 DEBUG (0, ("smbldap_talloc_dn: String conversion failure utf8 "
1744 "[%s]\n", utf8_dn));
1745 return NULL;
1747 ldap_memfree(utf8_dn);
1748 return unix_dn;
1751 /*******************************************************************
1752 Check if root-dse has a certain Control or Extension
1753 ********************************************************************/
1755 static bool smbldap_check_root_dse(LDAP *ld, const char **attrs, const char *value)
1757 LDAPMessage *msg = NULL;
1758 LDAPMessage *entry = NULL;
1759 char **values = NULL;
1760 int rc, num_result, num_values, i;
1761 bool result = False;
1763 if (!attrs[0]) {
1764 DEBUG(3,("smbldap_check_root_dse: nothing to look for\n"));
1765 return False;
1768 if (!strequal(attrs[0], "supportedExtension") &&
1769 !strequal(attrs[0], "supportedControl") &&
1770 !strequal(attrs[0], "namingContexts")) {
1771 DEBUG(3,("smbldap_check_root_dse: no idea what to query root-dse for: %s ?\n", attrs[0]));
1772 return False;
1775 rc = ldap_search_s(ld, "", LDAP_SCOPE_BASE,
1776 "(objectclass=*)", discard_const_p(char *, attrs), 0 , &msg);
1778 if (rc != LDAP_SUCCESS) {
1779 DEBUG(3,("smbldap_check_root_dse: Could not search rootDSE\n"));
1780 return False;
1783 num_result = ldap_count_entries(ld, msg);
1785 if (num_result != 1) {
1786 DEBUG(3,("smbldap_check_root_dse: Expected one rootDSE, got %d\n", num_result));
1787 goto done;
1790 entry = ldap_first_entry(ld, msg);
1792 if (entry == NULL) {
1793 DEBUG(3,("smbldap_check_root_dse: Could not retrieve rootDSE\n"));
1794 goto done;
1797 values = ldap_get_values(ld, entry, attrs[0]);
1799 if (values == NULL) {
1800 DEBUG(5,("smbldap_check_root_dse: LDAP Server does not support any %s\n", attrs[0]));
1801 goto done;
1804 num_values = ldap_count_values(values);
1806 if (num_values == 0) {
1807 DEBUG(5,("smbldap_check_root_dse: LDAP Server does not have any %s\n", attrs[0]));
1808 goto done;
1811 for (i=0; i<num_values; i++) {
1812 if (strcmp(values[i], value) == 0)
1813 result = True;
1817 done:
1818 if (values != NULL)
1819 ldap_value_free(values);
1820 if (msg != NULL)
1821 ldap_msgfree(msg);
1823 return result;
1827 /*******************************************************************
1828 Check if LDAP-Server supports a certain Control (OID in string format)
1829 ********************************************************************/
1831 bool smbldap_has_control(LDAP *ld, const char *control)
1833 const char *attrs[] = { "supportedControl", NULL };
1834 return smbldap_check_root_dse(ld, attrs, control);
1837 /*******************************************************************
1838 Check if LDAP-Server supports a certain Extension (OID in string format)
1839 ********************************************************************/
1841 bool smbldap_has_extension(LDAP *ld, const char *extension)
1843 const char *attrs[] = { "supportedExtension", NULL };
1844 return smbldap_check_root_dse(ld, attrs, extension);
1847 /*******************************************************************
1848 Check if LDAP-Server holds a given namingContext
1849 ********************************************************************/
1851 bool smbldap_has_naming_context(LDAP *ld, const char *naming_context)
1853 const char *attrs[] = { "namingContexts", NULL };
1854 return smbldap_check_root_dse(ld, attrs, naming_context);
1857 bool smbldap_set_creds(struct smbldap_state *ldap_state, bool anon, const char *dn, const char *secret)
1859 ldap_state->anonymous = anon;
1861 /* free any previously set credential */
1863 SAFE_FREE(ldap_state->bind_dn);
1864 ldap_state->bind_callback = NULL;
1865 ldap_state->bind_callback_data = NULL;
1867 if (ldap_state->bind_secret) {
1868 /* make sure secrets are zeroed out of memory */
1869 memset(ldap_state->bind_secret, '\0', strlen(ldap_state->bind_secret));
1870 SAFE_FREE(ldap_state->bind_secret);
1873 if ( ! anon) {
1874 ldap_state->bind_dn = SMB_STRDUP(dn);
1875 ldap_state->bind_secret = SMB_STRDUP(secret);
1878 return True;