Add alias support to winbindd_passdb. Sorry, Simo, this does not leave too
authorVolker Lendecke <vlendec@samba.org>
Sat, 13 Mar 2004 17:35:47 +0000 (17:35 +0000)
committerVolker Lendecke <vlendec@samba.org>
Sat, 13 Mar 2004 17:35:47 +0000 (17:35 +0000)
much of your winbindd_passdb, users are currently not provided by that, only
aliases. Currently the code to maintain that stuff is not yet in, this will be
next, see my next posting to samba-technical.

Volker

source/nsswitch/winbindd.h
source/nsswitch/winbindd_group.c
source/nsswitch/winbindd_passdb.c
source/nsswitch/winbindd_sid.c
source/nsswitch/winbindd_util.c

index 0087d58195d8eb938ff69a09bbeb352a5e22470b..5c05a1b0457bf489492d24a3e44298056a40c940 100644 (file)
@@ -97,6 +97,7 @@ struct winbindd_domain {
        BOOL native_mode;                      /* is this a win2k domain in native mode ? */
        BOOL active_directory;                 /* is this a win2k active directory ? */
        BOOL primary;                          /* is this our primary domain ? */
+       BOOL internal;          /* BUILTIN and member SAM */
 
        /* Lookup methods for this domain (LDAP or RPC) */
        struct winbindd_methods *methods;
index 4805e628dd800fc0c592eab48640df5b673cffd9..94bd0fa0b9c3231019e658db0b7ea4495b784d32 100644 (file)
@@ -104,6 +104,15 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
        DEBUG(10, ("group SID %s\n", sid_to_string(sid_string, group_sid)));
 
        *num_gr_mem = 0;
+
+       /* HACK ALERT!! This whole routine does not cope with group members
+        * from more than one domain, ie aliases. Thus we have to work it out
+        * ourselves in a special routine. */
+
+       if (domain->internal)
+               return fill_passdb_alias_grmem(domain, group_sid,
+                                              num_gr_mem,
+                                              gr_mem, gr_mem_len);
        
        if ( !((group_name_type==SID_NAME_DOM_GRP) ||
                ((group_name_type==SID_NAME_ALIAS) && domain->primary)) )
@@ -376,7 +385,8 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state)
        }
 
        if ( !((name_type==SID_NAME_DOM_GRP) ||
-              ((name_type==SID_NAME_ALIAS) && domain->primary) ))
+              ((name_type==SID_NAME_ALIAS) && domain->primary) ||
+              ((name_type==SID_NAME_ALIAS) && domain->internal)) )
        {
                DEBUG(1, ("name '%s' is not a local or domain group: %d\n", 
                          group_name, name_type));
@@ -539,8 +549,8 @@ static BOOL get_sam_group_entries(struct getent_state *ent)
        /* get the domain local groups if we are a member of a native win2k domain
           and are not using LDAP to get the groups */
           
-       if ( lp_security() != SEC_ADS && domain->native_mode 
-               && domain->primary )
+       if ( lp_security() != SEC_ADS && domain->native_mode 
+               && domain->primary) || domain->internal )
        {
                DEBUG(4,("get_sam_group_entries: Native Mode 2k domain; enumerating local groups as well\n"));
                
index 503b97899c418edd7e59d45c5985bacb1c25a192..36f5297efebf9f6a928c18e78c50ff97ba5be3a3 100644 (file)
@@ -5,6 +5,7 @@
 
    Copyright (C) Tim Potter 2000-2001,2003
    Copyright (C) Simo Sorce 2003
+   Copyright (C) Volker Lendecke 2004
    
    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
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include "includes.h"
 #include "winbindd.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
 
+static void
+add_member(const char *domain, const char *user,
+          char **members, int *num_members)
+{
+       fstring name;
 
-/* Query display info for a domain.  This returns enough information plus a
-   bit extra to give an overview of domain users for the User Manager
-   application. */
-static NTSTATUS query_user_list(struct winbindd_domain *domain,
-                              TALLOC_CTX *mem_ctx,
-                              uint32 *num_entries, 
-                              WINBIND_USERINFO **info)
+       fill_domain_username(name, domain, user);
+       safe_strcat(name, ",", sizeof(name)-1);
+       string_append(members, name);
+       *num_members += 1;
+}
+
+/**********************************************************************
+ Add member users resulting from sid. Expand if it is a domain group.
+**********************************************************************/
+
+static void
+add_expanded_sid(const DOM_SID *sid, char **members, int *num_members)
 {
-       SAM_ACCOUNT *sam_account = NULL;
+       DOM_SID dom_sid;
+       uint32 rid;
+       struct winbindd_domain *domain;
+       int i;
+
+       char *name = NULL;
+       enum SID_NAME_USE type;
+
+       uint32 num_names;
+       DOM_SID **sid_mem;
+       char **names;
+       uint32 *types;
+
        NTSTATUS result;
-       uint32 i;
 
-       DEBUG(3,("pdb: query_user_list\n"));
+       TALLOC_CTX *mem_ctx = talloc_init("add_expanded_sid");
 
-       if (NT_STATUS_IS_ERR(result = pdb_init_sam(&sam_account))) {
-               return result;
+       if (mem_ctx == NULL) {
+               DEBUG(1, ("talloc_init failed\n"));
+               return;
        }
 
-       i = 0;
-       *info = NULL;
-       
-       if (pdb_setsampwent(False)) {
-       
-               while (pdb_getsampwent(sam_account)) {
-               
-                       /* we return only nua accounts, or we will have duplicates */
-                       if (!idmap_check_sid_is_in_free_range(pdb_get_user_sid(sam_account))) {
-                               continue;
-                       }
-
-                       *info = talloc_realloc(mem_ctx, *info, (i + 1) * sizeof(WINBIND_USERINFO));
-                       if (!(*info)) {
-                               DEBUG(0,("query_user_list: out of memory!\n"));
-                               result = NT_STATUS_NO_MEMORY;
-                               break;
-                       }
-
-                       (*info)[i].user_sid = talloc(mem_ctx, sizeof(DOM_SID));
-                       (*info)[i].group_sid = talloc(mem_ctx, sizeof(DOM_SID));
-                       if (!((*info)[i].user_sid) || !((*info)[i].group_sid)) {
-                               DEBUG(0,("query_user_list: out of memory!\n"));
-                               result = NT_STATUS_NO_MEMORY;
-                               break;
-                       }
-                       sid_copy((*info)[i].user_sid, pdb_get_user_sid(sam_account));
-                       sid_copy((*info)[i].group_sid, pdb_get_group_sid(sam_account));
-
-                       (*info)[i].acct_name = talloc_strdup(mem_ctx, pdb_get_username(sam_account));
-                       (*info)[i].full_name = talloc_strdup(mem_ctx, pdb_get_fullname(sam_account));
-                       if (!((*info)[i].acct_name) || !((*info)[i].full_name)) {
-                               DEBUG(0,("query_user_list: out of memory!\n"));
-                               result = NT_STATUS_NO_MEMORY;
-                               break;
-                       }
-
-                       i++;
-
-                       if (NT_STATUS_IS_ERR(pdb_reset_sam(sam_account))) {
-                               result = NT_STATUS_UNSUCCESSFUL;
-                               break;
-                       }
+       sid_copy(&dom_sid, sid);
+       sid_split_rid(&dom_sid, &rid);
+
+       domain = find_domain_from_sid(&dom_sid);
+
+       if (domain == NULL) {
+               DEBUG(3, ("Could not find domain for sid %s\n",
+                         sid_string_static(sid)));
+               goto done;
+       }
+
+       result = domain->methods->sid_to_name(domain, mem_ctx, sid,
+                                             &name, &type);
+
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(3, ("sid_to_name failed for sid %s\n",
+                         sid_string_static(sid)));
+               goto done;
+       }
+
+       DEBUG(10, ("Found name %s, type %d\n", name, type));
+
+       if (type == SID_NAME_USER) {
+               add_member(domain->name, name, members, num_members);
+               goto done;
+       }
+
+       if (type != SID_NAME_DOM_GRP) {
+               DEBUG(10, ("Alias member %s neither user nor group, ignore\n",
+                          name));
+               goto done;
+       }
+
+       /* Expand the domain group */
+
+       result = domain->methods->lookup_groupmem(domain, mem_ctx,
+                                                 sid, &num_names,
+                                                 &sid_mem, &names,
+                                                 &types);
+
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(10, ("Could not lookup group members for %s: %s\n",
+                          name, nt_errstr(result)));
+               goto done;
+       }
+
+       for (i=0; i<num_names; i++) {
+               DEBUG(10, ("Adding group member SID %s\n",
+                          sid_string_static(sid_mem[i])));
+
+               if (types[i] != SID_NAME_USER) {
+                       DEBUG(1, ("Hmmm. Member %s of group %s is no user. "
+                                 "Ignoring.\n", names[i], name));
+                       continue;
                }
 
-               *num_entries = i;
-               result = NT_STATUS_OK;
-       
-       } else {
-               result = NT_STATUS_UNSUCCESSFUL;
+               add_member(domain->name, names[i], members, num_members);
        }
 
-       pdb_free_sam(&sam_account);
-       return result;
+ done:
+       talloc_destroy(mem_ctx);
+       return;
+}
+
+BOOL fill_passdb_alias_grmem(struct winbindd_domain *domain,
+                            DOM_SID *group_sid, 
+                            int *num_gr_mem, char **gr_mem, int *gr_mem_len)
+{
+       DOM_SID *members;
+       int i, num_members;
+
+       *num_gr_mem = 0;
+       *gr_mem = NULL;
+       *gr_mem_len = 0;
+
+       if (!pdb_enum_aliasmem(group_sid, &members, &num_members))
+               return True;
+
+       for (i=0; i<num_members; i++) {
+               add_expanded_sid(&members[i], gr_mem, num_gr_mem);
+       }
+
+       SAFE_FREE(members);
+
+       if (*gr_mem != NULL) {
+               int len;
+
+               /* We have at least one member, strip off the last "," */
+               len = strlen(*gr_mem);
+               (*gr_mem)[len-1] = '\0';
+               *gr_mem_len = len;
+       }
+
+       return True;
+}
+
+/* Query display info for a domain.  This returns enough information plus a
+   bit extra to give an overview of domain users for the User Manager
+   application. */
+static NTSTATUS query_user_list(struct winbindd_domain *domain,
+                              TALLOC_CTX *mem_ctx,
+                              uint32 *num_entries, 
+                              WINBIND_USERINFO **info)
+{
+       /* We don't have users */
+       *num_entries = 0;
+       *info = NULL;
+       return NT_STATUS_OK;
 }
 
 /* list all domain groups */
@@ -107,14 +185,10 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
                                uint32 *num_entries, 
                                struct acct_info **info)
 {
-       NTSTATUS result = NT_STATUS_OK;
-
-       DEBUG(3,("pdb: enum_dom_groups (group support not implemented)\n"));
-
+       /* We don't have domain groups */
        *num_entries = 0;
-       *info = 0;
-
-       return result;  
+       *info = NULL;
+       return NT_STATUS_OK;
 }
 
 /* List all domain groups */
@@ -124,14 +198,24 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
                                uint32 *num_entries, 
                                struct acct_info **info)
 {
-       NTSTATUS result = NT_STATUS_OK;
+       struct acct_info *talloced_info;
 
-       DEBUG(3,("pdb: enum_local_groups (group support not implemented)\n"));
+       /* Hmm. One billion aliases should be enough for a start */
 
-       *num_entries = 0;
-       *info = 0;
+       if (!pdb_enum_aliases(&domain->sid, 0, 1000000000,
+                             num_entries, info)) {
+               /* Nothing to report, just exit. */
+               return NT_STATUS_OK;
+       }
 
-       return result;  
+       talloced_info = (struct acct_info *)
+               talloc_memdup(mem_ctx, *info,
+                             *num_entries * sizeof(struct acct_info));
+
+       SAFE_FREE(*info);
+       *info = talloced_info;
+
+       return NT_STATUS_OK;
 }
 
 /* convert a single name to a sid in a domain */
@@ -141,23 +225,13 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
                            DOM_SID *sid,
                            enum SID_NAME_USE *type)
 {
-       SAM_ACCOUNT *sam_account = NULL;
-       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-
-       DEBUG(3,("pdb: name_to_sid name=%s (group support not implemented)\n", name));
-
-       if (NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) {
-               if (!pdb_getsampwnam(sam_account, name)) {
-                       result = NT_STATUS_UNSUCCESSFUL;
-               } else { /* it is a sam user */
-                       sid_copy(sid, pdb_get_user_sid(sam_account));
-                       *type = SID_NAME_USER;
-                       result = NT_STATUS_OK;
-               }
-       }
+       DEBUG(10, ("Finding name %s\n", name));
 
-       pdb_free_sam(&sam_account);
-       return result;  
+       if (!pdb_find_alias(name, sid))
+               return NT_STATUS_NONE_MAPPED;
+
+       *type = SID_NAME_ALIAS;
+       return NT_STATUS_OK;
 }
 
 /*
@@ -165,141 +239,56 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
 */
 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
                            TALLOC_CTX *mem_ctx,
-                           DOM_SID *sid,
+                           const DOM_SID *sid,
                            char **name,
                            enum SID_NAME_USE *type)
 {
-       SAM_ACCOUNT *sam_account = NULL;
-       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-       uint32 id;
+       struct acct_info info;
 
-       DEBUG(3,("pdb: sid_to_name sid=%s\n", sid_string_static(sid)));
+       DEBUG(10, ("Converting SID %s\n", sid_string_static(sid)));
 
-       if (NT_STATUS_IS_OK(sid_to_uid(sid, &id))) { /* this is a user */
+       if (!pdb_get_aliasinfo(sid, &info))
+               return NT_STATUS_NONE_MAPPED;
 
-               if (NT_STATUS_IS_ERR(result = pdb_init_sam(&sam_account))) {
-                       return result;
-               }
-       
-               if (!pdb_getsampwsid(sam_account, sid)) {
-                       pdb_free_sam(&sam_account);
-                       return NT_STATUS_UNSUCCESSFUL;
-               }
-       
-               *name = talloc_strdup(mem_ctx, pdb_get_username(sam_account));  
-               if (!(*name)) {
-                       DEBUG(0,("query_user: out of memory!\n"));
-                       pdb_free_sam(&sam_account);
-                       return NT_STATUS_NO_MEMORY;
-               }
+       *name = talloc_strdup(mem_ctx, info.acct_name);
+       *type = SID_NAME_ALIAS;
 
-               pdb_free_sam(&sam_account);
-               *type = SID_NAME_USER;
-               result = NT_STATUS_OK;
-
-       } else if (NT_STATUS_IS_OK(sid_to_gid(sid, &id))) { /* this is a group */
-               
-               DEBUG(3,("pdb: sid_to_name: group support not implemented\n"));
-               result = NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return result;
+       return NT_STATUS_OK;
 }
 
 /* Lookup user information from a rid or username. */
 static NTSTATUS query_user(struct winbindd_domain *domain, 
                           TALLOC_CTX *mem_ctx, 
-                          DOM_SID *user_sid, 
+                          const DOM_SID *user_sid,
                           WINBIND_USERINFO *user_info)
 {
-       SAM_ACCOUNT *sam_account = NULL;
-       NTSTATUS result;
-
-       DEBUG(3,("pdb: query_user sid=%s\n", sid_string_static(user_sid)));
-
-       if (NT_STATUS_IS_ERR(result = pdb_init_sam(&sam_account))) {
-               return result;
-       }
-       
-       if (!pdb_getsampwsid(sam_account, user_sid)) {
-               pdb_free_sam(&sam_account);
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       /* we return only nua accounts, or we will have duplicates */
-       if (!idmap_check_sid_is_in_free_range(user_sid)) {
-               pdb_free_sam(&sam_account);
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       user_info->user_sid = talloc(mem_ctx, sizeof(DOM_SID));
-       user_info->group_sid = talloc(mem_ctx, sizeof(DOM_SID));
-       if (!(user_info->user_sid) || !(user_info->group_sid)) {
-               DEBUG(0,("query_user: out of memory!\n"));
-               pdb_free_sam(&sam_account);
-               return NT_STATUS_NO_MEMORY;
-       }
-       sid_copy(user_info->user_sid, pdb_get_user_sid(sam_account));
-       sid_copy(user_info->group_sid, pdb_get_group_sid(sam_account));
-
-       user_info->acct_name = talloc_strdup(mem_ctx, pdb_get_username(sam_account));
-       user_info->full_name = talloc_strdup(mem_ctx, pdb_get_fullname(sam_account));
-       if (!(user_info->acct_name) || !(user_info->full_name)) {
-               DEBUG(0,("query_user: out of memory!\n"));
-               pdb_free_sam(&sam_account);
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       pdb_free_sam(&sam_account);
-       return NT_STATUS_OK;
-}                                   
+       return NT_STATUS_NO_SUCH_USER;
+}
 
 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
                                  TALLOC_CTX *mem_ctx,
-                                 DOM_SID *user_sid,
+                                 const DOM_SID *user_sid,
                                  uint32 *num_groups, DOM_SID ***user_gids)
 {
-       NTSTATUS result = NT_STATUS_OK;
-
-       DEBUG(3,("pdb: lookup_usergroups (group support not implemented)\n"));
-
-       num_groups = 0;
-       user_gids = 0;
-
-       return result;
+       return NT_STATUS_NO_SUCH_USER;
 }
 
 
 /* Lookup group membership given a rid.   */
 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
                                TALLOC_CTX *mem_ctx,
-                               DOM_SID *group_sid, uint32 *num_names, 
+                               const DOM_SID *group_sid, uint32 *num_names, 
                                DOM_SID ***sid_mem, char ***names, 
                                uint32 **name_types)
 {
-        NTSTATUS result = NT_STATUS_NOT_IMPLEMENTED;
-
-       DEBUG(3,("pdb: lookup_groupmem (group support not implemented)\n"));
-
-       num_names = 0;
-       sid_mem = 0;
-       names = 0;
-       name_types = 0;
-
-        return result;
+       return NT_STATUS_OK;
 }
 
 /* find the sequence number for a domain */
 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
 {
-       /* FIXME: we fake up the seq_num untill our passdb support it */
-       static uint32 seq_num;
-
-       DEBUG(3,("pdb: sequence_number\n"));
-
-       *seq = seq_num++;
-
+       *seq = 1;
        return NT_STATUS_OK;
 }
 
@@ -311,24 +300,14 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
                                char ***alt_names,
                                DOM_SID **dom_sids)
 {
-       NTSTATUS result = NT_STATUS_NOT_IMPLEMENTED;
-
-       DEBUG(3,("pdb: trusted_domains (todo!)\n"));
-
-       return result;
+       return NT_STATUS_OK;
 }
 
 /* find the domain sid for a domain */
 static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
 {
-       DEBUG(3,("pdb: domain_sid\n"));
-
-       if (strcmp(domain->name, lp_workgroup())) {
-               return NT_STATUS_INVALID_PARAMETER;
-       } else {
-               sid_copy(sid, get_global_sam_sid());
-               return NT_STATUS_OK;
-       }
+       sid_copy(sid, &domain->sid);
+       return NT_STATUS_OK;
 }
 
 /* find alternate names list for the domain 
index 9fbf47046d651e684d30f14f9083c207abddb24c..8ff6cfd2714b65bee6d9e1724587d78d0aac7d2a 100644 (file)
 
 enum winbindd_result winbindd_lookupsid(struct winbindd_cli_state *state)
 {
-       extern DOM_SID global_sid_Builtin;
        enum SID_NAME_USE type;
-       DOM_SID sid, tmp_sid;
-       uint32 rid;
+       DOM_SID sid;
        fstring name;
        fstring dom_name;
 
@@ -50,15 +48,6 @@ enum winbindd_result winbindd_lookupsid(struct winbindd_cli_state *state)
                return WINBINDD_ERROR;
        }
 
-       /* Don't look up BUILTIN sids */
-
-       sid_copy(&tmp_sid, &sid);
-       sid_split_rid(&tmp_sid, &rid);
-
-       if (sid_equal(&tmp_sid, &global_sid_Builtin)) {
-               return WINBINDD_ERROR;
-       }
-
        /* Lookup the sid */
 
        if (!winbindd_lookup_name_by_sid(&sid, dom_name, name, &type)) {
index 403ba399c88d1f6ec75dd3cdd86bd89a59d28ba1..6ac5c48285a9c17fcdb2a7c38a1e915b9cf434a9 100644 (file)
@@ -150,8 +150,9 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
        }
        
        /* set flags about native_mode, active_directory */
-          
-       set_dc_type_and_flags( domain );
+
+       if (!domain->internal)
+               set_dc_type_and_flags( domain );
        
        DEBUG(3,("add_trusted_domain: %s is an %s %s domain\n", domain->name,
                 domain->active_directory ? "ADS" : "NT4", 
@@ -303,6 +304,24 @@ BOOL init_domain_list(void)
 
        /* do an initial scan for trusted domains */
        add_trusted_domains(domain);
+
+       /* Add our local SAM domains */
+       {
+               DOM_SID sid;
+               extern struct winbindd_methods passdb_methods;
+               struct winbindd_domain *dom;
+
+               string_to_sid(&sid, "S-1-5-32");
+
+               dom = add_trusted_domain("BUILTIN", NULL, &passdb_methods,
+                                        &sid);
+               dom->internal = True;
+
+               dom = add_trusted_domain(get_global_sam_name(), NULL,
+                                        &passdb_methods,
+                                        get_global_sam_sid());
+               dom->internal = True;
+       }
        
        /* avoid rescanning this right away */
        last_trustdom_scan = time(NULL);