summaryrefslogtreecommitdiff
path: root/source3/nsswitch
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2002-10-08 18:32:42 +0000
committerGerald Carter <jerry@samba.org>2002-10-08 18:32:42 +0000
commitbfa93735abe52fe07fde1b10ece0c31f5cf73ef8 (patch)
tree8e0c4386faef9eb67bd38cf6230441df134f9088 /source3/nsswitch
parent641dd258adb2a3d265b89b2726d93fac3942e36a (diff)
downloadsamba-bfa93735abe52fe07fde1b10ece0c31f5cf73ef8.tar.gz
samba-bfa93735abe52fe07fde1b10ece0c31f5cf73ef8.tar.bz2
samba-bfa93735abe52fe07fde1b10ece0c31f5cf73ef8.zip
merge from APP_HEAD of winbindd's domain local group fix
(This used to be commit 09c6f6329d6ae9327b7ef06de0ea78d24d805456)
Diffstat (limited to 'source3/nsswitch')
-rw-r--r--source3/nsswitch/winbindd.h8
-rw-r--r--source3/nsswitch/winbindd_cache.c75
-rw-r--r--source3/nsswitch/winbindd_cm.c11
-rw-r--r--source3/nsswitch/winbindd_group.c57
-rw-r--r--source3/nsswitch/winbindd_rpc.c60
-rw-r--r--source3/nsswitch/winbindd_util.c2
6 files changed, 200 insertions, 13 deletions
diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h
index 4ca59ff1cc..e8bcf76bd3 100644
--- a/source3/nsswitch/winbindd.h
+++ b/source3/nsswitch/winbindd.h
@@ -123,12 +123,18 @@ struct winbindd_methods {
uint32 *num_entries,
WINBIND_USERINFO **info);
- /* get a list of groups */
+ /* get a list of domain groups */
NTSTATUS (*enum_dom_groups)(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32 *num_entries,
struct acct_info **info);
+ /* get a list of domain local groups */
+ NTSTATUS (*enum_local_groups)(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32 *num_entries,
+ struct acct_info **info);
+
/* convert one user or group name to a sid */
NTSTATUS (*name_to_sid)(struct winbindd_domain *domain,
const char *name,
diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c
index 060139af3e..8c02160e02 100644
--- a/source3/nsswitch/winbindd_cache.c
+++ b/source3/nsswitch/winbindd_cache.c
@@ -559,7 +559,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
if (!cache->tdb) goto do_query;
- centry = wcache_fetch(cache, domain, "GL/%s", domain->name);
+ centry = wcache_fetch(cache, domain, "GL/%s/domain", domain->name);
if (!centry) goto do_query;
*num_entries = centry_uint32(centry);
@@ -599,13 +599,83 @@ do_query:
centry_put_string(centry, (*info)[i].acct_desc);
centry_put_uint32(centry, (*info)[i].rid);
}
- centry_end(centry, "GL/%s", domain->name);
+ centry_end(centry, "GL/%s/domain", domain->name);
centry_free(centry);
skip_save:
return status;
}
+/* list all domain groups */
+static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32 *num_entries,
+ struct acct_info **info)
+{
+ struct winbind_cache *cache = get_cache(domain);
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+ int i;
+
+ if (!cache->tdb) goto do_query;
+
+ centry = wcache_fetch(cache, domain, "GL/%s/local", domain->name);
+ if (!centry) goto do_query;
+
+ *num_entries = centry_uint32(centry);
+
+ if (*num_entries == 0) goto do_cached;
+
+ (*info) = talloc(mem_ctx, sizeof(**info) * (*num_entries));
+ if (! (*info)) smb_panic("enum_dom_groups out of memory");
+ for (i=0; i<(*num_entries); i++) {
+ fstrcpy((*info)[i].acct_name, centry_string(centry, mem_ctx));
+ fstrcpy((*info)[i].acct_desc, centry_string(centry, mem_ctx));
+ (*info)[i].rid = centry_uint32(centry);
+ }
+
+do_cached:
+
+ /* If we are returning cached data and the domain controller
+ is down then we don't know whether the data is up to date
+ or not. Return NT_STATUS_MORE_PROCESSING_REQUIRED to
+ indicate this. */
+
+ if (wcache_server_down(domain)) {
+ DEBUG(10, ("query_user_list: returning cached user list and server was down\n"));
+ status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+ } else
+ status = centry->status;
+
+ centry_free(centry);
+ return status;
+
+do_query:
+ *num_entries = 0;
+ *info = NULL;
+
+ if (wcache_server_down(domain)) {
+ return NT_STATUS_SERVER_DISABLED;
+ }
+
+ status = cache->backend->enum_local_groups(domain, mem_ctx, num_entries, info);
+
+ /* and save it */
+ refresh_sequence_number(domain, True);
+ centry = centry_start(domain, status);
+ if (!centry) goto skip_save;
+ centry_put_uint32(centry, *num_entries);
+ for (i=0; i<(*num_entries); i++) {
+ centry_put_string(centry, (*info)[i].acct_name);
+ centry_put_string(centry, (*info)[i].acct_desc);
+ centry_put_uint32(centry, (*info)[i].rid);
+ }
+ centry_end(centry, "GL/%s/local", domain->name);
+ centry_free(centry);
+
+skip_save:
+ return status;
+}
/* convert a single name to a sid in a domain */
static NTSTATUS name_to_sid(struct winbindd_domain *domain,
@@ -906,6 +976,7 @@ struct winbindd_methods cache_methods = {
True,
query_user_list,
enum_dom_groups,
+ enum_local_groups,
name_to_sid,
sid_to_name,
query_user,
diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c
index def73edde6..cb1779f590 100644
--- a/source3/nsswitch/winbindd_cm.c
+++ b/source3/nsswitch/winbindd_cm.c
@@ -462,6 +462,15 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
if ( !cli_nt_session_open (new_conn->cli, pipe_index) ) {
result = NT_STATUS_PIPE_NOT_AVAILABLE;
+ /*
+ * only cache a failure if we are not trying to open the
+ * **win2k** specific lsarpc UUID. This could be an NT PDC
+ * and therefore a failure is normal. This should probably
+ * be abstracted to a check for 2k specific pipes and wondering
+ * if the PDC is an NT4 box. but since there is only one 2k
+ * specific UUID right now, i'm not going to bother. --jerry
+ */
+ if ( !is_win2k_pipe(pipe_index) )
add_failed_connection_entry(new_conn, result);
cli_shutdown(new_conn->cli);
return result;
@@ -563,7 +572,7 @@ BOOL cm_check_for_native_mode_win2k( const char *domain )
if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) )
{
- DEBUG(3, ("cm_check_for_native_mode_win2k: Could not open a connection to %s for PIPE_LSARPC (%s)\n",
+ DEBUG(5, ("cm_check_for_native_mode_win2k: Could not open a connection to %s for PIPE_LSARPC (%s)\n",
domain, nt_errstr(result)));
return False;
}
diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c
index abb6b9da75..dc22be1754 100644
--- a/source3/nsswitch/winbindd_group.c
+++ b/source3/nsswitch/winbindd_group.c
@@ -406,7 +406,7 @@ static BOOL get_sam_group_entries(struct getent_state *ent)
{
NTSTATUS status;
uint32 num_entries;
- struct acct_info *name_list = NULL;
+ struct acct_info *name_list = NULL, *tmp_name_list = NULL;
TALLOC_CTX *mem_ctx;
BOOL result = False;
struct acct_info *sam_grp_entries = NULL;
@@ -436,10 +436,9 @@ static BOOL get_sam_group_entries(struct getent_state *ent)
goto done;
}
- status = domain->methods->enum_dom_groups(domain,
- mem_ctx,
- &num_entries,
- &sam_grp_entries);
+ /* always get the domain global groups */
+
+ status = domain->methods->enum_dom_groups(domain, mem_ctx, &num_entries, &sam_grp_entries);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3, ("get_sam_group_entries: could not enumerate domain groups! Error: %s", nt_errstr(status)));
@@ -450,12 +449,54 @@ static BOOL get_sam_group_entries(struct getent_state *ent)
/* Copy entries into return buffer */
if (num_entries) {
- name_list = malloc(sizeof(struct acct_info) * num_entries);
- memcpy(name_list, sam_grp_entries,
- num_entries * sizeof(struct acct_info));
+ if ( !(name_list = malloc(sizeof(struct acct_info) * num_entries)) ) {
+ DEBUG(0,("get_sam_group_entries: Failed to malloc memory for %d domain groups!\n",
+ num_entries));
+ result = False;
+ goto done;
+ }
+ memcpy( name_list, sam_grp_entries, num_entries * sizeof(struct acct_info) );
}
ent->num_sam_entries = num_entries;
+
+ /* get the domain local groups if we are a member of
+ a native win2k domain */
+
+ if ( domain->native_mode )
+ {
+ DEBUG(4,("get_sam_group_entries: Native Mode 2k domain; enumerating local groups as well\n"));
+
+ status = domain->methods->enum_local_groups(domain, mem_ctx, &num_entries, &sam_grp_entries);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ DEBUG(3,("get_sam_group_entries: Failed to enumerate domain local groups!\n"));
+ num_entries = 0;
+ }
+ else
+ DEBUG(4,("get_sam_group_entries: Returned %d local groups\n", num_entries));
+
+ /* Copy entries into return buffer */
+
+ if ( num_entries ) {
+ if ( !(tmp_name_list = Realloc( name_list, sizeof(struct acct_info) * (ent->num_sam_entries+num_entries))) )
+ {
+ DEBUG(0,("get_sam_group_entries: Failed to realloc more memory for %d local groups!\n",
+ num_entries));
+ result = False;
+ SAFE_FREE( name_list );
+ goto done;
+ }
+
+ name_list = tmp_name_list;
+
+ memcpy( &name_list[ent->num_sam_entries], sam_grp_entries,
+ num_entries * sizeof(struct acct_info) );
+ }
+
+ ent->num_sam_entries += num_entries;
+ }
+
/* Fill in remaining fields */
diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c
index 047280e21e..d3a418027d 100644
--- a/source3/nsswitch/winbindd_rpc.c
+++ b/source3/nsswitch/winbindd_rpc.c
@@ -183,6 +183,65 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
return status;
}
+/* List all domain groups */
+
+static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32 *num_entries,
+ struct acct_info **info)
+{
+ uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
+ CLI_POLICY_HND *hnd;
+ POLICY_HND dom_pol;
+ NTSTATUS result;
+
+ *num_entries = 0;
+ *info = NULL;
+
+ if ( !(hnd = cm_get_sam_handle(domain->name)) )
+ return NT_STATUS_UNSUCCESSFUL;
+
+ if ( !NT_STATUS_IS_OK(result = cli_samr_open_domain( hnd->cli, mem_ctx, &hnd->pol,
+ des_access, &domain->sid, &dom_pol)) )
+ {
+ return result;
+ }
+
+ do {
+ struct acct_info *info2 = NULL;
+ uint32 count = 0, start = *num_entries;
+ TALLOC_CTX *mem_ctx2;
+
+ mem_ctx2 = talloc_init_named("enum_dom_local_groups[rpc]");
+
+ result = cli_samr_enum_als_groups( hnd->cli, mem_ctx2, &dom_pol,
+ &start, 0xFFFF, &info2, &count);
+
+ if ( !NT_STATUS_IS_OK(result)
+ && !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
+ {
+ talloc_destroy(mem_ctx2);
+ break;
+ }
+
+ (*info) = talloc_realloc(mem_ctx, *info,
+ sizeof(**info) * ((*num_entries) + count));
+ if (! *info) {
+ talloc_destroy(mem_ctx2);
+ cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
+ (*num_entries) += count;
+ talloc_destroy(mem_ctx2);
+ } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
+
+ cli_samr_close(hnd->cli, mem_ctx, &dom_pol);
+
+ return result;
+}
+
/* convert a single name to a sid in a domain */
static NTSTATUS name_to_sid(struct winbindd_domain *domain,
const char *name,
@@ -635,6 +694,7 @@ struct winbindd_methods msrpc_methods = {
False,
query_user_list,
enum_dom_groups,
+ enum_local_groups,
name_to_sid,
sid_to_name,
query_user,
diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c
index 005b1609b6..00354187aa 100644
--- a/source3/nsswitch/winbindd_util.c
+++ b/source3/nsswitch/winbindd_util.c
@@ -128,7 +128,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
if ( strequal( lp_workgroup(), domain_name) ) {
domain->native_mode = cm_check_for_native_mode_win2k( domain_name );
- DEBUG(5,("add_trusted_domain: %s is a %s mode domain\n", domain_name,
+ DEBUG(3,("add_trusted_domain: %s is a %s mode domain\n", domain_name,
domain->native_mode ? "native" : "mixed" ));
}