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