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