Updates for sane storage of ldap root DN passwords (tested, with upgrade
authorAndrew Bartlett <abartlet@samba.org>
Wed, 22 May 2002 09:02:16 +0000 (09:02 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 22 May 2002 09:02:16 +0000 (09:02 +0000)
from 2.2 format) and LDAP rebind support (untested, I don't have a setup
to match).

Andrew Bartlett
(This used to be commit 4f7ba78c9d50ac584497dcf1d78ce613112742d4)

source3/passdb/pdb_ldap.c
source3/passdb/secrets.c

index 46b464a588e96cf499f57ec4c1021b450c3749f6..55ce8bab369544f2165e8dfe8e2441503c5954b2 100644 (file)
@@ -77,36 +77,65 @@ static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_s
 /*******************************************************************
  find the ldap password
 ******************************************************************/
-static BOOL fetch_ldapsam_pw(char *dn, char* pw, int len)
+static BOOL fetch_ldapsam_pw(char **dn, char** pw)
 {
-       fstring key;
-       char *p;
-       void *data = NULL;
+       char *key = NULL;
        size_t size;
        
-       pstrcpy(key, dn);
-       for (p=key; *p; p++)
-               if (*p == ',') *p = '/';
+       *dn = smb_xstrdup(lp_ldap_admin_dn());
        
-       data=secrets_fetch(key, &size);
-       if (!size) {
-               DEBUG(0,("fetch_ldap_pw: no ldap secret retrieved!\n"));
-               return False;
+       if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
+               SAFE_FREE(*dn);
+               DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n"));
        }
        
-       if (size > len-1)
-       {
-               DEBUG(0,("fetch_ldap_pw: ldap secret is too long (%d > %d)!\n", size, len-1));
-               return False;
-       }
+       *pw=secrets_fetch(key, &size);
+       if (!size) {
+               /* Upgrade 2.2 style entry */
+               char *p;
+               char* old_style_key = strdup(*dn);
+               char *data;
+               fstring old_style_pw;
+               
+               if (!old_style_key) {
+                       DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n"));
+                       return False;
+               }
+
+               for (p=old_style_key; *p; p++)
+                       if (*p == ',') *p = '/';
+       
+               data=secrets_fetch(old_style_key, &size);
+               if (!size && size < sizeof(old_style_pw)) {
+                       DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
+                       SAFE_FREE(old_style_key);
+                       SAFE_FREE(*dn);
+                       return False;
+               }
+
+               strncpy(old_style_pw, data, size);
+               old_style_pw[size] = 0;
+
+               SAFE_FREE(data);
+
+               if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
+                       DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
+                       SAFE_FREE(old_style_key);
+                       SAFE_FREE(*dn);
+                       return False;                   
+               }
+               if (!secrets_delete(old_style_key)) {
+                       DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
+               }
 
-       memcpy(pw, data, size);
-       pw[size] = '\0';
+               SAFE_FREE(old_style_key);
+
+               *pw = smb_xstrdup(old_style_pw);                
+       }
        
        return True;
 }
 
-
 /*******************************************************************
  open a connection to the ldap server.
 ******************************************************************/
@@ -210,20 +239,57 @@ static BOOL ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP *
        return True;
 }
 
+
+/*******************************************************************
+ Add a rebind function for authenticated referrals
+******************************************************************/
+
+static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
+                      int *method, int freeit )
+{
+       int rc;
+       char *ldap_dn;
+       char *ldap_secret;
+       
+       /** @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 */
+               }
+               
+               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);
+
+               return rc;
+       }
+       return 0;
+}
+
 /*******************************************************************
  connect to the ldap server under system privilege.
 ******************************************************************/
 static BOOL ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct)
 {
        int rc;
-       static BOOL got_pw = False;
-       static pstring ldap_secret;
+       char *ldap_dn;
+       char *ldap_secret;
 
-       /* get the password if we don't have it already */
-       if (!got_pw && !(got_pw=fetch_ldapsam_pw(lp_ldap_admin_dn(), ldap_secret, sizeof(pstring)))) 
+       /* get the password */
+       if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
        {
-               DEBUG(0, ("ldap_connect_system: Failed to retrieve password for %s from secrets.tdb\n",
-                       lp_ldap_admin_dn()));
+               DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
                return False;
        }
 
@@ -231,16 +297,22 @@ static BOOL ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * l
           (OpenLDAP) doesnt' seem to support it */
           
        DEBUG(10,("ldap_connect_system: Binding to ldap server as \"%s\"\n",
-               lp_ldap_admin_dn()));
-               
-       if ((rc = ldap_simple_bind_s(ldap_struct, lp_ldap_admin_dn(), 
-               ldap_secret)) != LDAP_SUCCESS)
+               ldap_dn));
+       
+       ldap_set_rebind_proc(ldap_struct, (LDAP_REBIND_PROC *)(&rebindproc));   
+
+       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)));
                return False;
        }
        
-       DEBUG(2, ("ldap_connect_system: successful connection to the LDAP server\n"));
+       DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n"));
        return True;
 }
 
index 43fc3604a0cd72f9f50254cbc410f81120256732..38e78df9d7baab21abe6bc7e7b8bfc0a07420f93 100644 (file)
@@ -52,7 +52,7 @@ BOOL secrets_init(void)
 /* read a entry from the secrets database - the caller must free the result
    if size is non-null then the size of the entry is put in there
  */
-void *secrets_fetch(char *key, size_t *size)
+void *secrets_fetch(const char *key, size_t *size)
 {
        TDB_DATA kbuf, dbuf;
        secrets_init();
@@ -68,7 +68,7 @@ void *secrets_fetch(char *key, size_t *size)
 
 /* store a secrets entry 
  */
-BOOL secrets_store(char *key, void *data, size_t size)
+BOOL secrets_store(const char *key, void *data, size_t size)
 {
        TDB_DATA kbuf, dbuf;
        secrets_init();
@@ -84,7 +84,7 @@ BOOL secrets_store(char *key, void *data, size_t size)
 
 /* delete a secets database entry
  */
-BOOL secrets_delete(char *key)
+BOOL const secrets_delete(const char *key)
 {
        TDB_DATA kbuf;
        secrets_init();
@@ -136,7 +136,7 @@ BOOL secrets_fetch_domain_sid(char *domain, DOM_SID *sid)
  *
  * @return stored password's key
  **/
-char *trust_keystr(char *domain)
+const char *trust_keystr(const char *domain)
 {
        static fstring keystr;
 
@@ -154,7 +154,7 @@ char *trust_keystr(char *domain)
  *
  * @return stored password's key
  **/
-char *trustdom_keystr(char *domain)
+char *trustdom_keystr(const char *domain)
 {
        static char* keystr;
 
@@ -325,7 +325,7 @@ char *secrets_fetch_machine_password(void)
  Routine to delete the machine trust account password file for a domain.
 ************************************************************************/
 
-BOOL trust_password_delete(char *domain)
+BOOL trust_password_delete(const char *domain)
 {
        return secrets_delete(trust_keystr(domain));
 }
@@ -333,7 +333,7 @@ BOOL trust_password_delete(char *domain)
 /************************************************************************
  Routine to delete the password for trusted domain
 ************************************************************************/
-BOOL trusted_domain_password_delete(char *domain)
+BOOL trusted_domain_password_delete(const char *domain)
 {
        return secrets_delete(trustdom_keystr(domain));
 }
@@ -370,16 +370,20 @@ void reset_globals_after_fork(void)
        generate_random_buffer( &dummy, 1, True);
 }
 
-BOOL secrets_store_ldap_pw(char* dn, char* pw)
+BOOL secrets_store_ldap_pw(const char* dn, char* pw)
 {
-       fstring key;
-       char *p;
+       char *key = NULL;
+       BOOL ret;
        
-       pstrcpy(key, dn);
-       for (p=key; *p; p++)
-               if (*p == ',') *p = '/';
+       if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, dn) < 0) {
+               DEBUG(0, ("secrets_store_ldap_pw: asprintf failed!\n"));
+               return False;
+       }
+               
+       ret = secrets_store(key, pw, strlen(pw)+1);
        
-       return secrets_store(key, pw, strlen(pw));
+       SAFE_FREE(key);
+       return ret;
 }