A measure for collision of winbind mapping

kawasa_r at itg.hitachi.co.jp kawasa_r at itg.hitachi.co.jp
Fri May 7 14:33:56 GMT 2004


When winbindd is used with its idmap backend is set to LDAP, if registration 
management to the LDAP server is executed concurrently from plural winbind 
daemons, successive processes fail to obtain id.

If plural daemons try to register the uid/gid of the same user simultaneously,
successive daemons failed by "LDAP_ALREADY_EXISTS". In this case, the id itself 
is successfully registered.
However, the error handling management returns immediately after the detection, 
so they fail to obtain id.

If the reason of failure is "LDAP_ALREADY_EXISTS", assume that the registration
is duplicated and reissue smbldap_search() to get the registered mapping. 
 
Index: samba-302/source/sam/idmap_ldap.c
===================================================================
RCS file: /cvs/samba-302/source/sam/idmap_ldap.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- samba-302/source/sam/idmap_ldap.c	30 Mar 2004 07:28:00 -0000	1.3
+++ samba-302/source/sam/idmap_ldap.c	30 Mar 2004 09:47:51 -0000	1.4
@@ -45,6 +45,7 @@
 #define LDAP_MAX_ALLOC_ID 2
 BOOL ldap_allocate_id_error = False;
 BOOL ldap_alloc_collision = False;
+BOOL ldap_mapping_collision = False;
 
 
 /***********************************************************************
@@ -105,6 +106,9 @@
 			 sid_string, (unsigned long)((id_type & ID_USERID) ? id.uid : id.gid), type));
 		DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n", 
 			ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
+		if (rc == LDAP_ALREADY_EXISTS) {
+			ldap_mapping_collision = True;
+		}
 		return NT_STATUS_UNSUCCESSFUL;
 	}
 		
@@ -570,6 +574,7 @@
 
 	ldap_allocate_id_error = False;
 	ldap_alloc_collision = False;
+	ldap_mapping_collision = False;
 
 	sid_to_string(sid_str, sid);
 
@@ -619,7 +624,6 @@
 
 		DEBUG(8,("ldap_get_id_from_sid: Allocating new id\n"));
 		
-		ldap_allocate_id_error = False;
 		for (i = 0; i < LDAP_MAX_ALLOC_ID; i++) {
 			ret = ldap_allocate_id(id, *id_type);
 			if ( NT_STATUS_IS_OK(ret) ) {
@@ -641,9 +645,26 @@
 	
 		ret = ldap_set_mapping(sid, *id, *id_type);
 
-		/* all done */
+		if ( ldap_mapping_collision ) {
+			rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, 
+				filter, attr_list, 0, &result);
+			if (rc != LDAP_SUCCESS) {
+				DEBUG(3,("ldap_get_id_from_sid: Failure looking up idmap entry (%s)\n",
+					ldap_err2string(rc) ));
+				goto out;
+			}
+			/* check for the number of entries returned */
+			count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
+			if ( count > 1 ) {
+				DEBUG(0, ("ldap_get_id_from_sid: (2nd) search %s returned [%d] entries!\n",
+					filter, count));
+				goto out;
+			}
+		} else {
+			/* all done */
 
-		goto out;
+			goto out;
+		}
 	}
 
 	DEBUG(10,("ldap_get_id_from_sid: success\n"));



More information about the samba-technical mailing list