*id_to_*id call reshape to return NTSTATUS errors
[ira/wip.git] / source3 / rpc_server / srv_util.c
index 93640f3445aef9a61fe854d1be65305a7c0e10b4..f96ccaef672fac3dd9eadaefc5719e5b4e4ec187 100644 (file)
@@ -1,7 +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,
  */
 
 #include "includes.h"
-#include "nterr.h"
 
-extern int DEBUGLEVEL;
-extern DOM_SID global_machine_sid;
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
 
 /*
  * A list of the rids of well known BUILTIN and Domain users
@@ -81,616 +78,317 @@ rid_name domain_group_rids[] =
     { 0                             , NULL }
 };
 
-int make_dom_gids(char *gids_str, DOM_GID **ppgids)
-{
-  char *ptr;
-  pstring s2;
-  int count;
-  DOM_GID *gids;
-
-  *ppgids = NULL;
-
-  DEBUG(4,("make_dom_gids: %s\n", gids_str));
-
-  if (gids_str == NULL || *gids_str == 0)
-    return 0;
-
-  for (count = 0, ptr = gids_str; 
-       next_token(&ptr, s2, NULL, sizeof(s2)); 
-       count++)
-    ;
-
-  gids = (DOM_GID *)malloc( sizeof(DOM_GID) * count );
-  if(!gids)
-  {
-    DEBUG(0,("make_dom_gids: malloc fail !\n"));
-    return 0;
-  }
-
-  for (count = 0, ptr = gids_str; 
-       next_token(&ptr, s2, NULL, sizeof(s2)) && 
-              count < LSA_MAX_GROUPS; 
-       count++) 
-  {
-    /* the entries are of the form GID/ATTR, ATTR being optional.*/
-    char *attr;
-    uint32 rid = 0;
-    int i;
-
-    attr = strchr(s2,'/');
-    if (attr)
-      *attr++ = 0;
-
-    if (!attr || !*attr)
-      attr = "7"; /* default value for attribute is 7 */
-
-    /* look up the RID string and see if we can turn it into a rid number */
-    for (i = 0; builtin_alias_rids[i].name != NULL; i++)
-    {
-      if (strequal(builtin_alias_rids[i].name, s2))
-      {
-        rid = builtin_alias_rids[i].rid;
-        break;
-      }
-    }
-
-    if (rid == 0)
-      rid = atoi(s2);
-
-    if (rid == 0)
-    {
-      DEBUG(1,("make_dom_gids: unknown well-known alias RID %s/%s\n", s2, attr));
-      count--;
-    }
-    else
-    {
-      gids[count].g_rid = rid;
-      gids[count].attr  = atoi(attr);
-
-      DEBUG(5,("group id: %d attr: %d\n", gids[count].g_rid, gids[count].attr));
-    }
-  }
-
-  *ppgids = gids;
-  return count;
-}
-
 /*******************************************************************
- turns a DCE/RPC request into a DCE/RPC reply
-
- this is where the data really should be split up into an array of
- headers and data sections.
-
+ gets a domain user's groups
  ********************************************************************/
-BOOL create_rpc_reply(pipes_struct *p,
-                               uint32 data_start, uint32 data_end)
+NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, uint32 **prids, DOM_SID *q_sid)
 {
-       DEBUG(5,("create_rpc_reply: data_start: %d data_end: %d max_tsize: %d\n",
-                 data_start, data_end, p->hdr_ba.bba.max_tsize));
-
-       mem_buf_init(&(p->rhdr.data), 0);
-       mem_alloc_data(p->rhdr.data, 0x18);
-
-       p->rhdr.align = 4;
-       p->rhdr.io = False;
-
-       p->hdr_resp.alloc_hint = data_end - data_start; /* calculate remaining data to be sent */
-       p->hdr.pkt_type = RPC_RESPONSE; /* mark header as an rpc response */
-
-       /* set up rpc header (fragmentation issues) */
-       if (data_start == 0)
-       {
-               p->hdr.flags = RPC_FLG_FIRST;
-       }
-       else
-       {
-               p->hdr.flags = 0;
-       }
-
-       if (p->hdr_resp.alloc_hint + 0x18 <= p->hdr_ba.bba.max_tsize)
-       {
-               p->hdr.flags |= RPC_FLG_LAST;
-               p->hdr.frag_len = p->hdr_resp.alloc_hint + 0x18;
-       }
-       else
-       {
-               p->hdr.frag_len = p->hdr_ba.bba.max_tsize;
-       }
-
-       p->rhdr.data->offset.start = 0;
-       p->rhdr.data->offset.end   = 0x18;
-
-       /* store the header in the data stream */
-       p->rhdr.offset = 0;
-       smb_io_rpc_hdr   ("hdr", &(p->hdr   ), &(p->rhdr), 0);
-       smb_io_rpc_hdr_resp("resp", &(p->hdr_resp), &(p->rhdr), 0);
-
-       return p->rhdr.data != NULL && p->rhdr.offset == 0x18;
-}
-
-static BOOL api_pipe_ntlmssp_verify(pipes_struct *p)
-{
-       uchar lm_owf[24];
-       uchar nt_owf[24];
-       
-       DEBUG(5,("api_pipe_ntlmssp_verify: checking user details\n"));
-
-       if (p->ntlmssp_resp.hdr_lm_resp.str_str_len == 0) return False;
-       if (p->ntlmssp_resp.hdr_nt_resp.str_str_len == 0) return False;
-       if (p->ntlmssp_resp.hdr_usr    .str_str_len == 0) return False;
-       if (p->ntlmssp_resp.hdr_domain .str_str_len == 0) return False;
-       if (p->ntlmssp_resp.hdr_wks    .str_str_len == 0) return False;
-
-       memset(p->user_name, 0, sizeof(p->user_name));
-       memset(p->domain   , 0, sizeof(p->domain   ));
-       memset(p->wks      , 0, sizeof(p->wks      ));
-
-       if (IS_BITS_SET_ALL(p->ntlmssp_chal.neg_flags, NTLMSSP_NEGOTIATE_UNICODE))
-       {
-               fstrcpy(p->user_name, unistrn2((uint16*)p->ntlmssp_resp.user  , p->ntlmssp_resp.hdr_usr   .str_str_len/2));
-               fstrcpy(p->domain   , unistrn2((uint16*)p->ntlmssp_resp.domain, p->ntlmssp_resp.hdr_domain.str_str_len/2));
-               fstrcpy(p->wks      , unistrn2((uint16*)p->ntlmssp_resp.wks   , p->ntlmssp_resp.hdr_wks   .str_str_len/2));
-       }
-       else
-       {
-               fstrcpy(p->user_name, p->ntlmssp_resp.user  );
-               fstrcpy(p->domain   , p->ntlmssp_resp.domain);
-               fstrcpy(p->wks      , p->ntlmssp_resp.wks   );
-       }
-
-       DEBUG(5,("user: %s domain: %s wks: %s\n", p->user_name, p->domain, p->wks));
-
-       memcpy(lm_owf, p->ntlmssp_resp.lm_resp, sizeof(lm_owf));
-       memcpy(nt_owf, p->ntlmssp_resp.nt_resp, sizeof(nt_owf));
-
-#ifdef DEBUG_PASSWORD
-       DEBUG(100,("lm, nt owfs:\n"));
-       dump_data(100, lm_owf, sizeof(lm_owf));
-       dump_data(100, nt_owf, sizeof(nt_owf));
-#endif
-       become_root(True);
-       p->ntlmssp_validated = pass_check_smb(p->user_name, p->domain,
-                             p->ntlmssp_chal.challenge, lm_owf, nt_owf, NULL);
-       unbecome_root(True);
-
-       return p->ntlmssp_validated;
-}
-
-static BOOL api_pipe_ntlmssp(pipes_struct *p, prs_struct *pd)
-{
-       /* receive a negotiate; send a challenge; receive a response */
-       switch (p->auth_verifier.msg_type)
-       {
-               case NTLMSSP_NEGOTIATE:
-               {
-                       smb_io_rpc_auth_ntlmssp_neg("", &p->ntlmssp_neg, pd, 0);
-                       break;
-               }
-               case NTLMSSP_AUTH:
-               {
-                       smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, pd, 0);
-                       if (!api_pipe_ntlmssp_verify(p))
-                       {
-                               pd->offset = 0;
-                       }
-                       break;
+       SAM_ACCOUNT *sam_pass=NULL;
+       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.
+        * first it enumerates the full /etc/group and that can be slow.
+        * second, it works only with users' SIDs
+        * whereas the day we support nested groups, it will have to
+        * support both users's SIDs and domain groups' SIDs
+        *
+        * having our own ldap backend would be so much faster !
+        * we're far from that, but hope one day ;-) JFM.
+        */
+
+       *prids=NULL;
+       *numgroups=0;
+
+       winbind_groups_exist = lp_idmap_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)));
+
+       pdb_init_sam(&sam_pass);
+       become_root();
+       ret = pdb_getsampwsid(sam_pass, q_sid);
+       unbecome_root();
+       if (ret == False) {
+               pdb_free_sam(&sam_pass);
+               return NT_STATUS_NO_SUCH_USER;
+       }
+
+       fstrcpy(user_name, pdb_get_username(sam_pass));
+       grid=pdb_get_group_rid(sam_pass);
+       if (NT_STATUS_IS_ERR(sid_to_gid(pdb_get_group_sid(sam_pass), &gid))) {
+               /* this should never happen */
+               DEBUG(2,("get_alias_user_groups: sid_to_gid failed!\n"));
+               pdb_free_sam(&sam_pass);
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       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_UNSUCCESSFUL;
+       }
+
+       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;
                }
-               default:
-               {
-                       /* NTLMSSP expected: unexpected message type */
-                       DEBUG(3,("unexpected message type in NTLMSSP %d\n",
-                                 p->auth_verifier.msg_type));
-                       return False;
+               
+               /* if it's not an alias, continue */
+               if (map.sid_name_use!=SID_NAME_ALIAS) {
+                       DEBUG(10,("get_alias_user_groups: not returing %s, not an ALIAS group.\n", map.nt_name));
+                       continue;
                }
-       }
-
-       return (pd->offset != 0);
-}
-
-struct api_cmd
-{
-  char * pipe_clnt_name;
-  char * pipe_srv_name;
-  BOOL (*fn) (pipes_struct *, prs_struct *);
-};
-
-static struct api_cmd api_fd_commands[] =
-{
-    { "lsarpc",   "lsass",   api_ntlsa_rpc },
-    { "samr",     "lsass",   api_samr_rpc },
-    { "srvsvc",   "ntsvcs",  api_srvsvc_rpc },
-    { "wkssvc",   "ntsvcs",  api_wkssvc_rpc },
-    { "NETLOGON", "lsass",   api_netlog_rpc },
-    { "winreg",   "winreg",  api_reg_rpc },
-    { NULL,       NULL,      NULL }
-};
-
-static BOOL api_pipe_bind_auth_resp(pipes_struct *p, prs_struct *pd)
-{
-       p->ntlmssp_auth = False;
-
-       DEBUG(5,("api_pipe_bind_auth_resp: decode request. %d\n", __LINE__));
 
-       if (p->hdr.auth_len != 0)
-       {
-               /* decode the authentication verifier response */
-               smb_io_rpc_hdr_autha("", &p->autha_info, pd, 0);
-               if (pd->offset == 0) return False;
-
-               p->ntlmssp_auth = p->auth_info.auth_type = 0x0a;
-
-               if (p->ntlmssp_auth)
-               {
-                       smb_io_rpc_auth_verifier("", &p->auth_verifier, pd, 0);
-                       if (pd->offset == 0) return False;
-
-                       p->ntlmssp_auth = strequal(p->auth_verifier.signature, "NTLMSSP");
+               sid_copy(&tmp_sid, &map.sid);
+               sid_split_rid(&tmp_sid, &rid);
+               
+               /* if the sid is not in the correct domain, continue */
+               if (!sid_equal(&tmp_sid, sid)) {
+                       DEBUG(10,("get_alias_user_groups: not returing %s, not in the domain SID.\n", map.nt_name));
+                       continue;
                }
 
-               if (p->ntlmssp_auth)
-               {
-                       if (!api_pipe_ntlmssp(p, pd)) return False;
+               /* Don't return winbind groups as they are not local! */
+               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;
                }
-       }
-
-       return p->ntlmssp_auth;
-}
-
-static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd)
-{
-       uint16 assoc_gid;
-       fstring ack_pipe_name;
-       int i = 0;
-
-       p->ntlmssp_auth = False;
 
-       DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
-
-       for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
-       {
-               if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
-                   api_fd_commands[i].fn != NULL)
-               {
-                       DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
-                                  api_fd_commands[i].pipe_clnt_name,
-                                  api_fd_commands[i].pipe_srv_name));
-                       fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
-                       break;
-               }
-       }
-
-       if (api_fd_commands[i].fn == NULL) return False;
-
-       /* decode the bind request */
-       smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
-
-       if (pd->offset == 0) return False;
-
-       if (p->hdr.auth_len != 0)
-       {
-               /* decode the authentication verifier */
-               smb_io_rpc_hdr_auth    ("", &p->auth_info    , pd, 0);
-               if (pd->offset == 0) return False;
-
-               p->ntlmssp_auth = p->auth_info.auth_type = 0x0a;
-
-               if (p->ntlmssp_auth)
-               {
-                       smb_io_rpc_auth_verifier("", &p->auth_verifier, pd, 0);
-                       if (pd->offset == 0) return False;
-
-                       p->ntlmssp_auth = strequal(p->auth_verifier.signature, "NTLMSSP");
+               /* Don't return user private groups... */
+               if (Get_Pwnam(map.nt_name) != 0) {
+                       DEBUG(10,("get_alias_user_groups: not returing %s, clashes with user.\n", map.nt_name));
+                       continue;                       
                }
-
-               if (p->ntlmssp_auth)
-               {
-                       if (!api_pipe_ntlmssp(p, pd)) return False;
+               
+               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;
        }
 
-       /* name has to be \PIPE\xxxxx */
-       fstrcpy(ack_pipe_name, "\\PIPE\\");
-       fstrcat(ack_pipe_name, p->pipe_srv_name);
-
-       DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
+       free(groups);
 
-       prs_init(&(p->rdata), 1024, 4, 0, False);
-       prs_init(&(p->rhdr ), 0x10, 4, 0, False);
-       prs_init(&(p->rauth), 1024, 4, 0, False);
-       prs_init(&(p->rverf), 0x08, 4, 0, False);
-       prs_init(&(p->rntlm), 1024, 4, 0, False);
+       /* now check for the user's gid (the primary group rid) */
+       for (i=0; i<cur_rid && grid!=rids[i]; i++)
+               ;
 
-       /***/
-       /*** do the bind ack first ***/
-       /***/
-
-       if (p->ntlmssp_auth)
-       {
-               assoc_gid = 0x7a77;
+       /* the user's gid is already there */
+       if (i!=cur_rid) {
+               DEBUG(10,("get_alias_user_groups: user is already in the list. good.\n"));
+               goto done;
        }
-       else
-       {
-               assoc_gid = p->hdr_rb.bba.assoc_gid;
-       }
-
-       make_rpc_hdr_ba(&p->hdr_ba,
-                       p->hdr_rb.bba.max_tsize,
-                       p->hdr_rb.bba.max_rsize,
-                       assoc_gid,
-                       ack_pipe_name,
-                       0x1, 0x0, 0x0,
-                       &(p->hdr_rb.transfer));
-
-       smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0);
-       mem_realloc_data(p->rdata.data, p->rdata.offset);
 
-       /***/
-       /*** now the authentication ***/
-       /***/
-
-       if (p->ntlmssp_auth)
-       {
-               uint8 challenge[8];
-               generate_random_buffer(challenge, 8, False);
+       DEBUG(10,("get_alias_user_groups: looking for gid %d of user %s\n", (int)gid, user_name));
 
-               /*** authentication info ***/
+       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;
+       }       
 
-               make_rpc_hdr_auth(&p->auth_info, 0x0a, 0x06, 0, 1);
-               smb_io_rpc_hdr_auth("", &p->auth_info, &p->rverf, 0);
-               mem_realloc_data(p->rverf.data, p->rverf.offset);
-
-               /*** NTLMSSP verifier ***/
-
-               make_rpc_auth_verifier(&p->auth_verifier,
-                                      "NTLMSSP", NTLMSSP_CHALLENGE);
-               smb_io_rpc_auth_verifier("", &p->auth_verifier, &p->rauth, 0);
-               mem_realloc_data(p->rauth.data, p->rauth.offset);
-
-               /* NTLMSSP challenge ***/
-
-               make_rpc_auth_ntlmssp_chal(&p->ntlmssp_chal,
-                                          0x000082b1, challenge);
-               smb_io_rpc_auth_ntlmssp_chal("", &p->ntlmssp_chal, &p->rntlm, 0);
-               mem_realloc_data(p->rntlm.data, p->rntlm.offset);
+       /* the primary group isn't an alias */
+       if (map.sid_name_use!=SID_NAME_ALIAS) {
+               DEBUG(10,("get_alias_user_groups: not returing %s, not an ALIAS group.\n", map.nt_name));
+               goto done;
        }
 
-       /***/
-       /*** then do the header, now we know the length ***/
-       /***/
-
-       make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST,
-                    p->hdr.call_id,
-                    p->rdata.offset + p->rverf.offset + p->rauth.offset + p->rntlm.offset + 0x10,
-                    p->rauth.offset + p->rntlm.offset);
-
-       smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0);
-       mem_realloc_data(p->rhdr.data, p->rdata.offset);
+       sid_copy(&tmp_sid, &map.sid);
+       sid_split_rid(&tmp_sid, &rid);
 
-       /***/
-       /*** link rpc header, bind acknowledgment and authentication responses ***/
-       /***/
-
-       if (p->ntlmssp_auth)
-       {
-               prs_link(NULL     , &p->rhdr , &p->rdata);
-               prs_link(&p->rhdr , &p->rdata, &p->rverf);
-               prs_link(&p->rdata, &p->rverf, &p->rauth);
-               prs_link(&p->rverf, &p->rauth, &p->rntlm);
-               prs_link(&p->rauth, &p->rntlm, NULL     );
-       }
-       else
-       {
-               prs_link(NULL    , &p->rhdr , &p->rdata);
-               prs_link(&p->rhdr, &p->rdata, NULL     );
+       /* if the sid is not in the correct domain, continue */
+       if (!sid_equal(&tmp_sid, sid)) {
+               DEBUG(10,("get_alias_user_groups: not returing %s, not in the domain SID.\n", map.nt_name));
+               goto done;
        }
 
-       return True;
-}
-
-
-static BOOL api_pipe_auth_process(pipes_struct *p, prs_struct *pd)
-{
-       return True;
-}
-
-static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd)
-{
-       int i = 0;
-
-       if (p->ntlmssp_auth && p->ntlmssp_validated)
-       {
-               if (!api_pipe_auth_process(p)) return False;
-
-               DEBUG(0,("api_pipe_request: **** MUST CALL become_user() HERE **** \n"));
-#if 0
-               become_user();
-#endif
+       /* Don't return winbind groups as they are not local! */
+       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;
        }
 
-       for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
-       {
-               if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
-                   api_fd_commands[i].fn != NULL)
-               {
-                       DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
-                       return api_fd_commands[i].fn(p, pd);
-               }
+       /* Don't return user private groups... */
+       if (Get_Pwnam(map.nt_name) != 0) {
+               DEBUG(10,("get_alias_user_groups: not returing %s, clashes with user.\n", map.nt_name ));
+               goto done;                      
        }
-       return False;
-}
-
-BOOL rpc_command(pipes_struct *p, prs_struct *pd)
-{
-       BOOL reply = False;
-       if (pd->data == NULL) return False;
 
-       /* process the rpc header */
-       smb_io_rpc_hdr("", &p->hdr, pd, 0);
-
-       if (pd->offset == 0) return False;
-
-       switch (p->hdr.pkt_type)
-       {
-               case RPC_BIND   :
-               {
-                       reply = api_pipe_bind_req(p, pd);
-                       break;
-               }
-               case RPC_REQUEST:
-               {
-                       reply = api_pipe_request (p, pd);
-                       break;
-               }
-               case RPC_BINDRESP: /* not the real name! */
-               {
-                       reply = api_pipe_bind_auth_resp(p, pd);
-                       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);
+               return NT_STATUS_NO_MEMORY;
        }
+       rids=new_rids;
+
+       sid_peek_rid(&map.sid, &(rids[cur_rid]));
+       cur_rid++;
 
+done:
+       *prids=rids;
+       *numgroups=cur_rid;
+       pdb_free_sam(&sam_pass);
 
-       return reply;
+       return NT_STATUS_OK;
 }
 
 
 /*******************************************************************
- receives a netlogon pipe and responds.
+ gets a domain user's groups
  ********************************************************************/
-static BOOL api_rpc_command(pipes_struct *p, 
-                               char *rpc_name, struct api_struct *api_rpc_cmds,
-                               prs_struct *data)
+BOOL get_domain_user_groups(TALLOC_CTX *ctx, int *numgroups, DOM_GID **pgids, SAM_ACCOUNT *sam_pass)
 {
-       int fn_num;
-       DEBUG(4,("api_rpc_command: %s op 0x%x - ", rpc_name, p->hdr_req.opnum));
-
-       for (fn_num = 0; api_rpc_cmds[fn_num].name; fn_num++)
-       {
-               if (api_rpc_cmds[fn_num].opnum == p->hdr_req.opnum && api_rpc_cmds[fn_num].fn != NULL)
-               {
-                       DEBUG(3,("api_rpc_command: %s\n", api_rpc_cmds[fn_num].name));
-                       break;
-               }
-       }
-
-       if (api_rpc_cmds[fn_num].name == NULL)
-       {
-               DEBUG(4, ("unknown\n"));
-               return False;
-       }
+       GROUP_MAP *map=NULL;
+       int i, num, num_entries, cur_gid=0;
+       struct group *grp;
+       DOM_GID *gids;
+       fstring user_name;
+       uint32 grid;
+       uint32 tmp_rid;
 
-       /* start off with 1024 bytes, and a large safety margin too */
-       mem_buf_init(&(p->rdata.data), SAFETY_MARGIN);
-       mem_alloc_data(p->rdata.data, 1024);
+       *numgroups= 0;
 
-       p->rdata.io = False;
-       p->rdata.align = 4;
+       fstrcpy(user_name, pdb_get_username(sam_pass));
+       grid=pdb_get_group_rid(sam_pass);
 
-       p->rdata.data->offset.start = 0;
-       p->rdata.data->offset.end   = 0xffffffff;
+       DEBUG(10,("get_domain_user_groups: searching domain groups [%s] is a member of\n", user_name));
 
-       /* do the actual command */
-       p->rdata.offset = 0; 
-       api_rpc_cmds[fn_num].fn(p->vuid, data, &(p->rdata));
-
-       if (p->rdata.data == NULL || p->rdata.offset == 0)
-       {
-               mem_free_data(p->rdata.data);
+       /* first get the list of the domain groups */
+       if (!pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, &num_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV))
                return False;
-       }
-
-       mem_realloc_data(p->rdata.data, p->rdata.offset);
-
-       DEBUG(10,("called %s\n", rpc_name));
-
-       return True;
-}
-
+       DEBUG(10,("get_domain_user_groups: there are %d mapped groups\n", num_entries));
+
+       /* 
+        * alloc memory. In the worse case, we alloc memory for nothing.
+        * but I prefer to alloc for nothing
+        * than reallocing everytime.
+        */
+       gids = (DOM_GID *)talloc(ctx, sizeof(DOM_GID) *  num_entries);  
+
+       /* for each group, check if the user is a member of*/
+       for(i=0; i<num_entries; i++) {
+               if ((grp=getgrgid(map[i].gid)) == NULL) {
+                       /* very weird !!! */
+                       DEBUG(5,("get_domain_user_groups: gid %d doesn't exist anymore !\n", (int)map[i].gid));
+                       continue;
+               }
 
-/*******************************************************************
- receives a netlogon pipe and responds.
********************************************************************/
-BOOL api_rpcTNP(pipes_struct *p, char *rpc_name, struct api_struct *api_rpc_cmds,
-                               prs_struct *data)
-{
-       if (data == NULL || data->data == NULL)
-       {
-               DEBUG(2,("%s: NULL data received\n", rpc_name));
-               return False;
+               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 */
+                               sid_peek_rid(&map[i].sid, &(gids[cur_gid].g_rid));
+                               gids[cur_gid].attr=7;
+                               DEBUG(10,("get_domain_user_groups: user found in group %s\n", map[i].nt_name));
+                               cur_gid++;
+                               break;
+                       }
+               }
        }
 
-       /* read the rpc header */
-       smb_io_rpc_hdr_req("req", &(p->hdr_req), data, 0);
-
-       /* interpret the command */
-       if (!api_rpc_command(p, rpc_name, api_rpc_cmds, data))
-       {
-               return False;
+       /* we have checked the groups */
+       /* we must now check the gid of the user or the primary group rid, that's the same */
+       for (i=0; i<cur_gid && grid!=gids[i].g_rid; i++)
+               ;
+       
+       /* the user's gid is already there */
+       if (i!=cur_gid) {
+               /* 
+                * the primary group of the user but be the first one in the list
+                * don't ask ! JFM.
+                */
+               gids[i].g_rid=gids[0].g_rid;
+               gids[0].g_rid=grid;
+               goto done;
+       }
+
+       for(i=0; i<num_entries; i++) {
+               sid_peek_rid(&map[i].sid, &tmp_rid);
+               if (tmp_rid==grid) {
+                       /* 
+                        * the primary group of the user but be the first one in the list
+                        * don't ask ! JFM.
+                        */
+                       gids[cur_gid].g_rid=gids[0].g_rid;
+                       gids[0].g_rid=tmp_rid;
+                       gids[cur_gid].attr=7;
+                       DEBUG(10,("get_domain_user_groups: primary gid of user found in group %s\n", map[i].nt_name));
+                       cur_gid++;
+                       goto done; /* leave the loop early */
+               }
        }
 
-       /* create the rpc header */
-       if (!create_rpc_reply(p, 0, p->rdata.offset))
-       {
-               return False;
-       }
+       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"));
 
-       p->frag_len_left   = p->hdr.frag_len - p->file_offset;
-       p->next_frag_start = p->hdr.frag_len; 
-       
-       /* set up the data chain */
-       p->rhdr.data->offset.start = 0;
-       p->rhdr.data->offset.end   = p->rhdr.offset;
-       p->rhdr.data->next = p->rdata.data;
 
-       p->rdata.data->offset.start = p->rhdr.data->offset.end;
-       p->rdata.data->offset.end   = p->rhdr.data->offset.end + p->rdata.offset;
-       p->rdata.data->next = NULL;
+ done:
+       *pgids=gids;
+       *numgroups=cur_gid;
+       safe_free(map);
 
        return True;
 }
 
-
 /*******************************************************************
- gets a domain user's groups
+ gets a domain user's groups from their already-calculated NT_USER_TOKEN
  ********************************************************************/
-void get_domain_user_groups(char *domain_groups, char *user)
+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) 
 {
-       pstring tmp;
+       DOM_GID *gids;
+       int i;
 
-       if (domain_groups == NULL || user == NULL) return;
+       gids = (DOM_GID *)talloc(mem_ctx, sizeof(*gids) * nt_token->num_sids);
 
-       /* any additional groups this user is in.  e.g power users */
-       pstrcpy(domain_groups, lp_domain_groups());
-
-       /* can only be a user or a guest.  cannot be guest _and_ admin */
-       if (user_in_list(user, lp_domain_guest_group()))
-       {
-               slprintf(tmp, sizeof(tmp) - 1, " %ld/7 ", DOMAIN_GROUP_RID_GUESTS);
-               pstrcat(domain_groups, tmp);
-
-               DEBUG(3,("domain guest group access %s granted\n", tmp));
+       if (!gids) {
+               return NT_STATUS_NO_MEMORY;
        }
-       else
-       {
-               slprintf(tmp, sizeof(tmp) -1, " %ld/7 ", DOMAIN_GROUP_RID_USERS);
-               pstrcat(domain_groups, tmp);
-
-               DEBUG(3,("domain group access %s granted\n", tmp));
 
-               if (user_in_list(user, lp_domain_admin_group()))
-               {
-                       slprintf(tmp, sizeof(tmp) - 1, " %ld/7 ", DOMAIN_GROUP_RID_ADMINS);
-                       pstrcat(domain_groups, tmp);
+       *numgroups=0;
 
-                       DEBUG(3,("domain admin group access %s granted\n", tmp));
+       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;
 }
 
-
 /*******************************************************************
- lookup_group_name
+ Look up a local (domain) rid and return a name and type.
  ********************************************************************/
-uint32 lookup_group_name(uint32 rid, char *group_name, uint32 *type)
+NTSTATUS local_lookup_group_name(uint32 rid, char *group_name, uint32 *type)
 {
        int i = 0; 
        (*type) = SID_NAME_DOM_GRP;
@@ -706,17 +404,17 @@ uint32 lookup_group_name(uint32 rid, char *group_name, uint32 *type)
        {
                fstrcpy(group_name, domain_group_rids[i].name);
                DEBUG(5,(" = %s\n", group_name));
-               return 0x0;
+               return NT_STATUS_OK;
        }
 
        DEBUG(5,(" none mapped\n"));
-       return 0xC0000000 | NT_STATUS_NONE_MAPPED;
+       return NT_STATUS_NONE_MAPPED;
 }
 
 /*******************************************************************
- lookup_alias_name
+ Look up a local alias rid and return a name and type.
  ********************************************************************/
-uint32 lookup_alias_name(uint32 rid, char *alias_name, uint32 *type)
+NTSTATUS local_lookup_alias_name(uint32 rid, char *alias_name, uint32 *type)
 {
        int i = 0; 
        (*type) = SID_NAME_WKN_GRP;
@@ -732,20 +430,24 @@ uint32 lookup_alias_name(uint32 rid, char *alias_name, uint32 *type)
        {
                fstrcpy(alias_name, builtin_alias_rids[i].name);
                DEBUG(5,(" = %s\n", alias_name));
-               return 0x0;
+               return NT_STATUS_OK;
        }
 
        DEBUG(5,(" none mapped\n"));
-       return 0xC0000000 | NT_STATUS_NONE_MAPPED;
+       return NT_STATUS_NONE_MAPPED;
 }
 
+
+#if 0 /*Nobody uses this function just now*/
 /*******************************************************************
- lookup_user_name
+ Look up a local user rid and return a name and type.
  ********************************************************************/
-uint32 lookup_user_name(uint32 rid, char *user_name, uint32 *type)
+NTSTATUS local_lookup_user_name(uint32 rid, char *user_name, uint32 *type)
 {
-       struct sam_disp_info *disp_info;
+       SAM_ACCOUNT *sampwd=NULL;
        int i = 0;
+       BOOL ret;
+       
        (*type) = SID_NAME_USER;
 
        DEBUG(5,("lookup_user_name: rid: %d", rid));
@@ -756,35 +458,39 @@ uint32 lookup_user_name(uint32 rid, char *user_name, uint32 *type)
                i++;
        }
 
-       if (domain_user_rids[i].rid != 0)
-       {
+       if (domain_user_rids[i].rid != 0) {
                fstrcpy(user_name, domain_user_rids[i].name);
                DEBUG(5,(" = %s\n", user_name));
-               return 0x0;
+               return NT_STATUS_OK;
        }
 
+       pdb_init_sam(&sampwd);
+
        /* ok, it's a user.  find the user account */
-       become_root(True);
-       disp_info = getsamdisprid(rid);
-       unbecome_root(True);
+       become_root();
+       ret = pdb_getsampwrid(sampwd, rid);
+       unbecome_root();
 
-       if (disp_info != NULL)
-       {
-               fstrcpy(user_name, disp_info->smb_name);
+       if (ret == True) {
+               fstrcpy(user_name, pdb_get_username(sampwd) );
                DEBUG(5,(" = %s\n", user_name));
-               return 0x0;
+               pdb_free_sam(&sampwd);
+               return NT_STATUS_OK;
        }
 
        DEBUG(5,(" none mapped\n"));
-       return 0xC0000000 | NT_STATUS_NONE_MAPPED;
+       pdb_free_sam(&sampwd);
+       return NT_STATUS_NONE_MAPPED;
 }
 
+#endif
+
 /*******************************************************************
lookup_group_rid
Look up a local (domain) group name and return a rid
  ********************************************************************/
-uint32 lookup_group_rid(char *group_name, uint32 *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*/
@@ -795,15 +501,15 @@ uint32 lookup_group_rid(char *group_name, uint32 *rid)
 
        } while (grp_name != NULL && !strequal(grp_name, group_name));
 
-       return (grp_name != NULL) ? 0 : 0xC0000000 | NT_STATUS_NONE_MAPPED;
+       return (grp_name != NULL) ? NT_STATUS_OK : NT_STATUS_NONE_MAPPED;
 }
 
 /*******************************************************************
lookup_alias_rid
Look up a local (BUILTIN) alias name and return a rid
  ********************************************************************/
-uint32 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*/
@@ -814,27 +520,32 @@ uint32 lookup_alias_rid(char *alias_name, uint32 *rid)
 
        } while (als_name != NULL && !strequal(als_name, alias_name));
 
-       return (als_name != NULL) ? 0 : 0xC0000000 | NT_STATUS_NONE_MAPPED;
+       return (als_name != NULL) ? NT_STATUS_OK : NT_STATUS_NONE_MAPPED;
 }
 
 /*******************************************************************
lookup_user_rid
Look up a local user name and return a rid
  ********************************************************************/
-uint32 lookup_user_rid(char *user_name, uint32 *rid)
+NTSTATUS local_lookup_user_rid(char *user_name, uint32 *rid)
 {
-       struct sam_passwd *sam_pass;
+       SAM_ACCOUNT *sampass=NULL;
+       BOOL ret;
+
        (*rid) = 0;
 
+       pdb_init_sam(&sampass);
+
        /* find the user account */
-       become_root(True);
-       sam_pass = getsam21pwnam(user_name);
-       unbecome_root(True);
+       become_root();
+       ret = pdb_getsampwnam(sampass, user_name);
+       unbecome_root();
 
-       if (sam_pass != NULL)
-       {
-               (*rid) = sam_pass->user_rid;
-               return 0x0;
+       if (ret == True) {
+               (*rid) = pdb_get_user_rid(sampass);
+               pdb_free_sam(&sampass);
+               return NT_STATUS_OK;
        }
 
-       return 0xC0000000 | NT_STATUS_NONE_MAPPED;
+       pdb_free_sam(&sampass);
+       return NT_STATUS_NONE_MAPPED;
 }