-----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);