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

Reply via email to