summaryrefslogtreecommitdiff
path: root/source4/rpc_server/lsa
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2007-09-17 05:31:49 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 15:06:51 -0500
commit08c97435d3dd055329d41b3814af687c7404533f (patch)
treecd7b2eacbda9378478ea4b8eca2168bf3d3a151e /source4/rpc_server/lsa
parentffbb7e40604b9cffeb0c226279b929497b03a964 (diff)
downloadsamba-08c97435d3dd055329d41b3814af687c7404533f.tar.gz
samba-08c97435d3dd055329d41b3814af687c7404533f.tar.bz2
samba-08c97435d3dd055329d41b3814af687c7404533f.zip
r25194: A major rework of the Samba4 LSA LookupNames and LookupSids code, with
a new torture suite to match. This should fix bug #4954 by Matthias Wallnöfer <mwallnoefer@yahoo.de> Previously we had no knowlege of BUILTIN or well-known names. This code needs expansion to check with winbind for trusted domains. Andrew Bartlett (This used to be commit e6fc0e1f54ad64bdddc88e9ebd0d8d181b6ce26a)
Diffstat (limited to 'source4/rpc_server/lsa')
-rw-r--r--source4/rpc_server/lsa/dcesrv_lsa.c850
-rw-r--r--source4/rpc_server/lsa/lsa.h69
-rw-r--r--source4/rpc_server/lsa/lsa_init.c248
-rw-r--r--source4/rpc_server/lsa/lsa_lookup.c928
4 files changed, 1251 insertions, 844 deletions
diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c
index 144e61cd75..8a695bdedf 100644
--- a/source4/rpc_server/lsa/dcesrv_lsa.c
+++ b/source4/rpc_server/lsa/dcesrv_lsa.c
@@ -4,7 +4,7 @@
endpoint server for the lsarpc pipe
Copyright (C) Andrew Tridgell 2004
- Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2007
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,51 +20,11 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "includes.h"
-#include "rpc_server/dcerpc_server.h"
-#include "rpc_server/common/common.h"
-#include "auth/auth.h"
-#include "dsdb/samdb/samdb.h"
-#include "libcli/ldap/ldap.h"
-#include "lib/ldb/include/ldb_errors.h"
-#include "libcli/security/security.h"
-#include "libcli/auth/libcli_auth.h"
-#include "param/secrets.h"
-#include "db_wrap.h"
-#include "librpc/gen_ndr/ndr_dssetup.h"
-#include "param/param.h"
+#include "rpc_server/lsa/lsa.h"
/*
this type allows us to distinguish handle types
*/
-enum lsa_handle {
- LSA_HANDLE_POLICY,
- LSA_HANDLE_ACCOUNT,
- LSA_HANDLE_SECRET,
- LSA_HANDLE_TRUSTED_DOMAIN
-};
-
-/*
- state associated with a lsa_OpenPolicy() operation
-*/
-struct lsa_policy_state {
- struct dcesrv_handle *handle;
- struct ldb_context *sam_ldb;
- struct sidmap_context *sidmap;
- uint32_t access_mask;
- struct ldb_dn *domain_dn;
- struct ldb_dn *forest_dn;
- struct ldb_dn *builtin_dn;
- struct ldb_dn *system_dn;
- const char *domain_name;
- const char *domain_dns;
- const char *forest_dns;
- struct dom_sid *domain_sid;
- struct GUID domain_guid;
- struct dom_sid *builtin_sid;
- int mixed_domain;
-};
-
/*
state associated with a lsa_OpenAccount() operation
@@ -269,162 +229,6 @@ static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TA
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
-static NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct lsa_policy_state **_state)
-{
- struct lsa_policy_state *state;
- struct ldb_dn *partitions_basedn;
- struct ldb_result *dom_res;
- const char *dom_attrs[] = {
- "objectSid",
- "objectGUID",
- "nTMixedDomain",
- "fSMORoleOwner",
- NULL
- };
- struct ldb_result *ref_res;
- struct ldb_result *forest_ref_res;
- const char *ref_attrs[] = {
- "nETBIOSName",
- "dnsRoot",
- NULL
- };
- int ret;
-
- state = talloc(mem_ctx, struct lsa_policy_state);
- if (!state) {
- return NT_STATUS_NO_MEMORY;
- }
-
- /* make sure the sam database is accessible */
- state->sam_ldb = samdb_connect(state, dce_call->conn->auth_state.session_info);
- if (state->sam_ldb == NULL) {
- return NT_STATUS_INVALID_SYSTEM_SERVICE;
- }
-
- partitions_basedn = samdb_partitions_dn(state->sam_ldb, mem_ctx);
-
- state->sidmap = sidmap_open(state);
- if (state->sidmap == NULL) {
- return NT_STATUS_INVALID_SYSTEM_SERVICE;
- }
-
- /* work out the domain_dn - useful for so many calls its worth
- fetching here */
- state->domain_dn = samdb_base_dn(state->sam_ldb);
- if (!state->domain_dn) {
- return NT_STATUS_NO_MEMORY;
- }
-
- /* work out the forest root_dn - useful for so many calls its worth
- fetching here */
- state->forest_dn = samdb_root_dn(state->sam_ldb);
- if (!state->forest_dn) {
- return NT_STATUS_NO_MEMORY;
- }
-
- ret = ldb_search(state->sam_ldb, state->domain_dn, LDB_SCOPE_BASE, NULL, dom_attrs, &dom_res);
-
- if (ret != LDB_SUCCESS) {
- return NT_STATUS_INVALID_SYSTEM_SERVICE;
- }
- talloc_steal(mem_ctx, dom_res);
- if (dom_res->count != 1) {
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
-
- state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
- if (!state->domain_sid) {
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
-
- state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
- if (!state->domain_sid) {
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
-
- state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0);
-
- talloc_free(dom_res);
-
- ret = ldb_search_exp_fmt(state->sam_ldb, state, &ref_res,
- partitions_basedn, LDB_SCOPE_SUBTREE, ref_attrs,
- "(&(objectclass=crossRef)(ncName=%s))",
- ldb_dn_get_linearized(state->domain_dn));
-
- if (ret != LDB_SUCCESS) {
- talloc_free(ref_res);
- return NT_STATUS_INVALID_SYSTEM_SERVICE;
- }
- if (ref_res->count != 1) {
- talloc_free(ref_res);
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
-
- state->domain_name = ldb_msg_find_attr_as_string(ref_res->msgs[0], "nETBIOSName", NULL);
- if (!state->domain_name) {
- talloc_free(ref_res);
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
- talloc_steal(state, state->domain_name);
-
- state->domain_dns = ldb_msg_find_attr_as_string(ref_res->msgs[0], "dnsRoot", NULL);
- if (!state->domain_dns) {
- talloc_free(ref_res);
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
- talloc_steal(state, state->domain_dns);
-
- talloc_free(ref_res);
-
- ret = ldb_search_exp_fmt(state->sam_ldb, state, &forest_ref_res,
- partitions_basedn, LDB_SCOPE_SUBTREE, ref_attrs,
- "(&(objectclass=crossRef)(ncName=%s))",
- ldb_dn_get_linearized(state->forest_dn));
-
- if (ret != LDB_SUCCESS) {
- talloc_free(forest_ref_res);
- return NT_STATUS_INVALID_SYSTEM_SERVICE;
- }
- if (forest_ref_res->count != 1) {
- talloc_free(forest_ref_res);
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
-
- state->forest_dns = ldb_msg_find_attr_as_string(forest_ref_res->msgs[0], "dnsRoot", NULL);
- if (!state->forest_dns) {
- talloc_free(forest_ref_res);
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
- talloc_steal(state, state->forest_dns);
-
- talloc_free(forest_ref_res);
-
- /* work out the builtin_dn - useful for so many calls its worth
- fetching here */
- state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)");
- if (!state->builtin_dn) {
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
-
- /* work out the system_dn - useful for so many calls its worth
- fetching here */
- state->system_dn = samdb_search_dn(state->sam_ldb, state,
- state->domain_dn, "(&(objectClass=container)(cn=System))");
- if (!state->system_dn) {
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
-
- state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
- if (!state->builtin_sid) {
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
-
- *_state = state;
-
- return NT_STATUS_OK;
-}
-
/*
dssetup_DsRoleGetPrimaryDomainInformation
@@ -532,60 +336,6 @@ static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_cal
return WERR_INVALID_PARAM;
}
-/*
- lsa_OpenPolicy2
-*/
-static NTSTATUS dcesrv_lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct lsa_OpenPolicy2 *r)
-{
- NTSTATUS status;
- struct lsa_policy_state *state;
- struct dcesrv_handle *handle;
-
- ZERO_STRUCTP(r->out.handle);
-
- status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_POLICY);
- if (!handle) {
- return NT_STATUS_NO_MEMORY;
- }
-
- handle->data = talloc_steal(handle, state);
-
- state->access_mask = r->in.access_mask;
- state->handle = handle;
- *r->out.handle = handle->wire_handle;
-
- /* note that we have completely ignored the attr element of
- the OpenPolicy. As far as I can tell, this is what w2k3
- does */
-
- return NT_STATUS_OK;
-}
-
-/*
- lsa_OpenPolicy
- a wrapper around lsa_OpenPolicy2
-*/
-static NTSTATUS dcesrv_lsa_OpenPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct lsa_OpenPolicy *r)
-{
- struct lsa_OpenPolicy2 r2;
-
- r2.in.system_name = NULL;
- r2.in.attr = r->in.attr;
- r2.in.access_mask = r->in.access_mask;
- r2.out.handle = r->out.handle;
-
- return dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &r2);
-}
-
-
-
/*
fill in the AccountDomain info
@@ -643,6 +393,10 @@ static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call,
case LSA_POLICY_INFO_DNS:
return dcesrv_lsa_info_DNS(state, mem_ctx, &r->out.info->dns);
+ case LSA_POLICY_INFO_DB:
+ case LSA_POLICY_INFO_AUDIT_FULL_SET:
+ case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
+ return NT_STATUS_INVALID_PARAMETER;
}
return NT_STATUS_INVALID_INFO_CLASS;
@@ -1473,311 +1227,6 @@ static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_ca
}
-/*
- return the authority name and authority sid, given a sid
-*/
-static NTSTATUS dcesrv_lsa_authority_name(struct lsa_policy_state *state,
- TALLOC_CTX *mem_ctx, struct dom_sid *sid,
- const char **authority_name,
- struct dom_sid **authority_sid)
-{
- if (dom_sid_in_domain(state->domain_sid, sid)) {
- *authority_name = state->domain_name;
- *authority_sid = state->domain_sid;
- return NT_STATUS_OK;
- }
-
- if (dom_sid_in_domain(state->builtin_sid, sid)) {
- *authority_name = "BUILTIN";
- *authority_sid = state->builtin_sid;
- return NT_STATUS_OK;
- }
-
- *authority_sid = dom_sid_dup(mem_ctx, sid);
- if (*authority_sid == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- (*authority_sid)->num_auths = 0;
- *authority_name = dom_sid_string(mem_ctx, *authority_sid);
- if (*authority_name == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- 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,
- struct dom_sid *sid,
- struct lsa_RefDomainList *domains,
- uint32_t *sid_index)
-{
- NTSTATUS status;
- const char *authority_name;
- struct dom_sid *authority_sid;
- int i;
-
- /* work out the authority name */
- status = dcesrv_lsa_authority_name(state, mem_ctx, sid,
- &authority_name, &authority_sid);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- /* see if we've already done this authority name */
- for (i=0;i<domains->count;i++) {
- if (strcmp(authority_name, domains->domains[i].name.string) == 0) {
- *sid_index = i;
- return NT_STATUS_OK;
- }
- }
-
- domains->domains = talloc_realloc(domains,
- domains->domains,
- struct lsa_DomainInfo,
- domains->count+1);
- if (domains->domains == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- domains->domains[i].name.string = authority_name;
- domains->domains[i].sid = authority_sid;
- 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 **name, uint32_t *atype)
-{
- int ret;
- struct ldb_message **res;
- const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "name", NULL};
- NTSTATUS status;
-
- ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs,
- "objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx, sid));
- if (ret == 1) {
- *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
- if (!*name) {
- *name = ldb_msg_find_attr_as_string(res[0], "name", NULL);
- if (!*name) {
- *name = talloc_strdup(mem_ctx, sid_str);
- NT_STATUS_HAVE_NO_MEMORY(*name);
- }
- }
-
- *atype = samdb_result_uint(res[0], "sAMAccountType", 0);
-
- return NT_STATUS_OK;
- }
-
- status = sidmap_allocated_sid_lookup(state->sidmap, mem_ctx, sid, name, atype);
-
- return status;
-}
-
-
-/*
- lsa_LookupSids2
-*/
-static NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
- TALLOC_CTX *mem_ctx,
- struct lsa_LookupSids2 *r)
-{
- struct lsa_policy_state *state;
- int i;
- NTSTATUS status = NT_STATUS_OK;
-
- r->out.domains = NULL;
-
- status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- r->out.domains = talloc_zero(mem_ctx, struct lsa_RefDomainList);
- if (r->out.domains == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- 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) {
- 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;
- uint32_t atype, rtype, sid_index;
- NTSTATUS status2;
-
- r->out.names->count++;
- (*r->out.count)++;
-
- 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;
-
- if (sid_str == NULL) {
- r->out.names->names[i].name.string = "(SIDERROR)";
- status = STATUS_SOME_UNMAPPED;
- continue;
- }
-
- /* work out the authority name */
- status2 = dcesrv_lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
- if (!NT_STATUS_IS_OK(status2)) {
- return status2;
- }
-
- status2 = dcesrv_lsa_lookup_sid(state, mem_ctx, sid, sid_str,
- &name, &atype);
- if (!NT_STATUS_IS_OK(status2)) {
- status = STATUS_SOME_UNMAPPED;
- continue;
- }
-
- rtype = samdb_atype_map(atype);
- if (rtype == SID_NAME_UNKNOWN) {
- status = STATUS_SOME_UNMAPPED;
- continue;
- }
-
- r->out.names->names[i].sid_type = rtype;
- r->out.names->names[i].name.string = name;
- r->out.names->names[i].sid_index = sid_index;
- r->out.names->names[i].unknown = 0;
- }
-
- return status;
-}
-
-
-/*
- lsa_LookupSids3
-
- Identical to LookupSids2, but doesn't take a policy handle
-
-*/
-static NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
- TALLOC_CTX *mem_ctx,
- struct lsa_LookupSids3 *r)
-{
- struct lsa_LookupSids2 r2;
- struct lsa_OpenPolicy2 pol;
- NTSTATUS status;
- struct dcesrv_handle *h;
-
- /* No policy handle on the wire, so make one up here */
- r2.in.handle = talloc(mem_ctx, struct policy_handle);
- if (!r2.in.handle) {
- return NT_STATUS_NO_MEMORY;
- }
-
- pol.out.handle = r2.in.handle;
- pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
- pol.in.attr = NULL;
- pol.in.system_name = NULL;
- status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- /* ensure this handle goes away at the end of this call */
- DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
- talloc_steal(mem_ctx, h);
-
- r2.in.sids = r->in.sids;
- r2.in.names = r->in.names;
- r2.in.level = r->in.level;
- r2.in.count = r->in.count;
- r2.in.unknown1 = r->in.unknown1;
- r2.in.unknown2 = r->in.unknown2;
- r2.out.count = r->out.count;
- r2.out.names = r->out.names;
-
- status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
- if (dce_call->fault_code != 0) {
- return status;
- }
-
- r->out.domains = r2.out.domains;
- r->out.names = r2.out.names;
- r->out.count = r2.out.count;
-
- return status;
-}
-
-
-/*
- lsa_LookupSids
-*/
-static NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct lsa_LookupSids *r)
-{
- struct lsa_LookupSids2 r2;
- NTSTATUS status;
- int i;
-
- r2.in.handle = r->in.handle;
- r2.in.sids = r->in.sids;
- r2.in.names = NULL;
- r2.in.level = r->in.level;
- r2.in.count = r->in.count;
- r2.in.unknown1 = 0;
- r2.in.unknown2 = 0;
- r2.out.count = r->out.count;
- r2.out.names = NULL;
-
- status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
- if (dce_call->fault_code != 0) {
- return status;
- }
-
- 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++) {
- 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;
- }
-
- return status;
-}
-
-
/*
lsa_OpenAccount
*/
@@ -3007,293 +2456,6 @@ static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
-/*
- lookup a SID for 1 name
-*/
-static NTSTATUS dcesrv_lsa_lookup_name(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
- const char *name, struct dom_sid **sid, uint32_t *atype)
-{
- int ret;
- struct ldb_message **res;
- const char * const attrs[] = { "objectSid", "sAMAccountType", NULL};
- const char *p;
-
- p = strchr_m(name, '\\');
- if (p != NULL) {
- /* TODO: properly parse the domain prefix here, and use it to
- limit the search */
- name = p + 1;
- }
-
- ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, "sAMAccountName=%s", ldb_binary_encode_string(mem_ctx, name));
- if (ret == 1) {
- *sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
- if (*sid == NULL) {
- return NT_STATUS_INVALID_SID;
- }
-
- *atype = samdb_result_uint(res[0], "sAMAccountType", 0);
-
- return NT_STATUS_OK;
- }
-
- /* need to add a call into sidmap to check for a allocated sid */
-
- return NT_STATUS_INVALID_SID;
-}
-
-
-/*
- lsa_LookupNames3
-*/
-static NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
- TALLOC_CTX *mem_ctx,
- struct lsa_LookupNames3 *r)
-{
- struct lsa_policy_state *policy_state;
- struct dcesrv_handle *policy_handle;
- int i;
- NTSTATUS status = NT_STATUS_OK;
-
- DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
-
- policy_state = policy_handle->data;
-
- r->out.domains = NULL;
-
- r->out.domains = talloc_zero(mem_ctx, struct lsa_RefDomainList);
- if (r->out.domains == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- 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) {
- return NT_STATUS_NO_MEMORY;
- }
-
- for (i=0;i<r->in.num_names;i++) {
- const char *name = r->in.names[i].string;
- struct dom_sid *sid;
- uint32_t atype, rtype, sid_index;
- NTSTATUS status2;
-
- r->out.sids->count++;
- (*r->out.count)++;
-
- 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].unknown = 0;
-
- status2 = dcesrv_lsa_lookup_name(policy_state, mem_ctx, name, &sid, &atype);
- if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
- status = STATUS_SOME_UNMAPPED;
- continue;
- }
-
- rtype = samdb_atype_map(atype);
- if (rtype == SID_NAME_UNKNOWN) {
- status = STATUS_SOME_UNMAPPED;
- continue;
- }
-
- status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, sid, r->out.domains, &sid_index);
- if (!NT_STATUS_IS_OK(status2)) {
- return status2;
- }
-
- 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].unknown = 0;
- }
-
- return status;
-}
-
-/*
- lsa_LookupNames4
-
- Identical to LookupNames3, but doesn't take a policy handle
-
-*/
-static NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct lsa_LookupNames4 *r)
-{
- struct lsa_LookupNames3 r2;
- struct lsa_OpenPolicy2 pol;
- NTSTATUS status;
- struct dcesrv_handle *h;
-
- /* No policy handle on the wire, so make one up here */
- r2.in.handle = talloc(mem_ctx, struct policy_handle);
- if (!r2.in.handle) {
- return NT_STATUS_NO_MEMORY;
- }
-
- pol.out.handle = r2.in.handle;
- pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
- pol.in.attr = NULL;
- pol.in.system_name = NULL;
- status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- /* ensure this handle goes away at the end of this call */
- DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
- talloc_steal(mem_ctx, h);
-
- r2.in.num_names = r->in.num_names;
- r2.in.names = r->in.names;
- r2.in.sids = r->in.sids;
- r2.in.count = r->in.count;
- r2.in.unknown1 = r->in.unknown1;
- r2.in.unknown2 = r->in.unknown2;
- r2.out.domains = r->out.domains;
- r2.out.sids = r->out.sids;
- r2.out.count = r->out.count;
-
- status = dcesrv_lsa_LookupNames3(dce_call, mem_ctx, &r2);
- if (dce_call->fault_code != 0) {
- return status;
- }
-
- r->out.domains = r2.out.domains;
- r->out.sids = r2.out.sids;
- r->out.count = r2.out.count;
- return status;
-}
-
-/*
- lsa_LookupNames2
-*/
-static NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
- TALLOC_CTX *mem_ctx,
- struct lsa_LookupNames2 *r)
-{
- struct lsa_policy_state *state;
- struct dcesrv_handle *h;
- int i;
- NTSTATUS status = NT_STATUS_OK;
-
- r->out.domains = NULL;
-
- DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
-
- state = h->data;
-
- r->out.domains = talloc_zero(mem_ctx, struct lsa_RefDomainList);
- if (r->out.domains == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- 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) {
- return NT_STATUS_NO_MEMORY;
- }
-
- for (i=0;i<r->in.num_names;i++) {
- const char *name = r->in.names[i].string;
- struct dom_sid *sid;
- uint32_t atype, rtype, sid_index;
- NTSTATUS status2;
-
- r->out.sids->count++;
- (*r->out.count)++;
-
- r->out.sids->sids[i].sid_type = SID_NAME_UNKNOWN;
- r->out.sids->sids[i].rid = 0xFFFFFFFF;
- r->out.sids->sids[i].sid_index = 0xFFFFFFFF;
- r->out.sids->sids[i].unknown = 0;
-
- status2 = dcesrv_lsa_lookup_name(state, mem_ctx, name, &sid, &atype);
- if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
- status = STATUS_SOME_UNMAPPED;
- continue;
- }
-
- rtype = samdb_atype_map(atype);
- if (rtype == SID_NAME_UNKNOWN) {
- status = STATUS_SOME_UNMAPPED;
- continue;
- }
-
- status2 = dcesrv_lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
- if (!NT_STATUS_IS_OK(status2)) {
- return status2;
- }
-
- r->out.sids->sids[i].sid_type = rtype;
- r->out.sids->sids[i].rid = sid->sub_auths[sid->num_auths-1];
- r->out.sids->sids[i].sid_index = sid_index;
- r->out.sids->sids[i].unknown = 0;
- }
-
- return status;
-}
-
-/*
- lsa_LookupNames
-*/
-static NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct lsa_LookupNames *r)
-{
- struct lsa_LookupNames2 r2;
- NTSTATUS status;
- int i;
-
- 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.level = r->in.level;
- r2.in.count = r->in.count;
- r2.in.unknown1 = 0;
- r2.in.unknown2 = 0;
- r2.out.count = r->out.count;
-
- status = dcesrv_lsa_LookupNames2(dce_call, mem_ctx, &r2);
- if (dce_call->fault_code != 0) {
- return status;
- }
-
- r->out.domains = r2.out.domains;
- 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++) {
- 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;
- }
-
- return status;
-}
-
/*
lsa_CREDRWRITE
*/
diff --git a/source4/rpc_server/lsa/lsa.h b/source4/rpc_server/lsa/lsa.h
new file mode 100644
index 0000000000..6ecda0ff82
--- /dev/null
+++ b/source4/rpc_server/lsa/lsa.h
@@ -0,0 +1,69 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ endpoint server for the lsarpc pipe
+
+ Copyright (C) Andrew Tridgell 2004
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "rpc_server/dcerpc_server.h"
+#include "rpc_server/common/common.h"
+#include "auth/auth.h"
+#include "dsdb/samdb/samdb.h"
+#include "libcli/ldap/ldap.h"
+#include "lib/ldb/include/ldb_errors.h"
+#include "libcli/security/security.h"
+#include "libcli/auth/libcli_auth.h"
+#include "param/secrets.h"
+#include "db_wrap.h"
+#include "librpc/gen_ndr/ndr_dssetup.h"
+#include "param/param.h"
+
+/*
+ state associated with a lsa_OpenPolicy() operation
+*/
+struct lsa_policy_state {
+ struct dcesrv_handle *handle;
+ struct ldb_context *sam_ldb;
+ struct sidmap_context *sidmap;
+ uint32_t access_mask;
+ struct ldb_dn *domain_dn;
+ struct ldb_dn *forest_dn;
+ struct ldb_dn *builtin_dn;
+ struct ldb_dn *system_dn;
+ const char *domain_name;
+ const char *domain_dns;
+ const char *forest_dns;
+ struct dom_sid *domain_sid;
+ struct GUID domain_guid;
+ struct dom_sid *builtin_sid;
+ struct dom_sid *nt_authority_sid;
+ struct dom_sid *creator_owner_domain_sid;
+ struct dom_sid *world_domain_sid;
+ int mixed_domain;
+};
+
+enum lsa_handle {
+ LSA_HANDLE_POLICY,
+ LSA_HANDLE_ACCOUNT,
+ LSA_HANDLE_SECRET,
+ LSA_HANDLE_TRUSTED_DOMAIN
+};
+
+#include "rpc_server/lsa/proto.h"
+
diff --git a/source4/rpc_server/lsa/lsa_init.c b/source4/rpc_server/lsa/lsa_init.c
new file mode 100644
index 0000000000..6cf062a22a
--- /dev/null
+++ b/source4/rpc_server/lsa/lsa_init.c
@@ -0,0 +1,248 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ endpoint server for the lsarpc pipe
+
+ Copyright (C) Andrew Tridgell 2004
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2007
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rpc_server/lsa/lsa.h"
+
+NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct lsa_policy_state **_state)
+{
+ struct lsa_policy_state *state;
+ struct ldb_dn *partitions_basedn;
+ struct ldb_result *dom_res;
+ const char *dom_attrs[] = {
+ "objectSid",
+ "objectGUID",
+ "nTMixedDomain",
+ "fSMORoleOwner",
+ NULL
+ };
+ struct ldb_result *ref_res;
+ struct ldb_result *forest_ref_res;
+ const char *ref_attrs[] = {
+ "nETBIOSName",
+ "dnsRoot",
+ NULL
+ };
+ int ret;
+
+ state = talloc(mem_ctx, struct lsa_policy_state);
+ if (!state) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* make sure the sam database is accessible */
+ state->sam_ldb = samdb_connect(state, dce_call->conn->auth_state.session_info);
+ if (state->sam_ldb == NULL) {
+ return NT_STATUS_INVALID_SYSTEM_SERVICE;
+ }
+
+ partitions_basedn = samdb_partitions_dn(state->sam_ldb, mem_ctx);
+
+ state->sidmap = sidmap_open(state);
+ if (state->sidmap == NULL) {
+ return NT_STATUS_INVALID_SYSTEM_SERVICE;
+ }
+
+ /* work out the domain_dn - useful for so many calls its worth
+ fetching here */
+ state->domain_dn = samdb_base_dn(state->sam_ldb);
+ if (!state->domain_dn) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* work out the forest root_dn - useful for so many calls its worth
+ fetching here */
+ state->forest_dn = samdb_root_dn(state->sam_ldb);
+ if (!state->forest_dn) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ret = ldb_search(state->sam_ldb, state->domain_dn, LDB_SCOPE_BASE, NULL, dom_attrs, &dom_res);
+
+ if (ret != LDB_SUCCESS) {
+ return NT_STATUS_INVALID_SYSTEM_SERVICE;
+ }
+ talloc_steal(mem_ctx, dom_res);
+ if (dom_res->count != 1) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+
+ state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
+ if (!state->domain_sid) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+
+ state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
+ if (!state->domain_sid) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+
+ state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0);
+
+ talloc_free(dom_res);
+
+ ret = ldb_search_exp_fmt(state->sam_ldb, state, &ref_res,
+ partitions_basedn, LDB_SCOPE_SUBTREE, ref_attrs,
+ "(&(objectclass=crossRef)(ncName=%s))",
+ ldb_dn_get_linearized(state->domain_dn));
+
+ if (ret != LDB_SUCCESS) {
+ talloc_free(ref_res);
+ return NT_STATUS_INVALID_SYSTEM_SERVICE;
+ }
+ if (ref_res->count != 1) {
+ talloc_free(ref_res);
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+
+ state->domain_name = ldb_msg_find_attr_as_string(ref_res->msgs[0], "nETBIOSName", NULL);
+ if (!state->domain_name) {
+ talloc_free(ref_res);
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+ talloc_steal(state, state->domain_name);
+
+ state->domain_dns = ldb_msg_find_attr_as_string(ref_res->msgs[0], "dnsRoot", NULL);
+ if (!state->domain_dns) {
+ talloc_free(ref_res);
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+ talloc_steal(state, state->domain_dns);
+
+ talloc_free(ref_res);
+
+ ret = ldb_search_exp_fmt(state->sam_ldb, state, &forest_ref_res,
+ partitions_basedn, LDB_SCOPE_SUBTREE, ref_attrs,
+ "(&(objectclass=crossRef)(ncName=%s))",
+ ldb_dn_get_linearized(state->forest_dn));
+
+ if (ret != LDB_SUCCESS) {
+ talloc_free(forest_ref_res);
+ return NT_STATUS_INVALID_SYSTEM_SERVICE;
+ }
+ if (forest_ref_res->count != 1) {
+ talloc_free(forest_ref_res);
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+
+ state->forest_dns = ldb_msg_find_attr_as_string(forest_ref_res->msgs[0], "dnsRoot", NULL);
+ if (!state->forest_dns) {
+ talloc_free(forest_ref_res);
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+ talloc_steal(state, state->forest_dns);
+
+ talloc_free(forest_ref_res);
+
+ /* work out the builtin_dn - useful for so many calls its worth
+ fetching here */
+ state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)");
+ if (!state->builtin_dn) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+
+ /* work out the system_dn - useful for so many calls its worth
+ fetching here */
+ state->system_dn = samdb_search_dn(state->sam_ldb, state,
+ state->domain_dn, "(&(objectClass=container)(cn=System))");
+ if (!state->system_dn) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+
+ state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
+ if (!state->builtin_sid) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+
+ state->nt_authority_sid = dom_sid_parse_talloc(state, SID_NT_AUTHORITY);
+ if (!state->nt_authority_sid) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+
+ state->creator_owner_domain_sid = dom_sid_parse_talloc(state, SID_CREATOR_OWNER_DOMAIN);
+ if (!state->creator_owner_domain_sid) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+
+ state->world_domain_sid = dom_sid_parse_talloc(state, SID_WORLD_DOMAIN);
+ if (!state->world_domain_sid) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+
+ *_state = state;
+
+ return NT_STATUS_OK;
+}
+
+/*
+ lsa_OpenPolicy2
+*/
+NTSTATUS dcesrv_lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct lsa_OpenPolicy2 *r)
+{
+ NTSTATUS status;
+ struct lsa_policy_state *state;
+ struct dcesrv_handle *handle;
+
+ ZERO_STRUCTP(r->out.handle);
+
+ status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_POLICY);
+ if (!handle) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ handle->data = talloc_steal(handle, state);
+
+ state->access_mask = r->in.access_mask;
+ state->handle = handle;
+ *r->out.handle = handle->wire_handle;
+
+ /* note that we have completely ignored the attr element of
+ the OpenPolicy. As far as I can tell, this is what w2k3
+ does */
+
+ return NT_STATUS_OK;
+}
+
+/*
+ lsa_OpenPolicy
+ a wrapper around lsa_OpenPolicy2
+*/
+NTSTATUS dcesrv_lsa_OpenPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct lsa_OpenPolicy *r)
+{
+ struct lsa_OpenPolicy2 r2;
+
+ r2.in.system_name = NULL;
+ r2.in.attr = r->in.attr;
+ r2.in.access_mask = r->in.access_mask;
+ r2.out.handle = r->out.handle;
+
+ return dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &r2);
+}
+
+
diff --git a/source4/rpc_server/lsa/lsa_lookup.c b/source4/rpc_server/lsa/lsa_lookup.c
new file mode 100644
index 0000000000..4ca3e4d51e
--- /dev/null
+++ b/source4/rpc_server/lsa/lsa_lookup.c
@@ -0,0 +1,928 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ endpoint server for the lsarpc pipe
+
+ Copyright (C) Andrew Tridgell 2004
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2007
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rpc_server/lsa/lsa.h"
+
+static const struct {
+ const char *domain;
+ const char *name;
+ const char *sid;
+ int 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_OWNER,
+ .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_DIALUP,
+ .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 = "Termainal 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,
+ },
+ {
+ .sid = NULL,
+ }
+};
+
+static NTSTATUS lookup_well_known_names(TALLOC_CTX *mem_ctx, const char *domain,
+ const char *name, const char **authority_name,
+ struct dom_sid **sid, uint32_t *rtype)
+{
+ 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;
+}
+
+static NTSTATUS lookup_well_known_sids(TALLOC_CTX *mem_ctx,
+ const char *sid_str, const char **authority_name,
+ const char **name, uint32_t *rtype)
+{
+ 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;
+}
+
+/*
+ lookup a SID for 1 name
+*/
+static NTSTATUS dcesrv_lsa_lookup_name(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
+ const char *name, const char **authority_name,
+ struct dom_sid **sid, enum lsa_SidType *rtype)
+{
+ int ret, atype, i;
+ 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;
+ NTSTATUS status;
+
+ 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, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL, name, &domain, &username);
+ if (!NT_STATUS_IS_OK(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)) {
+ 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);
+ *rtype = SID_NAME_DOMAIN;
+ return NT_STATUS_OK;
+ }
+ if (strcasecmp_m(username, NAME_BUILTIN) == 0) {
+ *authority_name = NAME_BUILTIN;
+ *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
+ *rtype = SID_NAME_DOMAIN;
+ return NT_STATUS_OK;
+ }
+ if (strcasecmp_m(username, state->domain_dns) == 0) {
+ *authority_name = state->domain_name;
+ *sid = state->domain_sid;
+ *rtype = SID_NAME_DOMAIN;
+ return NT_STATUS_OK;
+ }
+ if (strcasecmp_m(username, state->domain_name) == 0) {
+ *authority_name = state->domain_name;
+ *sid = state->domain_sid;
+ *rtype = SID_NAME_DOMAIN;
+ 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(state, mem_ctx, name, authority_name, sid, rtype);
+ if (NT_STATUS_IS_OK(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(state, mem_ctx, name, authority_name, sid, rtype);
+ 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(state, mem_ctx, name, authority_name, sid, rtype);
+ 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);
+ *rtype = SID_NAME_DOMAIN;
+ return NT_STATUS_OK;
+ }
+
+ /* Look up table of well known names */
+ return lookup_well_known_names(mem_ctx, domain, username, authority_name,
+ sid, rtype);
+ } 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 = state->domain_name;
+ domain_dn = state->domain_dn;
+ } else if (strcasecmp_m(domain, state->domain_name) == 0) {
+ *authority_name = state->domain_name;
+ domain_dn = state->domain_dn;
+ } else {
+ /* Not local, need to ask winbind in future */
+ return STATUS_SOME_UNMAPPED;
+ }
+
+ ret = gendb_search_dn(state->sam_ldb, mem_ctx, domain_dn, &res, attrs);
+ if (ret == 1) {
+ domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
+ if (domain_sid == NULL) {
+ return NT_STATUS_INVALID_SID;
+ }
+ } else {
+ return NT_STATUS_INVALID_SID;
+ }
+
+ if (!*username) {
+ *sid = domain_sid;
+ *rtype = SID_NAME_DOMAIN;
+ 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));
+ if (ret == -1) {
+ return NT_STATUS_INVALID_SID;
+ }
+
+ 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 = samdb_result_uint(res[i], "sAMAccountType", 0);
+
+ *rtype = samdb_atype_map(atype);
+ if (*rtype == SID_NAME_UNKNOWN) {
+ return STATUS_SOME_UNMAPPED;
+ }
+
+ return NT_STATUS_OK;
+ }
+
+ /* need to add a call into sidmap to check for a allocated sid */
+
+ return NT_STATUS_INVALID_SID;
+}
+
+
+/*
+ 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,
+ struct lsa_RefDomainList *domains,
+ uint32_t *sid_index)
+{
+ struct dom_sid *authority_sid;
+ int 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;
+ }
+
+ /* see if we've already done this authority name */
+ for (i=0;i<domains->count;i++) {
+ if (strcasecmp_m(authority_name, domains->domains[i].name.string) == 0) {
+ *sid_index = i;
+ return NT_STATUS_OK;
+ }
+ }
+
+ domains->domains = talloc_realloc(domains,
+ domains->domains,
+ struct lsa_DomainInfo,
+ domains->count+1);
+ if (domains->domains == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ domains->domains[i].name.string = authority_name;
+ domains->domains[i].sid = authority_sid;
+ 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)
+{
+ NTSTATUS status;
+ int ret;
+ 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_in_domain(state->domain_sid, sid)) {
+ *authority_name = state->domain_name;
+ 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 */
+
+ return NT_STATUS_NOT_FOUND;
+ }
+
+ ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs,
+ "objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx, sid));
+ if (ret == 1) {
+ *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);
+ }
+ }
+
+ atype = samdb_result_uint(res[0], "sAMAccountType", 0);
+
+ *rtype = samdb_atype_map(atype);
+
+ return NT_STATUS_OK;
+ }
+
+ /* need to re-add a call into sidmap to check for a allocated sid */
+ /* status = sidmap_allocated_sid_lookup(state->sidmap, mem_ctx, sid, name, rtype); */
+
+ return NT_STATUS_NOT_FOUND;
+}
+
+
+/*
+ lsa_LookupSids2
+*/
+NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct lsa_LookupSids2 *r)
+{
+ struct lsa_policy_state *state;
+ int i;
+ NTSTATUS status = NT_STATUS_OK;
+
+ r->out.domains = NULL;
+
+ status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ r->out.domains = talloc_zero(mem_ctx, struct lsa_RefDomainList);
+ if (r->out.domains == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ 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) {
+ 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;
+
+ r->out.names->count++;
+
+ 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;
+
+ 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;
+ }
+
+ /* set up the authority table */
+ status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype,
+ authority_name, sid,
+ r->out.domains, &sid_index);
+ if (!NT_STATUS_IS_OK(status2)) {
+ return status2;
+ }
+
+ r->out.names->names[i].sid_type = rtype;
+ r->out.names->names[i].name.string = name;
+ r->out.names->names[i].sid_index = sid_index;
+ r->out.names->names[i].unknown = 0;
+
+ (*r->out.count)++;
+ }
+
+ if (*r->out.count == 0) {
+ return NT_STATUS_NONE_MAPPED;
+ }
+ if (*r->out.count != r->in.sids->num_sids) {
+ return STATUS_SOME_UNMAPPED;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/*
+ lsa_LookupSids3
+
+ Identical to LookupSids2, but doesn't take a policy handle
+
+*/
+NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct lsa_LookupSids3 *r)
+{
+ struct lsa_LookupSids2 r2;
+ struct lsa_OpenPolicy2 pol;
+ NTSTATUS status;
+ struct dcesrv_handle *h;
+
+ /* No policy handle on the wire, so make one up here */
+ r2.in.handle = talloc(mem_ctx, struct policy_handle);
+ if (!r2.in.handle) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ pol.out.handle = r2.in.handle;
+ pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ pol.in.attr = NULL;
+ pol.in.system_name = NULL;
+ status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* ensure this handle goes away at the end of this call */
+ DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
+ talloc_steal(mem_ctx, h);
+
+ r2.in.sids = r->in.sids;
+ r2.in.names = r->in.names;
+ r2.in.level = r->in.level;
+ r2.in.count = r->in.count;
+ r2.in.unknown1 = r->in.unknown1;
+ r2.in.unknown2 = r->in.unknown2;
+ r2.out.count = r->out.count;
+ r2.out.names = r->out.names;
+
+ status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
+ if (dce_call->fault_code != 0) {
+ return status;
+ }
+
+ r->out.domains = r2.out.domains;
+ r->out.names = r2.out.names;
+ r->out.count = r2.out.count;
+
+ return status;
+}
+
+
+/*
+ lsa_LookupSids
+*/
+NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct lsa_LookupSids *r)
+{
+ struct lsa_LookupSids2 r2;
+ NTSTATUS status;
+ int i;
+
+ r2.in.handle = r->in.handle;
+ r2.in.sids = r->in.sids;
+ r2.in.names = NULL;
+ r2.in.level = r->in.level;
+ r2.in.count = r->in.count;
+ r2.in.unknown1 = 0;
+ r2.in.unknown2 = 0;
+ r2.out.count = r->out.count;
+ r2.out.names = NULL;
+
+ status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
+ if (dce_call->fault_code != 0) {
+ return status;
+ }
+
+ 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++) {
+ 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;
+ }
+
+ return status;
+}
+
+
+/*
+ lsa_LookupNames3
+*/
+NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct lsa_LookupNames3 *r)
+{
+ struct lsa_policy_state *policy_state;
+ struct dcesrv_handle *policy_handle;
+ int i;
+
+ DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
+
+ policy_state = policy_handle->data;
+
+ r->out.domains = NULL;
+
+ r->out.domains = talloc_zero(mem_ctx, struct lsa_RefDomainList);
+ if (r->out.domains == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ 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) {
+ 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;
+ enum lsa_SidType rtype;
+ NTSTATUS status2;
+
+ r->out.sids->count++;
+
+ 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].unknown = 0;
+
+ status2 = dcesrv_lsa_lookup_name(policy_state, mem_ctx, name, &authority_name, &sid, &rtype);
+ if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
+ continue;
+ }
+
+ status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, rtype, authority_name,
+ sid, r->out.domains, &sid_index);
+ if (!NT_STATUS_IS_OK(status2)) {
+ return status2;
+ }
+
+ 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].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;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/*
+ lsa_LookupNames4
+
+ Identical to LookupNames3, but doesn't take a policy handle
+
+*/
+NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct lsa_LookupNames4 *r)
+{
+ struct lsa_LookupNames3 r2;
+ struct lsa_OpenPolicy2 pol;
+ NTSTATUS status;
+ struct dcesrv_handle *h;
+
+ /* No policy handle on the wire, so make one up here */
+ r2.in.handle = talloc(mem_ctx, struct policy_handle);
+ if (!r2.in.handle) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ pol.out.handle = r2.in.handle;
+ pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ pol.in.attr = NULL;
+ pol.in.system_name = NULL;
+ status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* ensure this handle goes away at the end of this call */
+ DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
+ talloc_steal(mem_ctx, h);
+
+ r2.in.num_names = r->in.num_names;
+ r2.in.names = r->in.names;
+ r2.in.sids = r->in.sids;
+ r2.in.count = r->in.count;
+ r2.in.unknown1 = r->in.unknown1;
+ r2.in.unknown2 = r->in.unknown2;
+ r2.out.domains = r->out.domains;
+ r2.out.sids = r->out.sids;
+ r2.out.count = r->out.count;
+
+ status = dcesrv_lsa_LookupNames3(dce_call, mem_ctx, &r2);
+ if (dce_call->fault_code != 0) {
+ return status;
+ }
+
+ r->out.domains = r2.out.domains;
+ r->out.sids = r2.out.sids;
+ r->out.count = r2.out.count;
+ return status;
+}
+
+/*
+ lsa_LookupNames2
+*/
+NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct lsa_LookupNames2 *r)
+{
+ struct lsa_policy_state *state;
+ struct dcesrv_handle *h;
+ int i;
+
+ r->out.domains = NULL;
+
+ DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
+
+ state = h->data;
+
+ r->out.domains = talloc_zero(mem_ctx, struct lsa_RefDomainList);
+ if (r->out.domains == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ 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) {
+ 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 rtype, sid_index;
+ NTSTATUS status2;
+
+ r->out.sids->count++;
+
+ r->out.sids->sids[i].sid_type = SID_NAME_UNKNOWN;
+ r->out.sids->sids[i].rid = 0xFFFFFFFF;
+ r->out.sids->sids[i].sid_index = 0xFFFFFFFF;
+ r->out.sids->sids[i].unknown = 0;
+
+ status2 = dcesrv_lsa_lookup_name(state, mem_ctx, name,
+ &authority_name, &sid, &rtype);
+ if (!NT_STATUS_IS_OK(status2)) {
+ continue;
+ }
+
+ status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, authority_name,
+ sid, r->out.domains, &sid_index);
+ if (!NT_STATUS_IS_OK(status2)) {
+ return status2;
+ }
+
+ r->out.sids->sids[i].sid_type = rtype;
+ r->out.sids->sids[i].rid = sid->sub_auths[sid->num_auths-1];
+ 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;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/*
+ lsa_LookupNames
+*/
+NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct lsa_LookupNames *r)
+{
+ struct lsa_LookupNames2 r2;
+ NTSTATUS status;
+ int i;
+
+ 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.level = r->in.level;
+ r2.in.count = r->in.count;
+ r2.in.unknown1 = 0;
+ r2.in.unknown2 = 0;
+ r2.out.count = r->out.count;
+
+ status = dcesrv_lsa_LookupNames2(dce_call, mem_ctx, &r2);
+ if (dce_call->fault_code != 0) {
+ return status;
+ }
+
+ r->out.domains = r2.out.domains;
+ 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++) {
+ 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;
+ }
+
+ return status;
+}
+