The Samba-Bugzilla – Attachment 13993 Details for
Bug 13286
LSA server on a DC doesn't support querying trusted domains
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for 4.8 cherry-picked from master
bug13286-v48.patch (text/plain), 163.75 KB, created by
Ralph Böhme
on 2018-02-27 10:26:42 UTC
(
hide
)
Description:
Patch for 4.8 cherry-picked from master
Filename:
MIME Type:
Creator:
Ralph Böhme
Created:
2018-02-27 10:26:42 UTC
Size:
163.75 KB
patch
obsolete
>From 797e16f63a7fba0270bc52d043b0fb17c63c1da7 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Tue, 20 Feb 2018 15:57:37 +0100 >Subject: [PATCH 01/22] rpcclient: fix variable initialisation and add > parenthesis to if clauses > >Just a few README.Coding fixes. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 9ccc6eef145c1f67e24cbb1c21402714f612c607) >--- > source3/rpcclient/cmd_lsarpc.c | 10 ++++++---- > 1 file changed, 6 insertions(+), 4 deletions(-) > >diff --git a/source3/rpcclient/cmd_lsarpc.c b/source3/rpcclient/cmd_lsarpc.c >index 2fa04a27752..058583d943a 100644 >--- a/source3/rpcclient/cmd_lsarpc.c >+++ b/source3/rpcclient/cmd_lsarpc.c >@@ -272,8 +272,8 @@ static NTSTATUS cmd_lsa_lookup_names_level(struct rpc_pipe_client *cli, > { > struct policy_handle pol; > NTSTATUS status, result; >- struct dom_sid *sids; >- enum lsa_SidType *types; >+ struct dom_sid *sids = NULL; >+ enum lsa_SidType *types = NULL; > int i, level; > struct dcerpc_binding_handle *b = cli->binding_handle; > >@@ -285,9 +285,9 @@ static NTSTATUS cmd_lsa_lookup_names_level(struct rpc_pipe_client *cli, > status = rpccli_lsa_open_policy(cli, mem_ctx, True, > SEC_FLAG_MAXIMUM_ALLOWED, > &pol); >- >- if (!NT_STATUS_IS_OK(status)) >+ if (!NT_STATUS_IS_OK(status)) { > goto done; >+ } > > level = atoi(argv[1]); > >@@ -296,7 +296,9 @@ static NTSTATUS cmd_lsa_lookup_names_level(struct rpc_pipe_client *cli, > > if (!NT_STATUS_IS_OK(status) && NT_STATUS_V(status) != > NT_STATUS_V(STATUS_SOME_UNMAPPED)) >+ { > goto done; >+ } > > status = NT_STATUS_OK; > >-- >2.13.6 > > >From a5d1e44a0cafb1a060ac3ee3f11af46ed7089fbb Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 25 Jan 2018 11:24:25 +0100 >Subject: [PATCH 02/22] rpcclient: add lookupsids_level command > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit 76868818e8b98a0cd4881d319e0735de5091b8b1) >--- > source3/rpcclient/cmd_lsarpc.c | 93 ++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 93 insertions(+) > >diff --git a/source3/rpcclient/cmd_lsarpc.c b/source3/rpcclient/cmd_lsarpc.c >index 058583d943a..462ed06e007 100644 >--- a/source3/rpcclient/cmd_lsarpc.c >+++ b/source3/rpcclient/cmd_lsarpc.c >@@ -454,6 +454,98 @@ static NTSTATUS cmd_lsa_lookup_sids(struct rpc_pipe_client *cli, TALLOC_CTX *mem > return status; > } > >+static NTSTATUS cmd_lsa_lookup_sids_level(struct rpc_pipe_client *cli, >+ TALLOC_CTX *mem_ctx, int argc, >+ const char **argv) >+{ >+ struct policy_handle pol; >+ NTSTATUS status, result; >+ struct dom_sid *sids = NULL; >+ char **domains = NULL; >+ char **names = NULL; >+ enum lsa_SidType *types = NULL; >+ int i, level; >+ struct dcerpc_binding_handle *b = cli->binding_handle; >+ >+ if (argc < 3) { >+ printf("Usage: %s [level] [sid1 [sid2 [...]]]\n", argv[0]); >+ return NT_STATUS_OK; >+ } >+ >+ status = rpccli_lsa_open_policy(cli, mem_ctx, True, >+ SEC_FLAG_MAXIMUM_ALLOWED, >+ &pol); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto done; >+ } >+ >+ level = atoi(argv[1]); >+ >+ /* Convert arguments to sids */ >+ >+ sids = talloc_array(mem_ctx, struct dom_sid, argc - 2); >+ if (sids == NULL) { >+ printf("could not allocate memory for %d sids\n", argc - 2); >+ goto done; >+ } >+ >+ for (i = 0; i < argc - 2; i++) { >+ if (!string_to_sid(&sids[i], argv[i + 2])) { >+ status = NT_STATUS_INVALID_SID; >+ goto done; >+ } >+ } >+ >+ /* Lookup the SIDs */ >+ >+ status = dcerpc_lsa_lookup_sids_generic(cli->binding_handle, >+ mem_ctx, >+ &pol, >+ argc - 2, >+ sids, >+ level, >+ &domains, >+ &names, >+ &types, >+ false, >+ &result); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto done; >+ } >+ status = result; >+ >+ if (!NT_STATUS_IS_OK(status) && NT_STATUS_V(status) != >+ NT_STATUS_V(STATUS_SOME_UNMAPPED)) >+ { >+ goto done; >+ } >+ >+ status = NT_STATUS_OK; >+ >+ /* Print results */ >+ >+ for (i = 0; i < (argc - 2); i++) { >+ fstring sid_str; >+ >+ sid_to_fstring(sid_str, &sids[i]); >+ if (types[i] == SID_NAME_DOMAIN) { >+ printf("%s %s (%d)\n", sid_str, >+ domains[i] ? domains[i] : "*unknown*", >+ types[i]); >+ } else { >+ printf("%s %s\\%s (%d)\n", sid_str, >+ domains[i] ? domains[i] : "*unknown*", >+ names[i] ? names[i] : "*unknown*", >+ types[i]); >+ } >+ } >+ >+ dcerpc_lsa_Close(b, mem_ctx, &pol, &result); >+ >+ done: >+ return status; >+} >+ > /* Resolve a list of SIDs to a list of names */ > > static NTSTATUS cmd_lsa_lookup_sids3(struct rpc_pipe_client *cli, >@@ -2281,6 +2373,7 @@ struct cmd_set lsarpc_commands[] = { > { "lsaquery", RPC_RTYPE_NTSTATUS, cmd_lsa_query_info_policy, NULL, &ndr_table_lsarpc, NULL, "Query info policy", "" }, > { "lookupsids", RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_sids, NULL, &ndr_table_lsarpc, NULL, "Convert SIDs to names", "" }, > { "lookupsids3", RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_sids3, NULL, &ndr_table_lsarpc, NULL, "Convert SIDs to names", "" }, >+ { "lookupsids_level", RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_sids_level, NULL, &ndr_table_lsarpc, NULL, "Convert SIDs to names", "" }, > { "lookupnames", RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_names, NULL, &ndr_table_lsarpc, NULL, "Convert names to SIDs", "" }, > { "lookupnames4", RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_names4, NULL, &ndr_table_lsarpc, NULL, "Convert names to SIDs", "" }, > { "lookupnames_level", RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_names_level, NULL, &ndr_table_lsarpc, NULL, "Convert names to SIDs", "" }, >-- >2.13.6 > > >From 6698bd305506ddeff0cc6a7c8c45e3dd2ff293db Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 20 Mar 2017 12:56:00 +0100 >Subject: [PATCH 03/22] s4:rpc_server/lsa: use > LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES/LSA_CLIENT_REVISION_1 in compat code > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit 3909f8fcfe6b82575ad8974acacde3270ce849fe) >--- > source4/rpc_server/lsa/lsa_lookup.c | 8 ++++---- > 1 file changed, 4 insertions(+), 4 deletions(-) > >diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c >index f54b118b5e8..d0361417ef9 100644 >--- a/source4/rpc_server/lsa/lsa_lookup.c >+++ b/source4/rpc_server/lsa/lsa_lookup.c >@@ -797,8 +797,8 @@ NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *m > r2.in.names = NULL; > r2.in.level = r->in.level; > r2.in.count = r->in.count; >- r2.in.lookup_options = 0; >- r2.in.client_revision = 0; >+ r2.in.lookup_options = LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES; >+ r2.in.client_revision = LSA_CLIENT_REVISION_1; > r2.out.count = r->out.count; > r2.out.names = NULL; > r2.out.domains = r->out.domains; >@@ -1124,8 +1124,8 @@ NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX * > r2.in.sids = NULL; > r2.in.level = r->in.level; > r2.in.count = r->in.count; >- r2.in.lookup_options = 0; >- r2.in.client_revision = 0; >+ r2.in.lookup_options = LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES; >+ r2.in.client_revision = LSA_CLIENT_REVISION_1; > r2.out.count = r->out.count; > r2.out.domains = r->out.domains; > >-- >2.13.6 > > >From 2c5c18ec38ba3c0b1e4de8faf0108727bf035c48 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 20 Mar 2017 12:56:00 +0100 >Subject: [PATCH 04/22] s4:rpc_server/lsa: make sure > dcesrv_lsa_LookupSids_common() gets prepared [ref] pointers > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit f6e60d2c2e1f0a4eb6426c7da683abaa11babd05) >--- > source4/rpc_server/lsa/lsa_lookup.c | 34 +++++++++++++++++++++++----------- > 1 file changed, 23 insertions(+), 11 deletions(-) > >diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c >index d0361417ef9..c2931c182c4 100644 >--- a/source4/rpc_server/lsa/lsa_lookup.c >+++ b/source4/rpc_server/lsa/lsa_lookup.c >@@ -596,13 +596,16 @@ static NTSTATUS dcesrv_lsa_LookupSids_common(struct dcesrv_call_state *dce_call, > NTSTATUS status = NT_STATUS_OK; > uint32_t i; > >+ *r->out.domains = NULL; >+ r->out.names->count = 0; >+ r->out.names->names = NULL; >+ *r->out.count = 0; >+ > if (r->in.level < LSA_LOOKUP_NAMES_ALL || > r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) { > return NT_STATUS_INVALID_PARAMETER; > } > >- *r->out.domains = NULL; >- > /* NOTE: the WSPP test suite tries SIDs with invalid revision numbers, > and expects NT_STATUS_INVALID_PARAMETER back - we just treat it as > an unknown SID. We could add a SID validator here. (tridge) >@@ -615,13 +618,6 @@ static NTSTATUS dcesrv_lsa_LookupSids_common(struct dcesrv_call_state *dce_call, > } > *r->out.domains = domains; > >- r->out.names = talloc_zero(mem_ctx, struct lsa_TransNameArray2); >- if (r->out.names == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- >- *r->out.count = 0; >- > r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName2, > r->in.sids->num_sids); > if (r->out.names->names == NULL) { >@@ -739,6 +735,11 @@ NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call, > DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED); > } > >+ *r->out.domains = NULL; >+ r->out.names->count = 0; >+ r->out.names->names = NULL; >+ *r->out.count = 0; >+ > status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, > 0, /* we skip access checks */ > &policy_state); >@@ -790,17 +791,28 @@ NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *m > DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED); > } > >+ *r->out.domains = NULL; >+ r->out.names->count = 0; >+ r->out.names->names = NULL; >+ *r->out.count = 0; >+ > ZERO_STRUCT(r2); > > r2.in.handle = r->in.handle; > r2.in.sids = r->in.sids; >- r2.in.names = NULL; >+ r2.in.names = talloc_zero(mem_ctx, struct lsa_TransNameArray2); >+ if (r2.in.names == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } > r2.in.level = r->in.level; > r2.in.count = r->in.count; > r2.in.lookup_options = LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES; > r2.in.client_revision = LSA_CLIENT_REVISION_1; > r2.out.count = r->out.count; >- r2.out.names = NULL; >+ r2.out.names = talloc_zero(mem_ctx, struct lsa_TransNameArray2); >+ if (r2.out.names == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } > r2.out.domains = r->out.domains; > > status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2); >-- >2.13.6 > > >From 390cb9fb695661de9e9fb4ce76c970e5d75e38fd Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 20 Mar 2017 12:56:00 +0100 >Subject: [PATCH 05/22] s4:rpc_server/lsa: expect prepared [ref] pointers in > dcesrv_lsa_LookupNames_common() > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit 3339a1c57266181570d5ca5e389719951f26b41d) >--- > source4/rpc_server/lsa/lsa_lookup.c | 21 +++++++++++---------- > 1 file changed, 11 insertions(+), 10 deletions(-) > >diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c >index c2931c182c4..8c100144cd0 100644 >--- a/source4/rpc_server/lsa/lsa_lookup.c >+++ b/source4/rpc_server/lsa/lsa_lookup.c >@@ -853,26 +853,22 @@ static NTSTATUS dcesrv_lsa_LookupNames_common(struct dcesrv_call_state *dce_call > struct lsa_RefDomainList *domains; > uint32_t i; > >+ *r->out.domains = NULL; >+ r->out.sids->count = 0; >+ r->out.sids->sids = NULL; >+ *r->out.count = 0; >+ > if (r->in.level < LSA_LOOKUP_NAMES_ALL || > r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) { > return NT_STATUS_INVALID_PARAMETER; > } > >- *r->out.domains = NULL; >- >- domains = talloc_zero(mem_ctx, struct lsa_RefDomainList); >+ domains = talloc_zero(r->out.domains, struct lsa_RefDomainList); > if (domains == NULL) { > return NT_STATUS_NO_MEMORY; > } > *r->out.domains = domains; > >- r->out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray3); >- if (r->out.sids == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- >- *r->out.count = 0; >- > r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid3, > r->in.num_names); > if (r->out.sids->sids == NULL) { >@@ -979,6 +975,11 @@ NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX > DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED); > } > >+ *r->out.domains = NULL; >+ r->out.sids->count = 0; >+ r->out.sids->sids = NULL; >+ *r->out.count = 0; >+ > status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, > 0, /* we skip access checks */ > &policy_state); >-- >2.13.6 > > >From 1511ada71d2762ed95da729608d7afdbf2ba2ad0 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 20 Mar 2017 12:56:00 +0100 >Subject: [PATCH 06/22] s4:rpc_server/lsa: make sure dcesrv_lsa_LookupNames2() > gets prepared [ref] pointers > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit fe43dd8678e4f598e0ae802e3d93ad9b28988783) >--- > source4/rpc_server/lsa/lsa_lookup.c | 30 +++++++++++++++++++----------- > 1 file changed, 19 insertions(+), 11 deletions(-) > >diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c >index 8c100144cd0..219e30194b7 100644 >--- a/source4/rpc_server/lsa/lsa_lookup.c >+++ b/source4/rpc_server/lsa/lsa_lookup.c >@@ -1035,10 +1035,13 @@ NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call, > DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED); > } > >- *r->out.domains = NULL; >- > DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY); > >+ *r->out.domains = NULL; >+ r->out.sids->count = 0; >+ r->out.sids->sids = NULL; >+ *r->out.count = 0; >+ > if (r->in.level < LSA_LOOKUP_NAMES_ALL || > r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) { > return NT_STATUS_INVALID_PARAMETER; >@@ -1046,19 +1049,12 @@ NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call, > > state = h->data; > >- domains = talloc_zero(mem_ctx, struct lsa_RefDomainList); >+ domains = talloc_zero(r->out.domains, struct lsa_RefDomainList); > if (domains == NULL) { > return NT_STATUS_NO_MEMORY; > } > *r->out.domains = domains; > >- r->out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray2); >- if (r->out.sids == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- >- *r->out.count = 0; >- > r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid2, > r->in.num_names); > if (r->out.sids->sids == NULL) { >@@ -1129,17 +1125,29 @@ NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX * > DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED); > } > >+ *r->out.domains = NULL; >+ r->out.sids->count = 0; >+ r->out.sids->sids = NULL; >+ *r->out.count = 0; >+ > ZERO_STRUCT(r2); > > r2.in.handle = r->in.handle; > r2.in.num_names = r->in.num_names; > r2.in.names = r->in.names; >- r2.in.sids = NULL; >+ r2.in.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray2); >+ if (r2.in.sids == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } > r2.in.level = r->in.level; > r2.in.count = r->in.count; > r2.in.lookup_options = LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES; > r2.in.client_revision = LSA_CLIENT_REVISION_1; > r2.out.count = r->out.count; >+ r2.out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray2); >+ if (r2.out.sids == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } > r2.out.domains = r->out.domains; > > status = dcesrv_lsa_LookupNames2(dce_call, mem_ctx, &r2); >-- >2.13.6 > > >From f1ea21743ce28725849c5f3e56b99bd47b6c85c0 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 20 Mar 2017 12:56:00 +0100 >Subject: [PATCH 07/22] s4:rpc_server/lsa: remove unused 'status' variable in > dcesrv_lsa_LookupSids_common() > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit e8a0223633fd2e6ebb3d864570b76932bc3e293a) >--- > source4/rpc_server/lsa/lsa_lookup.c | 5 +---- > 1 file changed, 1 insertion(+), 4 deletions(-) > >diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c >index 219e30194b7..a8a136b1266 100644 >--- a/source4/rpc_server/lsa/lsa_lookup.c >+++ b/source4/rpc_server/lsa/lsa_lookup.c >@@ -593,7 +593,6 @@ static NTSTATUS dcesrv_lsa_LookupSids_common(struct dcesrv_call_state *dce_call, > struct lsa_LookupSids2 *r) > { > struct lsa_RefDomainList *domains = NULL; >- NTSTATUS status = NT_STATUS_OK; > uint32_t i; > > *r->out.domains = NULL; >@@ -641,14 +640,12 @@ static NTSTATUS dcesrv_lsa_LookupSids_common(struct dcesrv_call_state *dce_call, > > if (sid_str == NULL) { > r->out.names->names[i].name.string = "(SIDERROR)"; >- status = STATUS_SOME_UNMAPPED; > continue; > } > > status2 = dcesrv_lsa_lookup_sid(state, mem_ctx, sid, sid_str, > &authority_name, &name, &rtype); > if (!NT_STATUS_IS_OK(status2)) { >- status = STATUS_SOME_UNMAPPED; > continue; > } > >@@ -675,7 +672,7 @@ static NTSTATUS dcesrv_lsa_LookupSids_common(struct dcesrv_call_state *dce_call, > return STATUS_SOME_UNMAPPED; > } > >- return status; >+ return NT_STATUS_OK; > } > > /* >-- >2.13.6 > > >From 3f81a05c900a3ba91dce6b78f1fc1e5ab824ab23 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 20 Mar 2017 12:56:00 +0100 >Subject: [PATCH 08/22] s4:rpc_server/lsa: simplify [ref] pointer handling in > dcesrv_lsa_LookupSids() > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit 5d868fd875803e361653ccca4e61c5c25dc114aa) >--- > source4/rpc_server/lsa/lsa_lookup.c | 27 ++++++++++----------------- > 1 file changed, 10 insertions(+), 17 deletions(-) > >diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c >index a8a136b1266..400b5214a1a 100644 >--- a/source4/rpc_server/lsa/lsa_lookup.c >+++ b/source4/rpc_server/lsa/lsa_lookup.c >@@ -793,6 +793,13 @@ NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *m > r->out.names->names = NULL; > *r->out.count = 0; > >+ r->out.names->names = talloc_zero_array(r->out.names, >+ struct lsa_TranslatedName, >+ r->in.sids->num_sids); >+ if (r->out.names->names == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ > ZERO_STRUCT(r2); > > r2.in.handle = r->in.handle; >@@ -816,27 +823,13 @@ NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *m > /* we deliberately don't check for error from the above, > as even on error we are supposed to return the names */ > >- r->out.domains = r2.out.domains; >- if (!r2.out.names) { >- r->out.names = NULL; >- return status; >- } >- >- r->out.names = talloc(mem_ctx, struct lsa_TransNameArray); >- if (r->out.names == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- r->out.names->count = r2.out.names->count; >- r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName, >- r->out.names->count); >- if (r->out.names->names == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- for (i=0;i<r->out.names->count;i++) { >+ SMB_ASSERT(r2.out.names->count <= r->in.sids->num_sids); >+ for (i=0;i<r2.out.names->count;i++) { > r->out.names->names[i].sid_type = r2.out.names->names[i].sid_type; > r->out.names->names[i].name.string = r2.out.names->names[i].name.string; > r->out.names->names[i].sid_index = r2.out.names->names[i].sid_index; > } >+ r->out.names->count = r2.out.names->count; > > return status; > } >-- >2.13.6 > > >From 5213ccdfdb03eeb86f94413dc4a198207e88abef Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 20 Mar 2017 12:56:00 +0100 >Subject: [PATCH 09/22] s4:rpc_server/lsa: simplify [ref] pointer handling in > dcesrv_lsa_LookupNames() > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit 7c1c9bf53ffc24a25038326767e33f008c7a5552) >--- > source4/rpc_server/lsa/lsa_lookup.c | 24 ++++++++++-------------- > 1 file changed, 10 insertions(+), 14 deletions(-) > >diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c >index 400b5214a1a..defcef5089a 100644 >--- a/source4/rpc_server/lsa/lsa_lookup.c >+++ b/source4/rpc_server/lsa/lsa_lookup.c >@@ -1120,6 +1120,13 @@ NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX * > r->out.sids->sids = NULL; > *r->out.count = 0; > >+ r->out.sids->sids = talloc_zero_array(r->out.sids, >+ struct lsa_TranslatedSid, >+ r->in.num_names); >+ if (r->out.sids->sids == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ > ZERO_STRUCT(r2); > > r2.in.handle = r->in.handle; >@@ -1141,25 +1148,14 @@ NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX * > r2.out.domains = r->out.domains; > > status = dcesrv_lsa_LookupNames2(dce_call, mem_ctx, &r2); >- if (r2.out.sids == NULL) { >- return status; >- } > >- r->out.sids = talloc(mem_ctx, struct lsa_TransSidArray); >- if (r->out.sids == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- r->out.sids->count = r2.out.sids->count; >- r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid, >- r->out.sids->count); >- if (r->out.sids->sids == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- for (i=0;i<r->out.sids->count;i++) { >+ SMB_ASSERT(r2.out.sids->count <= r->in.num_names); >+ for (i=0;i<r2.out.sids->count;i++) { > r->out.sids->sids[i].sid_type = r2.out.sids->sids[i].sid_type; > r->out.sids->sids[i].rid = r2.out.sids->sids[i].rid; > r->out.sids->sids[i].sid_index = r2.out.sids->sids[i].sid_index; > } >+ r->out.sids->count = r2.out.sids->count; > > return status; > } >-- >2.13.6 > > >From 0b2c7c16f6fa7c74a5ac047a79cfda0a32de31ed Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 22 Jan 2018 09:27:49 +0100 >Subject: [PATCH 10/22] s4:rpc_server/lsa: rename 'state' variable to > 'policy_state' in dcesrv_lsa_LookupSids_common() > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit c0f6103ddea9a825f0f0dcf169e70a5f6a55c2e2) >--- > source4/rpc_server/lsa/lsa_lookup.c | 8 ++++---- > 1 file changed, 4 insertions(+), 4 deletions(-) > >diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c >index defcef5089a..378aff055e8 100644 >--- a/source4/rpc_server/lsa/lsa_lookup.c >+++ b/source4/rpc_server/lsa/lsa_lookup.c >@@ -589,7 +589,7 @@ static NTSTATUS dcesrv_lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX > > static NTSTATUS dcesrv_lsa_LookupSids_common(struct dcesrv_call_state *dce_call, > TALLOC_CTX *mem_ctx, >- struct lsa_policy_state *state, >+ struct lsa_policy_state *policy_state, > struct lsa_LookupSids2 *r) > { > struct lsa_RefDomainList *domains = NULL; >@@ -643,15 +643,15 @@ static NTSTATUS dcesrv_lsa_LookupSids_common(struct dcesrv_call_state *dce_call, > continue; > } > >- status2 = dcesrv_lsa_lookup_sid(state, mem_ctx, sid, sid_str, >+ status2 = dcesrv_lsa_lookup_sid(policy_state, mem_ctx, sid, sid_str, > &authority_name, &name, &rtype); > if (!NT_STATUS_IS_OK(status2)) { > continue; > } > > /* set up the authority table */ >- status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, >- authority_name, sid, >+ status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, rtype, >+ authority_name, sid, > domains, &sid_index); > if (!NT_STATUS_IS_OK(status2)) { > continue; >-- >2.13.6 > > >From 431f4f628115301d2b305e6829cf7a342e6b903f Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 22 Jan 2018 09:27:49 +0100 >Subject: [PATCH 11/22] s4:rpc_server/lsa: rename 'state' variable to > 'policy_state' in dcesrv_lsa_LookupSids2() > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit c78c17dc2fbaf523d1957bb748aa75ecd81e793b) >--- > source4/rpc_server/lsa/lsa_lookup.c | 10 +++++----- > 1 file changed, 5 insertions(+), 5 deletions(-) > >diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c >index 378aff055e8..65c664ebfb8 100644 >--- a/source4/rpc_server/lsa/lsa_lookup.c >+++ b/source4/rpc_server/lsa/lsa_lookup.c >@@ -684,20 +684,20 @@ NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call, > { > enum dcerpc_transport_t transport = > dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description); >- struct lsa_policy_state *state; >- struct dcesrv_handle *h; >+ struct lsa_policy_state *policy_state = NULL; >+ struct dcesrv_handle *policy_handle = NULL; > > if (transport != NCACN_NP && transport != NCALRPC) { > DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED); > } > >- DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY); >+ DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY); > >- state = h->data; >+ policy_state = policy_handle->data; > > return dcesrv_lsa_LookupSids_common(dce_call, > mem_ctx, >- state, >+ policy_state, > r); > } > >-- >2.13.6 > > >From 824586641d74b845c9710d2729eda33d0061c5fa Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 22 Jan 2018 09:27:49 +0100 >Subject: [PATCH 12/22] s4:rpc_server/lsa: rename 'state' variable to > 'policy_state' in dcesrv_lsa_LookupNames2() > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit ec55c18ceda5c430eaec97c5d7e594941e3a31fc) >--- > source4/rpc_server/lsa/lsa_lookup.c | 21 ++++++++++++--------- > 1 file changed, 12 insertions(+), 9 deletions(-) > >diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c >index 65c664ebfb8..cefc48fcd8b 100644 >--- a/source4/rpc_server/lsa/lsa_lookup.c >+++ b/source4/rpc_server/lsa/lsa_lookup.c >@@ -1015,8 +1015,8 @@ NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call, > { > enum dcerpc_transport_t transport = > dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description); >- struct lsa_policy_state *state; >- struct dcesrv_handle *h; >+ struct lsa_policy_state *policy_state = NULL; >+ struct dcesrv_handle *policy_handle = NULL; > uint32_t i; > struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; > struct lsa_RefDomainList *domains; >@@ -1025,7 +1025,9 @@ NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call, > DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED); > } > >- DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY); >+ DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY); >+ >+ policy_state = policy_handle->data; > > *r->out.domains = NULL; > r->out.sids->count = 0; >@@ -1037,8 +1039,6 @@ NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call, > return NT_STATUS_INVALID_PARAMETER; > } > >- state = h->data; >- > domains = talloc_zero(r->out.domains, struct lsa_RefDomainList); > if (domains == NULL) { > return NT_STATUS_NO_MEMORY; >@@ -1069,14 +1069,17 @@ NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call, > r->out.sids->sids[i].sid_index = 0xFFFFFFFF; > r->out.sids->sids[i].unknown = 0; > >- status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, state, mem_ctx, name, >- &authority_name, &sid, &rtype, &rid); >+ status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, >+ policy_state, mem_ctx, name, >+ &authority_name, &sid, &rtype, >+ &rid); > if (!NT_STATUS_IS_OK(status2)) { > continue; > } > >- status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, authority_name, >- sid, domains, &sid_index); >+ status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, >+ rtype, authority_name, sid, >+ domains, &sid_index); > if (!NT_STATUS_IS_OK(status2)) { > continue; > } >-- >2.13.6 > > >From 0004db17a238bbdc0ce290473a82f4ff7ee1c768 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 22 Jan 2018 20:21:14 +0100 >Subject: [PATCH 13/22] s4:rpc_server/lsa: base dcesrv_lsa_LookupNames() on > dcesrv_lsa_LookupNames_common() > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit 37cb34d16406d27831be74e952ee744e58b79fb4) >--- > source4/rpc_server/lsa/lsa_lookup.c | 43 +++++++++++++++++++++++++++++++------ > 1 file changed, 36 insertions(+), 7 deletions(-) > >diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c >index cefc48fcd8b..1e9b4c6cd9e 100644 >--- a/source4/rpc_server/lsa/lsa_lookup.c >+++ b/source4/rpc_server/lsa/lsa_lookup.c >@@ -1110,7 +1110,9 @@ NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX * > { > enum dcerpc_transport_t transport = > dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description); >- struct lsa_LookupNames2 r2; >+ struct lsa_policy_state *policy_state = NULL; >+ struct dcesrv_handle *policy_handle = NULL; >+ struct lsa_LookupNames3 r2; > NTSTATUS status; > uint32_t i; > >@@ -1118,6 +1120,10 @@ NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX * > DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED); > } > >+ DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY); >+ >+ policy_state = policy_handle->data; >+ > *r->out.domains = NULL; > r->out.sids->count = 0; > r->out.sids->sids = NULL; >@@ -1135,7 +1141,7 @@ NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX * > r2.in.handle = r->in.handle; > r2.in.num_names = r->in.num_names; > r2.in.names = r->in.names; >- r2.in.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray2); >+ r2.in.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray3); > if (r2.in.sids == NULL) { > return NT_STATUS_NO_MEMORY; > } >@@ -1144,19 +1150,42 @@ NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX * > r2.in.lookup_options = LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES; > r2.in.client_revision = LSA_CLIENT_REVISION_1; > r2.out.count = r->out.count; >- r2.out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray2); >+ r2.out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray3); > if (r2.out.sids == NULL) { > return NT_STATUS_NO_MEMORY; > } > r2.out.domains = r->out.domains; > >- status = dcesrv_lsa_LookupNames2(dce_call, mem_ctx, &r2); >+ status = dcesrv_lsa_LookupNames_common(dce_call, >+ mem_ctx, >+ policy_state, >+ &r2); > > SMB_ASSERT(r2.out.sids->count <= r->in.num_names); > for (i=0;i<r2.out.sids->count;i++) { >- r->out.sids->sids[i].sid_type = r2.out.sids->sids[i].sid_type; >- r->out.sids->sids[i].rid = r2.out.sids->sids[i].rid; >- r->out.sids->sids[i].sid_index = r2.out.sids->sids[i].sid_index; >+ struct lsa_TranslatedSid3 *s3 = >+ &r2.out.sids->sids[i]; >+ struct lsa_TranslatedSid *s = >+ &r->out.sids->sids[i]; >+ >+ s->sid_type = s3->sid_type; >+ if (s3->sid_type == SID_NAME_DOMAIN) { >+ s->rid = UINT32_MAX; >+ } else if (s3->flags & 0x00000004) { >+ s->rid = UINT32_MAX; >+ } else if (s3->sid == NULL) { >+ /* >+ * MS-LSAT 3.1.4.7 - rid zero is considered >+ * equivalent to sid NULL - so we should return >+ * 0 rid for unmapped entries >+ */ >+ s->rid = 0; >+ } else { >+ s->rid = 0; >+ dom_sid_split_rid(NULL, s3->sid, >+ NULL, &s->rid); >+ } >+ s->sid_index = s3->sid_index; > } > r->out.sids->count = r2.out.sids->count; > >-- >2.13.6 > > >From 666732ecd4be7f1468c3ab9e96f4a1ae9dc98bd7 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 22 Jan 2018 20:21:14 +0100 >Subject: [PATCH 14/22] s4:rpc_server/lsa: base dcesrv_lsa_LookupNames2() on > dcesrv_lsa_LookupNames_common() > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit e6c9984bd563525dc312b67fe69ea7e4be04ee4e) >--- > source4/rpc_server/lsa/lsa_lookup.c | 114 ++++++++++++++++++------------------ > 1 file changed, 58 insertions(+), 56 deletions(-) > >diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c >index 1e9b4c6cd9e..bb14cf7a16b 100644 >--- a/source4/rpc_server/lsa/lsa_lookup.c >+++ b/source4/rpc_server/lsa/lsa_lookup.c >@@ -1017,9 +1017,9 @@ NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call, > dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description); > struct lsa_policy_state *policy_state = NULL; > struct dcesrv_handle *policy_handle = NULL; >+ struct lsa_LookupNames3 r2; >+ NTSTATUS status; > uint32_t i; >- struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; >- struct lsa_RefDomainList *domains; > > if (transport != NCACN_NP && transport != NCALRPC) { > DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED); >@@ -1034,72 +1034,74 @@ NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call, > r->out.sids->sids = NULL; > *r->out.count = 0; > >- if (r->in.level < LSA_LOOKUP_NAMES_ALL || >- r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) { >- return NT_STATUS_INVALID_PARAMETER; >+ r->out.sids->sids = talloc_zero_array(r->out.sids, >+ struct lsa_TranslatedSid2, >+ r->in.num_names); >+ if (r->out.sids->sids == NULL) { >+ return NT_STATUS_NO_MEMORY; > } > >- domains = talloc_zero(r->out.domains, struct lsa_RefDomainList); >- if (domains == NULL) { >+ ZERO_STRUCT(r2); >+ >+ r2.in.handle = r->in.handle; >+ r2.in.num_names = r->in.num_names; >+ r2.in.names = r->in.names; >+ r2.in.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray3); >+ if (r2.in.sids == NULL) { > return NT_STATUS_NO_MEMORY; > } >- *r->out.domains = domains; >- >- r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid2, >- r->in.num_names); >- if (r->out.sids->sids == NULL) { >+ r2.in.level = r->in.level; >+ r2.in.count = r->in.count; >+ /* >+ * MS-LSAT 3.1.4.7: >+ * >+ * The LookupOptions and ClientRevision parameters MUST be ignored. >+ * Message processing MUST happen as if LookupOptions is set to >+ * 0x00000000 and ClientRevision is set to 0x00000002. >+ */ >+ r2.in.lookup_options = LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES; >+ r2.in.client_revision = LSA_CLIENT_REVISION_2; >+ r2.out.count = r->out.count; >+ r2.out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray3); >+ if (r2.out.sids == NULL) { > return NT_STATUS_NO_MEMORY; > } >+ r2.out.domains = r->out.domains; > >- for (i=0;i<r->in.num_names;i++) { >- const char *name = r->in.names[i].string; >- const char *authority_name; >- struct dom_sid *sid; >- uint32_t sid_index, rid=0; >- enum lsa_SidType rtype; >- NTSTATUS status2; >- >- r->out.sids->count++; >- >- r->out.sids->sids[i].sid_type = SID_NAME_UNKNOWN; >- /* MS-LSAT 3.1.4.7 - rid zero is considered equivalent >- to sid NULL - so we should return 0 rid for >- unmapped entries */ >- r->out.sids->sids[i].rid = 0; >- r->out.sids->sids[i].sid_index = 0xFFFFFFFF; >- r->out.sids->sids[i].unknown = 0; >+ status = dcesrv_lsa_LookupNames_common(dce_call, >+ mem_ctx, >+ policy_state, >+ &r2); > >- status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, >- policy_state, mem_ctx, name, >- &authority_name, &sid, &rtype, >- &rid); >- if (!NT_STATUS_IS_OK(status2)) { >- continue; >- } >+ SMB_ASSERT(r2.out.sids->count <= r->in.num_names); >+ for (i=0;i<r2.out.sids->count;i++) { >+ struct lsa_TranslatedSid3 *s3 = >+ &r2.out.sids->sids[i]; >+ struct lsa_TranslatedSid2 *s2 = >+ &r->out.sids->sids[i]; > >- status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, >- rtype, authority_name, sid, >- domains, &sid_index); >- if (!NT_STATUS_IS_OK(status2)) { >- continue; >+ s2->sid_type = s3->sid_type; >+ if (s3->sid_type == SID_NAME_DOMAIN) { >+ s2->rid = UINT32_MAX; >+ } else if (s3->flags & 0x00000004) { >+ s2->rid = UINT32_MAX; >+ } else if (s3->sid == NULL) { >+ /* >+ * MS-LSAT 3.1.4.7 - rid zero is considered >+ * equivalent to sid NULL - so we should return >+ * 0 rid for unmapped entries >+ */ >+ s2->rid = 0; >+ } else { >+ s2->rid = 0; >+ dom_sid_split_rid(NULL, s3->sid, >+ NULL, &s2->rid); > } >- >- r->out.sids->sids[i].sid_type = rtype; >- r->out.sids->sids[i].rid = rid; >- r->out.sids->sids[i].sid_index = sid_index; >- r->out.sids->sids[i].unknown = 0; >- >- (*r->out.count)++; >- } >- >- if (*r->out.count == 0) { >- return NT_STATUS_NONE_MAPPED; >- } >- if (*r->out.count != r->in.num_names) { >- return STATUS_SOME_UNMAPPED; >+ s2->sid_index = s3->sid_index; > } >+ r->out.sids->count = r2.out.sids->count; > >- return NT_STATUS_OK; >+ return status; > } > > /* >-- >2.13.6 > > >From 38fe3d8ba0781480a03e6732daa2768fd5b2a5e4 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 19 Jan 2018 13:42:40 +0100 >Subject: [PATCH 15/22] s4:rpc_server/lsa: prepare dcesrv_lsa_LookupSids* for > async processing > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit ab7988aa2fd1a43f576a4b73a6893c61c7ef1957) >--- > source4/rpc_server/lsa/lsa_lookup.c | 215 ++++++++++++++++++++++++++---------- > 1 file changed, 157 insertions(+), 58 deletions(-) > >diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c >index bb14cf7a16b..62d29d3173e 100644 >--- a/source4/rpc_server/lsa/lsa_lookup.c >+++ b/source4/rpc_server/lsa/lsa_lookup.c >@@ -587,11 +587,27 @@ static NTSTATUS dcesrv_lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX > return NT_STATUS_OK; > } > >-static NTSTATUS dcesrv_lsa_LookupSids_common(struct dcesrv_call_state *dce_call, >- TALLOC_CTX *mem_ctx, >- struct lsa_policy_state *policy_state, >- struct lsa_LookupSids2 *r) >+struct dcesrv_lsa_LookupSids_base_state { >+ struct dcesrv_call_state *dce_call; >+ >+ TALLOC_CTX *mem_ctx; >+ >+ struct lsa_policy_state *policy_state; >+ >+ struct lsa_LookupSids3 r; >+ >+ struct { >+ struct lsa_LookupSids *l; >+ struct lsa_LookupSids2 *l2; >+ struct lsa_LookupSids3 *l3; >+ } _r; >+}; >+ >+static NTSTATUS dcesrv_lsa_LookupSids_base_call(struct dcesrv_lsa_LookupSids_base_state *state) > { >+ struct lsa_policy_state *policy_state = state->policy_state; >+ TALLOC_CTX *mem_ctx = state->mem_ctx; >+ struct lsa_LookupSids3 *r = &state->r; > struct lsa_RefDomainList *domains = NULL; > uint32_t i; > >@@ -675,6 +691,45 @@ static NTSTATUS dcesrv_lsa_LookupSids_common(struct dcesrv_call_state *dce_call, > return NT_STATUS_OK; > } > >+static void dcesrv_lsa_LookupSids_base_map( >+ struct dcesrv_lsa_LookupSids_base_state *state) >+{ >+ if (state->_r.l3 != NULL) { >+ struct lsa_LookupSids3 *r = state->_r.l3; >+ >+ r->out.result = state->r.out.result; >+ return; >+ } >+ >+ if (state->_r.l2 != NULL) { >+ struct lsa_LookupSids2 *r = state->_r.l2; >+ >+ r->out.result = state->r.out.result; >+ return; >+ } >+ >+ if (state->_r.l != NULL) { >+ struct lsa_LookupSids *r = state->_r.l; >+ uint32_t i; >+ >+ r->out.result = state->r.out.result; >+ >+ SMB_ASSERT(state->r.out.names->count <= r->in.sids->num_sids); >+ for (i = 0; i < state->r.out.names->count; i++) { >+ struct lsa_TranslatedName2 *n2 = >+ &state->r.out.names->names[i]; >+ struct lsa_TranslatedName *n = >+ &r->out.names->names[i]; >+ >+ n->sid_type = n2->sid_type; >+ n->name = n2->name; >+ n->sid_index = n2->sid_index; >+ } >+ r->out.names->count = state->r.out.names->count; >+ return; >+ } >+} >+ > /* > lsa_LookupSids2 > */ >@@ -684,8 +739,9 @@ NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call, > { > enum dcerpc_transport_t transport = > dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description); >- struct lsa_policy_state *policy_state = NULL; >+ struct dcesrv_lsa_LookupSids_base_state *state = NULL; > struct dcesrv_handle *policy_handle = NULL; >+ NTSTATUS status; > > if (transport != NCACN_NP && transport != NCALRPC) { > DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED); >@@ -693,12 +749,43 @@ NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call, > > DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY); > >- policy_state = policy_handle->data; >+ *r->out.domains = NULL; >+ r->out.names->count = 0; >+ r->out.names->names = NULL; >+ *r->out.count = 0; >+ >+ state = talloc_zero(mem_ctx, struct dcesrv_lsa_LookupSids_base_state); >+ if (state == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ state->dce_call = dce_call; >+ state->mem_ctx = mem_ctx; >+ >+ state->policy_state = policy_handle->data; >+ >+ state->r.in.sids = r->in.sids; >+ state->r.in.level = r->in.level; >+ state->r.in.lookup_options = r->in.lookup_options; >+ state->r.in.client_revision = r->in.client_revision; >+ state->r.in.names = r->in.names; >+ state->r.in.count = r->in.count; >+ state->r.out.domains = r->out.domains; >+ state->r.out.names = r->out.names; >+ state->r.out.count = r->out.count; >+ >+ state->_r.l2 = r; > >- return dcesrv_lsa_LookupSids_common(dce_call, >- mem_ctx, >- policy_state, >- r); >+ status = dcesrv_lsa_LookupSids_base_call(state); >+ >+ if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) { >+ return status; >+ } >+ >+ state->r.out.result = status; >+ dcesrv_lsa_LookupSids_base_map(state); >+ TALLOC_FREE(state); >+ return status; > } > > >@@ -715,8 +802,7 @@ NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call, > enum dcerpc_transport_t transport = > dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description); > const struct dcesrv_auth *auth = &dce_call->conn->auth_state; >- struct lsa_policy_state *policy_state; >- struct lsa_LookupSids2 q; >+ struct dcesrv_lsa_LookupSids_base_state *state = NULL; > NTSTATUS status; > > if (transport != NCACN_IP_TCP) { >@@ -737,37 +823,42 @@ NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call, > r->out.names->names = NULL; > *r->out.count = 0; > >- status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, >+ state = talloc_zero(mem_ctx, struct dcesrv_lsa_LookupSids_base_state); >+ if (state == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ state->dce_call = dce_call; >+ state->mem_ctx = mem_ctx; >+ >+ status = dcesrv_lsa_get_policy_state(state->dce_call, mem_ctx, > 0, /* we skip access checks */ >- &policy_state); >+ &state->policy_state); > if (!NT_STATUS_IS_OK(status)) { > return status; > } > >- ZERO_STRUCT(q); >+ state->r.in.sids = r->in.sids; >+ state->r.in.level = r->in.level; >+ state->r.in.lookup_options = r->in.lookup_options; >+ state->r.in.client_revision = r->in.client_revision; >+ state->r.in.names = r->in.names; >+ state->r.in.count = r->in.count; >+ state->r.out.domains = r->out.domains; >+ state->r.out.names = r->out.names; >+ state->r.out.count = r->out.count; > >- q.in.handle = NULL; >- q.in.sids = r->in.sids; >- q.in.names = r->in.names; >- q.in.level = r->in.level; >- q.in.count = r->in.count; >- q.in.lookup_options = r->in.lookup_options; >- q.in.client_revision = r->in.client_revision; >- q.out.count = r->out.count; >- q.out.names = r->out.names; >- q.out.domains = r->out.domains; >+ state->_r.l3 = r; > >- status = dcesrv_lsa_LookupSids_common(dce_call, >- mem_ctx, >- policy_state, >- &q); >- >- talloc_free(policy_state); >+ status = dcesrv_lsa_LookupSids_base_call(state); > >- r->out.count = q.out.count; >- r->out.names = q.out.names; >- r->out.domains = q.out.domains; >+ if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) { >+ return status; >+ } > >+ state->r.out.result = status; >+ dcesrv_lsa_LookupSids_base_map(state); >+ TALLOC_FREE(state); > return status; > } > >@@ -780,14 +871,16 @@ NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *m > { > enum dcerpc_transport_t transport = > dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description); >- struct lsa_LookupSids2 r2; >+ struct dcesrv_lsa_LookupSids_base_state *state = NULL; >+ struct dcesrv_handle *policy_handle = NULL; > NTSTATUS status; >- uint32_t i; > > if (transport != NCACN_NP && transport != NCALRPC) { > DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED); > } > >+ DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY); >+ > *r->out.domains = NULL; > r->out.names->count = 0; > r->out.names->names = NULL; >@@ -800,37 +893,43 @@ NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *m > return NT_STATUS_NO_MEMORY; > } > >- ZERO_STRUCT(r2); >+ state = talloc_zero(mem_ctx, struct dcesrv_lsa_LookupSids_base_state); >+ if (state == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ state->dce_call = dce_call; >+ state->mem_ctx = mem_ctx; >+ >+ state->policy_state = policy_handle->data; > >- r2.in.handle = r->in.handle; >- r2.in.sids = r->in.sids; >- r2.in.names = talloc_zero(mem_ctx, struct lsa_TransNameArray2); >- if (r2.in.names == NULL) { >+ state->r.in.sids = r->in.sids; >+ state->r.in.level = r->in.level; >+ state->r.in.lookup_options = LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES; >+ state->r.in.client_revision = LSA_CLIENT_REVISION_1; >+ state->r.in.names = talloc_zero(state, struct lsa_TransNameArray2); >+ if (state->r.in.names == NULL) { > return NT_STATUS_NO_MEMORY; > } >- r2.in.level = r->in.level; >- r2.in.count = r->in.count; >- r2.in.lookup_options = LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES; >- r2.in.client_revision = LSA_CLIENT_REVISION_1; >- r2.out.count = r->out.count; >- r2.out.names = talloc_zero(mem_ctx, struct lsa_TransNameArray2); >- if (r2.out.names == NULL) { >+ state->r.in.count = r->in.count; >+ state->r.out.domains = r->out.domains; >+ state->r.out.names = talloc_zero(state, struct lsa_TransNameArray2); >+ if (state->r.out.names == NULL) { > return NT_STATUS_NO_MEMORY; > } >- r2.out.domains = r->out.domains; >+ state->r.out.count = r->out.count; > >- status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2); >- /* we deliberately don't check for error from the above, >- as even on error we are supposed to return the names */ >+ state->_r.l = r; > >- SMB_ASSERT(r2.out.names->count <= r->in.sids->num_sids); >- for (i=0;i<r2.out.names->count;i++) { >- r->out.names->names[i].sid_type = r2.out.names->names[i].sid_type; >- r->out.names->names[i].name.string = r2.out.names->names[i].name.string; >- r->out.names->names[i].sid_index = r2.out.names->names[i].sid_index; >+ status = dcesrv_lsa_LookupSids_base_call(state); >+ >+ if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) { >+ return status; > } >- r->out.names->count = r2.out.names->count; > >+ state->r.out.result = status; >+ dcesrv_lsa_LookupSids_base_map(state); >+ TALLOC_FREE(state); > return status; > } > >-- >2.13.6 > > >From 74cd9c8dbdbf41421b4e9bd4128a604f39781f15 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 19 Jan 2018 13:42:40 +0100 >Subject: [PATCH 16/22] s4:rpc_server/lsa: prepare dcesrv_lsa_LookupNames* for > async processing > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit 9b6a0b1a63f2ebfbd578047401dfbe38606c8c44) >--- > source4/rpc_server/lsa/lsa_lookup.c | 392 +++++++++++++++++++++++------------- > 1 file changed, 250 insertions(+), 142 deletions(-) > >diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c >index 62d29d3173e..83043cbe17e 100644 >--- a/source4/rpc_server/lsa/lsa_lookup.c >+++ b/source4/rpc_server/lsa/lsa_lookup.c >@@ -933,13 +933,32 @@ NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *m > return status; > } > >-static NTSTATUS dcesrv_lsa_LookupNames_common(struct dcesrv_call_state *dce_call, >- TALLOC_CTX *mem_ctx, >- struct lsa_policy_state *policy_state, >- struct lsa_LookupNames3 *r) >+struct dcesrv_lsa_LookupNames_base_state { >+ struct dcesrv_call_state *dce_call; >+ >+ TALLOC_CTX *mem_ctx; >+ >+ struct lsa_policy_state *policy_state; >+ >+ struct lsa_LookupNames4 r; >+ >+ struct { >+ struct lsa_LookupNames *l; >+ struct lsa_LookupNames2 *l2; >+ struct lsa_LookupNames3 *l3; >+ struct lsa_LookupNames4 *l4; >+ } _r; >+}; >+ >+ >+static NTSTATUS dcesrv_lsa_LookupNames_base_call(struct dcesrv_lsa_LookupNames_base_state *state) > { >- struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; >- struct lsa_RefDomainList *domains; >+ struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx; >+ struct dcesrv_call_state *dce_call = state->dce_call; >+ struct lsa_policy_state *policy_state = state->policy_state; >+ TALLOC_CTX *mem_ctx = state->mem_ctx; >+ struct lsa_LookupNames4 *r = &state->r; >+ struct lsa_RefDomainList *domains = NULL; > uint32_t i; > > *r->out.domains = NULL; >@@ -1009,6 +1028,97 @@ static NTSTATUS dcesrv_lsa_LookupNames_common(struct dcesrv_call_state *dce_call > return NT_STATUS_OK; > } > >+static void dcesrv_lsa_LookupNames_base_map( >+ struct dcesrv_lsa_LookupNames_base_state *state) >+{ >+ if (state->_r.l4 != NULL) { >+ struct lsa_LookupNames4 *r = state->_r.l4; >+ >+ r->out.result = state->r.out.result; >+ return; >+ } >+ >+ if (state->_r.l3 != NULL) { >+ struct lsa_LookupNames3 *r = state->_r.l3; >+ >+ r->out.result = state->r.out.result; >+ return; >+ } >+ >+ if (state->_r.l2 != NULL) { >+ struct lsa_LookupNames2 *r = state->_r.l2; >+ uint32_t i; >+ >+ r->out.result = state->r.out.result; >+ >+ SMB_ASSERT(state->r.out.sids->count <= r->in.num_names); >+ for (i = 0; i < state->r.out.sids->count; i++) { >+ const struct lsa_TranslatedSid3 *s3 = >+ &state->r.out.sids->sids[i]; >+ struct lsa_TranslatedSid2 *s2 = >+ &r->out.sids->sids[i]; >+ >+ s2->sid_type = s3->sid_type; >+ if (s3->sid_type == SID_NAME_DOMAIN) { >+ s2->rid = UINT32_MAX; >+ } else if (s3->flags & 0x00000004) { >+ s2->rid = UINT32_MAX; >+ } else if (s3->sid == NULL) { >+ /* >+ * MS-LSAT 3.1.4.7 - rid zero is considered >+ * equivalent to sid NULL - so we should return >+ * 0 rid for unmapped entries >+ */ >+ s2->rid = 0; >+ } else { >+ s2->rid = 0; >+ dom_sid_split_rid(NULL, s3->sid, >+ NULL, &s2->rid); >+ } >+ s2->sid_index = s3->sid_index; >+ s2->unknown = s3->flags; >+ } >+ r->out.sids->count = state->r.out.sids->count; >+ return; >+ } >+ >+ if (state->_r.l != NULL) { >+ struct lsa_LookupNames *r = state->_r.l; >+ uint32_t i; >+ >+ r->out.result = state->r.out.result; >+ >+ SMB_ASSERT(state->r.out.sids->count <= r->in.num_names); >+ for (i = 0; i < state->r.out.sids->count; i++) { >+ struct lsa_TranslatedSid3 *s3 = >+ &state->r.out.sids->sids[i]; >+ struct lsa_TranslatedSid *s = >+ &r->out.sids->sids[i]; >+ >+ s->sid_type = s3->sid_type; >+ if (s3->sid_type == SID_NAME_DOMAIN) { >+ s->rid = UINT32_MAX; >+ } else if (s3->flags & 0x00000004) { >+ s->rid = UINT32_MAX; >+ } else if (s3->sid == NULL) { >+ /* >+ * MS-LSAT 3.1.4.7 - rid zero is considered >+ * equivalent to sid NULL - so we should return >+ * 0 rid for unmapped entries >+ */ >+ s->rid = 0; >+ } else { >+ s->rid = 0; >+ dom_sid_split_rid(NULL, s3->sid, >+ NULL, &s->rid); >+ } >+ s->sid_index = s3->sid_index; >+ } >+ r->out.sids->count = state->r.out.sids->count; >+ return; >+ } >+} >+ > /* > lsa_LookupNames3 > */ >@@ -1018,8 +1128,9 @@ NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call, > { > enum dcerpc_transport_t transport = > dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description); >- struct lsa_policy_state *policy_state; >- struct dcesrv_handle *policy_handle; >+ struct dcesrv_lsa_LookupNames_base_state *state = NULL; >+ struct dcesrv_handle *policy_handle = NULL; >+ NTSTATUS status; > > if (transport != NCACN_NP && transport != NCALRPC) { > DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED); >@@ -1027,12 +1138,44 @@ NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call, > > DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY); > >- policy_state = policy_handle->data; >+ *r->out.domains = NULL; >+ r->out.sids->count = 0; >+ r->out.sids->sids = NULL; >+ *r->out.count = 0; >+ >+ state = talloc_zero(mem_ctx, struct dcesrv_lsa_LookupNames_base_state); >+ if (state == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ state->dce_call = dce_call; >+ state->mem_ctx = mem_ctx; >+ >+ state->policy_state = policy_handle->data; >+ >+ state->r.in.num_names = r->in.num_names; >+ state->r.in.names = r->in.names; >+ state->r.in.level = r->in.level; >+ state->r.in.lookup_options = r->in.lookup_options; >+ state->r.in.client_revision = r->in.client_revision; >+ state->r.in.sids = r->in.sids; >+ state->r.in.count = r->in.count; >+ state->r.out.domains = r->out.domains; >+ state->r.out.sids = r->out.sids; >+ state->r.out.count = r->out.count; >+ >+ state->_r.l3 = r; >+ >+ status = dcesrv_lsa_LookupNames_base_call(state); > >- return dcesrv_lsa_LookupNames_common(dce_call, >- mem_ctx, >- policy_state, >- r); >+ if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) { >+ return status; >+ } >+ >+ state->r.out.result = status; >+ dcesrv_lsa_LookupNames_base_map(state); >+ TALLOC_FREE(state); >+ return status; > } > > /* >@@ -1047,8 +1190,7 @@ NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX > enum dcerpc_transport_t transport = > dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description); > const struct dcesrv_auth *auth = &dce_call->conn->auth_state; >- struct lsa_policy_state *policy_state; >- struct lsa_LookupNames3 q; >+ struct dcesrv_lsa_LookupNames_base_state *state = NULL; > NTSTATUS status; > > if (transport != NCACN_IP_TCP) { >@@ -1069,39 +1211,43 @@ NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX > r->out.sids->sids = NULL; > *r->out.count = 0; > >- status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, >+ state = talloc_zero(mem_ctx, struct dcesrv_lsa_LookupNames_base_state); >+ if (state == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ state->dce_call = dce_call; >+ state->mem_ctx = mem_ctx; >+ >+ status = dcesrv_lsa_get_policy_state(state->dce_call, state, > 0, /* we skip access checks */ >- &policy_state); >+ &state->policy_state); > if (!NT_STATUS_IS_OK(status)) { > return status; > } > >- ZERO_STRUCT(q); >- >- q.in.handle = NULL; >- q.in.num_names = r->in.num_names; >- q.in.names = r->in.names; >- q.in.level = r->in.level; >- q.in.sids = r->in.sids; >- q.in.count = r->in.count; >- q.in.lookup_options = r->in.lookup_options; >- q.in.client_revision = r->in.client_revision; >- >- q.out.count = r->out.count; >- q.out.sids = r->out.sids; >- q.out.domains = r->out.domains; >+ state->r.in.num_names = r->in.num_names; >+ state->r.in.names = r->in.names; >+ state->r.in.level = r->in.level; >+ state->r.in.lookup_options = r->in.lookup_options; >+ state->r.in.client_revision = r->in.client_revision; >+ state->r.in.sids = r->in.sids; >+ state->r.in.count = r->in.count; >+ state->r.out.domains = r->out.domains; >+ state->r.out.sids = r->out.sids; >+ state->r.out.count = r->out.count; > >- status = dcesrv_lsa_LookupNames_common(dce_call, >- mem_ctx, >- policy_state, >- &q); >+ state->_r.l4 = r; > >- talloc_free(policy_state); >+ status = dcesrv_lsa_LookupNames_base_call(state); > >- r->out.count = q.out.count; >- r->out.sids = q.out.sids; >- r->out.domains = q.out.domains; >+ if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) { >+ return status; >+ } > >+ state->r.out.result = status; >+ dcesrv_lsa_LookupNames_base_map(state); >+ TALLOC_FREE(state); > return status; > } > >@@ -1114,11 +1260,9 @@ NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call, > { > enum dcerpc_transport_t transport = > dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description); >- struct lsa_policy_state *policy_state = NULL; >+ struct dcesrv_lsa_LookupNames_base_state *state = NULL; > struct dcesrv_handle *policy_handle = NULL; >- struct lsa_LookupNames3 r2; > NTSTATUS status; >- uint32_t i; > > if (transport != NCACN_NP && transport != NCALRPC) { > DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED); >@@ -1126,8 +1270,6 @@ NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call, > > DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY); > >- policy_state = policy_handle->data; >- > *r->out.domains = NULL; > r->out.sids->count = 0; > r->out.sids->sids = NULL; >@@ -1140,17 +1282,19 @@ NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call, > return NT_STATUS_NO_MEMORY; > } > >- ZERO_STRUCT(r2); >- >- r2.in.handle = r->in.handle; >- r2.in.num_names = r->in.num_names; >- r2.in.names = r->in.names; >- r2.in.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray3); >- if (r2.in.sids == NULL) { >+ state = talloc_zero(mem_ctx, struct dcesrv_lsa_LookupNames_base_state); >+ if (state == NULL) { > return NT_STATUS_NO_MEMORY; > } >- r2.in.level = r->in.level; >- r2.in.count = r->in.count; >+ >+ state->dce_call = dce_call; >+ state->mem_ctx = mem_ctx; >+ >+ state->policy_state = policy_handle->data; >+ >+ state->r.in.num_names = r->in.num_names; >+ state->r.in.names = r->in.names; >+ state->r.in.level = r->in.level; > /* > * MS-LSAT 3.1.4.7: > * >@@ -1158,48 +1302,31 @@ NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call, > * Message processing MUST happen as if LookupOptions is set to > * 0x00000000 and ClientRevision is set to 0x00000002. > */ >- r2.in.lookup_options = LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES; >- r2.in.client_revision = LSA_CLIENT_REVISION_2; >- r2.out.count = r->out.count; >- r2.out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray3); >- if (r2.out.sids == NULL) { >+ state->r.in.lookup_options = LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES; >+ state->r.in.client_revision = LSA_CLIENT_REVISION_2; >+ state->r.in.sids = talloc_zero(state, struct lsa_TransSidArray3); >+ if (state->r.in.sids == NULL) { > return NT_STATUS_NO_MEMORY; > } >- r2.out.domains = r->out.domains; >- >- status = dcesrv_lsa_LookupNames_common(dce_call, >- mem_ctx, >- policy_state, >- &r2); >- >- SMB_ASSERT(r2.out.sids->count <= r->in.num_names); >- for (i=0;i<r2.out.sids->count;i++) { >- struct lsa_TranslatedSid3 *s3 = >- &r2.out.sids->sids[i]; >- struct lsa_TranslatedSid2 *s2 = >- &r->out.sids->sids[i]; >- >- s2->sid_type = s3->sid_type; >- if (s3->sid_type == SID_NAME_DOMAIN) { >- s2->rid = UINT32_MAX; >- } else if (s3->flags & 0x00000004) { >- s2->rid = UINT32_MAX; >- } else if (s3->sid == NULL) { >- /* >- * MS-LSAT 3.1.4.7 - rid zero is considered >- * equivalent to sid NULL - so we should return >- * 0 rid for unmapped entries >- */ >- s2->rid = 0; >- } else { >- s2->rid = 0; >- dom_sid_split_rid(NULL, s3->sid, >- NULL, &s2->rid); >- } >- s2->sid_index = s3->sid_index; >+ state->r.in.count = r->in.count; >+ state->r.out.domains = r->out.domains; >+ state->r.out.sids = talloc_zero(state, struct lsa_TransSidArray3); >+ if (state->r.out.sids == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ state->r.out.count = r->out.count; >+ >+ state->_r.l2 = r; >+ >+ status = dcesrv_lsa_LookupNames_base_call(state); >+ >+ if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) { >+ return status; > } >- r->out.sids->count = r2.out.sids->count; > >+ state->r.out.result = status; >+ dcesrv_lsa_LookupNames_base_map(state); >+ TALLOC_FREE(state); > return status; > } > >@@ -1211,11 +1338,9 @@ NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX * > { > enum dcerpc_transport_t transport = > dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description); >- struct lsa_policy_state *policy_state = NULL; >+ struct dcesrv_lsa_LookupNames_base_state *state = NULL; > struct dcesrv_handle *policy_handle = NULL; >- struct lsa_LookupNames3 r2; > NTSTATUS status; >- uint32_t i; > > if (transport != NCACN_NP && transport != NCALRPC) { > DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED); >@@ -1223,8 +1348,6 @@ NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX * > > DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY); > >- policy_state = policy_handle->data; >- > *r->out.domains = NULL; > r->out.sids->count = 0; > r->out.sids->sids = NULL; >@@ -1237,59 +1360,44 @@ NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX * > return NT_STATUS_NO_MEMORY; > } > >- ZERO_STRUCT(r2); >+ state = talloc_zero(mem_ctx, struct dcesrv_lsa_LookupNames_base_state); >+ if (state == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ state->dce_call = dce_call; >+ state->mem_ctx = mem_ctx; >+ >+ state->policy_state = policy_handle->data; > >- r2.in.handle = r->in.handle; >- r2.in.num_names = r->in.num_names; >- r2.in.names = r->in.names; >- r2.in.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray3); >- if (r2.in.sids == NULL) { >+ state->r.in.num_names = r->in.num_names; >+ state->r.in.names = r->in.names; >+ state->r.in.level = r->in.level; >+ state->r.in.lookup_options = LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES; >+ state->r.in.client_revision = LSA_CLIENT_REVISION_1; >+ state->r.in.sids = talloc_zero(state, struct lsa_TransSidArray3); >+ if (state->r.in.sids == NULL) { > return NT_STATUS_NO_MEMORY; > } >- r2.in.level = r->in.level; >- r2.in.count = r->in.count; >- r2.in.lookup_options = LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES; >- r2.in.client_revision = LSA_CLIENT_REVISION_1; >- r2.out.count = r->out.count; >- r2.out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray3); >- if (r2.out.sids == NULL) { >+ state->r.in.count = r->in.count; >+ state->r.out.domains = r->out.domains; >+ state->r.out.sids = talloc_zero(state, struct lsa_TransSidArray3); >+ if (state->r.out.sids == NULL) { > return NT_STATUS_NO_MEMORY; > } >- r2.out.domains = r->out.domains; >- >- status = dcesrv_lsa_LookupNames_common(dce_call, >- mem_ctx, >- policy_state, >- &r2); >- >- SMB_ASSERT(r2.out.sids->count <= r->in.num_names); >- for (i=0;i<r2.out.sids->count;i++) { >- struct lsa_TranslatedSid3 *s3 = >- &r2.out.sids->sids[i]; >- struct lsa_TranslatedSid *s = >- &r->out.sids->sids[i]; >- >- s->sid_type = s3->sid_type; >- if (s3->sid_type == SID_NAME_DOMAIN) { >- s->rid = UINT32_MAX; >- } else if (s3->flags & 0x00000004) { >- s->rid = UINT32_MAX; >- } else if (s3->sid == NULL) { >- /* >- * MS-LSAT 3.1.4.7 - rid zero is considered >- * equivalent to sid NULL - so we should return >- * 0 rid for unmapped entries >- */ >- s->rid = 0; >- } else { >- s->rid = 0; >- dom_sid_split_rid(NULL, s3->sid, >- NULL, &s->rid); >- } >- s->sid_index = s3->sid_index; >+ state->r.out.count = r->out.count; >+ >+ state->_r.l = r; >+ >+ status = dcesrv_lsa_LookupNames_base_call(state); >+ >+ if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) { >+ return status; > } >- r->out.sids->count = r2.out.sids->count; > >+ state->r.out.result = status; >+ dcesrv_lsa_LookupNames_base_map(state); >+ TALLOC_FREE(state); > return status; > } > >-- >2.13.6 > > >From 9dedb68a6251a7b82c25a78e907e4db77a57fada Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 16 Feb 2018 01:14:00 +0100 >Subject: [PATCH 17/22] s4:dsdb: add dsdb_trust_domain_by_{sid,name}() > >This gets the lsa_ForestTrustDomainInfo for the searched >domain as well as the lsa_TrustDomainInfoInfoEx for the >direct trust (which might be the same for external trust or >the forest root domain). > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit e9ace1852ff88ebb7778e8db9a49bc5c61512d16) >--- > source4/dsdb/common/util_trusts.c | 222 ++++++++++++++++++++++++++++++++++++++ > 1 file changed, 222 insertions(+) > >diff --git a/source4/dsdb/common/util_trusts.c b/source4/dsdb/common/util_trusts.c >index 1534829199b..7dcbea2ce6d 100644 >--- a/source4/dsdb/common/util_trusts.c >+++ b/source4/dsdb/common/util_trusts.c >@@ -2822,6 +2822,9 @@ struct dsdb_trust_routing_domain { > struct dsdb_trust_routing_domain *prev, *next; > > struct lsa_TrustDomainInfoInfoEx *tdo; >+ >+ struct lsa_ForestTrustDomainInfo di; >+ > struct lsa_ForestTrustInformation *fti; > }; > >@@ -2881,6 +2884,10 @@ NTSTATUS dsdb_trust_routing_table_load(struct ldb_context *sam_ctx, > return status; > } > >+ d->di.domain_sid = d->tdo->sid; >+ d->di.netbios_domain_name.string = d->tdo->netbios_name.string; >+ d->di.dns_domain_name.string = d->tdo->domain_name.string; >+ > if (root_trust_tdo != NULL) { > root_direction_tdo = root_trust_tdo; > } else if (trust_parent_tdo != NULL) { >@@ -2923,6 +2930,10 @@ NTSTATUS dsdb_trust_routing_table_load(struct ldb_context *sam_ctx, > return status; > } > >+ d->di.domain_sid = d->tdo->sid; >+ d->di.netbios_domain_name.string = d->tdo->netbios_name.string; >+ d->di.dns_domain_name.string = d->tdo->domain_name.string; >+ > DLIST_ADD_END(table->domains, d); > > if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) { >@@ -3197,3 +3208,214 @@ const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_routing_by_name( > > return NULL; > } >+ >+const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_domain_by_sid( >+ const struct dsdb_trust_routing_table *table, >+ const struct dom_sid *sid, >+ const struct lsa_ForestTrustDomainInfo **pdi) >+{ >+ const struct dsdb_trust_routing_domain *d = NULL; >+ >+ if (pdi != NULL) { >+ *pdi = NULL; >+ } >+ >+ if (sid == NULL) { >+ return NULL; >+ } >+ >+ for (d = table->domains; d != NULL; d = d->next) { >+ bool transitive = false; >+ uint32_t i; >+ >+ if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) { >+ transitive = true; >+ } >+ >+ if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) { >+ transitive = true; >+ } >+ >+ if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) { >+ transitive = false; >+ } >+ >+ if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) { >+ transitive = false; >+ } >+ >+ if (!transitive || d->fti == NULL) { >+ bool match = false; >+ >+ match = dom_sid_equal(d->di.domain_sid, sid); >+ if (match) { >+ /* >+ * exact match, it's the domain itself. >+ */ >+ if (pdi != NULL) { >+ *pdi = &d->di; >+ } >+ return d->tdo; >+ } >+ continue; >+ } >+ >+ for (i = 0; i < d->fti->count; i++ ) { >+ const struct lsa_ForestTrustRecord *f = d->fti->entries[i]; >+ const struct lsa_ForestTrustDomainInfo *di = NULL; >+ const struct dom_sid *fti_sid = NULL; >+ bool match = false; >+ >+ if (f == NULL) { >+ /* broken record */ >+ continue; >+ } >+ >+ if (f->type != LSA_FOREST_TRUST_DOMAIN_INFO) { >+ continue; >+ } >+ >+ if (f->flags & LSA_SID_DISABLED_MASK) { >+ /* >+ * any flag disables the entry. >+ */ >+ continue; >+ } >+ >+ di = &f->forest_trust_data.domain_info; >+ fti_sid = di->domain_sid; >+ if (fti_sid == NULL) { >+ /* broken record */ >+ continue; >+ } >+ >+ match = dom_sid_equal(fti_sid, sid); >+ if (match) { >+ /* >+ * exact match, it's a domain in the forest. >+ */ >+ if (pdi != NULL) { >+ *pdi = di; >+ } >+ return d->tdo; >+ } >+ } >+ } >+ >+ return NULL; >+} >+ >+const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_domain_by_name( >+ const struct dsdb_trust_routing_table *table, >+ const char *name, >+ const struct lsa_ForestTrustDomainInfo **pdi) >+{ >+ const struct dsdb_trust_routing_domain *d = NULL; >+ >+ if (pdi != NULL) { >+ *pdi = NULL; >+ } >+ >+ if (name == NULL) { >+ return NULL; >+ } >+ >+ for (d = table->domains; d != NULL; d = d->next) { >+ bool transitive = false; >+ uint32_t i; >+ >+ if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) { >+ transitive = true; >+ } >+ >+ if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) { >+ transitive = true; >+ } >+ >+ if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) { >+ transitive = false; >+ } >+ >+ if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) { >+ transitive = false; >+ } >+ >+ if (!transitive || d->fti == NULL) { >+ bool match = false; >+ >+ match = strequal_m(d->di.netbios_domain_name.string, >+ name); >+ if (match) { >+ /* >+ * exact match for netbios name, >+ * it's the domain itself. >+ */ >+ if (pdi != NULL) { >+ *pdi = &d->di; >+ } >+ return d->tdo; >+ } >+ match = strequal_m(d->di.dns_domain_name.string, >+ name); >+ if (match) { >+ /* >+ * exact match for dns name, >+ * it's the domain itself. >+ */ >+ if (pdi != NULL) { >+ *pdi = &d->di; >+ } >+ return d->tdo; >+ } >+ continue; >+ } >+ >+ for (i = 0; i < d->fti->count; i++ ) { >+ const struct lsa_ForestTrustRecord *f = d->fti->entries[i]; >+ const struct lsa_ForestTrustDomainInfo *di = NULL; >+ bool match = false; >+ >+ if (f == NULL) { >+ /* broken record */ >+ continue; >+ } >+ >+ if (f->type != LSA_FOREST_TRUST_DOMAIN_INFO) { >+ continue; >+ } >+ di = &f->forest_trust_data.domain_info; >+ >+ if (!(f->flags & LSA_NB_DISABLED_MASK)) { >+ match = strequal_m(di->netbios_domain_name.string, >+ name); >+ if (match) { >+ /* >+ * exact match for netbios name, >+ * it's a domain in the forest. >+ */ >+ if (pdi != NULL) { >+ *pdi = di; >+ } >+ return d->tdo; >+ } >+ } >+ >+ if (!(f->flags & LSA_TLN_DISABLED_MASK)) { >+ match = strequal_m(di->dns_domain_name.string, >+ name); >+ if (match) { >+ /* >+ * exact match for dns name, >+ * it's a domain in the forest. >+ */ >+ if (pdi != NULL) { >+ *pdi = di; >+ } >+ return d->tdo; >+ } >+ } >+ } >+ } >+ >+ return NULL; >+} >-- >2.13.6 > > >From ec8c9aed8a4cd8879885611c81463d217670f36d Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 20 Mar 2017 12:55:44 +0100 >Subject: [PATCH 18/22] libcli/security: add > dom_sid_lookup_predefined_{sid,name}() > >This basically implements [MS-LSAT] 3.1.1.1.1 Predefined Translation Database >and Corresponding View. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit d7780c66866144eba59408c03af50256825165ba) >--- > libcli/security/dom_sid.h | 13 ++ > libcli/security/util_sid.c | 499 +++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 512 insertions(+) > >diff --git a/libcli/security/dom_sid.h b/libcli/security/dom_sid.h >index bdcec941d3f..6c3225e267d 100644 >--- a/libcli/security/dom_sid.h >+++ b/libcli/security/dom_sid.h >@@ -62,6 +62,19 @@ extern const struct dom_sid global_sid_Unix_NFS_Groups; > extern const struct dom_sid global_sid_Unix_NFS_Mode; > extern const struct dom_sid global_sid_Unix_NFS_Other; > >+enum lsa_SidType; >+ >+NTSTATUS dom_sid_lookup_predefined_name(const char *name, >+ const struct dom_sid **sid, >+ enum lsa_SidType *type, >+ const struct dom_sid **authority_sid, >+ const char **authority_name); >+NTSTATUS dom_sid_lookup_predefined_sid(const struct dom_sid *sid, >+ const char **name, >+ enum lsa_SidType *type, >+ const struct dom_sid **authority_sid, >+ const char **authority_name); >+ > int dom_sid_compare_auth(const struct dom_sid *sid1, > const struct dom_sid *sid2); > int dom_sid_compare(const struct dom_sid *sid1, const struct dom_sid *sid2); >diff --git a/libcli/security/util_sid.c b/libcli/security/util_sid.c >index e84cfb48265..4e4a8fa0d3e 100644 >--- a/libcli/security/util_sid.c >+++ b/libcli/security/util_sid.c >@@ -434,3 +434,502 @@ bool is_null_sid(const struct dom_sid *sid) > const struct dom_sid null_sid = {0}; > return dom_sid_equal(sid, &null_sid); > } >+ >+/* >+ * See [MS-LSAT] 3.1.1.1.1 Predefined Translation Database and Corresponding View >+ */ >+struct predefined_name_mapping { >+ const char *name; >+ enum lsa_SidType type; >+ struct dom_sid sid; >+}; >+ >+struct predefined_domain_mapping { >+ const char *domain; >+ struct dom_sid sid; >+ size_t num_names; >+ const struct predefined_name_mapping *names; >+}; >+ >+/* S-1-${AUTHORITY} */ >+#define _SID0(authority) \ >+ { 1, 0, {0,0,0,0,0,authority}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}} >+/* S-1-${AUTHORITY}-${SUB1} */ >+#define _SID1(authority,sub1) \ >+ { 1, 1, {0,0,0,0,0,authority}, {sub1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}} >+/* S-1-${AUTHORITY}-${SUB1}-${SUB2} */ >+#define _SID2(authority,sub1,sub2) \ >+ { 1, 2, {0,0,0,0,0,authority}, {sub1,sub2,0,0,0,0,0,0,0,0,0,0,0,0,0}} >+ >+/* >+ * S-1-0 >+ */ >+static const struct predefined_name_mapping predefined_names_S_1_0[] = { >+ { >+ .name = "NULL SID", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(0, 0), /* S-1-0-0 */ >+ }, >+}; >+ >+/* >+ * S-1-1 >+ */ >+static const struct predefined_name_mapping predefined_names_S_1_1[] = { >+ { >+ .name = "Everyone", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(1, 0), /* S-1-1-0 */ >+ }, >+}; >+ >+/* >+ * S-1-2 >+ */ >+static const struct predefined_name_mapping predefined_names_S_1_2[] = { >+ { >+ .name = "LOCAL", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(2, 0), /* S-1-2-0 */ >+ }, >+}; >+ >+/* >+ * S-1-3 >+ */ >+static const struct predefined_name_mapping predefined_names_S_1_3[] = { >+ { >+ .name = "CREATOR OWNER", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(3, 0), /* S-1-3-0 */ >+ }, >+ { >+ .name = "CREATOR GROUP", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(3, 1), /* S-1-3-1 */ >+ }, >+ { >+ .name = "CREATOR OWNER SERVER", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(3, 0), /* S-1-3-2 */ >+ }, >+ { >+ .name = "CREATOR GROUP SERVER", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(3, 1), /* S-1-3-3 */ >+ }, >+ { >+ .name = "OWNER RIGHTS", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(3, 4), /* S-1-3-4 */ >+ }, >+}; >+ >+/* >+ * S-1-5 only 'NT Pseudo Domain' >+ */ >+static const struct predefined_name_mapping predefined_names_S_1_5p[] = { >+ { >+ .name = "NT Pseudo Domain", >+ .type = SID_NAME_DOMAIN, >+ .sid = _SID0(5), /* S-1-5 */ >+ }, >+}; >+ >+/* >+ * S-1-5 'NT AUTHORITY' >+ */ >+static const struct predefined_name_mapping predefined_names_S_1_5a[] = { >+ { >+ .name = "DIALUP", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 1), /* S-1-5-1 */ >+ }, >+ { >+ .name = "NETWORK", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 2), /* S-1-5-2 */ >+ }, >+ { >+ .name = "BATCH", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 3), /* S-1-5-3 */ >+ }, >+ { >+ .name = "INTERACTIVE", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 4), /* S-1-5-4 */ >+ }, >+ { >+ .name = "SERVICE", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 6), /* S-1-5-6 */ >+ }, >+ { >+ .name = "ANONYMOUS LOGON", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 7), /* S-1-5-7 */ >+ }, >+ { >+ .name = "PROXY", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 8), /* S-1-5-8 */ >+ }, >+ { >+ .name = "ENTERPRISE DOMAIN CONTROLLERS", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 9), /* S-1-5-9 */ >+ }, >+ { >+ .name = "SELF", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 10), /* S-1-5-10 */ >+ }, >+ { >+ .name = "Authenticated Users", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 11), /* S-1-5-11 */ >+ }, >+ { >+ .name = "RESTRICTED", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 12), /* S-1-5-12 */ >+ }, >+ { >+ .name = "TERMINAL SERVER USER", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 13), /* S-1-5-13 */ >+ }, >+ { >+ .name = "REMOTE INTERACTIVE LOGON", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 14), /* S-1-5-14 */ >+ }, >+ { >+ .name = "This Organization", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 15), /* S-1-5-15 */ >+ }, >+ { >+ .name = "IUSR", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 17), /* S-1-5-17 */ >+ }, >+ { >+ .name = "SYSTEM", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 18), /* S-1-5-18 */ >+ }, >+ { >+ .name = "LOCAL SERVICE", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 19), /* S-1-5-19 */ >+ }, >+ { >+ .name = "NETWORK SERVICE", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 20), /* S-1-5-20 */ >+ }, >+ { >+ .name = "WRITE RESTRICTED", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 33), /* S-1-5-33 */ >+ }, >+ { >+ .name = "Other Organization", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID1(5, 1000), /* S-1-5-1000 */ >+ }, >+}; >+ >+/* >+ * S-1-5-32 >+ */ >+static const struct predefined_name_mapping predefined_names_S_1_5_32[] = { >+ { >+ .name = "BUILTIN", >+ .type = SID_NAME_DOMAIN, >+ .sid = _SID1(5, 32), /* S-1-5-32 */ >+ }, >+}; >+ >+/* >+ * S-1-5-64 >+ */ >+static const struct predefined_name_mapping predefined_names_S_1_5_64[] = { >+ { >+ .name = "NTLM Authentication", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID2(5, 64, 10), /* S-1-5-64-10 */ >+ }, >+ { >+ .name = "SChannel Authentication", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID2(5, 64, 14), /* S-1-5-64-14 */ >+ }, >+ { >+ .name = "Digest Authentication", >+ .type = SID_NAME_WKN_GRP, >+ .sid = _SID2(5, 64, 21), /* S-1-5-64-21 */ >+ }, >+}; >+ >+/* >+ * S-1-7 >+ */ >+static const struct predefined_name_mapping predefined_names_S_1_7[] = { >+ { >+ .name = "Internet$", >+ .type = SID_NAME_DOMAIN, >+ .sid = _SID0(7), /* S-1-7 */ >+ }, >+}; >+ >+/* >+ * S-1-16 >+ */ >+static const struct predefined_name_mapping predefined_names_S_1_16[] = { >+ { >+ .name = "Mandatory Label", >+ .type = SID_NAME_DOMAIN, >+ .sid = _SID0(16), /* S-1-16 */ >+ }, >+ { >+ .name = "Untrusted Mandatory Level", >+ .type = SID_NAME_LABEL, >+ .sid = _SID1(16, 0), /* S-1-16-0 */ >+ }, >+ { >+ .name = "Low Mandatory Level", >+ .type = SID_NAME_LABEL, >+ .sid = _SID1(16, 4096), /* S-1-16-4096 */ >+ }, >+ { >+ .name = "Medium Mandatory Level", >+ .type = SID_NAME_LABEL, >+ .sid = _SID1(16, 8192), /* S-1-16-8192 */ >+ }, >+ { >+ .name = "High Mandatory Level", >+ .type = SID_NAME_LABEL, >+ .sid = _SID1(16, 12288), /* S-1-16-12288 */ >+ }, >+ { >+ .name = "System Mandatory Level", >+ .type = SID_NAME_LABEL, >+ .sid = _SID1(16, 16384), /* S-1-16-16384 */ >+ }, >+ { >+ .name = "Protected Process Mandatory Level", >+ .type = SID_NAME_LABEL, >+ .sid = _SID1(16, 20480), /* S-1-16-20480 */ >+ }, >+}; >+ >+static const struct predefined_domain_mapping predefined_domains[] = { >+ { >+ .domain = "", >+ .sid = _SID0(0), /* S-1-0 */ >+ .num_names = ARRAY_SIZE(predefined_names_S_1_0), >+ .names = predefined_names_S_1_0, >+ }, >+ { >+ .domain = "", >+ .sid = _SID0(1), /* S-1-1 */ >+ .num_names = ARRAY_SIZE(predefined_names_S_1_1), >+ .names = predefined_names_S_1_1, >+ }, >+ { >+ .domain = "", >+ .sid = _SID0(2), /* S-1-2 */ >+ .num_names = ARRAY_SIZE(predefined_names_S_1_2), >+ .names = predefined_names_S_1_2, >+ }, >+ { >+ .domain = "", >+ .sid = _SID0(3), /* S-1-3 */ >+ .num_names = ARRAY_SIZE(predefined_names_S_1_3), >+ .names = predefined_names_S_1_3, >+ }, >+ { >+ .domain = "", >+ .sid = _SID0(3), /* S-1-3 */ >+ .num_names = ARRAY_SIZE(predefined_names_S_1_3), >+ .names = predefined_names_S_1_3, >+ }, >+ /* >+ * S-1-5 is split here >+ * >+ * 'NT Pseudo Domain' has precedence before 'NT AUTHORITY'. >+ * >+ * In a LookupSids with multiple sids e.g. S-1-5 and S-1-5-7 >+ * the domain section (struct lsa_DomainInfo) gets >+ * 'NT Pseudo Domain' with S-1-5. If asked in reversed order >+ * S-1-5-7 and then S-1-5, you get struct lsa_DomainInfo >+ * with 'NT AUTHORITY' and S-1-5. >+ */ >+ { >+ .domain = "NT Pseudo Domain", >+ .sid = _SID0(5), /* S-1-5 */ >+ .num_names = ARRAY_SIZE(predefined_names_S_1_5p), >+ .names = predefined_names_S_1_5p, >+ }, >+ { >+ .domain = "NT AUTHORITY", >+ .sid = _SID0(5), /* S-1-5 */ >+ .num_names = ARRAY_SIZE(predefined_names_S_1_5a), >+ .names = predefined_names_S_1_5a, >+ }, >+ { >+ .domain = "BUILTIN", >+ .sid = _SID1(5, 32), /* S-1-5-32 */ >+ .num_names = ARRAY_SIZE(predefined_names_S_1_5_32), >+ .names = predefined_names_S_1_5_32, >+ }, >+ /* >+ * 'NT AUTHORITY' again with S-1-5-64 this time >+ */ >+ { >+ .domain = "NT AUTHORITY", >+ .sid = _SID1(5, 64), /* S-1-5-64 */ >+ .num_names = ARRAY_SIZE(predefined_names_S_1_5_64), >+ .names = predefined_names_S_1_5_64, >+ }, >+ { >+ .domain = "Internet$", >+ .sid = _SID0(7), /* S-1-7 */ >+ .num_names = ARRAY_SIZE(predefined_names_S_1_7), >+ .names = predefined_names_S_1_7, >+ }, >+ { >+ .domain = "Mandatory Label", >+ .sid = _SID0(16), /* S-1-16 */ >+ .num_names = ARRAY_SIZE(predefined_names_S_1_16), >+ .names = predefined_names_S_1_16, >+ }, >+}; >+ >+NTSTATUS dom_sid_lookup_predefined_name(const char *name, >+ const struct dom_sid **sid, >+ enum lsa_SidType *type, >+ const struct dom_sid **authority_sid, >+ const char **authority_name) >+{ >+ size_t di; >+ const char *domain = ""; >+ size_t domain_len = 0; >+ const char *p; >+ bool match; >+ >+ *sid = NULL; >+ *type = SID_NAME_UNKNOWN; >+ *authority_sid = NULL; >+ *authority_name = NULL; >+ >+ if (name == NULL) { >+ name = ""; >+ } >+ >+ p = strchr(name, '\\'); >+ if (p != NULL) { >+ domain = name; >+ domain_len = PTR_DIFF(p, domain); >+ name = p + 1; >+ } >+ >+ match = strequal(name, ""); >+ if (match) { >+ /* >+ * Strange, but that's what W2012R2 does. >+ */ >+ name = "BUILTIN"; >+ } >+ >+ for (di = 0; di < ARRAY_SIZE(predefined_domains); di++) { >+ const struct predefined_domain_mapping *d = >+ &predefined_domains[di]; >+ size_t ni; >+ >+ if (domain_len != 0) { >+ int cmp; >+ >+ cmp = strncasecmp(d->domain, domain, domain_len); >+ if (cmp != 0) { >+ continue; >+ } >+ } >+ >+ for (ni = 0; ni < d->num_names; ni++) { >+ const struct predefined_name_mapping *n = >+ &d->names[ni]; >+ >+ match = strequal(n->name, name); >+ if (!match) { >+ continue; >+ } >+ >+ *sid = &n->sid; >+ *type = n->type; >+ *authority_sid = &d->sid; >+ *authority_name = d->domain; >+ return NT_STATUS_OK; >+ } >+ } >+ >+ return NT_STATUS_NONE_MAPPED; >+} >+ >+NTSTATUS dom_sid_lookup_predefined_sid(const struct dom_sid *sid, >+ const char **name, >+ enum lsa_SidType *type, >+ const struct dom_sid **authority_sid, >+ const char **authority_name) >+{ >+ size_t di; >+ bool match_domain = false; >+ >+ *name = NULL; >+ *type = SID_NAME_UNKNOWN; >+ *authority_sid = NULL; >+ *authority_name = NULL; >+ >+ if (sid == NULL) { >+ return NT_STATUS_INVALID_SID; >+ } >+ >+ for (di = 0; di < ARRAY_SIZE(predefined_domains); di++) { >+ const struct predefined_domain_mapping *d = >+ &predefined_domains[di]; >+ size_t ni; >+ int cmp; >+ >+ cmp = dom_sid_compare_auth(&d->sid, sid); >+ if (cmp != 0) { >+ continue; >+ } >+ >+ match_domain = true; >+ >+ for (ni = 0; ni < d->num_names; ni++) { >+ const struct predefined_name_mapping *n = >+ &d->names[ni]; >+ >+ cmp = dom_sid_compare(&n->sid, sid); >+ if (cmp != 0) { >+ continue; >+ } >+ >+ *name = n->name; >+ *type = n->type; >+ *authority_sid = &d->sid; >+ *authority_name = d->domain; >+ return NT_STATUS_OK; >+ } >+ } >+ >+ if (!match_domain) { >+ return NT_STATUS_INVALID_SID; >+ } >+ >+ return NT_STATUS_NONE_MAPPED; >+} >-- >2.13.6 > > >From bdd4573449c862edb5f4e3baed3760724162cd91 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 15 Feb 2018 10:30:28 +0100 >Subject: [PATCH 19/22] test_trust_ntlm.sh: add lookup name tests > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit 475a761637bbcc93edbe8d83fc13037e1087941a) >--- > selftest/knownfail.d/s3-lsa-server | 1 + > selftest/knownfail.d/s4-lsa-server | 2 + > testprogs/blackbox/test_trust_ntlm.sh | 77 +++++++++++++++++++++++++++-------- > 3 files changed, 62 insertions(+), 18 deletions(-) > create mode 100644 selftest/knownfail.d/s3-lsa-server > create mode 100644 selftest/knownfail.d/s4-lsa-server > >diff --git a/selftest/knownfail.d/s3-lsa-server b/selftest/knownfail.d/s3-lsa-server >new file mode 100644 >index 00000000000..de1244f6746 >--- /dev/null >+++ b/selftest/knownfail.d/s3-lsa-server >@@ -0,0 +1 @@ >+^samba4.blackbox.trust_ntlm.Test08.rpcclient.lookupnames.with.ADDOM.SAMBA.EXAMPLE.COM\(ad_member:local\) >diff --git a/selftest/knownfail.d/s4-lsa-server b/selftest/knownfail.d/s4-lsa-server >new file mode 100644 >index 00000000000..86365e2868c >--- /dev/null >+++ b/selftest/knownfail.d/s4-lsa-server >@@ -0,0 +1,2 @@ >+^samba4.blackbox.trust_ntlm.Test07.rpcclient.lookupnames.with.ADDOMAIN.*fl20 >+^samba4.blackbox.trust_ntlm.Test08.rpcclient.lookupnames.with.ADDOM.SAMBA.EXAMPLE.COM.*fl20 >diff --git a/testprogs/blackbox/test_trust_ntlm.sh b/testprogs/blackbox/test_trust_ntlm.sh >index 44946bb9262..101303ede26 100755 >--- a/testprogs/blackbox/test_trust_ntlm.sh >+++ b/testprogs/blackbox/test_trust_ntlm.sh >@@ -36,19 +36,35 @@ unc="//$SERVER/tmp" > . `dirname $0`/subunit.sh > . `dirname $0`/common_test_fns.inc > >-CREDS="$DOMAIN\\$USERNAME%$PASSWORD" >-WBCREDS="$DOMAIN/$USERNAME%$PASSWORD" >+DNAME="$DOMAIN" >+NAME="$DNAME\\$USERNAME" >+WBNAME="$DNAME/$USERNAME" >+CREDS="$NAME%$PASSWORD" >+WBCREDS="$WBNAME%$PASSWORD" > EXPCREDS="Account Name: $USERNAME, Authority Name: $DOMAIN" >+EXPSID="(User: 1)" >+EXPDSID="(Domain: 3)" > test_rpcclient_grep "Test01 rpcclient getusername with $CREDS" getusername "$SERVER" "$EXPCREDS" -U$CREDS || failed=`expr $failed + 1` > test_smbclient "Test01 smbclient with $CREDS" 'ls' "$unc" -U$CREDS || failed=`expr $failed + 1` > testit "Test01 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS || failed=`expr $failed + 1` >- >-CREDS="$REALM\\$USERNAME%$PASSWORD" >-WBCREDS="$REALM/$USERNAME%$PASSWORD" >+test_rpcclient_grep "Test01 rpcclient lookupnames with $NAME" "lookupnames_level 1 '$NAME'" "$SERVER" "$EXPSID" -U$CREDS || failed=`expr $failed + 1` >+testit "Test01 wbinfo -n with $WBNAME" $VALGRIND $wbinfo -n "$WBNAME" || failed=`expr $failed + 1` >+test_rpcclient_grep "Test01 rpcclient lookupnames with $DNAME" "lookupnames_level 1 '$DNAME'" "$SERVER" "$EXPDSID" -U$CREDS || failed=`expr $failed + 1` >+ >+DNAME="$REALM" >+NAME="$DNAME\\$USERNAME" >+WBNAME="$DNAME/$USERNAME" >+CREDS="$NAME%$PASSWORD" >+WBCREDS="$WBNAME%$PASSWORD" > EXPCREDS="Account Name: $USERNAME, Authority Name: $DOMAIN" >+EXPSID="(User: 1)" >+EXPDSID="(Domain: 3)" > test_rpcclient_grep "Test02 rpcclient getusername with $CREDS" getusername "$SERVER" "$EXPCREDS" -U$CREDS || failed=`expr $failed + 1` > test_smbclient "Test02 smbclient with $CREDS" 'ls' "$unc" -U$CREDS || failed=`expr $failed + 1` > testit "Test02 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS || failed=`expr $failed + 1` >+test_rpcclient_grep "Test02 rpcclient lookupnames with $NAME" "lookupnames_level 1 '$NAME'" "$SERVER" "$EXPSID" -U$CREDS || failed=`expr $failed + 1` >+testit "Test02 wbinfo -n with $WBNAME" $VALGRIND $wbinfo -n "$WBNAME" || failed=`expr $failed + 1` >+test_rpcclient_grep "Test02 rpcclient lookupnames with $DNAME" "lookupnames_level 1 '$DNAME'" "$SERVER" "$EXPDSID" -U$CREDS || failed=`expr $failed + 1` > > CREDS="$USERNAME@$DOMAIN%$PASSWORD" > WBCREDS="$USERNAME@$DOMAIN%$PASSWORD" >@@ -86,12 +102,20 @@ else > #testit "Test04 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS || failed=`expr $failed + 1` > fi > >-CREDS="UNKNOWNDOMAIN\\$USERNAME%$PASSWORD" >-WBCREDS="UNKNOWNDOMAIN/$USERNAME%$PASSWORD" >+DNAME="UNKNOWNDOMAIN" >+NAME="$DNAME\\$USERNAME" >+WBNAME="$DNAME/$USERNAME" >+CREDS="$NAME%$PASSWORD" >+WBCREDS="$WBNAME%$PASSWORD" > EXPCREDS="Account Name: $USERNAME, Authority Name: $DOMAIN" >+EXPSID="NT_STATUS_NONE_MAPPED" >+EXPDSID="NT_STATUS_NONE_MAPPED" > test_rpcclient_grep "Test05 rpcclient getusername with $CREDS" getusername "$SERVER" "$EXPCREDS" -U$CREDS || failed=`expr $failed + 1` > test_smbclient "Test05 smbclient with $CREDS" 'ls' "$unc" -U$CREDS || failed=`expr $failed + 1` > testit_expect_failure "Fail05 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS || failed=`expr $failed + 1` >+test_rpcclient_expect_failure_grep "Test05 rpcclient lookupnames with $NAME" "lookupnames_level 1 '$NAME'" "$SERVER" "$EXPSID" -U$CREDS || failed=`expr $failed + 1` >+testit_expect_failure "Test05 wbinfo -n with $WBNAME" $VALGRIND $wbinfo -n "$WBNAME" || failed=`expr $failed + 1` >+test_rpcclient_expect_failure_grep "Test05 rpcclient lookupnames with $DNAME" "lookupnames_level 1 '$DNAME'" "$SERVER" "$EXPDSID" -U$CREDS || failed=`expr $failed + 1` > > CREDS="$TRUST_DOMAIN\\$USERNAME%$PASSWORD" > WBCREDS="$TRUST_DOMAIN/$USERNAME%$PASSWORD" >@@ -100,19 +124,35 @@ test_rpcclient_expect_failure_grep "Fail06 rpcclient getusername with $CREDS" ge > test_smbclient_expect_failure "Fail06 smbclient with $CREDS" 'ls' "$unc" -U$CREDS && failed=`expr $failed + 1` > testit_expect_failure "Fail06 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS && failed=`expr $failed + 1` > >-CREDS="$TRUST_DOMAIN\\$TRUST_USERNAME%$TRUST_PASSWORD" >-WBCREDS="$TRUST_DOMAIN/$TRUST_USERNAME%$TRUST_PASSWORD" >+DNAME="$TRUST_DOMAIN" >+NAME="$DNAME\\$TRUST_USERNAME" >+WBNAME="$DNAME/$TRUST_USERNAME" >+CREDS="$NAME%$TRUST_PASSWORD" >+WBCREDS="$WBNAME%$TRUST_PASSWORD" > EXPCREDS="Account Name: $TRUST_USERNAME, Authority Name: $TRUST_DOMAIN" >+EXPSID="(User: 1)" >+EXPDSID="(Domain: 3)" > test_rpcclient_grep "Test07 rpcclient getusername with $CREDS" getusername "$SERVER" "$EXPCREDS" -U$CREDS || failed=`expr $failed + 1` > test_smbclient "Test07 smbclient with $CREDS" 'ls' "$unc" -U$CREDS || failed=`expr $failed + 1` > testit "Test07 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS || failed=`expr $failed + 1` >- >-CREDS="$TRUST_REALM\\$TRUST_USERNAME%$TRUST_PASSWORD" >-WBCREDS="$TRUST_REALM/$TRUST_USERNAME%$TRUST_PASSWORD" >+test_rpcclient_grep "Test07 rpcclient lookupnames with $NAME" "lookupnames_level 1 '$NAME'" "$SERVER" "$EXPSID" -U$CREDS || failed=`expr $failed + 1` >+testit "Test07 wbinfo -n with $WBNAME" $VALGRIND $wbinfo -n "$WBNAME" || failed=`expr $failed + 1` >+test_rpcclient_grep "Test07 rpcclient lookupnames with $DNAME" "lookupnames_level 1 '$DNAME'" "$SERVER" "$EXPDSID" -U$CREDS || failed=`expr $failed + 1` >+ >+DNAME="$TRUST_REALM" >+NAME="$DNAME\\$TRUST_USERNAME" >+WBNAME="$DNAME/$TRUST_USERNAME" >+CREDS="$NAME%$TRUST_PASSWORD" >+WBCREDS="$WBNAME%$TRUST_PASSWORD" > EXPCREDS="Account Name: $TRUST_USERNAME, Authority Name: $TRUST_DOMAIN" >+EXPSID="(User: 1)" >+EXPDSID="(Domain: 3)" > test_rpcclient_grep "Test08 rpcclient getusername with $CREDS" getusername "$SERVER" "$EXPCREDS" -U$CREDS || failed=`expr $failed + 1` > test_smbclient "Test08 smbclient with $CREDS" 'ls' "$unc" -U$CREDS || failed=`expr $failed + 1` > testit "Test08 wbinfo -a with $WBCREDS" $VALGRIND $wbinfo -a $WBCREDS || failed=`expr $failed + 1` >+test_rpcclient_grep "Test08 rpcclient lookupnames with $NAME" "lookupnames_level 1 '$NAME'" "$SERVER" "$EXPSID" -U$CREDS || failed=`expr $failed + 1` >+testit "Test08 wbinfo -n with $WBNAME" $VALGRIND $wbinfo -n "$WBNAME" || failed=`expr $failed + 1` >+test_rpcclient_grep "Test08 rpcclient lookupnames with $DNAME" "lookupnames_level 1 '$DNAME'" "$SERVER" "$EXPDSID" -U$CREDS || failed=`expr $failed + 1` > > CREDS="$TRUST_USERNAME@$TRUST_DOMAIN%$TRUST_PASSWORD" > WBCREDS="$TRUST_USERNAME@$TRUST_DOMAIN%$TRUST_PASSWORD" >@@ -154,11 +194,12 @@ fi > > lowerrealm=$(echo $TRUST_REALM | tr '[A-Z]' '[a-z]') > >-if test x$TYPE = x"forest"; then >- >-fi >- >-if test x$UNTRUSTED = x"yes"; then >+#if test x$TYPE = x"forest"; then >+# >+#fi >+# >+#if test x$UNTRUSTED = x"yes"; then >+# >+#fi > >-fi > exit $failed >-- >2.13.6 > > >From 2ef30e6da7cc848fe799874fecb29995ddaa9deb Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 23 Jan 2018 00:52:50 +0100 >Subject: [PATCH 20/22] s4:rpc_server/lsa: rewrite lookup sids/names code to > honor the given lookup level > >[MS-LSAT] 2.2.16 LSAP_LOOKUP_LEVEL defines the which views each level should >consult. > >Up to now we support some wellknown sids, the builtin domain and our >account domain, but all levels query all views. > >This commit implements 3 views (predefined, builtin, account domain) >+ a dummy winbind view (which will later be used to implement the >gc, forest and trust views).. > >Depending on the level we select the required views. > >This might not be perfect in all details, but it's enough >to pass all existing tests, which already revealed bugs >during the development of this patch. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit 3801c417db5891ee4a45b09e8841d8f1ff4500f9) >--- > source4/rpc_server/lsa/lsa_lookup.c | 1412 +++++++++++++++++++++-------------- > 1 file changed, 855 insertions(+), 557 deletions(-) > >diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c >index 83043cbe17e..8da537c2951 100644 >--- a/source4/rpc_server/lsa/lsa_lookup.c >+++ b/source4/rpc_server/lsa/lsa_lookup.c >@@ -21,473 +21,160 @@ > */ > > #include "rpc_server/lsa/lsa.h" >+#include "libds/common/roles.h" > #include "libds/common/flag_mapping.h" > >-static const struct { >- const char *domain; >+struct dcesrv_lsa_TranslatedItem { >+ enum lsa_SidType type; >+ const struct dom_sid *sid; > const char *name; >- const char *sid; >- enum lsa_SidType rtype; >-} well_known[] = { >- { >- .name = "EVERYONE", >- .sid = SID_WORLD, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .name = "CREATOR OWNER", >- .sid = SID_CREATOR_OWNER, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .name = "CREATOR GROUP", >- .sid = SID_CREATOR_GROUP, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .name = "Owner Rights", >- .sid = SID_OWNER_RIGHTS, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "Dialup", >- .sid = SID_NT_DIALUP, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "Network", >- .sid = SID_NT_NETWORK, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "Batch", >- .sid = SID_NT_BATCH, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "Interactive", >- .sid = SID_NT_INTERACTIVE, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "Service", >- .sid = SID_NT_SERVICE, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "ANONYMOUS LOGON", >- .sid = SID_NT_ANONYMOUS, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "Proxy", >- .sid = SID_NT_PROXY, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "ServerLogon", >- .sid = SID_NT_ENTERPRISE_DCS, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "Self", >- .sid = SID_NT_SELF, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "Authenticated Users", >- .sid = SID_NT_AUTHENTICATED_USERS, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "Restricted", >- .sid = SID_NT_RESTRICTED, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "Terminal Server User", >- .sid = SID_NT_TERMINAL_SERVER_USERS, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "Remote Interactive Logon", >- .sid = SID_NT_REMOTE_INTERACTIVE, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "This Organization", >- .sid = SID_NT_THIS_ORGANISATION, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "SYSTEM", >- .sid = SID_NT_SYSTEM, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "Local Service", >- .sid = SID_NT_LOCAL_SERVICE, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "Network Service", >- .sid = SID_NT_NETWORK_SERVICE, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "Digest Authentication", >- .sid = SID_NT_DIGEST_AUTHENTICATION, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "Enterprise Domain Controllers", >- .sid = SID_NT_ENTERPRISE_DCS, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "NTLM Authentication", >- .sid = SID_NT_NTLM_AUTHENTICATION, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "Other Organization", >- .sid = SID_NT_OTHER_ORGANISATION, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "SChannel Authentication", >- .sid = SID_NT_SCHANNEL_AUTHENTICATION, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .domain = "NT AUTHORITY", >- .name = "IUSR", >- .sid = SID_NT_IUSR, >- .rtype = SID_NAME_WKN_GRP, >- }, >- { >- .sid = NULL, >- } >+ const char *authority_name; >+ const struct dom_sid *authority_sid; >+ uint32_t flags; >+ bool done; >+ struct { >+ const char *domain; /* only $DOMAIN\ */ >+ const char *namespace; /* $NAMESPACE\ or @$NAMESPACE */ >+ const char *principal; /* \$PRINCIPAL or $PRIN@IPAL */ >+ const char *sid; /* "S-1-5-21-9000-8000-7000-6000" */ >+ const char *rid; /* "00001770" */ >+ } hints; > }; > >-static NTSTATUS lookup_well_known_names(TALLOC_CTX *mem_ctx, const char *domain, >- const char *name, const char **authority_name, >- struct dom_sid **sid, enum lsa_SidType *rtype) >-{ >- unsigned int i; >- for (i=0; well_known[i].sid; i++) { >- if (domain) { >- if (strcasecmp_m(domain, well_known[i].domain) == 0 >- && strcasecmp_m(name, well_known[i].name) == 0) { >- *authority_name = well_known[i].domain; >- *sid = dom_sid_parse_talloc(mem_ctx, well_known[i].sid); >- *rtype = well_known[i].rtype; >- return NT_STATUS_OK; >- } >- } else { >- if (strcasecmp_m(name, well_known[i].name) == 0) { >- *authority_name = well_known[i].domain; >- *sid = dom_sid_parse_talloc(mem_ctx, well_known[i].sid); >- *rtype = well_known[i].rtype; >- return NT_STATUS_OK; >- } >- } >- } >- return NT_STATUS_NOT_FOUND; >-} >+struct dcesrv_lsa_LookupSids_base_state; >+struct dcesrv_lsa_LookupNames_base_state; > >-static NTSTATUS lookup_well_known_sids(TALLOC_CTX *mem_ctx, >- const char *sid_str, const char **authority_name, >- const char **name, enum lsa_SidType *rtype) >-{ >- unsigned int i; >- for (i=0; well_known[i].sid; i++) { >- if (strcasecmp_m(sid_str, well_known[i].sid) == 0) { >- *authority_name = well_known[i].domain; >- *name = well_known[i].name; >- *rtype = well_known[i].rtype; >- return NT_STATUS_OK; >- } >- } >- return NT_STATUS_NOT_FOUND; >-} >+struct dcesrv_lsa_Lookup_view { >+ const char *name; >+ NTSTATUS (*lookup_sid)(struct dcesrv_lsa_LookupSids_base_state *state, >+ struct dcesrv_lsa_TranslatedItem *item); >+ NTSTATUS (*lookup_name)(struct dcesrv_lsa_LookupNames_base_state *state, >+ struct dcesrv_lsa_TranslatedItem *item); >+}; >+ >+struct dcesrv_lsa_Lookup_view_table { >+ const char *name; >+ size_t count; >+ const struct dcesrv_lsa_Lookup_view **array; >+}; >+ >+static const struct dcesrv_lsa_Lookup_view_table *dcesrv_lsa_view_table( >+ enum lsa_LookupNamesLevel level); > > /* > lookup a SID for 1 name > */ >-static NTSTATUS dcesrv_lsa_lookup_name(struct tevent_context *ev_ctx, >- struct loadparm_context *lp_ctx, >- struct lsa_policy_state *state, TALLOC_CTX *mem_ctx, >- const char *name, const char **authority_name, >- struct dom_sid **sid, enum lsa_SidType *rtype, >- uint32_t *rid) >+static NTSTATUS dcesrv_lsa_lookup_name(struct lsa_policy_state *state, >+ TALLOC_CTX *mem_ctx, >+ const char *domain_name, >+ const struct dom_sid *domain_sid, >+ struct ldb_dn *domain_dn, >+ const char *principal, >+ const struct dom_sid **p_sid, >+ enum lsa_SidType *p_type) > { >- int ret, i; >- uint32_t atype; >- struct ldb_message **res; > const char * const attrs[] = { "objectSid", "sAMAccountType", NULL}; >- const char *p; >- const char *domain; >- const char *username; >- struct ldb_dn *domain_dn; >- struct dom_sid *domain_sid; >+ struct ldb_message **res = NULL; >+ const char *nt4_account = NULL; >+ char *encoded_account = NULL; >+ const char *at = NULL; > NTSTATUS status; >+ const struct dom_sid *sid = NULL; >+ uint32_t atype; >+ enum lsa_SidType type; >+ bool match = false; >+ int ret; >+ >+ if (principal == NULL && principal[0] == '\0') { >+ return NT_STATUS_NONE_MAPPED; >+ } >+ >+ at = strchr(principal, '@'); >+ if (at != NULL) { >+ const char *nt4_domain = NULL; > >- p = strchr_m(name, '\\'); >- if (p != NULL) { >- domain = talloc_strndup(mem_ctx, name, p-name); >- if (!domain) { >- return NT_STATUS_NO_MEMORY; >- } >- username = p + 1; >- } else if (strchr_m(name, '@')) { > status = crack_name_to_nt4_name(mem_ctx, > state->sam_ldb, > DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL, >- name, &domain, &username); >+ principal, >+ &nt4_domain, >+ &nt4_account); > if (!NT_STATUS_IS_OK(status)) { >- DEBUG(3, ("Failed to crack name %s into an NT4 name: %s\n", name, nt_errstr(status))); >- return status; >- } >- } else { >- domain = NULL; >- username = name; >- } >- >- if (!domain) { >- /* Look up table of well known names */ >- status = lookup_well_known_names(mem_ctx, NULL, username, authority_name, sid, rtype); >- if (NT_STATUS_IS_OK(status)) { >- dom_sid_split_rid(NULL, *sid, NULL, rid); >- return NT_STATUS_OK; >- } >- >- if (username == NULL) { >- *authority_name = NAME_BUILTIN; >- *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN); >- if (*sid == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- *rtype = SID_NAME_DOMAIN; >- *rid = 0xFFFFFFFF; >- return NT_STATUS_OK; >- } >- >- if (strcasecmp_m(username, NAME_NT_AUTHORITY) == 0) { >- *authority_name = NAME_NT_AUTHORITY; >- *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY); >- if (*sid == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- *rtype = SID_NAME_DOMAIN; >- dom_sid_split_rid(NULL, *sid, NULL, rid); >- return NT_STATUS_OK; >- } >- if (strcasecmp_m(username, NAME_BUILTIN) == 0) { >- *authority_name = NAME_BUILTIN; >- *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN); >- if (*sid == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- *rtype = SID_NAME_DOMAIN; >- *rid = 0xFFFFFFFF; >- return NT_STATUS_OK; >- } >- if (strcasecmp_m(username, state->domain_dns) == 0) { >- *authority_name = talloc_strdup(mem_ctx, >- state->domain_name); >- if (*authority_name == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- *sid = dom_sid_dup(mem_ctx, state->domain_sid); >- if (*sid == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- *rtype = SID_NAME_DOMAIN; >- *rid = 0xFFFFFFFF; >- return NT_STATUS_OK; >- } >- if (strcasecmp_m(username, state->domain_name) == 0) { >- *authority_name = talloc_strdup(mem_ctx, >- state->domain_name); >- if (*authority_name == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- *sid = dom_sid_dup(mem_ctx, state->domain_sid); >- if (*sid == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- *rtype = SID_NAME_DOMAIN; >- *rid = 0xFFFFFFFF; >- return NT_STATUS_OK; >- } >- >- /* Perhaps this is a well known user? */ >- name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_NT_AUTHORITY, username); >- if (!name) { >- return NT_STATUS_NO_MEMORY; >- } >- status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid); >- if (NT_STATUS_IS_OK(status)) { >+ DEBUG(3, ("Failed to crack name %s into an NT4 name: %s\n", >+ principal, nt_errstr(status))); > return status; > } > >- /* Perhaps this is a BUILTIN user? */ >- name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_BUILTIN, username); >- if (!name) { >- return NT_STATUS_NO_MEMORY; >- } >- status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid); >- if (NT_STATUS_IS_OK(status)) { >- return status; >- } >- >- /* OK, I give up - perhaps we need to assume the user is in our domain? */ >- name = talloc_asprintf(mem_ctx, "%s\\%s", state->domain_name, username); >- if (!name) { >- return NT_STATUS_NO_MEMORY; >- } >- status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid); >- if (NT_STATUS_IS_OK(status)) { >- return status; >- } >- >- return STATUS_SOME_UNMAPPED; >- } else if (strcasecmp_m(domain, NAME_NT_AUTHORITY) == 0) { >- if (!*username) { >- *authority_name = NAME_NT_AUTHORITY; >- *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY); >- if (*sid == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- *rtype = SID_NAME_DOMAIN; >- dom_sid_split_rid(NULL, *sid, NULL, rid); >- return NT_STATUS_OK; >- } >- >- /* Look up table of well known names */ >- status = lookup_well_known_names(mem_ctx, domain, username, authority_name, >- sid, rtype); >- if (NT_STATUS_IS_OK(status)) { >- dom_sid_split_rid(NULL, *sid, NULL, rid); >+ match = strequal(nt4_domain, domain_name); >+ if (!match) { >+ /* >+ * TODO: handle multiple domains in a forest. >+ */ >+ return NT_STATUS_NONE_MAPPED; > } >- return status; >- } else if (strcasecmp_m(domain, NAME_BUILTIN) == 0) { >- *authority_name = NAME_BUILTIN; >- domain_dn = state->builtin_dn; >- } else if (strcasecmp_m(domain, state->domain_dns) == 0) { >- *authority_name = talloc_strdup(mem_ctx, >- state->domain_name); >- if (*authority_name == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- domain_dn = state->domain_dn; >- } else if (strcasecmp_m(domain, state->domain_name) == 0) { >- *authority_name = talloc_strdup(mem_ctx, >- state->domain_name); >- if (*authority_name == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- domain_dn = state->domain_dn; > } else { >- /* Not local, need to ask winbind in future */ >- return STATUS_SOME_UNMAPPED; >+ nt4_account = principal; > } > >- ret = gendb_search_dn(state->sam_ldb, mem_ctx, domain_dn, &res, attrs); >- if (ret != 1) { >- return NT_STATUS_INTERNAL_DB_CORRUPTION; >- } >- domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid"); >- if (domain_sid == NULL) { >- return NT_STATUS_INVALID_SID; >+ encoded_account = ldb_binary_encode_string(mem_ctx, nt4_account); >+ if (encoded_account == NULL) { >+ return NT_STATUS_NO_MEMORY; > } > >- if (!*username) { >- *sid = domain_sid; >- *rtype = SID_NAME_DOMAIN; >- *rid = 0xFFFFFFFF; >- return NT_STATUS_OK; >- } >- > ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs, > "(&(sAMAccountName=%s)(objectSid=*))", >- ldb_binary_encode_string(mem_ctx, username)); >+ encoded_account); >+ TALLOC_FREE(encoded_account); > if (ret < 0) { >- return NT_STATUS_INTERNAL_DB_CORRUPTION; >+ return NT_STATUS_INTERNAL_DB_ERROR; >+ } >+ if (ret == 0) { >+ return NT_STATUS_NONE_MAPPED; >+ } >+ if (ret > 1) { >+ status = NT_STATUS_INTERNAL_DB_CORRUPTION; >+ DBG_ERR("nt4_account[%s] found %d times (principal[%s]) - %s\n", >+ nt4_account, ret, principal, nt_errstr(status)); >+ return status; > } > >- for (i=0; i < ret; i++) { >- *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid"); >- if (*sid == NULL) { >- return NT_STATUS_INVALID_SID; >- } >- >- /* Check that this is in the domain */ >- if (!dom_sid_in_domain(domain_sid, *sid)) { >- continue; >- } >- >- atype = ldb_msg_find_attr_as_uint(res[i], "sAMAccountType", 0); >- >- *rtype = ds_atype_map(atype); >- if (*rtype == SID_NAME_UNKNOWN) { >- return STATUS_SOME_UNMAPPED; >- } >+ sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid"); >+ if (sid == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } > >- dom_sid_split_rid(NULL, *sid, NULL, rid); >- return NT_STATUS_OK; >+ /* Check that this is in the domain */ >+ match = dom_sid_in_domain(domain_sid, sid); >+ if (!match) { >+ return NT_STATUS_NONE_MAPPED; > } > >- /* need to check for an allocated sid */ >+ atype = ldb_msg_find_attr_as_uint(res[0], "sAMAccountType", 0); >+ type = ds_atype_map(atype); >+ if (type == SID_NAME_UNKNOWN) { >+ return NT_STATUS_NONE_MAPPED; >+ } > >- return NT_STATUS_INVALID_SID; >+ *p_sid = sid; >+ *p_type = type; >+ return NT_STATUS_OK; > } > > > /* > add to the lsa_RefDomainList for LookupSids and LookupNames > */ >-static NTSTATUS dcesrv_lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx, >- enum lsa_SidType rtype, >- const char *authority_name, >- struct dom_sid *sid, >+static NTSTATUS dcesrv_lsa_authority_list(const char *authority_name, >+ const struct dom_sid *authority_sid, > struct lsa_RefDomainList *domains, > uint32_t *sid_index) > { >- struct dom_sid *authority_sid; > uint32_t i; > >- if (rtype != SID_NAME_DOMAIN) { >- authority_sid = dom_sid_dup(mem_ctx, sid); >- if (authority_sid == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- authority_sid->num_auths--; >- } else { >- authority_sid = sid; >+ *sid_index = UINT32_MAX; >+ >+ if (authority_name == NULL) { >+ return NT_STATUS_OK; > } > > /* see if we've already done this authority name */ >@@ -505,85 +192,77 @@ static NTSTATUS dcesrv_lsa_authority_list(struct lsa_policy_state *state, TALLOC > if (domains->domains == NULL) { > return NT_STATUS_NO_MEMORY; > } >- domains->domains[i].name.string = authority_name; >- domains->domains[i].sid = authority_sid; >+ domains->domains[i].name.string = talloc_strdup(domains->domains, >+ authority_name); >+ if (domains->domains[i].name.string == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ domains->domains[i].sid = dom_sid_dup(domains->domains, >+ authority_sid); >+ if (domains->domains[i].sid == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } > domains->count++; > domains->max_size = LSA_REF_DOMAIN_LIST_MULTIPLIER * domains->count; > *sid_index = i; >- >+ > return NT_STATUS_OK; > } > > /* > lookup a name for 1 SID > */ >-static NTSTATUS dcesrv_lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx, >- struct dom_sid *sid, const char *sid_str, >- const char **authority_name, >- const char **name, enum lsa_SidType *rtype) >+static NTSTATUS dcesrv_lsa_lookup_sid(struct lsa_policy_state *state, >+ TALLOC_CTX *mem_ctx, >+ const char *domain_name, >+ const struct dom_sid *domain_sid, >+ struct ldb_dn *domain_dn, >+ const struct dom_sid *sid, >+ const char **p_name, >+ enum lsa_SidType *p_type) > { >- NTSTATUS status; >- int ret; >+ const char * const attrs[] = { "sAMAccountName", "sAMAccountType", NULL}; >+ struct ldb_message **res = NULL; >+ char *encoded_sid = NULL; >+ const char *name = NULL; > uint32_t atype; >- struct ldb_message **res; >- struct ldb_dn *domain_dn; >- const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "cn", NULL}; >- >- status = lookup_well_known_sids(mem_ctx, sid_str, authority_name, name, rtype); >- if (NT_STATUS_IS_OK(status)) { >- return status; >- } >- >- if (dom_sid_equal(state->domain_sid, sid)) { >- *authority_name = talloc_strdup(mem_ctx, state->domain_name); >- if (*authority_name == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- *name = NULL; >- *rtype = SID_NAME_DOMAIN; >- return NT_STATUS_OK; >- } >- >- if (dom_sid_in_domain(state->domain_sid, sid)) { >- *authority_name = talloc_strdup(mem_ctx, state->domain_name); >- if (*authority_name == NULL) { >- return NT_STATUS_NO_MEMORY; >- } >- domain_dn = state->domain_dn; >- } else if (dom_sid_in_domain(state->builtin_sid, sid)) { >- *authority_name = NAME_BUILTIN; >- domain_dn = state->builtin_dn; >- } else { >- /* Not well known, our domain or built in */ >- >- /* In future, we must look at SID histories, and at trusted domains via winbind */ >+ enum lsa_SidType type; >+ int ret; > >- return NT_STATUS_NOT_FOUND; >+ encoded_sid = ldap_encode_ndr_dom_sid(mem_ctx, sid); >+ if (encoded_sid == NULL) { >+ return NT_STATUS_NO_MEMORY; > } > >- /* need to re-add a check for an allocated sid */ >- > ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs, >- "objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx, sid)); >- if ((ret < 0) || (ret > 1)) { >- return NT_STATUS_INTERNAL_DB_CORRUPTION; >+ "(&(objectSid=%s)(sAMAccountName=*))", encoded_sid); >+ TALLOC_FREE(encoded_sid); >+ if (ret < 0) { >+ return NT_STATUS_INTERNAL_DB_ERROR; > } > if (ret == 0) { >- return NT_STATUS_NOT_FOUND; >+ return NT_STATUS_NONE_MAPPED; >+ } >+ if (ret > 1) { >+ NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION; >+ DBG_ERR("sid[%s] found %d times - %s\n", >+ dom_sid_string(mem_ctx, sid), ret, nt_errstr(status)); >+ return status; > } > >- *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL); >- if (!*name) { >- *name = ldb_msg_find_attr_as_string(res[0], "cn", NULL); >- if (!*name) { >- *name = talloc_strdup(mem_ctx, sid_str); >- NT_STATUS_HAVE_NO_MEMORY(*name); >- } >+ name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL); >+ if (name == NULL) { >+ return NT_STATUS_INTERNAL_ERROR; > } > > atype = ldb_msg_find_attr_as_uint(res[0], "sAMAccountType", 0); >- *rtype = ds_atype_map(atype); >+ type = ds_atype_map(atype); >+ if (type == SID_NAME_UNKNOWN) { >+ return NT_STATUS_NONE_MAPPED; >+ } > >+ *p_name = name; >+ *p_type = type; > return NT_STATUS_OK; > } > >@@ -596,6 +275,11 @@ struct dcesrv_lsa_LookupSids_base_state { > > struct lsa_LookupSids3 r; > >+ const struct dcesrv_lsa_Lookup_view_table *view_table; >+ struct dcesrv_lsa_TranslatedItem *items; >+ >+ struct dsdb_trust_routing_table *routing_table; >+ > struct { > struct lsa_LookupSids *l; > struct lsa_LookupSids2 *l2; >@@ -603,12 +287,15 @@ struct dcesrv_lsa_LookupSids_base_state { > } _r; > }; > >+static NTSTATUS dcesrv_lsa_LookupSids_base_finish( >+ struct dcesrv_lsa_LookupSids_base_state *state); >+static void dcesrv_lsa_LookupSids_base_map( >+ struct dcesrv_lsa_LookupSids_base_state *state); >+ > static NTSTATUS dcesrv_lsa_LookupSids_base_call(struct dcesrv_lsa_LookupSids_base_state *state) > { >- struct lsa_policy_state *policy_state = state->policy_state; >- TALLOC_CTX *mem_ctx = state->mem_ctx; > struct lsa_LookupSids3 *r = &state->r; >- struct lsa_RefDomainList *domains = NULL; >+ uint32_t v; > uint32_t i; > > *r->out.domains = NULL; >@@ -616,69 +303,119 @@ static NTSTATUS dcesrv_lsa_LookupSids_base_call(struct dcesrv_lsa_LookupSids_bas > r->out.names->names = NULL; > *r->out.count = 0; > >- if (r->in.level < LSA_LOOKUP_NAMES_ALL || >- r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) { >+ state->view_table = dcesrv_lsa_view_table(r->in.level); >+ if (state->view_table == NULL) { > return NT_STATUS_INVALID_PARAMETER; > } > >- /* NOTE: the WSPP test suite tries SIDs with invalid revision numbers, >- and expects NT_STATUS_INVALID_PARAMETER back - we just treat it as >- an unknown SID. We could add a SID validator here. (tridge) >- MS-DTYP 2.4.2 >- */ >- >- domains = talloc_zero(r->out.domains, struct lsa_RefDomainList); >- if (domains == NULL) { >+ *r->out.domains = talloc_zero(r->out.domains, struct lsa_RefDomainList); >+ if (*r->out.domains == NULL) { > return NT_STATUS_NO_MEMORY; > } >- *r->out.domains = domains; > >- r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName2, >- r->in.sids->num_sids); >+ r->out.names->names = talloc_zero_array(r->out.names, >+ struct lsa_TranslatedName2, >+ r->in.sids->num_sids); > if (r->out.names->names == NULL) { > return NT_STATUS_NO_MEMORY; > } > >+ state->items = talloc_zero_array(state, >+ struct dcesrv_lsa_TranslatedItem, >+ r->in.sids->num_sids); >+ if (state->items == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ > for (i=0;i<r->in.sids->num_sids;i++) { >- struct dom_sid *sid = r->in.sids->sids[i].sid; >- char *sid_str = dom_sid_string(mem_ctx, sid); >- const char *name, *authority_name; >- enum lsa_SidType rtype; >- uint32_t sid_index; >- NTSTATUS status2; >+ struct dcesrv_lsa_TranslatedItem *item = &state->items[i]; >+ uint32_t rid = 0; > >- r->out.names->count++; >+ if (r->in.sids->sids[i].sid == NULL) { >+ return NT_STATUS_INVALID_PARAMETER; >+ } > >- r->out.names->names[i].sid_type = SID_NAME_UNKNOWN; >- r->out.names->names[i].name.string = sid_str; >- r->out.names->names[i].sid_index = 0xFFFFFFFF; >- r->out.names->names[i].unknown = 0; >+ item->type = SID_NAME_UNKNOWN; >+ item->sid = r->in.sids->sids[i].sid; > >- if (sid_str == NULL) { >- r->out.names->names[i].name.string = "(SIDERROR)"; >- continue; >+ item->hints.sid = dom_sid_string(state->items, item->sid); >+ if (item->hints.sid == NULL) { >+ return NT_STATUS_NO_MEMORY; > } > >- status2 = dcesrv_lsa_lookup_sid(policy_state, mem_ctx, sid, sid_str, >- &authority_name, &name, &rtype); >- if (!NT_STATUS_IS_OK(status2)) { >- continue; >+ dom_sid_split_rid(state->items, item->sid, NULL, &rid); >+ item->hints.rid = talloc_asprintf(state->items, >+ "%08X", (unsigned)rid); >+ if (item->hints.rid == NULL) { >+ return NT_STATUS_NO_MEMORY; > } >+ } > >- /* set up the authority table */ >- status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, rtype, >- authority_name, sid, >- domains, &sid_index); >- if (!NT_STATUS_IS_OK(status2)) { >- continue; >+ for (v=0; v < state->view_table->count; v++) { >+ const struct dcesrv_lsa_Lookup_view *view = >+ state->view_table->array[v]; >+ >+ for (i=0; i < r->in.sids->num_sids; i++) { >+ struct dcesrv_lsa_TranslatedItem *item = &state->items[i]; >+ NTSTATUS status; >+ >+ if (item->done) { >+ continue; >+ } >+ >+ status = view->lookup_sid(state, item); >+ if (NT_STATUS_IS_OK(status)) { >+ item->done = true; >+ } else if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) { >+ status = NT_STATUS_OK; >+ } else if (NT_STATUS_EQUAL(status, NT_STATUS_SOME_NOT_MAPPED)) { >+ status = NT_STATUS_OK; >+ } >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ } >+ } >+ >+ return dcesrv_lsa_LookupSids_base_finish(state); >+} >+ >+static NTSTATUS dcesrv_lsa_LookupSids_base_finish( >+ struct dcesrv_lsa_LookupSids_base_state *state) >+{ >+ struct lsa_LookupSids3 *r = &state->r; >+ uint32_t i; >+ >+ for (i=0;i<r->in.sids->num_sids;i++) { >+ struct dcesrv_lsa_TranslatedItem *item = &state->items[i]; >+ NTSTATUS status; >+ uint32_t sid_index = UINT32_MAX; >+ >+ status = dcesrv_lsa_authority_list(item->authority_name, >+ item->authority_sid, >+ *r->out.domains, >+ &sid_index); >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; > } > >- r->out.names->names[i].sid_type = rtype; >- r->out.names->names[i].name.string = name; >+ if (item->name == NULL && r->in.level == LSA_LOOKUP_NAMES_ALL) { >+ if (sid_index == UINT32_MAX) { >+ item->name = item->hints.sid; >+ } else { >+ item->name = item->hints.rid; >+ } >+ } >+ >+ r->out.names->names[i].sid_type = item->type; >+ r->out.names->names[i].name.string = item->name; > r->out.names->names[i].sid_index = sid_index; >- r->out.names->names[i].unknown = 0; >+ r->out.names->names[i].unknown = item->flags; > >- (*r->out.count)++; >+ r->out.names->count++; >+ if (item->type != SID_NAME_UNKNOWN) { >+ (*r->out.count)++; >+ } > } > > if (*r->out.count == 0) { >@@ -942,6 +679,11 @@ struct dcesrv_lsa_LookupNames_base_state { > > struct lsa_LookupNames4 r; > >+ const struct dcesrv_lsa_Lookup_view_table *view_table; >+ struct dcesrv_lsa_TranslatedItem *items; >+ >+ struct dsdb_trust_routing_table *routing_table; >+ > struct { > struct lsa_LookupNames *l; > struct lsa_LookupNames2 *l2; >@@ -950,15 +692,16 @@ struct dcesrv_lsa_LookupNames_base_state { > } _r; > }; > >+static NTSTATUS dcesrv_lsa_LookupNames_base_finish( >+ struct dcesrv_lsa_LookupNames_base_state *state); >+static void dcesrv_lsa_LookupNames_base_map( >+ struct dcesrv_lsa_LookupNames_base_state *state); > > static NTSTATUS dcesrv_lsa_LookupNames_base_call(struct dcesrv_lsa_LookupNames_base_state *state) > { >- struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx; >- struct dcesrv_call_state *dce_call = state->dce_call; >- struct lsa_policy_state *policy_state = state->policy_state; >- TALLOC_CTX *mem_ctx = state->mem_ctx; > struct lsa_LookupNames4 *r = &state->r; >- struct lsa_RefDomainList *domains = NULL; >+ enum lsa_LookupOptions invalid_lookup_options = 0; >+ uint32_t v; > uint32_t i; > > *r->out.domains = NULL; >@@ -966,58 +709,148 @@ static NTSTATUS dcesrv_lsa_LookupNames_base_call(struct dcesrv_lsa_LookupNames_b > r->out.sids->sids = NULL; > *r->out.count = 0; > >- if (r->in.level < LSA_LOOKUP_NAMES_ALL || >- r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) { >+ if (r->in.level != LSA_LOOKUP_NAMES_ALL) { >+ invalid_lookup_options |= >+ LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES_LOCAL; >+ } >+ if (r->in.lookup_options & invalid_lookup_options) { > return NT_STATUS_INVALID_PARAMETER; > } > >- domains = talloc_zero(r->out.domains, struct lsa_RefDomainList); >- if (domains == NULL) { >+ state->view_table = dcesrv_lsa_view_table(r->in.level); >+ if (state->view_table == NULL) { >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ *r->out.domains = talloc_zero(r->out.domains, struct lsa_RefDomainList); >+ if (*r->out.domains == NULL) { > return NT_STATUS_NO_MEMORY; > } >- *r->out.domains = domains; > >- r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid3, >- r->in.num_names); >+ r->out.sids->sids = talloc_zero_array(r->out.sids, >+ struct lsa_TranslatedSid3, >+ r->in.num_names); > if (r->out.sids->sids == NULL) { > return NT_STATUS_NO_MEMORY; > } > >+ state->items = talloc_zero_array(state, >+ struct dcesrv_lsa_TranslatedItem, >+ r->in.num_names); >+ if (state->items == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ > for (i=0;i<r->in.num_names;i++) { >- const char *name = r->in.names[i].string; >- const char *authority_name; >- struct dom_sid *sid; >- uint32_t sid_index, rid; >- enum lsa_SidType rtype; >- NTSTATUS status2; >+ struct dcesrv_lsa_TranslatedItem *item = &state->items[i]; >+ char *p = NULL; >+ >+ item->type = SID_NAME_UNKNOWN; >+ item->name = r->in.names[i].string; >+ /* >+ * Note: that item->name can be NULL! >+ * >+ * See test_LookupNames_NULL() in >+ * source4/torture/rpc/lsa.c >+ * >+ * nt4 returns NT_STATUS_NONE_MAPPED with sid_type >+ * SID_NAME_UNKNOWN, rid 0, and sid_index -1; >+ * >+ * w2k3/w2k8 return NT_STATUS_OK with sid_type >+ * SID_NAME_DOMAIN, rid -1 and sid_index 0 and BUILTIN domain >+ */ >+ if (item->name == NULL) { >+ continue; >+ } > >- r->out.sids->count++; >+ item->hints.principal = item->name; >+ p = strchr(item->name, '\\'); >+ if (p != NULL && p != item->name) { >+ item->hints.domain = talloc_strndup(state->items, >+ item->name, >+ p - item->name); >+ if (item->hints.domain == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ item->hints.namespace = item->hints.domain; >+ p++; >+ if (p[0] == '\0') { >+ /* >+ * This is just 'BUILTIN\'. >+ */ >+ item->hints.principal = NULL; >+ } else { >+ item->hints.principal = p; >+ } >+ } >+ if (item->hints.domain == NULL) { >+ p = strchr(item->name, '@'); >+ if (p != NULL && p != item->name && p[1] != '\0') { >+ item->hints.namespace = p + 1; >+ } >+ } >+ } > >- r->out.sids->sids[i].sid_type = SID_NAME_UNKNOWN; >- r->out.sids->sids[i].sid = NULL; >- r->out.sids->sids[i].sid_index = 0xFFFFFFFF; >- r->out.sids->sids[i].flags = 0; >+ for (v=0; v < state->view_table->count; v++) { >+ const struct dcesrv_lsa_Lookup_view *view = >+ state->view_table->array[v]; > >- status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, policy_state, mem_ctx, name, >- &authority_name, &sid, &rtype, &rid); >- if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) { >- continue; >+ for (i=0; i < r->in.num_names; i++) { >+ struct dcesrv_lsa_TranslatedItem *item = &state->items[i]; >+ NTSTATUS status; >+ >+ if (item->done) { >+ continue; >+ } >+ >+ status = view->lookup_name(state, item); >+ if (NT_STATUS_IS_OK(status)) { >+ item->done = true; >+ } else if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) { >+ status = NT_STATUS_OK; >+ } else if (NT_STATUS_EQUAL(status, NT_STATUS_SOME_NOT_MAPPED)) { >+ status = NT_STATUS_OK; >+ } >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } > } >+ } > >- status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, rtype, authority_name, >- sid, domains, &sid_index); >- if (!NT_STATUS_IS_OK(status2)) { >- continue; >+ return dcesrv_lsa_LookupNames_base_finish(state); >+} >+ >+static NTSTATUS dcesrv_lsa_LookupNames_base_finish( >+ struct dcesrv_lsa_LookupNames_base_state *state) >+{ >+ struct lsa_LookupNames4 *r = &state->r; >+ uint32_t i; >+ >+ for (i=0;i<r->in.num_names;i++) { >+ struct dcesrv_lsa_TranslatedItem *item = &state->items[i]; >+ NTSTATUS status; >+ uint32_t sid_index = UINT32_MAX; >+ >+ status = dcesrv_lsa_authority_list(item->authority_name, >+ item->authority_sid, >+ *r->out.domains, >+ &sid_index); >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; > } > >- r->out.sids->sids[i].sid_type = rtype; >- r->out.sids->sids[i].sid = sid; >- r->out.sids->sids[i].sid_index = sid_index; >- r->out.sids->sids[i].flags = 0; >+ r->out.sids->sids[i].sid_type = item->type; >+ r->out.sids->sids[i].sid = discard_const_p(struct dom_sid, >+ item->sid); >+ r->out.sids->sids[i].sid_index = sid_index; >+ r->out.sids->sids[i].flags = item->flags; > >- (*r->out.count)++; >+ r->out.sids->count++; >+ if (item->type != SID_NAME_UNKNOWN) { >+ (*r->out.count)++; >+ } > } >- >+ > if (*r->out.count == 0) { > return NT_STATUS_NONE_MAPPED; > } >@@ -1401,3 +1234,468 @@ NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX * > return status; > } > >+static NTSTATUS dcesrv_lsa_lookup_name_predefined( >+ struct dcesrv_lsa_LookupNames_base_state *state, >+ struct dcesrv_lsa_TranslatedItem *item) >+{ >+ NTSTATUS status; >+ >+ status = dom_sid_lookup_predefined_name(item->name, >+ &item->sid, >+ &item->type, >+ &item->authority_sid, >+ &item->authority_name); >+ if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) { >+ return status; >+ } >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ >+ return NT_STATUS_OK; >+} >+ >+static NTSTATUS dcesrv_lsa_lookup_sid_predefined( >+ struct dcesrv_lsa_LookupSids_base_state *state, >+ struct dcesrv_lsa_TranslatedItem *item) >+{ >+ NTSTATUS status; >+ >+ status = dom_sid_lookup_predefined_sid(item->sid, >+ &item->name, >+ &item->type, >+ &item->authority_sid, >+ &item->authority_name); >+ if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) { >+ return status; >+ } >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ >+ return NT_STATUS_OK; >+} >+ >+static const struct dcesrv_lsa_Lookup_view view_predefined = { >+ .name = "Predefined", >+ .lookup_sid = dcesrv_lsa_lookup_sid_predefined, >+ .lookup_name = dcesrv_lsa_lookup_name_predefined, >+}; >+ >+static NTSTATUS dcesrv_lsa_lookup_name_builtin( >+ struct dcesrv_lsa_LookupNames_base_state *state, >+ struct dcesrv_lsa_TranslatedItem *item) >+{ >+ struct lsa_policy_state *policy_state = state->policy_state; >+ NTSTATUS status; >+ bool is_builtin = false; >+ >+ if (item->name == NULL) { >+ /* >+ * This should not be mapped. >+ */ >+ return NT_STATUS_OK; >+ } >+ >+ /* >+ * The predefined view already handled the BUILTIN domain. >+ * >+ * Now we just need to find the principal. >+ * >+ * We only allow 'BUILTIN\something' and >+ * not 'something@BUILTIN. >+ * >+ * And we try out best for just 'something'. >+ */ >+ is_builtin = strequal(item->hints.domain, NAME_BUILTIN); >+ if (!is_builtin && item->hints.domain != NULL) { >+ return NT_STATUS_NONE_MAPPED; >+ } >+ >+ status = dcesrv_lsa_lookup_name(state->policy_state, >+ state->mem_ctx, >+ NAME_BUILTIN, >+ policy_state->builtin_sid, >+ policy_state->builtin_dn, >+ item->hints.principal, >+ &item->sid, >+ &item->type); >+ if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) { >+ if (!is_builtin) { >+ return NT_STATUS_NONE_MAPPED; >+ } >+ /* >+ * We know we're authoritive >+ */ >+ status = NT_STATUS_OK; >+ } >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ >+ item->authority_name = NAME_BUILTIN; >+ item->authority_sid = policy_state->builtin_sid; >+ return NT_STATUS_OK; >+} >+ >+static NTSTATUS dcesrv_lsa_lookup_sid_builtin( >+ struct dcesrv_lsa_LookupSids_base_state *state, >+ struct dcesrv_lsa_TranslatedItem *item) >+{ >+ struct lsa_policy_state *policy_state = state->policy_state; >+ NTSTATUS status; >+ bool is_builtin = false; >+ >+ /* >+ * The predefined view already handled the BUILTIN domain. >+ * >+ * Now we just need to find the principal. >+ */ >+ is_builtin = dom_sid_in_domain(policy_state->builtin_sid, item->sid); >+ if (!is_builtin) { >+ return NT_STATUS_NONE_MAPPED; >+ } >+ >+ status = dcesrv_lsa_lookup_sid(state->policy_state, >+ state->mem_ctx, >+ NAME_BUILTIN, >+ policy_state->builtin_sid, >+ policy_state->builtin_dn, >+ item->sid, >+ &item->name, >+ &item->type); >+ if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) { >+ /* >+ * We know we're authoritive >+ */ >+ status = NT_STATUS_OK; >+ } >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ >+ item->authority_name = NAME_BUILTIN; >+ item->authority_sid = policy_state->builtin_sid; >+ return NT_STATUS_OK; >+} >+ >+static const struct dcesrv_lsa_Lookup_view view_builtin = { >+ .name = "Builtin", >+ .lookup_sid = dcesrv_lsa_lookup_sid_builtin, >+ .lookup_name = dcesrv_lsa_lookup_name_builtin, >+}; >+ >+static NTSTATUS dcesrv_lsa_lookup_name_account( >+ struct dcesrv_lsa_LookupNames_base_state *state, >+ struct dcesrv_lsa_TranslatedItem *item) >+{ >+ struct lsa_policy_state *policy_state = state->policy_state; >+ struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx; >+ struct lsa_LookupNames4 *r = &state->r; >+ NTSTATUS status; >+ int role; >+ bool (*is_local_match_fn)(struct loadparm_context *, const char *) = NULL; >+ bool is_domain = false; >+ bool try_lookup = false; >+ const char *check_domain_name = NULL; >+ >+ role = lpcfg_server_role(lp_ctx); >+ if (role == ROLE_ACTIVE_DIRECTORY_DC) { >+ is_local_match_fn = lpcfg_is_my_domain_or_realm; >+ } else { >+ is_local_match_fn = lpcfg_is_myname; >+ } >+ >+ if (item->name == NULL) { >+ /* >+ * This should not be mapped. >+ */ >+ return NT_STATUS_OK; >+ } >+ >+ if (item->hints.domain != NULL && item->hints.principal == NULL) { >+ /* >+ * This is 'DOMAIN\'. >+ */ >+ check_domain_name = item->hints.domain; >+ } else { >+ /* >+ * This is just 'DOMAIN'. >+ */ >+ check_domain_name = item->name; >+ } >+ is_domain = is_local_match_fn(lp_ctx, check_domain_name); >+ if (is_domain) { >+ item->type = SID_NAME_DOMAIN; >+ item->sid = policy_state->domain_sid; >+ item->authority_name = policy_state->domain_name; >+ item->authority_sid = policy_state->domain_sid; >+ return NT_STATUS_OK; >+ } >+ >+ if (r->in.lookup_options & LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES_LOCAL) { >+ if (item->hints.domain != item->hints.namespace) { >+ /* >+ * This means the client asked for an UPN, >+ * and it should not be mapped. >+ */ >+ return NT_STATUS_OK; >+ } >+ } >+ >+ if (item->hints.namespace != NULL) { >+ is_domain = is_local_match_fn(lp_ctx, item->hints.namespace); >+ try_lookup = is_domain; >+ } else { >+ try_lookup = true; >+ } >+ >+ if (!try_lookup) { >+ struct dcesrv_lsa_TranslatedItem tmp; >+ >+ tmp = *item; >+ status = dom_sid_lookup_predefined_name(item->hints.namespace, >+ &tmp.sid, >+ &tmp.type, >+ &tmp.authority_sid, >+ &tmp.authority_name); >+ if (NT_STATUS_IS_OK(status)) { >+ /* >+ * It should not be handled by us. >+ */ >+ return NT_STATUS_NONE_MAPPED; >+ } >+ if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) { >+ return status; >+ } >+ } >+ >+ if (!try_lookup) { >+ const struct lsa_TrustDomainInfoInfoEx *tdo = NULL; >+ const struct lsa_ForestTrustDomainInfo *di = NULL; >+ >+ if (state->routing_table == NULL) { >+ status = dsdb_trust_routing_table_load(policy_state->sam_ldb, >+ state, >+ &state->routing_table); >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ } >+ >+ tdo = dsdb_trust_domain_by_name(state->routing_table, >+ item->hints.namespace, >+ &di); >+ if (tdo == NULL) { >+ /* >+ * The name is not resolvable at all... >+ */ >+ return NT_STATUS_OK; >+ } >+ >+ if (!(tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) { >+ /* >+ * The name is not resolvable here >+ */ >+ return NT_STATUS_NONE_MAPPED; >+ } >+ >+ /* >+ * TODO: handle multiple domains in a forest together with >+ * LSA_LOOKUP_NAMES_PRIMARY_DOMAIN_ONLY >+ */ >+ is_domain = true; >+ try_lookup = true; >+ } >+ >+ if (!try_lookup) { >+ /* >+ * It should not be handled by us. >+ */ >+ return NT_STATUS_NONE_MAPPED; >+ } >+ >+ /* >+ * TODO: handle multiple domains in our forest. >+ */ >+ >+ status = dcesrv_lsa_lookup_name(state->policy_state, >+ state->mem_ctx, >+ policy_state->domain_name, >+ policy_state->domain_sid, >+ policy_state->domain_dn, >+ item->hints.principal, >+ &item->sid, >+ &item->type); >+ if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) { >+ if (!is_domain) { >+ return NT_STATUS_NONE_MAPPED; >+ } >+ /* >+ * We know we're authoritive >+ */ >+ status = NT_STATUS_OK; >+ } >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ >+ item->authority_name = policy_state->domain_name; >+ item->authority_sid = policy_state->domain_sid; >+ return NT_STATUS_OK; >+} >+ >+static NTSTATUS dcesrv_lsa_lookup_sid_account( >+ struct dcesrv_lsa_LookupSids_base_state *state, >+ struct dcesrv_lsa_TranslatedItem *item) >+{ >+ struct lsa_policy_state *policy_state = state->policy_state; >+ NTSTATUS status; >+ bool is_domain; >+ >+ is_domain = dom_sid_equal(policy_state->domain_sid, item->sid); >+ if (is_domain) { >+ item->type = SID_NAME_DOMAIN; >+ item->name = policy_state->domain_name; >+ item->authority_name = policy_state->domain_name; >+ item->authority_sid = policy_state->domain_sid; >+ return NT_STATUS_OK; >+ } >+ is_domain = dom_sid_in_domain(policy_state->domain_sid, item->sid); >+ if (!is_domain) { >+ return NT_STATUS_NONE_MAPPED; >+ } >+ >+ status = dcesrv_lsa_lookup_sid(state->policy_state, >+ state->mem_ctx, >+ policy_state->domain_name, >+ policy_state->domain_sid, >+ policy_state->domain_dn, >+ item->sid, >+ &item->name, >+ &item->type); >+ if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) { >+ /* >+ * We know we're authoritive >+ */ >+ status = NT_STATUS_OK; >+ } >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ >+ item->authority_name = policy_state->domain_name; >+ item->authority_sid = policy_state->domain_sid; >+ return NT_STATUS_OK; >+} >+ >+static const struct dcesrv_lsa_Lookup_view view_account = { >+ .name = "Account", >+ .lookup_sid = dcesrv_lsa_lookup_sid_account, >+ .lookup_name = dcesrv_lsa_lookup_name_account, >+}; >+ >+static NTSTATUS dcesrv_lsa_lookup_name_winbind( >+ struct dcesrv_lsa_LookupNames_base_state *state, >+ struct dcesrv_lsa_TranslatedItem *item) >+{ >+ return NT_STATUS_NONE_MAPPED; >+} >+ >+static NTSTATUS dcesrv_lsa_lookup_sid_winbind( >+ struct dcesrv_lsa_LookupSids_base_state *state, >+ struct dcesrv_lsa_TranslatedItem *item) >+{ >+ return NT_STATUS_NONE_MAPPED; >+} >+ >+static const struct dcesrv_lsa_Lookup_view view_winbind = { >+ .name = "Winbind", >+ .lookup_sid = dcesrv_lsa_lookup_sid_winbind, >+ .lookup_name = dcesrv_lsa_lookup_name_winbind, >+}; >+ >+static const struct dcesrv_lsa_Lookup_view *table_all_views[] = { >+ &view_predefined, >+ &view_builtin, >+ &view_account, >+ &view_winbind, >+}; >+ >+static const struct dcesrv_lsa_Lookup_view_table table_all = { >+ .name = "LSA_LOOKUP_NAMES_ALL", >+ .count = ARRAY_SIZE(table_all_views), >+ .array = table_all_views, >+}; >+ >+static const struct dcesrv_lsa_Lookup_view *table_domains_views[] = { >+ &view_account, >+ &view_winbind, >+}; >+ >+static const struct dcesrv_lsa_Lookup_view_table table_domains = { >+ .name = "LSA_LOOKUP_NAMES_DOMAINS_ONLY", >+ .count = ARRAY_SIZE(table_domains_views), >+ .array = table_domains_views, >+}; >+ >+static const struct dcesrv_lsa_Lookup_view *table_primary_views[] = { >+ &view_account, >+}; >+ >+static const struct dcesrv_lsa_Lookup_view_table table_primary = { >+ .name = "LSA_LOOKUP_NAMES_PRIMARY_DOMAIN_ONLY", >+ .count = ARRAY_SIZE(table_primary_views), >+ .array = table_primary_views, >+}; >+ >+static const struct dcesrv_lsa_Lookup_view *table_remote_views[] = { >+ &view_winbind, >+}; >+ >+static const struct dcesrv_lsa_Lookup_view_table table_gc = { >+ .name = "LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY", >+ .count = ARRAY_SIZE(table_domains_views), >+ .array = table_domains_views, >+}; >+ >+static const struct dcesrv_lsa_Lookup_view_table table_xreferral = { >+ .name = "LSA_LOOKUP_NAMES_FOREST_TRUSTS_ONLY", >+ .count = ARRAY_SIZE(table_remote_views), >+ .array = table_remote_views, >+}; >+ >+static const struct dcesrv_lsa_Lookup_view_table table_xresolve = { >+ .name = "LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY2", >+ .count = ARRAY_SIZE(table_domains_views), >+ .array = table_domains_views, >+}; >+ >+static const struct dcesrv_lsa_Lookup_view_table table_rodc = { >+ .name = "LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC", >+ .count = ARRAY_SIZE(table_remote_views), >+ .array = table_remote_views, >+}; >+ >+static const struct dcesrv_lsa_Lookup_view_table *dcesrv_lsa_view_table( >+ enum lsa_LookupNamesLevel level) >+{ >+ switch (level) { >+ case LSA_LOOKUP_NAMES_ALL: >+ return &table_all; >+ case LSA_LOOKUP_NAMES_DOMAINS_ONLY: >+ return &table_domains; >+ case LSA_LOOKUP_NAMES_PRIMARY_DOMAIN_ONLY: >+ return &table_primary; >+ case LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY: >+ return &table_gc; >+ case LSA_LOOKUP_NAMES_FOREST_TRUSTS_ONLY: >+ return &table_xreferral; >+ case LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY2: >+ return &table_xresolve; >+ case LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC: >+ return &table_rodc; >+ } >+ >+ return NULL; >+} >-- >2.13.6 > > >From b9c611fbe152da73c80993de8b2d959dab956647 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 23 Jan 2018 13:19:37 +0100 >Subject: [PATCH 21/22] winbindd: implement > wb_irpc_lsa_{LookupNames4,LookupSids3}() > >This will be used by the LSA Server on an AD DC to request remote views >from trusts. > >In future we should implement wb_lookupnames_send/recv similar to >wb_lookupsids_send/recv, but for now using wb_lookupname_send/recv in a loop >works as a first step. > >We also need to make use of req->in.level and req->in.client_revision >once we want to support more than one domain within our own forest. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit 3ffebee3de4aa313027779bc98cb6326fa17be85) >--- > source3/winbindd/winbindd_irpc.c | 408 +++++++++++++++++++++++++++++++++++++++ > 1 file changed, 408 insertions(+) > >diff --git a/source3/winbindd/winbindd_irpc.c b/source3/winbindd/winbindd_irpc.c >index 4101469ad99..e03312ec7af 100644 >--- a/source3/winbindd/winbindd_irpc.c >+++ b/source3/winbindd/winbindd_irpc.c >@@ -25,6 +25,10 @@ > #include "librpc/gen_ndr/ndr_winbind_c.h" > #include "source4/lib/messaging/irpc.h" > #include "librpc/gen_ndr/ndr_winbind.h" >+#include "librpc/gen_ndr/ndr_lsa.h" >+#include "librpc/gen_ndr/ndr_lsa_c.h" >+#include "libcli/security/dom_sid.h" >+#include "passdb/lookup_sid.h" /* only for LOOKUP_NAME_NO_NSS flag */ > > struct wb_irpc_forward_state { > struct irpc_message *msg; >@@ -330,6 +334,398 @@ static NTSTATUS wb_irpc_SendToSam(struct irpc_message *msg, > domain, IRPC_CALL_TIMEOUT); > } > >+struct wb_irpc_lsa_LookupSids3_state { >+ struct irpc_message *msg; >+ struct lsa_LookupSids3 *req; >+}; >+ >+static void wb_irpc_lsa_LookupSids3_done(struct tevent_req *subreq); >+ >+static NTSTATUS wb_irpc_lsa_LookupSids3_call(struct irpc_message *msg, >+ struct lsa_LookupSids3 *req) >+{ >+ struct wb_irpc_lsa_LookupSids3_state *state = NULL; >+ struct tevent_req *subreq = NULL; >+ struct dom_sid *sids = NULL; >+ uint32_t i; >+ >+ state = talloc_zero(msg, struct wb_irpc_lsa_LookupSids3_state); >+ if (state == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ state->msg = msg; >+ state->req = req; >+ >+ state->req->out.domains = talloc_zero(state->msg, >+ struct lsa_RefDomainList *); >+ if (state->req->out.domains == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ state->req->out.names = talloc_zero(state->msg, >+ struct lsa_TransNameArray2); >+ if (state->req->out.names == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ state->req->out.count = talloc_zero(state->msg, uint32_t); >+ if (state->req->out.count == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ state->req->out.names->names = talloc_zero_array(state->msg, >+ struct lsa_TranslatedName2, >+ req->in.sids->num_sids); >+ if (state->req->out.names->names == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ sids = talloc_zero_array(state, struct dom_sid, >+ req->in.sids->num_sids); >+ if (sids == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ for (i = 0; i < req->in.sids->num_sids; i++) { >+ if (req->in.sids->sids[i].sid == NULL) { >+ return NT_STATUS_REQUEST_NOT_ACCEPTED; >+ } >+ >+ sids[i] = *req->in.sids->sids[i].sid; >+ } >+ >+ subreq = wb_lookupsids_send(msg, >+ server_event_context(), >+ sids, req->in.sids->num_sids); >+ if (subreq == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ tevent_req_set_callback(subreq, wb_irpc_lsa_LookupSids3_done, state); >+ msg->defer_reply = true; >+ >+ return NT_STATUS_OK; >+} >+ >+static void wb_irpc_lsa_LookupSids3_done(struct tevent_req *subreq) >+{ >+ struct wb_irpc_lsa_LookupSids3_state *state = >+ tevent_req_callback_data(subreq, >+ struct wb_irpc_lsa_LookupSids3_state); >+ struct lsa_RefDomainList *domains = NULL; >+ struct lsa_TransNameArray *names = NULL; >+ NTSTATUS status; >+ uint32_t i; >+ >+ status = wb_lookupsids_recv(subreq, state->msg, >+ &domains, &names); >+ TALLOC_FREE(subreq); >+ if (!NT_STATUS_IS_OK(status)) { >+ DEBUG(0,("RPC callback failed for %s - %s\n", >+ __func__, nt_errstr(status))); >+ irpc_send_reply(state->msg, status); >+ return; >+ } >+ >+ if (names->count > state->req->in.sids->num_sids) { >+ status = NT_STATUS_INTERNAL_ERROR; >+ DEBUG(0,("RPC callback failed for %s - %s\n", >+ __func__, nt_errstr(status))); >+ irpc_send_reply(state->msg, status); >+ return; >+ } >+ >+ *state->req->out.domains = domains; >+ for (i = 0; i < names->count; i++) { >+ struct lsa_TranslatedName2 *n2 = >+ &state->req->out.names->names[i]; >+ >+ n2->sid_type = names->names[i].sid_type; >+ n2->name = names->names[i].name; >+ n2->sid_index = names->names[i].sid_index; >+ n2->unknown = 0; >+ >+ if (n2->sid_type != SID_NAME_UNKNOWN) { >+ (*state->req->out.count)++; >+ } >+ } >+ state->req->out.names->count = names->count; >+ >+ if (*state->req->out.count == 0) { >+ state->req->out.result = NT_STATUS_NONE_MAPPED; >+ } else if (*state->req->out.count != names->count) { >+ state->req->out.result = NT_STATUS_SOME_NOT_MAPPED; >+ } else { >+ state->req->out.result = NT_STATUS_OK; >+ } >+ >+ irpc_send_reply(state->msg, NT_STATUS_OK); >+ return; >+} >+ >+struct wb_irpc_lsa_LookupNames4_name { >+ void *state; >+ uint32_t idx; >+ const char *domain; >+ char *name; >+ struct dom_sid sid; >+ enum lsa_SidType type; >+ struct dom_sid *authority_sid; >+}; >+ >+struct wb_irpc_lsa_LookupNames4_state { >+ struct irpc_message *msg; >+ struct lsa_LookupNames4 *req; >+ struct wb_irpc_lsa_LookupNames4_name *names; >+ uint32_t num_pending; >+ uint32_t num_domain_sids; >+ struct dom_sid *domain_sids; >+}; >+ >+static void wb_irpc_lsa_LookupNames4_done(struct tevent_req *subreq); >+ >+static NTSTATUS wb_irpc_lsa_LookupNames4_call(struct irpc_message *msg, >+ struct lsa_LookupNames4 *req) >+{ >+ struct wb_irpc_lsa_LookupNames4_state *state = NULL; >+ struct tevent_req *subreq = NULL; >+ uint32_t i; >+ >+ >+ state = talloc_zero(msg, struct wb_irpc_lsa_LookupNames4_state); >+ if (state == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ state->msg = msg; >+ state->req = req; >+ >+ state->req->out.domains = talloc_zero(state->msg, >+ struct lsa_RefDomainList *); >+ if (state->req->out.domains == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ state->req->out.sids = talloc_zero(state->msg, >+ struct lsa_TransSidArray3); >+ if (state->req->out.sids == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ state->req->out.count = talloc_zero(state->msg, uint32_t); >+ if (state->req->out.count == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ state->req->out.sids->sids = talloc_zero_array(state->msg, >+ struct lsa_TranslatedSid3, >+ req->in.num_names); >+ if (state->req->out.sids->sids == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ state->names = talloc_zero_array(state, >+ struct wb_irpc_lsa_LookupNames4_name, >+ req->in.num_names); >+ if (state->names == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ for (i = 0; i < req->in.num_names; i++) { >+ struct wb_irpc_lsa_LookupNames4_name *nstate = >+ &state->names[i]; >+ char *p = NULL; >+ >+ if (req->in.names[i].string == NULL) { >+ DBG_ERR("%s: name[%s] NT_STATUS_REQUEST_NOT_ACCEPTED.\n", >+ __location__, req->in.names[i].string); >+ return NT_STATUS_REQUEST_NOT_ACCEPTED; >+ } >+ nstate->state = state; >+ nstate->idx = i; >+ nstate->name = talloc_strdup(state->names, >+ req->in.names[i].string); >+ if (nstate->name == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ nstate->type = SID_NAME_UNKNOWN; >+ >+ /* cope with the name being a fully qualified name */ >+ p = strchr(nstate->name, '\\'); >+ if (p != NULL) { >+ *p = 0; >+ nstate->domain = nstate->name; >+ nstate->name = p+1; >+ } else if ((p = strchr(nstate->name, '@')) != NULL) { >+ /* upn */ >+ nstate->domain = p + 1; >+ *p = 0; >+ } else { >+ /* >+ * TODO: select the domain based on >+ * req->in.level and req->in.client_revision >+ * >+ * For now we don't allow this. >+ */ >+ DBG_ERR("%s: name[%s] NT_STATUS_REQUEST_NOT_ACCEPTED.\n", >+ __location__, nstate->name); >+ return NT_STATUS_REQUEST_NOT_ACCEPTED; >+ } >+ >+ subreq = wb_lookupname_send(msg, >+ server_event_context(), >+ nstate->domain, >+ nstate->name, >+ LOOKUP_NAME_NO_NSS); >+ if (subreq == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ tevent_req_set_callback(subreq, >+ wb_irpc_lsa_LookupNames4_done, >+ nstate); >+ state->num_pending++; >+ } >+ >+ msg->defer_reply = true; >+ >+ return NT_STATUS_OK; >+} >+ >+static void wb_irpc_lsa_LookupNames4_domains_done(struct tevent_req *subreq); >+ >+static void wb_irpc_lsa_LookupNames4_done(struct tevent_req *subreq) >+{ >+ struct wb_irpc_lsa_LookupNames4_name *nstate = >+ (struct wb_irpc_lsa_LookupNames4_name *) >+ tevent_req_callback_data_void(subreq); >+ struct wb_irpc_lsa_LookupNames4_state *state = >+ talloc_get_type_abort(nstate->state, >+ struct wb_irpc_lsa_LookupNames4_state); >+ NTSTATUS status; >+ >+ SMB_ASSERT(state->num_pending > 0); >+ state->num_pending--; >+ status = wb_lookupname_recv(subreq, &nstate->sid, &nstate->type); >+ TALLOC_FREE(subreq); >+ if (!NT_STATUS_IS_OK(status)) { >+ DEBUG(0,("RPC callback failed for %s - %s\n", >+ __func__, nt_errstr(status))); >+ irpc_send_reply(state->msg, status); >+ return; >+ } >+ >+ status = dom_sid_split_rid(state, &nstate->sid, >+ &nstate->authority_sid, NULL); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("dom_sid_split_rid(%s) failed - %s\n", >+ sid_string_dbg(&nstate->sid), nt_errstr(status)); >+ irpc_send_reply(state->msg, status); >+ return; >+ } >+ >+ status = add_sid_to_array_unique(state, >+ nstate->authority_sid, >+ &state->domain_sids, >+ &state->num_domain_sids); >+ if (!NT_STATUS_IS_OK(status)) { >+ DBG_ERR("add_sid_to_array_unique(%s) failed - %s\n", >+ sid_string_dbg(nstate->authority_sid), nt_errstr(status)); >+ irpc_send_reply(state->msg, status); >+ return; >+ } >+ >+ if (state->num_pending > 0) { >+ /* >+ * wait for more... >+ */ >+ return; >+ } >+ >+ /* >+ * Now resolve all domains back to a name >+ * to get a good lsa_RefDomainList >+ */ >+ subreq = wb_lookupsids_send(state, >+ server_event_context(), >+ state->domain_sids, >+ state->num_domain_sids); >+ if (subreq == NULL) { >+ status = NT_STATUS_NO_MEMORY; >+ DBG_ERR("wb_lookupsids_send - %s\n", >+ nt_errstr(status)); >+ irpc_send_reply(state->msg, status); >+ return; >+ } >+ tevent_req_set_callback(subreq, >+ wb_irpc_lsa_LookupNames4_domains_done, >+ state); >+ >+ return; >+} >+ >+static void wb_irpc_lsa_LookupNames4_domains_done(struct tevent_req *subreq) >+{ >+ struct wb_irpc_lsa_LookupNames4_state *state = >+ tevent_req_callback_data(subreq, >+ struct wb_irpc_lsa_LookupNames4_state); >+ struct lsa_RefDomainList *domains = NULL; >+ struct lsa_TransNameArray *names = NULL; >+ NTSTATUS status; >+ uint32_t i; >+ >+ status = wb_lookupsids_recv(subreq, state->msg, >+ &domains, &names); >+ TALLOC_FREE(subreq); >+ if (!NT_STATUS_IS_OK(status)) { >+ DEBUG(0,("RPC callback failed for %s - %s\n", >+ __func__, nt_errstr(status))); >+ irpc_send_reply(state->msg, status); >+ return; >+ } >+ >+ *state->req->out.domains = domains; >+ for (i = 0; i < state->req->in.num_names; i++) { >+ struct wb_irpc_lsa_LookupNames4_name *nstate = >+ &state->names[i]; >+ struct lsa_TranslatedSid3 *s3 = >+ &state->req->out.sids->sids[i]; >+ uint32_t di; >+ >+ s3->sid_type = nstate->type; >+ if (s3->sid_type != SID_NAME_UNKNOWN) { >+ s3->sid = &nstate->sid; >+ } else { >+ s3->sid = NULL; >+ } >+ s3->sid_index = UINT32_MAX; >+ for (di = 0; di < domains->count; di++) { >+ bool match; >+ >+ if (domains->domains[di].sid == NULL) { >+ continue; >+ } >+ >+ match = dom_sid_equal(nstate->authority_sid, >+ domains->domains[di].sid); >+ if (match) { >+ s3->sid_index = di; >+ break; >+ } >+ } >+ if (s3->sid_type != SID_NAME_UNKNOWN) { >+ (*state->req->out.count)++; >+ } >+ } >+ state->req->out.sids->count = state->req->in.num_names; >+ >+ if (*state->req->out.count == 0) { >+ state->req->out.result = NT_STATUS_NONE_MAPPED; >+ } else if (*state->req->out.count != state->req->in.num_names) { >+ state->req->out.result = NT_STATUS_SOME_NOT_MAPPED; >+ } else { >+ state->req->out.result = NT_STATUS_OK; >+ } >+ >+ irpc_send_reply(state->msg, NT_STATUS_OK); >+ return; >+} >+ > NTSTATUS wb_irpc_register(void) > { > NTSTATUS status; >@@ -361,6 +757,18 @@ NTSTATUS wb_irpc_register(void) > if (!NT_STATUS_IS_OK(status)) { > return status; > } >+ status = IRPC_REGISTER(winbind_imessaging_context(), >+ lsarpc, LSA_LOOKUPSIDS3, >+ wb_irpc_lsa_LookupSids3_call, NULL); >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ status = IRPC_REGISTER(winbind_imessaging_context(), >+ lsarpc, LSA_LOOKUPNAMES4, >+ wb_irpc_lsa_LookupNames4_call, NULL); >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } > > return NT_STATUS_OK; > } >-- >2.13.6 > > >From 7fe54af5ccce16e1ac1df532789dff8fa36d6650 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 19 Jan 2018 13:42:40 +0100 >Subject: [PATCH 22/22] s4:rpc_server/lsa: implement forwarding > lsa_Lookup{Sids,Names}() requests to winbindd > >This might not be perfect yet, but it's enough to allow names from trusted >forests/domain to be resolved, which is very important for samba based >domain members. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=13286 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit e9d5b8b6b41155a8a043275ae497bdb87044d476) >--- > selftest/knownfail.d/s4-lsa-server | 2 - > source4/rpc_server/lsa/lsa_lookup.c | 527 +++++++++++++++++++++++++++++++++++- > 2 files changed, 525 insertions(+), 4 deletions(-) > delete mode 100644 selftest/knownfail.d/s4-lsa-server > >diff --git a/selftest/knownfail.d/s4-lsa-server b/selftest/knownfail.d/s4-lsa-server >deleted file mode 100644 >index 86365e2868c..00000000000 >--- a/selftest/knownfail.d/s4-lsa-server >+++ /dev/null >@@ -1,2 +0,0 @@ >-^samba4.blackbox.trust_ntlm.Test07.rpcclient.lookupnames.with.ADDOMAIN.*fl20 >-^samba4.blackbox.trust_ntlm.Test08.rpcclient.lookupnames.with.ADDOM.SAMBA.EXAMPLE.COM.*fl20 >diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c >index 8da537c2951..3baff1ec11f 100644 >--- a/source4/rpc_server/lsa/lsa_lookup.c >+++ b/source4/rpc_server/lsa/lsa_lookup.c >@@ -23,6 +23,8 @@ > #include "rpc_server/lsa/lsa.h" > #include "libds/common/roles.h" > #include "libds/common/flag_mapping.h" >+#include "lib/messaging/irpc.h" >+#include "librpc/gen_ndr/ndr_lsa_c.h" > > struct dcesrv_lsa_TranslatedItem { > enum lsa_SidType type; >@@ -31,6 +33,7 @@ struct dcesrv_lsa_TranslatedItem { > const char *authority_name; > const struct dom_sid *authority_sid; > uint32_t flags; >+ uint32_t wb_idx; > bool done; > struct { > const char *domain; /* only $DOMAIN\ */ >@@ -281,6 +284,15 @@ struct dcesrv_lsa_LookupSids_base_state { > struct dsdb_trust_routing_table *routing_table; > > struct { >+ struct dcerpc_binding_handle *irpc_handle; >+ struct lsa_SidArray sids; >+ struct lsa_RefDomainList *domains; >+ struct lsa_TransNameArray2 names; >+ uint32_t count; >+ NTSTATUS result; >+ } wb; >+ >+ struct { > struct lsa_LookupSids *l; > struct lsa_LookupSids2 *l2; > struct lsa_LookupSids3 *l3; >@@ -291,10 +303,12 @@ static NTSTATUS dcesrv_lsa_LookupSids_base_finish( > struct dcesrv_lsa_LookupSids_base_state *state); > static void dcesrv_lsa_LookupSids_base_map( > struct dcesrv_lsa_LookupSids_base_state *state); >+static void dcesrv_lsa_LookupSids_base_done(struct tevent_req *subreq); > > static NTSTATUS dcesrv_lsa_LookupSids_base_call(struct dcesrv_lsa_LookupSids_base_state *state) > { > struct lsa_LookupSids3 *r = &state->r; >+ struct tevent_req *subreq = NULL; > uint32_t v; > uint32_t i; > >@@ -377,7 +391,47 @@ static NTSTATUS dcesrv_lsa_LookupSids_base_call(struct dcesrv_lsa_LookupSids_bas > } > } > >- return dcesrv_lsa_LookupSids_base_finish(state); >+ if (state->wb.irpc_handle == NULL) { >+ return dcesrv_lsa_LookupSids_base_finish(state); >+ } >+ >+ state->wb.sids.sids = talloc_zero_array(state, struct lsa_SidPtr, >+ r->in.sids->num_sids); >+ if (state->wb.sids.sids == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ for (i=0; i < r->in.sids->num_sids; i++) { >+ struct dcesrv_lsa_TranslatedItem *item = &state->items[i]; >+ >+ if (item->done) { >+ continue; >+ } >+ >+ item->wb_idx = state->wb.sids.num_sids; >+ state->wb.sids.sids[item->wb_idx] = r->in.sids->sids[i]; >+ state->wb.sids.num_sids++; >+ } >+ >+ subreq = dcerpc_lsa_LookupSids3_send(state, >+ state->dce_call->event_ctx, >+ state->wb.irpc_handle, >+ &state->wb.sids, >+ &state->wb.domains, >+ &state->wb.names, >+ state->r.in.level, >+ &state->wb.count, >+ state->r.in.lookup_options, >+ state->r.in.client_revision); >+ if (subreq == NULL) { >+ return NT_STATUS_NO_MEMORY;; >+ } >+ state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC; >+ tevent_req_set_callback(subreq, >+ dcesrv_lsa_LookupSids_base_done, >+ state); >+ >+ return NT_STATUS_OK; > } > > static NTSTATUS dcesrv_lsa_LookupSids_base_finish( >@@ -467,6 +521,91 @@ static void dcesrv_lsa_LookupSids_base_map( > } > } > >+static void dcesrv_lsa_LookupSids_base_done(struct tevent_req *subreq) >+{ >+ struct dcesrv_lsa_LookupSids_base_state *state = >+ tevent_req_callback_data(subreq, >+ struct dcesrv_lsa_LookupSids_base_state); >+ struct dcesrv_call_state *dce_call = state->dce_call; >+ NTSTATUS status; >+ uint32_t i; >+ >+ status = dcerpc_lsa_LookupSids3_recv(subreq, state->mem_ctx, >+ &state->wb.result); >+ TALLOC_FREE(subreq); >+ if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { >+ DEBUG(0,(__location__ ": IRPC callback failed %s\n", >+ nt_errstr(status))); >+ goto finished; >+ } else if (!NT_STATUS_IS_OK(status)) { >+ state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM; >+ DEBUG(0,(__location__ ": IRPC callback failed %s\n", >+ nt_errstr(status))); >+ goto finished; >+ } >+ >+ status = state->wb.result; >+ if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) { >+ status = NT_STATUS_OK; >+ } else if (NT_STATUS_EQUAL(status, NT_STATUS_SOME_NOT_MAPPED)) { >+ status = NT_STATUS_OK; >+ } >+ if (!NT_STATUS_IS_OK(status)) { >+ goto finished; >+ } >+ >+ for (i=0; i < state->r.in.sids->num_sids; i++) { >+ struct dcesrv_lsa_TranslatedItem *item = &state->items[i]; >+ struct lsa_TranslatedName2 *s2 = NULL; >+ struct lsa_DomainInfo *d = NULL; >+ >+ if (item->done) { >+ continue; >+ } >+ >+ if (item->wb_idx >= state->wb.names.count) { >+ status = NT_STATUS_INTERNAL_ERROR; >+ goto finished; >+ } >+ >+ s2 = &state->wb.names.names[item->wb_idx]; >+ >+ item->type = s2->sid_type; >+ item->name = s2->name.string; >+ item->flags = s2->unknown; >+ >+ if (s2->sid_index == UINT32_MAX) { >+ continue; >+ } >+ >+ if (state->wb.domains == NULL) { >+ status = NT_STATUS_INTERNAL_ERROR; >+ goto finished; >+ } >+ >+ if (s2->sid_index >= state->wb.domains->count) { >+ status = NT_STATUS_INTERNAL_ERROR; >+ goto finished; >+ } >+ >+ d = &state->wb.domains->domains[s2->sid_index]; >+ >+ item->authority_name = d->name.string; >+ item->authority_sid = d->sid; >+ } >+ >+ status = dcesrv_lsa_LookupSids_base_finish(state); >+ finished: >+ state->r.out.result = status; >+ dcesrv_lsa_LookupSids_base_map(state); >+ TALLOC_FREE(state); >+ >+ status = dcesrv_reply(dce_call); >+ if (!NT_STATUS_IS_OK(status)) { >+ DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status))); >+ } >+} >+ > /* > lsa_LookupSids2 > */ >@@ -685,6 +824,16 @@ struct dcesrv_lsa_LookupNames_base_state { > struct dsdb_trust_routing_table *routing_table; > > struct { >+ struct dcerpc_binding_handle *irpc_handle; >+ uint32_t num_names; >+ struct lsa_String *names; >+ struct lsa_RefDomainList *domains; >+ struct lsa_TransSidArray3 sids; >+ uint32_t count; >+ NTSTATUS result; >+ } wb; >+ >+ struct { > struct lsa_LookupNames *l; > struct lsa_LookupNames2 *l2; > struct lsa_LookupNames3 *l3; >@@ -696,11 +845,13 @@ static NTSTATUS dcesrv_lsa_LookupNames_base_finish( > struct dcesrv_lsa_LookupNames_base_state *state); > static void dcesrv_lsa_LookupNames_base_map( > struct dcesrv_lsa_LookupNames_base_state *state); >+static void dcesrv_lsa_LookupNames_base_done(struct tevent_req *subreq); > > static NTSTATUS dcesrv_lsa_LookupNames_base_call(struct dcesrv_lsa_LookupNames_base_state *state) > { > struct lsa_LookupNames4 *r = &state->r; > enum lsa_LookupOptions invalid_lookup_options = 0; >+ struct tevent_req *subreq = NULL; > uint32_t v; > uint32_t i; > >@@ -817,7 +968,48 @@ static NTSTATUS dcesrv_lsa_LookupNames_base_call(struct dcesrv_lsa_LookupNames_b > } > } > >- return dcesrv_lsa_LookupNames_base_finish(state); >+ if (state->wb.irpc_handle == NULL) { >+ return dcesrv_lsa_LookupNames_base_finish(state); >+ } >+ >+ state->wb.names = talloc_zero_array(state, struct lsa_String, >+ r->in.num_names); >+ if (state->wb.names == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ for (i=0;i<r->in.num_names;i++) { >+ struct dcesrv_lsa_TranslatedItem *item = &state->items[i]; >+ >+ if (item->done) { >+ continue; >+ } >+ >+ item->wb_idx = state->wb.num_names; >+ state->wb.names[item->wb_idx] = r->in.names[i]; >+ state->wb.num_names++; >+ } >+ >+ subreq = dcerpc_lsa_LookupNames4_send(state, >+ state->dce_call->event_ctx, >+ state->wb.irpc_handle, >+ state->wb.num_names, >+ state->wb.names, >+ &state->wb.domains, >+ &state->wb.sids, >+ state->r.in.level, >+ &state->wb.count, >+ state->r.in.lookup_options, >+ state->r.in.client_revision); >+ if (subreq == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC; >+ tevent_req_set_callback(subreq, >+ dcesrv_lsa_LookupNames_base_done, >+ state); >+ >+ return NT_STATUS_OK; > } > > static NTSTATUS dcesrv_lsa_LookupNames_base_finish( >@@ -952,6 +1144,91 @@ static void dcesrv_lsa_LookupNames_base_map( > } > } > >+static void dcesrv_lsa_LookupNames_base_done(struct tevent_req *subreq) >+{ >+ struct dcesrv_lsa_LookupNames_base_state *state = >+ tevent_req_callback_data(subreq, >+ struct dcesrv_lsa_LookupNames_base_state); >+ struct dcesrv_call_state *dce_call = state->dce_call; >+ NTSTATUS status; >+ uint32_t i; >+ >+ status = dcerpc_lsa_LookupNames4_recv(subreq, state->mem_ctx, >+ &state->wb.result); >+ TALLOC_FREE(subreq); >+ if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { >+ DEBUG(0,(__location__ ": IRPC callback failed %s\n", >+ nt_errstr(status))); >+ goto finished; >+ } else if (!NT_STATUS_IS_OK(status)) { >+ state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM; >+ DEBUG(0,(__location__ ": IRPC callback failed %s\n", >+ nt_errstr(status))); >+ goto finished; >+ } >+ >+ status = state->wb.result; >+ if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) { >+ status = NT_STATUS_OK; >+ } else if (NT_STATUS_EQUAL(status, NT_STATUS_SOME_NOT_MAPPED)) { >+ status = NT_STATUS_OK; >+ } >+ if (!NT_STATUS_IS_OK(status)) { >+ goto finished; >+ } >+ >+ for (i=0; i < state->r.in.num_names;i++) { >+ struct dcesrv_lsa_TranslatedItem *item = &state->items[i]; >+ struct lsa_TranslatedSid3 *s3 = NULL; >+ struct lsa_DomainInfo *d = NULL; >+ >+ if (item->done) { >+ continue; >+ } >+ >+ if (item->wb_idx >= state->wb.sids.count) { >+ status = NT_STATUS_INTERNAL_ERROR; >+ goto finished; >+ } >+ >+ s3 = &state->wb.sids.sids[item->wb_idx]; >+ >+ item->type = s3->sid_type; >+ item->sid = s3->sid; >+ item->flags = s3->flags; >+ >+ if (s3->sid_index == UINT32_MAX) { >+ continue; >+ } >+ >+ if (state->wb.domains == NULL) { >+ status = NT_STATUS_INTERNAL_ERROR; >+ goto finished; >+ } >+ >+ if (s3->sid_index >= state->wb.domains->count) { >+ status = NT_STATUS_INTERNAL_ERROR; >+ goto finished; >+ } >+ >+ d = &state->wb.domains->domains[s3->sid_index]; >+ >+ item->authority_name = d->name.string; >+ item->authority_sid = d->sid; >+ } >+ >+ status = dcesrv_lsa_LookupNames_base_finish(state); >+ finished: >+ state->r.out.result = status; >+ dcesrv_lsa_LookupNames_base_map(state); >+ TALLOC_FREE(state); >+ >+ status = dcesrv_reply(dce_call); >+ if (!NT_STATUS_IS_OK(status)) { >+ DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status))); >+ } >+} >+ > /* > lsa_LookupNames3 > */ >@@ -1599,6 +1876,142 @@ static NTSTATUS dcesrv_lsa_lookup_name_winbind( > struct dcesrv_lsa_LookupNames_base_state *state, > struct dcesrv_lsa_TranslatedItem *item) > { >+ struct lsa_LookupNames4 *r = &state->r; >+ const struct lsa_TrustDomainInfoInfoEx *tdo = NULL; >+ const struct lsa_ForestTrustDomainInfo *di = NULL; >+ NTSTATUS status; >+ const char *check_domain_name = NULL; >+ bool expect_domain = false; >+ >+ if (item->name == NULL) { >+ /* >+ * This should not be mapped. >+ */ >+ return NT_STATUS_OK; >+ } >+ >+ if (item->hints.domain != NULL && item->hints.principal == NULL) { >+ /* >+ * This is 'DOMAIN\'. >+ */ >+ check_domain_name = item->hints.domain; >+ expect_domain = true; >+ } else if (item->hints.namespace != NULL) { >+ /* >+ * This is 'DOMAIN\someone' >+ * or 'someone@DOMAIN' >+ */ >+ check_domain_name = item->hints.namespace; >+ } else { >+ /* >+ * This is just 'DOMAIN'. >+ */ >+ check_domain_name = item->name; >+ expect_domain = true; >+ } >+ >+ if (state->routing_table == NULL) { >+ struct lsa_policy_state *policy_state = state->policy_state; >+ >+ status = dsdb_trust_routing_table_load(policy_state->sam_ldb, >+ state, >+ &state->routing_table); >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ } >+ >+ tdo = dsdb_trust_domain_by_name(state->routing_table, >+ check_domain_name, >+ &di); >+ if (tdo == NULL) { >+ /* >+ * The name is not resolvable at all... >+ * >+ * And for now we don't send unqualified names >+ * to winbindd, as we don't handle them >+ * there yet. >+ * >+ * TODO: how should that work within >+ * winbindd? >+ */ >+ return NT_STATUS_OK; >+ } >+ >+ if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) { >+ /* >+ * The name should have been resolved in the account view. >+ * >+ * TODO: handle multiple domains in a forest... >+ */ >+ return NT_STATUS_OK; >+ } >+ >+ if (expect_domain) { >+ const char *name = NULL; >+ const struct dom_sid *sid = NULL; >+ >+ name = talloc_strdup(state->mem_ctx, >+ di->netbios_domain_name.string); >+ if (name == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ sid = dom_sid_dup(state->mem_ctx, >+ di->domain_sid); >+ if (sid == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ item->type = SID_NAME_DOMAIN; >+ item->sid = sid; >+ item->authority_name = name; >+ item->authority_sid = sid; >+ return NT_STATUS_OK; >+ } >+ >+ if (r->in.lookup_options & LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES_LOCAL) { >+ if (item->hints.namespace == NULL) { >+ /* >+ * We should not try to resolve isolated names >+ * remotely. >+ */ >+ return NT_STATUS_OK; >+ } >+ } >+ >+ /* >+ * We know at least the domain part of the name exists. >+ * >+ * For now the rest handled within winbindd. >+ * >+ * In future we can optimize it based on >+ * r->in.level. >+ * >+ * We can also try to resolve SID_NAME_DOMAIN >+ * just based on the routing table. >+ */ >+ >+ if (state->wb.irpc_handle != NULL) { >+ /* >+ * already called... >+ */ >+ return NT_STATUS_NONE_MAPPED; >+ } >+ >+ state->wb.irpc_handle = irpc_binding_handle_by_name(state, >+ state->dce_call->msg_ctx, >+ "winbind_server", >+ &ndr_table_lsarpc); >+ if (state->wb.irpc_handle == NULL) { >+ DEBUG(0,("Failed to get binding_handle for winbind_server task\n")); >+ state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM; >+ return NT_STATUS_INVALID_SYSTEM_SERVICE; >+ } >+ >+ /* >+ * 60 seconds timeout should be enough >+ */ >+ dcerpc_binding_handle_set_timeout(state->wb.irpc_handle, 60); >+ > return NT_STATUS_NONE_MAPPED; > } > >@@ -1606,6 +2019,116 @@ static NTSTATUS dcesrv_lsa_lookup_sid_winbind( > struct dcesrv_lsa_LookupSids_base_state *state, > struct dcesrv_lsa_TranslatedItem *item) > { >+ const struct lsa_TrustDomainInfoInfoEx *tdo = NULL; >+ const struct lsa_ForestTrustDomainInfo *di = NULL; >+ struct dcesrv_lsa_TranslatedItem tmp; >+ struct dom_sid domain_sid = {0,}; >+ NTSTATUS status; >+ bool match; >+ >+ /* >+ * Verify the sid is not INVALID. >+ */ >+ tmp = *item; >+ status = dom_sid_lookup_predefined_sid(tmp.sid, >+ &tmp.name, >+ &tmp.type, >+ &tmp.authority_sid, >+ &tmp.authority_name); >+ if (NT_STATUS_IS_OK(status)) { >+ status = NT_STATUS_NONE_MAPPED; >+ } >+ if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) { >+ /* >+ * Typically INVALID_SID >+ */ >+ return status; >+ } >+ >+ if (state->routing_table == NULL) { >+ struct lsa_policy_state *policy_state = state->policy_state; >+ >+ status = dsdb_trust_routing_table_load(policy_state->sam_ldb, >+ state, >+ &state->routing_table); >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ } >+ >+ domain_sid = *item->sid; >+ if (domain_sid.num_auths == 5) { >+ sid_split_rid(&domain_sid, NULL); >+ } >+ >+ tdo = dsdb_trust_domain_by_sid(state->routing_table, >+ &domain_sid, &di); >+ if (tdo == NULL) { >+ /* >+ * The sid is not resolvable at all... >+ */ >+ return NT_STATUS_OK; >+ } >+ >+ if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) { >+ /* >+ * The name should have been resolved in the account view. >+ * >+ * TODO: handle multiple domains in a forest... >+ */ >+ return NT_STATUS_OK; >+ } >+ >+ match = dom_sid_equal(di->domain_sid, item->sid); >+ if (match) { >+ const char *name = NULL; >+ >+ name = talloc_strdup(state->mem_ctx, >+ di->netbios_domain_name.string); >+ if (name == NULL) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ item->type = SID_NAME_DOMAIN; >+ item->name = name; >+ item->authority_name = name; >+ item->authority_sid = item->sid; >+ return NT_STATUS_OK; >+ } >+ >+ /* >+ * We know at least the domain part of the sid exists. >+ * >+ * For now the rest handled within winbindd. >+ * >+ * In future we can optimize it based on >+ * r->in.level. >+ * >+ * We can also try to resolve SID_NAME_DOMAIN >+ * just based on the routing table. >+ */ >+ if (state->wb.irpc_handle != NULL) { >+ /* >+ * already called... >+ */ >+ return NT_STATUS_NONE_MAPPED; >+ } >+ >+ state->wb.irpc_handle = irpc_binding_handle_by_name(state, >+ state->dce_call->msg_ctx, >+ "winbind_server", >+ &ndr_table_lsarpc); >+ if (state->wb.irpc_handle == NULL) { >+ DEBUG(0,("Failed to get binding_handle for winbind_server task\n")); >+ state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM; >+ return NT_STATUS_INVALID_SYSTEM_SERVICE; >+ } >+ >+ /* >+ * 60 seconds timeout should be enough >+ */ >+ dcerpc_binding_handle_set_timeout(state->wb.irpc_handle, 60); >+ > return NT_STATUS_NONE_MAPPED; > } > >-- >2.13.6 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
metze
:
review+
Actions:
View
Attachments on
bug 13286
: 13993