A RID allocator and its consequences

Volker.Lendecke at SerNet.DE Volker.Lendecke at SerNet.DE
Thu Sep 26 21:04:00 GMT 2002


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi!

This is a surprisingly little (compiled, but not tested) patch that
mainly should do the following:

Implement a rid allocator in secrets.tdb. This might not be the right
place to do it, but as we are one-domain with passdb, RID allocation
is a global thing.

Second, in get_group_from_gid it initializes a new group mapping as an
alias on the fly. So if the gid exists it should basically not fail
anymore.

Third, as a consequence of get_group_from_gid, most of the calls to
pdb_gid_to_group_rid are gone. There's two left in passdb.c which I
don't really understand. Maybe it's too late now. The remaining one is
in pdb_nisplus which I will not touch for now.

This is only an interim step I think, the next step would be to remove
the group_sid from SAM_ACCOUNT completely, as we can now always get a
SID for a gid.

Volker

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: Key-ID ADE377D8, Fingerprint available: phone +49 551 3700000

iD8DBQE9k3PwZeeQha3jd9gRAs4qAJ49Ua2+Qx+T7Zvd8mNdCAXunOcv7ACeOCQe
i2OZ34EVYmXfLS8hzTUoidc=
=BVZQ
-----END PGP SIGNATURE-----

diff -ur samba/cvs/head/samba/source/Makefile.in head/source/Makefile.in
--- samba/cvs/head/samba/source/Makefile.in	Thu Sep 26 14:13:29 2002
+++ head/source/Makefile.in	Thu Sep 26 17:37:42 2002
@@ -429,8 +429,9 @@
                  $(UBIQX_OBJ) $(LIB_OBJ)
 
 SMBCACLS_OBJ = utils/smbcacls.o $(LOCKING_OBJ) $(LIBSMB_OBJ) $(PARAM_OBJ) \
-                 $(UBIQX_OBJ) $(LIB_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_GET_SET_OBJ) \
-		 $(LIBMSRPC_OBJ) 
+                 $(UBIQX_OBJ) $(LIB_OBJ) $(RPC_PARSE_OBJ) $(SECRETS_OBJ) \
+		 $(LIBMSRPC_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) 
+
 
 TALLOCTORT_OBJ = lib/talloctort.o  $(LIB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ)
 
@@ -494,7 +495,7 @@
 		nsswitch/winbindd_dual.o
 
 WINBINDD_OBJ = \
-		$(WINBINDD_OBJ1) $(PASSDB_GET_SET_OBJ) \
+		$(WINBINDD_OBJ1) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
 		$(LIBNMB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
 		$(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) \
 		$(PROFILE_OBJ) $(UNIGRP_OBJ) \
diff -ur samba/cvs/head/samba/source/groupdb/mapping.c head/source/groupdb/mapping.c
--- samba/cvs/head/samba/source/groupdb/mapping.c	Mon Sep 23 18:34:17 2002
+++ head/source/groupdb/mapping.c	Thu Sep 26 22:39:00 2002
@@ -1040,14 +1040,13 @@
 	return True;
 }
 
-
-
 /****************************************************************************
 Returns a GROUP_MAP struct based on the gid.
 ****************************************************************************/
 BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map, BOOL with_priv)
 {
 	struct group *grp;
+	uint32 rid;
 
 	if(!init_group_mapping()) {
 		DEBUG(0,("failed to initialize group mapping"));
@@ -1057,24 +1056,46 @@
 	if ( (grp=getgrgid(gid)) == NULL)
 		return False;
 
-	/*
-	 * make a group map from scratch if doesn't exist.
-	 */
-	if (!get_group_map_from_gid(gid, map, with_priv)) {
-		map->gid=gid;
-		map->sid_name_use=SID_NAME_ALIAS;
-		map->systemaccount=PR_ACCESS_FROM_NETWORK;
-		init_privilege(&map->priv_set);
-
-		/* interim solution until we have a last RID allocated */
+	if (get_group_map_from_gid(gid, map, with_priv))
+		return True;
 
-		sid_copy(&map->sid, get_global_sam_sid());
-		sid_append_rid(&map->sid, pdb_gid_to_group_rid(gid));
+	/* There's no mapping, try to create one on the fly. */
 
-		fstrcpy(map->nt_name, grp->gr_name);
-		fstrcpy(map->comment, "Local Unix Group");
+	if ((rid = secrets_allocate_rid()) != 0) {
+		DOM_SID sid;
+		fstring string_sid;
+		PRIVILEGE_SET priv_set;
+
+		sid_copy(&sid, get_global_sam_sid());
+		sid_append_rid(&sid, rid);
+		sid_to_string(string_sid, &sid);
+		init_privilege(&priv_set);
+
+		if (add_initial_entry(gid, string_sid, SID_NAME_ALIAS,
+				      grp->gr_name, "Local Unix Group",
+				      priv_set, PR_ACCESS_FROM_NETWORK)) {
+			if (get_group_map_from_gid(gid, map, with_priv))
+				return True;
+		}
+		DEBUG(0, ("Weird! Did not find the group map just created\n"));
 	}
-	
+
+	/* Fake a group. This is just a bad hack, as
+	   the RID will clash with a mapped group. */
+
+	DEBUG(0, ("Faking a group mapping\n"));
+
+	map->gid=gid;
+	map->sid_name_use=SID_NAME_ALIAS;
+	map->systemaccount=PR_ACCESS_FROM_NETWORK;
+	init_privilege(&map->priv_set);
+
+	sid_copy(&map->sid, get_global_sam_sid());
+	sid_append_rid(&map->sid, pdb_gid_to_group_rid(gid));
+
+	fstrcpy(map->nt_name, grp->gr_name);
+	fstrcpy(map->comment, "Local Unix Group");
+
 	return True;
 }
 
diff -ur samba/cvs/head/samba/source/include/secrets.h head/source/include/secrets.h
--- samba/cvs/head/samba/source/include/secrets.h	Tue Jul 30 19:23:06 2002
+++ head/source/include/secrets.h	Thu Sep 26 20:37:10 2002
@@ -35,6 +35,9 @@
 #define SECRETS_DOMAIN_SID    "SECRETS/SID"
 #define SECRETS_SAM_SID       "SAM/SID"
 
+/* The next RID for a domain */
+#define SECRETS_NEXTRID       "SECRETS/NEXTRID"
+
 /* The domain GUID and server GUID (NOT the same) are also not secret */
 #define SECRETS_DOMAIN_GUID   "SECRETS/DOMGUID"
 #define SECRETS_SERVER_GUID   "SECRETS/GUID"
diff -ur samba/cvs/head/samba/source/passdb/passdb.c head/source/passdb/passdb.c
--- samba/cvs/head/samba/source/passdb/passdb.c	Thu Sep 26 14:13:30 2002
+++ head/source/passdb/passdb.c	Thu Sep 26 22:22:59 2002
@@ -207,25 +207,27 @@
 			return NT_STATUS_UNSUCCESSFUL;
 		}
 	} else {
+		uint32 rid = secrets_allocate_rid();
 
-		if (!pdb_set_user_sid_from_rid(sam_account, 
-					       fallback_pdb_uid_to_user_rid(pwd->pw_uid))) {
+		if (rid == 0) {
+			DEBUG(0,("Can't allocate a RID\n"));
+			return NT_STATUS_UNSUCCESSFUL;
+		}
+
+		if (!pdb_set_user_sid_from_rid(sam_account, rid)) {
 			DEBUG(0,("Can't set User SID from RID!\n"));
 			return NT_STATUS_INVALID_PARAMETER;
 		}
 		
-		/* call the mapping code here */
-		if(get_group_map_from_gid(pwd->pw_gid, &map, MAPPING_WITHOUT_PRIV)) {
-			if (!pdb_set_group_sid(sam_account,&map.sid)){
-				DEBUG(0,("Can't set Group SID!\n"));
-				return NT_STATUS_INVALID_PARAMETER;
-			}
-		} 
-		else {
-			if (!pdb_set_group_sid_from_rid(sam_account,pdb_gid_to_group_rid(pwd->pw_gid))) {
-				DEBUG(0,("Can't set Group SID\n"));
-				return NT_STATUS_INVALID_PARAMETER;
-			}
+		if(!get_group_from_gid(pwd->pw_gid, &map,
+				       MAPPING_WITHOUT_PRIV)) {
+			DEBUG(0,("Can't get Group SID\n"));
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+
+		if (!pdb_set_group_sid(sam_account,&map.sid)){
+			DEBUG(0,("Can't set Group SID!\n"));
+			return NT_STATUS_INVALID_PARAMETER;
 		}
 	}
 
@@ -898,7 +900,7 @@
 
 	sid_copy(psid, get_global_sam_sid());
 	
-	if (get_group_map_from_gid(gid, &map, MAPPING_WITHOUT_PRIV)) {
+	if (get_group_from_gid(gid, &map, MAPPING_WITHOUT_PRIV)) {
 		sid_copy(psid, &map.sid);
 	} 
 	else {
diff -ur samba/cvs/head/samba/source/passdb/pdb_get_set.c head/source/passdb/pdb_get_set.c
--- samba/cvs/head/samba/source/passdb/pdb_get_set.c	Thu Sep 26 14:13:30 2002
+++ head/source/passdb/pdb_get_set.c	Thu Sep 26 22:22:56 2002
@@ -166,11 +166,24 @@
 
 const DOM_SID *pdb_get_group_sid(const SAM_ACCOUNT *sampass)
 {
-	if (sampass)
-		return &sampass->private.group_sid;
-	else	
+	struct passwd *pwd;
+	static GROUP_MAP map;
+	static DOM_SID sid;
+
+	if (!sampass)
 		return (NULL);
-}	
+
+	/* If the user's unix primary group is mapped to a NT SID, use
+           that. Otherwise use the pdb-stored SID. Unix is still boss
+           here :-) */
+
+	if ( ((pwd = getpwuid(sampass->private.uid)) != NULL)
+	     && get_group_from_gid(pwd->pw_gid, &map, False))
+		return &map.sid;
+
+	DEBUG(0, ("SAM inconsistent: uid or gid disappeard\n"));
+	return &sampass->private.group_sid;
+}
 
 /**
  * Get flags showing what is initalised in the SAM_ACCOUNT
diff -ur samba/cvs/head/samba/source/passdb/pdb_ldap.c head/source/passdb/pdb_ldap.c
--- samba/cvs/head/samba/source/passdb/pdb_ldap.c	Thu Sep 26 14:13:30 2002
+++ head/source/passdb/pdb_ldap.c	Thu Sep 26 22:57:25 2002
@@ -506,11 +506,6 @@
 	snprintf(filter, sizeof(filter) - 1, "rid=%i", rid);
 	rc = ldapsam_search_one_user(ldap_state, ldap_struct, filter, result);
 	
-	if (rc != LDAP_SUCCESS)
-		rc = ldapsam_search_one_user_by_uid(ldap_state, ldap_struct, 
-						    fallback_pdb_user_rid_to_uid(rid), 
-						    result);
-
 	return rc;
 }
 
@@ -719,13 +714,12 @@
 
 		if (group_rid == 0) {
 			GROUP_MAP map;
-			/* call the mapping code here */
-			if(get_group_map_from_gid(gid, &map, MAPPING_WITHOUT_PRIV)) {
-				pdb_set_group_sid(sampass, &map.sid);
-			} 
-			else {
-				pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid));
+			if(!get_group_from_gid(gid, &map,
+					       MAPPING_WITHOUT_PRIV)) {
+				DEBUG(2, ("Group [%d] does not exist\n", gid));
+				return False;
 			}
+			pdb_set_group_sid(sampass, &map.sid);
 		}
 	}
 
@@ -939,14 +933,23 @@
 	slprintf(temp, sizeof(temp) - 1, "%i", rid);
 	make_a_mod(mods, ldap_op, "rid", temp);
 
+	rid = 0;
+
 	if ( pdb_get_group_rid(sampass) ) {
 		rid = pdb_get_group_rid(sampass);
 	} else if (IS_SAM_SET(sampass, FLAG_SAM_GID)) {
-		rid = pdb_gid_to_group_rid(pdb_get_gid(sampass));
+		GROUP_MAP map;
+
+		if (get_group_from_gid(pdb_get_gid(sampass),
+				       &map, MAPPING_WITHOUT_PRIV))
+			sid_peek_rid(&map.sid, &rid);
 	} else if (ldap_state->permit_non_unix_accounts) {
 		rid = DOMAIN_GROUP_RID_USERS;
-	} else {
-		DEBUG(0, ("NO group RID specified on account %s, cannot store!\n", pdb_get_username(sampass)));
+	}
+
+	if (rid == 0) {
+		DEBUG(0, ("NO group RID specified on account %s, "
+			  "cannot store!\n", pdb_get_username(sampass)));
 		return False;
 	}
 
diff -ur samba/cvs/head/samba/source/passdb/pdb_nisplus.c head/source/passdb/pdb_nisplus.c
--- samba/cvs/head/samba/source/passdb/pdb_nisplus.c	Thu Sep 26 14:13:30 2002
+++ head/source/passdb/pdb_nisplus.c	Thu Sep 26 22:24:35 2002
@@ -1078,7 +1078,7 @@
 		rid = pdb_get_group_rid (sampass);
 
 		if (rid == 0) {
-			if (get_group_map_from_gid
+			if (get_group_from_gid
 			    (pdb_get_gid (sampass), &map,
 			     MAPPING_WITHOUT_PRIV)) {
 				if (!sid_peek_check_rid
diff -ur samba/cvs/head/samba/source/passdb/secrets.c head/source/passdb/secrets.c
--- samba/cvs/head/samba/source/passdb/secrets.c	Wed Sep 18 08:19:02 2002
+++ head/source/passdb/secrets.c	Thu Sep 26 20:50:15 2002
@@ -104,7 +104,7 @@
 	return secrets_store(key, sid, sizeof(DOM_SID));
 }
 
-BOOL secrets_fetch_domain_sid(char *domain, DOM_SID *sid)
+BOOL secrets_fetch_domain_sid(const char *domain, DOM_SID *sid)
 {
 	DOM_SID *dyn_sid;
 	fstring key;
@@ -644,4 +644,71 @@
 
 	tdb_chainunlock(tdb, key);
 	DEBUG(10,("secrets_named_mutex: released mutex for %s\n", name ));
+}
+
+/*
+  Store an initial 'next rid' to secrets.tdb.
+*/
+BOOL secrets_init_nextrid(uint32 rid)
+{
+	fstring key;
+	fstring new_rid;
+
+	if (!secrets_init())
+		return False;
+
+	slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_NEXTRID, lp_workgroup());
+
+	if (tdb_lock_bystring(tdb, key) != 0)
+		return False;
+
+	slprintf(new_rid, sizeof(new_rid), "%d", rid);
+	secrets_store(key, new_rid, strlen(new_rid)+1);
+	tdb_unlock_bystring(tdb, key);
+
+	return True;
+}
+
+/*
+  Allocate a new RID
+*/
+uint32 secrets_allocate_rid(void)
+{
+	fstring key;
+	char *rid_string;
+	fstring new_rid;
+	uint32 rid;
+
+	if (!secrets_init())
+		return 0;
+
+	slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_NEXTRID, lp_workgroup());
+
+	if (tdb_lock_bystring(tdb, key) != 0)
+		return 0;
+
+	if ((rid_string = secrets_fetch(key, NULL)) == NULL) {
+		tdb_unlock_bystring(tdb, key);
+		DEBUG(0, ("Can't allocate a RID for Domain %s: "
+			  "You should run 'net initrid'\n",
+			  lp_workgroup()));
+		return 0;
+	}
+
+	rid = atoi(rid_string);
+
+	if (rid == 0) {
+		tdb_unlock_bystring(tdb, key);
+		DEBUG(0, ("Ran out of RIDs for Domain %s -- Boom!\n",
+			  lp_workgroup()));
+		return 0;
+	}
+
+	SAFE_FREE(rid_string);
+
+	slprintf(new_rid, sizeof(new_rid), "%d", rid+1);
+	secrets_store(key, new_rid, strlen(new_rid)+1);
+	tdb_unlock_bystring(tdb, key);
+
+	return rid;
 }
diff -ur samba/cvs/head/samba/source/rpc_server/srv_samr_nt.c head/source/rpc_server/srv_samr_nt.c
--- samba/cvs/head/samba/source/rpc_server/srv_samr_nt.c	Thu Sep 26 17:36:48 2002
+++ head/source/rpc_server/srv_samr_nt.c	Thu Sep 26 22:55:36 2002
@@ -3899,7 +3899,8 @@
 	if ((grp=getgrgid(gid)) == NULL)
 		return NT_STATUS_ACCESS_DENIED;
 
-	r_u->rid=pdb_gid_to_group_rid(grp->gr_gid);
+	if ((r_u->rid=secrets_allocate_rid()) == 0)
+		return NT_STATUS_ACCESS_DENIED;
 
 	/* add the group to the mapping table */
 	sid_copy(&info_sid, get_global_sam_sid());
@@ -3964,7 +3965,8 @@
 	if ((grp=getgrgid(gid)) == NULL)
 		return NT_STATUS_ACCESS_DENIED;
 
-	r_u->rid=pdb_gid_to_group_rid(grp->gr_gid);
+	if ((r_u->rid=secrets_allocate_rid()) == 0)
+		return NT_STATUS_ACCESS_DENIED;
 
 	sid_copy(&info_sid, get_global_sam_sid());
 	sid_append_rid(&info_sid, r_u->rid);
diff -ur samba/cvs/head/samba/source/utils/net.c head/source/utils/net.c
--- samba/cvs/head/samba/source/utils/net.c	Mon Sep 23 19:51:22 2002
+++ head/source/utils/net.c	Thu Sep 26 20:42:51 2002
@@ -397,6 +397,106 @@
 	return 0;
 }
 
+static uint32 get_maxrid(void)
+{
+	SAM_ACCOUNT *pwd = NULL;
+	uint32 max_rid = 0;
+	GROUP_MAP *map = NULL;
+	int num_entries = 0;
+	int i;
+
+	if (!pdb_setsampwent(False)) {
+		DEBUG(0, ("load_sampwd_entries: Unable to open passdb.\n"));
+		return 0;
+	}
+
+	for (; (NT_STATUS_IS_OK(pdb_init_sam(&pwd))) 
+		     && pdb_getsampwent(pwd) == True; pwd=NULL) {
+		uint32 rid;
+
+		if (!sid_peek_rid(pdb_get_user_sid(pwd), &rid)) {
+			DEBUG(0, ("can't get RID for user '%s'\n",
+				  pdb_get_username(pwd)));
+			pdb_free_sam(&pwd);
+			continue;
+		}
+
+		if (rid > max_rid)
+			max_rid = rid;
+
+		d_printf("%d is user '%s'\n", rid, pdb_get_username(pwd));
+		pdb_free_sam(&pwd);
+	}
+
+	pdb_endsampwent();
+	pdb_free_sam(&pwd);
+
+	if (!enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries,
+				ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV))
+		return max_rid;
+
+	for (i = 0; i < num_entries; i++) {
+		uint32 rid;
+
+		if (!sid_peek_check_rid(get_global_sam_sid(), &map[i].sid,
+					&rid)) {
+			DEBUG(3, ("skipping map for group '%s', SID %s\n",
+				  map[i].nt_name,
+				  sid_string_static(&map[i].sid)));
+			continue;
+		}
+		d_printf("%d is group '%s'\n", rid, map[i].nt_name);
+
+		if (rid > max_rid)
+			max_rid = rid;
+	}
+
+	SAFE_FREE(map);
+
+	return max_rid;
+}
+
+static int net_initrid(int argc, const char **argv)
+{
+	uint32 rid;
+
+	if (argc != 0) {
+	        DEBUG(0, ("usage: net initrid\n"));
+		return 1;
+	}
+
+	if ((rid = get_maxrid()) == 0) {
+		DEBUG(0, ("can't get current maximum rid\n"));
+		return 1;
+	}
+
+	if (!secrets_init_nextrid(rid+1)) {
+		DEBUG(0, ("can't store new 'next rid' in secrets.tdb\n"));
+		return 1;
+	}
+
+	return 0;
+}
+
+static int net_allocrid(int argc, const char **argv)
+{
+	uint32 rid;
+
+	if (argc != 0) {
+		DEBUG(0, ("usage: net allocrid\n"));
+		return 1;
+	}
+
+	if ((rid = secrets_allocate_rid()) == 0) {
+		DEBUG(0, ("Could not allocate a RID\n"));
+		return 1;
+	}
+
+	d_printf("Next RID to use: %d\n", rid);
+	return 0;
+}
+	
+
 /* main function table */
 static struct functable net_func[] = {
 	{"RPC", net_rpc},
@@ -424,6 +524,8 @@
 	{"GETLOCALSID", net_getlocalsid},
 	{"SETLOCALSID", net_setlocalsid},
 	{"GETDOMAINSID", net_getdomainsid},
+	{"INITRID", net_initrid},
+	{"ALLOCRID", net_allocrid},
 
 	{"HELP", net_help},
 	{NULL, NULL}
diff -ur samba/cvs/head/samba/source/utils/net_rpc_samsync.c head/source/utils/net_rpc_samsync.c
--- samba/cvs/head/samba/source/utils/net_rpc_samsync.c	Tue Sep 24 16:12:07 2002
+++ head/source/utils/net_rpc_samsync.c	Thu Sep 26 22:41:28 2002
@@ -4,6 +4,7 @@
 
    Copyright (C) Andrew Tridgell 2002
    Copyright (C) Tim Potter 2001,2002
+   Modified by Volker Lendecke 2002
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff -ur samba/cvs/head/samba/source/utils/smbgroupedit.c head/source/utils/smbgroupedit.c
--- samba/cvs/head/samba/source/utils/smbgroupedit.c	Thu Sep 26 17:36:48 2002
+++ head/source/utils/smbgroupedit.c	Thu Sep 26 22:50:23 2002
@@ -394,7 +394,7 @@
 		}
 
 		if (rid == -1) {
-			rid = pdb_gid_to_group_rid(gid);
+			rid = secrets_allocate_rid();
 		}
 		return addgroup(gid, sid_type, ntgroup?ntgroup:group,
 				group_desc, privilege, rid);



More information about the samba-technical mailing list