summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/passdb/pdb_ldap.c148
1 files changed, 114 insertions, 34 deletions
diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c
index 45e71b7a14..581aa48b99 100644
--- a/source3/passdb/pdb_ldap.c
+++ b/source3/passdb/pdb_ldap.c
@@ -70,8 +70,14 @@ struct ldapsam_privates {
uint32 low_nua_rid;
uint32 high_nua_rid;
+
+ char *bind_dn;
+ char *bind_secret;
};
+
+static struct ldapsam_privates *static_ldap_state;
+
static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state);
/*******************************************************************
@@ -157,7 +163,7 @@ static BOOL ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP *
DEBUG(0, ("ldap_open_connection: cannot access LDAP when not root..\n"));
return False;
}
-
+
#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri));
@@ -252,43 +258,92 @@ static BOOL ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP *
/*******************************************************************
- Add a rebind function for authenticated referrals
+ a rebind function for authenticated referrals
+ This version takes a void* that we can shove useful stuff in :-)
******************************************************************/
-static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
- int *method, int freeit )
+static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
+ int *methodp, int freeit, void *arg)
{
- int rc;
- char *ldap_dn;
- char *ldap_secret;
+ struct ldapsam_privates *ldap_state = arg;
/** @TODO Should we be doing something to check what servers we rebind to?
Could we get a referral to a machine that we don't want to give our
username and password to? */
- if (freeit != 0)
- {
-
- if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
- {
- DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
- return LDAP_OPERATIONS_ERROR; /* No idea what to return */
- }
-
+ if (freeit) {
+ SAFE_FREE(*whop);
+ memset(*credp, '\0', strlen(*credp));
+ SAFE_FREE(*credp);
+ } else {
DEBUG(5,("ldap_connect_system: Rebinding as \"%s\"\n",
- ldap_dn));
-
- rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
-
- SAFE_FREE(ldap_dn);
- SAFE_FREE(ldap_secret);
+ ldap_state->bind_dn));
- return rc;
+ *whop = strdup(ldap_state->bind_dn);
+ if (!*whop) {
+ return LDAP_NO_MEMORY;
+ }
+ *credp = strdup(ldap_state->bind_secret);
+ if (!*credp) {
+ SAFE_FREE(*whop);
+ return LDAP_NO_MEMORY;
+ }
+ *methodp = LDAP_AUTH_SIMPLE;
}
return 0;
}
/*******************************************************************
+ a rebind function for authenticated referrals
+ This version takes a void* that we can shove useful stuff in :-)
+ and actually does the connection.
+******************************************************************/
+
+static int rebindproc_connect_with_state (LDAP *ldap_struct,
+ LDAP_CONST char *url,
+ ber_tag_t request,
+ ber_int_t msgid, void *arg)
+{
+ struct ldapsam_privates *ldap_state = arg;
+ int rc;
+ DEBUG(5,("ldap_connect_system: Rebinding as \"%s\"\n",
+ ldap_state->bind_dn));
+
+ /** @TODO Should we be doing something to check what servers we rebind to?
+ Could we get a referral to a machine that we don't want to give our
+ username and password to? */
+
+ rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
+
+ return rc;
+}
+
+/*******************************************************************
+ Add a rebind function for authenticated referrals
+******************************************************************/
+
+static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
+ int *method, int freeit )
+{
+ return rebindproc_with_state(ldap_struct, whop, credp,
+ method, freeit, static_ldap_state);
+
+}
+
+/*******************************************************************
+ a rebind function for authenticated referrals
+ this also does the connection, but no void*.
+******************************************************************/
+
+static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
+ ber_int_t msgid)
+{
+ return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid,
+ static_ldap_state);
+}
+
+
+/*******************************************************************
connect to the ldap server under system privilege.
******************************************************************/
static BOOL ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct)
@@ -297,6 +352,10 @@ static BOOL ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * l
char *ldap_dn;
char *ldap_secret;
+ /* The rebind proc needs this *HACK*. We are not multithreaded, so
+ this will work, but it's not nice. */
+ static_ldap_state = ldap_state;
+
/* get the password */
if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
{
@@ -304,24 +363,32 @@ static BOOL ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * l
return False;
}
+ ldap_state->bind_dn = ldap_dn;
+ ldap_state->bind_secret = ldap_secret;
+
/* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
(OpenLDAP) doesnt' seem to support it */
DEBUG(10,("ldap_connect_system: Binding to ldap server as \"%s\"\n",
ldap_dn));
-#if LDAP_SET_REBIND_PROC_ARGS == 3
- ldap_set_rebind_proc(ldap_struct, (LDAP_REBIND_PROC *)(&rebindproc), NULL);
-#elif LDAP_SET_REBIND_PROC_ARGS == 2
- ldap_set_rebind_proc(ldap_struct, (LDAP_REBIND_PROC *)(&rebindproc));
+#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+# if LDAP_SET_REBIND_PROC_ARGS == 2
+ ldap_set_rebind_proc(ldap_struct, &rebindproc_connect);
+# endif
+# if LDAP_SET_REBIND_PROC_ARGS == 3
+ ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);
+# endif
+#else
+# if LDAP_SET_REBIND_PROC_ARGS == 2
+ ldap_set_rebind_proc(ldap_struct, &rebindproc);
+# endif
+# if LDAP_SET_REBIND_PROC_ARGS == 3
+ ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);
+# endif
#endif
-
-
rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
- SAFE_FREE(ldap_dn);
- SAFE_FREE(ldap_secret);
-
if (rc != LDAP_SUCCESS)
{
DEBUG(0, ("Bind failed: %s\n", ldap_err2string(rc)));
@@ -761,18 +828,20 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
/* leave as default */
} else {
pdb_gethexpwd(temp, smblmpwd);
- memset((char *)temp, '\0', sizeof(temp));
+ memset((char *)temp, '\0', strlen(temp)+1);
if (!pdb_set_lanman_passwd(sampass, smblmpwd))
return False;
+ ZERO_STRUCT(smblmpwd);
}
if (!get_single_attribute (ldap_struct, entry, "ntPassword", temp)) {
/* leave as default */
} else {
pdb_gethexpwd(temp, smbntpwd);
- memset((char *)temp, '\0', sizeof(temp));
+ memset((char *)temp, '\0', strlen(temp)+1);
if (!pdb_set_nt_passwd(sampass, smbntpwd))
return False;
+ ZERO_STRUCT(smbntpwd);
}
if (!get_single_attribute (ldap_struct, entry, "acctFlags", temp)) {
@@ -1158,6 +1227,10 @@ static BOOL ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT * us
struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
BOOL ret = False;
+ /* The rebind proc needs this *HACK*. We are not multithreaded, so
+ this will work, but it's not nice. */
+ static_ldap_state = ldap_state;
+
while (!ret) {
if (!ldap_state->entry)
return False;
@@ -1535,6 +1608,13 @@ static void free_private_data(void **vp)
ldap_unbind((*ldap_state)->ldap_struct);
}
+ if ((*ldap_state)->bind_secret) {
+ memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
+ }
+
+ SAFE_FREE((*ldap_state)->bind_dn);
+ SAFE_FREE((*ldap_state)->bind_secret);
+
*ldap_state = NULL;
/* No need to free any further, as it is talloc()ed */