+/* need access mask/acl implementation */
+
/*
Unix SMB/CIFS implementation.
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-2008
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
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 "rpc_server/lsa/lsa.h"
+#include "../lib/util/util_ldb.h"
+#include "libcli/ldap/ldap_ndr.h"
+#include "system/kerberos.h"
+#include "auth/kerberos/kerberos.h"
+#include "librpc/gen_ndr/ndr_drsblobs.h"
+#include "librpc/gen_ndr/ndr_lsa.h"
+#include "../lib/crypto/crypto.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
uint32_t access_mask;
struct ldb_dn *secret_dn;
struct ldb_context *sam_ldb;
- BOOL global;
+ bool global;
};
/*
struct lsa_policy_state *policy;
uint32_t access_mask;
struct ldb_dn *trusted_domain_dn;
+ struct ldb_dn *trusted_domain_user_dn;
};
static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
*/
static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct lsa_Delete *r)
+{
+ return NT_STATUS_NOT_SUPPORTED;
+}
+
+
+/*
+ lsa_DeleteObject
+*/
+static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct lsa_DeleteObject *r)
{
struct dcesrv_handle *h;
int ret;
DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
+
if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
struct lsa_secret_state *secret_state = h->data;
- ret = samdb_delete(secret_state->sam_ldb, mem_ctx, secret_state->secret_dn);
+
+ /* Ensure user is permitted to delete this... */
+ switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+ {
+ case SECURITY_SYSTEM:
+ case SECURITY_ADMINISTRATOR:
+ break;
+ default:
+ /* Users and annonymous are not allowed delete things */
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ ret = ldb_delete(secret_state->sam_ldb,
+ secret_state->secret_dn);
talloc_free(h);
if (ret != 0) {
return NT_STATUS_INVALID_HANDLE;
}
+ ZERO_STRUCTP(r->out.handle);
+
return NT_STATUS_OK;
} else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
- struct lsa_trusted_domain_state *trusted_domain_state = h->data;
- ret = samdb_delete(trusted_domain_state->policy->sam_ldb, mem_ctx,
- trusted_domain_state->trusted_domain_dn);
- talloc_free(h);
+ struct lsa_trusted_domain_state *trusted_domain_state =
+ talloc_get_type(h->data, struct lsa_trusted_domain_state);
+ ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
if (ret != 0) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
+ trusted_domain_state->trusted_domain_dn);
+ if (ret != 0) {
+ ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
return NT_STATUS_INVALID_HANDLE;
}
+ if (trusted_domain_state->trusted_domain_user_dn) {
+ ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
+ trusted_domain_state->trusted_domain_user_dn);
+ if (ret != 0) {
+ ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
+ return NT_STATUS_INVALID_HANDLE;
+ }
+ }
+
+ ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
+ if (ret != 0) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ talloc_free(h);
+ ZERO_STRUCTP(r->out.handle);
+
return NT_STATUS_OK;
} else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
struct lsa_RightSet *rights;
r2.in.sid = astate->account_sid;
r2.out.rights = rights;
+ /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
+ but we have a LSA_HANDLE_ACCOUNT here, so this call
+ will always fail */
status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
return NT_STATUS_OK;
if (!NT_STATUS_IS_OK(status)) {
return status;
}
+
+ ZERO_STRUCTP(r->out.handle);
}
return NT_STATUS_INVALID_HANDLE;
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
ZERO_STRUCT(domain_guid);
- switch (lp_server_role()) {
+ switch (lp_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
case ROLE_STANDALONE:
role = DS_ROLE_STANDALONE_SERVER;
break;
break;
}
- switch (lp_server_role()) {
+ switch (lp_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
case ROLE_STANDALONE:
- domain = talloc_strdup(mem_ctx, lp_workgroup());
+ domain = talloc_strdup(mem_ctx, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));
W_ERROR_HAVE_NO_MEMORY(domain);
break;
case ROLE_DOMAIN_MEMBER:
- domain = talloc_strdup(mem_ctx, lp_workgroup());
+ domain = talloc_strdup(mem_ctx, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));
W_ERROR_HAVE_NO_MEMORY(domain);
/* TODO: what is with dns_domain and forest and guid? */
break;
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
*/
ZERO_STRUCTP(r->out.info);
switch (r->in.level) {
+ case LSA_POLICY_INFO_AUDIT_LOG:
+ /* we don't need to fill in any of this */
+ ZERO_STRUCT(r->out.info->audit_log);
+ return NT_STATUS_OK;
+ case LSA_POLICY_INFO_AUDIT_EVENTS:
+ /* we don't need to fill in any of this */
+ ZERO_STRUCT(r->out.info->audit_events);
+ return NT_STATUS_OK;
+ case LSA_POLICY_INFO_PD:
+ /* we don't need to fill in any of this */
+ ZERO_STRUCT(r->out.info->pd);
+ return NT_STATUS_OK;
+
case LSA_POLICY_INFO_DOMAIN:
+ return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &r->out.info->domain);
case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &r->out.info->account_domain);
+ case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
+ return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &r->out.info->l_account_domain);
+
+
+ case LSA_POLICY_INFO_ROLE:
+ r->out.info->role.role = LSA_ROLE_PRIMARY;
+ return NT_STATUS_OK;
case LSA_POLICY_INFO_DNS:
+ case LSA_POLICY_INFO_DNS_INT:
return dcesrv_lsa_info_DNS(state, mem_ctx, &r->out.info->dns);
+
+ case LSA_POLICY_INFO_REPLICA:
+ ZERO_STRUCT(r->out.info->replica);
+ return NT_STATUS_OK;
+
+ case LSA_POLICY_INFO_QUOTA:
+ ZERO_STRUCT(r->out.info->quota);
+ return NT_STATUS_OK;
+
+ case LSA_POLICY_INFO_MOD:
+ case LSA_POLICY_INFO_AUDIT_FULL_SET:
+ case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
+ /* windows gives INVALID_PARAMETER */
+ r->out.info = NULL;
+ return NT_STATUS_INVALID_PARAMETER;
}
+ r->out.info = NULL;
return NT_STATUS_INVALID_INFO_CLASS;
}
struct lsa_QueryInfoPolicy2 r2;
NTSTATUS status;
+ ZERO_STRUCT(r2);
+
r2.in.handle = r->in.handle;
r2.in.level = r->in.level;
static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct lsa_SetInfoPolicy *r)
{
+ /* need to support this */
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
lsa_CreateAccount
+
+ This call does not seem to have any long-term effects, hence no database operations
+
+ we need to talk to the MS product group to find out what this account database means!
+
+ answer is that the lsa database is totally separate from the SAM and
+ ldap databases. We are going to need a separate ldb to store these
+ accounts. The SIDs on this account bear no relation to the SIDs in
+ AD
*/
static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct lsa_CreateAccount *r)
/*
lsa_CreateTrustedDomainEx2
*/
-static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
- TALLOC_CTX *mem_ctx,
- struct lsa_CreateTrustedDomainEx2 *r)
-{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
-/*
- lsa_CreateTrustedDomainEx
-*/
-static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
- TALLOC_CTX *mem_ctx,
- struct lsa_CreateTrustedDomainEx *r)
-{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
-/*
- lsa_CreateTrustedDomain
-*/
-static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct lsa_CreateTrustedDomain *r)
+static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct lsa_CreateTrustedDomainEx2 *r,
+ int op)
{
struct dcesrv_handle *policy_handle;
struct lsa_policy_state *policy_state;
struct lsa_trusted_domain_state *trusted_domain_state;
struct dcesrv_handle *handle;
- struct ldb_message **msgs, *msg;
+ struct ldb_message **msgs, *msg, *msg_user;
const char *attrs[] = {
NULL
};
+ const char *netbios_name;
+ const char *dns_name;
const char *name;
+ DATA_BLOB session_key = data_blob(NULL, 0);
+ DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
+ struct trustDomainPasswords auth_struct;
int ret;
-
- DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
+ NTSTATUS nt_status;
+ enum ndr_err_code ndr_err;
+
+ DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
ZERO_STRUCTP(r->out.trustdom_handle);
policy_state = policy_handle->data;
- if (!r->in.info->name.string) {
+ nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
+ netbios_name = r->in.info->netbios_name.string;
+ if (!netbios_name) {
return NT_STATUS_INVALID_PARAMETER;
}
- name = r->in.info->name.string;
- trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
+ dns_name = r->in.info->domain_name.string;
+
+ trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
if (!trusted_domain_state) {
return NT_STATUS_NO_MEMORY;
}
trusted_domain_state->policy = policy_state;
- msg = ldb_msg_new(mem_ctx);
- if (msg == NULL) {
- return NT_STATUS_NO_MEMORY;
+ if (strcasecmp(netbios_name, "BUILTIN") == 0
+ || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
+ || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
+ return NT_STATUS_INVALID_PARAMETER;;
}
- /* search for the trusted_domain record */
- ret = gendb_search(trusted_domain_state->policy->sam_ldb,
- mem_ctx, policy_state->system_dn, &msgs, attrs,
- "(&(cn=%s)(objectclass=trustedDomain))",
- ldb_binary_encode_string(mem_ctx, r->in.info->name.string));
- if (ret > 0) {
- return NT_STATUS_OBJECT_NAME_COLLISION;
+ if (strcasecmp(netbios_name, policy_state->domain_name) == 0
+ || strcasecmp(netbios_name, policy_state->domain_dns) == 0
+ || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
+ || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
+ || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
+ return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
+ }
+
+ /* While this is a REF pointer, some of the functions that wrap this don't provide this */
+ if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
+ /* No secrets are created at this time, for this function */
+ auth_struct.outgoing.count = 0;
+ auth_struct.incoming.count = 0;
+ } else {
+ auth_blob = data_blob_const(r->in.auth_info->auth_blob.data, r->in.auth_info->auth_blob.size);
+ arcfour_crypt_blob(auth_blob.data, auth_blob.length, &session_key);
+ ndr_err = ndr_pull_struct_blob(&auth_blob, mem_ctx,
+ lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
+ &auth_struct,
+ (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
+ if (auth_struct.incoming.count > 1) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ if (auth_struct.incoming.count) {
+ int i;
+ struct trustAuthInOutBlob incoming;
+
+ incoming.count = auth_struct.incoming.count;
+ incoming.current = talloc(mem_ctx, struct AuthenticationInformationArray);
+ if (!incoming.current) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ incoming.current->array = *auth_struct.incoming.current;
+ if (!incoming.current->array) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ incoming.previous = talloc(mem_ctx, struct AuthenticationInformationArray);
+ if (!incoming.previous) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ incoming.previous->array = talloc_array(mem_ctx, struct AuthenticationInformation, incoming.count);
+ if (!incoming.previous->array) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i = 0; i < incoming.count; i++) {
+ incoming.previous->array[i].LastUpdateTime = 0;
+ incoming.previous->array[i].AuthType = 0;
+ }
+ ndr_err = ndr_push_struct_blob(&trustAuthIncoming, mem_ctx,
+ lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
+ &incoming,
+ (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ } else {
+ trustAuthIncoming = data_blob(NULL, 0);
}
- if (ret < 0 || ret > 1) {
- DEBUG(0,("Found %d records matching DN %s\n", ret,
- ldb_dn_get_linearized(policy_state->system_dn)));
+ if (auth_struct.outgoing.count) {
+ int i;
+ struct trustAuthInOutBlob outgoing;
+
+ outgoing.count = auth_struct.outgoing.count;
+ outgoing.current = talloc(mem_ctx, struct AuthenticationInformationArray);
+ if (!outgoing.current) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ outgoing.current->array = *auth_struct.outgoing.current;
+ if (!outgoing.current->array) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ outgoing.previous = talloc(mem_ctx, struct AuthenticationInformationArray);
+ if (!outgoing.previous) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ outgoing.previous->array = talloc_array(mem_ctx, struct AuthenticationInformation, outgoing.count);
+ if (!outgoing.previous->array) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i = 0; i < outgoing.count; i++) {
+ outgoing.previous->array[i].LastUpdateTime = 0;
+ outgoing.previous->array[i].AuthType = 0;
+ }
+ ndr_err = ndr_push_struct_blob(&trustAuthOutgoing, mem_ctx,
+ lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
+ &outgoing,
+ (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ } else {
+ trustAuthOutgoing = data_blob(NULL, 0);
+ }
+
+ ret = ldb_transaction_start(policy_state->sam_ldb);
+ if (ret != LDB_SUCCESS) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ if (dns_name) {
+ char *dns_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
+ char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
+ /* search for the trusted_domain record */
+ ret = gendb_search(policy_state->sam_ldb,
+ mem_ctx, policy_state->system_dn, &msgs, attrs,
+ "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
+ dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
+ if (ret > 0) {
+ ldb_transaction_cancel(policy_state->sam_ldb);
+ return NT_STATUS_OBJECT_NAME_COLLISION;
+ }
+ } else {
+ char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
+ /* search for the trusted_domain record */
+ ret = gendb_search(policy_state->sam_ldb,
+ mem_ctx, policy_state->system_dn, &msgs, attrs,
+ "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
+ netbios_encoded, netbios_encoded, netbios_encoded);
+ if (ret > 0) {
+ ldb_transaction_cancel(policy_state->sam_ldb);
+ return NT_STATUS_OBJECT_NAME_COLLISION;
+ }
+ }
+
+ if (ret < 0 ) {
+ ldb_transaction_cancel(policy_state->sam_ldb);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
+ name = dns_name ? dns_name : netbios_name;
+
+ msg = ldb_msg_new(mem_ctx);
+ if (msg == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
+ ldb_transaction_cancel(policy_state->sam_ldb);
return NT_STATUS_NO_MEMORY;
}
- samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "flatname", name);
+ samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "flatname", netbios_name);
if (r->in.info->sid) {
const char *sid_string = dom_sid_string(mem_ctx, r->in.info->sid);
if (!sid_string) {
+ ldb_transaction_cancel(policy_state->sam_ldb);
return NT_STATUS_NO_MEMORY;
}
}
samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "objectClass", "trustedDomain");
+
+ samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
+
+ samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
+
+ samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
+ if (dns_name) {
+ samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustPartner", dns_name);
+ }
+
+ if (trustAuthIncoming.data) {
+ ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
+ if (ret != LDB_SUCCESS) {
+ ldb_transaction_cancel(policy_state->sam_ldb);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+ if (trustAuthOutgoing.data) {
+ ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
+ if (ret != LDB_SUCCESS) {
+ ldb_transaction_cancel(policy_state->sam_ldb);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
/* create the trusted_domain */
ret = ldb_add(trusted_domain_state->policy->sam_ldb, msg);
+ switch (ret) {
+ case LDB_SUCCESS:
+ break;
+ case LDB_ERR_ENTRY_ALREADY_EXISTS:
+ ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
+ DEBUG(0,("Failed to create trusted domain record %s: %s\n",
+ ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(trusted_domain_state->policy->sam_ldb)));
+ return NT_STATUS_DOMAIN_EXISTS;
+ case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
+ ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
+ DEBUG(0,("Failed to create trusted domain record %s: %s\n",
+ ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(trusted_domain_state->policy->sam_ldb)));
+ return NT_STATUS_ACCESS_DENIED;
+ default:
+ ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
+ DEBUG(0,("Failed to create user record %s: %s\n",
+ ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(trusted_domain_state->policy->sam_ldb)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
+ msg_user = ldb_msg_new(mem_ctx);
+ if (msg == NULL) {
+ ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* Inbound trusts must also create a cn=users object to match */
+
+ trusted_domain_state->trusted_domain_user_dn = msg_user->dn
+ = ldb_dn_copy(trusted_domain_state, policy_state->domain_dn);
+ if ( ! ldb_dn_add_child_fmt(msg_user->dn, "cn=users")) {
+ ldb_transaction_cancel(policy_state->sam_ldb);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if ( ! ldb_dn_add_child_fmt(msg_user->dn, "cn=%s", netbios_name)) {
+ ldb_transaction_cancel(policy_state->sam_ldb);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ldb_msg_add_string(msg_user, "objectClass", "user");
+
+ ldb_msg_add_steal_string(msg_user, "samAccountName",
+ talloc_asprintf(mem_ctx, "%s$", netbios_name));
+
+ if (samdb_msg_add_uint(trusted_domain_state->policy->sam_ldb, mem_ctx, msg_user,
+ "userAccountControl",
+ UF_INTERDOMAIN_TRUST_ACCOUNT) != 0) {
+ ldb_transaction_cancel(policy_state->sam_ldb);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (auth_struct.incoming.count) {
+ int i;
+ for (i=0; i < auth_struct.incoming.count; i++ ) {
+ if (auth_struct.incoming.current[i]->AuthType == TRUST_AUTH_TYPE_NT4OWF) {
+ samdb_msg_add_hash(trusted_domain_state->policy->sam_ldb,
+ mem_ctx, msg_user, "unicodePwd",
+ &auth_struct.incoming.current[i]->AuthInfo.nt4owf.password);
+ } else if (auth_struct.incoming.current[i]->AuthType == TRUST_AUTH_TYPE_CLEAR) {
+ DATA_BLOB new_password = data_blob_const(auth_struct.incoming.current[i]->AuthInfo.clear.password,
+ auth_struct.incoming.current[i]->AuthInfo.clear.size);
+ ret = ldb_msg_add_value(msg_user, "clearTextPassword", &new_password, NULL);
+ if (ret != LDB_SUCCESS) {
+ ldb_transaction_cancel(policy_state->sam_ldb);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+ }
+ }
+
+ /* create the cn=users trusted_domain account */
+ ret = ldb_add(trusted_domain_state->policy->sam_ldb, msg_user);
+ switch (ret) {
+ case LDB_SUCCESS:
+ break;
+ case LDB_ERR_ENTRY_ALREADY_EXISTS:
+ ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
+ DEBUG(0,("Failed to create trusted domain record %s: %s\n",
+ ldb_dn_get_linearized(msg_user->dn),
+ ldb_errstring(trusted_domain_state->policy->sam_ldb)));
+ return NT_STATUS_DOMAIN_EXISTS;
+ case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
+ ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
+ DEBUG(0,("Failed to create trusted domain record %s: %s\n",
+ ldb_dn_get_linearized(msg_user->dn),
+ ldb_errstring(trusted_domain_state->policy->sam_ldb)));
+ return NT_STATUS_ACCESS_DENIED;
+ default:
+ ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
+ DEBUG(0,("Failed to create user record %s: %s\n",
+ ldb_dn_get_linearized(msg_user->dn),
+ ldb_errstring(trusted_domain_state->policy->sam_ldb)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ }
+
+ ret = ldb_transaction_commit(policy_state->sam_ldb);
if (ret != LDB_SUCCESS) {
- DEBUG(0,("Failed to create trusted_domain record %s: %s\n",
- ldb_dn_get_linearized(msg->dn), ldb_errstring(trusted_domain_state->policy->sam_ldb)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
return NT_STATUS_OK;
}
+/*
+ lsa_CreateTrustedDomainEx2
+*/
+static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct lsa_CreateTrustedDomainEx2 *r)
+{
+ return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2);
+}
+/*
+ lsa_CreateTrustedDomainEx
+*/
+static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct lsa_CreateTrustedDomainEx *r)
+{
+ struct lsa_CreateTrustedDomainEx2 r2;
+
+ r2.in.policy_handle = r->in.policy_handle;
+ r2.in.info = r->in.info;
+ r2.in.auth_info = r->in.auth_info;
+ r2.out.trustdom_handle = r->out.trustdom_handle;
+ return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX);
+}
+
+/*
+ lsa_CreateTrustedDomain
+*/
+static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct lsa_CreateTrustedDomain *r)
+{
+ struct lsa_CreateTrustedDomainEx2 r2;
+
+ r2.in.policy_handle = r->in.policy_handle;
+ r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
+ if (!r2.in.info) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ r2.in.info->domain_name.string = NULL;
+ r2.in.info->netbios_name = r->in.info->name;
+ r2.in.info->sid = r->in.info->sid;
+ r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
+ r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
+ r2.in.info->trust_attributes = 0;
+
+ r2.in.access_mask = r->in.access_mask;
+ r2.out.trustdom_handle = r->out.trustdom_handle;
+
+ return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN);
+
+}
+
/*
lsa_OpenTrustedDomain
*/
struct dcesrv_handle *handle;
struct ldb_message **msgs;
const char *attrs[] = {
+ "trustDirection",
+ "flatname",
NULL
};
ZERO_STRUCTP(r->out.trustdom_handle);
policy_state = policy_handle->data;
- trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
+ trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
if (!trusted_domain_state) {
return NT_STATUS_NO_MEMORY;
}
}
trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
-
+
+ trusted_domain_state->trusted_domain_user_dn = NULL;
+
+ if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
+ const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
+ /* search for the trusted_domain record */
+ ret = gendb_search(trusted_domain_state->policy->sam_ldb,
+ mem_ctx, policy_state->domain_dn, &msgs, attrs,
+ "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%d))",
+ flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
+ if (ret == 1) {
+ trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
+ }
+ }
handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
if (!handle) {
return NT_STATUS_NO_MEMORY;
return NT_STATUS_INVALID_PARAMETER;
}
- trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
+ trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
if (!trusted_domain_state) {
return NT_STATUS_NO_MEMORY;
}
{
NTSTATUS status;
struct lsa_OpenTrustedDomain open;
- struct lsa_Delete delete;
+ struct lsa_DeleteObject delete;
struct dcesrv_handle *h;
open.in.handle = r->in.handle;
talloc_steal(mem_ctx, h);
delete.in.handle = open.out.trustdom_handle;
- status = dcesrv_lsa_Delete(dce_call, mem_ctx, &delete);
+ delete.out.handle = open.out.trustdom_handle;
+ status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &delete);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
"trustDirection",
"trustType",
"trustAttributes",
+ "msDs-supportedEncryptionTypes",
NULL
};
DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
- trusted_domain_state = h->data;
+ trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
/* pull all the user attributes */
ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
ZERO_STRUCT(r->out.info->full_info);
return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->full_info.info_ex);
- case LSA_TRUSTED_DOMAIN_INFO_INFO_ALL:
- ZERO_STRUCT(r->out.info->info_all);
- return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->info_all.info_ex);
+ case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
+ ZERO_STRUCT(r->out.info->full_info2_internal);
+ r->out.info->full_info2_internal.posix_offset.posix_offset
+ = samdb_result_uint(msg, "posixOffset", 0);
+ return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->full_info2_internal.info.info_ex);
+
+ case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRTYPION_TYPES:
+ r->out.info->enc_types.enc_types
+ = samdb_result_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
+ break;
- case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS_INFO:
- case LSA_TRUSTED_DOMAIN_INFO_11:
+ case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
+ case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
/* oops, we don't want to return the info after all */
talloc_free(r->out.info);
r->out.info = NULL;
if (count == -1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- if (count == 0 || r->in.max_size == 0) {
- return NT_STATUS_OK;
- }
/* convert to lsa_TrustInformation format */
entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
if (count == -1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- if (count == 0 || r->in.max_size == 0) {
- return NT_STATUS_OK;
- }
/* convert to lsa_DomainInformation format */
entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
r->out.domains->count = MIN(r->out.domains->count,
1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
- r->out.domains->domains = entries + *r->in.resume_handle;
- r->out.domains->count = r->out.domains->count;
-
- if (r->out.domains->count < count - *r->in.resume_handle) {
- *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
- return STATUS_MORE_ENTRIES;
- }
-
- return NT_STATUS_OK;
-}
-
-
-/*
- 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;
+ r->out.domains->domains = entries + *r->in.resume_handle;
+ r->out.domains->count = r->out.domains->count;
+
+ if (r->out.domains->count < count - *r->in.resume_handle) {
+ *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
+ return STATUS_MORE_ENTRIES;
}
- return status;
+ return NT_STATUS_OK;
}
return NT_STATUS_OK;
}
- ret = samdb_modify(state->sam_ldb, mem_ctx, msg);
+ ret = ldb_modify(state->sam_ldb, msg);
if (ret != 0) {
if (ldb_flag == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct lsa_GetSystemAccessAccount *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ int i;
+ NTSTATUS status;
+ struct lsa_EnumPrivsAccount enumPrivs;
+
+ enumPrivs.in.handle = r->in.handle;
+
+ status = dcesrv_lsa_EnumPrivsAccount(dce_call, mem_ctx, &enumPrivs);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ *(r->out.access_mask) = 0x00000000;
+
+ for (i = 0; i < enumPrivs.out.privs->count; i++) {
+ int priv = enumPrivs.out.privs->set[i].luid.low;
+
+ switch (priv) {
+ case SEC_PRIV_INTERACTIVE_LOGON:
+ *(r->out.access_mask) |= LSA_POLICY_MODE_INTERACTIVE;
+ break;
+ case SEC_PRIV_NETWORK_LOGON:
+ *(r->out.access_mask) |= LSA_POLICY_MODE_NETWORK;
+ break;
+ case SEC_PRIV_REMOTE_INTERACTIVE_LOGON:
+ *(r->out.access_mask) |= LSA_POLICY_MODE_REMOTE_INTERACTIVE;
+ break;
+ }
+ }
+
+ return NT_STATUS_OK;
}
DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
ZERO_STRUCTP(r->out.sec_handle);
+ switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+ {
+ case SECURITY_SYSTEM:
+ case SECURITY_ADMINISTRATOR:
+ break;
+ default:
+ /* Users and annonymous are not allowed create secrets */
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
policy_state = policy_handle->data;
if (!r->in.name.string) {
if (strncmp("G$", r->in.name.string, 2) == 0) {
const char *name2;
name = &r->in.name.string[2];
- secret_state->sam_ldb = talloc_reference(secret_state, policy_state->sam_ldb);
- secret_state->global = True;
+ /* We need to connect to the database as system, as this is one of the rare RPC calls that must read the secrets (and this is denied otherwise) */
+ secret_state->sam_ldb = talloc_reference(secret_state,
+ samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(secret_state, dce_call->conn->dce_ctx->lp_ctx)));
+ secret_state->global = true;
if (strlen(name) < 1) {
return NT_STATUS_INVALID_PARAMETER;
samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name2);
} else {
- secret_state->global = False;
+ secret_state->global = false;
name = r->in.name.string;
if (strlen(name) < 1) {
return NT_STATUS_INVALID_PARAMETER;
}
- secret_state->sam_ldb = talloc_reference(secret_state, secrets_db_connect(mem_ctx));
+ secret_state->sam_ldb = talloc_reference(secret_state,
+ secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
/* search for the secret record */
ret = gendb_search(secret_state->sam_ldb, mem_ctx,
ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
/* create the secret */
- ret = samdb_add(secret_state->sam_ldb, mem_ctx, msg);
+ ret = ldb_add(secret_state->sam_ldb, msg);
if (ret != 0) {
DEBUG(0,("Failed to create secret record %s: %s\n",
ldb_dn_get_linearized(msg->dn),
return NT_STATUS_INVALID_PARAMETER;
}
+ switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+ {
+ case SECURITY_SYSTEM:
+ case SECURITY_ADMINISTRATOR:
+ break;
+ default:
+ /* Users and annonymous are not allowed to access secrets */
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
secret_state = talloc(mem_ctx, struct lsa_secret_state);
if (!secret_state) {
return NT_STATUS_NO_MEMORY;
if (strncmp("G$", r->in.name.string, 2) == 0) {
name = &r->in.name.string[2];
- secret_state->sam_ldb = talloc_reference(secret_state, policy_state->sam_ldb);
- secret_state->global = True;
+ /* We need to connect to the database as system, as this is one of the rare RPC calls that must read the secrets (and this is denied otherwise) */
+ secret_state->sam_ldb = talloc_reference(secret_state,
+ samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(secret_state, dce_call->conn->dce_ctx->lp_ctx)));
+ secret_state->global = true;
if (strlen(name) < 1) {
return NT_STATUS_INVALID_PARAMETER;
}
} else {
- secret_state->sam_ldb = talloc_reference(secret_state, secrets_db_connect(mem_ctx));
+ secret_state->global = false;
+ secret_state->sam_ldb = talloc_reference(secret_state,
+ secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
- secret_state->global = False;
name = r->in.name.string;
if (strlen(name) < 1) {
return NT_STATUS_INVALID_PARAMETER;
return NT_STATUS_NO_MEMORY;
}
- if (!r->in.new_val) {
- /* This behaviour varies depending of if this is a local, or a global secret... */
- if (secret_state->global) {
- /* set old value mtime */
- if (samdb_msg_add_uint64(secret_state->sam_ldb,
- mem_ctx, msg, "lastSetTime", nt_now) != 0) {
- return NT_STATUS_NO_MEMORY;
- }
- } else {
- if (samdb_msg_add_delete(secret_state->sam_ldb,
- mem_ctx, msg, "currentValue")) {
- return NT_STATUS_NO_MEMORY;
- }
- if (samdb_msg_add_delete(secret_state->sam_ldb,
- mem_ctx, msg, "lastSetTime")) {
- return NT_STATUS_NO_MEMORY;
- }
+ } else {
+ /* If the old value is not set, then migrate the
+ * current value to the old value */
+ const struct ldb_val *old_val;
+ NTTIME last_set_time;
+ struct ldb_message **res;
+ const char *attrs[] = {
+ "currentValue",
+ "lastSetTime",
+ NULL
+ };
+
+ /* search for the secret record */
+ ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
+ secret_state->secret_dn, &res, attrs);
+ if (ret == 0) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ if (ret != 1) {
+ DEBUG(0,("Found %d records matching dn=%s\n", ret,
+ ldb_dn_get_linearized(secret_state->secret_dn)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
+ last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
+
+ if (old_val) {
+ /* set old value */
+ if (samdb_msg_add_value(secret_state->sam_ldb,
+ mem_ctx, msg, "priorValue",
+ old_val) != 0) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ } else {
+ if (samdb_msg_add_delete(secret_state->sam_ldb,
+ mem_ctx, msg, "priorValue")) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ }
+
+ /* set old value mtime */
+ if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
+ if (samdb_msg_add_uint64(secret_state->sam_ldb,
+ mem_ctx, msg, "priorSetTime", last_set_time) != 0) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ } else {
+ if (samdb_msg_add_uint64(secret_state->sam_ldb,
+ mem_ctx, msg, "priorSetTime", nt_now) != 0) {
+ return NT_STATUS_NO_MEMORY;
}
}
}
return NT_STATUS_NO_MEMORY;
}
- /* If the old value is not set, then migrate the
- * current value to the old value */
- if (!r->in.old_val) {
- const struct ldb_val *new_val;
- NTTIME last_set_time;
- struct ldb_message **res;
- const char *attrs[] = {
- "currentValue",
- "lastSetTime",
- NULL
- };
-
- /* search for the secret record */
- ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
- secret_state->secret_dn, &res, attrs);
- if (ret == 0) {
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- }
-
- if (ret != 1) {
- DEBUG(0,("Found %d records matching dn=%s\n", ret,
- ldb_dn_get_linearized(secret_state->secret_dn)));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
- last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
-
- if (new_val) {
- /* set value */
- if (samdb_msg_add_value(secret_state->sam_ldb,
- mem_ctx, msg, "priorValue",
- new_val) != 0) {
- return NT_STATUS_NO_MEMORY;
- }
- }
-
- /* set new value mtime */
- if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
- if (samdb_msg_add_uint64(secret_state->sam_ldb,
- mem_ctx, msg, "priorSetTime", last_set_time) != 0) {
- return NT_STATUS_NO_MEMORY;
- }
- }
+ } else {
+ /* NULL out the NEW value */
+ if (samdb_msg_add_uint64(secret_state->sam_ldb,
+ mem_ctx, msg, "lastSetTime", nt_now) != 0) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ if (samdb_msg_add_delete(secret_state->sam_ldb,
+ mem_ctx, msg, "currentValue")) {
+ return NT_STATUS_NO_MEMORY;
}
}
DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
+ /* Ensure user is permitted to read this... */
+ switch (security_session_user_level(dce_call->conn->auth_state.session_info))
+ {
+ case SECURITY_SYSTEM:
+ case SECURITY_ADMINISTRATOR:
+ break;
+ default:
+ /* Users and annonymous are not allowed to read secrets */
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
secret_state = h->data;
/* pull all the user attributes */
}
-/*
- lsa_DeleteObject
-*/
-static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct lsa_DeleteObject *r)
-{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
-
/*
lsa_EnumAccountsWithUserRight
*/
TALLOC_CTX *mem_ctx,
struct lsa_SetInfoPolicy2 *r)
{
+ /* need to support these */
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
TALLOC_CTX *mem_ctx,
struct lsa_QueryDomainInformationPolicy *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ r->out.info = talloc(mem_ctx, union lsa_DomainInformationPolicy);
+ if (!r->out.info) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ switch (r->in.level) {
+ case LSA_DOMAIN_INFO_POLICY_EFS:
+ talloc_free(r->out.info);
+ r->out.info = NULL;
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ case LSA_DOMAIN_INFO_POLICY_KERBEROS:
+ {
+ struct lsa_DomainInfoKerberos *k = &r->out.info->kerberos_info;
+ struct smb_krb5_context *smb_krb5_context;
+ int ret = smb_krb5_init_context(mem_ctx,
+ dce_call->event_ctx,
+ dce_call->conn->dce_ctx->lp_ctx,
+ &smb_krb5_context);
+ if (ret != 0) {
+ talloc_free(r->out.info);
+ r->out.info = NULL;
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ k->enforce_restrictions = 0; /* FIXME, details missing from MS-LSAD 2.2.53 */
+ k->service_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
+ k->user_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
+ k->user_tkt_renewaltime = 0; /* Need to find somewhere to store this, and query in KDC too */
+ k->clock_skew = krb5_get_max_time_skew(smb_krb5_context->krb5_context);
+ talloc_free(smb_krb5_context);
+ return NT_STATUS_OK;
+ }
+ default:
+ talloc_free(r->out.info);
+ r->out.info = NULL;
+ return NT_STATUS_INVALID_INFO_CLASS;
+ }
}
/*
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
*/