diff options
-rw-r--r-- | source3/passdb/pdb_ldap.c | 148 |
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 */ |