1 /* need access mask/acl implementation */
4 Unix SMB/CIFS implementation.
6 endpoint server for the lsarpc pipe
8 Copyright (C) Andrew Tridgell 2004
9 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "rpc_server/lsa/lsa.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_drsblobs.h"
29 #include "librpc/gen_ndr/ndr_lsa.h"
30 #include "lib/util/tsort.h"
31 #include "dsdb/common/util.h"
32 #include "libcli/security/session.h"
33 #include "libcli/lsarpc/util_lsarpc.h"
34 #include "lib/messaging/irpc.h"
35 #include "libds/common/roles.h"
36 #include "lib/util/smb_strtox.h"
38 #include "lib/crypto/gnutls_helpers.h"
39 #include <gnutls/gnutls.h>
40 #include <gnutls/crypto.h>
44 #define DCESRV_INTERFACE_LSARPC_BIND(context, iface) \
45 dcesrv_interface_lsarpc_bind(context, iface)
46 static NTSTATUS dcesrv_interface_lsarpc_bind(struct dcesrv_connection_context *context,
47 const struct dcesrv_interface *iface)
49 return dcesrv_interface_bind_reject_connect(context, iface);
52 static NTSTATUS lsarpc__op_init_server(struct dcesrv_context *dce_ctx,
53 const struct dcesrv_endpoint_server *ep_server);
54 static const struct dcesrv_interface dcesrv_lsarpc_interface;
56 #define NCACN_NP_PIPE_NETLOGON "ncacn_np:[\\pipe\\netlogon]"
57 #define NCACN_NP_PIPE_LSASS "ncacn_np:[\\pipe\\lsass]"
58 #define DCESRV_INTERFACE_LSARPC_NCACN_NP_SECONDARY_ENDPOINT NCACN_NP_PIPE_LSASS
60 #define DCESRV_INTERFACE_LSARPC_INIT_SERVER \
61 dcesrv_interface_lsarpc_init_server
62 static NTSTATUS dcesrv_interface_lsarpc_init_server(struct dcesrv_context *dce_ctx,
63 const struct dcesrv_endpoint_server *ep_server)
65 if (lpcfg_lsa_over_netlogon(dce_ctx->lp_ctx)) {
66 NTSTATUS ret = dcesrv_interface_register(dce_ctx,
67 NCACN_NP_PIPE_NETLOGON,
69 &dcesrv_lsarpc_interface, NULL);
70 if (!NT_STATUS_IS_OK(ret)) {
71 DEBUG(1,("lsarpc_op_init_server: failed to register endpoint '\\pipe\\netlogon'\n"));
75 return lsarpc__op_init_server(dce_ctx, ep_server);
79 this type allows us to distinguish handle types
83 state associated with a lsa_OpenAccount() operation
85 struct lsa_account_state {
86 struct lsa_policy_state *policy;
88 struct dom_sid *account_sid;
93 state associated with a lsa_OpenSecret() operation
95 struct lsa_secret_state {
96 struct lsa_policy_state *policy;
98 struct ldb_dn *secret_dn;
99 struct ldb_context *sam_ldb;
104 state associated with a lsa_OpenTrustedDomain() operation
106 struct lsa_trusted_domain_state {
107 struct lsa_policy_state *policy;
108 uint32_t access_mask;
109 struct ldb_dn *trusted_domain_dn;
110 struct ldb_dn *trusted_domain_user_dn;
113 static bool dcesrc_lsa_valid_AccountRight(const char *right)
115 enum sec_privilege priv_id;
118 priv_id = sec_privilege_id(right);
119 if (priv_id != SEC_PRIV_INVALID) {
123 right_bit = sec_right_bit(right);
124 if (right_bit != 0) {
132 this is based on the samba3 function make_lsa_object_sd()
133 It uses the same logic, but with samba4 helper functions
135 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
136 struct security_descriptor **sd,
142 struct dom_sid *domain_sid, *domain_admins_sid;
143 const char *domain_admins_sid_str, *sidstr;
144 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
146 status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
147 if (!NT_STATUS_IS_OK(status)) {
148 TALLOC_FREE(tmp_ctx);
152 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
153 if (domain_admins_sid == NULL) {
154 TALLOC_FREE(tmp_ctx);
155 return NT_STATUS_NO_MEMORY;
158 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
159 if (domain_admins_sid_str == NULL) {
160 TALLOC_FREE(tmp_ctx);
161 return NT_STATUS_NO_MEMORY;
164 sidstr = dom_sid_string(tmp_ctx, sid);
165 if (sidstr == NULL) {
166 TALLOC_FREE(tmp_ctx);
167 return NT_STATUS_NO_MEMORY;
170 *sd = security_descriptor_dacl_create(mem_ctx,
174 SEC_ACE_TYPE_ACCESS_ALLOWED,
175 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
177 SID_BUILTIN_ADMINISTRATORS,
178 SEC_ACE_TYPE_ACCESS_ALLOWED,
181 SID_BUILTIN_ACCOUNT_OPERATORS,
182 SEC_ACE_TYPE_ACCESS_ALLOWED,
185 domain_admins_sid_str,
186 SEC_ACE_TYPE_ACCESS_ALLOWED,
190 SEC_ACE_TYPE_ACCESS_ALLOWED,
194 talloc_free(tmp_ctx);
196 NT_STATUS_HAVE_NO_MEMORY(*sd);
202 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
204 struct lsa_EnumAccountRights *r);
206 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
208 struct lsa_policy_state *state,
211 const struct lsa_RightSet *rights);
216 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
219 enum dcerpc_transport_t transport =
220 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
221 struct dcesrv_handle *h;
223 if (transport != NCACN_NP && transport != NCALRPC) {
224 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
227 *r->out.handle = *r->in.handle;
229 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
233 ZERO_STRUCTP(r->out.handle);
242 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
243 struct lsa_Delete *r)
245 return NT_STATUS_NOT_SUPPORTED;
252 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
253 struct lsa_DeleteObject *r)
255 struct auth_session_info *session_info =
256 dcesrv_call_session_info(dce_call);
257 struct dcesrv_handle *h;
260 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
262 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
263 struct lsa_secret_state *secret_state = h->data;
265 /* Ensure user is permitted to delete this... */
266 switch (security_session_user_level(session_info, NULL))
268 case SECURITY_SYSTEM:
269 case SECURITY_ADMINISTRATOR:
272 /* Users and anonymous are not allowed to delete things */
273 return NT_STATUS_ACCESS_DENIED;
276 ret = ldb_delete(secret_state->sam_ldb,
277 secret_state->secret_dn);
278 if (ret != LDB_SUCCESS) {
279 return NT_STATUS_INVALID_HANDLE;
282 ZERO_STRUCTP(r->out.handle);
286 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
287 struct lsa_trusted_domain_state *trusted_domain_state =
288 talloc_get_type(h->data, struct lsa_trusted_domain_state);
289 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
290 if (ret != LDB_SUCCESS) {
291 return NT_STATUS_INTERNAL_DB_CORRUPTION;
294 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
295 trusted_domain_state->trusted_domain_dn);
296 if (ret != LDB_SUCCESS) {
297 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
298 return NT_STATUS_INVALID_HANDLE;
301 if (trusted_domain_state->trusted_domain_user_dn) {
302 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
303 trusted_domain_state->trusted_domain_user_dn);
304 if (ret != LDB_SUCCESS) {
305 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
306 return NT_STATUS_INVALID_HANDLE;
310 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
311 if (ret != LDB_SUCCESS) {
312 return NT_STATUS_INTERNAL_DB_CORRUPTION;
315 ZERO_STRUCTP(r->out.handle);
319 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
320 struct lsa_RightSet *rights;
321 struct lsa_account_state *astate;
322 struct lsa_EnumAccountRights r2;
325 rights = talloc(mem_ctx, struct lsa_RightSet);
327 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
331 r2.in.handle = &astate->policy->handle->wire_handle;
332 r2.in.sid = astate->account_sid;
333 r2.out.rights = rights;
335 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
336 but we have a LSA_HANDLE_ACCOUNT here, so this call
338 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
339 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
343 if (!NT_STATUS_IS_OK(status)) {
347 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
348 LDB_FLAG_MOD_DELETE, astate->account_sid,
350 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
354 if (!NT_STATUS_IS_OK(status)) {
358 ZERO_STRUCTP(r->out.handle);
363 return NT_STATUS_INVALID_HANDLE;
370 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
371 struct lsa_EnumPrivs *r)
373 struct dcesrv_handle *h;
375 enum sec_privilege priv;
376 const char *privname;
378 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
380 i = *r->in.resume_handle;
382 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
383 r->out.privs->count < r->in.max_count) {
384 struct lsa_PrivEntry *e;
385 privname = sec_privilege_name(priv);
386 r->out.privs->privs = talloc_realloc(r->out.privs,
388 struct lsa_PrivEntry,
389 r->out.privs->count+1);
390 if (r->out.privs->privs == NULL) {
391 return NT_STATUS_NO_MEMORY;
393 e = &r->out.privs->privs[r->out.privs->count];
396 e->name.string = privname;
397 r->out.privs->count++;
401 *r->out.resume_handle = i;
410 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
411 struct lsa_QuerySecurity *r)
413 struct auth_session_info *session_info =
414 dcesrv_call_session_info(dce_call);
415 struct dcesrv_handle *h;
416 const struct security_descriptor *sd = NULL;
417 uint32_t access_granted = 0;
418 struct sec_desc_buf *sdbuf = NULL;
422 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
424 sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
426 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
427 struct lsa_policy_state *pstate = h->data;
430 access_granted = pstate->access_mask;
432 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
433 struct lsa_account_state *astate = h->data;
434 struct security_descriptor *_sd = NULL;
436 status = dcesrv_build_lsa_sd(mem_ctx, &_sd, sid,
437 LSA_ACCOUNT_ALL_ACCESS);
438 if (!NT_STATUS_IS_OK(status)) {
442 access_granted = astate->access_mask;
444 return NT_STATUS_INVALID_HANDLE;
447 sdbuf = talloc_zero(mem_ctx, struct sec_desc_buf);
449 return NT_STATUS_NO_MEMORY;
452 status = security_descriptor_for_client(sdbuf, sd, r->in.sec_info,
453 access_granted, &sdbuf->sd);
454 if (!NT_STATUS_IS_OK(status)) {
458 *r->out.sdbuf = sdbuf;
467 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
468 struct lsa_SetSecObj *r)
470 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
477 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
478 struct lsa_ChangePassword *r)
480 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
484 dssetup_DsRoleGetPrimaryDomainInformation
486 This is not an LSA call, but is the only call left on the DSSETUP
487 pipe (after the pipe was truncated), and needs lsa_get_policy_state
489 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
491 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
493 union dssetup_DsRoleInfo *info;
495 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
496 W_ERROR_HAVE_NO_MEMORY(info);
498 switch (r->in.level) {
499 case DS_ROLE_BASIC_INFORMATION:
501 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
503 const char *domain = NULL;
504 const char *dns_domain = NULL;
505 const char *forest = NULL;
506 struct GUID domain_guid;
507 struct lsa_policy_state *state;
509 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
510 0, /* we skip access checks */
512 if (!NT_STATUS_IS_OK(status)) {
513 return ntstatus_to_werror(status);
516 ZERO_STRUCT(domain_guid);
518 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
519 case ROLE_STANDALONE:
520 role = DS_ROLE_STANDALONE_SERVER;
522 case ROLE_DOMAIN_MEMBER:
523 role = DS_ROLE_MEMBER_SERVER;
525 case ROLE_ACTIVE_DIRECTORY_DC:
526 if (samdb_is_pdc(state->sam_ldb)) {
527 role = DS_ROLE_PRIMARY_DC;
529 role = DS_ROLE_BACKUP_DC;
534 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
535 case ROLE_STANDALONE:
536 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
537 W_ERROR_HAVE_NO_MEMORY(domain);
539 case ROLE_DOMAIN_MEMBER:
540 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
541 W_ERROR_HAVE_NO_MEMORY(domain);
542 /* TODO: what is with dns_domain and forest and guid? */
544 case ROLE_ACTIVE_DIRECTORY_DC:
545 flags = DS_ROLE_PRIMARY_DS_RUNNING;
547 if (state->mixed_domain == 1) {
548 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
551 domain = state->domain_name;
552 dns_domain = state->domain_dns;
553 forest = state->forest_dns;
555 domain_guid = state->domain_guid;
556 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
560 info->basic.role = role;
561 info->basic.flags = flags;
562 info->basic.domain = domain;
563 info->basic.dns_domain = dns_domain;
564 info->basic.forest = forest;
565 info->basic.domain_guid = domain_guid;
570 case DS_ROLE_UPGRADE_STATUS:
572 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
573 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
578 case DS_ROLE_OP_STATUS:
580 info->opstatus.status = DS_ROLE_OP_IDLE;
586 return WERR_INVALID_PARAMETER;
591 fill in the AccountDomain info
593 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
594 struct lsa_DomainInfo *info)
596 info->name.string = state->domain_name;
597 info->sid = state->domain_sid;
603 fill in the DNS domain info
605 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
606 struct lsa_DnsDomainInfo *info)
608 info->name.string = state->domain_name;
609 info->sid = state->domain_sid;
610 info->dns_domain.string = state->domain_dns;
611 info->dns_forest.string = state->forest_dns;
612 info->domain_guid = state->domain_guid;
620 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
621 struct lsa_QueryInfoPolicy2 *r)
623 struct lsa_policy_state *state;
624 struct dcesrv_handle *h;
625 union lsa_PolicyInformation *info;
629 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
633 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
635 return NT_STATUS_NO_MEMORY;
639 switch (r->in.level) {
640 case LSA_POLICY_INFO_AUDIT_LOG:
641 /* we don't need to fill in any of this */
642 ZERO_STRUCT(info->audit_log);
644 case LSA_POLICY_INFO_AUDIT_EVENTS:
645 /* we don't need to fill in any of this */
646 ZERO_STRUCT(info->audit_events);
648 case LSA_POLICY_INFO_PD:
649 /* we don't need to fill in any of this */
650 ZERO_STRUCT(info->pd);
653 case LSA_POLICY_INFO_DOMAIN:
654 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
655 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
656 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
657 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
658 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
660 case LSA_POLICY_INFO_ROLE:
661 info->role.role = LSA_ROLE_PRIMARY;
664 case LSA_POLICY_INFO_DNS:
665 case LSA_POLICY_INFO_DNS_INT:
666 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
668 case LSA_POLICY_INFO_REPLICA:
669 ZERO_STRUCT(info->replica);
672 case LSA_POLICY_INFO_QUOTA:
673 ZERO_STRUCT(info->quota);
676 case LSA_POLICY_INFO_MOD:
677 case LSA_POLICY_INFO_AUDIT_FULL_SET:
678 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
679 /* windows gives INVALID_PARAMETER */
681 return NT_STATUS_INVALID_PARAMETER;
685 return NT_STATUS_INVALID_INFO_CLASS;
691 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
692 struct lsa_QueryInfoPolicy *r)
694 struct lsa_QueryInfoPolicy2 r2;
699 r2.in.handle = r->in.handle;
700 r2.in.level = r->in.level;
701 r2.out.info = r->out.info;
703 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
711 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
712 struct lsa_SetInfoPolicy *r)
714 /* need to support this */
715 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
722 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
723 struct lsa_ClearAuditLog *r)
725 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
729 static const struct generic_mapping dcesrv_lsa_account_mapping = {
733 LSA_ACCOUNT_ALL_ACCESS
739 This call does not seem to have any long-term effects, hence no database operations
741 we need to talk to the MS product group to find out what this account database means!
743 answer is that the lsa database is totally separate from the SAM and
744 ldap databases. We are going to need a separate ldb to store these
745 accounts. The SIDs on this account bear no relation to the SIDs in
748 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
749 struct lsa_CreateAccount *r)
751 struct lsa_account_state *astate;
753 struct lsa_policy_state *state;
754 struct dcesrv_handle *h, *ah;
756 ZERO_STRUCTP(r->out.acct_handle);
758 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
762 astate = talloc(dce_call->conn, struct lsa_account_state);
763 if (astate == NULL) {
764 return NT_STATUS_NO_MEMORY;
767 astate->account_sid = dom_sid_dup(astate, r->in.sid);
768 if (astate->account_sid == NULL) {
770 return NT_STATUS_NO_MEMORY;
773 astate->policy = talloc_reference(astate, state);
774 astate->access_mask = r->in.access_mask;
777 * For now we grant all requested access.
779 * We will fail at the ldb layer later.
781 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
782 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
783 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
785 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
787 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X].\n",
788 __func__, dom_sid_string(mem_ctx, astate->account_sid),
789 (unsigned)r->in.access_mask,
790 (unsigned)astate->access_mask));
792 ah = dcesrv_handle_create(dce_call, LSA_HANDLE_ACCOUNT);
795 return NT_STATUS_NO_MEMORY;
798 ah->data = talloc_steal(ah, astate);
800 *r->out.acct_handle = ah->wire_handle;
809 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
810 struct lsa_EnumAccounts *r)
812 struct dcesrv_handle *h;
813 struct lsa_policy_state *state;
815 struct ldb_message **res;
816 const char * const attrs[] = { "objectSid", NULL};
819 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
823 /* NOTE: This call must only return accounts that have at least
826 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
827 "(&(objectSid=*)(privilege=*))");
829 return NT_STATUS_INTERNAL_DB_CORRUPTION;
832 if (*r->in.resume_handle >= ret) {
833 return NT_STATUS_NO_MORE_ENTRIES;
836 count = ret - *r->in.resume_handle;
837 if (count > r->in.num_entries) {
838 count = r->in.num_entries;
842 return NT_STATUS_NO_MORE_ENTRIES;
845 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
846 if (r->out.sids->sids == NULL) {
847 return NT_STATUS_NO_MEMORY;
850 for (i=0;i<count;i++) {
851 r->out.sids->sids[i].sid =
852 samdb_result_dom_sid(r->out.sids->sids,
853 res[i + *r->in.resume_handle],
855 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
858 r->out.sids->num_sids = count;
859 *r->out.resume_handle = count + *r->in.resume_handle;
864 /* This decrypts and returns Trusted Domain Auth Information Internal data */
865 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
866 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
867 struct trustDomainPasswords *auth_struct)
869 DATA_BLOB session_key = data_blob(NULL, 0);
870 enum ndr_err_code ndr_err;
872 gnutls_cipher_hd_t cipher_hnd = NULL;
873 gnutls_datum_t _session_key;
876 nt_status = dcesrv_transport_session_key(dce_call, &session_key);
877 if (!NT_STATUS_IS_OK(nt_status)) {
881 _session_key = (gnutls_datum_t) {
882 .data = session_key.data,
883 .size = session_key.length,
886 rc = gnutls_cipher_init(&cipher_hnd,
887 GNUTLS_CIPHER_ARCFOUR_128,
891 nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
895 rc = gnutls_cipher_encrypt(cipher_hnd,
898 gnutls_cipher_deinit(cipher_hnd);
900 nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
904 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
906 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
907 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
908 return NT_STATUS_INVALID_PARAMETER;
911 nt_status = NT_STATUS_OK;
916 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
918 struct trustAuthInOutBlob *iopw,
919 DATA_BLOB *trustauth_blob)
921 enum ndr_err_code ndr_err;
923 if (iopw->current.count != iopw->count) {
924 return NT_STATUS_INVALID_PARAMETER;
927 if (iopw->previous.count > iopw->current.count) {
928 return NT_STATUS_INVALID_PARAMETER;
931 if (iopw->previous.count == 0) {
933 * If the previous credentials are not present
934 * we need to make a copy.
936 iopw->previous = iopw->current;
939 if (iopw->previous.count < iopw->current.count) {
940 struct AuthenticationInformationArray *c = &iopw->current;
941 struct AuthenticationInformationArray *p = &iopw->previous;
944 * The previous array needs to have the same size
945 * as the current one.
947 * We may have to fill with TRUST_AUTH_TYPE_NONE
950 p->array = talloc_realloc(mem_ctx, p->array,
951 struct AuthenticationInformation,
953 if (p->array == NULL) {
954 return NT_STATUS_NO_MEMORY;
957 while (p->count < c->count) {
958 struct AuthenticationInformation *a =
959 &p->array[p->count++];
961 *a = (struct AuthenticationInformation) {
962 .LastUpdateTime = p->array[0].LastUpdateTime,
963 .AuthType = TRUST_AUTH_TYPE_NONE,
968 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
970 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
971 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
972 return NT_STATUS_INVALID_PARAMETER;
978 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
979 struct ldb_context *sam_ldb,
980 struct ldb_dn *base_dn,
981 const char *netbios_name,
982 struct trustAuthInOutBlob *in,
983 struct ldb_dn **user_dn)
985 struct ldb_request *req;
986 struct ldb_message *msg;
991 dn = ldb_dn_copy(mem_ctx, base_dn);
993 return NT_STATUS_NO_MEMORY;
995 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
996 return NT_STATUS_NO_MEMORY;
999 msg = ldb_msg_new(mem_ctx);
1001 return NT_STATUS_NO_MEMORY;
1005 ret = ldb_msg_add_string(msg, "objectClass", "user");
1006 if (ret != LDB_SUCCESS) {
1007 return NT_STATUS_NO_MEMORY;
1010 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
1011 if (ret != LDB_SUCCESS) {
1012 return NT_STATUS_NO_MEMORY;
1015 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
1016 UF_INTERDOMAIN_TRUST_ACCOUNT);
1017 if (ret != LDB_SUCCESS) {
1018 return NT_STATUS_NO_MEMORY;
1021 for (i = 0; i < in->count; i++) {
1022 const char *attribute;
1024 switch (in->current.array[i].AuthType) {
1025 case TRUST_AUTH_TYPE_NT4OWF:
1026 attribute = "unicodePwd";
1027 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1030 case TRUST_AUTH_TYPE_CLEAR:
1031 attribute = "clearTextPassword";
1032 v.data = in->current.array[i].AuthInfo.clear.password;
1033 v.length = in->current.array[i].AuthInfo.clear.size;
1039 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1040 if (ret != LDB_SUCCESS) {
1041 return NT_STATUS_NO_MEMORY;
1045 /* create the trusted_domain user account */
1046 ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
1047 ldb_op_default_callback, NULL);
1048 if (ret != LDB_SUCCESS) {
1049 return NT_STATUS_NO_MEMORY;
1052 ret = ldb_request_add_control(req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
1054 if (ret != LDB_SUCCESS) {
1055 return NT_STATUS_NO_MEMORY;
1058 ret = dsdb_autotransaction_request(sam_ldb, req);
1059 if (ret != LDB_SUCCESS) {
1060 DEBUG(0,("Failed to create user record %s: %s\n",
1061 ldb_dn_get_linearized(msg->dn),
1062 ldb_errstring(sam_ldb)));
1065 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1066 return NT_STATUS_DOMAIN_EXISTS;
1067 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1068 return NT_STATUS_ACCESS_DENIED;
1070 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1077 return NT_STATUS_OK;
1081 lsa_CreateTrustedDomainEx2
1083 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
1084 TALLOC_CTX *mem_ctx,
1085 struct lsa_CreateTrustedDomainEx2 *r,
1087 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
1089 struct dcesrv_handle *policy_handle;
1090 struct lsa_policy_state *policy_state;
1091 struct lsa_trusted_domain_state *trusted_domain_state;
1092 struct dcesrv_handle *handle;
1093 struct ldb_message **msgs, *msg;
1094 const char *attrs[] = {
1097 const char *netbios_name;
1098 const char *dns_name;
1099 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1100 struct trustDomainPasswords auth_struct;
1103 struct ldb_context *sam_ldb;
1104 struct server_id *server_ids = NULL;
1105 uint32_t num_server_ids = 0;
1108 char *dns_encoded = NULL;
1109 char *netbios_encoded = NULL;
1110 char *sid_encoded = NULL;
1111 struct imessaging_context *imsg_ctx =
1112 dcesrv_imessaging_context(dce_call->conn);
1114 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
1115 ZERO_STRUCTP(r->out.trustdom_handle);
1117 policy_state = policy_handle->data;
1118 sam_ldb = policy_state->sam_ldb;
1120 netbios_name = r->in.info->netbios_name.string;
1121 if (!netbios_name) {
1122 return NT_STATUS_INVALID_PARAMETER;
1125 dns_name = r->in.info->domain_name.string;
1126 if (dns_name == NULL) {
1127 return NT_STATUS_INVALID_PARAMETER;
1130 if (r->in.info->sid == NULL) {
1131 return NT_STATUS_INVALID_SID;
1135 * We expect S-1-5-21-A-B-C, but we don't
1136 * allow S-1-5-21-0-0-0 as this is used
1137 * for claims and compound identities.
1139 ok = dom_sid_is_valid_account_domain(r->in.info->sid);
1141 return NT_STATUS_INVALID_PARAMETER;
1144 dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1145 if (dns_encoded == NULL) {
1146 return NT_STATUS_NO_MEMORY;
1148 netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1149 if (netbios_encoded == NULL) {
1150 return NT_STATUS_NO_MEMORY;
1152 sid_encoded = ldap_encode_ndr_dom_sid(mem_ctx, r->in.info->sid);
1153 if (sid_encoded == NULL) {
1154 return NT_STATUS_NO_MEMORY;
1157 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1158 if (!trusted_domain_state) {
1159 return NT_STATUS_NO_MEMORY;
1161 trusted_domain_state->policy = policy_state;
1163 if (strcasecmp(netbios_name, "BUILTIN") == 0
1164 || (strcasecmp(dns_name, "BUILTIN") == 0)
1165 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
1166 return NT_STATUS_INVALID_PARAMETER;
1169 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
1170 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
1171 || strcasecmp(dns_name, policy_state->domain_dns) == 0
1172 || strcasecmp(dns_name, policy_state->domain_name) == 0
1173 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
1174 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
1177 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
1178 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
1179 /* No secrets are created at this time, for this function */
1180 auth_struct.outgoing.count = 0;
1181 auth_struct.incoming.count = 0;
1182 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
1183 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
1184 r->in.auth_info_internal->auth_blob.size);
1185 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1186 &auth_blob, &auth_struct);
1187 if (!NT_STATUS_IS_OK(nt_status)) {
1190 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
1192 if (unencrypted_auth_info->incoming_count > 1) {
1193 return NT_STATUS_INVALID_PARAMETER;
1196 /* more investigation required here, do not create secrets for
1198 auth_struct.outgoing.count = 0;
1199 auth_struct.incoming.count = 0;
1201 return NT_STATUS_INVALID_PARAMETER;
1204 if (auth_struct.incoming.count) {
1205 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1206 &auth_struct.incoming,
1207 &trustAuthIncoming);
1208 if (!NT_STATUS_IS_OK(nt_status)) {
1212 trustAuthIncoming = data_blob(NULL, 0);
1215 if (auth_struct.outgoing.count) {
1216 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1217 &auth_struct.outgoing,
1218 &trustAuthOutgoing);
1219 if (!NT_STATUS_IS_OK(nt_status)) {
1223 trustAuthOutgoing = data_blob(NULL, 0);
1226 ret = ldb_transaction_start(sam_ldb);
1227 if (ret != LDB_SUCCESS) {
1228 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1231 /* search for the trusted_domain record */
1232 ret = gendb_search(sam_ldb,
1233 mem_ctx, policy_state->system_dn, &msgs, attrs,
1234 "(&(objectClass=trustedDomain)(|"
1235 "(flatname=%s)(trustPartner=%s)"
1236 "(flatname=%s)(trustPartner=%s)"
1237 "(securityIdentifier=%s)))",
1238 dns_encoded, dns_encoded,
1239 netbios_encoded, netbios_encoded,
1242 ldb_transaction_cancel(sam_ldb);
1243 return NT_STATUS_OBJECT_NAME_COLLISION;
1246 ldb_transaction_cancel(sam_ldb);
1247 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1250 msg = ldb_msg_new(mem_ctx);
1252 return NT_STATUS_NO_MEMORY;
1255 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1256 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", dns_name)) {
1257 ldb_transaction_cancel(sam_ldb);
1258 return NT_STATUS_NO_MEMORY;
1261 ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1262 if (ret != LDB_SUCCESS) {
1263 ldb_transaction_cancel(sam_ldb);
1264 return NT_STATUS_NO_MEMORY;;
1267 ret = ldb_msg_add_string(msg, "flatname", netbios_name);
1268 if (ret != LDB_SUCCESS) {
1269 ldb_transaction_cancel(sam_ldb);
1270 return NT_STATUS_NO_MEMORY;
1273 ret = ldb_msg_add_string(msg, "trustPartner", dns_name);
1274 if (ret != LDB_SUCCESS) {
1275 ldb_transaction_cancel(sam_ldb);
1276 return NT_STATUS_NO_MEMORY;;
1279 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier",
1281 if (ret != LDB_SUCCESS) {
1282 ldb_transaction_cancel(sam_ldb);
1283 return NT_STATUS_NO_MEMORY;;
1286 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1287 if (ret != LDB_SUCCESS) {
1288 ldb_transaction_cancel(sam_ldb);
1289 return NT_STATUS_NO_MEMORY;;
1292 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1293 if (ret != LDB_SUCCESS) {
1294 ldb_transaction_cancel(sam_ldb);
1295 return NT_STATUS_NO_MEMORY;;
1298 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1299 if (ret != LDB_SUCCESS) {
1300 ldb_transaction_cancel(sam_ldb);
1301 return NT_STATUS_NO_MEMORY;;
1304 if (trustAuthIncoming.data) {
1305 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1306 if (ret != LDB_SUCCESS) {
1307 ldb_transaction_cancel(sam_ldb);
1308 return NT_STATUS_NO_MEMORY;
1311 if (trustAuthOutgoing.data) {
1312 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1313 if (ret != LDB_SUCCESS) {
1314 ldb_transaction_cancel(sam_ldb);
1315 return NT_STATUS_NO_MEMORY;
1319 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1321 /* create the trusted_domain */
1322 ret = ldb_add(sam_ldb, msg);
1326 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1327 ldb_transaction_cancel(sam_ldb);
1328 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1329 ldb_dn_get_linearized(msg->dn),
1330 ldb_errstring(sam_ldb)));
1331 return NT_STATUS_DOMAIN_EXISTS;
1332 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1333 ldb_transaction_cancel(sam_ldb);
1334 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1335 ldb_dn_get_linearized(msg->dn),
1336 ldb_errstring(sam_ldb)));
1337 return NT_STATUS_ACCESS_DENIED;
1339 ldb_transaction_cancel(sam_ldb);
1340 DEBUG(0,("Failed to create user record %s: %s\n",
1341 ldb_dn_get_linearized(msg->dn),
1342 ldb_errstring(sam_ldb)));
1343 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1346 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1347 struct ldb_dn *user_dn;
1348 /* Inbound trusts must also create a cn=users object to match */
1349 nt_status = add_trust_user(mem_ctx, sam_ldb,
1350 policy_state->domain_dn,
1352 &auth_struct.incoming,
1354 if (!NT_STATUS_IS_OK(nt_status)) {
1355 ldb_transaction_cancel(sam_ldb);
1359 /* save the trust user dn */
1360 trusted_domain_state->trusted_domain_user_dn
1361 = talloc_steal(trusted_domain_state, user_dn);
1364 ret = ldb_transaction_commit(sam_ldb);
1365 if (ret != LDB_SUCCESS) {
1366 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1370 * Notify winbindd that we have a new trust
1372 status = irpc_servers_byname(imsg_ctx,
1377 if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
1378 imessaging_send(imsg_ctx,
1380 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1383 TALLOC_FREE(server_ids);
1385 handle = dcesrv_handle_create(dce_call, LSA_HANDLE_TRUSTED_DOMAIN);
1387 return NT_STATUS_NO_MEMORY;
1390 handle->data = talloc_steal(handle, trusted_domain_state);
1392 trusted_domain_state->access_mask = r->in.access_mask;
1393 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1395 *r->out.trustdom_handle = handle->wire_handle;
1397 return NT_STATUS_OK;
1401 lsa_CreateTrustedDomainEx2
1403 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1404 TALLOC_CTX *mem_ctx,
1405 struct lsa_CreateTrustedDomainEx2 *r)
1407 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1410 lsa_CreateTrustedDomainEx
1412 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1413 TALLOC_CTX *mem_ctx,
1414 struct lsa_CreateTrustedDomainEx *r)
1416 struct lsa_CreateTrustedDomainEx2 r2;
1418 r2.in.policy_handle = r->in.policy_handle;
1419 r2.in.info = r->in.info;
1420 r2.out.trustdom_handle = r->out.trustdom_handle;
1421 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1425 lsa_CreateTrustedDomain
1427 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1428 struct lsa_CreateTrustedDomain *r)
1430 struct lsa_CreateTrustedDomainEx2 r2;
1432 r2.in.policy_handle = r->in.policy_handle;
1433 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1435 return NT_STATUS_NO_MEMORY;
1438 r2.in.info->domain_name = r->in.info->name;
1439 r2.in.info->netbios_name = r->in.info->name;
1440 r2.in.info->sid = r->in.info->sid;
1441 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1442 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1443 r2.in.info->trust_attributes = 0;
1445 r2.in.access_mask = r->in.access_mask;
1446 r2.out.trustdom_handle = r->out.trustdom_handle;
1448 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1451 static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
1452 struct dcesrv_call_state *dce_call,
1453 TALLOC_CTX *tmp_mem,
1454 struct lsa_policy_state *policy_state,
1456 uint32_t access_mask,
1457 struct dcesrv_handle **_handle)
1459 struct lsa_trusted_domain_state *trusted_domain_state;
1460 struct dcesrv_handle *handle;
1461 struct ldb_message **msgs;
1462 const char *attrs[] = {
1470 /* TODO: perform access checks */
1472 /* search for the trusted_domain record */
1473 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1474 policy_state->system_dn,
1475 &msgs, attrs, "%s", filter);
1477 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1481 DEBUG(0,("Found %d records matching %s under %s\n", ret,
1483 ldb_dn_get_linearized(policy_state->system_dn)));
1484 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1487 trusted_domain_state = talloc_zero(tmp_mem,
1488 struct lsa_trusted_domain_state);
1489 if (!trusted_domain_state) {
1490 return NT_STATUS_NO_MEMORY;
1492 trusted_domain_state->policy = policy_state;
1494 trusted_domain_state->trusted_domain_dn =
1495 talloc_steal(trusted_domain_state, msgs[0]->dn);
1497 direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1498 if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1499 const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1502 /* search for the trusted_domain account */
1503 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1504 policy_state->domain_dn,
1506 "(&(samaccountname=%s$)(objectclass=user)"
1507 "(userAccountControl:%s:=%u))",
1509 LDB_OID_COMPARATOR_AND,
1510 UF_INTERDOMAIN_TRUST_ACCOUNT);
1512 trusted_domain_state->trusted_domain_user_dn =
1513 talloc_steal(trusted_domain_state, msgs[0]->dn);
1517 handle = dcesrv_handle_create(dce_call, LSA_HANDLE_TRUSTED_DOMAIN);
1519 return NT_STATUS_NO_MEMORY;
1522 handle->data = talloc_steal(handle, trusted_domain_state);
1524 trusted_domain_state->access_mask = access_mask;
1525 trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1530 return NT_STATUS_OK;
1534 lsa_OpenTrustedDomain
1536 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1537 struct lsa_OpenTrustedDomain *r)
1539 struct dcesrv_handle *policy_handle;
1540 struct lsa_policy_state *policy_state;
1541 struct dcesrv_handle *handle;
1542 const char *sid_string;
1546 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1547 ZERO_STRUCTP(r->out.trustdom_handle);
1548 policy_state = policy_handle->data;
1550 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1552 return NT_STATUS_NO_MEMORY;
1555 filter = talloc_asprintf(mem_ctx,
1556 "(&(securityIdentifier=%s)"
1557 "(objectclass=trustedDomain))",
1559 if (filter == NULL) {
1560 return NT_STATUS_NO_MEMORY;
1563 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1568 if (!NT_STATUS_IS_OK(status)) {
1572 *r->out.trustdom_handle = handle->wire_handle;
1574 return NT_STATUS_OK;
1579 lsa_OpenTrustedDomainByName
1581 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1582 TALLOC_CTX *mem_ctx,
1583 struct lsa_OpenTrustedDomainByName *r)
1585 struct dcesrv_handle *policy_handle;
1586 struct lsa_policy_state *policy_state;
1587 struct dcesrv_handle *handle;
1592 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1593 ZERO_STRUCTP(r->out.trustdom_handle);
1594 policy_state = policy_handle->data;
1596 if (!r->in.name.string) {
1597 return NT_STATUS_INVALID_PARAMETER;
1600 /* search for the trusted_domain record */
1601 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1602 if (td_name == NULL) {
1603 return NT_STATUS_NO_MEMORY;
1606 filter = talloc_asprintf(mem_ctx,
1607 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1608 "(objectclass=trustedDomain))",
1609 td_name, td_name, td_name);
1610 if (filter == NULL) {
1611 return NT_STATUS_NO_MEMORY;
1614 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1619 if (!NT_STATUS_IS_OK(status)) {
1623 *r->out.trustdom_handle = handle->wire_handle;
1625 return NT_STATUS_OK;
1631 lsa_SetTrustedDomainInfo
1633 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1634 struct lsa_SetTrustedDomainInfo *r)
1636 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1641 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1642 * otherwise at least one must be provided */
1643 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1644 struct ldb_dn *basedn, const char *dns_domain,
1645 const char *netbios, struct dom_sid2 *sid,
1646 struct ldb_message ***msgs)
1648 const char *attrs[] = { "flatname", "trustPartner",
1649 "securityIdentifier", "trustDirection",
1650 "trustType", "trustAttributes",
1652 "msDs-supportedEncryptionTypes",
1653 "msDS-TrustForestTrustInfo",
1658 char *sidstr = NULL;
1663 if (dns_domain || netbios || sid) {
1664 filter = talloc_strdup(mem_ctx,
1665 "(&(objectclass=trustedDomain)(|");
1667 filter = talloc_strdup(mem_ctx,
1668 "(objectclass=trustedDomain)");
1671 return NT_STATUS_NO_MEMORY;
1675 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1677 return NT_STATUS_NO_MEMORY;
1679 filter = talloc_asprintf_append(filter,
1680 "(trustPartner=%s)", dns);
1682 return NT_STATUS_NO_MEMORY;
1686 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1688 return NT_STATUS_NO_MEMORY;
1690 filter = talloc_asprintf_append(filter,
1691 "(flatname=%s)", nbn);
1693 return NT_STATUS_NO_MEMORY;
1697 sidstr = dom_sid_string(mem_ctx, sid);
1699 return NT_STATUS_INVALID_PARAMETER;
1701 filter = talloc_asprintf_append(filter,
1702 "(securityIdentifier=%s)",
1705 return NT_STATUS_NO_MEMORY;
1708 if (dns_domain || netbios || sid) {
1709 filter = talloc_asprintf_append(filter, "))");
1711 return NT_STATUS_NO_MEMORY;
1715 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1717 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1721 return NT_STATUS_OBJECT_NAME_COLLISION;
1724 return NT_STATUS_OK;
1727 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1728 struct ldb_context *sam_ldb,
1729 struct ldb_message *orig,
1730 struct ldb_message *dest,
1731 const char *attribute,
1733 uint32_t *orig_value)
1735 const struct ldb_val *orig_val;
1736 uint32_t orig_uint = 0;
1737 unsigned int flags = 0;
1741 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1742 if (!orig_val || !orig_val->data) {
1743 /* add new attribute */
1744 flags = LDB_FLAG_MOD_ADD;
1747 orig_uint = smb_strtoul((const char *)orig_val->data,
1752 if (error != 0 || orig_uint != value) {
1753 /* replace also if can't get value */
1754 flags = LDB_FLAG_MOD_REPLACE;
1759 /* stored value is identical, nothing to change */
1763 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1764 if (ret != LDB_SUCCESS) {
1765 return NT_STATUS_NO_MEMORY;
1768 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1769 if (ret != LDB_SUCCESS) {
1770 return NT_STATUS_NO_MEMORY;
1775 *orig_value = orig_uint;
1777 return NT_STATUS_OK;
1780 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1781 struct ldb_context *sam_ldb,
1782 struct ldb_dn *base_dn,
1784 const char *netbios_name,
1785 struct trustAuthInOutBlob *in)
1787 const char *attrs[] = { "userAccountControl", NULL };
1788 struct ldb_message **msgs;
1789 struct ldb_message *msg;
1794 ret = gendb_search(sam_ldb, mem_ctx,
1795 base_dn, &msgs, attrs,
1796 "samAccountName=%s$", netbios_name);
1798 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1803 return NT_STATUS_OK;
1806 /* ok no existing user, add it from scratch */
1807 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1808 netbios_name, in, NULL);
1811 /* check user is what we are looking for */
1812 uac = ldb_msg_find_attr_as_uint(msgs[0],
1813 "userAccountControl", 0);
1814 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1815 return NT_STATUS_OBJECT_NAME_COLLISION;
1819 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1822 return NT_STATUS_OK;
1823 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1824 return NT_STATUS_ACCESS_DENIED;
1826 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1830 /* entry exists, just modify secret if any */
1831 if (in == NULL || in->count == 0) {
1832 return NT_STATUS_OK;
1835 msg = ldb_msg_new(mem_ctx);
1837 return NT_STATUS_NO_MEMORY;
1839 msg->dn = msgs[0]->dn;
1841 for (i = 0; i < in->count; i++) {
1842 const char *attribute;
1844 switch (in->current.array[i].AuthType) {
1845 case TRUST_AUTH_TYPE_NT4OWF:
1846 attribute = "unicodePwd";
1847 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1850 case TRUST_AUTH_TYPE_CLEAR:
1851 attribute = "clearTextPassword";
1852 v.data = in->current.array[i].AuthInfo.clear.password;
1853 v.length = in->current.array[i].AuthInfo.clear.size;
1859 ret = ldb_msg_add_empty(msg, attribute,
1860 LDB_FLAG_MOD_REPLACE, NULL);
1861 if (ret != LDB_SUCCESS) {
1862 return NT_STATUS_NO_MEMORY;
1865 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1866 if (ret != LDB_SUCCESS) {
1867 return NT_STATUS_NO_MEMORY;
1871 /* create the trusted_domain user account */
1872 ret = ldb_modify(sam_ldb, msg);
1873 if (ret != LDB_SUCCESS) {
1874 DEBUG(0,("Failed to create user record %s: %s\n",
1875 ldb_dn_get_linearized(msg->dn),
1876 ldb_errstring(sam_ldb)));
1879 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1880 return NT_STATUS_DOMAIN_EXISTS;
1881 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1882 return NT_STATUS_ACCESS_DENIED;
1884 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1888 return NT_STATUS_OK;
1892 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1893 struct lsa_policy_state *p_state,
1894 TALLOC_CTX *mem_ctx,
1895 struct ldb_message *dom_msg,
1896 enum lsa_TrustDomInfoEnum level,
1897 union lsa_TrustedDomainInfo *info)
1899 uint32_t *posix_offset = NULL;
1900 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1901 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1902 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1903 uint32_t *enc_types = NULL;
1904 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1905 struct trustDomainPasswords auth_struct;
1906 struct trustAuthInOutBlob *current_passwords = NULL;
1908 struct ldb_message **msgs;
1909 struct ldb_message *msg;
1910 bool add_outgoing = false;
1911 bool add_incoming = false;
1912 bool del_outgoing = false;
1913 bool del_incoming = false;
1914 bool del_forest_info = false;
1915 bool in_transaction = false;
1920 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1921 posix_offset = &info->posix_offset.posix_offset;
1923 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1924 info_ex = &info->info_ex;
1926 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1927 auth_info = &info->auth_info;
1929 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1930 posix_offset = &info->full_info.posix_offset.posix_offset;
1931 info_ex = &info->full_info.info_ex;
1932 auth_info = &info->full_info.auth_info;
1934 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1935 auth_info_int = &info->auth_info_internal;
1937 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1938 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1939 info_ex = &info->full_info_internal.info_ex;
1940 auth_info_int = &info->full_info_internal.auth_info;
1942 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1943 enc_types = &info->enc_types.enc_types;
1946 return NT_STATUS_INVALID_PARAMETER;
1950 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1952 &trustAuthOutgoing);
1953 if (!NT_STATUS_IS_OK(nt_status)) {
1956 if (trustAuthIncoming.data) {
1957 /* This does the decode of some of this twice, but it is easier that way */
1958 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1959 auth_info->incoming_count,
1960 auth_info->incoming_current_auth_info,
1962 ¤t_passwords);
1963 if (!NT_STATUS_IS_OK(nt_status)) {
1969 /* decode auth_info_int if set */
1970 if (auth_info_int) {
1972 /* now decrypt blob */
1973 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1974 auth_info_int->auth_blob.size);
1976 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1977 &auth_blob, &auth_struct);
1978 if (!NT_STATUS_IS_OK(nt_status)) {
1984 /* verify data matches */
1985 if (info_ex->trust_attributes &
1986 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1987 /* TODO: check what behavior level we have */
1988 if (strcasecmp_m(p_state->domain_dns,
1989 p_state->forest_dns) != 0) {
1990 return NT_STATUS_INVALID_DOMAIN_STATE;
1994 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1995 if (ret == LDB_SUCCESS && am_rodc) {
1996 return NT_STATUS_NO_SUCH_DOMAIN;
1999 /* verify only one object matches the dns/netbios/sid
2000 * triplet and that this is the one we already have */
2001 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
2003 info_ex->domain_name.string,
2004 info_ex->netbios_name.string,
2005 info_ex->sid, &msgs);
2006 if (!NT_STATUS_IS_OK(nt_status)) {
2009 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
2010 return NT_STATUS_OBJECT_NAME_COLLISION;
2015 /* TODO: should we fetch previous values from the existing entry
2016 * and append them ? */
2017 if (auth_info_int && auth_struct.incoming.count) {
2018 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
2019 &auth_struct.incoming,
2020 &trustAuthIncoming);
2021 if (!NT_STATUS_IS_OK(nt_status)) {
2025 current_passwords = &auth_struct.incoming;
2028 trustAuthIncoming = data_blob(NULL, 0);
2031 if (auth_info_int && auth_struct.outgoing.count) {
2032 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
2033 &auth_struct.outgoing,
2034 &trustAuthOutgoing);
2035 if (!NT_STATUS_IS_OK(nt_status)) {
2039 trustAuthOutgoing = data_blob(NULL, 0);
2042 msg = ldb_msg_new(mem_ctx);
2044 return NT_STATUS_NO_MEMORY;
2046 msg->dn = dom_msg->dn;
2049 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2052 *posix_offset, NULL);
2053 if (!NT_STATUS_IS_OK(nt_status)) {
2060 uint32_t changed_attrs;
2064 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2067 info_ex->trust_direction,
2069 if (!NT_STATUS_IS_OK(nt_status)) {
2073 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2074 if (auth_info != NULL && trustAuthIncoming.length > 0) {
2075 add_incoming = true;
2078 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2079 if (auth_info != NULL && trustAuthOutgoing.length > 0) {
2080 add_outgoing = true;
2084 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
2085 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
2086 del_incoming = true;
2088 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
2089 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2090 del_outgoing = true;
2093 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
2094 if (origtype == -1 || origtype != info_ex->trust_type) {
2095 DEBUG(1, ("Attempted to change trust type! "
2096 "Operation not handled\n"));
2097 return NT_STATUS_INVALID_PARAMETER;
2100 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2103 info_ex->trust_attributes,
2105 if (!NT_STATUS_IS_OK(nt_status)) {
2108 /* TODO: check forestFunctionality from ldb opaque */
2109 /* TODO: check what is set makes sense */
2111 changed_attrs = origattrs ^ info_ex->trust_attributes;
2112 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2114 * For now we only allow
2115 * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
2117 * TODO: we may need to support more attribute changes
2119 DEBUG(1, ("Attempted to change trust attributes "
2120 "(0x%08x != 0x%08x)! "
2121 "Operation not handled yet...\n",
2122 (unsigned)origattrs,
2123 (unsigned)info_ex->trust_attributes));
2124 return NT_STATUS_INVALID_PARAMETER;
2127 if (!(info_ex->trust_attributes &
2128 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
2130 struct ldb_message_element *orig_forest_el = NULL;
2132 orig_forest_el = ldb_msg_find_element(dom_msg,
2133 "msDS-TrustForestTrustInfo");
2134 if (orig_forest_el != NULL) {
2135 del_forest_info = true;
2141 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2143 "msDS-SupportedEncryptionTypes",
2145 if (!NT_STATUS_IS_OK(nt_status)) {
2150 if (add_incoming || del_incoming) {
2151 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
2152 LDB_FLAG_MOD_REPLACE, NULL);
2153 if (ret != LDB_SUCCESS) {
2154 return NT_STATUS_NO_MEMORY;
2157 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
2158 &trustAuthIncoming, NULL);
2159 if (ret != LDB_SUCCESS) {
2160 return NT_STATUS_NO_MEMORY;
2164 if (add_outgoing || del_outgoing) {
2165 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2166 LDB_FLAG_MOD_REPLACE, NULL);
2167 if (ret != LDB_SUCCESS) {
2168 return NT_STATUS_NO_MEMORY;
2171 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
2172 &trustAuthOutgoing, NULL);
2173 if (ret != LDB_SUCCESS) {
2174 return NT_STATUS_NO_MEMORY;
2178 if (del_forest_info) {
2179 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
2180 LDB_FLAG_MOD_REPLACE, NULL);
2181 if (ret != LDB_SUCCESS) {
2182 return NT_STATUS_NO_MEMORY;
2186 /* start transaction */
2187 ret = ldb_transaction_start(p_state->sam_ldb);
2188 if (ret != LDB_SUCCESS) {
2189 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2191 in_transaction = true;
2193 if (msg->num_elements) {
2194 ret = ldb_modify(p_state->sam_ldb, msg);
2195 if (ret != LDB_SUCCESS) {
2196 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
2197 ldb_dn_get_linearized(msg->dn),
2198 ldb_errstring(p_state->sam_ldb)));
2199 nt_status = dsdb_ldb_err_to_ntstatus(ret);
2204 if (add_incoming || del_incoming) {
2205 const char *netbios_name;
2207 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
2209 if (!netbios_name) {
2210 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
2214 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
2215 nt_status = update_trust_user(mem_ctx,
2221 if (!NT_STATUS_IS_OK(nt_status)) {
2226 /* ok, all fine, commit transaction and return */
2227 ret = ldb_transaction_commit(p_state->sam_ldb);
2228 if (ret != LDB_SUCCESS) {
2229 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2231 in_transaction = false;
2233 nt_status = NT_STATUS_OK;
2236 if (in_transaction) {
2237 ldb_transaction_cancel(p_state->sam_ldb);
2243 lsa_SetInfomrationTrustedDomain
2245 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
2246 struct dcesrv_call_state *dce_call,
2247 TALLOC_CTX *mem_ctx,
2248 struct lsa_SetInformationTrustedDomain *r)
2250 struct dcesrv_handle *h;
2251 struct lsa_trusted_domain_state *td_state;
2252 struct ldb_message **msgs;
2255 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
2256 LSA_HANDLE_TRUSTED_DOMAIN);
2258 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2260 /* get the trusted domain object */
2261 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
2262 td_state->trusted_domain_dn,
2263 NULL, NULL, NULL, &msgs);
2264 if (!NT_STATUS_IS_OK(nt_status)) {
2265 if (NT_STATUS_EQUAL(nt_status,
2266 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2269 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2272 return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
2273 msgs[0], r->in.level, r->in.info);
2278 lsa_DeleteTrustedDomain
2280 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2281 struct lsa_DeleteTrustedDomain *r)
2284 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2285 struct lsa_DeleteObject del;
2286 struct dcesrv_handle *h;
2288 opn.in.handle = r->in.handle;
2289 opn.in.sid = r->in.dom_sid;
2290 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2291 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2292 if (!opn.out.trustdom_handle) {
2293 return NT_STATUS_NO_MEMORY;
2295 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2296 if (!NT_STATUS_IS_OK(status)) {
2300 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2301 talloc_steal(mem_ctx, h);
2303 del.in.handle = opn.out.trustdom_handle;
2304 del.out.handle = opn.out.trustdom_handle;
2305 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2306 if (!NT_STATUS_IS_OK(status)) {
2309 return NT_STATUS_OK;
2312 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2313 struct ldb_message *msg,
2314 struct lsa_TrustDomainInfoInfoEx *info_ex)
2316 info_ex->domain_name.string
2317 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2318 info_ex->netbios_name.string
2319 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2321 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2322 info_ex->trust_direction
2323 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2325 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2326 info_ex->trust_attributes
2327 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2328 return NT_STATUS_OK;
2332 lsa_QueryTrustedDomainInfo
2334 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2335 struct lsa_QueryTrustedDomainInfo *r)
2337 union lsa_TrustedDomainInfo *info = NULL;
2338 struct dcesrv_handle *h;
2339 struct lsa_trusted_domain_state *trusted_domain_state;
2340 struct ldb_message *msg;
2342 struct ldb_message **res;
2343 const char *attrs[] = {
2346 "securityIdentifier",
2350 "msDs-supportedEncryptionTypes",
2354 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2356 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2358 /* pull all the user attributes */
2359 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2360 trusted_domain_state->trusted_domain_dn, &res, attrs);
2362 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2366 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2368 return NT_STATUS_NO_MEMORY;
2370 *r->out.info = info;
2372 switch (r->in.level) {
2373 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2374 info->name.netbios_name.string
2375 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2377 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2378 info->posix_offset.posix_offset
2379 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2381 #if 0 /* Win2k3 doesn't implement this */
2382 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2383 r->out.info->info_basic.netbios_name.string
2384 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2385 r->out.info->info_basic.sid
2386 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2389 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2390 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2392 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2393 ZERO_STRUCT(info->full_info);
2394 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2395 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2396 ZERO_STRUCT(info->full_info2_internal);
2397 info->full_info2_internal.posix_offset.posix_offset
2398 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2399 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2401 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2402 info->enc_types.enc_types
2403 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2406 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2407 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2408 /* oops, we don't want to return the info after all */
2410 *r->out.info = NULL;
2411 return NT_STATUS_INVALID_PARAMETER;
2413 /* oops, we don't want to return the info after all */
2415 *r->out.info = NULL;
2416 return NT_STATUS_INVALID_INFO_CLASS;
2419 return NT_STATUS_OK;
2424 lsa_QueryTrustedDomainInfoBySid
2426 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2427 struct lsa_QueryTrustedDomainInfoBySid *r)
2430 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2431 struct lsa_QueryTrustedDomainInfo query;
2432 struct dcesrv_handle *h;
2434 opn.in.handle = r->in.handle;
2435 opn.in.sid = r->in.dom_sid;
2436 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2437 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2438 if (!opn.out.trustdom_handle) {
2439 return NT_STATUS_NO_MEMORY;
2441 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2442 if (!NT_STATUS_IS_OK(status)) {
2446 /* Ensure this handle goes away at the end of this call */
2447 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2448 talloc_steal(mem_ctx, h);
2450 query.in.trustdom_handle = opn.out.trustdom_handle;
2451 query.in.level = r->in.level;
2452 query.out.info = r->out.info;
2453 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2454 if (!NT_STATUS_IS_OK(status)) {
2458 return NT_STATUS_OK;
2462 lsa_SetTrustedDomainInfoByName
2464 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2465 TALLOC_CTX *mem_ctx,
2466 struct lsa_SetTrustedDomainInfoByName *r)
2468 struct dcesrv_handle *policy_handle;
2469 struct lsa_policy_state *policy_state;
2470 struct ldb_message **msgs;
2473 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2474 policy_state = policy_handle->data;
2476 /* get the trusted domain object */
2477 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2478 policy_state->domain_dn,
2479 r->in.trusted_domain->string,
2480 r->in.trusted_domain->string,
2482 if (!NT_STATUS_IS_OK(nt_status)) {
2483 if (NT_STATUS_EQUAL(nt_status,
2484 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2487 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2490 return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2491 msgs[0], r->in.level, r->in.info);
2495 lsa_QueryTrustedDomainInfoByName
2497 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2498 TALLOC_CTX *mem_ctx,
2499 struct lsa_QueryTrustedDomainInfoByName *r)
2502 struct lsa_OpenTrustedDomainByName opn = {{0},{0}};
2503 struct lsa_QueryTrustedDomainInfo query;
2504 struct dcesrv_handle *h;
2506 opn.in.handle = r->in.handle;
2507 opn.in.name = *r->in.trusted_domain;
2508 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2509 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2510 if (!opn.out.trustdom_handle) {
2511 return NT_STATUS_NO_MEMORY;
2513 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2514 if (!NT_STATUS_IS_OK(status)) {
2518 /* Ensure this handle goes away at the end of this call */
2519 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2520 talloc_steal(mem_ctx, h);
2522 query.in.trustdom_handle = opn.out.trustdom_handle;
2523 query.in.level = r->in.level;
2524 query.out.info = r->out.info;
2525 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2526 if (!NT_STATUS_IS_OK(status)) {
2530 return NT_STATUS_OK;
2534 lsa_CloseTrustedDomainEx
2536 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2537 TALLOC_CTX *mem_ctx,
2538 struct lsa_CloseTrustedDomainEx *r)
2540 /* The result of a bad hair day from an IDL programmer? Not
2541 * implmented in Win2k3. You should always just lsa_Close
2543 return NT_STATUS_NOT_IMPLEMENTED;
2548 comparison function for sorting lsa_DomainInformation array
2550 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2552 return strcasecmp_m(e1->name.string, e2->name.string);
2558 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2559 struct lsa_EnumTrustDom *r)
2561 struct dcesrv_handle *policy_handle;
2562 struct lsa_DomainInfo *entries;
2563 struct lsa_policy_state *policy_state;
2564 struct ldb_message **domains;
2565 const char *attrs[] = {
2567 "securityIdentifier",
2574 *r->out.resume_handle = 0;
2576 r->out.domains->domains = NULL;
2577 r->out.domains->count = 0;
2579 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2581 policy_state = policy_handle->data;
2583 /* search for all users in this domain. This could possibly be cached and
2584 resumed based on resume_key */
2585 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2586 "objectclass=trustedDomain");
2588 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2591 /* convert to lsa_TrustInformation format */
2592 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2594 return NT_STATUS_NO_MEMORY;
2596 for (i=0;i<count;i++) {
2597 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2598 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2601 /* sort the results by name */
2602 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2604 if (*r->in.resume_handle >= count) {
2605 *r->out.resume_handle = -1;
2607 return NT_STATUS_NO_MORE_ENTRIES;
2610 /* return the rest, limit by max_size. Note that we
2611 use the w2k3 element size value of 60 */
2612 r->out.domains->count = count - *r->in.resume_handle;
2613 r->out.domains->count = MIN(r->out.domains->count,
2614 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2616 r->out.domains->domains = entries + *r->in.resume_handle;
2618 if (r->out.domains->count < count - *r->in.resume_handle) {
2619 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2620 return STATUS_MORE_ENTRIES;
2623 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2624 * always be larger than the previous input resume handle, in
2625 * particular when hitting the last query it is vital to set the
2626 * resume handle correctly to avoid infinite client loops, as
2627 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2628 * status is NT_STATUS_OK - gd */
2630 *r->out.resume_handle = (uint32_t)-1;
2632 return NT_STATUS_OK;
2636 comparison function for sorting lsa_DomainInformation array
2638 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2640 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2644 lsa_EnumTrustedDomainsEx
2646 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2647 struct lsa_EnumTrustedDomainsEx *r)
2649 struct dcesrv_handle *policy_handle;
2650 struct lsa_TrustDomainInfoInfoEx *entries;
2651 struct lsa_policy_state *policy_state;
2652 struct ldb_message **domains;
2653 const char *attrs[] = {
2656 "securityIdentifier",
2666 *r->out.resume_handle = 0;
2668 r->out.domains->domains = NULL;
2669 r->out.domains->count = 0;
2671 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2673 policy_state = policy_handle->data;
2675 /* search for all users in this domain. This could possibly be cached and
2676 resumed based on resume_key */
2677 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2678 "objectclass=trustedDomain");
2680 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2683 /* convert to lsa_DomainInformation format */
2684 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2686 return NT_STATUS_NO_MEMORY;
2688 for (i=0;i<count;i++) {
2689 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2690 if (!NT_STATUS_IS_OK(nt_status)) {
2695 /* sort the results by name */
2696 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2698 if (*r->in.resume_handle >= count) {
2699 *r->out.resume_handle = -1;
2701 return NT_STATUS_NO_MORE_ENTRIES;
2704 /* return the rest, limit by max_size. Note that we
2705 use the w2k3 element size value of 60 */
2706 r->out.domains->count = count - *r->in.resume_handle;
2707 r->out.domains->count = MIN(r->out.domains->count,
2708 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2710 r->out.domains->domains = entries + *r->in.resume_handle;
2712 if (r->out.domains->count < count - *r->in.resume_handle) {
2713 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2714 return STATUS_MORE_ENTRIES;
2717 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2719 return NT_STATUS_OK;
2726 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2727 struct lsa_OpenAccount *r)
2729 struct dcesrv_handle *h, *ah;
2730 struct lsa_policy_state *state;
2731 struct lsa_account_state *astate;
2733 ZERO_STRUCTP(r->out.acct_handle);
2735 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2739 astate = talloc(dce_call->conn, struct lsa_account_state);
2740 if (astate == NULL) {
2741 return NT_STATUS_NO_MEMORY;
2744 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2745 if (astate->account_sid == NULL) {
2746 talloc_free(astate);
2747 return NT_STATUS_NO_MEMORY;
2750 astate->policy = talloc_reference(astate, state);
2751 astate->access_mask = r->in.access_mask;
2754 * For now we grant all requested access.
2756 * We will fail at the ldb layer later.
2758 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2759 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2760 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2762 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2764 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2765 __func__, dom_sid_string(mem_ctx, astate->account_sid),
2766 (unsigned)r->in.access_mask,
2767 (unsigned)astate->access_mask));
2769 ah = dcesrv_handle_create(dce_call, LSA_HANDLE_ACCOUNT);
2771 talloc_free(astate);
2772 return NT_STATUS_NO_MEMORY;
2775 ah->data = talloc_steal(ah, astate);
2777 *r->out.acct_handle = ah->wire_handle;
2779 return NT_STATUS_OK;
2784 lsa_EnumPrivsAccount
2786 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2787 TALLOC_CTX *mem_ctx,
2788 struct lsa_EnumPrivsAccount *r)
2790 struct dcesrv_handle *h;
2791 struct lsa_account_state *astate;
2794 struct ldb_message **res;
2795 const char * const attrs[] = { "privilege", NULL};
2796 struct ldb_message_element *el;
2798 struct lsa_PrivilegeSet *privs;
2800 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2804 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2805 if (privs == NULL) {
2806 return NT_STATUS_NO_MEMORY;
2812 *r->out.privs = privs;
2814 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2815 if (sidstr == NULL) {
2816 return NT_STATUS_NO_MEMORY;
2819 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2820 "objectSid=%s", sidstr);
2822 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2825 return NT_STATUS_OK;
2828 el = ldb_msg_find_element(res[0], "privilege");
2829 if (el == NULL || el->num_values == 0) {
2830 return NT_STATUS_OK;
2833 privs->set = talloc_array(privs,
2834 struct lsa_LUIDAttribute, el->num_values);
2835 if (privs->set == NULL) {
2836 return NT_STATUS_NO_MEMORY;
2840 for (i=0;i<el->num_values;i++) {
2841 int id = sec_privilege_id((const char *)el->values[i].data);
2842 if (id == SEC_PRIV_INVALID) {
2843 /* Perhaps an account right, not a privilege */
2846 privs->set[j].attribute = 0;
2847 privs->set[j].luid.low = id;
2848 privs->set[j].luid.high = 0;
2854 return NT_STATUS_OK;
2858 lsa_EnumAccountRights
2860 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2861 TALLOC_CTX *mem_ctx,
2862 struct lsa_EnumAccountRights *r)
2864 struct dcesrv_handle *h;
2865 struct lsa_policy_state *state;
2868 struct ldb_message **res;
2869 const char * const attrs[] = { "privilege", NULL};
2871 struct ldb_message_element *el;
2873 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2877 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2878 if (sidstr == NULL) {
2879 return NT_STATUS_NO_MEMORY;
2882 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2883 "(&(objectSid=%s)(privilege=*))", sidstr);
2885 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2888 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2889 dom_sid_string(mem_ctx, r->in.sid),
2890 ldb_errstring(state->pdb)));
2891 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2894 el = ldb_msg_find_element(res[0], "privilege");
2895 if (el == NULL || el->num_values == 0) {
2896 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2899 r->out.rights->count = el->num_values;
2900 r->out.rights->names = talloc_array(r->out.rights,
2901 struct lsa_StringLarge, r->out.rights->count);
2902 if (r->out.rights->names == NULL) {
2903 return NT_STATUS_NO_MEMORY;
2906 for (i=0;i<el->num_values;i++) {
2907 r->out.rights->names[i].string = (const char *)el->values[i].data;
2910 return NT_STATUS_OK;
2916 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2918 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2919 TALLOC_CTX *mem_ctx,
2920 struct lsa_policy_state *state,
2922 struct dom_sid *sid,
2923 const struct lsa_RightSet *rights)
2925 struct auth_session_info *session_info =
2926 dcesrv_call_session_info(dce_call);
2927 const char *sidstr, *sidndrstr;
2928 struct ldb_message *msg;
2929 struct ldb_message_element *el;
2932 struct lsa_EnumAccountRights r2;
2935 if (security_session_user_level(session_info, NULL) <
2936 SECURITY_ADMINISTRATOR) {
2937 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2938 return NT_STATUS_ACCESS_DENIED;
2941 msg = ldb_msg_new(mem_ctx);
2943 return NT_STATUS_NO_MEMORY;
2946 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2947 if (sidndrstr == NULL) {
2949 return NT_STATUS_NO_MEMORY;
2952 sidstr = dom_sid_string(msg, sid);
2953 if (sidstr == NULL) {
2955 return NT_STATUS_NO_MEMORY;
2958 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2959 if (dnstr == NULL) {
2961 return NT_STATUS_NO_MEMORY;
2964 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2965 if (msg->dn == NULL) {
2967 return NT_STATUS_NO_MEMORY;
2970 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2973 r2.in.handle = &state->handle->wire_handle;
2975 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2977 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2978 if (!NT_STATUS_IS_OK(status)) {
2979 ZERO_STRUCTP(r2.out.rights);
2983 for (i=0;i<rights->count;i++) {
2986 ok = dcesrc_lsa_valid_AccountRight(rights->names[i].string);
2989 return NT_STATUS_NO_SUCH_PRIVILEGE;
2992 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2994 for (j=0;j<r2.out.rights->count;j++) {
2995 if (strcasecmp_m(r2.out.rights->names[j].string,
2996 rights->names[i].string) == 0) {
3000 if (j != r2.out.rights->count) continue;
3003 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
3004 if (ret != LDB_SUCCESS) {
3006 return NT_STATUS_NO_MEMORY;
3010 el = ldb_msg_find_element(msg, "privilege");
3013 return NT_STATUS_OK;
3016 el->flags = ldb_flag;
3018 ret = ldb_modify(state->pdb, msg);
3019 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
3020 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
3022 return NT_STATUS_NO_MEMORY;
3024 ldb_msg_add_string(msg, "comment", "added via LSA");
3025 ret = ldb_add(state->pdb, msg);
3027 if (ret != LDB_SUCCESS) {
3028 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
3030 return NT_STATUS_OK;
3032 DEBUG(3, ("Could not %s attributes from %s: %s",
3033 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
3034 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
3036 return NT_STATUS_UNEXPECTED_IO_ERROR;
3040 return NT_STATUS_OK;
3044 lsa_AddPrivilegesToAccount
3046 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3047 struct lsa_AddPrivilegesToAccount *r)
3049 struct lsa_RightSet rights;
3050 struct dcesrv_handle *h;
3051 struct lsa_account_state *astate;
3054 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3058 rights.count = r->in.privs->count;
3059 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
3060 if (rights.names == NULL) {
3061 return NT_STATUS_NO_MEMORY;
3063 for (i=0;i<rights.count;i++) {
3064 int id = r->in.privs->set[i].luid.low;
3065 if (r->in.privs->set[i].luid.high) {
3066 return NT_STATUS_NO_SUCH_PRIVILEGE;
3068 rights.names[i].string = sec_privilege_name(id);
3069 if (rights.names[i].string == NULL) {
3070 return NT_STATUS_NO_SUCH_PRIVILEGE;
3074 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3075 LDB_FLAG_MOD_ADD, astate->account_sid,
3081 lsa_RemovePrivilegesFromAccount
3083 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3084 struct lsa_RemovePrivilegesFromAccount *r)
3086 struct lsa_RightSet *rights;
3087 struct dcesrv_handle *h;
3088 struct lsa_account_state *astate;
3091 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3095 rights = talloc(mem_ctx, struct lsa_RightSet);
3097 if (r->in.remove_all == 1 &&
3098 r->in.privs == NULL) {
3099 struct lsa_EnumAccountRights r2;
3102 r2.in.handle = &astate->policy->handle->wire_handle;
3103 r2.in.sid = astate->account_sid;
3104 r2.out.rights = rights;
3106 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
3107 if (!NT_STATUS_IS_OK(status)) {
3111 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3112 LDB_FLAG_MOD_DELETE, astate->account_sid,
3116 if (r->in.remove_all != 0) {
3117 return NT_STATUS_INVALID_PARAMETER;
3120 rights->count = r->in.privs->count;
3121 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
3122 if (rights->names == NULL) {
3123 return NT_STATUS_NO_MEMORY;
3125 for (i=0;i<rights->count;i++) {
3126 int id = r->in.privs->set[i].luid.low;
3127 if (r->in.privs->set[i].luid.high) {
3128 return NT_STATUS_NO_SUCH_PRIVILEGE;
3130 rights->names[i].string = sec_privilege_name(id);
3131 if (rights->names[i].string == NULL) {
3132 return NT_STATUS_NO_SUCH_PRIVILEGE;
3136 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3137 LDB_FLAG_MOD_DELETE, astate->account_sid,
3143 lsa_GetQuotasForAccount
3145 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3146 struct lsa_GetQuotasForAccount *r)
3148 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3153 lsa_SetQuotasForAccount
3155 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3156 struct lsa_SetQuotasForAccount *r)
3158 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3163 lsa_GetSystemAccessAccount
3165 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3166 struct lsa_GetSystemAccessAccount *r)
3168 struct dcesrv_handle *h;
3169 struct lsa_account_state *astate;
3172 struct ldb_message **res;
3173 const char * const attrs[] = { "privilege", NULL};
3174 struct ldb_message_element *el;
3177 *(r->out.access_mask) = 0x00000000;
3179 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3183 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
3184 if (sidstr == NULL) {
3185 return NT_STATUS_NO_MEMORY;
3188 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
3189 "objectSid=%s", sidstr);
3191 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3194 return NT_STATUS_OK;
3197 el = ldb_msg_find_element(res[0], "privilege");
3198 if (el == NULL || el->num_values == 0) {
3199 return NT_STATUS_OK;
3202 for (i=0;i<el->num_values;i++) {
3203 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
3204 if (right_bit == 0) {
3205 /* Perhaps an privilege, not a right */
3208 *(r->out.access_mask) |= right_bit;
3211 return NT_STATUS_OK;
3216 lsa_SetSystemAccessAccount
3218 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3219 struct lsa_SetSystemAccessAccount *r)
3221 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3226 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3227 struct lsa_CreateSecret *r)
3229 struct auth_session_info *session_info =
3230 dcesrv_call_session_info(dce_call);
3231 struct dcesrv_handle *policy_handle;
3232 struct lsa_policy_state *policy_state;
3233 struct lsa_secret_state *secret_state;
3234 struct dcesrv_handle *handle;
3235 struct ldb_message **msgs, *msg;
3236 const char *attrs[] = {
3244 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3245 ZERO_STRUCTP(r->out.sec_handle);
3247 switch (security_session_user_level(session_info, NULL))
3249 case SECURITY_SYSTEM:
3250 case SECURITY_ADMINISTRATOR:
3253 /* Users and annonymous are not allowed create secrets */
3254 return NT_STATUS_ACCESS_DENIED;
3257 policy_state = policy_handle->data;
3259 if (!r->in.name.string) {
3260 return NT_STATUS_INVALID_PARAMETER;
3263 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3264 NT_STATUS_HAVE_NO_MEMORY(secret_state);
3265 secret_state->policy = policy_state;
3267 msg = ldb_msg_new(mem_ctx);
3269 return NT_STATUS_NO_MEMORY;
3272 if (strncmp("G$", r->in.name.string, 2) == 0) {
3275 secret_state->global = true;
3277 name = &r->in.name.string[2];
3278 if (strlen(name) == 0) {
3279 return NT_STATUS_INVALID_PARAMETER;
3282 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3283 ldb_binary_encode_string(mem_ctx, name));
3284 NT_STATUS_HAVE_NO_MEMORY(name2);
3287 * We need to connect to the database as system, as this is
3288 * one of the rare RPC calls that must read the secrets
3289 * (and this is denied otherwise)
3291 * We also save the current remote session details so they can
3292 * used by the audit logging module. This allows the audit
3293 * logging to report the remote users details, rather than the
3294 * system users details.
3296 secret_state->sam_ldb =
3297 dcesrv_samdb_connect_as_system(secret_state, dce_call);
3298 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3300 /* search for the secret record */
3301 ret = gendb_search(secret_state->sam_ldb,
3302 mem_ctx, policy_state->system_dn, &msgs, attrs,
3303 "(&(cn=%s)(objectclass=secret))",
3306 return NT_STATUS_OBJECT_NAME_COLLISION;
3310 DEBUG(0,("Failure searching for CN=%s: %s\n",
3311 name2, ldb_errstring(secret_state->sam_ldb)));
3312 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3315 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3316 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3317 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3318 return NT_STATUS_NO_MEMORY;
3321 ret = ldb_msg_add_string(msg, "cn", name2);
3322 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3324 secret_state->global = false;
3326 name = r->in.name.string;
3327 if (strlen(name) == 0) {
3328 return NT_STATUS_INVALID_PARAMETER;
3331 secret_state->sam_ldb = secrets_db_connect(secret_state,
3332 dce_call->conn->dce_ctx->lp_ctx);
3333 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3335 /* search for the secret record */
3336 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3337 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3339 "(&(cn=%s)(objectclass=secret))",
3340 ldb_binary_encode_string(mem_ctx, name));
3342 return NT_STATUS_OBJECT_NAME_COLLISION;
3346 DEBUG(0,("Failure searching for CN=%s: %s\n",
3347 name, ldb_errstring(secret_state->sam_ldb)));
3348 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3351 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3352 "cn=%s,cn=LSA Secrets", name);
3353 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3354 ret = ldb_msg_add_string(msg, "cn", name);
3355 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3358 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3359 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3361 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3362 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3364 /* create the secret */
3365 ret = ldb_add(secret_state->sam_ldb, msg);
3366 if (ret != LDB_SUCCESS) {
3367 DEBUG(0,("Failed to create secret record %s: %s\n",
3368 ldb_dn_get_linearized(msg->dn),
3369 ldb_errstring(secret_state->sam_ldb)));
3370 return NT_STATUS_ACCESS_DENIED;
3373 handle = dcesrv_handle_create(dce_call, LSA_HANDLE_SECRET);
3374 NT_STATUS_HAVE_NO_MEMORY(handle);
3376 handle->data = talloc_steal(handle, secret_state);
3378 secret_state->access_mask = r->in.access_mask;
3379 secret_state->policy = talloc_reference(secret_state, policy_state);
3380 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3382 *r->out.sec_handle = handle->wire_handle;
3384 return NT_STATUS_OK;
3391 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3392 struct lsa_OpenSecret *r)
3394 struct auth_session_info *session_info =
3395 dcesrv_call_session_info(dce_call);
3396 struct dcesrv_handle *policy_handle;
3397 struct lsa_policy_state *policy_state;
3398 struct lsa_secret_state *secret_state;
3399 struct dcesrv_handle *handle;
3400 struct ldb_message **msgs;
3401 const char *attrs[] = {
3407 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3408 ZERO_STRUCTP(r->out.sec_handle);
3409 policy_state = policy_handle->data;
3411 if (!r->in.name.string) {
3412 return NT_STATUS_INVALID_PARAMETER;
3415 switch (security_session_user_level(session_info, NULL))
3417 case SECURITY_SYSTEM:
3418 case SECURITY_ADMINISTRATOR:
3421 /* Users and annonymous are not allowed to access secrets */
3422 return NT_STATUS_ACCESS_DENIED;
3425 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3426 if (!secret_state) {
3427 return NT_STATUS_NO_MEMORY;
3429 secret_state->policy = policy_state;
3431 if (strncmp("G$", r->in.name.string, 2) == 0) {
3432 name = &r->in.name.string[2];
3434 * We need to connect to the database as system, as this is
3435 * one of the rare RPC calls that must read the secrets
3436 * (and this is denied otherwise)
3438 * We also save the current remote session details so they can
3439 * used by the audit logging module. This allows the audit
3440 * logging to report the remote users details, rather than the
3441 * system users details.
3443 secret_state->sam_ldb =
3444 dcesrv_samdb_connect_as_system(secret_state, dce_call);
3445 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3446 secret_state->global = true;
3448 if (strlen(name) < 1) {
3449 return NT_STATUS_INVALID_PARAMETER;
3452 /* search for the secret record */
3453 ret = gendb_search(secret_state->sam_ldb,
3454 mem_ctx, policy_state->system_dn, &msgs, attrs,
3455 "(&(cn=%s Secret)(objectclass=secret))",
3456 ldb_binary_encode_string(mem_ctx, name));
3458 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3462 DEBUG(0,("Found %d records matching DN %s\n", ret,
3463 ldb_dn_get_linearized(policy_state->system_dn)));
3464 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3467 secret_state->global = false;
3468 secret_state->sam_ldb = secrets_db_connect(secret_state,
3469 dce_call->conn->dce_ctx->lp_ctx);
3470 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3472 name = r->in.name.string;
3473 if (strlen(name) < 1) {
3474 return NT_STATUS_INVALID_PARAMETER;
3477 /* search for the secret record */
3478 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3479 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3481 "(&(cn=%s)(objectclass=secret))",
3482 ldb_binary_encode_string(mem_ctx, name));
3484 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3488 DEBUG(0,("Found %d records matching CN=%s\n",
3489 ret, ldb_binary_encode_string(mem_ctx, name)));
3490 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3494 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3496 handle = dcesrv_handle_create(dce_call, LSA_HANDLE_SECRET);
3498 return NT_STATUS_NO_MEMORY;
3501 handle->data = talloc_steal(handle, secret_state);
3503 secret_state->access_mask = r->in.access_mask;
3504 secret_state->policy = talloc_reference(secret_state, policy_state);
3506 *r->out.sec_handle = handle->wire_handle;
3508 return NT_STATUS_OK;
3515 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3516 struct lsa_SetSecret *r)
3519 struct dcesrv_handle *h;
3520 struct lsa_secret_state *secret_state;
3521 struct ldb_message *msg;
3522 DATA_BLOB session_key;
3523 DATA_BLOB crypt_secret, secret;
3526 NTSTATUS status = NT_STATUS_OK;
3528 struct timeval now = timeval_current();
3529 NTTIME nt_now = timeval_to_nttime(&now);
3531 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3533 secret_state = h->data;
3535 msg = ldb_msg_new(mem_ctx);
3537 return NT_STATUS_NO_MEMORY;
3540 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3542 return NT_STATUS_NO_MEMORY;
3544 status = dcesrv_transport_session_key(dce_call, &session_key);
3545 if (!NT_STATUS_IS_OK(status)) {
3549 if (r->in.old_val) {
3551 crypt_secret.data = r->in.old_val->data;
3552 crypt_secret.length = r->in.old_val->size;
3554 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3555 if (!NT_STATUS_IS_OK(status)) {
3559 val.data = secret.data;
3560 val.length = secret.length;
3563 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3564 return NT_STATUS_NO_MEMORY;
3567 /* set old value mtime */
3568 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3569 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3570 return NT_STATUS_NO_MEMORY;
3574 /* If the old value is not set, then migrate the
3575 * current value to the old value */
3576 const struct ldb_val *old_val;
3577 NTTIME last_set_time;
3578 struct ldb_message **res;
3579 const char *attrs[] = {
3585 /* search for the secret record */
3586 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3587 secret_state->secret_dn, &res, attrs);
3589 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3593 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3594 ldb_dn_get_linearized(secret_state->secret_dn)));
3595 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3598 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3599 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3603 if (ldb_msg_add_value(msg, "priorValue",
3604 old_val, NULL) != LDB_SUCCESS) {
3605 return NT_STATUS_NO_MEMORY;
3608 if (samdb_msg_add_delete(secret_state->sam_ldb,
3609 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3610 return NT_STATUS_NO_MEMORY;
3614 /* set old value mtime */
3615 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3616 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3617 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3618 return NT_STATUS_NO_MEMORY;
3621 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3622 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3623 return NT_STATUS_NO_MEMORY;
3628 if (r->in.new_val) {
3630 crypt_secret.data = r->in.new_val->data;
3631 crypt_secret.length = r->in.new_val->size;
3633 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3634 if (!NT_STATUS_IS_OK(status)) {
3638 val.data = secret.data;
3639 val.length = secret.length;
3642 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3643 return NT_STATUS_NO_MEMORY;
3646 /* set new value mtime */
3647 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3648 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3649 return NT_STATUS_NO_MEMORY;
3652 /* NULL out the NEW value */
3653 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3654 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3655 return NT_STATUS_NO_MEMORY;
3657 if (samdb_msg_add_delete(secret_state->sam_ldb,
3658 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3659 return NT_STATUS_NO_MEMORY;
3663 /* modify the samdb record */
3664 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3665 if (ret != LDB_SUCCESS) {
3666 return dsdb_ldb_err_to_ntstatus(ret);
3669 return NT_STATUS_OK;
3676 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3677 struct lsa_QuerySecret *r)
3679 struct auth_session_info *session_info =
3680 dcesrv_call_session_info(dce_call);
3681 struct dcesrv_handle *h;
3682 struct lsa_secret_state *secret_state;
3683 struct ldb_message *msg;
3684 DATA_BLOB session_key;
3685 DATA_BLOB crypt_secret, secret;
3687 struct ldb_message **res;
3688 const char *attrs[] = {
3698 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3700 /* Ensure user is permitted to read this... */
3701 switch (security_session_user_level(session_info, NULL))
3703 case SECURITY_SYSTEM:
3704 case SECURITY_ADMINISTRATOR:
3707 /* Users and annonymous are not allowed to read secrets */
3708 return NT_STATUS_ACCESS_DENIED;
3711 secret_state = h->data;
3713 /* pull all the user attributes */
3714 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3715 secret_state->secret_dn, &res, attrs);
3717 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3721 nt_status = dcesrv_transport_session_key(dce_call, &session_key);
3722 if (!NT_STATUS_IS_OK(nt_status)) {
3726 if (r->in.old_val) {
3727 const struct ldb_val *prior_val;
3728 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3729 if (!r->out.old_val) {
3730 return NT_STATUS_NO_MEMORY;
3732 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3734 if (prior_val && prior_val->length) {
3735 secret.data = prior_val->data;
3736 secret.length = prior_val->length;
3739 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3740 if (!crypt_secret.length) {
3741 return NT_STATUS_NO_MEMORY;
3743 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3744 if (!r->out.old_val->buf) {
3745 return NT_STATUS_NO_MEMORY;
3747 r->out.old_val->buf->size = crypt_secret.length;
3748 r->out.old_val->buf->length = crypt_secret.length;
3749 r->out.old_val->buf->data = crypt_secret.data;
3753 if (r->in.old_mtime) {
3754 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3755 if (!r->out.old_mtime) {
3756 return NT_STATUS_NO_MEMORY;
3758 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3761 if (r->in.new_val) {
3762 const struct ldb_val *new_val;
3763 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3764 if (!r->out.new_val) {
3765 return NT_STATUS_NO_MEMORY;
3768 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3770 if (new_val && new_val->length) {
3771 secret.data = new_val->data;
3772 secret.length = new_val->length;
3775 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3776 if (!crypt_secret.length) {
3777 return NT_STATUS_NO_MEMORY;
3779 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3780 if (!r->out.new_val->buf) {
3781 return NT_STATUS_NO_MEMORY;
3783 r->out.new_val->buf->length = crypt_secret.length;
3784 r->out.new_val->buf->size = crypt_secret.length;
3785 r->out.new_val->buf->data = crypt_secret.data;
3789 if (r->in.new_mtime) {
3790 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3791 if (!r->out.new_mtime) {
3792 return NT_STATUS_NO_MEMORY;
3794 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3797 return NT_STATUS_OK;
3804 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3805 TALLOC_CTX *mem_ctx,
3806 struct lsa_LookupPrivValue *r)
3808 struct dcesrv_handle *h;
3811 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3813 id = sec_privilege_id(r->in.name->string);
3814 if (id == SEC_PRIV_INVALID) {
3815 return NT_STATUS_NO_SUCH_PRIVILEGE;
3818 r->out.luid->low = id;
3819 r->out.luid->high = 0;
3821 return NT_STATUS_OK;
3828 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3829 TALLOC_CTX *mem_ctx,
3830 struct lsa_LookupPrivName *r)
3832 struct dcesrv_handle *h;
3833 struct lsa_StringLarge *name;
3834 const char *privname;
3836 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3838 if (r->in.luid->high != 0) {
3839 return NT_STATUS_NO_SUCH_PRIVILEGE;
3842 privname = sec_privilege_name(r->in.luid->low);
3843 if (privname == NULL) {
3844 return NT_STATUS_NO_SUCH_PRIVILEGE;
3847 name = talloc(mem_ctx, struct lsa_StringLarge);
3849 return NT_STATUS_NO_MEMORY;
3852 name->string = privname;
3854 *r->out.name = name;
3856 return NT_STATUS_OK;
3861 lsa_LookupPrivDisplayName
3863 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3864 TALLOC_CTX *mem_ctx,
3865 struct lsa_LookupPrivDisplayName *r)
3867 struct dcesrv_handle *h;
3868 struct lsa_StringLarge *disp_name = NULL;
3869 enum sec_privilege id;
3871 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3873 id = sec_privilege_id(r->in.name->string);
3874 if (id == SEC_PRIV_INVALID) {
3875 return NT_STATUS_NO_SUCH_PRIVILEGE;
3878 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3879 if (disp_name == NULL) {
3880 return NT_STATUS_NO_MEMORY;
3883 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3884 if (disp_name->string == NULL) {
3885 return NT_STATUS_INTERNAL_ERROR;
3888 *r->out.disp_name = disp_name;
3889 *r->out.returned_language_id = 0;
3891 return NT_STATUS_OK;
3896 lsa_EnumAccountsWithUserRight
3898 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3899 TALLOC_CTX *mem_ctx,
3900 struct lsa_EnumAccountsWithUserRight *r)
3902 struct dcesrv_handle *h;
3903 struct lsa_policy_state *state;
3905 struct ldb_message **res;
3906 const char * const attrs[] = { "objectSid", NULL};
3907 const char *privname;
3910 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3914 if (r->in.name == NULL) {
3915 return NT_STATUS_NO_SUCH_PRIVILEGE;
3918 privname = r->in.name->string;
3920 ok = dcesrc_lsa_valid_AccountRight(privname);
3922 return NT_STATUS_NO_SUCH_PRIVILEGE;
3925 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3926 "privilege=%s", privname);
3928 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3931 return NT_STATUS_NO_MORE_ENTRIES;
3934 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3935 if (r->out.sids->sids == NULL) {
3936 return NT_STATUS_NO_MEMORY;
3938 for (i=0;i<ret;i++) {
3939 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3940 res[i], "objectSid");
3941 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3943 r->out.sids->num_sids = ret;
3945 return NT_STATUS_OK;
3950 lsa_AddAccountRights
3952 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3953 TALLOC_CTX *mem_ctx,
3954 struct lsa_AddAccountRights *r)
3956 struct dcesrv_handle *h;
3957 struct lsa_policy_state *state;
3959 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3963 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3965 r->in.sid, r->in.rights);
3970 lsa_RemoveAccountRights
3972 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3973 TALLOC_CTX *mem_ctx,
3974 struct lsa_RemoveAccountRights *r)
3976 struct dcesrv_handle *h;
3977 struct lsa_policy_state *state;
3979 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3983 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3984 LDB_FLAG_MOD_DELETE,
3985 r->in.sid, r->in.rights);
3990 lsa_StorePrivateData
3992 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3993 struct lsa_StorePrivateData *r)
3995 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4000 lsa_RetrievePrivateData
4002 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4003 struct lsa_RetrievePrivateData *r)
4005 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4012 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4013 struct lsa_GetUserName *r)
4015 enum dcerpc_transport_t transport =
4016 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
4017 struct auth_session_info *session_info =
4018 dcesrv_call_session_info(dce_call);
4019 NTSTATUS status = NT_STATUS_OK;
4020 const char *account_name;
4021 const char *authority_name;
4022 struct lsa_String *_account_name;
4023 struct lsa_String *_authority_name = NULL;
4025 if (transport != NCACN_NP && transport != NCALRPC) {
4026 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
4029 /* this is what w2k3 does */
4030 r->out.account_name = r->in.account_name;
4031 r->out.authority_name = r->in.authority_name;
4033 if (r->in.account_name
4034 && *r->in.account_name
4035 /* && *(*r->in.account_name)->string */
4037 return NT_STATUS_INVALID_PARAMETER;
4040 if (r->in.authority_name
4041 && *r->in.authority_name
4042 /* && *(*r->in.authority_name)->string */
4044 return NT_STATUS_INVALID_PARAMETER;
4047 account_name = talloc_reference(mem_ctx, session_info->info->account_name);
4048 authority_name = talloc_reference(mem_ctx, session_info->info->domain_name);
4050 _account_name = talloc(mem_ctx, struct lsa_String);
4051 NT_STATUS_HAVE_NO_MEMORY(_account_name);
4052 _account_name->string = account_name;
4054 if (r->in.authority_name) {
4055 _authority_name = talloc(mem_ctx, struct lsa_String);
4056 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
4057 _authority_name->string = authority_name;
4060 *r->out.account_name = _account_name;
4061 if (r->out.authority_name) {
4062 *r->out.authority_name = _authority_name;
4071 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
4072 TALLOC_CTX *mem_ctx,
4073 struct lsa_SetInfoPolicy2 *r)
4075 /* need to support these */
4076 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4079 static void kdc_get_policy(TALLOC_CTX *mem_ctx,
4080 struct loadparm_context *lp_ctx,
4081 struct smb_krb5_context *smb_krb5_context,
4082 struct lsa_DomainInfoKerberos *k)
4084 time_t svc_tkt_lifetime;
4085 time_t usr_tkt_lifetime;
4086 time_t renewal_lifetime;
4088 /* Our KDC always re-validates the client */
4089 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
4091 lpcfg_default_kdc_policy(mem_ctx, lp_ctx, &svc_tkt_lifetime,
4092 &usr_tkt_lifetime, &renewal_lifetime);
4094 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
4095 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
4096 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
4097 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
4098 However in the parent function we basically just did a full
4099 krb5_context init with the only purpose of getting a global
4100 config option (the max skew), it would probably make more sense
4101 to have a lp_ or ldb global option as the samba default */
4102 if (smb_krb5_context) {
4103 unix_to_nt_time(&k->clock_skew,
4104 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
4110 lsa_QueryDomainInformationPolicy
4112 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4113 TALLOC_CTX *mem_ctx,
4114 struct lsa_QueryDomainInformationPolicy *r)
4116 union lsa_DomainInformationPolicy *info;
4118 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
4120 return NT_STATUS_NO_MEMORY;
4123 switch (r->in.level) {
4124 case LSA_DOMAIN_INFO_POLICY_EFS:
4126 *r->out.info = NULL;
4127 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4128 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
4130 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
4131 struct smb_krb5_context *smb_krb5_context;
4132 int ret = smb_krb5_init_context(mem_ctx,
4133 dce_call->conn->dce_ctx->lp_ctx,
4137 *r->out.info = NULL;
4138 return NT_STATUS_INTERNAL_ERROR;
4140 kdc_get_policy(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
4143 talloc_free(smb_krb5_context);
4144 *r->out.info = info;
4145 return NT_STATUS_OK;
4149 *r->out.info = NULL;
4150 return NT_STATUS_INVALID_INFO_CLASS;
4155 lsa_SetDomInfoPolicy
4157 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4158 TALLOC_CTX *mem_ctx,
4159 struct lsa_SetDomainInformationPolicy *r)
4161 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4167 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
4168 TALLOC_CTX *mem_ctx,
4169 struct lsa_TestCall *r)
4171 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4177 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4178 struct lsa_CREDRWRITE *r)
4180 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4187 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4188 struct lsa_CREDRREAD *r)
4190 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4197 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4198 struct lsa_CREDRENUMERATE *r)
4200 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4205 lsa_CREDRWRITEDOMAINCREDENTIALS
4207 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4208 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
4210 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4215 lsa_CREDRREADDOMAINCREDENTIALS
4217 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4218 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
4220 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4227 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4228 struct lsa_CREDRDELETE *r)
4230 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4235 lsa_CREDRGETTARGETINFO
4237 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4238 struct lsa_CREDRGETTARGETINFO *r)
4240 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4245 lsa_CREDRPROFILELOADED
4247 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4248 struct lsa_CREDRPROFILELOADED *r)
4250 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4255 lsa_CREDRGETSESSIONTYPES
4257 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4258 struct lsa_CREDRGETSESSIONTYPES *r)
4260 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4265 lsa_LSARREGISTERAUDITEVENT
4267 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4268 struct lsa_LSARREGISTERAUDITEVENT *r)
4270 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4275 lsa_LSARGENAUDITEVENT
4277 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4278 struct lsa_LSARGENAUDITEVENT *r)
4280 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4285 lsa_LSARUNREGISTERAUDITEVENT
4287 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4288 struct lsa_LSARUNREGISTERAUDITEVENT *r)
4290 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4295 lsa_lsaRQueryForestTrustInformation
4297 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4298 struct lsa_lsaRQueryForestTrustInformation *r)
4300 struct dcesrv_handle *h = NULL;
4301 struct lsa_policy_state *p_state = NULL;
4302 int forest_level = DS_DOMAIN_FUNCTION_2000;
4303 const char * const trust_attrs[] = {
4304 "securityIdentifier",
4310 "msDS-TrustForestTrustInfo",
4313 struct ldb_message *trust_tdo_msg = NULL;
4314 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4315 struct ForestTrustInfo *trust_fti = NULL;
4316 struct lsa_ForestTrustInformation *trust_lfti = NULL;
4319 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4323 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4324 return NT_STATUS_INVALID_DOMAIN_STATE;
4327 forest_level = dsdb_forest_functional_level(p_state->sam_ldb);
4328 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4329 return NT_STATUS_INVALID_DOMAIN_STATE;
4332 if (r->in.trusted_domain_name->string == NULL) {
4333 return NT_STATUS_NO_SUCH_DOMAIN;
4336 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4337 r->in.trusted_domain_name->string,
4338 r->in.trusted_domain_name->string,
4339 trust_attrs, mem_ctx, &trust_tdo_msg);
4340 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4341 return NT_STATUS_NO_SUCH_DOMAIN;
4343 if (!NT_STATUS_IS_OK(status)) {
4347 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4348 if (!NT_STATUS_IS_OK(status)) {
4352 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4353 return NT_STATUS_INVALID_PARAMETER;
4356 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4357 return NT_STATUS_INVALID_PARAMETER;
4360 status = dsdb_trust_parse_forest_info(mem_ctx,
4363 if (!NT_STATUS_IS_OK(status)) {
4367 status = dsdb_trust_forest_info_to_lsa(mem_ctx, trust_fti,
4369 if (!NT_STATUS_IS_OK(status)) {
4373 *r->out.forest_trust_info = trust_lfti;
4374 return NT_STATUS_OK;
4378 lsa_lsaRSetForestTrustInformation
4380 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4381 TALLOC_CTX *mem_ctx,
4382 struct lsa_lsaRSetForestTrustInformation *r)
4384 struct dcesrv_handle *h;
4385 struct lsa_policy_state *p_state;
4386 const char * const trust_attrs[] = {
4387 "securityIdentifier",
4393 "msDS-TrustForestTrustInfo",
4396 struct ldb_message *trust_tdo_msg = NULL;
4397 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4398 struct lsa_ForestTrustInformation *step1_lfti = NULL;
4399 struct lsa_ForestTrustInformation *step2_lfti = NULL;
4400 struct ForestTrustInfo *trust_fti = NULL;
4401 struct ldb_result *trusts_res = NULL;
4403 struct lsa_TrustDomainInfoInfoEx *xref_tdo = NULL;
4404 struct lsa_ForestTrustInformation *xref_lfti = NULL;
4405 struct lsa_ForestTrustCollisionInfo *c_info = NULL;
4406 DATA_BLOB ft_blob = {};
4407 struct ldb_message *msg = NULL;
4408 struct server_id *server_ids = NULL;
4409 uint32_t num_server_ids = 0;
4411 enum ndr_err_code ndr_err;
4413 bool in_transaction = false;
4414 struct imessaging_context *imsg_ctx =
4415 dcesrv_imessaging_context(dce_call->conn);
4417 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4421 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4422 return NT_STATUS_INVALID_DOMAIN_STATE;
4425 if (r->in.check_only == 0) {
4426 ret = ldb_transaction_start(p_state->sam_ldb);
4427 if (ret != LDB_SUCCESS) {
4428 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4430 in_transaction = true;
4434 * abort if we are not a PDC
4436 * In future we should use a function like IsEffectiveRoleOwner()
4438 if (!samdb_is_pdc(p_state->sam_ldb)) {
4439 status = NT_STATUS_INVALID_DOMAIN_ROLE;
4443 if (r->in.trusted_domain_name->string == NULL) {
4444 status = NT_STATUS_NO_SUCH_DOMAIN;
4448 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4449 r->in.trusted_domain_name->string,
4450 r->in.trusted_domain_name->string,
4451 trust_attrs, mem_ctx, &trust_tdo_msg);
4452 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4453 status = NT_STATUS_NO_SUCH_DOMAIN;
4456 if (!NT_STATUS_IS_OK(status)) {
4460 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4461 if (!NT_STATUS_IS_OK(status)) {
4465 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4466 status = NT_STATUS_INVALID_PARAMETER;
4470 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4471 status = NT_STATUS_INVALID_PARAMETER;
4476 * verify and normalize the given forest trust info.
4478 * Step1: doesn't reorder yet, so step1_lfti might contain
4479 * NULL entries. This means dsdb_trust_verify_forest_info()
4480 * can generate collision entries with the callers index.
4482 status = dsdb_trust_normalize_forest_info_step1(mem_ctx,
4483 r->in.forest_trust_info,
4485 if (!NT_STATUS_IS_OK(status)) {
4489 c_info = talloc_zero(r->out.collision_info,
4490 struct lsa_ForestTrustCollisionInfo);
4491 if (c_info == NULL) {
4492 status = NT_STATUS_NO_MEMORY;
4497 * First check our own forest, then other domains/forests
4500 status = dsdb_trust_xref_tdo_info(mem_ctx, p_state->sam_ldb,
4502 if (!NT_STATUS_IS_OK(status)) {
4505 status = dsdb_trust_xref_forest_info(mem_ctx, p_state->sam_ldb,
4507 if (!NT_STATUS_IS_OK(status)) {
4512 * The documentation proposed to generate
4513 * LSA_FOREST_TRUST_COLLISION_XREF collisions.
4514 * But Windows always uses LSA_FOREST_TRUST_COLLISION_TDO.
4516 status = dsdb_trust_verify_forest_info(xref_tdo, xref_lfti,
4517 LSA_FOREST_TRUST_COLLISION_TDO,
4518 c_info, step1_lfti);
4519 if (!NT_STATUS_IS_OK(status)) {
4523 /* fetch all other trusted domain objects */
4524 status = dsdb_trust_search_tdos(p_state->sam_ldb,
4525 trust_tdo->domain_name.string,
4527 mem_ctx, &trusts_res);
4528 if (!NT_STATUS_IS_OK(status)) {
4533 * now check against the other domains.
4534 * and generate LSA_FOREST_TRUST_COLLISION_TDO collisions.
4536 for (i = 0; i < trusts_res->count; i++) {
4537 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
4538 struct ForestTrustInfo *fti = NULL;
4539 struct lsa_ForestTrustInformation *lfti = NULL;
4541 status = dsdb_trust_parse_tdo_info(mem_ctx,
4542 trusts_res->msgs[i],
4544 if (!NT_STATUS_IS_OK(status)) {
4548 status = dsdb_trust_parse_forest_info(tdo,
4549 trusts_res->msgs[i],
4551 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
4554 if (!NT_STATUS_IS_OK(status)) {
4558 status = dsdb_trust_forest_info_to_lsa(tdo, fti, &lfti);
4559 if (!NT_STATUS_IS_OK(status)) {
4563 status = dsdb_trust_verify_forest_info(tdo, lfti,
4564 LSA_FOREST_TRUST_COLLISION_TDO,
4565 c_info, step1_lfti);
4566 if (!NT_STATUS_IS_OK(status)) {
4573 if (r->in.check_only != 0) {
4574 status = NT_STATUS_OK;
4579 * not just a check, write info back
4583 * normalize the given forest trust info.
4585 * Step2: adds TOP_LEVEL_NAME[_EX] in reverse order,
4586 * followed by DOMAIN_INFO in reverse order. It also removes
4587 * possible NULL entries from Step1.
4589 status = dsdb_trust_normalize_forest_info_step2(mem_ctx, step1_lfti,
4591 if (!NT_STATUS_IS_OK(status)) {
4595 status = dsdb_trust_forest_info_from_lsa(mem_ctx, step2_lfti,
4597 if (!NT_STATUS_IS_OK(status)) {
4601 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, trust_fti,
4602 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4603 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4604 status = NT_STATUS_INVALID_PARAMETER;
4608 msg = ldb_msg_new(mem_ctx);
4610 status = NT_STATUS_NO_MEMORY;
4614 msg->dn = ldb_dn_copy(mem_ctx, trust_tdo_msg->dn);
4616 status = NT_STATUS_NO_MEMORY;
4620 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4621 LDB_FLAG_MOD_REPLACE, NULL);
4622 if (ret != LDB_SUCCESS) {
4623 status = NT_STATUS_NO_MEMORY;
4626 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4628 if (ret != LDB_SUCCESS) {
4629 status = NT_STATUS_NO_MEMORY;
4633 ret = ldb_modify(p_state->sam_ldb, msg);
4634 if (ret != LDB_SUCCESS) {
4635 status = dsdb_ldb_err_to_ntstatus(ret);
4637 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4638 ldb_errstring(p_state->sam_ldb)));
4643 /* ok, all fine, commit transaction and return */
4644 in_transaction = false;
4645 ret = ldb_transaction_commit(p_state->sam_ldb);
4646 if (ret != LDB_SUCCESS) {
4647 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4652 * Notify winbindd that we have a acquired forest trust info
4654 status = irpc_servers_byname(imsg_ctx,
4659 if (!NT_STATUS_IS_OK(status)) {
4660 DBG_ERR("irpc_servers_byname failed\n");
4664 imessaging_send(imsg_ctx,
4666 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
4669 status = NT_STATUS_OK;
4672 if (NT_STATUS_IS_OK(status) && c_info->count != 0) {
4673 *r->out.collision_info = c_info;
4676 if (in_transaction) {
4677 ldb_transaction_cancel(p_state->sam_ldb);
4686 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4687 struct lsa_CREDRRENAME *r)
4689 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4695 lsa_LSAROPENPOLICYSCE
4697 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4698 struct lsa_LSAROPENPOLICYSCE *r)
4700 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4705 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4707 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4708 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4710 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4715 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4717 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4718 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4720 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4725 lsa_LSARADTREPORTSECURITYEVENT
4727 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4728 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4730 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4734 /* include the generated boilerplate */
4735 #include "librpc/gen_ndr/ndr_lsa_s.c"
4739 /*****************************************
4740 NOTE! The remaining calls below were
4741 removed in w2k3, so the DCESRV_FAULT()
4742 replies are the correct implementation. Do
4743 not try and fill these in with anything else
4744 ******************************************/
4747 dssetup_DsRoleDnsNameToFlatName
4749 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4750 struct dssetup_DsRoleDnsNameToFlatName *r)
4752 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4757 dssetup_DsRoleDcAsDc
4759 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4760 struct dssetup_DsRoleDcAsDc *r)
4762 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4767 dssetup_DsRoleDcAsReplica
4769 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4770 struct dssetup_DsRoleDcAsReplica *r)
4772 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4777 dssetup_DsRoleDemoteDc
4779 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4780 struct dssetup_DsRoleDemoteDc *r)
4782 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4787 dssetup_DsRoleGetDcOperationProgress
4789 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4790 struct dssetup_DsRoleGetDcOperationProgress *r)
4792 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4797 dssetup_DsRoleGetDcOperationResults
4799 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4800 struct dssetup_DsRoleGetDcOperationResults *r)
4802 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4807 dssetup_DsRoleCancel
4809 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4810 struct dssetup_DsRoleCancel *r)
4812 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4817 dssetup_DsRoleServerSaveStateForUpgrade
4819 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4820 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4822 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4827 dssetup_DsRoleUpgradeDownlevelServer
4829 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4830 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4832 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4837 dssetup_DsRoleAbortDownlevelServerUpgrade
4839 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4840 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4842 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4846 /* include the generated boilerplate */
4847 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4849 NTSTATUS dcerpc_server_lsa_init(TALLOC_CTX *ctx)
4853 ret = dcerpc_server_dssetup_init(ctx);
4854 if (!NT_STATUS_IS_OK(ret)) {
4857 ret = dcerpc_server_lsarpc_init(ctx);
4858 if (!NT_STATUS_IS_OK(ret)) {