From d30e816b17d547f91909e1c020e662938d41d0b0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 24 Nov 2011 10:58:52 +0100 Subject: [PATCH 1/8] s3: user_domain is not used in wb_getpwsid --- source3/winbindd/wb_getpwsid.c | 7 ------- 1 files changed, 0 insertions(+), 7 deletions(-) diff --git a/source3/winbindd/wb_getpwsid.c b/source3/winbindd/wb_getpwsid.c index 3c942f0..5bd384b 100644 --- a/source3/winbindd/wb_getpwsid.c +++ b/source3/winbindd/wb_getpwsid.c @@ -23,7 +23,6 @@ #include "../libcli/security/security.h" struct wb_getpwsid_state { - struct winbindd_domain *user_domain; struct tevent_context *ev; struct dom_sid sid; struct wbint_userinfo *userinfo; @@ -50,12 +49,6 @@ struct tevent_req *wb_getpwsid_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->pw = pw; - state->user_domain = find_domain_from_sid_noinit(user_sid); - if (state->user_domain == NULL) { - tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER); - return tevent_req_post(req, ev); - } - subreq = wb_queryuser_send(state, ev, &state->sid); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); -- 1.7.5.4 From a488a72b86666e620a7b7b83bbfdb0dd58d9b53d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 24 Nov 2011 11:12:11 +0100 Subject: [PATCH 2/8] s3: Do wb_queryuser out of the netsamlogon_cache if possible --- source3/winbindd/wb_queryuser.c | 33 ++++++++++++++++++++++++++++----- 1 files changed, 28 insertions(+), 5 deletions(-) diff --git a/source3/winbindd/wb_queryuser.c b/source3/winbindd/wb_queryuser.c index 33416b9..e356116 100644 --- a/source3/winbindd/wb_queryuser.c +++ b/source3/winbindd/wb_queryuser.c @@ -36,6 +36,7 @@ struct tevent_req *wb_queryuser_send(TALLOC_CTX *mem_ctx, struct tevent_req *req, *subreq; struct wb_queryuser_state *state; struct winbindd_domain *domain; + struct netr_SamInfo3 *info3; req = tevent_req_create(mem_ctx, &state, struct wb_queryuser_state); if (req == NULL) { @@ -43,14 +44,36 @@ struct tevent_req *wb_queryuser_send(TALLOC_CTX *mem_ctx, } sid_copy(&state->sid, user_sid); - domain = find_domain_from_sid_noinit(user_sid); - if (domain == NULL) { - tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER); + state->info = talloc(state, struct wbint_userinfo); + if (tevent_req_nomem(state->info, req)) { return tevent_req_post(req, ev); } - state->info = talloc(state, struct wbint_userinfo); - if (tevent_req_nomem(state->info, req)) { + info3 = netsamlogon_cache_get(talloc_tos(), user_sid); + if (info3 != NULL) { + struct dom_sid domain_sid; + sid_copy(&domain_sid, user_sid); + sid_split_rid(&domain_sid, NULL); + + sid_copy(&state->info->user_sid, user_sid); + sid_compose(&state->info->group_sid, &domain_sid, + info3->base.primary_gid); + state->info->acct_name = talloc_strdup( + state->info, info3->base.account_name.string); + state->info->full_name = talloc_strdup( + state->info, info3->base.full_name.string); + state->info->homedir = talloc_strdup( + state->info, ""); + state->info->shell = talloc_strdup( + state->info, "/bin/false"); + TALLOC_FREE(info3); + tevent_req_done(req); + return tevent_req_post(req, ev); + } + + domain = find_domain_from_sid_noinit(user_sid); + if (domain == NULL) { + tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER); return tevent_req_post(req, ev); } -- 1.7.5.4 From 7cb65798afad83102fcd8b61b659e9645596191c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 24 Nov 2011 11:31:01 +0100 Subject: [PATCH 3/8] s3: Move domain lookup to wb_lookupusergroups --- source3/winbindd/wb_gettoken.c | 18 +----------------- source3/winbindd/wb_lookupusergroups.c | 20 ++++++++++++++++++-- source3/winbindd/winbindd_getuserdomgroups.c | 11 +---------- source3/winbindd/winbindd_proto.h | 1 - 4 files changed, 20 insertions(+), 30 deletions(-) diff --git a/source3/winbindd/wb_gettoken.c b/source3/winbindd/wb_gettoken.c index aaaffa0..c2f459a 100644 --- a/source3/winbindd/wb_gettoken.c +++ b/source3/winbindd/wb_gettoken.c @@ -45,7 +45,6 @@ struct tevent_req *wb_gettoken_send(TALLOC_CTX *mem_ctx, { struct tevent_req *req, *subreq; struct wb_gettoken_state *state; - struct winbindd_domain *domain; req = tevent_req_create(mem_ctx, &state, struct wb_gettoken_state); if (req == NULL) { @@ -54,22 +53,7 @@ struct tevent_req *wb_gettoken_send(TALLOC_CTX *mem_ctx, sid_copy(&state->usersid, sid); state->ev = ev; - domain = find_domain_from_sid_noinit(sid); - if (domain == NULL) { - DEBUG(5, ("Could not find domain from SID %s\n", - sid_string_dbg(sid))); - tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER); - return tevent_req_post(req, ev); - } - - if (lp_winbind_trusted_domains_only() && domain->primary) { - DEBUG(7, ("wb_gettoken: My domain -- rejecting getgroups() " - "for %s.\n", sid_string_tos(sid))); - tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER); - return tevent_req_post(req, ev); - } - - subreq = wb_lookupusergroups_send(state, ev, domain, &state->usersid); + subreq = wb_lookupusergroups_send(state, ev, &state->usersid); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } diff --git a/source3/winbindd/wb_lookupusergroups.c b/source3/winbindd/wb_lookupusergroups.c index aeffc17..e07f58d 100644 --- a/source3/winbindd/wb_lookupusergroups.c +++ b/source3/winbindd/wb_lookupusergroups.c @@ -32,11 +32,11 @@ static void wb_lookupusergroups_done(struct tevent_req *subreq); struct tevent_req *wb_lookupusergroups_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct winbindd_domain *domain, const struct dom_sid *sid) { struct tevent_req *req, *subreq; struct wb_lookupusergroups_state *state; + struct winbindd_domain *domain; req = tevent_req_create(mem_ctx, &state, struct wb_lookupusergroups_state); @@ -45,8 +45,24 @@ struct tevent_req *wb_lookupusergroups_send(TALLOC_CTX *mem_ctx, } sid_copy(&state->sid, sid); + domain = find_domain_from_sid_noinit(&state->sid); + if (domain == NULL) { + DEBUG(1, ("could not find domain entry for sid %s\n", + sid_string_tos(sid))); + tevent_req_nterror(req, NT_STATUS_NO_SUCH_DOMAIN); + return tevent_req_post(req, ev); + } + + if (lp_winbind_trusted_domains_only() && domain->primary) { + DEBUG(7, ("wb_gettoken: My domain -- rejecting getgroups() " + "for %s.\n", sid_string_tos(sid))); + tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER); + return tevent_req_post(req, ev); + } + subreq = dcerpc_wbint_LookupUserGroups_send( - state, ev, dom_child_handle(domain), &state->sid, &state->sids); + state, ev, dom_child_handle(domain), &state->sid, + &state->sids); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } diff --git a/source3/winbindd/winbindd_getuserdomgroups.c b/source3/winbindd/winbindd_getuserdomgroups.c index 55094bb..d0c7ac1 100644 --- a/source3/winbindd/winbindd_getuserdomgroups.c +++ b/source3/winbindd/winbindd_getuserdomgroups.c @@ -36,7 +36,6 @@ struct tevent_req *winbindd_getuserdomgroups_send(TALLOC_CTX *mem_ctx, { struct tevent_req *req, *subreq; struct winbindd_getuserdomgroups_state *state; - struct winbindd_domain *domain; req = tevent_req_create(mem_ctx, &state, struct winbindd_getuserdomgroups_state); @@ -56,15 +55,7 @@ struct tevent_req *winbindd_getuserdomgroups_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } - domain = find_domain_from_sid_noinit(&state->sid); - if (domain == NULL) { - DEBUG(1,("could not find domain entry for sid %s\n", - request->data.sid)); - tevent_req_nterror(req, NT_STATUS_NO_SUCH_DOMAIN); - return tevent_req_post(req, ev); - } - - subreq = wb_lookupusergroups_send(state, ev, domain, &state->sid); + subreq = wb_lookupusergroups_send(state, ev, &state->sid); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index ab61223..4a05152 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -598,7 +598,6 @@ NTSTATUS winbindd_getsidaliases_recv(struct tevent_req *req, struct winbindd_response *response); struct tevent_req *wb_lookupusergroups_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct winbindd_domain *domain, const struct dom_sid *sid); NTSTATUS wb_lookupusergroups_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, int *num_sids, struct dom_sid **sids); -- 1.7.5.4 From 5288a6ffd5d7cc8a66d06bc70e9b99a5d4f3095d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 24 Nov 2011 11:38:42 +0100 Subject: [PATCH 4/8] s3: Attempt lookup_usergroups_cached in wb_lookupusergroups --- source3/winbindd/wb_lookupusergroups.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/source3/winbindd/wb_lookupusergroups.c b/source3/winbindd/wb_lookupusergroups.c index e07f58d..e232425 100644 --- a/source3/winbindd/wb_lookupusergroups.c +++ b/source3/winbindd/wb_lookupusergroups.c @@ -37,6 +37,7 @@ struct tevent_req *wb_lookupusergroups_send(TALLOC_CTX *mem_ctx, struct tevent_req *req, *subreq; struct wb_lookupusergroups_state *state; struct winbindd_domain *domain; + NTSTATUS status; req = tevent_req_create(mem_ctx, &state, struct wb_lookupusergroups_state); @@ -45,6 +46,14 @@ struct tevent_req *wb_lookupusergroups_send(TALLOC_CTX *mem_ctx, } sid_copy(&state->sid, sid); + status = lookup_usergroups_cached(NULL, state, &state->sid, + &state->sids.num_sids, + &state->sids.sids); + if (NT_STATUS_IS_OK(status)) { + tevent_req_done(req); + return tevent_req_post(req, ev); + } + domain = find_domain_from_sid_noinit(&state->sid); if (domain == NULL) { DEBUG(1, ("could not find domain entry for sid %s\n", -- 1.7.5.4 From ad36092607aa7bcc8324404179d1ea355d6b3739 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 24 Nov 2011 15:09:37 +0100 Subject: [PATCH 5/8] s3: Try the netsamlogon_cache in wb_fill_pwent --- source3/winbindd/wb_fill_pwent.c | 32 ++++++++++++++++++++++++++------ 1 files changed, 26 insertions(+), 6 deletions(-) diff --git a/source3/winbindd/wb_fill_pwent.c b/source3/winbindd/wb_fill_pwent.c index 8f09480..463f41a 100644 --- a/source3/winbindd/wb_fill_pwent.c +++ b/source3/winbindd/wb_fill_pwent.c @@ -90,7 +90,7 @@ static void wb_fill_pwent_sid2gid_done(struct tevent_req *subreq) struct wb_fill_pwent_state *state = tevent_req_data( req, struct wb_fill_pwent_state); struct winbindd_domain *domain; - char *dom_name; + char *dom_name = NULL; fstring user_name, output_username; char *mapped_name = NULL; NTSTATUS status; @@ -102,17 +102,37 @@ static void wb_fill_pwent_sid2gid_done(struct tevent_req *subreq) } domain = find_domain_from_sid_noinit(&state->info->user_sid); - if (domain == NULL) { - tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER); - return; + if (domain != NULL) { + dom_name = domain->name; + } else { + struct netr_SamInfo3 *info3 = NULL; + + info3 = netsamlogon_cache_get( + talloc_tos(), &state->info->user_sid); + if (info3 == NULL) { + tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER); + return; + } + + dom_name = talloc_strdup( + state, info3->base.domain.string); + if (tevent_req_nomem(dom_name, req)) { + return; + } + TALLOC_FREE(info3); } - dom_name = domain->name; /* Username */ fstrcpy(user_name, state->info->acct_name); strlower_m(user_name); - status = normalize_name_map(state, domain, user_name, &mapped_name); + + if (domain != NULL) { + status = normalize_name_map(state, domain, user_name, + &mapped_name); + } else { + status = NT_STATUS_NONE_MAPPED; + } /* Basic removal of whitespace */ if (NT_STATUS_IS_OK(status)) { -- 1.7.5.4 From 5c482602862de1e054e8e92df299a1786563a500 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Nov 2011 10:11:02 +0100 Subject: [PATCH 6/8] s3: Apply some const --- source3/include/proto.h | 4 ++-- source3/libsmb/trustdom_cache.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index 28b58b2..bf22491 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1312,8 +1312,8 @@ WERROR map_werror_from_unix(int error); bool trustdom_cache_enable(void); bool trustdom_cache_shutdown(void); -bool trustdom_cache_store(char* name, char* alt_name, const struct dom_sid *sid, - time_t timeout); +bool trustdom_cache_store(const char *name, const char *alt_name, + const struct dom_sid *sid, time_t timeout); bool trustdom_cache_fetch(const char* name, struct dom_sid* sid); uint32 trustdom_cache_fetch_timestamp( void ); bool trustdom_cache_store_timestamp( uint32 t, time_t timeout ); diff --git a/source3/libsmb/trustdom_cache.c b/source3/libsmb/trustdom_cache.c index 56f6011..178e898 100644 --- a/source3/libsmb/trustdom_cache.c +++ b/source3/libsmb/trustdom_cache.c @@ -96,8 +96,8 @@ static char* trustdom_cache_key(const char* name) * false if store attempt failed **/ -bool trustdom_cache_store(char* name, char* alt_name, const struct dom_sid *sid, - time_t timeout) +bool trustdom_cache_store(const char *name, const char *alt_name, + const struct dom_sid *sid, time_t timeout) { char *key, *alt_key; fstring sid_string; -- 1.7.5.4 From ce2e646f7c01b0229b5f1d40e75119aa133f909e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 24 Nov 2011 21:42:11 +0100 Subject: [PATCH 7/8] s3: Make sure that we get domain_info for authenticated users Without this, if winbind does not know about a trust, make_user_info_map will map any legitimate authentication request to the local sam, even if our DC could have authenticated it via weird trust paths. --- source3/auth/auth_domain.c | 4 ++++ source3/smbd/sesssetup.c | 4 ++++ source3/winbindd/winbindd_creds.c | 4 ++++ source3/winbindd/winbindd_misc.c | 10 ++++++++++ source3/winbindd/winbindd_pam.c | 8 ++++++++ 5 files changed, 30 insertions(+), 0 deletions(-) diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index 8a71603..07fedbb 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -344,6 +344,10 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, if (NT_STATUS_IS_OK(nt_status)) { (*server_info)->nss_token |= user_info->was_mapped; netsamlogon_cache_store(user_info->client.account_name, info3); + trustdom_cache_store( + info3->base.domain.string, "", + info3->base.domain_sid, + time(NULL) + 600); TALLOC_FREE(info3); } } diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index d514b93..03063a2 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -363,6 +363,10 @@ static void reply_spnego_kerberos(struct smb_request *req, /* save the PAC data if we have it */ if (logon_info) { netsamlogon_cache_store(user, &logon_info->info3); + trustdom_cache_store( + logon_info->info3.base.domain.string, "", + logon_info->info3.base.domain_sid, + time(NULL) + 600); } /* setup the string used by %U */ diff --git a/source3/winbindd/winbindd_creds.c b/source3/winbindd/winbindd_creds.c index 6bbd0ff..bbd19c9 100644 --- a/source3/winbindd/winbindd_creds.c +++ b/source3/winbindd/winbindd_creds.c @@ -122,6 +122,10 @@ NTSTATUS winbindd_store_creds(struct winbindd_domain *domain, if (!netsamlogon_cache_store(user, info3)) { return NT_STATUS_ACCESS_DENIED; } + trustdom_cache_store( + info3->base.domain.string, "", + info3->base.domain_sid, + time(NULL) + 600); } return NT_STATUS_OK; diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c index 7d25167..ad492ca 100644 --- a/source3/winbindd/winbindd_misc.c +++ b/source3/winbindd/winbindd_misc.c @@ -228,8 +228,18 @@ void winbindd_domain_info(struct winbindd_cli_state *cli) domain = find_domain_from_name_noinit(cli->request->domain_name); if (domain == NULL) { + struct dom_sid sid; DEBUG(3, ("Did not find domain [%s]\n", cli->request->domain_name)); + if (trustdom_cache_fetch(cli->request->domain_name, + &sid)) { + fstrcpy(cli->response->data.domain_info.name, + cli->request->domain_name); + sid_to_fstring(cli->response->data.domain_info.sid, + &sid); + request_ok(cli); + return; + } request_error(cli); return; } diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index bde16b1..2ffc89f 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1670,6 +1670,10 @@ process_result: wcache_invalidate_samlogon(find_domain_from_name(name_domain), &user_sid); netsamlogon_cache_store(name_user, info3); + trustdom_cache_store( + info3->base.domain.string, "", + info3->base.domain_sid, + time(NULL) + 600); /* save name_to_sid info as early as possible (only if this is our primary domain so we don't invalidate @@ -1839,6 +1843,10 @@ process_result: wcache_invalidate_samlogon(find_domain_from_name(name_domain), &user_sid); netsamlogon_cache_store(name_user, info3); + trustdom_cache_store( + info3->base.domain.string, "", + info3->base.domain_sid, + time(NULL) + 600); /* Check if the user is in the right group */ -- 1.7.5.4 From b690499e8b6ac2e02a916cfd748affd7bd51ec6b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 23 Dec 2011 12:35:03 +0100 Subject: [PATCH 8/8] s3: Do not map to SAM at all. Needs further testing --- source3/auth/auth_util.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index a904da4..9a25055 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -119,6 +119,10 @@ NTSTATUS make_user_info_map(struct auth_usersupplied_info **user_info, * non-domain member box will also map to WORKSTATION\user. * This also deals with the client passing in a "" domain */ +#if 0 + /* + * Not sure this is valid at all, need to check + */ if (!is_trusted_domain(domain) && !strequal(domain, my_sam_name())) { @@ -130,6 +134,7 @@ NTSTATUS make_user_info_map(struct auth_usersupplied_info **user_info, "workstation [%s]\n", client_domain, domain, smb_name, workstation_name)); } +#endif /* We know that the given domain is trusted (and we are allowing them), * it is our global SAM name, or for legacy behavior it is our -- 1.7.5.4