From bfa93735abe52fe07fde1b10ece0c31f5cf73ef8 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 8 Oct 2002 18:32:42 +0000 Subject: merge from APP_HEAD of winbindd's domain local group fix (This used to be commit 09c6f6329d6ae9327b7ef06de0ea78d24d805456) --- source3/nsswitch/winbindd.h | 8 +++- source3/nsswitch/winbindd_cache.c | 75 ++++++++++++++++++++++++++++++++++++- source3/nsswitch/winbindd_cm.c | 11 +++++- source3/nsswitch/winbindd_group.c | 57 ++++++++++++++++++++++++---- source3/nsswitch/winbindd_rpc.c | 60 +++++++++++++++++++++++++++++ source3/nsswitch/winbindd_util.c | 2 +- source3/rpc_client/cli_pipe.c | 16 ++++++++ source3/rpc_server/srv_spoolss_nt.c | 8 +--- source3/utils/status.c | 5 +++ 9 files changed, 222 insertions(+), 20 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" )); } diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 7e1289edff..71e422f251 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -983,6 +983,22 @@ char* get_pipe_name_from_index( const int pipe_index ) return pipe_names[pipe_index].client_pipe; } +/**************************************************************************** + Check to see if this pipe index points to one of + the pipes only supported by Win2k + ****************************************************************************/ + +BOOL is_win2k_pipe( const int pipe_idx ) +{ + switch ( pipe_idx ) + { + case PI_LSARPC_DS: + return True; + } + + return False; +} + /**************************************************************************** check the rpc bind acknowledge response ****************************************************************************/ diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 41ef599a3c..2851ed79c6 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -5603,23 +5603,17 @@ static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer) char *cmd = lp_addprinter_cmd(); char **qlines; pstring command; - pstring driverlocation; int numlines; int ret; int fd; fstring remote_machine = "%m"; - /* build driver path... only 9X architecture is needed for legacy reasons */ - slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0", - get_called_name()); - /* change \ to \\ for the shell */ - all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring)); standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine)); slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"", cmd, printer->info_2->printername, printer->info_2->sharename, printer->info_2->portname, printer->info_2->drivername, - printer->info_2->location, driverlocation, remote_machine); + printer->info_2->location, printer->info_2->comment, remote_machine); DEBUG(10,("Running [%s]\n", command)); ret = smbrun(command, &fd); diff --git a/source3/utils/status.c b/source3/utils/status.c index d87497f2fa..7c2381099d 100644 --- a/source3/utils/status.c +++ b/source3/utils/status.c @@ -175,6 +175,11 @@ static int profile_dump(void) d_printf("write_count: %u\n", profile_p->syscall_write_count); d_printf("write_time: %u\n", profile_p->syscall_write_time); d_printf("write_bytes: %u\n", profile_p->syscall_write_bytes); +#ifdef HAVE_SENDFILE + d_printf("sendfile_count: %u\n", profile_p->syscall_sendfile_count); + d_printf("sendfile_time: %u\n", profile_p->syscall_sendfile_time); + d_printf("sendfile_bytes: %u\n", profile_p->syscall_sendfile_bytes); +#endif d_printf("lseek_count: %u\n", profile_p->syscall_lseek_count); d_printf("lseek_time: %u\n", profile_p->syscall_lseek_time); d_printf("rename_count: %u\n", profile_p->syscall_rename_count); -- cgit