This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.
[kai/samba.git] / source / rpc_server / srv_util.c
index 5c781c20ae7455367a063edac274e7d9bc1ab781..4eba9c7d1f51623f515afa79840ca13f5e59808b 100644 (file)
@@ -1,6 +1,5 @@
 /* 
- *  Unix SMB/Netbios implementation.
- *  Version 1.9.
+ *  Unix SMB/CIFS implementation.
  *  RPC Pipe client / server routines
  *  Copyright (C) Andrew Tridgell              1992-1998
  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
@@ -39,6 +38,9 @@
 
 #include "includes.h"
 
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
 /*
  * A list of the rids of well known BUILTIN and Domain users
  * and groups.
@@ -82,18 +84,19 @@ rid_name domain_group_rids[] =
 NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, uint32 **prids, DOM_SID *q_sid)
 {
        SAM_ACCOUNT *sam_pass=NULL;
-       char *sep;
-       struct sys_grent *glist;
-       struct sys_grent *grp;
-       int i, num, cur_rid=0;
-       gid_t *gid;
+       int i, cur_rid=0;
+       gid_t gid;
+       gid_t *groups = NULL;
+       int num_groups;
        GROUP_MAP map;
        DOM_SID tmp_sid;
        fstring user_name;
        fstring str_domsid, str_qsid;
        uint32 rid,grid;
        uint32 *rids=NULL, *new_rids=NULL;
+       gid_t winbind_gid_low, winbind_gid_high;
        BOOL ret;
+       BOOL winbind_groups_exist;
 
        /*
         * this code is far from perfect.
@@ -109,17 +112,15 @@ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, ui
        *prids=NULL;
        *numgroups=0;
 
-       sep = lp_winbind_separator();
+       winbind_groups_exist = lp_winbind_gid(&winbind_gid_low, &winbind_gid_high);
 
 
        DEBUG(10,("get_alias_user_groups: looking if SID %s is a member of groups in the SID domain %s\n", 
                  sid_to_string(str_qsid, q_sid), sid_to_string(str_domsid, sid)));
 
-       sid_peek_rid(q_sid, &rid);
-
        pdb_init_sam(&sam_pass);
        become_root();
-       ret = pdb_getsampwrid(sam_pass, rid);
+       ret = pdb_getsampwsid(sam_pass, q_sid);
        unbecome_root();
        if (ret == False) {
                pdb_free_sam(&sam_pass);
@@ -129,16 +130,21 @@ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, ui
        fstrcpy(user_name, pdb_get_username(sam_pass));
        grid=pdb_get_group_rid(sam_pass);
        gid=pdb_get_gid(sam_pass);
-       
-       grp = glist = getgrent_list();
-       if (grp == NULL) {
+
+       become_root();
+       /* on some systems this must run as root */
+       num_groups = getgroups_user(user_name, &groups);        
+       unbecome_root();
+       if (num_groups == -1) {
+               /* this should never happen */
+               DEBUG(2,("get_alias_user_groups: getgroups_user failed\n"));
                pdb_free_sam(&sam_pass);
-               return NT_STATUS_NO_MEMORY;
+               return NT_STATUS_UNSUCCESSFUL;
        }
-       
-       for (; grp != NULL; grp = grp->next) {
-               if(!get_group_from_gid(grp->gr_gid, &map, MAPPING_WITHOUT_PRIV)) {
-                       DEBUG(10,("get_alias_user_groups: gid %d. not found\n", (int)grp->gr_gid));
+
+       for (i=0;i<num_groups;i++) {
+               if(!get_group_from_gid(groups[i], &map, MAPPING_WITHOUT_PRIV)) {
+                       DEBUG(10,("get_alias_user_groups: gid %d. not found\n", (int)groups[i]));
                        continue;
                }
                
@@ -158,7 +164,7 @@ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, ui
                }
 
                /* Don't return winbind groups as they are not local! */
-               if (strchr_m(map.nt_name, *sep) != NULL) {
+               if (winbind_groups_exist && (groups[i] >= winbind_gid_low) && (groups[i] <= winbind_gid_high)) {
                        DEBUG(10,("get_alias_user_groups: not returing %s, not local.\n", map.nt_name));
                        continue;
                }
@@ -169,30 +175,21 @@ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, ui
                        continue;                       
                }
                
-               /* the group is fine, we can check if there is the user we're looking for */
-               DEBUG(10,("get_alias_user_groups: checking if the user is a member of %s.\n", map.nt_name));
-               
-               for(num=0; grp->gr_mem[num]!=NULL; num++) {
-                       if(strcmp(grp->gr_mem[num], user_name)==0) {
-                               /* we found the user, add the group to the list */
-                               
-                               new_rids=(uint32 *)Realloc(rids, sizeof(uint32)*(cur_rid+1));
-                               if (new_rids==NULL) {
-                                       DEBUG(10,("get_alias_user_groups: could not realloc memory\n"));
-                                       pdb_free_sam(&sam_pass);
-                                       return NT_STATUS_NO_MEMORY;
-                               }
-                               rids=new_rids;
-                               
-                               sid_peek_rid(&map.sid, &(rids[cur_rid]));
-                               DEBUG(10,("get_alias_user_groups: user found in group %s\n", map.nt_name));
-                               cur_rid++;
-                               break;
-                       }
+               new_rids=(uint32 *)Realloc(rids, sizeof(uint32)*(cur_rid+1));
+               if (new_rids==NULL) {
+                       DEBUG(10,("get_alias_user_groups: could not realloc memory\n"));
+                       pdb_free_sam(&sam_pass);
+                       free(groups);
+                       return NT_STATUS_NO_MEMORY;
                }
+               rids=new_rids;
+               
+               sid_peek_rid(&map.sid, &(rids[cur_rid]));
+               cur_rid++;
+               break;
        }
 
-       grent_free(glist);
+       free(groups);
 
        /* now check for the user's gid (the primary group rid) */
        for (i=0; i<cur_rid && grid!=rids[i]; i++)
@@ -204,9 +201,9 @@ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, ui
                goto done;
        }
 
-       DEBUG(10,("get_alias_user_groups: looking for gid %d of user %s\n", (int)*gid, user_name));
+       DEBUG(10,("get_alias_user_groups: looking for gid %d of user %s\n", (int)gid, user_name));
 
-       if(!get_group_from_gid(*gid, &map, MAPPING_WITHOUT_PRIV)) {
+       if(!get_group_from_gid(gid, &map, MAPPING_WITHOUT_PRIV)) {
                DEBUG(0,("get_alias_user_groups: gid of user %s doesn't exist. Check your /etc/passwd and /etc/group files\n", user_name));
                goto done;
        }       
@@ -227,7 +224,7 @@ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, ui
        }
 
        /* Don't return winbind groups as they are not local! */
-       if (strchr_m(map.nt_name, *sep) != NULL) {
+       if (winbind_groups_exist && (gid >= winbind_gid_low) && (gid <= winbind_gid_high)) {
                DEBUG(10,("get_alias_user_groups: not returing %s, not local.\n", map.nt_name ));
                goto done;
        }
@@ -271,7 +268,7 @@ BOOL get_domain_user_groups(TALLOC_CTX *ctx, int *numgroups, DOM_GID **pgids, SA
        uint32 grid;
        uint32 tmp_rid;
 
-       *numgroups=0;
+       *numgroups= 0;
 
        fstrcpy(user_name, pdb_get_username(sam_pass));
        grid=pdb_get_group_rid(sam_pass);
@@ -279,7 +276,7 @@ BOOL get_domain_user_groups(TALLOC_CTX *ctx, int *numgroups, DOM_GID **pgids, SA
        DEBUG(10,("get_domain_user_groups: searching domain groups [%s] is a member of\n", user_name));
 
        /* first get the list of the domain groups */
-       if (!enum_group_mapping(SID_NAME_DOM_GRP, &map, &num_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV))
+       if (!pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, &num_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV))
                return False;
        DEBUG(10,("get_domain_user_groups: there are %d mapped groups\n", num_entries));
 
@@ -345,6 +342,7 @@ BOOL get_domain_user_groups(TALLOC_CTX *ctx, int *numgroups, DOM_GID **pgids, SA
        DEBUG(0,("get_domain_user_groups: primary gid of user [%s] is not a Domain group !\n", user_name));
        DEBUGADD(0,("get_domain_user_groups: You should fix it, NT doesn't like that\n"));
 
+
  done:
        *pgids=gids;
        *numgroups=cur_gid;
@@ -353,6 +351,35 @@ BOOL get_domain_user_groups(TALLOC_CTX *ctx, int *numgroups, DOM_GID **pgids, SA
        return True;
 }
 
+/*******************************************************************
+ gets a domain user's groups from their already-calculated NT_USER_TOKEN
+ ********************************************************************/
+NTSTATUS nt_token_to_group_list(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid, 
+                               const NT_USER_TOKEN *nt_token,
+                               int *numgroups, DOM_GID **pgids) 
+{
+       DOM_GID *gids;
+       int i;
+
+       gids = (DOM_GID *)talloc(mem_ctx, sizeof(*gids) * nt_token->num_sids);
+
+       if (!gids) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       *numgroups=0;
+
+       for (i=PRIMARY_GROUP_SID_INDEX; i < nt_token->num_sids; i++) {
+               if (sid_compare_domain(domain_sid, &nt_token->user_sids[i])==0) {
+                       sid_peek_rid(&nt_token->user_sids[i], &(gids[*numgroups].g_rid));
+                       gids[*numgroups].attr=7;
+                       (*numgroups)++;
+               }
+       }
+       *pgids = gids; 
+       return NT_STATUS_OK;
+}
+
 /*******************************************************************
  Look up a local (domain) rid and return a name and type.
  ********************************************************************/
@@ -405,6 +432,8 @@ NTSTATUS local_lookup_alias_name(uint32 rid, char *alias_name, uint32 *type)
        return NT_STATUS_NONE_MAPPED;
 }
 
+
+#if 0 /*Nobody uses this function just now*/
 /*******************************************************************
  Look up a local user rid and return a name and type.
  ********************************************************************/
@@ -449,12 +478,14 @@ NTSTATUS local_lookup_user_name(uint32 rid, char *user_name, uint32 *type)
        return NT_STATUS_NONE_MAPPED;
 }
 
+#endif
+
 /*******************************************************************
  Look up a local (domain) group name and return a rid
  ********************************************************************/
 NTSTATUS local_lookup_group_rid(char *group_name, uint32 *rid)
 {
-       char *grp_name;
+       const char *grp_name;
        int i = -1; /* start do loop at -1 */
 
        do /* find, if it exists, a group rid for the group name*/
@@ -471,9 +502,9 @@ NTSTATUS local_lookup_group_rid(char *group_name, uint32 *rid)
 /*******************************************************************
  Look up a local (BUILTIN) alias name and return a rid
  ********************************************************************/
-NTSTATUS local_lookup_alias_rid(char *alias_name, uint32 *rid)
+NTSTATUS local_lookup_alias_rid(const char *alias_name, uint32 *rid)
 {
-       char *als_name;
+       const char *als_name;
        int i = -1; /* start do loop at -1 */
 
        do /* find, if it exists, a alias rid for the alias name*/