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>
42 #define DCESRV_INTERFACE_LSARPC_BIND(context, iface) \
43 dcesrv_interface_lsarpc_bind(context, iface)
44 static NTSTATUS dcesrv_interface_lsarpc_bind(struct dcesrv_connection_context *context,
45 const struct dcesrv_interface *iface)
47 return dcesrv_interface_bind_reject_connect(context, iface);
50 static NTSTATUS lsarpc__op_init_server(struct dcesrv_context *dce_ctx,
51 const struct dcesrv_endpoint_server *ep_server);
52 static const struct dcesrv_interface dcesrv_lsarpc_interface;
54 #define NCACN_NP_PIPE_NETLOGON "ncacn_np:[\\pipe\\netlogon]"
55 #define NCACN_NP_PIPE_LSASS "ncacn_np:[\\pipe\\lsass]"
56 #define DCESRV_INTERFACE_LSARPC_NCACN_NP_SECONDARY_ENDPOINT NCACN_NP_PIPE_LSASS
58 #define DCESRV_INTERFACE_LSARPC_INIT_SERVER \
59 dcesrv_interface_lsarpc_init_server
60 static NTSTATUS dcesrv_interface_lsarpc_init_server(struct dcesrv_context *dce_ctx,
61 const struct dcesrv_endpoint_server *ep_server)
63 if (lpcfg_lsa_over_netlogon(dce_ctx->lp_ctx)) {
64 NTSTATUS ret = dcesrv_interface_register(dce_ctx,
65 NCACN_NP_PIPE_NETLOGON,
67 &dcesrv_lsarpc_interface, NULL);
68 if (!NT_STATUS_IS_OK(ret)) {
69 DEBUG(1,("lsarpc_op_init_server: failed to register endpoint '\\pipe\\netlogon'\n"));
73 return lsarpc__op_init_server(dce_ctx, ep_server);
77 this type allows us to distinguish handle types
81 state associated with a lsa_OpenAccount() operation
83 struct lsa_account_state {
84 struct lsa_policy_state *policy;
86 struct dom_sid *account_sid;
91 state associated with a lsa_OpenSecret() operation
93 struct lsa_secret_state {
94 struct lsa_policy_state *policy;
96 struct ldb_dn *secret_dn;
97 struct ldb_context *sam_ldb;
102 state associated with a lsa_OpenTrustedDomain() operation
104 struct lsa_trusted_domain_state {
105 struct lsa_policy_state *policy;
106 uint32_t access_mask;
107 struct ldb_dn *trusted_domain_dn;
108 struct ldb_dn *trusted_domain_user_dn;
111 static bool dcesrc_lsa_valid_AccountRight(const char *right)
113 enum sec_privilege priv_id;
116 priv_id = sec_privilege_id(right);
117 if (priv_id != SEC_PRIV_INVALID) {
121 right_bit = sec_right_bit(right);
122 if (right_bit != 0) {
130 this is based on the samba3 function make_lsa_object_sd()
131 It uses the same logic, but with samba4 helper functions
133 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
134 struct security_descriptor **sd,
140 struct dom_sid *domain_sid, *domain_admins_sid;
141 const char *domain_admins_sid_str, *sidstr;
142 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
144 status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
145 if (!NT_STATUS_IS_OK(status)) {
146 TALLOC_FREE(tmp_ctx);
150 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
151 if (domain_admins_sid == NULL) {
152 TALLOC_FREE(tmp_ctx);
153 return NT_STATUS_NO_MEMORY;
156 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
157 if (domain_admins_sid_str == NULL) {
158 TALLOC_FREE(tmp_ctx);
159 return NT_STATUS_NO_MEMORY;
162 sidstr = dom_sid_string(tmp_ctx, sid);
163 if (sidstr == NULL) {
164 TALLOC_FREE(tmp_ctx);
165 return NT_STATUS_NO_MEMORY;
168 *sd = security_descriptor_dacl_create(mem_ctx,
172 SEC_ACE_TYPE_ACCESS_ALLOWED,
173 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
175 SID_BUILTIN_ADMINISTRATORS,
176 SEC_ACE_TYPE_ACCESS_ALLOWED,
179 SID_BUILTIN_ACCOUNT_OPERATORS,
180 SEC_ACE_TYPE_ACCESS_ALLOWED,
183 domain_admins_sid_str,
184 SEC_ACE_TYPE_ACCESS_ALLOWED,
188 SEC_ACE_TYPE_ACCESS_ALLOWED,
192 talloc_free(tmp_ctx);
194 NT_STATUS_HAVE_NO_MEMORY(*sd);
200 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
202 struct lsa_EnumAccountRights *r);
204 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
206 struct lsa_policy_state *state,
209 const struct lsa_RightSet *rights);
214 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
217 enum dcerpc_transport_t transport =
218 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
219 struct dcesrv_handle *h;
221 if (transport != NCACN_NP && transport != NCALRPC) {
222 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
225 *r->out.handle = *r->in.handle;
227 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
231 ZERO_STRUCTP(r->out.handle);
240 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
241 struct lsa_Delete *r)
243 return NT_STATUS_NOT_SUPPORTED;
250 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
251 struct lsa_DeleteObject *r)
253 struct auth_session_info *session_info =
254 dcesrv_call_session_info(dce_call);
255 struct dcesrv_handle *h;
258 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
260 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
261 struct lsa_secret_state *secret_state = h->data;
263 /* Ensure user is permitted to delete this... */
264 switch (security_session_user_level(session_info, NULL))
266 case SECURITY_SYSTEM:
267 case SECURITY_ADMINISTRATOR:
270 /* Users and anonymous are not allowed to delete things */
271 return NT_STATUS_ACCESS_DENIED;
274 ret = ldb_delete(secret_state->sam_ldb,
275 secret_state->secret_dn);
276 if (ret != LDB_SUCCESS) {
277 return NT_STATUS_INVALID_HANDLE;
280 ZERO_STRUCTP(r->out.handle);
284 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
285 struct lsa_trusted_domain_state *trusted_domain_state =
286 talloc_get_type(h->data, struct lsa_trusted_domain_state);
287 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
288 if (ret != LDB_SUCCESS) {
289 return NT_STATUS_INTERNAL_DB_CORRUPTION;
292 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
293 trusted_domain_state->trusted_domain_dn);
294 if (ret != LDB_SUCCESS) {
295 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
296 return NT_STATUS_INVALID_HANDLE;
299 if (trusted_domain_state->trusted_domain_user_dn) {
300 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
301 trusted_domain_state->trusted_domain_user_dn);
302 if (ret != LDB_SUCCESS) {
303 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
304 return NT_STATUS_INVALID_HANDLE;
308 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
309 if (ret != LDB_SUCCESS) {
310 return NT_STATUS_INTERNAL_DB_CORRUPTION;
313 ZERO_STRUCTP(r->out.handle);
317 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
318 struct lsa_RightSet *rights;
319 struct lsa_account_state *astate;
320 struct lsa_EnumAccountRights r2;
323 rights = talloc(mem_ctx, struct lsa_RightSet);
325 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
329 r2.in.handle = &astate->policy->handle->wire_handle;
330 r2.in.sid = astate->account_sid;
331 r2.out.rights = rights;
333 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
334 but we have a LSA_HANDLE_ACCOUNT here, so this call
336 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
337 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
341 if (!NT_STATUS_IS_OK(status)) {
345 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
346 LDB_FLAG_MOD_DELETE, astate->account_sid,
348 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
352 if (!NT_STATUS_IS_OK(status)) {
356 ZERO_STRUCTP(r->out.handle);
361 return NT_STATUS_INVALID_HANDLE;
368 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
369 struct lsa_EnumPrivs *r)
371 struct dcesrv_handle *h;
373 enum sec_privilege priv;
374 const char *privname;
376 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
378 i = *r->in.resume_handle;
380 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
381 r->out.privs->count < r->in.max_count) {
382 struct lsa_PrivEntry *e;
383 privname = sec_privilege_name(priv);
384 r->out.privs->privs = talloc_realloc(r->out.privs,
386 struct lsa_PrivEntry,
387 r->out.privs->count+1);
388 if (r->out.privs->privs == NULL) {
389 return NT_STATUS_NO_MEMORY;
391 e = &r->out.privs->privs[r->out.privs->count];
394 e->name.string = privname;
395 r->out.privs->count++;
399 *r->out.resume_handle = i;
408 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
409 struct lsa_QuerySecurity *r)
411 struct auth_session_info *session_info =
412 dcesrv_call_session_info(dce_call);
413 struct dcesrv_handle *h;
414 const struct security_descriptor *sd = NULL;
415 uint32_t access_granted = 0;
416 struct sec_desc_buf *sdbuf = NULL;
420 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
422 sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
424 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
425 struct lsa_policy_state *pstate = h->data;
428 access_granted = pstate->access_mask;
430 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
431 struct lsa_account_state *astate = h->data;
432 struct security_descriptor *_sd = NULL;
434 status = dcesrv_build_lsa_sd(mem_ctx, &_sd, sid,
435 LSA_ACCOUNT_ALL_ACCESS);
436 if (!NT_STATUS_IS_OK(status)) {
440 access_granted = astate->access_mask;
442 return NT_STATUS_INVALID_HANDLE;
445 sdbuf = talloc_zero(mem_ctx, struct sec_desc_buf);
447 return NT_STATUS_NO_MEMORY;
450 status = security_descriptor_for_client(sdbuf, sd, r->in.sec_info,
451 access_granted, &sdbuf->sd);
452 if (!NT_STATUS_IS_OK(status)) {
456 *r->out.sdbuf = sdbuf;
465 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
466 struct lsa_SetSecObj *r)
468 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
475 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
476 struct lsa_ChangePassword *r)
478 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
482 dssetup_DsRoleGetPrimaryDomainInformation
484 This is not an LSA call, but is the only call left on the DSSETUP
485 pipe (after the pipe was truncated), and needs lsa_get_policy_state
487 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
489 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
491 union dssetup_DsRoleInfo *info;
493 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
494 W_ERROR_HAVE_NO_MEMORY(info);
496 switch (r->in.level) {
497 case DS_ROLE_BASIC_INFORMATION:
499 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
501 const char *domain = NULL;
502 const char *dns_domain = NULL;
503 const char *forest = NULL;
504 struct GUID domain_guid;
505 struct lsa_policy_state *state;
507 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
508 0, /* we skip access checks */
510 if (!NT_STATUS_IS_OK(status)) {
511 return ntstatus_to_werror(status);
514 ZERO_STRUCT(domain_guid);
516 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
517 case ROLE_STANDALONE:
518 role = DS_ROLE_STANDALONE_SERVER;
520 case ROLE_DOMAIN_MEMBER:
521 role = DS_ROLE_MEMBER_SERVER;
523 case ROLE_ACTIVE_DIRECTORY_DC:
524 if (samdb_is_pdc(state->sam_ldb)) {
525 role = DS_ROLE_PRIMARY_DC;
527 role = DS_ROLE_BACKUP_DC;
532 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
533 case ROLE_STANDALONE:
534 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
535 W_ERROR_HAVE_NO_MEMORY(domain);
537 case ROLE_DOMAIN_MEMBER:
538 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
539 W_ERROR_HAVE_NO_MEMORY(domain);
540 /* TODO: what is with dns_domain and forest and guid? */
542 case ROLE_ACTIVE_DIRECTORY_DC:
543 flags = DS_ROLE_PRIMARY_DS_RUNNING;
545 if (state->mixed_domain == 1) {
546 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
549 domain = state->domain_name;
550 dns_domain = state->domain_dns;
551 forest = state->forest_dns;
553 domain_guid = state->domain_guid;
554 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
558 info->basic.role = role;
559 info->basic.flags = flags;
560 info->basic.domain = domain;
561 info->basic.dns_domain = dns_domain;
562 info->basic.forest = forest;
563 info->basic.domain_guid = domain_guid;
568 case DS_ROLE_UPGRADE_STATUS:
570 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
571 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
576 case DS_ROLE_OP_STATUS:
578 info->opstatus.status = DS_ROLE_OP_IDLE;
584 return WERR_INVALID_PARAMETER;
589 fill in the AccountDomain info
591 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
592 struct lsa_DomainInfo *info)
594 info->name.string = state->domain_name;
595 info->sid = state->domain_sid;
601 fill in the DNS domain info
603 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
604 struct lsa_DnsDomainInfo *info)
606 info->name.string = state->domain_name;
607 info->sid = state->domain_sid;
608 info->dns_domain.string = state->domain_dns;
609 info->dns_forest.string = state->forest_dns;
610 info->domain_guid = state->domain_guid;
618 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
619 struct lsa_QueryInfoPolicy2 *r)
621 struct lsa_policy_state *state;
622 struct dcesrv_handle *h;
623 union lsa_PolicyInformation *info;
627 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
631 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
633 return NT_STATUS_NO_MEMORY;
637 switch (r->in.level) {
638 case LSA_POLICY_INFO_AUDIT_LOG:
639 /* we don't need to fill in any of this */
640 ZERO_STRUCT(info->audit_log);
642 case LSA_POLICY_INFO_AUDIT_EVENTS:
643 /* we don't need to fill in any of this */
644 ZERO_STRUCT(info->audit_events);
646 case LSA_POLICY_INFO_PD:
647 /* we don't need to fill in any of this */
648 ZERO_STRUCT(info->pd);
651 case LSA_POLICY_INFO_DOMAIN:
652 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
653 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
654 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
655 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
656 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
658 case LSA_POLICY_INFO_ROLE:
659 info->role.role = LSA_ROLE_PRIMARY;
662 case LSA_POLICY_INFO_DNS:
663 case LSA_POLICY_INFO_DNS_INT:
664 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
666 case LSA_POLICY_INFO_REPLICA:
667 ZERO_STRUCT(info->replica);
670 case LSA_POLICY_INFO_QUOTA:
671 ZERO_STRUCT(info->quota);
674 case LSA_POLICY_INFO_MOD:
675 case LSA_POLICY_INFO_AUDIT_FULL_SET:
676 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
677 /* windows gives INVALID_PARAMETER */
679 return NT_STATUS_INVALID_PARAMETER;
683 return NT_STATUS_INVALID_INFO_CLASS;
689 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
690 struct lsa_QueryInfoPolicy *r)
692 struct lsa_QueryInfoPolicy2 r2;
697 r2.in.handle = r->in.handle;
698 r2.in.level = r->in.level;
699 r2.out.info = r->out.info;
701 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
709 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
710 struct lsa_SetInfoPolicy *r)
712 /* need to support this */
713 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
720 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
721 struct lsa_ClearAuditLog *r)
723 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
727 static const struct generic_mapping dcesrv_lsa_account_mapping = {
731 LSA_ACCOUNT_ALL_ACCESS
737 This call does not seem to have any long-term effects, hence no database operations
739 we need to talk to the MS product group to find out what this account database means!
741 answer is that the lsa database is totally separate from the SAM and
742 ldap databases. We are going to need a separate ldb to store these
743 accounts. The SIDs on this account bear no relation to the SIDs in
746 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
747 struct lsa_CreateAccount *r)
749 struct lsa_account_state *astate;
751 struct lsa_policy_state *state;
752 struct dcesrv_handle *h, *ah;
754 ZERO_STRUCTP(r->out.acct_handle);
756 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
760 astate = talloc(dce_call->conn, struct lsa_account_state);
761 if (astate == NULL) {
762 return NT_STATUS_NO_MEMORY;
765 astate->account_sid = dom_sid_dup(astate, r->in.sid);
766 if (astate->account_sid == NULL) {
768 return NT_STATUS_NO_MEMORY;
771 astate->policy = talloc_reference(astate, state);
772 astate->access_mask = r->in.access_mask;
775 * For now we grant all requested access.
777 * We will fail at the ldb layer later.
779 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
780 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
781 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
783 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
785 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X].\n",
786 __func__, dom_sid_string(mem_ctx, astate->account_sid),
787 (unsigned)r->in.access_mask,
788 (unsigned)astate->access_mask));
790 ah = dcesrv_handle_create(dce_call, LSA_HANDLE_ACCOUNT);
793 return NT_STATUS_NO_MEMORY;
796 ah->data = talloc_steal(ah, astate);
798 *r->out.acct_handle = ah->wire_handle;
807 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
808 struct lsa_EnumAccounts *r)
810 struct dcesrv_handle *h;
811 struct lsa_policy_state *state;
813 struct ldb_message **res;
814 const char * const attrs[] = { "objectSid", NULL};
817 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
821 /* NOTE: This call must only return accounts that have at least
824 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
825 "(&(objectSid=*)(privilege=*))");
827 return NT_STATUS_INTERNAL_DB_CORRUPTION;
830 if (*r->in.resume_handle >= ret) {
831 return NT_STATUS_NO_MORE_ENTRIES;
834 count = ret - *r->in.resume_handle;
835 if (count > r->in.num_entries) {
836 count = r->in.num_entries;
840 return NT_STATUS_NO_MORE_ENTRIES;
843 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
844 if (r->out.sids->sids == NULL) {
845 return NT_STATUS_NO_MEMORY;
848 for (i=0;i<count;i++) {
849 r->out.sids->sids[i].sid =
850 samdb_result_dom_sid(r->out.sids->sids,
851 res[i + *r->in.resume_handle],
853 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
856 r->out.sids->num_sids = count;
857 *r->out.resume_handle = count + *r->in.resume_handle;
862 /* This decrypts and returns Trusted Domain Auth Information Internal data */
863 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
864 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
865 struct trustDomainPasswords *auth_struct)
867 DATA_BLOB session_key = data_blob(NULL, 0);
868 enum ndr_err_code ndr_err;
870 gnutls_cipher_hd_t cipher_hnd = NULL;
871 gnutls_datum_t _session_key;
874 nt_status = dcesrv_transport_session_key(dce_call, &session_key);
875 if (!NT_STATUS_IS_OK(nt_status)) {
879 _session_key = (gnutls_datum_t) {
880 .data = session_key.data,
881 .size = session_key.length,
884 rc = gnutls_cipher_init(&cipher_hnd,
885 GNUTLS_CIPHER_ARCFOUR_128,
889 nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
893 rc = gnutls_cipher_encrypt(cipher_hnd,
896 gnutls_cipher_deinit(cipher_hnd);
898 nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
902 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
904 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
905 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
906 return NT_STATUS_INVALID_PARAMETER;
909 nt_status = NT_STATUS_OK;
914 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
916 struct trustAuthInOutBlob *iopw,
917 DATA_BLOB *trustauth_blob)
919 enum ndr_err_code ndr_err;
921 if (iopw->current.count != iopw->count) {
922 return NT_STATUS_INVALID_PARAMETER;
925 if (iopw->previous.count > iopw->current.count) {
926 return NT_STATUS_INVALID_PARAMETER;
929 if (iopw->previous.count == 0) {
931 * If the previous credentials are not present
932 * we need to make a copy.
934 iopw->previous = iopw->current;
937 if (iopw->previous.count < iopw->current.count) {
938 struct AuthenticationInformationArray *c = &iopw->current;
939 struct AuthenticationInformationArray *p = &iopw->previous;
942 * The previous array needs to have the same size
943 * as the current one.
945 * We may have to fill with TRUST_AUTH_TYPE_NONE
948 p->array = talloc_realloc(mem_ctx, p->array,
949 struct AuthenticationInformation,
951 if (p->array == NULL) {
952 return NT_STATUS_NO_MEMORY;
955 while (p->count < c->count) {
956 struct AuthenticationInformation *a =
957 &p->array[p->count++];
959 *a = (struct AuthenticationInformation) {
960 .LastUpdateTime = p->array[0].LastUpdateTime,
961 .AuthType = TRUST_AUTH_TYPE_NONE,
966 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
968 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
969 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
970 return NT_STATUS_INVALID_PARAMETER;
976 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
977 struct ldb_context *sam_ldb,
978 struct ldb_dn *base_dn,
979 const char *netbios_name,
980 struct trustAuthInOutBlob *in,
981 struct ldb_dn **user_dn)
983 struct ldb_request *req;
984 struct ldb_message *msg;
989 dn = ldb_dn_copy(mem_ctx, base_dn);
991 return NT_STATUS_NO_MEMORY;
993 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
994 return NT_STATUS_NO_MEMORY;
997 msg = ldb_msg_new(mem_ctx);
999 return NT_STATUS_NO_MEMORY;
1003 ret = ldb_msg_add_string(msg, "objectClass", "user");
1004 if (ret != LDB_SUCCESS) {
1005 return NT_STATUS_NO_MEMORY;
1008 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
1009 if (ret != LDB_SUCCESS) {
1010 return NT_STATUS_NO_MEMORY;
1013 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
1014 UF_INTERDOMAIN_TRUST_ACCOUNT);
1015 if (ret != LDB_SUCCESS) {
1016 return NT_STATUS_NO_MEMORY;
1019 for (i = 0; i < in->count; i++) {
1020 const char *attribute;
1022 switch (in->current.array[i].AuthType) {
1023 case TRUST_AUTH_TYPE_NT4OWF:
1024 attribute = "unicodePwd";
1025 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1028 case TRUST_AUTH_TYPE_CLEAR:
1029 attribute = "clearTextPassword";
1030 v.data = in->current.array[i].AuthInfo.clear.password;
1031 v.length = in->current.array[i].AuthInfo.clear.size;
1037 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1038 if (ret != LDB_SUCCESS) {
1039 return NT_STATUS_NO_MEMORY;
1043 /* create the trusted_domain user account */
1044 ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
1045 ldb_op_default_callback, NULL);
1046 if (ret != LDB_SUCCESS) {
1047 return NT_STATUS_NO_MEMORY;
1050 ret = ldb_request_add_control(req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
1052 if (ret != LDB_SUCCESS) {
1053 return NT_STATUS_NO_MEMORY;
1056 ret = dsdb_autotransaction_request(sam_ldb, req);
1057 if (ret != LDB_SUCCESS) {
1058 DEBUG(0,("Failed to create user record %s: %s\n",
1059 ldb_dn_get_linearized(msg->dn),
1060 ldb_errstring(sam_ldb)));
1063 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1064 return NT_STATUS_DOMAIN_EXISTS;
1065 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1066 return NT_STATUS_ACCESS_DENIED;
1068 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1075 return NT_STATUS_OK;
1079 lsa_CreateTrustedDomainEx2
1081 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
1082 TALLOC_CTX *mem_ctx,
1083 struct lsa_CreateTrustedDomainEx2 *r,
1085 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
1087 struct dcesrv_handle *policy_handle;
1088 struct lsa_policy_state *policy_state;
1089 struct lsa_trusted_domain_state *trusted_domain_state;
1090 struct dcesrv_handle *handle;
1091 struct ldb_message **msgs, *msg;
1092 const char *attrs[] = {
1095 const char *netbios_name;
1096 const char *dns_name;
1097 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1098 struct trustDomainPasswords auth_struct;
1101 struct ldb_context *sam_ldb;
1102 struct server_id *server_ids = NULL;
1103 uint32_t num_server_ids = 0;
1106 char *dns_encoded = NULL;
1107 char *netbios_encoded = NULL;
1108 char *sid_encoded = NULL;
1109 struct imessaging_context *imsg_ctx =
1110 dcesrv_imessaging_context(dce_call->conn);
1112 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
1113 ZERO_STRUCTP(r->out.trustdom_handle);
1115 policy_state = policy_handle->data;
1116 sam_ldb = policy_state->sam_ldb;
1118 netbios_name = r->in.info->netbios_name.string;
1119 if (!netbios_name) {
1120 return NT_STATUS_INVALID_PARAMETER;
1123 dns_name = r->in.info->domain_name.string;
1124 if (dns_name == NULL) {
1125 return NT_STATUS_INVALID_PARAMETER;
1128 if (r->in.info->sid == NULL) {
1129 return NT_STATUS_INVALID_SID;
1133 * We expect S-1-5-21-A-B-C, but we don't
1134 * allow S-1-5-21-0-0-0 as this is used
1135 * for claims and compound identities.
1137 ok = dom_sid_is_valid_account_domain(r->in.info->sid);
1139 return NT_STATUS_INVALID_PARAMETER;
1142 dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1143 if (dns_encoded == NULL) {
1144 return NT_STATUS_NO_MEMORY;
1146 netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1147 if (netbios_encoded == NULL) {
1148 return NT_STATUS_NO_MEMORY;
1150 sid_encoded = ldap_encode_ndr_dom_sid(mem_ctx, r->in.info->sid);
1151 if (sid_encoded == NULL) {
1152 return NT_STATUS_NO_MEMORY;
1155 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1156 if (!trusted_domain_state) {
1157 return NT_STATUS_NO_MEMORY;
1159 trusted_domain_state->policy = policy_state;
1161 if (strcasecmp(netbios_name, "BUILTIN") == 0
1162 || (strcasecmp(dns_name, "BUILTIN") == 0)
1163 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
1164 return NT_STATUS_INVALID_PARAMETER;
1167 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
1168 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
1169 || strcasecmp(dns_name, policy_state->domain_dns) == 0
1170 || strcasecmp(dns_name, policy_state->domain_name) == 0
1171 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
1172 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
1175 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
1176 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
1177 /* No secrets are created at this time, for this function */
1178 auth_struct.outgoing.count = 0;
1179 auth_struct.incoming.count = 0;
1180 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
1181 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
1182 r->in.auth_info_internal->auth_blob.size);
1183 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1184 &auth_blob, &auth_struct);
1185 if (!NT_STATUS_IS_OK(nt_status)) {
1188 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
1190 if (unencrypted_auth_info->incoming_count > 1) {
1191 return NT_STATUS_INVALID_PARAMETER;
1194 /* more investigation required here, do not create secrets for
1196 auth_struct.outgoing.count = 0;
1197 auth_struct.incoming.count = 0;
1199 return NT_STATUS_INVALID_PARAMETER;
1202 if (auth_struct.incoming.count) {
1203 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1204 &auth_struct.incoming,
1205 &trustAuthIncoming);
1206 if (!NT_STATUS_IS_OK(nt_status)) {
1210 trustAuthIncoming = data_blob(NULL, 0);
1213 if (auth_struct.outgoing.count) {
1214 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1215 &auth_struct.outgoing,
1216 &trustAuthOutgoing);
1217 if (!NT_STATUS_IS_OK(nt_status)) {
1221 trustAuthOutgoing = data_blob(NULL, 0);
1224 ret = ldb_transaction_start(sam_ldb);
1225 if (ret != LDB_SUCCESS) {
1226 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1229 /* search for the trusted_domain record */
1230 ret = gendb_search(sam_ldb,
1231 mem_ctx, policy_state->system_dn, &msgs, attrs,
1232 "(&(objectClass=trustedDomain)(|"
1233 "(flatname=%s)(trustPartner=%s)"
1234 "(flatname=%s)(trustPartner=%s)"
1235 "(securityIdentifier=%s)))",
1236 dns_encoded, dns_encoded,
1237 netbios_encoded, netbios_encoded,
1240 ldb_transaction_cancel(sam_ldb);
1241 return NT_STATUS_OBJECT_NAME_COLLISION;
1244 ldb_transaction_cancel(sam_ldb);
1245 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1248 msg = ldb_msg_new(mem_ctx);
1250 return NT_STATUS_NO_MEMORY;
1253 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1254 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", dns_name)) {
1255 ldb_transaction_cancel(sam_ldb);
1256 return NT_STATUS_NO_MEMORY;
1259 ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1260 if (ret != LDB_SUCCESS) {
1261 ldb_transaction_cancel(sam_ldb);
1262 return NT_STATUS_NO_MEMORY;;
1265 ret = ldb_msg_add_string(msg, "flatname", netbios_name);
1266 if (ret != LDB_SUCCESS) {
1267 ldb_transaction_cancel(sam_ldb);
1268 return NT_STATUS_NO_MEMORY;
1271 ret = ldb_msg_add_string(msg, "trustPartner", dns_name);
1272 if (ret != LDB_SUCCESS) {
1273 ldb_transaction_cancel(sam_ldb);
1274 return NT_STATUS_NO_MEMORY;;
1277 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier",
1279 if (ret != LDB_SUCCESS) {
1280 ldb_transaction_cancel(sam_ldb);
1281 return NT_STATUS_NO_MEMORY;;
1284 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1285 if (ret != LDB_SUCCESS) {
1286 ldb_transaction_cancel(sam_ldb);
1287 return NT_STATUS_NO_MEMORY;;
1290 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1291 if (ret != LDB_SUCCESS) {
1292 ldb_transaction_cancel(sam_ldb);
1293 return NT_STATUS_NO_MEMORY;;
1296 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1297 if (ret != LDB_SUCCESS) {
1298 ldb_transaction_cancel(sam_ldb);
1299 return NT_STATUS_NO_MEMORY;;
1302 if (trustAuthIncoming.data) {
1303 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1304 if (ret != LDB_SUCCESS) {
1305 ldb_transaction_cancel(sam_ldb);
1306 return NT_STATUS_NO_MEMORY;
1309 if (trustAuthOutgoing.data) {
1310 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1311 if (ret != LDB_SUCCESS) {
1312 ldb_transaction_cancel(sam_ldb);
1313 return NT_STATUS_NO_MEMORY;
1317 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1319 /* create the trusted_domain */
1320 ret = ldb_add(sam_ldb, msg);
1324 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1325 ldb_transaction_cancel(sam_ldb);
1326 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1327 ldb_dn_get_linearized(msg->dn),
1328 ldb_errstring(sam_ldb)));
1329 return NT_STATUS_DOMAIN_EXISTS;
1330 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1331 ldb_transaction_cancel(sam_ldb);
1332 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1333 ldb_dn_get_linearized(msg->dn),
1334 ldb_errstring(sam_ldb)));
1335 return NT_STATUS_ACCESS_DENIED;
1337 ldb_transaction_cancel(sam_ldb);
1338 DEBUG(0,("Failed to create user record %s: %s\n",
1339 ldb_dn_get_linearized(msg->dn),
1340 ldb_errstring(sam_ldb)));
1341 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1344 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1345 struct ldb_dn *user_dn;
1346 /* Inbound trusts must also create a cn=users object to match */
1347 nt_status = add_trust_user(mem_ctx, sam_ldb,
1348 policy_state->domain_dn,
1350 &auth_struct.incoming,
1352 if (!NT_STATUS_IS_OK(nt_status)) {
1353 ldb_transaction_cancel(sam_ldb);
1357 /* save the trust user dn */
1358 trusted_domain_state->trusted_domain_user_dn
1359 = talloc_steal(trusted_domain_state, user_dn);
1362 ret = ldb_transaction_commit(sam_ldb);
1363 if (ret != LDB_SUCCESS) {
1364 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1368 * Notify winbindd that we have a new trust
1370 status = irpc_servers_byname(imsg_ctx,
1375 if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
1376 imessaging_send(imsg_ctx,
1378 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1381 TALLOC_FREE(server_ids);
1383 handle = dcesrv_handle_create(dce_call, LSA_HANDLE_TRUSTED_DOMAIN);
1385 return NT_STATUS_NO_MEMORY;
1388 handle->data = talloc_steal(handle, trusted_domain_state);
1390 trusted_domain_state->access_mask = r->in.access_mask;
1391 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1393 *r->out.trustdom_handle = handle->wire_handle;
1395 return NT_STATUS_OK;
1399 lsa_CreateTrustedDomainEx2
1401 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1402 TALLOC_CTX *mem_ctx,
1403 struct lsa_CreateTrustedDomainEx2 *r)
1405 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1408 lsa_CreateTrustedDomainEx
1410 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1411 TALLOC_CTX *mem_ctx,
1412 struct lsa_CreateTrustedDomainEx *r)
1414 struct lsa_CreateTrustedDomainEx2 r2;
1416 r2.in.policy_handle = r->in.policy_handle;
1417 r2.in.info = r->in.info;
1418 r2.out.trustdom_handle = r->out.trustdom_handle;
1419 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1423 lsa_CreateTrustedDomain
1425 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1426 struct lsa_CreateTrustedDomain *r)
1428 struct lsa_CreateTrustedDomainEx2 r2;
1430 r2.in.policy_handle = r->in.policy_handle;
1431 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1433 return NT_STATUS_NO_MEMORY;
1436 r2.in.info->domain_name = r->in.info->name;
1437 r2.in.info->netbios_name = r->in.info->name;
1438 r2.in.info->sid = r->in.info->sid;
1439 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1440 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1441 r2.in.info->trust_attributes = 0;
1443 r2.in.access_mask = r->in.access_mask;
1444 r2.out.trustdom_handle = r->out.trustdom_handle;
1446 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1449 static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
1450 struct dcesrv_call_state *dce_call,
1451 TALLOC_CTX *tmp_mem,
1452 struct lsa_policy_state *policy_state,
1454 uint32_t access_mask,
1455 struct dcesrv_handle **_handle)
1457 struct lsa_trusted_domain_state *trusted_domain_state;
1458 struct dcesrv_handle *handle;
1459 struct ldb_message **msgs;
1460 const char *attrs[] = {
1468 /* TODO: perform access checks */
1470 /* search for the trusted_domain record */
1471 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1472 policy_state->system_dn,
1473 &msgs, attrs, "%s", filter);
1475 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1479 DEBUG(0,("Found %d records matching %s under %s\n", ret,
1481 ldb_dn_get_linearized(policy_state->system_dn)));
1482 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1485 trusted_domain_state = talloc_zero(tmp_mem,
1486 struct lsa_trusted_domain_state);
1487 if (!trusted_domain_state) {
1488 return NT_STATUS_NO_MEMORY;
1490 trusted_domain_state->policy = policy_state;
1492 trusted_domain_state->trusted_domain_dn =
1493 talloc_steal(trusted_domain_state, msgs[0]->dn);
1495 direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1496 if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1497 const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1500 /* search for the trusted_domain account */
1501 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1502 policy_state->domain_dn,
1504 "(&(samaccountname=%s$)(objectclass=user)"
1505 "(userAccountControl:%s:=%u))",
1507 LDB_OID_COMPARATOR_AND,
1508 UF_INTERDOMAIN_TRUST_ACCOUNT);
1510 trusted_domain_state->trusted_domain_user_dn =
1511 talloc_steal(trusted_domain_state, msgs[0]->dn);
1515 handle = dcesrv_handle_create(dce_call, LSA_HANDLE_TRUSTED_DOMAIN);
1517 return NT_STATUS_NO_MEMORY;
1520 handle->data = talloc_steal(handle, trusted_domain_state);
1522 trusted_domain_state->access_mask = access_mask;
1523 trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1528 return NT_STATUS_OK;
1532 lsa_OpenTrustedDomain
1534 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1535 struct lsa_OpenTrustedDomain *r)
1537 struct dcesrv_handle *policy_handle;
1538 struct lsa_policy_state *policy_state;
1539 struct dcesrv_handle *handle;
1540 const char *sid_string;
1544 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1545 ZERO_STRUCTP(r->out.trustdom_handle);
1546 policy_state = policy_handle->data;
1548 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1550 return NT_STATUS_NO_MEMORY;
1553 filter = talloc_asprintf(mem_ctx,
1554 "(&(securityIdentifier=%s)"
1555 "(objectclass=trustedDomain))",
1557 if (filter == NULL) {
1558 return NT_STATUS_NO_MEMORY;
1561 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1566 if (!NT_STATUS_IS_OK(status)) {
1570 *r->out.trustdom_handle = handle->wire_handle;
1572 return NT_STATUS_OK;
1577 lsa_OpenTrustedDomainByName
1579 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1580 TALLOC_CTX *mem_ctx,
1581 struct lsa_OpenTrustedDomainByName *r)
1583 struct dcesrv_handle *policy_handle;
1584 struct lsa_policy_state *policy_state;
1585 struct dcesrv_handle *handle;
1590 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1591 ZERO_STRUCTP(r->out.trustdom_handle);
1592 policy_state = policy_handle->data;
1594 if (!r->in.name.string) {
1595 return NT_STATUS_INVALID_PARAMETER;
1598 /* search for the trusted_domain record */
1599 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1600 if (td_name == NULL) {
1601 return NT_STATUS_NO_MEMORY;
1604 filter = talloc_asprintf(mem_ctx,
1605 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1606 "(objectclass=trustedDomain))",
1607 td_name, td_name, td_name);
1608 if (filter == NULL) {
1609 return NT_STATUS_NO_MEMORY;
1612 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1617 if (!NT_STATUS_IS_OK(status)) {
1621 *r->out.trustdom_handle = handle->wire_handle;
1623 return NT_STATUS_OK;
1629 lsa_SetTrustedDomainInfo
1631 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1632 struct lsa_SetTrustedDomainInfo *r)
1634 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1639 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1640 * otherwise at least one must be provided */
1641 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1642 struct ldb_dn *basedn, const char *dns_domain,
1643 const char *netbios, struct dom_sid2 *sid,
1644 struct ldb_message ***msgs)
1646 const char *attrs[] = { "flatname", "trustPartner",
1647 "securityIdentifier", "trustDirection",
1648 "trustType", "trustAttributes",
1650 "msDs-supportedEncryptionTypes",
1651 "msDS-TrustForestTrustInfo",
1656 char *sidstr = NULL;
1661 if (dns_domain || netbios || sid) {
1662 filter = talloc_strdup(mem_ctx,
1663 "(&(objectclass=trustedDomain)(|");
1665 filter = talloc_strdup(mem_ctx,
1666 "(objectclass=trustedDomain)");
1669 return NT_STATUS_NO_MEMORY;
1673 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1675 return NT_STATUS_NO_MEMORY;
1677 filter = talloc_asprintf_append(filter,
1678 "(trustPartner=%s)", dns);
1680 return NT_STATUS_NO_MEMORY;
1684 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1686 return NT_STATUS_NO_MEMORY;
1688 filter = talloc_asprintf_append(filter,
1689 "(flatname=%s)", nbn);
1691 return NT_STATUS_NO_MEMORY;
1695 sidstr = dom_sid_string(mem_ctx, sid);
1697 return NT_STATUS_INVALID_PARAMETER;
1699 filter = talloc_asprintf_append(filter,
1700 "(securityIdentifier=%s)",
1703 return NT_STATUS_NO_MEMORY;
1706 if (dns_domain || netbios || sid) {
1707 filter = talloc_asprintf_append(filter, "))");
1709 return NT_STATUS_NO_MEMORY;
1713 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1715 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1719 return NT_STATUS_OBJECT_NAME_COLLISION;
1722 return NT_STATUS_OK;
1725 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1726 struct ldb_context *sam_ldb,
1727 struct ldb_message *orig,
1728 struct ldb_message *dest,
1729 const char *attribute,
1731 uint32_t *orig_value)
1733 const struct ldb_val *orig_val;
1734 uint32_t orig_uint = 0;
1735 unsigned int flags = 0;
1739 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1740 if (!orig_val || !orig_val->data) {
1741 /* add new attribute */
1742 flags = LDB_FLAG_MOD_ADD;
1745 orig_uint = smb_strtoul((const char *)orig_val->data,
1750 if (error != 0 || orig_uint != value) {
1751 /* replace also if can't get value */
1752 flags = LDB_FLAG_MOD_REPLACE;
1757 /* stored value is identical, nothing to change */
1761 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1762 if (ret != LDB_SUCCESS) {
1763 return NT_STATUS_NO_MEMORY;
1766 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1767 if (ret != LDB_SUCCESS) {
1768 return NT_STATUS_NO_MEMORY;
1773 *orig_value = orig_uint;
1775 return NT_STATUS_OK;
1778 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1779 struct ldb_context *sam_ldb,
1780 struct ldb_dn *base_dn,
1782 const char *netbios_name,
1783 struct trustAuthInOutBlob *in)
1785 const char *attrs[] = { "userAccountControl", NULL };
1786 struct ldb_message **msgs;
1787 struct ldb_message *msg;
1792 ret = gendb_search(sam_ldb, mem_ctx,
1793 base_dn, &msgs, attrs,
1794 "samAccountName=%s$", netbios_name);
1796 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1801 return NT_STATUS_OK;
1804 /* ok no existing user, add it from scratch */
1805 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1806 netbios_name, in, NULL);
1809 /* check user is what we are looking for */
1810 uac = ldb_msg_find_attr_as_uint(msgs[0],
1811 "userAccountControl", 0);
1812 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1813 return NT_STATUS_OBJECT_NAME_COLLISION;
1817 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1820 return NT_STATUS_OK;
1821 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1822 return NT_STATUS_ACCESS_DENIED;
1824 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1828 /* entry exists, just modify secret if any */
1829 if (in == NULL || in->count == 0) {
1830 return NT_STATUS_OK;
1833 msg = ldb_msg_new(mem_ctx);
1835 return NT_STATUS_NO_MEMORY;
1837 msg->dn = msgs[0]->dn;
1839 for (i = 0; i < in->count; i++) {
1840 const char *attribute;
1842 switch (in->current.array[i].AuthType) {
1843 case TRUST_AUTH_TYPE_NT4OWF:
1844 attribute = "unicodePwd";
1845 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1848 case TRUST_AUTH_TYPE_CLEAR:
1849 attribute = "clearTextPassword";
1850 v.data = in->current.array[i].AuthInfo.clear.password;
1851 v.length = in->current.array[i].AuthInfo.clear.size;
1857 ret = ldb_msg_add_empty(msg, attribute,
1858 LDB_FLAG_MOD_REPLACE, NULL);
1859 if (ret != LDB_SUCCESS) {
1860 return NT_STATUS_NO_MEMORY;
1863 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1864 if (ret != LDB_SUCCESS) {
1865 return NT_STATUS_NO_MEMORY;
1869 /* create the trusted_domain user account */
1870 ret = ldb_modify(sam_ldb, msg);
1871 if (ret != LDB_SUCCESS) {
1872 DEBUG(0,("Failed to create user record %s: %s\n",
1873 ldb_dn_get_linearized(msg->dn),
1874 ldb_errstring(sam_ldb)));
1877 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1878 return NT_STATUS_DOMAIN_EXISTS;
1879 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1880 return NT_STATUS_ACCESS_DENIED;
1882 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1886 return NT_STATUS_OK;
1890 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1891 struct lsa_policy_state *p_state,
1892 TALLOC_CTX *mem_ctx,
1893 struct ldb_message *dom_msg,
1894 enum lsa_TrustDomInfoEnum level,
1895 union lsa_TrustedDomainInfo *info)
1897 uint32_t *posix_offset = NULL;
1898 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1899 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1900 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1901 uint32_t *enc_types = NULL;
1902 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1903 struct trustDomainPasswords auth_struct;
1904 struct trustAuthInOutBlob *current_passwords = NULL;
1906 struct ldb_message **msgs;
1907 struct ldb_message *msg;
1908 bool add_outgoing = false;
1909 bool add_incoming = false;
1910 bool del_outgoing = false;
1911 bool del_incoming = false;
1912 bool del_forest_info = false;
1913 bool in_transaction = false;
1918 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1919 posix_offset = &info->posix_offset.posix_offset;
1921 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1922 info_ex = &info->info_ex;
1924 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1925 auth_info = &info->auth_info;
1927 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1928 posix_offset = &info->full_info.posix_offset.posix_offset;
1929 info_ex = &info->full_info.info_ex;
1930 auth_info = &info->full_info.auth_info;
1932 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1933 auth_info_int = &info->auth_info_internal;
1935 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1936 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1937 info_ex = &info->full_info_internal.info_ex;
1938 auth_info_int = &info->full_info_internal.auth_info;
1940 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1941 enc_types = &info->enc_types.enc_types;
1944 return NT_STATUS_INVALID_PARAMETER;
1948 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1950 &trustAuthOutgoing);
1951 if (!NT_STATUS_IS_OK(nt_status)) {
1954 if (trustAuthIncoming.data) {
1955 /* This does the decode of some of this twice, but it is easier that way */
1956 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1957 auth_info->incoming_count,
1958 auth_info->incoming_current_auth_info,
1960 ¤t_passwords);
1961 if (!NT_STATUS_IS_OK(nt_status)) {
1967 /* decode auth_info_int if set */
1968 if (auth_info_int) {
1970 /* now decrypt blob */
1971 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1972 auth_info_int->auth_blob.size);
1974 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1975 &auth_blob, &auth_struct);
1976 if (!NT_STATUS_IS_OK(nt_status)) {
1982 /* verify data matches */
1983 if (info_ex->trust_attributes &
1984 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1985 /* TODO: check what behavior level we have */
1986 if (strcasecmp_m(p_state->domain_dns,
1987 p_state->forest_dns) != 0) {
1988 return NT_STATUS_INVALID_DOMAIN_STATE;
1992 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1993 if (ret == LDB_SUCCESS && am_rodc) {
1994 return NT_STATUS_NO_SUCH_DOMAIN;
1997 /* verify only one object matches the dns/netbios/sid
1998 * triplet and that this is the one we already have */
1999 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
2001 info_ex->domain_name.string,
2002 info_ex->netbios_name.string,
2003 info_ex->sid, &msgs);
2004 if (!NT_STATUS_IS_OK(nt_status)) {
2007 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
2008 return NT_STATUS_OBJECT_NAME_COLLISION;
2013 /* TODO: should we fetch previous values from the existing entry
2014 * and append them ? */
2015 if (auth_info_int && auth_struct.incoming.count) {
2016 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
2017 &auth_struct.incoming,
2018 &trustAuthIncoming);
2019 if (!NT_STATUS_IS_OK(nt_status)) {
2023 current_passwords = &auth_struct.incoming;
2026 trustAuthIncoming = data_blob(NULL, 0);
2029 if (auth_info_int && auth_struct.outgoing.count) {
2030 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
2031 &auth_struct.outgoing,
2032 &trustAuthOutgoing);
2033 if (!NT_STATUS_IS_OK(nt_status)) {
2037 trustAuthOutgoing = data_blob(NULL, 0);
2040 msg = ldb_msg_new(mem_ctx);
2042 return NT_STATUS_NO_MEMORY;
2044 msg->dn = dom_msg->dn;
2047 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2050 *posix_offset, NULL);
2051 if (!NT_STATUS_IS_OK(nt_status)) {
2058 uint32_t changed_attrs;
2062 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2065 info_ex->trust_direction,
2067 if (!NT_STATUS_IS_OK(nt_status)) {
2071 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2072 if (auth_info != NULL && trustAuthIncoming.length > 0) {
2073 add_incoming = true;
2076 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2077 if (auth_info != NULL && trustAuthOutgoing.length > 0) {
2078 add_outgoing = true;
2082 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
2083 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
2084 del_incoming = true;
2086 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
2087 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2088 del_outgoing = true;
2091 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
2092 if (origtype == -1 || origtype != info_ex->trust_type) {
2093 DEBUG(1, ("Attempted to change trust type! "
2094 "Operation not handled\n"));
2095 return NT_STATUS_INVALID_PARAMETER;
2098 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2101 info_ex->trust_attributes,
2103 if (!NT_STATUS_IS_OK(nt_status)) {
2106 /* TODO: check forestFunctionality from ldb opaque */
2107 /* TODO: check what is set makes sense */
2109 changed_attrs = origattrs ^ info_ex->trust_attributes;
2110 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2112 * For now we only allow
2113 * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
2115 * TODO: we may need to support more attribute changes
2117 DEBUG(1, ("Attempted to change trust attributes "
2118 "(0x%08x != 0x%08x)! "
2119 "Operation not handled yet...\n",
2120 (unsigned)origattrs,
2121 (unsigned)info_ex->trust_attributes));
2122 return NT_STATUS_INVALID_PARAMETER;
2125 if (!(info_ex->trust_attributes &
2126 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
2128 struct ldb_message_element *orig_forest_el = NULL;
2130 orig_forest_el = ldb_msg_find_element(dom_msg,
2131 "msDS-TrustForestTrustInfo");
2132 if (orig_forest_el != NULL) {
2133 del_forest_info = true;
2139 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2141 "msDS-SupportedEncryptionTypes",
2143 if (!NT_STATUS_IS_OK(nt_status)) {
2148 if (add_incoming || del_incoming) {
2149 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
2150 LDB_FLAG_MOD_REPLACE, NULL);
2151 if (ret != LDB_SUCCESS) {
2152 return NT_STATUS_NO_MEMORY;
2155 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
2156 &trustAuthIncoming, NULL);
2157 if (ret != LDB_SUCCESS) {
2158 return NT_STATUS_NO_MEMORY;
2162 if (add_outgoing || del_outgoing) {
2163 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2164 LDB_FLAG_MOD_REPLACE, NULL);
2165 if (ret != LDB_SUCCESS) {
2166 return NT_STATUS_NO_MEMORY;
2169 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
2170 &trustAuthOutgoing, NULL);
2171 if (ret != LDB_SUCCESS) {
2172 return NT_STATUS_NO_MEMORY;
2176 if (del_forest_info) {
2177 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
2178 LDB_FLAG_MOD_REPLACE, NULL);
2179 if (ret != LDB_SUCCESS) {
2180 return NT_STATUS_NO_MEMORY;
2184 /* start transaction */
2185 ret = ldb_transaction_start(p_state->sam_ldb);
2186 if (ret != LDB_SUCCESS) {
2187 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2189 in_transaction = true;
2191 if (msg->num_elements) {
2192 ret = ldb_modify(p_state->sam_ldb, msg);
2193 if (ret != LDB_SUCCESS) {
2194 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
2195 ldb_dn_get_linearized(msg->dn),
2196 ldb_errstring(p_state->sam_ldb)));
2197 nt_status = dsdb_ldb_err_to_ntstatus(ret);
2202 if (add_incoming || del_incoming) {
2203 const char *netbios_name;
2205 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
2207 if (!netbios_name) {
2208 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
2212 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
2213 nt_status = update_trust_user(mem_ctx,
2219 if (!NT_STATUS_IS_OK(nt_status)) {
2224 /* ok, all fine, commit transaction and return */
2225 ret = ldb_transaction_commit(p_state->sam_ldb);
2226 if (ret != LDB_SUCCESS) {
2227 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2229 in_transaction = false;
2231 nt_status = NT_STATUS_OK;
2234 if (in_transaction) {
2235 ldb_transaction_cancel(p_state->sam_ldb);
2241 lsa_SetInfomrationTrustedDomain
2243 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
2244 struct dcesrv_call_state *dce_call,
2245 TALLOC_CTX *mem_ctx,
2246 struct lsa_SetInformationTrustedDomain *r)
2248 struct dcesrv_handle *h;
2249 struct lsa_trusted_domain_state *td_state;
2250 struct ldb_message **msgs;
2253 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
2254 LSA_HANDLE_TRUSTED_DOMAIN);
2256 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2258 /* get the trusted domain object */
2259 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
2260 td_state->trusted_domain_dn,
2261 NULL, NULL, NULL, &msgs);
2262 if (!NT_STATUS_IS_OK(nt_status)) {
2263 if (NT_STATUS_EQUAL(nt_status,
2264 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2267 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2270 return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
2271 msgs[0], r->in.level, r->in.info);
2276 lsa_DeleteTrustedDomain
2278 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2279 struct lsa_DeleteTrustedDomain *r)
2282 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2283 struct lsa_DeleteObject del;
2284 struct dcesrv_handle *h;
2286 opn.in.handle = r->in.handle;
2287 opn.in.sid = r->in.dom_sid;
2288 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2289 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2290 if (!opn.out.trustdom_handle) {
2291 return NT_STATUS_NO_MEMORY;
2293 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2294 if (!NT_STATUS_IS_OK(status)) {
2298 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2299 talloc_steal(mem_ctx, h);
2301 del.in.handle = opn.out.trustdom_handle;
2302 del.out.handle = opn.out.trustdom_handle;
2303 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2304 if (!NT_STATUS_IS_OK(status)) {
2307 return NT_STATUS_OK;
2310 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2311 struct ldb_message *msg,
2312 struct lsa_TrustDomainInfoInfoEx *info_ex)
2314 info_ex->domain_name.string
2315 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2316 info_ex->netbios_name.string
2317 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2319 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2320 info_ex->trust_direction
2321 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2323 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2324 info_ex->trust_attributes
2325 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2326 return NT_STATUS_OK;
2330 lsa_QueryTrustedDomainInfo
2332 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2333 struct lsa_QueryTrustedDomainInfo *r)
2335 union lsa_TrustedDomainInfo *info = NULL;
2336 struct dcesrv_handle *h;
2337 struct lsa_trusted_domain_state *trusted_domain_state;
2338 struct ldb_message *msg;
2340 struct ldb_message **res;
2341 const char *attrs[] = {
2344 "securityIdentifier",
2348 "msDs-supportedEncryptionTypes",
2352 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2354 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2356 /* pull all the user attributes */
2357 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2358 trusted_domain_state->trusted_domain_dn, &res, attrs);
2360 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2364 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2366 return NT_STATUS_NO_MEMORY;
2368 *r->out.info = info;
2370 switch (r->in.level) {
2371 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2372 info->name.netbios_name.string
2373 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2375 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2376 info->posix_offset.posix_offset
2377 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2379 #if 0 /* Win2k3 doesn't implement this */
2380 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2381 r->out.info->info_basic.netbios_name.string
2382 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2383 r->out.info->info_basic.sid
2384 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2387 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2388 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2390 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2391 ZERO_STRUCT(info->full_info);
2392 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2393 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2394 ZERO_STRUCT(info->full_info2_internal);
2395 info->full_info2_internal.posix_offset.posix_offset
2396 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2397 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2399 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2400 info->enc_types.enc_types
2401 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2404 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2405 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2406 /* oops, we don't want to return the info after all */
2408 *r->out.info = NULL;
2409 return NT_STATUS_INVALID_PARAMETER;
2411 /* oops, we don't want to return the info after all */
2413 *r->out.info = NULL;
2414 return NT_STATUS_INVALID_INFO_CLASS;
2417 return NT_STATUS_OK;
2422 lsa_QueryTrustedDomainInfoBySid
2424 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2425 struct lsa_QueryTrustedDomainInfoBySid *r)
2428 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2429 struct lsa_QueryTrustedDomainInfo query;
2430 struct dcesrv_handle *h;
2432 opn.in.handle = r->in.handle;
2433 opn.in.sid = r->in.dom_sid;
2434 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2435 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2436 if (!opn.out.trustdom_handle) {
2437 return NT_STATUS_NO_MEMORY;
2439 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2440 if (!NT_STATUS_IS_OK(status)) {
2444 /* Ensure this handle goes away at the end of this call */
2445 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2446 talloc_steal(mem_ctx, h);
2448 query.in.trustdom_handle = opn.out.trustdom_handle;
2449 query.in.level = r->in.level;
2450 query.out.info = r->out.info;
2451 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2452 if (!NT_STATUS_IS_OK(status)) {
2456 return NT_STATUS_OK;
2460 lsa_SetTrustedDomainInfoByName
2462 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2463 TALLOC_CTX *mem_ctx,
2464 struct lsa_SetTrustedDomainInfoByName *r)
2466 struct dcesrv_handle *policy_handle;
2467 struct lsa_policy_state *policy_state;
2468 struct ldb_message **msgs;
2471 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2472 policy_state = policy_handle->data;
2474 /* get the trusted domain object */
2475 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2476 policy_state->domain_dn,
2477 r->in.trusted_domain->string,
2478 r->in.trusted_domain->string,
2480 if (!NT_STATUS_IS_OK(nt_status)) {
2481 if (NT_STATUS_EQUAL(nt_status,
2482 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2485 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2488 return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2489 msgs[0], r->in.level, r->in.info);
2493 lsa_QueryTrustedDomainInfoByName
2495 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2496 TALLOC_CTX *mem_ctx,
2497 struct lsa_QueryTrustedDomainInfoByName *r)
2500 struct lsa_OpenTrustedDomainByName opn = {{0},{0}};
2501 struct lsa_QueryTrustedDomainInfo query;
2502 struct dcesrv_handle *h;
2504 opn.in.handle = r->in.handle;
2505 opn.in.name = *r->in.trusted_domain;
2506 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2507 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2508 if (!opn.out.trustdom_handle) {
2509 return NT_STATUS_NO_MEMORY;
2511 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2512 if (!NT_STATUS_IS_OK(status)) {
2516 /* Ensure this handle goes away at the end of this call */
2517 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2518 talloc_steal(mem_ctx, h);
2520 query.in.trustdom_handle = opn.out.trustdom_handle;
2521 query.in.level = r->in.level;
2522 query.out.info = r->out.info;
2523 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2524 if (!NT_STATUS_IS_OK(status)) {
2528 return NT_STATUS_OK;
2532 lsa_CloseTrustedDomainEx
2534 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2535 TALLOC_CTX *mem_ctx,
2536 struct lsa_CloseTrustedDomainEx *r)
2538 /* The result of a bad hair day from an IDL programmer? Not
2539 * implmented in Win2k3. You should always just lsa_Close
2541 return NT_STATUS_NOT_IMPLEMENTED;
2546 comparison function for sorting lsa_DomainInformation array
2548 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2550 return strcasecmp_m(e1->name.string, e2->name.string);
2556 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2557 struct lsa_EnumTrustDom *r)
2559 struct dcesrv_handle *policy_handle;
2560 struct lsa_DomainInfo *entries;
2561 struct lsa_policy_state *policy_state;
2562 struct ldb_message **domains;
2563 const char *attrs[] = {
2565 "securityIdentifier",
2572 *r->out.resume_handle = 0;
2574 r->out.domains->domains = NULL;
2575 r->out.domains->count = 0;
2577 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2579 policy_state = policy_handle->data;
2581 /* search for all users in this domain. This could possibly be cached and
2582 resumed based on resume_key */
2583 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2584 "objectclass=trustedDomain");
2586 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2589 /* convert to lsa_TrustInformation format */
2590 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2592 return NT_STATUS_NO_MEMORY;
2594 for (i=0;i<count;i++) {
2595 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2596 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2599 /* sort the results by name */
2600 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2602 if (*r->in.resume_handle >= count) {
2603 *r->out.resume_handle = -1;
2605 return NT_STATUS_NO_MORE_ENTRIES;
2608 /* return the rest, limit by max_size. Note that we
2609 use the w2k3 element size value of 60 */
2610 r->out.domains->count = count - *r->in.resume_handle;
2611 r->out.domains->count = MIN(r->out.domains->count,
2612 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2614 r->out.domains->domains = entries + *r->in.resume_handle;
2616 if (r->out.domains->count < count - *r->in.resume_handle) {
2617 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2618 return STATUS_MORE_ENTRIES;
2621 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2622 * always be larger than the previous input resume handle, in
2623 * particular when hitting the last query it is vital to set the
2624 * resume handle correctly to avoid infinite client loops, as
2625 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2626 * status is NT_STATUS_OK - gd */
2628 *r->out.resume_handle = (uint32_t)-1;
2630 return NT_STATUS_OK;
2634 comparison function for sorting lsa_DomainInformation array
2636 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2638 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2642 lsa_EnumTrustedDomainsEx
2644 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2645 struct lsa_EnumTrustedDomainsEx *r)
2647 struct dcesrv_handle *policy_handle;
2648 struct lsa_TrustDomainInfoInfoEx *entries;
2649 struct lsa_policy_state *policy_state;
2650 struct ldb_message **domains;
2651 const char *attrs[] = {
2654 "securityIdentifier",
2664 *r->out.resume_handle = 0;
2666 r->out.domains->domains = NULL;
2667 r->out.domains->count = 0;
2669 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2671 policy_state = policy_handle->data;
2673 /* search for all users in this domain. This could possibly be cached and
2674 resumed based on resume_key */
2675 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2676 "objectclass=trustedDomain");
2678 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2681 /* convert to lsa_DomainInformation format */
2682 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2684 return NT_STATUS_NO_MEMORY;
2686 for (i=0;i<count;i++) {
2687 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2688 if (!NT_STATUS_IS_OK(nt_status)) {
2693 /* sort the results by name */
2694 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2696 if (*r->in.resume_handle >= count) {
2697 *r->out.resume_handle = -1;
2699 return NT_STATUS_NO_MORE_ENTRIES;
2702 /* return the rest, limit by max_size. Note that we
2703 use the w2k3 element size value of 60 */
2704 r->out.domains->count = count - *r->in.resume_handle;
2705 r->out.domains->count = MIN(r->out.domains->count,
2706 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2708 r->out.domains->domains = entries + *r->in.resume_handle;
2710 if (r->out.domains->count < count - *r->in.resume_handle) {
2711 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2712 return STATUS_MORE_ENTRIES;
2715 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2717 return NT_STATUS_OK;
2724 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2725 struct lsa_OpenAccount *r)
2727 struct dcesrv_handle *h, *ah;
2728 struct lsa_policy_state *state;
2729 struct lsa_account_state *astate;
2731 ZERO_STRUCTP(r->out.acct_handle);
2733 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2737 astate = talloc(dce_call->conn, struct lsa_account_state);
2738 if (astate == NULL) {
2739 return NT_STATUS_NO_MEMORY;
2742 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2743 if (astate->account_sid == NULL) {
2744 talloc_free(astate);
2745 return NT_STATUS_NO_MEMORY;
2748 astate->policy = talloc_reference(astate, state);
2749 astate->access_mask = r->in.access_mask;
2752 * For now we grant all requested access.
2754 * We will fail at the ldb layer later.
2756 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2757 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2758 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2760 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2762 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2763 __func__, dom_sid_string(mem_ctx, astate->account_sid),
2764 (unsigned)r->in.access_mask,
2765 (unsigned)astate->access_mask));
2767 ah = dcesrv_handle_create(dce_call, LSA_HANDLE_ACCOUNT);
2769 talloc_free(astate);
2770 return NT_STATUS_NO_MEMORY;
2773 ah->data = talloc_steal(ah, astate);
2775 *r->out.acct_handle = ah->wire_handle;
2777 return NT_STATUS_OK;
2782 lsa_EnumPrivsAccount
2784 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2785 TALLOC_CTX *mem_ctx,
2786 struct lsa_EnumPrivsAccount *r)
2788 struct dcesrv_handle *h;
2789 struct lsa_account_state *astate;
2792 struct ldb_message **res;
2793 const char * const attrs[] = { "privilege", NULL};
2794 struct ldb_message_element *el;
2796 struct lsa_PrivilegeSet *privs;
2798 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2802 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2803 if (privs == NULL) {
2804 return NT_STATUS_NO_MEMORY;
2810 *r->out.privs = privs;
2812 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2813 if (sidstr == NULL) {
2814 return NT_STATUS_NO_MEMORY;
2817 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2818 "objectSid=%s", sidstr);
2820 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2823 return NT_STATUS_OK;
2826 el = ldb_msg_find_element(res[0], "privilege");
2827 if (el == NULL || el->num_values == 0) {
2828 return NT_STATUS_OK;
2831 privs->set = talloc_array(privs,
2832 struct lsa_LUIDAttribute, el->num_values);
2833 if (privs->set == NULL) {
2834 return NT_STATUS_NO_MEMORY;
2838 for (i=0;i<el->num_values;i++) {
2839 int id = sec_privilege_id((const char *)el->values[i].data);
2840 if (id == SEC_PRIV_INVALID) {
2841 /* Perhaps an account right, not a privilege */
2844 privs->set[j].attribute = 0;
2845 privs->set[j].luid.low = id;
2846 privs->set[j].luid.high = 0;
2852 return NT_STATUS_OK;
2856 lsa_EnumAccountRights
2858 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2859 TALLOC_CTX *mem_ctx,
2860 struct lsa_EnumAccountRights *r)
2862 struct dcesrv_handle *h;
2863 struct lsa_policy_state *state;
2866 struct ldb_message **res;
2867 const char * const attrs[] = { "privilege", NULL};
2869 struct ldb_message_element *el;
2871 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2875 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2876 if (sidstr == NULL) {
2877 return NT_STATUS_NO_MEMORY;
2880 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2881 "(&(objectSid=%s)(privilege=*))", sidstr);
2883 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2886 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2887 dom_sid_string(mem_ctx, r->in.sid),
2888 ldb_errstring(state->pdb)));
2889 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2892 el = ldb_msg_find_element(res[0], "privilege");
2893 if (el == NULL || el->num_values == 0) {
2894 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2897 r->out.rights->count = el->num_values;
2898 r->out.rights->names = talloc_array(r->out.rights,
2899 struct lsa_StringLarge, r->out.rights->count);
2900 if (r->out.rights->names == NULL) {
2901 return NT_STATUS_NO_MEMORY;
2904 for (i=0;i<el->num_values;i++) {
2905 r->out.rights->names[i].string = (const char *)el->values[i].data;
2908 return NT_STATUS_OK;
2914 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2916 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2917 TALLOC_CTX *mem_ctx,
2918 struct lsa_policy_state *state,
2920 struct dom_sid *sid,
2921 const struct lsa_RightSet *rights)
2923 struct auth_session_info *session_info =
2924 dcesrv_call_session_info(dce_call);
2925 const char *sidstr, *sidndrstr;
2926 struct ldb_message *msg;
2927 struct ldb_message_element *el;
2930 struct lsa_EnumAccountRights r2;
2933 if (security_session_user_level(session_info, NULL) <
2934 SECURITY_ADMINISTRATOR) {
2935 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2936 return NT_STATUS_ACCESS_DENIED;
2939 msg = ldb_msg_new(mem_ctx);
2941 return NT_STATUS_NO_MEMORY;
2944 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2945 if (sidndrstr == NULL) {
2947 return NT_STATUS_NO_MEMORY;
2950 sidstr = dom_sid_string(msg, sid);
2951 if (sidstr == NULL) {
2953 return NT_STATUS_NO_MEMORY;
2956 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2957 if (dnstr == NULL) {
2959 return NT_STATUS_NO_MEMORY;
2962 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2963 if (msg->dn == NULL) {
2965 return NT_STATUS_NO_MEMORY;
2968 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2971 r2.in.handle = &state->handle->wire_handle;
2973 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2975 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2976 if (!NT_STATUS_IS_OK(status)) {
2977 ZERO_STRUCTP(r2.out.rights);
2981 for (i=0;i<rights->count;i++) {
2984 ok = dcesrc_lsa_valid_AccountRight(rights->names[i].string);
2987 return NT_STATUS_NO_SUCH_PRIVILEGE;
2990 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2992 for (j=0;j<r2.out.rights->count;j++) {
2993 if (strcasecmp_m(r2.out.rights->names[j].string,
2994 rights->names[i].string) == 0) {
2998 if (j != r2.out.rights->count) continue;
3001 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
3002 if (ret != LDB_SUCCESS) {
3004 return NT_STATUS_NO_MEMORY;
3008 el = ldb_msg_find_element(msg, "privilege");
3011 return NT_STATUS_OK;
3014 el->flags = ldb_flag;
3016 ret = ldb_modify(state->pdb, msg);
3017 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
3018 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
3020 return NT_STATUS_NO_MEMORY;
3022 ldb_msg_add_string(msg, "comment", "added via LSA");
3023 ret = ldb_add(state->pdb, msg);
3025 if (ret != LDB_SUCCESS) {
3026 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
3028 return NT_STATUS_OK;
3030 DEBUG(3, ("Could not %s attributes from %s: %s",
3031 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
3032 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
3034 return NT_STATUS_UNEXPECTED_IO_ERROR;
3038 return NT_STATUS_OK;
3042 lsa_AddPrivilegesToAccount
3044 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3045 struct lsa_AddPrivilegesToAccount *r)
3047 struct lsa_RightSet rights;
3048 struct dcesrv_handle *h;
3049 struct lsa_account_state *astate;
3052 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3056 rights.count = r->in.privs->count;
3057 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
3058 if (rights.names == NULL) {
3059 return NT_STATUS_NO_MEMORY;
3061 for (i=0;i<rights.count;i++) {
3062 int id = r->in.privs->set[i].luid.low;
3063 if (r->in.privs->set[i].luid.high) {
3064 return NT_STATUS_NO_SUCH_PRIVILEGE;
3066 rights.names[i].string = sec_privilege_name(id);
3067 if (rights.names[i].string == NULL) {
3068 return NT_STATUS_NO_SUCH_PRIVILEGE;
3072 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3073 LDB_FLAG_MOD_ADD, astate->account_sid,
3079 lsa_RemovePrivilegesFromAccount
3081 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3082 struct lsa_RemovePrivilegesFromAccount *r)
3084 struct lsa_RightSet *rights;
3085 struct dcesrv_handle *h;
3086 struct lsa_account_state *astate;
3089 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3093 rights = talloc(mem_ctx, struct lsa_RightSet);
3095 if (r->in.remove_all == 1 &&
3096 r->in.privs == NULL) {
3097 struct lsa_EnumAccountRights r2;
3100 r2.in.handle = &astate->policy->handle->wire_handle;
3101 r2.in.sid = astate->account_sid;
3102 r2.out.rights = rights;
3104 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
3105 if (!NT_STATUS_IS_OK(status)) {
3109 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3110 LDB_FLAG_MOD_DELETE, astate->account_sid,
3114 if (r->in.remove_all != 0) {
3115 return NT_STATUS_INVALID_PARAMETER;
3118 rights->count = r->in.privs->count;
3119 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
3120 if (rights->names == NULL) {
3121 return NT_STATUS_NO_MEMORY;
3123 for (i=0;i<rights->count;i++) {
3124 int id = r->in.privs->set[i].luid.low;
3125 if (r->in.privs->set[i].luid.high) {
3126 return NT_STATUS_NO_SUCH_PRIVILEGE;
3128 rights->names[i].string = sec_privilege_name(id);
3129 if (rights->names[i].string == NULL) {
3130 return NT_STATUS_NO_SUCH_PRIVILEGE;
3134 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3135 LDB_FLAG_MOD_DELETE, astate->account_sid,
3141 lsa_GetQuotasForAccount
3143 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3144 struct lsa_GetQuotasForAccount *r)
3146 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3151 lsa_SetQuotasForAccount
3153 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3154 struct lsa_SetQuotasForAccount *r)
3156 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3161 lsa_GetSystemAccessAccount
3163 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3164 struct lsa_GetSystemAccessAccount *r)
3166 struct dcesrv_handle *h;
3167 struct lsa_account_state *astate;
3170 struct ldb_message **res;
3171 const char * const attrs[] = { "privilege", NULL};
3172 struct ldb_message_element *el;
3175 *(r->out.access_mask) = 0x00000000;
3177 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3181 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
3182 if (sidstr == NULL) {
3183 return NT_STATUS_NO_MEMORY;
3186 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
3187 "objectSid=%s", sidstr);
3189 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3192 return NT_STATUS_OK;
3195 el = ldb_msg_find_element(res[0], "privilege");
3196 if (el == NULL || el->num_values == 0) {
3197 return NT_STATUS_OK;
3200 for (i=0;i<el->num_values;i++) {
3201 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
3202 if (right_bit == 0) {
3203 /* Perhaps an privilege, not a right */
3206 *(r->out.access_mask) |= right_bit;
3209 return NT_STATUS_OK;
3214 lsa_SetSystemAccessAccount
3216 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3217 struct lsa_SetSystemAccessAccount *r)
3219 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3224 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3225 struct lsa_CreateSecret *r)
3227 struct auth_session_info *session_info =
3228 dcesrv_call_session_info(dce_call);
3229 struct dcesrv_handle *policy_handle;
3230 struct lsa_policy_state *policy_state;
3231 struct lsa_secret_state *secret_state;
3232 struct dcesrv_handle *handle;
3233 struct ldb_message **msgs, *msg;
3234 const char *attrs[] = {
3242 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3243 ZERO_STRUCTP(r->out.sec_handle);
3245 switch (security_session_user_level(session_info, NULL))
3247 case SECURITY_SYSTEM:
3248 case SECURITY_ADMINISTRATOR:
3251 /* Users and annonymous are not allowed create secrets */
3252 return NT_STATUS_ACCESS_DENIED;
3255 policy_state = policy_handle->data;
3257 if (!r->in.name.string) {
3258 return NT_STATUS_INVALID_PARAMETER;
3261 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3262 NT_STATUS_HAVE_NO_MEMORY(secret_state);
3263 secret_state->policy = policy_state;
3265 msg = ldb_msg_new(mem_ctx);
3267 return NT_STATUS_NO_MEMORY;
3270 if (strncmp("G$", r->in.name.string, 2) == 0) {
3273 secret_state->global = true;
3275 name = &r->in.name.string[2];
3276 if (strlen(name) == 0) {
3277 return NT_STATUS_INVALID_PARAMETER;
3280 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3281 ldb_binary_encode_string(mem_ctx, name));
3282 NT_STATUS_HAVE_NO_MEMORY(name2);
3285 * We need to connect to the database as system, as this is
3286 * one of the rare RPC calls that must read the secrets
3287 * (and this is denied otherwise)
3289 * We also save the current remote session details so they can
3290 * used by the audit logging module. This allows the audit
3291 * logging to report the remote users details, rather than the
3292 * system users details.
3294 secret_state->sam_ldb =
3295 dcesrv_samdb_connect_as_system(secret_state, dce_call);
3296 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3298 /* search for the secret record */
3299 ret = gendb_search(secret_state->sam_ldb,
3300 mem_ctx, policy_state->system_dn, &msgs, attrs,
3301 "(&(cn=%s)(objectclass=secret))",
3304 return NT_STATUS_OBJECT_NAME_COLLISION;
3308 DEBUG(0,("Failure searching for CN=%s: %s\n",
3309 name2, ldb_errstring(secret_state->sam_ldb)));
3310 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3313 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3314 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3315 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3316 return NT_STATUS_NO_MEMORY;
3319 ret = ldb_msg_add_string(msg, "cn", name2);
3320 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3322 secret_state->global = false;
3324 name = r->in.name.string;
3325 if (strlen(name) == 0) {
3326 return NT_STATUS_INVALID_PARAMETER;
3329 secret_state->sam_ldb = secrets_db_connect(secret_state,
3330 dce_call->conn->dce_ctx->lp_ctx);
3331 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3333 /* search for the secret record */
3334 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3335 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3337 "(&(cn=%s)(objectclass=secret))",
3338 ldb_binary_encode_string(mem_ctx, name));
3340 return NT_STATUS_OBJECT_NAME_COLLISION;
3344 DEBUG(0,("Failure searching for CN=%s: %s\n",
3345 name, ldb_errstring(secret_state->sam_ldb)));
3346 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3349 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3350 "cn=%s,cn=LSA Secrets", name);
3351 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3352 ret = ldb_msg_add_string(msg, "cn", name);
3353 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3356 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3357 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3359 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3360 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3362 /* create the secret */
3363 ret = ldb_add(secret_state->sam_ldb, msg);
3364 if (ret != LDB_SUCCESS) {
3365 DEBUG(0,("Failed to create secret record %s: %s\n",
3366 ldb_dn_get_linearized(msg->dn),
3367 ldb_errstring(secret_state->sam_ldb)));
3368 return NT_STATUS_ACCESS_DENIED;
3371 handle = dcesrv_handle_create(dce_call, LSA_HANDLE_SECRET);
3372 NT_STATUS_HAVE_NO_MEMORY(handle);
3374 handle->data = talloc_steal(handle, secret_state);
3376 secret_state->access_mask = r->in.access_mask;
3377 secret_state->policy = talloc_reference(secret_state, policy_state);
3378 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3380 *r->out.sec_handle = handle->wire_handle;
3382 return NT_STATUS_OK;
3389 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3390 struct lsa_OpenSecret *r)
3392 struct auth_session_info *session_info =
3393 dcesrv_call_session_info(dce_call);
3394 struct dcesrv_handle *policy_handle;
3395 struct lsa_policy_state *policy_state;
3396 struct lsa_secret_state *secret_state;
3397 struct dcesrv_handle *handle;
3398 struct ldb_message **msgs;
3399 const char *attrs[] = {
3405 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3406 ZERO_STRUCTP(r->out.sec_handle);
3407 policy_state = policy_handle->data;
3409 if (!r->in.name.string) {
3410 return NT_STATUS_INVALID_PARAMETER;
3413 switch (security_session_user_level(session_info, NULL))
3415 case SECURITY_SYSTEM:
3416 case SECURITY_ADMINISTRATOR:
3419 /* Users and annonymous are not allowed to access secrets */
3420 return NT_STATUS_ACCESS_DENIED;
3423 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3424 if (!secret_state) {
3425 return NT_STATUS_NO_MEMORY;
3427 secret_state->policy = policy_state;
3429 if (strncmp("G$", r->in.name.string, 2) == 0) {
3430 name = &r->in.name.string[2];
3432 * We need to connect to the database as system, as this is
3433 * one of the rare RPC calls that must read the secrets
3434 * (and this is denied otherwise)
3436 * We also save the current remote session details so they can
3437 * used by the audit logging module. This allows the audit
3438 * logging to report the remote users details, rather than the
3439 * system users details.
3441 secret_state->sam_ldb =
3442 dcesrv_samdb_connect_as_system(secret_state, dce_call);
3443 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3444 secret_state->global = true;
3446 if (strlen(name) < 1) {
3447 return NT_STATUS_INVALID_PARAMETER;
3450 /* search for the secret record */
3451 ret = gendb_search(secret_state->sam_ldb,
3452 mem_ctx, policy_state->system_dn, &msgs, attrs,
3453 "(&(cn=%s Secret)(objectclass=secret))",
3454 ldb_binary_encode_string(mem_ctx, name));
3456 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3460 DEBUG(0,("Found %d records matching DN %s\n", ret,
3461 ldb_dn_get_linearized(policy_state->system_dn)));
3462 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3465 secret_state->global = false;
3466 secret_state->sam_ldb = secrets_db_connect(secret_state,
3467 dce_call->conn->dce_ctx->lp_ctx);
3468 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3470 name = r->in.name.string;
3471 if (strlen(name) < 1) {
3472 return NT_STATUS_INVALID_PARAMETER;
3475 /* search for the secret record */
3476 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3477 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3479 "(&(cn=%s)(objectclass=secret))",
3480 ldb_binary_encode_string(mem_ctx, name));
3482 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3486 DEBUG(0,("Found %d records matching CN=%s\n",
3487 ret, ldb_binary_encode_string(mem_ctx, name)));
3488 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3492 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3494 handle = dcesrv_handle_create(dce_call, LSA_HANDLE_SECRET);
3496 return NT_STATUS_NO_MEMORY;
3499 handle->data = talloc_steal(handle, secret_state);
3501 secret_state->access_mask = r->in.access_mask;
3502 secret_state->policy = talloc_reference(secret_state, policy_state);
3504 *r->out.sec_handle = handle->wire_handle;
3506 return NT_STATUS_OK;
3513 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3514 struct lsa_SetSecret *r)
3517 struct dcesrv_handle *h;
3518 struct lsa_secret_state *secret_state;
3519 struct ldb_message *msg;
3520 DATA_BLOB session_key;
3521 DATA_BLOB crypt_secret, secret;
3524 NTSTATUS status = NT_STATUS_OK;
3526 struct timeval now = timeval_current();
3527 NTTIME nt_now = timeval_to_nttime(&now);
3529 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3531 secret_state = h->data;
3533 msg = ldb_msg_new(mem_ctx);
3535 return NT_STATUS_NO_MEMORY;
3538 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3540 return NT_STATUS_NO_MEMORY;
3542 status = dcesrv_transport_session_key(dce_call, &session_key);
3543 if (!NT_STATUS_IS_OK(status)) {
3547 if (r->in.old_val) {
3549 crypt_secret.data = r->in.old_val->data;
3550 crypt_secret.length = r->in.old_val->size;
3552 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3553 if (!NT_STATUS_IS_OK(status)) {
3557 val.data = secret.data;
3558 val.length = secret.length;
3561 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3562 return NT_STATUS_NO_MEMORY;
3565 /* set old value mtime */
3566 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3567 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3568 return NT_STATUS_NO_MEMORY;
3572 /* If the old value is not set, then migrate the
3573 * current value to the old value */
3574 const struct ldb_val *old_val;
3575 NTTIME last_set_time;
3576 struct ldb_message **res;
3577 const char *attrs[] = {
3583 /* search for the secret record */
3584 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3585 secret_state->secret_dn, &res, attrs);
3587 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3591 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3592 ldb_dn_get_linearized(secret_state->secret_dn)));
3593 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3596 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3597 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3601 if (ldb_msg_add_value(msg, "priorValue",
3602 old_val, NULL) != LDB_SUCCESS) {
3603 return NT_STATUS_NO_MEMORY;
3606 if (samdb_msg_add_delete(secret_state->sam_ldb,
3607 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3608 return NT_STATUS_NO_MEMORY;
3612 /* set old value mtime */
3613 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3614 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3615 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3616 return NT_STATUS_NO_MEMORY;
3619 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3620 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3621 return NT_STATUS_NO_MEMORY;
3626 if (r->in.new_val) {
3628 crypt_secret.data = r->in.new_val->data;
3629 crypt_secret.length = r->in.new_val->size;
3631 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3632 if (!NT_STATUS_IS_OK(status)) {
3636 val.data = secret.data;
3637 val.length = secret.length;
3640 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3641 return NT_STATUS_NO_MEMORY;
3644 /* set new value mtime */
3645 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3646 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3647 return NT_STATUS_NO_MEMORY;
3650 /* NULL out the NEW value */
3651 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3652 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3653 return NT_STATUS_NO_MEMORY;
3655 if (samdb_msg_add_delete(secret_state->sam_ldb,
3656 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3657 return NT_STATUS_NO_MEMORY;
3661 /* modify the samdb record */
3662 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3663 if (ret != LDB_SUCCESS) {
3664 return dsdb_ldb_err_to_ntstatus(ret);
3667 return NT_STATUS_OK;
3674 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3675 struct lsa_QuerySecret *r)
3677 struct auth_session_info *session_info =
3678 dcesrv_call_session_info(dce_call);
3679 struct dcesrv_handle *h;
3680 struct lsa_secret_state *secret_state;
3681 struct ldb_message *msg;
3682 DATA_BLOB session_key;
3683 DATA_BLOB crypt_secret, secret;
3685 struct ldb_message **res;
3686 const char *attrs[] = {
3696 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3698 /* Ensure user is permitted to read this... */
3699 switch (security_session_user_level(session_info, NULL))
3701 case SECURITY_SYSTEM:
3702 case SECURITY_ADMINISTRATOR:
3705 /* Users and annonymous are not allowed to read secrets */
3706 return NT_STATUS_ACCESS_DENIED;
3709 secret_state = h->data;
3711 /* pull all the user attributes */
3712 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3713 secret_state->secret_dn, &res, attrs);
3715 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3719 nt_status = dcesrv_transport_session_key(dce_call, &session_key);
3720 if (!NT_STATUS_IS_OK(nt_status)) {
3724 if (r->in.old_val) {
3725 const struct ldb_val *prior_val;
3726 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3727 if (!r->out.old_val) {
3728 return NT_STATUS_NO_MEMORY;
3730 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3732 if (prior_val && prior_val->length) {
3733 secret.data = prior_val->data;
3734 secret.length = prior_val->length;
3737 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3738 if (!crypt_secret.length) {
3739 return NT_STATUS_NO_MEMORY;
3741 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3742 if (!r->out.old_val->buf) {
3743 return NT_STATUS_NO_MEMORY;
3745 r->out.old_val->buf->size = crypt_secret.length;
3746 r->out.old_val->buf->length = crypt_secret.length;
3747 r->out.old_val->buf->data = crypt_secret.data;
3751 if (r->in.old_mtime) {
3752 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3753 if (!r->out.old_mtime) {
3754 return NT_STATUS_NO_MEMORY;
3756 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3759 if (r->in.new_val) {
3760 const struct ldb_val *new_val;
3761 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3762 if (!r->out.new_val) {
3763 return NT_STATUS_NO_MEMORY;
3766 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3768 if (new_val && new_val->length) {
3769 secret.data = new_val->data;
3770 secret.length = new_val->length;
3773 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3774 if (!crypt_secret.length) {
3775 return NT_STATUS_NO_MEMORY;
3777 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3778 if (!r->out.new_val->buf) {
3779 return NT_STATUS_NO_MEMORY;
3781 r->out.new_val->buf->length = crypt_secret.length;
3782 r->out.new_val->buf->size = crypt_secret.length;
3783 r->out.new_val->buf->data = crypt_secret.data;
3787 if (r->in.new_mtime) {
3788 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3789 if (!r->out.new_mtime) {
3790 return NT_STATUS_NO_MEMORY;
3792 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3795 return NT_STATUS_OK;
3802 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3803 TALLOC_CTX *mem_ctx,
3804 struct lsa_LookupPrivValue *r)
3806 struct dcesrv_handle *h;
3809 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3811 id = sec_privilege_id(r->in.name->string);
3812 if (id == SEC_PRIV_INVALID) {
3813 return NT_STATUS_NO_SUCH_PRIVILEGE;
3816 r->out.luid->low = id;
3817 r->out.luid->high = 0;
3819 return NT_STATUS_OK;
3826 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3827 TALLOC_CTX *mem_ctx,
3828 struct lsa_LookupPrivName *r)
3830 struct dcesrv_handle *h;
3831 struct lsa_StringLarge *name;
3832 const char *privname;
3834 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3836 if (r->in.luid->high != 0) {
3837 return NT_STATUS_NO_SUCH_PRIVILEGE;
3840 privname = sec_privilege_name(r->in.luid->low);
3841 if (privname == NULL) {
3842 return NT_STATUS_NO_SUCH_PRIVILEGE;
3845 name = talloc(mem_ctx, struct lsa_StringLarge);
3847 return NT_STATUS_NO_MEMORY;
3850 name->string = privname;
3852 *r->out.name = name;
3854 return NT_STATUS_OK;
3859 lsa_LookupPrivDisplayName
3861 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3862 TALLOC_CTX *mem_ctx,
3863 struct lsa_LookupPrivDisplayName *r)
3865 struct dcesrv_handle *h;
3866 struct lsa_StringLarge *disp_name = NULL;
3867 enum sec_privilege id;
3869 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3871 id = sec_privilege_id(r->in.name->string);
3872 if (id == SEC_PRIV_INVALID) {
3873 return NT_STATUS_NO_SUCH_PRIVILEGE;
3876 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3877 if (disp_name == NULL) {
3878 return NT_STATUS_NO_MEMORY;
3881 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3882 if (disp_name->string == NULL) {
3883 return NT_STATUS_INTERNAL_ERROR;
3886 *r->out.disp_name = disp_name;
3887 *r->out.returned_language_id = 0;
3889 return NT_STATUS_OK;
3894 lsa_EnumAccountsWithUserRight
3896 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3897 TALLOC_CTX *mem_ctx,
3898 struct lsa_EnumAccountsWithUserRight *r)
3900 struct dcesrv_handle *h;
3901 struct lsa_policy_state *state;
3903 struct ldb_message **res;
3904 const char * const attrs[] = { "objectSid", NULL};
3905 const char *privname;
3908 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3912 if (r->in.name == NULL) {
3913 return NT_STATUS_NO_SUCH_PRIVILEGE;
3916 privname = r->in.name->string;
3918 ok = dcesrc_lsa_valid_AccountRight(privname);
3920 return NT_STATUS_NO_SUCH_PRIVILEGE;
3923 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3924 "privilege=%s", privname);
3926 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3929 return NT_STATUS_NO_MORE_ENTRIES;
3932 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3933 if (r->out.sids->sids == NULL) {
3934 return NT_STATUS_NO_MEMORY;
3936 for (i=0;i<ret;i++) {
3937 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3938 res[i], "objectSid");
3939 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3941 r->out.sids->num_sids = ret;
3943 return NT_STATUS_OK;
3948 lsa_AddAccountRights
3950 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3951 TALLOC_CTX *mem_ctx,
3952 struct lsa_AddAccountRights *r)
3954 struct dcesrv_handle *h;
3955 struct lsa_policy_state *state;
3957 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3961 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3963 r->in.sid, r->in.rights);
3968 lsa_RemoveAccountRights
3970 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3971 TALLOC_CTX *mem_ctx,
3972 struct lsa_RemoveAccountRights *r)
3974 struct dcesrv_handle *h;
3975 struct lsa_policy_state *state;
3977 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3981 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3982 LDB_FLAG_MOD_DELETE,
3983 r->in.sid, r->in.rights);
3988 lsa_StorePrivateData
3990 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3991 struct lsa_StorePrivateData *r)
3993 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3998 lsa_RetrievePrivateData
4000 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4001 struct lsa_RetrievePrivateData *r)
4003 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4010 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4011 struct lsa_GetUserName *r)
4013 enum dcerpc_transport_t transport =
4014 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
4015 struct auth_session_info *session_info =
4016 dcesrv_call_session_info(dce_call);
4017 NTSTATUS status = NT_STATUS_OK;
4018 const char *account_name;
4019 const char *authority_name;
4020 struct lsa_String *_account_name;
4021 struct lsa_String *_authority_name = NULL;
4023 if (transport != NCACN_NP && transport != NCALRPC) {
4024 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
4027 /* this is what w2k3 does */
4028 r->out.account_name = r->in.account_name;
4029 r->out.authority_name = r->in.authority_name;
4031 if (r->in.account_name
4032 && *r->in.account_name
4033 /* && *(*r->in.account_name)->string */
4035 return NT_STATUS_INVALID_PARAMETER;
4038 if (r->in.authority_name
4039 && *r->in.authority_name
4040 /* && *(*r->in.authority_name)->string */
4042 return NT_STATUS_INVALID_PARAMETER;
4045 account_name = talloc_reference(mem_ctx, session_info->info->account_name);
4046 authority_name = talloc_reference(mem_ctx, session_info->info->domain_name);
4048 _account_name = talloc(mem_ctx, struct lsa_String);
4049 NT_STATUS_HAVE_NO_MEMORY(_account_name);
4050 _account_name->string = account_name;
4052 if (r->in.authority_name) {
4053 _authority_name = talloc(mem_ctx, struct lsa_String);
4054 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
4055 _authority_name->string = authority_name;
4058 *r->out.account_name = _account_name;
4059 if (r->out.authority_name) {
4060 *r->out.authority_name = _authority_name;
4069 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
4070 TALLOC_CTX *mem_ctx,
4071 struct lsa_SetInfoPolicy2 *r)
4073 /* need to support these */
4074 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4077 static void kdc_get_policy(TALLOC_CTX *mem_ctx,
4078 struct loadparm_context *lp_ctx,
4079 struct smb_krb5_context *smb_krb5_context,
4080 struct lsa_DomainInfoKerberos *k)
4082 time_t svc_tkt_lifetime;
4083 time_t usr_tkt_lifetime;
4084 time_t renewal_lifetime;
4086 /* Our KDC always re-validates the client */
4087 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
4089 lpcfg_default_kdc_policy(mem_ctx, lp_ctx, &svc_tkt_lifetime,
4090 &usr_tkt_lifetime, &renewal_lifetime);
4092 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
4093 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
4094 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
4095 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
4096 However in the parent function we basically just did a full
4097 krb5_context init with the only purpose of getting a global
4098 config option (the max skew), it would probably make more sense
4099 to have a lp_ or ldb global option as the samba default */
4100 if (smb_krb5_context) {
4101 unix_to_nt_time(&k->clock_skew,
4102 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
4108 lsa_QueryDomainInformationPolicy
4110 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4111 TALLOC_CTX *mem_ctx,
4112 struct lsa_QueryDomainInformationPolicy *r)
4114 union lsa_DomainInformationPolicy *info;
4116 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
4118 return NT_STATUS_NO_MEMORY;
4121 switch (r->in.level) {
4122 case LSA_DOMAIN_INFO_POLICY_EFS:
4124 *r->out.info = NULL;
4125 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4126 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
4128 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
4129 struct smb_krb5_context *smb_krb5_context;
4130 int ret = smb_krb5_init_context(mem_ctx,
4131 dce_call->conn->dce_ctx->lp_ctx,
4135 *r->out.info = NULL;
4136 return NT_STATUS_INTERNAL_ERROR;
4138 kdc_get_policy(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
4141 talloc_free(smb_krb5_context);
4142 *r->out.info = info;
4143 return NT_STATUS_OK;
4147 *r->out.info = NULL;
4148 return NT_STATUS_INVALID_INFO_CLASS;
4153 lsa_SetDomInfoPolicy
4155 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4156 TALLOC_CTX *mem_ctx,
4157 struct lsa_SetDomainInformationPolicy *r)
4159 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4165 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
4166 TALLOC_CTX *mem_ctx,
4167 struct lsa_TestCall *r)
4169 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4175 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4176 struct lsa_CREDRWRITE *r)
4178 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4185 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4186 struct lsa_CREDRREAD *r)
4188 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4195 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4196 struct lsa_CREDRENUMERATE *r)
4198 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4203 lsa_CREDRWRITEDOMAINCREDENTIALS
4205 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4206 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
4208 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4213 lsa_CREDRREADDOMAINCREDENTIALS
4215 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4216 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
4218 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4225 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4226 struct lsa_CREDRDELETE *r)
4228 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4233 lsa_CREDRGETTARGETINFO
4235 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4236 struct lsa_CREDRGETTARGETINFO *r)
4238 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4243 lsa_CREDRPROFILELOADED
4245 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4246 struct lsa_CREDRPROFILELOADED *r)
4248 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4253 lsa_CREDRGETSESSIONTYPES
4255 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4256 struct lsa_CREDRGETSESSIONTYPES *r)
4258 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4263 lsa_LSARREGISTERAUDITEVENT
4265 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4266 struct lsa_LSARREGISTERAUDITEVENT *r)
4268 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4273 lsa_LSARGENAUDITEVENT
4275 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4276 struct lsa_LSARGENAUDITEVENT *r)
4278 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4283 lsa_LSARUNREGISTERAUDITEVENT
4285 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4286 struct lsa_LSARUNREGISTERAUDITEVENT *r)
4288 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4293 lsa_lsaRQueryForestTrustInformation
4295 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4296 struct lsa_lsaRQueryForestTrustInformation *r)
4298 struct dcesrv_handle *h = NULL;
4299 struct lsa_policy_state *p_state = NULL;
4300 int forest_level = DS_DOMAIN_FUNCTION_2000;
4301 const char * const trust_attrs[] = {
4302 "securityIdentifier",
4308 "msDS-TrustForestTrustInfo",
4311 struct ldb_message *trust_tdo_msg = NULL;
4312 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4313 struct ForestTrustInfo *trust_fti = NULL;
4314 struct lsa_ForestTrustInformation *trust_lfti = NULL;
4317 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4321 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4322 return NT_STATUS_INVALID_DOMAIN_STATE;
4325 forest_level = dsdb_forest_functional_level(p_state->sam_ldb);
4326 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4327 return NT_STATUS_INVALID_DOMAIN_STATE;
4330 if (r->in.trusted_domain_name->string == NULL) {
4331 return NT_STATUS_NO_SUCH_DOMAIN;
4334 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4335 r->in.trusted_domain_name->string,
4336 r->in.trusted_domain_name->string,
4337 trust_attrs, mem_ctx, &trust_tdo_msg);
4338 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4339 return NT_STATUS_NO_SUCH_DOMAIN;
4341 if (!NT_STATUS_IS_OK(status)) {
4345 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4346 if (!NT_STATUS_IS_OK(status)) {
4350 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4351 return NT_STATUS_INVALID_PARAMETER;
4354 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4355 return NT_STATUS_INVALID_PARAMETER;
4358 status = dsdb_trust_parse_forest_info(mem_ctx,
4361 if (!NT_STATUS_IS_OK(status)) {
4365 status = dsdb_trust_forest_info_to_lsa(mem_ctx, trust_fti,
4367 if (!NT_STATUS_IS_OK(status)) {
4371 *r->out.forest_trust_info = trust_lfti;
4372 return NT_STATUS_OK;
4376 lsa_lsaRSetForestTrustInformation
4378 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4379 TALLOC_CTX *mem_ctx,
4380 struct lsa_lsaRSetForestTrustInformation *r)
4382 struct dcesrv_handle *h;
4383 struct lsa_policy_state *p_state;
4384 const char * const trust_attrs[] = {
4385 "securityIdentifier",
4391 "msDS-TrustForestTrustInfo",
4394 struct ldb_message *trust_tdo_msg = NULL;
4395 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4396 struct lsa_ForestTrustInformation *step1_lfti = NULL;
4397 struct lsa_ForestTrustInformation *step2_lfti = NULL;
4398 struct ForestTrustInfo *trust_fti = NULL;
4399 struct ldb_result *trusts_res = NULL;
4401 struct lsa_TrustDomainInfoInfoEx *xref_tdo = NULL;
4402 struct lsa_ForestTrustInformation *xref_lfti = NULL;
4403 struct lsa_ForestTrustCollisionInfo *c_info = NULL;
4404 DATA_BLOB ft_blob = {};
4405 struct ldb_message *msg = NULL;
4406 struct server_id *server_ids = NULL;
4407 uint32_t num_server_ids = 0;
4409 enum ndr_err_code ndr_err;
4411 bool in_transaction = false;
4412 struct imessaging_context *imsg_ctx =
4413 dcesrv_imessaging_context(dce_call->conn);
4415 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4419 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4420 return NT_STATUS_INVALID_DOMAIN_STATE;
4423 if (r->in.check_only == 0) {
4424 ret = ldb_transaction_start(p_state->sam_ldb);
4425 if (ret != LDB_SUCCESS) {
4426 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4428 in_transaction = true;
4432 * abort if we are not a PDC
4434 * In future we should use a function like IsEffectiveRoleOwner()
4436 if (!samdb_is_pdc(p_state->sam_ldb)) {
4437 status = NT_STATUS_INVALID_DOMAIN_ROLE;
4441 if (r->in.trusted_domain_name->string == NULL) {
4442 status = NT_STATUS_NO_SUCH_DOMAIN;
4446 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4447 r->in.trusted_domain_name->string,
4448 r->in.trusted_domain_name->string,
4449 trust_attrs, mem_ctx, &trust_tdo_msg);
4450 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4451 status = NT_STATUS_NO_SUCH_DOMAIN;
4454 if (!NT_STATUS_IS_OK(status)) {
4458 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4459 if (!NT_STATUS_IS_OK(status)) {
4463 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4464 status = NT_STATUS_INVALID_PARAMETER;
4468 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4469 status = NT_STATUS_INVALID_PARAMETER;
4474 * verify and normalize the given forest trust info.
4476 * Step1: doesn't reorder yet, so step1_lfti might contain
4477 * NULL entries. This means dsdb_trust_verify_forest_info()
4478 * can generate collision entries with the callers index.
4480 status = dsdb_trust_normalize_forest_info_step1(mem_ctx,
4481 r->in.forest_trust_info,
4483 if (!NT_STATUS_IS_OK(status)) {
4487 c_info = talloc_zero(r->out.collision_info,
4488 struct lsa_ForestTrustCollisionInfo);
4489 if (c_info == NULL) {
4490 status = NT_STATUS_NO_MEMORY;
4495 * First check our own forest, then other domains/forests
4498 status = dsdb_trust_xref_tdo_info(mem_ctx, p_state->sam_ldb,
4500 if (!NT_STATUS_IS_OK(status)) {
4503 status = dsdb_trust_xref_forest_info(mem_ctx, p_state->sam_ldb,
4505 if (!NT_STATUS_IS_OK(status)) {
4510 * The documentation proposed to generate
4511 * LSA_FOREST_TRUST_COLLISION_XREF collisions.
4512 * But Windows always uses LSA_FOREST_TRUST_COLLISION_TDO.
4514 status = dsdb_trust_verify_forest_info(xref_tdo, xref_lfti,
4515 LSA_FOREST_TRUST_COLLISION_TDO,
4516 c_info, step1_lfti);
4517 if (!NT_STATUS_IS_OK(status)) {
4521 /* fetch all other trusted domain objects */
4522 status = dsdb_trust_search_tdos(p_state->sam_ldb,
4523 trust_tdo->domain_name.string,
4525 mem_ctx, &trusts_res);
4526 if (!NT_STATUS_IS_OK(status)) {
4531 * now check against the other domains.
4532 * and generate LSA_FOREST_TRUST_COLLISION_TDO collisions.
4534 for (i = 0; i < trusts_res->count; i++) {
4535 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
4536 struct ForestTrustInfo *fti = NULL;
4537 struct lsa_ForestTrustInformation *lfti = NULL;
4539 status = dsdb_trust_parse_tdo_info(mem_ctx,
4540 trusts_res->msgs[i],
4542 if (!NT_STATUS_IS_OK(status)) {
4546 status = dsdb_trust_parse_forest_info(tdo,
4547 trusts_res->msgs[i],
4549 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
4552 if (!NT_STATUS_IS_OK(status)) {
4556 status = dsdb_trust_forest_info_to_lsa(tdo, fti, &lfti);
4557 if (!NT_STATUS_IS_OK(status)) {
4561 status = dsdb_trust_verify_forest_info(tdo, lfti,
4562 LSA_FOREST_TRUST_COLLISION_TDO,
4563 c_info, step1_lfti);
4564 if (!NT_STATUS_IS_OK(status)) {
4571 if (r->in.check_only != 0) {
4572 status = NT_STATUS_OK;
4577 * not just a check, write info back
4581 * normalize the given forest trust info.
4583 * Step2: adds TOP_LEVEL_NAME[_EX] in reverse order,
4584 * followed by DOMAIN_INFO in reverse order. It also removes
4585 * possible NULL entries from Step1.
4587 status = dsdb_trust_normalize_forest_info_step2(mem_ctx, step1_lfti,
4589 if (!NT_STATUS_IS_OK(status)) {
4593 status = dsdb_trust_forest_info_from_lsa(mem_ctx, step2_lfti,
4595 if (!NT_STATUS_IS_OK(status)) {
4599 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, trust_fti,
4600 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4601 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4602 status = NT_STATUS_INVALID_PARAMETER;
4606 msg = ldb_msg_new(mem_ctx);
4608 status = NT_STATUS_NO_MEMORY;
4612 msg->dn = ldb_dn_copy(mem_ctx, trust_tdo_msg->dn);
4614 status = NT_STATUS_NO_MEMORY;
4618 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4619 LDB_FLAG_MOD_REPLACE, NULL);
4620 if (ret != LDB_SUCCESS) {
4621 status = NT_STATUS_NO_MEMORY;
4624 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4626 if (ret != LDB_SUCCESS) {
4627 status = NT_STATUS_NO_MEMORY;
4631 ret = ldb_modify(p_state->sam_ldb, msg);
4632 if (ret != LDB_SUCCESS) {
4633 status = dsdb_ldb_err_to_ntstatus(ret);
4635 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4636 ldb_errstring(p_state->sam_ldb)));
4641 /* ok, all fine, commit transaction and return */
4642 in_transaction = false;
4643 ret = ldb_transaction_commit(p_state->sam_ldb);
4644 if (ret != LDB_SUCCESS) {
4645 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4650 * Notify winbindd that we have a acquired forest trust info
4652 status = irpc_servers_byname(imsg_ctx,
4657 if (!NT_STATUS_IS_OK(status)) {
4658 DBG_ERR("irpc_servers_byname failed\n");
4662 imessaging_send(imsg_ctx,
4664 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
4667 status = NT_STATUS_OK;
4670 if (NT_STATUS_IS_OK(status) && c_info->count != 0) {
4671 *r->out.collision_info = c_info;
4674 if (in_transaction) {
4675 ldb_transaction_cancel(p_state->sam_ldb);
4684 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4685 struct lsa_CREDRRENAME *r)
4687 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4693 lsa_LSAROPENPOLICYSCE
4695 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4696 struct lsa_LSAROPENPOLICYSCE *r)
4698 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4703 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4705 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4706 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4708 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4713 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4715 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4716 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4718 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4723 lsa_LSARADTREPORTSECURITYEVENT
4725 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4726 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4728 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4732 /* include the generated boilerplate */
4733 #include "librpc/gen_ndr/ndr_lsa_s.c"
4737 /*****************************************
4738 NOTE! The remaining calls below were
4739 removed in w2k3, so the DCESRV_FAULT()
4740 replies are the correct implementation. Do
4741 not try and fill these in with anything else
4742 ******************************************/
4745 dssetup_DsRoleDnsNameToFlatName
4747 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4748 struct dssetup_DsRoleDnsNameToFlatName *r)
4750 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4755 dssetup_DsRoleDcAsDc
4757 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4758 struct dssetup_DsRoleDcAsDc *r)
4760 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4765 dssetup_DsRoleDcAsReplica
4767 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4768 struct dssetup_DsRoleDcAsReplica *r)
4770 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4775 dssetup_DsRoleDemoteDc
4777 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4778 struct dssetup_DsRoleDemoteDc *r)
4780 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4785 dssetup_DsRoleGetDcOperationProgress
4787 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4788 struct dssetup_DsRoleGetDcOperationProgress *r)
4790 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4795 dssetup_DsRoleGetDcOperationResults
4797 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4798 struct dssetup_DsRoleGetDcOperationResults *r)
4800 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4805 dssetup_DsRoleCancel
4807 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4808 struct dssetup_DsRoleCancel *r)
4810 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4815 dssetup_DsRoleServerSaveStateForUpgrade
4817 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4818 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4820 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4825 dssetup_DsRoleUpgradeDownlevelServer
4827 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4828 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4830 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4835 dssetup_DsRoleAbortDownlevelServerUpgrade
4837 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4838 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4840 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4844 /* include the generated boilerplate */
4845 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4847 NTSTATUS dcerpc_server_lsa_init(TALLOC_CTX *ctx)
4851 ret = dcerpc_server_dssetup_init(ctx);
4852 if (!NT_STATUS_IS_OK(ret)) {
4855 ret = dcerpc_server_lsarpc_init(ctx);
4856 if (!NT_STATUS_IS_OK(ret)) {