[PATCH] LDAP naming violation

Yohann Fourteau yohann.fourteau at aitb.org
Tue Feb 24 10:16:11 GMT 2004


Hi,

I've done a patch to solve the probleme of naming violation in pdb_ldap.c when
deleting/changing naming attribut (uid in most cases).
Without that patch, in a PDC role, you can't change the name of a machine, nor
delete an account (with opendldap > 2.1.x and X500 compliant server ).


Diff based off of Samba-3.0.2:
----------------------------------8<---------------------
--- a/smbldap.c	Thu Feb 19 15:52:00 2004
+++ b/smbldap.c	Thu Feb 19 15:52:13 2004
@@ -970,22 +970,166 @@
 	int 		rc = LDAP_SERVER_DOWN;
 	int 		attempts = 0;
 	char           *utf8_dn;
+	/* Yohann */
+	BOOL		do_rename = False;
+	BOOL		naming_deleted = False;
+	BOOL		naming_more_value = False;
+	int		i,j,k,new_rdn_len,new_dn_len;
+	char	       *rdn_attribut;
+	char 	      **rdn;
+	char	       *new_rdn;
+	char	       *new_dn;
+	char	       *utf8_new_rdn;
+	char	       *utf8_new_dn;
+	char	       *new_rdn_value;
+	char	       *rdn_value;
+	
+	rdn = ldap_explode_dn(dn,0);
+	rdn_attribut = strdup(strtok(rdn[0],"="));
+	rdn_value = strdup(strtok(NULL,","));
+	DEBUG(5,("smbldap_modify: dn => [%s]\n", dn ));
+	
+        for (i = 0; attrs[i] != NULL; i++) {
+		if ( ( attrs[i]->mod_op == LDAP_MOD_DELETE )
+			&&  strequal(attrs[i]->mod_type,rdn_attribut) ) {
+			for (j=0;attrs[i]->mod_values[j] != NULL; j++) {
+				if (strequal(attrs[i]->mod_values[j],rdn_value)) {
+					SAFE_FREE(attrs[i]->mod_values[j]);
+					attrs[i]->mod_values[j]=attrs[i]->mod_values[j+1];
+					for (k=j+1;attrs[i]->mod_values[k] != NULL; k++)
+						attrs[i]->mod_values[k]=attrs[i]->mod_values[k+1];
+					naming_deleted = True;
+				} else {
+					naming_more_value = True;
+				}
+			}
+
+			if (!naming_more_value) {
+				SAFE_FREE(attrs[i]->mod_type);
+				for (j=0;attrs[i]->mod_values[j] != NULL; j++)
+					SAFE_FREE(attrs[i]->mod_values[j]);
+				SAFE_FREE(attrs[i]->mod_values);
+				SAFE_FREE(attrs[i]); 
+				attrs[i]=attrs[i+1];
+				for (j=i+1; attrs[j] != NULL; j++) {
+					attrs[j]=attrs[j+1];
+				}
+			}
+		}
+
+		if ( ( attrs[i] != NULL ) 
+		      && ( ( attrs[i]->mod_op == LDAP_MOD_ADD && naming_deleted ) ||
attrs[i]->mod_op == LDAP_MOD_REPLACE )
+		      && ( attrs[i]->mod_values[0] != NULL)
+		      && ( strequal(attrs[i]->mod_type,rdn_attribut) ) ) {
+			do_rename = True;
+			new_rdn_value = strdup(attrs[i]->mod_values[0]);
+			if (!new_rdn_value) {
+				SAFE_FREE(rdn_attribut);
+				return LDAP_NO_MEMORY;
+			}
+			
+			new_rdn_len= strlen(rdn_attribut) + strlen(new_rdn_value) + 2;
+			new_rdn = malloc( new_rdn_len );
+			if (!new_rdn) {
+				SAFE_FREE(rdn_attribut);
+				SAFE_FREE(new_rdn_value);
+				return LDAP_NO_MEMORY;
+			}
+
+			new_rdn[0] = '\0';
+			safe_strcat( new_rdn, rdn_attribut, new_rdn_len);
+			safe_strcat( new_rdn, "=" , new_rdn_len);
+			safe_strcat( new_rdn, new_rdn_value, new_rdn_len);
+			if (push_utf8_allocate(&utf8_new_rdn, new_rdn) == (size_t)-1) {
+				SAFE_FREE(rdn_attribut);
+				SAFE_FREE(new_rdn_value);
+				SAFE_FREE(new_rdn);
+				return LDAP_NO_MEMORY;
+			}
+			
+			new_dn_len=strlen(new_rdn);
+			for(j=1; rdn[j] != NULL; j++) {
+				new_dn_len += strlen(rdn[j]) + 1;
+			}
+			new_dn=malloc(new_dn_len + 1);
+			if (!new_dn) {
+				SAFE_FREE(rdn_attribut);
+				SAFE_FREE(new_rdn_value);
+				SAFE_FREE(new_rdn);
+				SAFE_FREE(utf8_new_rdn);
+				return LDAP_NO_MEMORY;
+			}
+			new_dn[0]='\0';
+			safe_strcat(new_dn,new_rdn,new_dn_len);
+			for(j=1; rdn[j] != NULL; j++) {
+				safe_strcat(new_dn,",",new_dn_len);
+				safe_strcat(new_dn,rdn[j],new_dn_len);
+			}
+			
+			if (push_utf8_allocate(&utf8_new_dn, new_dn) == (size_t)-1) {
+				SAFE_FREE(rdn_attribut);
+				SAFE_FREE(new_rdn_value);
+				SAFE_FREE(new_rdn);
+				SAFE_FREE(new_dn);
+				SAFE_FREE(utf8_new_rdn);
+				return LDAP_NO_MEMORY;
+			}
+			
+			DEBUG(5,("smbldap_modify: newdn => [%s]\n", new_rdn ));
+			SAFE_FREE(new_rdn_value);
+			SAFE_FREE(new_rdn);
+			SAFE_FREE(new_dn);
+			if (attrs[i]->mod_op != LDAP_MOD_REPLACE) {
+				if (attrs[i]->mod_values[1] == NULL) {
+					SAFE_FREE(attrs[i]->mod_type);
+					for (j=0;attrs[i]->mod_values[j] != NULL; j++)
+						SAFE_FREE(attrs[i]->mod_values[j]);
+					SAFE_FREE(attrs[i]->mod_values);
+					SAFE_FREE(attrs[i]); 
+					attrs[i]=attrs[i+1];
+					for (j=i+1; attrs[j] != NULL; j++) {
+						attrs[j]=attrs[j+1];
+					}
+				} else {
+					SAFE_FREE(attrs[i]->mod_values[0]);
+					attrs[i]->mod_values[0]=attrs[i]->mod_values[1];
+					for (j=1;attrs[i]->mod_values[j] != NULL; j++)
+						attrs[i]->mod_values[j]=attrs[i]->mod_values[j+1];
+				}
+			}
+			continue;
+		}
+	}
 
+	SAFE_FREE(rdn_attribut);
+	SAFE_FREE(rdn_value);
+	ldap_value_free(rdn);
+	
 	SMB_ASSERT(ldap_state);
 
 	DEBUG(5,("smbldap_modify: dn => [%s]\n", dn ));
 
 	if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
+		SAFE_FREE(utf8_new_rdn);
+		SAFE_FREE(utf8_new_dn);
 		return LDAP_NO_MEMORY;
 	}
+        
 
 	while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) {
 		
 		if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
 			continue;
 		
-		rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs);
+		if (do_rename && (rc = ldap_modrdn2_s(ldap_state->ldap_struct, utf8_dn,
utf8_new_rdn, 1)) != LDAP_SUCCESS )
+			continue;
+		
+		if (do_rename)
+			rc = ldap_modify_s(ldap_state->ldap_struct, utf8_new_dn, attrs);
+		else
+			rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs);
 	}
+
 	
 	if (rc == LDAP_SERVER_DOWN) {
 		DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
@@ -994,6 +1138,11 @@
 	
 	ldap_state->last_use = time(NULL);
 
+
+	if (do_rename) {
+		SAFE_FREE(utf8_new_rdn);
+		SAFE_FREE(utf8_new_dn);
+	}
 	SAFE_FREE(utf8_dn);
 	return rc;
 }

----------------------------->8---------------------

Cdt,
-- 
Yohann F.


More information about the samba-technical mailing list