diff options
author | Gerald Carter <jerry@samba.org> | 2004-12-23 18:45:36 +0000 |
---|---|---|
committer | Gerald Carter <jerry@samba.org> | 2004-12-23 18:45:36 +0000 |
commit | b262548fec09659f46839dcf4c079176775f0871 (patch) | |
tree | 2f44f7f1cdce6d71d868626caea49fdfb82e1249 /source/nsswitch | |
parent | 8d91e07ef22ad3ed484b04bc4968380a24940696 (diff) | |
download | samba-b262548fec09659f46839dcf4c079176775f0871.tar.gz samba-b262548fec09659f46839dcf4c079176775f0871.tar.xz samba-b262548fec09659f46839dcf4c079176775f0871.zip |
r4348: syncing up for 3.0.11pre1
Diffstat (limited to 'source/nsswitch')
-rw-r--r-- | source/nsswitch/pam_winbind.c | 2 | ||||
-rw-r--r-- | source/nsswitch/winbindd.h | 4 | ||||
-rw-r--r-- | source/nsswitch/winbindd_cm.c | 584 | ||||
-rw-r--r-- | source/nsswitch/winbindd_group.c | 25 | ||||
-rw-r--r-- | source/nsswitch/winbindd_nss.h | 17 | ||||
-rw-r--r-- | source/nsswitch/winbindd_pam.c | 2 | ||||
-rw-r--r-- | source/nsswitch/winbindd_rpc.c | 23 | ||||
-rw-r--r-- | source/nsswitch/winbindd_util.c | 2 | ||||
-rw-r--r-- | source/nsswitch/winbindd_wins.c | 6 |
9 files changed, 468 insertions, 197 deletions
diff --git a/source/nsswitch/pam_winbind.c b/source/nsswitch/pam_winbind.c index 9d4f0954ceb..bfd8dd45ee5 100644 --- a/source/nsswitch/pam_winbind.c +++ b/source/nsswitch/pam_winbind.c @@ -189,7 +189,7 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type, return retval; default: /* we don't know anything about this return value */ - _pam_log(LOG_ERR, "internal module error (retval = %d, user = `%s'", + _pam_log(LOG_ERR, "internal module error (retval = %d, user = `%s')", retval, user); return retval; } diff --git a/source/nsswitch/winbindd.h b/source/nsswitch/winbindd.h index 477d2e0f682..22deaf82c6e 100644 --- a/source/nsswitch/winbindd.h +++ b/source/nsswitch/winbindd.h @@ -113,6 +113,10 @@ struct winbindd_domain { void *private; + /* A working DC */ + fstring dcname; + struct sockaddr_in dcaddr; + /* Sequence number stuff */ time_t last_seq_check; diff --git a/source/nsswitch/winbindd_cm.c b/source/nsswitch/winbindd_cm.c index 139efec2141..1843ec188b0 100644 --- a/source/nsswitch/winbindd_cm.c +++ b/source/nsswitch/winbindd_cm.c @@ -201,205 +201,469 @@ static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain, return True; } -/* Open a connction to the remote server, cache failures for 30 seconds */ +/************************************************************************ + Given a fd with a just-connected TCP connection to a DC, open a connection + to the pipe. +************************************************************************/ -static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const int pipe_index, - struct winbindd_cm_conn *new_conn) +static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, + const int sockfd, + const int pipe_index, + const char *controller, + struct cli_state **cli, + BOOL *retry) { - NTSTATUS result; - char *machine_password; - char *machine_krb5_principal, *ipc_username, *ipc_domain, *ipc_password; - struct in_addr dc_ip; - int i; - BOOL retry = True; + char *machine_password, *machine_krb5_principal; + char *ipc_username, *ipc_domain, *ipc_password; + struct ntuser_creds creds; - ZERO_STRUCT(dc_ip); + BOOL got_mutex; + BOOL add_failed_connection = True; - fstrcpy(new_conn->domain, domain->name); + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - if (!get_dc_name_via_netlogon(domain, new_conn->controller, &dc_ip)) { + struct sockaddr peeraddr; + socklen_t peeraddr_len; - /* connection failure cache has been moved inside of - get_dc_name so we can deal with half dead DC's --jerry */ + struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr; - if (!get_dc_name(domain->name, domain->alt_name[0] ? - domain->alt_name : NULL, - new_conn->controller, &dc_ip)) { - result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; - add_failed_connection_entry(domain->name, "", result); - return result; - } - } - - /* Initialise SMB connection */ - fstrcpy(new_conn->pipe_name, get_pipe_name_from_index(pipe_index)); - - /* grab stored passwords */ + machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL, + NULL); - machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); - - if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(), lp_realm()) == -1) { + if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(), + lp_realm()) == -1) { SAFE_FREE(machine_password); return NT_STATUS_NO_MEMORY; } cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password); - for (i = 0; retry && (i < 3); i++) { - BOOL got_mutex; - if (!(got_mutex = secrets_named_mutex(new_conn->controller, WINBIND_SERVER_MUTEX_WAIT_TIME))) { - DEBUG(0,("cm_open_connection: mutex grab failed for %s\n", new_conn->controller)); - result = NT_STATUS_POSSIBLE_DEADLOCK; - continue; + *retry = True; + + got_mutex = secrets_named_mutex(controller, + WINBIND_SERVER_MUTEX_WAIT_TIME); + + if (!got_mutex) { + DEBUG(0,("cm_open_connection: mutex grab failed for %s\n", + controller)); + result = NT_STATUS_POSSIBLE_DEADLOCK; + goto done; + } + + if ((*cli = cli_initialise(NULL)) == NULL) { + DEBUG(1, ("Could not cli_initialize\n")); + result = NT_STATUS_NO_MEMORY; + goto done; + } + + (*cli)->timeout = 10000; /* 10 seconds */ + (*cli)->fd = sockfd; + fstrcpy((*cli)->desthost, controller); + (*cli)->use_kerberos = True; + + peeraddr_len = sizeof(peeraddr); + + if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) || + (peeraddr_len != sizeof(struct sockaddr_in)) || + (peeraddr_in->sin_family != PF_INET)) + goto done; + + if (ntohs(peeraddr_in->sin_port) == 139) { + struct nmb_name calling; + struct nmb_name called; + + make_nmb_name(&calling, global_myname(), 0x0); + make_nmb_name(&called, "*SMBSERVER", 0x20); + + if (!cli_session_request(*cli, &calling, &called)) { + DEBUG(8, ("cli_session_request failed for %s\n", + controller)); + goto done; } - - new_conn->cli = NULL; - result = cli_start_connection(&new_conn->cli, global_myname(), - new_conn->controller, - &dc_ip, 0, Undefined, - CLI_FULL_CONNECTION_USE_KERBEROS, - &retry); + } - if (NT_STATUS_IS_OK(result)) { + cli_setup_signing_state(*cli, Undefined); - /* reset the error code */ - result = NT_STATUS_UNSUCCESSFUL; + if (!cli_negprot(*cli)) { + DEBUG(1, ("cli_negprot failed\n")); + cli_shutdown(*cli); + goto done; + } - /* Krb5 session */ + /* Krb5 session */ - if ((lp_security() == SEC_ADS) - && (new_conn->cli->protocol >= PROTOCOL_NT1 && new_conn->cli->capabilities & CAP_EXTENDED_SECURITY)) { - ADS_STATUS ads_status; - new_conn->cli->use_kerberos = True; - DEBUG(5, ("connecting to %s from %s with kerberos principal [%s]\n", - new_conn->controller, global_myname(), machine_krb5_principal)); - - ads_status = cli_session_setup_spnego(new_conn->cli, machine_krb5_principal, - machine_password, - lp_workgroup()); - if (!ADS_ERR_OK(ads_status)) { - DEBUG(4,("failed kerberos session setup with %s\n", ads_errstr(ads_status))); - result = ads_ntstatus(ads_status); - } else { - result = NT_STATUS_OK; - } - } - new_conn->cli->use_kerberos = False; - - /* only do this is we have a username/password for thr IPC$ connection */ - - if ( !NT_STATUS_IS_OK(result) - && new_conn->cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE - && strlen(ipc_username) ) - { - DEBUG(5, ("connecting to %s from %s with username [%s]\\[%s]\n", - new_conn->controller, global_myname(), ipc_domain, ipc_username)); - - result = NT_STATUS_OK; - - if (!cli_session_setup(new_conn->cli, ipc_username, - ipc_password, strlen(ipc_password)+1, - ipc_password, strlen(ipc_password)+1, - ipc_domain)) { - result = cli_nt_error(new_conn->cli); - DEBUG(4,("failed authenticated session setup with %s\n", nt_errstr(result))); - if (NT_STATUS_IS_OK(result)) - result = NT_STATUS_UNSUCCESSFUL; - } - } - - /* anonymous is all that is left if we get to here */ - - if (!NT_STATUS_IS_OK(result)) { - - DEBUG(5, ("anonymous connection attempt to %s from %s\n", - new_conn->controller, global_myname())); - - result = NT_STATUS_OK; - - if (!cli_session_setup(new_conn->cli, "", NULL, 0, NULL, 0, "")) - { - result = cli_nt_error(new_conn->cli); - DEBUG(4,("failed anonymous session setup with %s\n", nt_errstr(result))); - if (NT_STATUS_IS_OK(result)) - result = NT_STATUS_UNSUCCESSFUL; - } - - } + if ((lp_security() == SEC_ADS) + && ((*cli)->protocol >= PROTOCOL_NT1 && + (*cli)->capabilities & CAP_EXTENDED_SECURITY)) { + + ADS_STATUS ads_status; + (*cli)->use_kerberos = True; + DEBUG(5, ("connecting to %s from %s with kerberos principal " + "[%s]\n", controller, global_myname(), + machine_krb5_principal)); + + ads_status = cli_session_setup_spnego(*cli, + machine_krb5_principal, + machine_password, + lp_workgroup()); + + if (!ADS_ERR_OK(ads_status)) + DEBUG(4,("failed kerberos session setup with %s\n", + ads_errstr(ads_status))); + + result = ads_ntstatus(ads_status); + } - if (NT_STATUS_IS_OK(result) && !cli_send_tconX(new_conn->cli, "IPC$", "IPC", - "", 0)) { - result = cli_nt_error(new_conn->cli); - DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result))); - cli_shutdown(new_conn->cli); - if (NT_STATUS_IS_OK(result)) { - result = NT_STATUS_UNSUCCESSFUL; - } - } - } + if (NT_STATUS_IS_OK(result)) + goto session_setup_done; - if (NT_STATUS_IS_OK(result)) { - struct ntuser_creds creds; - init_creds(&creds, ipc_username, ipc_domain, ipc_password); - cli_init_creds(new_conn->cli, &creds); + /* Fall back to non-kerberos session setup */ + + (*cli)->use_kerberos = False; + + if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) && + (strlen(ipc_username) > 0)) { + + /* Only try authenticated if we have a username */ + + DEBUG(5, ("connecting to %s from %s with username " + "[%s]\\[%s]\n", controller, global_myname(), + ipc_domain, ipc_username)); + + if (cli_session_setup(*cli, ipc_username, + ipc_password, strlen(ipc_password)+1, + ipc_password, strlen(ipc_password)+1, + ipc_domain)) { + DEBUG(5, ("authenticated session setup failed\n")); + goto session_setup_done; } + } + + /* Fall back to anonymous connection, this might fail later */ + + if (cli_session_setup(*cli, "", NULL, 0, NULL, 0, "")) { + DEBUG(5, ("Connected anonymously\n")); + goto session_setup_done; + } - if (got_mutex) - secrets_named_mutex_release(new_conn->controller); + result = cli_nt_error(*cli); + + if (NT_STATUS_IS_OK(result)) + result = NT_STATUS_UNSUCCESSFUL; + + /* We can't session setup */ + + goto done; + + session_setup_done: + + if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) { + + result = cli_nt_error(*cli); + + DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result))); if (NT_STATUS_IS_OK(result)) - break; + result = NT_STATUS_UNSUCCESSFUL; + + cli_shutdown(*cli); + goto done; } - /* try and use schannel if possible, but continue anyway if it - failed. This allows existing setups to continue working, - while solving the win2003 '100 user' limit for systems that - are joined properly. - - Only do this for our own domain or perhaps a trusted domain - if we are on a Samba DC */ + init_creds(&creds, ipc_username, ipc_domain, ipc_password); + cli_init_creds(*cli, &creds); - if (NT_STATUS_IS_OK(result) && (domain->primary || IS_DC) ) { - NTSTATUS status = setup_schannel( new_conn->cli, domain->name ); + secrets_named_mutex_release(controller); + got_mutex = False; + *retry = False; + + if (domain->primary || IS_DC) { + NTSTATUS status = setup_schannel( *cli, domain->name ); if (!NT_STATUS_IS_OK(status)) { - DEBUG(3,("schannel refused - continuing without schannel (%s)\n", - nt_errstr(status))); + DEBUG(3,("schannel refused - continuing without " + "schannel (%s)\n", nt_errstr(status))); } } + /* set the domain if empty; needed for schannel connections */ + if ( !*(*cli)->domain ) + fstrcpy( (*cli)->domain, domain->name ); + + if ( !cli_nt_session_open (*cli, pipe_index) ) { + + result = NT_STATUS_PIPE_NOT_AVAILABLE; + + /* This might be a NT4 DC */ + if ( is_win2k_pipe(pipe_index) ) + add_failed_connection = False; + + cli_shutdown(*cli); + goto done; + } + + result = NT_STATUS_OK; + add_failed_connection = False; + + done: + if (got_mutex) + secrets_named_mutex_release(controller); + + SAFE_FREE(machine_password); + SAFE_FREE(machine_krb5_principal); SAFE_FREE(ipc_username); SAFE_FREE(ipc_domain); SAFE_FREE(ipc_password); - SAFE_FREE(machine_password); - SAFE_FREE(machine_krb5_principal); - if (!NT_STATUS_IS_OK(result)) { - add_failed_connection_entry(domain->name, new_conn->controller, result); - return result; + if (add_failed_connection) + add_failed_connection_entry(domain->name, controller, result); + + return result; +} + +struct dc_name_ip { + fstring name; + struct in_addr ip; +}; + +static BOOL add_one_dc_unique(TALLOC_CTX *mem_ctx, const char *domain_name, + const char *dcname, struct in_addr ip, + struct dc_name_ip **dcs, int *num) +{ + if (!NT_STATUS_IS_OK(check_negative_conn_cache(domain_name, dcname))) + return False; + + *dcs = TALLOC_REALLOC_ARRAY(mem_ctx, *dcs, struct dc_name_ip, (*num)+1); + + if (*dcs == NULL) + return False; + + fstrcpy((*dcs)[*num].name, dcname); + (*dcs)[*num].ip = ip; + *num += 1; + return True; +} + +static BOOL add_string_to_array(TALLOC_CTX *mem_ctx, + const char *str, char ***array, int *num) +{ + char *dup_str = talloc_strdup(mem_ctx, str); + + *array = TALLOC_REALLOC_ARRAY(mem_ctx, *array, char *, (*num)+1); + + if ((*array == NULL) || (dup_str == NULL)) + return False; + + (*array)[*num] = dup_str; + *num += 1; + return True; +} + +static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx, + struct in_addr ip, uint16 port, + struct sockaddr_in **addrs, int *num) +{ + *addrs = TALLOC_REALLOC_ARRAY(mem_ctx, *addrs, struct sockaddr_in, (*num)+1); + + if (*addrs == NULL) + return False; + + (*addrs)[*num].sin_family = PF_INET; + putip((char *)&((*addrs)[*num].sin_addr), (char *)&ip); + (*addrs)[*num].sin_port = htons(port); + + *num += 1; + return True; +} + +static BOOL get_dcs_1c(TALLOC_CTX *mem_ctx, + const struct winbindd_domain *domain, + struct dc_name_ip **dcs, int *num_dcs) +{ + struct ip_service *iplist = NULL; + int i, num = 0; + + if (!internal_resolve_name(domain->name, 0x1c, &iplist, &num, + lp_name_resolve_order())) + return False; + + /* Now try to find the server names of at least one IP address, hosts + * not replying are cached as such */ + + for (i=0; i<num; i++) { + + fstring dcname; + + if (!name_status_find(domain->name, 0x1c, 0x20, iplist[i].ip, + dcname)) + continue; + + if (add_one_dc_unique(mem_ctx, domain->name, dcname, + iplist[i].ip, dcs, num_dcs)) { + /* One DC responded, so we assume that he will also + work on 139/445 */ + break; + } } - - /* set the domain if empty; needed for schannel connections */ - if ( !*new_conn->cli->domain ) - fstrcpy( new_conn->cli->domain, domain->name ); - - - 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(domain->name, new_conn->controller, result); - cli_shutdown(new_conn->cli); - return result; + + return True; +} + +static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain, + struct dc_name_ip **dcs, int *num_dcs) +{ + fstring dcname; + struct in_addr ip; + BOOL is_our_domain; + + const char *p; + + is_our_domain = strequal(domain->name, lp_workgroup()); + + if (!is_our_domain && get_dc_name_via_netlogon(domain, dcname, &ip) && + add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs)) + return True; + + if (!is_our_domain) { + /* NETLOGON to our own domain could not give us a DC name + * (which is an error), fall back to looking up domain#1c */ + return get_dcs_1c(mem_ctx, domain, dcs, num_dcs); } - return NT_STATUS_OK; + if (must_use_pdc(domain->name) && get_pdc_ip(domain->name, &ip)) { + + if (!name_status_find(domain->name, 0x1b, 0x20, ip, dcname)) + return False; + + if (add_one_dc_unique(mem_ctx, domain->name, + dcname, ip, dcs, num_dcs)) + return True; + } + + p = lp_passwordserver(); + + if (*p == 0) + return get_dcs_1c(mem_ctx, domain, dcs, num_dcs); + + while (next_token(&p, dcname, LIST_SEP, sizeof(dcname))) { + + if (strequal(dcname, "*")) { + get_dcs_1c(mem_ctx, domain, dcs, num_dcs); + continue; + } + + if (!resolve_name(dcname, &ip, 0x20)) + continue; + + add_one_dc_unique(mem_ctx, domain->name, dcname, ip, + dcs, num_dcs); + } + + return True; +} + +static BOOL find_new_dc(TALLOC_CTX *mem_ctx, + const struct winbindd_domain *domain, + fstring dcname, struct sockaddr_in *addr, int *fd) +{ + struct dc_name_ip *dcs = NULL; + int num_dcs = 0; + + char **dcnames = NULL; + int num_dcnames = 0; + + struct sockaddr_in *addrs = NULL; + int num_addrs = 0; + + int i, fd_index; + + if (!get_dcs(mem_ctx, domain, &dcs, &num_dcs) || (num_dcs == 0)) + return False; + + for (i=0; i<num_dcs; i++) { + + add_string_to_array(mem_ctx, dcs[i].name, + &dcnames, &num_dcnames); + add_sockaddr_to_array(mem_ctx, dcs[i].ip, 445, + &addrs, &num_addrs); + + add_string_to_array(mem_ctx, dcs[i].name, + &dcnames, &num_dcnames); + add_sockaddr_to_array(mem_ctx, dcs[i].ip, 139, + &addrs, &num_addrs); + } + + if ((num_dcnames == 0) || (num_dcnames != num_addrs)) + return False; + + if (!open_any_socket_out(addrs, num_addrs, 10000, &fd_index, fd)) { + for (i=0; i<num_dcs; i++) { + add_failed_connection_entry(domain->name, + dcs[i].name, + NT_STATUS_UNSUCCESSFUL); + } + return False; + } + + fstrcpy(dcname, dcnames[fd_index]); + *addr = addrs[fd_index]; + + return True; +} + +static NTSTATUS cm_open_connection(struct winbindd_domain *domain, + const int pipe_index, + struct winbindd_cm_conn *new_conn) +{ + TALLOC_CTX *mem_ctx; + NTSTATUS result; + + int retries; + + if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) + return NT_STATUS_NO_MEMORY; + + for (retries = 0; retries < 3; retries++) { + + int fd = -1; + BOOL retry; + + result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; + + if ((strlen(domain->dcname) > 0) && + NT_STATUS_IS_OK(check_negative_conn_cache(domain->name, + domain->dcname))) { + int dummy; + if (!open_any_socket_out(&domain->dcaddr, 1, 10000, + &dummy, &fd)) { + fd = -1; + } + } + + if ((fd == -1) && + !find_new_dc(mem_ctx, domain, domain->dcname, + &domain->dcaddr, &fd)) + break; + + new_conn->cli = NULL; + + result = cm_prepare_connection(domain, fd, pipe_index, + domain->dcname, + &new_conn->cli, &retry); + + if (NT_STATUS_IS_OK(result)) { + fstrcpy(new_conn->domain, domain->name); + /* Initialise SMB connection */ + fstrcpy(new_conn->pipe_name, + get_pipe_name_from_index(pipe_index)); + break; + } + + if (!retry) + break; + } + + talloc_destroy(mem_ctx); + return result; } /************************************************************************ diff --git a/source/nsswitch/winbindd_group.c b/source/nsswitch/winbindd_group.c index 8ece6f114a8..d64c2e4a19c 100644 --- a/source/nsswitch/winbindd_group.c +++ b/source/nsswitch/winbindd_group.c @@ -932,7 +932,7 @@ static void add_local_gids_from_sid(DOM_SID *sid, gid_t **gids, int *num) /* Add nested group memberships */ - if (!pdb_enum_alias_memberships(sid, &aliases, &num_aliases)) + if (!pdb_enum_alias_memberships(sid, 1, &aliases, &num_aliases)) return; for (j=0; j<num_aliases; j++) { @@ -1029,7 +1029,7 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) if (!winbindd_lookup_sid_by_name(domain, domain->name, name_user, &user_sid, &name_type)) { - DEBUG(1, ("user '%s' does not exist\n", name_user)); + DEBUG(4, ("user '%s' does not exist\n", name_user)); goto done; } @@ -1085,9 +1085,6 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) add_gids_from_group_sid(&info3->other_sids[i].sid, &gid_list, &num_gids); - - if (gid_list == NULL) - goto done; } for (i = 0; i < info3->num_groups2; i++) { @@ -1099,9 +1096,6 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) add_gids_from_group_sid(&group_sid, &gid_list, &num_gids); - - if (gid_list == NULL) - goto done; } SAFE_FREE(info3); @@ -1119,12 +1113,13 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) for (i = 0; i < num_groups; i++) { add_gids_from_group_sid(user_grpsids[i], &gid_list, &num_gids); - - if (gid_list == NULL) - goto done; } } + /* We want at least one group... */ + if (gid_list == NULL) + goto done; + remove_duplicate_gids( &num_gids, gid_list ); /* Send data back to client */ @@ -1142,7 +1137,7 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) return result; } -static void add_sid_to_array_unique(TALLOC_CTX *mem_ctx, const DOM_SID *sid, +static void add_sid_to_parray_unique(TALLOC_CTX *mem_ctx, const DOM_SID *sid, DOM_SID ***sids, int *num_sids) { int i; @@ -1170,15 +1165,15 @@ static void add_local_sids_from_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, DOM_SID *aliases = NULL; int i, num_aliases = 0; - if (!pdb_enum_alias_memberships(sid, &aliases, &num_aliases)) + if (!pdb_enum_alias_memberships(sid, 1, &aliases, &num_aliases)) return; if (num_aliases == 0) return; for (i=0; i<num_aliases; i++) - add_sid_to_array_unique(mem_ctx, &aliases[i], user_grpsids, - num_groups); + add_sid_to_parray_unique(mem_ctx, &aliases[i], user_grpsids, + num_groups); SAFE_FREE(aliases); diff --git a/source/nsswitch/winbindd_nss.h b/source/nsswitch/winbindd_nss.h index 9a99bad9d74..88e3254d24a 100644 --- a/source/nsswitch/winbindd_nss.h +++ b/source/nsswitch/winbindd_nss.h @@ -5,20 +5,9 @@ Copyright (C) Tim Potter 2000 - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + You are free to use this interface definition in any way you see + fit, including without restriction, using this header in your own + products. You do not need to give any attribution. */ #ifndef SAFE_FREE diff --git a/source/nsswitch/winbindd_pam.c b/source/nsswitch/winbindd_pam.c index f7d3ac5aa41..cb44ec98d76 100644 --- a/source/nsswitch/winbindd_pam.c +++ b/source/nsswitch/winbindd_pam.c @@ -612,7 +612,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) memcpy(state->response.data.auth.user_session_key, info3.user_sess_key, sizeof(state->response.data.auth.user_session_key) /* 16 */); } if (state->request.flags & WBFLAG_PAM_LMKEY) { - memcpy(state->response.data.auth.first_8_lm_hash, info3.padding, sizeof(state->response.data.auth.first_8_lm_hash) /* 8 */); + memcpy(state->response.data.auth.first_8_lm_hash, info3.lm_sess_key, sizeof(state->response.data.auth.first_8_lm_hash) /* 8 */); } } diff --git a/source/nsswitch/winbindd_rpc.c b/source/nsswitch/winbindd_rpc.c index de7f2ff76fb..e6edb70f079 100644 --- a/source/nsswitch/winbindd_rpc.c +++ b/source/nsswitch/winbindd_rpc.c @@ -807,10 +807,10 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) TALLOC_CTX *mem_ctx; CLI_POLICY_HND *hnd; SAM_UNK_CTR ctr; - uint16 switch_value = 2; NTSTATUS result; POLICY_HND dom_pol; BOOL got_dom_pol = False; + BOOL got_seq_num = False; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; int retry; @@ -856,10 +856,27 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) /* Query domain info */ result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol, - switch_value, &ctr); + 8, &ctr); if (NT_STATUS_IS_OK(result)) { - *seq = ctr.info.inf2.seq_num; + *seq = ctr.info.inf8.seq_num.low; + got_seq_num = True; + goto seq_num; + } + + /* retry with info-level 2 in case the dc does not support info-level 8 + * (like all older samba2 and samba3 dc's - Guenther */ + + result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol, + 2, &ctr); + + if (NT_STATUS_IS_OK(result)) { + *seq = ctr.info.inf2.seq_num.low; + got_seq_num = True; + } + + seq_num: + if (got_seq_num) { DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)*seq)); } else { DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n", diff --git a/source/nsswitch/winbindd_util.c b/source/nsswitch/winbindd_util.c index 7cbcba12453..1f727dd18d5 100644 --- a/source/nsswitch/winbindd_util.c +++ b/source/nsswitch/winbindd_util.c @@ -641,7 +641,7 @@ BOOL parse_domain_user(const char *domuser, fstring domain, fstring user) */ void fill_domain_username(fstring name, const char *domain, const char *user) { - strlower_m( name ); + strlower_m( user ); if (assume_domain(domain)) { strlcpy(name, user, sizeof(fstring)); diff --git a/source/nsswitch/winbindd_wins.c b/source/nsswitch/winbindd_wins.c index 07c383e0e62..f199ebcb437 100644 --- a/source/nsswitch/winbindd_wins.c +++ b/source/nsswitch/winbindd_wins.c @@ -88,7 +88,7 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count) { int fd; struct ip_service *ret = NULL; - struct in_addr *return_ip; + struct in_addr *return_ip = NULL; int j, i, flags = 0; *count = 0; @@ -121,7 +121,9 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count) j--) { struct in_addr *bcast = iface_n_bcast(j); return_ip = name_query(fd,name,0x20,True,True,*bcast,count, &flags, NULL); - if (return_ip) break; + if (return_ip) { + break; + } } close(fd); |