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/crypto/crypto.h"
31 #include "lib/util/tsort.h"
32 #include "dsdb/common/util.h"
33 #include "libcli/security/session.h"
34 #include "libcli/lsarpc/util_lsarpc.h"
35 #include "lib/messaging/irpc.h"
36 #include "libds/common/roles.h"
38 #define DCESRV_INTERFACE_LSARPC_BIND(call, iface) \
39 dcesrv_interface_lsarpc_bind(call, iface)
40 static NTSTATUS dcesrv_interface_lsarpc_bind(struct dcesrv_call_state *dce_call,
41 const struct dcesrv_interface *iface)
43 return dcesrv_interface_bind_reject_connect(dce_call, iface);
46 static NTSTATUS lsarpc__op_init_server(struct dcesrv_context *dce_ctx,
47 const struct dcesrv_endpoint_server *ep_server);
48 static const struct dcesrv_interface dcesrv_lsarpc_interface;
50 #define DCESRV_INTERFACE_LSARPC_INIT_SERVER \
51 dcesrv_interface_lsarpc_init_server
52 static NTSTATUS dcesrv_interface_lsarpc_init_server(struct dcesrv_context *dce_ctx,
53 const struct dcesrv_endpoint_server *ep_server)
55 if (lpcfg_lsa_over_netlogon(dce_ctx->lp_ctx)) {
56 NTSTATUS ret = dcesrv_interface_register(dce_ctx,
57 "ncacn_np:[\\pipe\\netlogon]",
58 &dcesrv_lsarpc_interface, NULL);
59 if (!NT_STATUS_IS_OK(ret)) {
60 DEBUG(1,("lsarpc_op_init_server: failed to register endpoint '\\pipe\\netlogon'\n"));
64 return lsarpc__op_init_server(dce_ctx, ep_server);
68 this type allows us to distinguish handle types
72 state associated with a lsa_OpenAccount() operation
74 struct lsa_account_state {
75 struct lsa_policy_state *policy;
77 struct dom_sid *account_sid;
82 state associated with a lsa_OpenSecret() operation
84 struct lsa_secret_state {
85 struct lsa_policy_state *policy;
87 struct ldb_dn *secret_dn;
88 struct ldb_context *sam_ldb;
93 state associated with a lsa_OpenTrustedDomain() operation
95 struct lsa_trusted_domain_state {
96 struct lsa_policy_state *policy;
98 struct ldb_dn *trusted_domain_dn;
99 struct ldb_dn *trusted_domain_user_dn;
102 static bool dcesrc_lsa_valid_AccountRight(const char *right)
104 enum sec_privilege priv_id;
107 priv_id = sec_privilege_id(right);
108 if (priv_id != SEC_PRIV_INVALID) {
112 right_bit = sec_right_bit(right);
113 if (right_bit != 0) {
121 this is based on the samba3 function make_lsa_object_sd()
122 It uses the same logic, but with samba4 helper functions
124 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
125 struct security_descriptor **sd,
131 struct dom_sid *domain_sid, *domain_admins_sid;
132 const char *domain_admins_sid_str, *sidstr;
133 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
135 status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
136 if (!NT_STATUS_IS_OK(status)) {
137 TALLOC_FREE(tmp_ctx);
141 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
142 if (domain_admins_sid == NULL) {
143 TALLOC_FREE(tmp_ctx);
144 return NT_STATUS_NO_MEMORY;
147 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
148 if (domain_admins_sid_str == NULL) {
149 TALLOC_FREE(tmp_ctx);
150 return NT_STATUS_NO_MEMORY;
153 sidstr = dom_sid_string(tmp_ctx, sid);
154 if (sidstr == NULL) {
155 TALLOC_FREE(tmp_ctx);
156 return NT_STATUS_NO_MEMORY;
159 *sd = security_descriptor_dacl_create(mem_ctx,
163 SEC_ACE_TYPE_ACCESS_ALLOWED,
164 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
166 SID_BUILTIN_ADMINISTRATORS,
167 SEC_ACE_TYPE_ACCESS_ALLOWED,
170 SID_BUILTIN_ACCOUNT_OPERATORS,
171 SEC_ACE_TYPE_ACCESS_ALLOWED,
174 domain_admins_sid_str,
175 SEC_ACE_TYPE_ACCESS_ALLOWED,
179 SEC_ACE_TYPE_ACCESS_ALLOWED,
183 talloc_free(tmp_ctx);
185 NT_STATUS_HAVE_NO_MEMORY(*sd);
191 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
193 struct lsa_EnumAccountRights *r);
195 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
197 struct lsa_policy_state *state,
200 const struct lsa_RightSet *rights);
205 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
208 enum dcerpc_transport_t transport =
209 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
210 struct dcesrv_handle *h;
212 if (transport != NCACN_NP && transport != NCALRPC) {
213 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
216 *r->out.handle = *r->in.handle;
218 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
222 ZERO_STRUCTP(r->out.handle);
231 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
232 struct lsa_Delete *r)
234 return NT_STATUS_NOT_SUPPORTED;
241 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
242 struct lsa_DeleteObject *r)
244 struct auth_session_info *session_info =
245 dcesrv_call_session_info(dce_call);
246 struct dcesrv_handle *h;
249 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
251 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
252 struct lsa_secret_state *secret_state = h->data;
254 /* Ensure user is permitted to delete this... */
255 switch (security_session_user_level(session_info, NULL))
257 case SECURITY_SYSTEM:
258 case SECURITY_ADMINISTRATOR:
261 /* Users and anonymous are not allowed to delete things */
262 return NT_STATUS_ACCESS_DENIED;
265 ret = ldb_delete(secret_state->sam_ldb,
266 secret_state->secret_dn);
267 if (ret != LDB_SUCCESS) {
268 return NT_STATUS_INVALID_HANDLE;
271 ZERO_STRUCTP(r->out.handle);
275 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
276 struct lsa_trusted_domain_state *trusted_domain_state =
277 talloc_get_type(h->data, struct lsa_trusted_domain_state);
278 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
279 if (ret != LDB_SUCCESS) {
280 return NT_STATUS_INTERNAL_DB_CORRUPTION;
283 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
284 trusted_domain_state->trusted_domain_dn);
285 if (ret != LDB_SUCCESS) {
286 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
287 return NT_STATUS_INVALID_HANDLE;
290 if (trusted_domain_state->trusted_domain_user_dn) {
291 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
292 trusted_domain_state->trusted_domain_user_dn);
293 if (ret != LDB_SUCCESS) {
294 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
295 return NT_STATUS_INVALID_HANDLE;
299 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
300 if (ret != LDB_SUCCESS) {
301 return NT_STATUS_INTERNAL_DB_CORRUPTION;
304 ZERO_STRUCTP(r->out.handle);
308 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
309 struct lsa_RightSet *rights;
310 struct lsa_account_state *astate;
311 struct lsa_EnumAccountRights r2;
314 rights = talloc(mem_ctx, struct lsa_RightSet);
316 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
320 r2.in.handle = &astate->policy->handle->wire_handle;
321 r2.in.sid = astate->account_sid;
322 r2.out.rights = rights;
324 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
325 but we have a LSA_HANDLE_ACCOUNT here, so this call
327 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
328 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
332 if (!NT_STATUS_IS_OK(status)) {
336 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
337 LDB_FLAG_MOD_DELETE, astate->account_sid,
339 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
343 if (!NT_STATUS_IS_OK(status)) {
347 ZERO_STRUCTP(r->out.handle);
352 return NT_STATUS_INVALID_HANDLE;
359 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
360 struct lsa_EnumPrivs *r)
362 struct dcesrv_handle *h;
364 enum sec_privilege priv;
365 const char *privname;
367 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
369 i = *r->in.resume_handle;
371 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
372 r->out.privs->count < r->in.max_count) {
373 struct lsa_PrivEntry *e;
374 privname = sec_privilege_name(priv);
375 r->out.privs->privs = talloc_realloc(r->out.privs,
377 struct lsa_PrivEntry,
378 r->out.privs->count+1);
379 if (r->out.privs->privs == NULL) {
380 return NT_STATUS_NO_MEMORY;
382 e = &r->out.privs->privs[r->out.privs->count];
385 e->name.string = privname;
386 r->out.privs->count++;
390 *r->out.resume_handle = i;
399 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
400 struct lsa_QuerySecurity *r)
402 struct auth_session_info *session_info =
403 dcesrv_call_session_info(dce_call);
404 struct dcesrv_handle *h;
405 const struct security_descriptor *sd = NULL;
406 uint32_t access_granted = 0;
407 struct sec_desc_buf *sdbuf = NULL;
411 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
413 sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
415 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
416 struct lsa_policy_state *pstate = h->data;
419 access_granted = pstate->access_mask;
421 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
422 struct lsa_account_state *astate = h->data;
423 struct security_descriptor *_sd = NULL;
425 status = dcesrv_build_lsa_sd(mem_ctx, &_sd, sid,
426 LSA_ACCOUNT_ALL_ACCESS);
427 if (!NT_STATUS_IS_OK(status)) {
431 access_granted = astate->access_mask;
433 return NT_STATUS_INVALID_HANDLE;
436 sdbuf = talloc_zero(mem_ctx, struct sec_desc_buf);
438 return NT_STATUS_NO_MEMORY;
441 status = security_descriptor_for_client(sdbuf, sd, r->in.sec_info,
442 access_granted, &sdbuf->sd);
443 if (!NT_STATUS_IS_OK(status)) {
447 *r->out.sdbuf = sdbuf;
456 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
457 struct lsa_SetSecObj *r)
459 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
466 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
467 struct lsa_ChangePassword *r)
469 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
473 dssetup_DsRoleGetPrimaryDomainInformation
475 This is not an LSA call, but is the only call left on the DSSETUP
476 pipe (after the pipe was truncated), and needs lsa_get_policy_state
478 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
480 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
482 union dssetup_DsRoleInfo *info;
484 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
485 W_ERROR_HAVE_NO_MEMORY(info);
487 switch (r->in.level) {
488 case DS_ROLE_BASIC_INFORMATION:
490 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
492 const char *domain = NULL;
493 const char *dns_domain = NULL;
494 const char *forest = NULL;
495 struct GUID domain_guid;
496 struct lsa_policy_state *state;
498 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
499 0, /* we skip access checks */
501 if (!NT_STATUS_IS_OK(status)) {
502 return ntstatus_to_werror(status);
505 ZERO_STRUCT(domain_guid);
507 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
508 case ROLE_STANDALONE:
509 role = DS_ROLE_STANDALONE_SERVER;
511 case ROLE_DOMAIN_MEMBER:
512 role = DS_ROLE_MEMBER_SERVER;
514 case ROLE_ACTIVE_DIRECTORY_DC:
515 if (samdb_is_pdc(state->sam_ldb)) {
516 role = DS_ROLE_PRIMARY_DC;
518 role = DS_ROLE_BACKUP_DC;
523 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
524 case ROLE_STANDALONE:
525 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
526 W_ERROR_HAVE_NO_MEMORY(domain);
528 case ROLE_DOMAIN_MEMBER:
529 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
530 W_ERROR_HAVE_NO_MEMORY(domain);
531 /* TODO: what is with dns_domain and forest and guid? */
533 case ROLE_ACTIVE_DIRECTORY_DC:
534 flags = DS_ROLE_PRIMARY_DS_RUNNING;
536 if (state->mixed_domain == 1) {
537 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
540 domain = state->domain_name;
541 dns_domain = state->domain_dns;
542 forest = state->forest_dns;
544 domain_guid = state->domain_guid;
545 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
549 info->basic.role = role;
550 info->basic.flags = flags;
551 info->basic.domain = domain;
552 info->basic.dns_domain = dns_domain;
553 info->basic.forest = forest;
554 info->basic.domain_guid = domain_guid;
559 case DS_ROLE_UPGRADE_STATUS:
561 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
562 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
567 case DS_ROLE_OP_STATUS:
569 info->opstatus.status = DS_ROLE_OP_IDLE;
575 return WERR_INVALID_PARAMETER;
580 fill in the AccountDomain info
582 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
583 struct lsa_DomainInfo *info)
585 info->name.string = state->domain_name;
586 info->sid = state->domain_sid;
592 fill in the DNS domain info
594 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
595 struct lsa_DnsDomainInfo *info)
597 info->name.string = state->domain_name;
598 info->sid = state->domain_sid;
599 info->dns_domain.string = state->domain_dns;
600 info->dns_forest.string = state->forest_dns;
601 info->domain_guid = state->domain_guid;
609 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
610 struct lsa_QueryInfoPolicy2 *r)
612 struct lsa_policy_state *state;
613 struct dcesrv_handle *h;
614 union lsa_PolicyInformation *info;
618 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
622 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
624 return NT_STATUS_NO_MEMORY;
628 switch (r->in.level) {
629 case LSA_POLICY_INFO_AUDIT_LOG:
630 /* we don't need to fill in any of this */
631 ZERO_STRUCT(info->audit_log);
633 case LSA_POLICY_INFO_AUDIT_EVENTS:
634 /* we don't need to fill in any of this */
635 ZERO_STRUCT(info->audit_events);
637 case LSA_POLICY_INFO_PD:
638 /* we don't need to fill in any of this */
639 ZERO_STRUCT(info->pd);
642 case LSA_POLICY_INFO_DOMAIN:
643 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
644 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
645 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
646 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
647 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
649 case LSA_POLICY_INFO_ROLE:
650 info->role.role = LSA_ROLE_PRIMARY;
653 case LSA_POLICY_INFO_DNS:
654 case LSA_POLICY_INFO_DNS_INT:
655 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
657 case LSA_POLICY_INFO_REPLICA:
658 ZERO_STRUCT(info->replica);
661 case LSA_POLICY_INFO_QUOTA:
662 ZERO_STRUCT(info->quota);
665 case LSA_POLICY_INFO_MOD:
666 case LSA_POLICY_INFO_AUDIT_FULL_SET:
667 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
668 /* windows gives INVALID_PARAMETER */
670 return NT_STATUS_INVALID_PARAMETER;
674 return NT_STATUS_INVALID_INFO_CLASS;
680 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
681 struct lsa_QueryInfoPolicy *r)
683 struct lsa_QueryInfoPolicy2 r2;
688 r2.in.handle = r->in.handle;
689 r2.in.level = r->in.level;
690 r2.out.info = r->out.info;
692 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
700 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
701 struct lsa_SetInfoPolicy *r)
703 /* need to support this */
704 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
711 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
712 struct lsa_ClearAuditLog *r)
714 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
718 static const struct generic_mapping dcesrv_lsa_account_mapping = {
722 LSA_ACCOUNT_ALL_ACCESS
728 This call does not seem to have any long-term effects, hence no database operations
730 we need to talk to the MS product group to find out what this account database means!
732 answer is that the lsa database is totally separate from the SAM and
733 ldap databases. We are going to need a separate ldb to store these
734 accounts. The SIDs on this account bear no relation to the SIDs in
737 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
738 struct lsa_CreateAccount *r)
740 struct lsa_account_state *astate;
742 struct lsa_policy_state *state;
743 struct dcesrv_handle *h, *ah;
745 ZERO_STRUCTP(r->out.acct_handle);
747 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
751 astate = talloc(dce_call->conn, struct lsa_account_state);
752 if (astate == NULL) {
753 return NT_STATUS_NO_MEMORY;
756 astate->account_sid = dom_sid_dup(astate, r->in.sid);
757 if (astate->account_sid == NULL) {
759 return NT_STATUS_NO_MEMORY;
762 astate->policy = talloc_reference(astate, state);
763 astate->access_mask = r->in.access_mask;
766 * For now we grant all requested access.
768 * We will fail at the ldb layer later.
770 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
771 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
772 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
774 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
776 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X].\n",
777 __func__, dom_sid_string(mem_ctx, astate->account_sid),
778 (unsigned)r->in.access_mask,
779 (unsigned)astate->access_mask));
781 ah = dcesrv_handle_create(dce_call, LSA_HANDLE_ACCOUNT);
784 return NT_STATUS_NO_MEMORY;
787 ah->data = talloc_steal(ah, astate);
789 *r->out.acct_handle = ah->wire_handle;
798 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
799 struct lsa_EnumAccounts *r)
801 struct dcesrv_handle *h;
802 struct lsa_policy_state *state;
804 struct ldb_message **res;
805 const char * const attrs[] = { "objectSid", NULL};
808 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
812 /* NOTE: This call must only return accounts that have at least
815 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
816 "(&(objectSid=*)(privilege=*))");
818 return NT_STATUS_INTERNAL_DB_CORRUPTION;
821 if (*r->in.resume_handle >= ret) {
822 return NT_STATUS_NO_MORE_ENTRIES;
825 count = ret - *r->in.resume_handle;
826 if (count > r->in.num_entries) {
827 count = r->in.num_entries;
831 return NT_STATUS_NO_MORE_ENTRIES;
834 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
835 if (r->out.sids->sids == NULL) {
836 return NT_STATUS_NO_MEMORY;
839 for (i=0;i<count;i++) {
840 r->out.sids->sids[i].sid =
841 samdb_result_dom_sid(r->out.sids->sids,
842 res[i + *r->in.resume_handle],
844 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
847 r->out.sids->num_sids = count;
848 *r->out.resume_handle = count + *r->in.resume_handle;
853 /* This decrypts and returns Trusted Domain Auth Information Internal data */
854 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
855 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
856 struct trustDomainPasswords *auth_struct)
858 DATA_BLOB session_key = data_blob(NULL, 0);
859 enum ndr_err_code ndr_err;
862 nt_status = dcesrv_transport_session_key(dce_call, &session_key);
863 if (!NT_STATUS_IS_OK(nt_status)) {
867 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
868 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
870 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
871 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
872 return NT_STATUS_INVALID_PARAMETER;
878 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
880 struct trustAuthInOutBlob *iopw,
881 DATA_BLOB *trustauth_blob)
883 enum ndr_err_code ndr_err;
885 if (iopw->current.count != iopw->count) {
886 return NT_STATUS_INVALID_PARAMETER;
889 if (iopw->previous.count > iopw->current.count) {
890 return NT_STATUS_INVALID_PARAMETER;
893 if (iopw->previous.count == 0) {
895 * If the previous credentials are not present
896 * we need to make a copy.
898 iopw->previous = iopw->current;
901 if (iopw->previous.count < iopw->current.count) {
902 struct AuthenticationInformationArray *c = &iopw->current;
903 struct AuthenticationInformationArray *p = &iopw->previous;
906 * The previous array needs to have the same size
907 * as the current one.
909 * We may have to fill with TRUST_AUTH_TYPE_NONE
912 p->array = talloc_realloc(mem_ctx, p->array,
913 struct AuthenticationInformation,
915 if (p->array == NULL) {
916 return NT_STATUS_NO_MEMORY;
919 while (p->count < c->count) {
920 struct AuthenticationInformation *a =
921 &p->array[p->count++];
923 *a = (struct AuthenticationInformation) {
924 .LastUpdateTime = p->array[0].LastUpdateTime,
925 .AuthType = TRUST_AUTH_TYPE_NONE,
930 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
932 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
933 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
934 return NT_STATUS_INVALID_PARAMETER;
940 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
941 struct ldb_context *sam_ldb,
942 struct ldb_dn *base_dn,
943 const char *netbios_name,
944 struct trustAuthInOutBlob *in,
945 struct ldb_dn **user_dn)
947 struct ldb_request *req;
948 struct ldb_message *msg;
953 dn = ldb_dn_copy(mem_ctx, base_dn);
955 return NT_STATUS_NO_MEMORY;
957 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
958 return NT_STATUS_NO_MEMORY;
961 msg = ldb_msg_new(mem_ctx);
963 return NT_STATUS_NO_MEMORY;
967 ret = ldb_msg_add_string(msg, "objectClass", "user");
968 if (ret != LDB_SUCCESS) {
969 return NT_STATUS_NO_MEMORY;
972 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
973 if (ret != LDB_SUCCESS) {
974 return NT_STATUS_NO_MEMORY;
977 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
978 UF_INTERDOMAIN_TRUST_ACCOUNT);
979 if (ret != LDB_SUCCESS) {
980 return NT_STATUS_NO_MEMORY;
983 for (i = 0; i < in->count; i++) {
984 const char *attribute;
986 switch (in->current.array[i].AuthType) {
987 case TRUST_AUTH_TYPE_NT4OWF:
988 attribute = "unicodePwd";
989 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
992 case TRUST_AUTH_TYPE_CLEAR:
993 attribute = "clearTextPassword";
994 v.data = in->current.array[i].AuthInfo.clear.password;
995 v.length = in->current.array[i].AuthInfo.clear.size;
1001 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1002 if (ret != LDB_SUCCESS) {
1003 return NT_STATUS_NO_MEMORY;
1007 /* create the trusted_domain user account */
1008 ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
1009 ldb_op_default_callback, NULL);
1010 if (ret != LDB_SUCCESS) {
1011 return NT_STATUS_NO_MEMORY;
1014 ret = ldb_request_add_control(req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
1016 if (ret != LDB_SUCCESS) {
1017 return NT_STATUS_NO_MEMORY;
1020 ret = dsdb_autotransaction_request(sam_ldb, req);
1021 if (ret != LDB_SUCCESS) {
1022 DEBUG(0,("Failed to create user record %s: %s\n",
1023 ldb_dn_get_linearized(msg->dn),
1024 ldb_errstring(sam_ldb)));
1027 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1028 return NT_STATUS_DOMAIN_EXISTS;
1029 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1030 return NT_STATUS_ACCESS_DENIED;
1032 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1039 return NT_STATUS_OK;
1043 lsa_CreateTrustedDomainEx2
1045 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
1046 TALLOC_CTX *mem_ctx,
1047 struct lsa_CreateTrustedDomainEx2 *r,
1049 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
1051 struct dcesrv_handle *policy_handle;
1052 struct lsa_policy_state *policy_state;
1053 struct lsa_trusted_domain_state *trusted_domain_state;
1054 struct dcesrv_handle *handle;
1055 struct ldb_message **msgs, *msg;
1056 const char *attrs[] = {
1059 const char *netbios_name;
1060 const char *dns_name;
1061 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1062 struct trustDomainPasswords auth_struct;
1065 struct ldb_context *sam_ldb;
1066 struct server_id *server_ids = NULL;
1067 uint32_t num_server_ids = 0;
1070 char *dns_encoded = NULL;
1071 char *netbios_encoded = NULL;
1072 char *sid_encoded = NULL;
1074 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
1075 ZERO_STRUCTP(r->out.trustdom_handle);
1077 policy_state = policy_handle->data;
1078 sam_ldb = policy_state->sam_ldb;
1080 netbios_name = r->in.info->netbios_name.string;
1081 if (!netbios_name) {
1082 return NT_STATUS_INVALID_PARAMETER;
1085 dns_name = r->in.info->domain_name.string;
1086 if (dns_name == NULL) {
1087 return NT_STATUS_INVALID_PARAMETER;
1090 if (r->in.info->sid == NULL) {
1091 return NT_STATUS_INVALID_SID;
1095 * We expect S-1-5-21-A-B-C, but we don't
1096 * allow S-1-5-21-0-0-0 as this is used
1097 * for claims and compound identities.
1099 ok = dom_sid_is_valid_account_domain(r->in.info->sid);
1101 return NT_STATUS_INVALID_PARAMETER;
1104 dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1105 if (dns_encoded == NULL) {
1106 return NT_STATUS_NO_MEMORY;
1108 netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1109 if (netbios_encoded == NULL) {
1110 return NT_STATUS_NO_MEMORY;
1112 sid_encoded = ldap_encode_ndr_dom_sid(mem_ctx, r->in.info->sid);
1113 if (sid_encoded == NULL) {
1114 return NT_STATUS_NO_MEMORY;
1117 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1118 if (!trusted_domain_state) {
1119 return NT_STATUS_NO_MEMORY;
1121 trusted_domain_state->policy = policy_state;
1123 if (strcasecmp(netbios_name, "BUILTIN") == 0
1124 || (strcasecmp(dns_name, "BUILTIN") == 0)
1125 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
1126 return NT_STATUS_INVALID_PARAMETER;
1129 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
1130 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
1131 || strcasecmp(dns_name, policy_state->domain_dns) == 0
1132 || strcasecmp(dns_name, policy_state->domain_name) == 0
1133 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
1134 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
1137 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
1138 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
1139 /* No secrets are created at this time, for this function */
1140 auth_struct.outgoing.count = 0;
1141 auth_struct.incoming.count = 0;
1142 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
1143 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
1144 r->in.auth_info_internal->auth_blob.size);
1145 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1146 &auth_blob, &auth_struct);
1147 if (!NT_STATUS_IS_OK(nt_status)) {
1150 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
1152 if (unencrypted_auth_info->incoming_count > 1) {
1153 return NT_STATUS_INVALID_PARAMETER;
1156 /* more investigation required here, do not create secrets for
1158 auth_struct.outgoing.count = 0;
1159 auth_struct.incoming.count = 0;
1161 return NT_STATUS_INVALID_PARAMETER;
1164 if (auth_struct.incoming.count) {
1165 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1166 &auth_struct.incoming,
1167 &trustAuthIncoming);
1168 if (!NT_STATUS_IS_OK(nt_status)) {
1172 trustAuthIncoming = data_blob(NULL, 0);
1175 if (auth_struct.outgoing.count) {
1176 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1177 &auth_struct.outgoing,
1178 &trustAuthOutgoing);
1179 if (!NT_STATUS_IS_OK(nt_status)) {
1183 trustAuthOutgoing = data_blob(NULL, 0);
1186 ret = ldb_transaction_start(sam_ldb);
1187 if (ret != LDB_SUCCESS) {
1188 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1191 /* search for the trusted_domain record */
1192 ret = gendb_search(sam_ldb,
1193 mem_ctx, policy_state->system_dn, &msgs, attrs,
1194 "(&(objectClass=trustedDomain)(|"
1195 "(flatname=%s)(trustPartner=%s)"
1196 "(flatname=%s)(trustPartner=%s)"
1197 "(securityIdentifier=%s)))",
1198 dns_encoded, dns_encoded,
1199 netbios_encoded, netbios_encoded,
1202 ldb_transaction_cancel(sam_ldb);
1203 return NT_STATUS_OBJECT_NAME_COLLISION;
1206 ldb_transaction_cancel(sam_ldb);
1207 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1210 msg = ldb_msg_new(mem_ctx);
1212 return NT_STATUS_NO_MEMORY;
1215 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1216 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", dns_name)) {
1217 ldb_transaction_cancel(sam_ldb);
1218 return NT_STATUS_NO_MEMORY;
1221 ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1222 if (ret != LDB_SUCCESS) {
1223 ldb_transaction_cancel(sam_ldb);
1224 return NT_STATUS_NO_MEMORY;;
1227 ret = ldb_msg_add_string(msg, "flatname", netbios_name);
1228 if (ret != LDB_SUCCESS) {
1229 ldb_transaction_cancel(sam_ldb);
1230 return NT_STATUS_NO_MEMORY;
1233 ret = ldb_msg_add_string(msg, "trustPartner", dns_name);
1234 if (ret != LDB_SUCCESS) {
1235 ldb_transaction_cancel(sam_ldb);
1236 return NT_STATUS_NO_MEMORY;;
1239 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier",
1241 if (ret != LDB_SUCCESS) {
1242 ldb_transaction_cancel(sam_ldb);
1243 return NT_STATUS_NO_MEMORY;;
1246 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1247 if (ret != LDB_SUCCESS) {
1248 ldb_transaction_cancel(sam_ldb);
1249 return NT_STATUS_NO_MEMORY;;
1252 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1253 if (ret != LDB_SUCCESS) {
1254 ldb_transaction_cancel(sam_ldb);
1255 return NT_STATUS_NO_MEMORY;;
1258 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1259 if (ret != LDB_SUCCESS) {
1260 ldb_transaction_cancel(sam_ldb);
1261 return NT_STATUS_NO_MEMORY;;
1264 if (trustAuthIncoming.data) {
1265 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1266 if (ret != LDB_SUCCESS) {
1267 ldb_transaction_cancel(sam_ldb);
1268 return NT_STATUS_NO_MEMORY;
1271 if (trustAuthOutgoing.data) {
1272 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1273 if (ret != LDB_SUCCESS) {
1274 ldb_transaction_cancel(sam_ldb);
1275 return NT_STATUS_NO_MEMORY;
1279 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1281 /* create the trusted_domain */
1282 ret = ldb_add(sam_ldb, msg);
1286 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1287 ldb_transaction_cancel(sam_ldb);
1288 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1289 ldb_dn_get_linearized(msg->dn),
1290 ldb_errstring(sam_ldb)));
1291 return NT_STATUS_DOMAIN_EXISTS;
1292 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1293 ldb_transaction_cancel(sam_ldb);
1294 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1295 ldb_dn_get_linearized(msg->dn),
1296 ldb_errstring(sam_ldb)));
1297 return NT_STATUS_ACCESS_DENIED;
1299 ldb_transaction_cancel(sam_ldb);
1300 DEBUG(0,("Failed to create user record %s: %s\n",
1301 ldb_dn_get_linearized(msg->dn),
1302 ldb_errstring(sam_ldb)));
1303 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1306 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1307 struct ldb_dn *user_dn;
1308 /* Inbound trusts must also create a cn=users object to match */
1309 nt_status = add_trust_user(mem_ctx, sam_ldb,
1310 policy_state->domain_dn,
1312 &auth_struct.incoming,
1314 if (!NT_STATUS_IS_OK(nt_status)) {
1315 ldb_transaction_cancel(sam_ldb);
1319 /* save the trust user dn */
1320 trusted_domain_state->trusted_domain_user_dn
1321 = talloc_steal(trusted_domain_state, user_dn);
1324 ret = ldb_transaction_commit(sam_ldb);
1325 if (ret != LDB_SUCCESS) {
1326 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1330 * Notify winbindd that we have a new trust
1332 status = irpc_servers_byname(dce_call->msg_ctx,
1335 &num_server_ids, &server_ids);
1336 if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
1337 imessaging_send(dce_call->msg_ctx, server_ids[0],
1338 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS, NULL);
1340 TALLOC_FREE(server_ids);
1342 handle = dcesrv_handle_create(dce_call, LSA_HANDLE_TRUSTED_DOMAIN);
1344 return NT_STATUS_NO_MEMORY;
1347 handle->data = talloc_steal(handle, trusted_domain_state);
1349 trusted_domain_state->access_mask = r->in.access_mask;
1350 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1352 *r->out.trustdom_handle = handle->wire_handle;
1354 return NT_STATUS_OK;
1358 lsa_CreateTrustedDomainEx2
1360 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1361 TALLOC_CTX *mem_ctx,
1362 struct lsa_CreateTrustedDomainEx2 *r)
1364 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1367 lsa_CreateTrustedDomainEx
1369 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1370 TALLOC_CTX *mem_ctx,
1371 struct lsa_CreateTrustedDomainEx *r)
1373 struct lsa_CreateTrustedDomainEx2 r2;
1375 r2.in.policy_handle = r->in.policy_handle;
1376 r2.in.info = r->in.info;
1377 r2.out.trustdom_handle = r->out.trustdom_handle;
1378 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1382 lsa_CreateTrustedDomain
1384 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1385 struct lsa_CreateTrustedDomain *r)
1387 struct lsa_CreateTrustedDomainEx2 r2;
1389 r2.in.policy_handle = r->in.policy_handle;
1390 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1392 return NT_STATUS_NO_MEMORY;
1395 r2.in.info->domain_name = r->in.info->name;
1396 r2.in.info->netbios_name = r->in.info->name;
1397 r2.in.info->sid = r->in.info->sid;
1398 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1399 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1400 r2.in.info->trust_attributes = 0;
1402 r2.in.access_mask = r->in.access_mask;
1403 r2.out.trustdom_handle = r->out.trustdom_handle;
1405 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1408 static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
1409 struct dcesrv_call_state *dce_call,
1410 TALLOC_CTX *tmp_mem,
1411 struct lsa_policy_state *policy_state,
1413 uint32_t access_mask,
1414 struct dcesrv_handle **_handle)
1416 struct lsa_trusted_domain_state *trusted_domain_state;
1417 struct dcesrv_handle *handle;
1418 struct ldb_message **msgs;
1419 const char *attrs[] = {
1427 /* TODO: perform access checks */
1429 /* search for the trusted_domain record */
1430 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1431 policy_state->system_dn,
1432 &msgs, attrs, "%s", filter);
1434 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1438 DEBUG(0,("Found %d records matching %s under %s\n", ret,
1440 ldb_dn_get_linearized(policy_state->system_dn)));
1441 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1444 trusted_domain_state = talloc_zero(tmp_mem,
1445 struct lsa_trusted_domain_state);
1446 if (!trusted_domain_state) {
1447 return NT_STATUS_NO_MEMORY;
1449 trusted_domain_state->policy = policy_state;
1451 trusted_domain_state->trusted_domain_dn =
1452 talloc_steal(trusted_domain_state, msgs[0]->dn);
1454 direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1455 if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1456 const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1459 /* search for the trusted_domain account */
1460 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1461 policy_state->domain_dn,
1463 "(&(samaccountname=%s$)(objectclass=user)"
1464 "(userAccountControl:%s:=%u))",
1466 LDB_OID_COMPARATOR_AND,
1467 UF_INTERDOMAIN_TRUST_ACCOUNT);
1469 trusted_domain_state->trusted_domain_user_dn =
1470 talloc_steal(trusted_domain_state, msgs[0]->dn);
1474 handle = dcesrv_handle_create(dce_call, LSA_HANDLE_TRUSTED_DOMAIN);
1476 return NT_STATUS_NO_MEMORY;
1479 handle->data = talloc_steal(handle, trusted_domain_state);
1481 trusted_domain_state->access_mask = access_mask;
1482 trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1487 return NT_STATUS_OK;
1491 lsa_OpenTrustedDomain
1493 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1494 struct lsa_OpenTrustedDomain *r)
1496 struct dcesrv_handle *policy_handle;
1497 struct lsa_policy_state *policy_state;
1498 struct dcesrv_handle *handle;
1499 const char *sid_string;
1503 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1504 ZERO_STRUCTP(r->out.trustdom_handle);
1505 policy_state = policy_handle->data;
1507 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1509 return NT_STATUS_NO_MEMORY;
1512 filter = talloc_asprintf(mem_ctx,
1513 "(&(securityIdentifier=%s)"
1514 "(objectclass=trustedDomain))",
1516 if (filter == NULL) {
1517 return NT_STATUS_NO_MEMORY;
1520 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1525 if (!NT_STATUS_IS_OK(status)) {
1529 *r->out.trustdom_handle = handle->wire_handle;
1531 return NT_STATUS_OK;
1536 lsa_OpenTrustedDomainByName
1538 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1539 TALLOC_CTX *mem_ctx,
1540 struct lsa_OpenTrustedDomainByName *r)
1542 struct dcesrv_handle *policy_handle;
1543 struct lsa_policy_state *policy_state;
1544 struct dcesrv_handle *handle;
1549 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1550 ZERO_STRUCTP(r->out.trustdom_handle);
1551 policy_state = policy_handle->data;
1553 if (!r->in.name.string) {
1554 return NT_STATUS_INVALID_PARAMETER;
1557 /* search for the trusted_domain record */
1558 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1559 if (td_name == NULL) {
1560 return NT_STATUS_NO_MEMORY;
1563 filter = talloc_asprintf(mem_ctx,
1564 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1565 "(objectclass=trustedDomain))",
1566 td_name, td_name, td_name);
1567 if (filter == NULL) {
1568 return NT_STATUS_NO_MEMORY;
1571 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1576 if (!NT_STATUS_IS_OK(status)) {
1580 *r->out.trustdom_handle = handle->wire_handle;
1582 return NT_STATUS_OK;
1588 lsa_SetTrustedDomainInfo
1590 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1591 struct lsa_SetTrustedDomainInfo *r)
1593 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1598 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1599 * otherwise at least one must be provided */
1600 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1601 struct ldb_dn *basedn, const char *dns_domain,
1602 const char *netbios, struct dom_sid2 *sid,
1603 struct ldb_message ***msgs)
1605 const char *attrs[] = { "flatname", "trustPartner",
1606 "securityIdentifier", "trustDirection",
1607 "trustType", "trustAttributes",
1609 "msDs-supportedEncryptionTypes",
1610 "msDS-TrustForestTrustInfo",
1615 char *sidstr = NULL;
1620 if (dns_domain || netbios || sid) {
1621 filter = talloc_strdup(mem_ctx,
1622 "(&(objectclass=trustedDomain)(|");
1624 filter = talloc_strdup(mem_ctx,
1625 "(objectclass=trustedDomain)");
1628 return NT_STATUS_NO_MEMORY;
1632 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1634 return NT_STATUS_NO_MEMORY;
1636 filter = talloc_asprintf_append(filter,
1637 "(trustPartner=%s)", dns);
1639 return NT_STATUS_NO_MEMORY;
1643 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1645 return NT_STATUS_NO_MEMORY;
1647 filter = talloc_asprintf_append(filter,
1648 "(flatname=%s)", nbn);
1650 return NT_STATUS_NO_MEMORY;
1654 sidstr = dom_sid_string(mem_ctx, sid);
1656 return NT_STATUS_INVALID_PARAMETER;
1658 filter = talloc_asprintf_append(filter,
1659 "(securityIdentifier=%s)",
1662 return NT_STATUS_NO_MEMORY;
1665 if (dns_domain || netbios || sid) {
1666 filter = talloc_asprintf_append(filter, "))");
1668 return NT_STATUS_NO_MEMORY;
1672 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1674 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1678 return NT_STATUS_OBJECT_NAME_COLLISION;
1681 return NT_STATUS_OK;
1684 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1685 struct ldb_context *sam_ldb,
1686 struct ldb_message *orig,
1687 struct ldb_message *dest,
1688 const char *attribute,
1690 uint32_t *orig_value)
1692 const struct ldb_val *orig_val;
1693 uint32_t orig_uint = 0;
1694 unsigned int flags = 0;
1697 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1698 if (!orig_val || !orig_val->data) {
1699 /* add new attribute */
1700 flags = LDB_FLAG_MOD_ADD;
1704 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1705 if (errno != 0 || orig_uint != value) {
1706 /* replace also if can't get value */
1707 flags = LDB_FLAG_MOD_REPLACE;
1712 /* stored value is identical, nothing to change */
1716 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1717 if (ret != LDB_SUCCESS) {
1718 return NT_STATUS_NO_MEMORY;
1721 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1722 if (ret != LDB_SUCCESS) {
1723 return NT_STATUS_NO_MEMORY;
1728 *orig_value = orig_uint;
1730 return NT_STATUS_OK;
1733 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1734 struct ldb_context *sam_ldb,
1735 struct ldb_dn *base_dn,
1737 const char *netbios_name,
1738 struct trustAuthInOutBlob *in)
1740 const char *attrs[] = { "userAccountControl", NULL };
1741 struct ldb_message **msgs;
1742 struct ldb_message *msg;
1747 ret = gendb_search(sam_ldb, mem_ctx,
1748 base_dn, &msgs, attrs,
1749 "samAccountName=%s$", netbios_name);
1751 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1756 return NT_STATUS_OK;
1759 /* ok no existing user, add it from scratch */
1760 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1761 netbios_name, in, NULL);
1764 /* check user is what we are looking for */
1765 uac = ldb_msg_find_attr_as_uint(msgs[0],
1766 "userAccountControl", 0);
1767 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1768 return NT_STATUS_OBJECT_NAME_COLLISION;
1772 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1775 return NT_STATUS_OK;
1776 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1777 return NT_STATUS_ACCESS_DENIED;
1779 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1783 /* entry exists, just modify secret if any */
1784 if (in == NULL || in->count == 0) {
1785 return NT_STATUS_OK;
1788 msg = ldb_msg_new(mem_ctx);
1790 return NT_STATUS_NO_MEMORY;
1792 msg->dn = msgs[0]->dn;
1794 for (i = 0; i < in->count; i++) {
1795 const char *attribute;
1797 switch (in->current.array[i].AuthType) {
1798 case TRUST_AUTH_TYPE_NT4OWF:
1799 attribute = "unicodePwd";
1800 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1803 case TRUST_AUTH_TYPE_CLEAR:
1804 attribute = "clearTextPassword";
1805 v.data = in->current.array[i].AuthInfo.clear.password;
1806 v.length = in->current.array[i].AuthInfo.clear.size;
1812 ret = ldb_msg_add_empty(msg, attribute,
1813 LDB_FLAG_MOD_REPLACE, NULL);
1814 if (ret != LDB_SUCCESS) {
1815 return NT_STATUS_NO_MEMORY;
1818 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1819 if (ret != LDB_SUCCESS) {
1820 return NT_STATUS_NO_MEMORY;
1824 /* create the trusted_domain user account */
1825 ret = ldb_modify(sam_ldb, msg);
1826 if (ret != LDB_SUCCESS) {
1827 DEBUG(0,("Failed to create user record %s: %s\n",
1828 ldb_dn_get_linearized(msg->dn),
1829 ldb_errstring(sam_ldb)));
1832 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1833 return NT_STATUS_DOMAIN_EXISTS;
1834 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1835 return NT_STATUS_ACCESS_DENIED;
1837 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1841 return NT_STATUS_OK;
1845 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1846 struct lsa_policy_state *p_state,
1847 TALLOC_CTX *mem_ctx,
1848 struct ldb_message *dom_msg,
1849 enum lsa_TrustDomInfoEnum level,
1850 union lsa_TrustedDomainInfo *info)
1852 uint32_t *posix_offset = NULL;
1853 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1854 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1855 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1856 uint32_t *enc_types = NULL;
1857 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1858 struct trustDomainPasswords auth_struct;
1859 struct trustAuthInOutBlob *current_passwords = NULL;
1861 struct ldb_message **msgs;
1862 struct ldb_message *msg;
1863 bool add_outgoing = false;
1864 bool add_incoming = false;
1865 bool del_outgoing = false;
1866 bool del_incoming = false;
1867 bool del_forest_info = false;
1868 bool in_transaction = false;
1873 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1874 posix_offset = &info->posix_offset.posix_offset;
1876 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1877 info_ex = &info->info_ex;
1879 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1880 auth_info = &info->auth_info;
1882 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1883 posix_offset = &info->full_info.posix_offset.posix_offset;
1884 info_ex = &info->full_info.info_ex;
1885 auth_info = &info->full_info.auth_info;
1887 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1888 auth_info_int = &info->auth_info_internal;
1890 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1891 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1892 info_ex = &info->full_info_internal.info_ex;
1893 auth_info_int = &info->full_info_internal.auth_info;
1895 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1896 enc_types = &info->enc_types.enc_types;
1899 return NT_STATUS_INVALID_PARAMETER;
1903 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1905 &trustAuthOutgoing);
1906 if (!NT_STATUS_IS_OK(nt_status)) {
1909 if (trustAuthIncoming.data) {
1910 /* This does the decode of some of this twice, but it is easier that way */
1911 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1912 auth_info->incoming_count,
1913 auth_info->incoming_current_auth_info,
1915 ¤t_passwords);
1916 if (!NT_STATUS_IS_OK(nt_status)) {
1922 /* decode auth_info_int if set */
1923 if (auth_info_int) {
1925 /* now decrypt blob */
1926 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1927 auth_info_int->auth_blob.size);
1929 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1930 &auth_blob, &auth_struct);
1931 if (!NT_STATUS_IS_OK(nt_status)) {
1937 /* verify data matches */
1938 if (info_ex->trust_attributes &
1939 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1940 /* TODO: check what behavior level we have */
1941 if (strcasecmp_m(p_state->domain_dns,
1942 p_state->forest_dns) != 0) {
1943 return NT_STATUS_INVALID_DOMAIN_STATE;
1947 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1948 if (ret == LDB_SUCCESS && am_rodc) {
1949 return NT_STATUS_NO_SUCH_DOMAIN;
1952 /* verify only one object matches the dns/netbios/sid
1953 * triplet and that this is the one we already have */
1954 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1956 info_ex->domain_name.string,
1957 info_ex->netbios_name.string,
1958 info_ex->sid, &msgs);
1959 if (!NT_STATUS_IS_OK(nt_status)) {
1962 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1963 return NT_STATUS_OBJECT_NAME_COLLISION;
1968 /* TODO: should we fetch previous values from the existing entry
1969 * and append them ? */
1970 if (auth_info_int && auth_struct.incoming.count) {
1971 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1972 &auth_struct.incoming,
1973 &trustAuthIncoming);
1974 if (!NT_STATUS_IS_OK(nt_status)) {
1978 current_passwords = &auth_struct.incoming;
1981 trustAuthIncoming = data_blob(NULL, 0);
1984 if (auth_info_int && auth_struct.outgoing.count) {
1985 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1986 &auth_struct.outgoing,
1987 &trustAuthOutgoing);
1988 if (!NT_STATUS_IS_OK(nt_status)) {
1992 trustAuthOutgoing = data_blob(NULL, 0);
1995 msg = ldb_msg_new(mem_ctx);
1997 return NT_STATUS_NO_MEMORY;
1999 msg->dn = dom_msg->dn;
2002 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2005 *posix_offset, NULL);
2006 if (!NT_STATUS_IS_OK(nt_status)) {
2013 uint32_t changed_attrs;
2017 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2020 info_ex->trust_direction,
2022 if (!NT_STATUS_IS_OK(nt_status)) {
2026 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2027 if (auth_info != NULL && trustAuthIncoming.length > 0) {
2028 add_incoming = true;
2031 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2032 if (auth_info != NULL && trustAuthOutgoing.length > 0) {
2033 add_outgoing = true;
2037 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
2038 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
2039 del_incoming = true;
2041 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
2042 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2043 del_outgoing = true;
2046 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
2047 if (origtype == -1 || origtype != info_ex->trust_type) {
2048 DEBUG(1, ("Attempted to change trust type! "
2049 "Operation not handled\n"));
2050 return NT_STATUS_INVALID_PARAMETER;
2053 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2056 info_ex->trust_attributes,
2058 if (!NT_STATUS_IS_OK(nt_status)) {
2061 /* TODO: check forestFunctionality from ldb opaque */
2062 /* TODO: check what is set makes sense */
2064 changed_attrs = origattrs ^ info_ex->trust_attributes;
2065 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2067 * For now we only allow
2068 * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
2070 * TODO: we may need to support more attribute changes
2072 DEBUG(1, ("Attempted to change trust attributes "
2073 "(0x%08x != 0x%08x)! "
2074 "Operation not handled yet...\n",
2075 (unsigned)origattrs,
2076 (unsigned)info_ex->trust_attributes));
2077 return NT_STATUS_INVALID_PARAMETER;
2080 if (!(info_ex->trust_attributes &
2081 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
2083 struct ldb_message_element *orig_forest_el = NULL;
2085 orig_forest_el = ldb_msg_find_element(dom_msg,
2086 "msDS-TrustForestTrustInfo");
2087 if (orig_forest_el != NULL) {
2088 del_forest_info = true;
2094 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2096 "msDS-SupportedEncryptionTypes",
2098 if (!NT_STATUS_IS_OK(nt_status)) {
2103 if (add_incoming || del_incoming) {
2104 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
2105 LDB_FLAG_MOD_REPLACE, NULL);
2106 if (ret != LDB_SUCCESS) {
2107 return NT_STATUS_NO_MEMORY;
2110 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
2111 &trustAuthIncoming, NULL);
2112 if (ret != LDB_SUCCESS) {
2113 return NT_STATUS_NO_MEMORY;
2117 if (add_outgoing || del_outgoing) {
2118 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2119 LDB_FLAG_MOD_REPLACE, NULL);
2120 if (ret != LDB_SUCCESS) {
2121 return NT_STATUS_NO_MEMORY;
2124 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
2125 &trustAuthOutgoing, NULL);
2126 if (ret != LDB_SUCCESS) {
2127 return NT_STATUS_NO_MEMORY;
2131 if (del_forest_info) {
2132 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
2133 LDB_FLAG_MOD_REPLACE, NULL);
2134 if (ret != LDB_SUCCESS) {
2135 return NT_STATUS_NO_MEMORY;
2139 /* start transaction */
2140 ret = ldb_transaction_start(p_state->sam_ldb);
2141 if (ret != LDB_SUCCESS) {
2142 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2144 in_transaction = true;
2146 if (msg->num_elements) {
2147 ret = ldb_modify(p_state->sam_ldb, msg);
2148 if (ret != LDB_SUCCESS) {
2149 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
2150 ldb_dn_get_linearized(msg->dn),
2151 ldb_errstring(p_state->sam_ldb)));
2152 nt_status = dsdb_ldb_err_to_ntstatus(ret);
2157 if (add_incoming || del_incoming) {
2158 const char *netbios_name;
2160 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
2162 if (!netbios_name) {
2163 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
2167 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
2168 nt_status = update_trust_user(mem_ctx,
2174 if (!NT_STATUS_IS_OK(nt_status)) {
2179 /* ok, all fine, commit transaction and return */
2180 ret = ldb_transaction_commit(p_state->sam_ldb);
2181 if (ret != LDB_SUCCESS) {
2182 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2184 in_transaction = false;
2186 nt_status = NT_STATUS_OK;
2189 if (in_transaction) {
2190 ldb_transaction_cancel(p_state->sam_ldb);
2196 lsa_SetInfomrationTrustedDomain
2198 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
2199 struct dcesrv_call_state *dce_call,
2200 TALLOC_CTX *mem_ctx,
2201 struct lsa_SetInformationTrustedDomain *r)
2203 struct dcesrv_handle *h;
2204 struct lsa_trusted_domain_state *td_state;
2205 struct ldb_message **msgs;
2208 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
2209 LSA_HANDLE_TRUSTED_DOMAIN);
2211 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2213 /* get the trusted domain object */
2214 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
2215 td_state->trusted_domain_dn,
2216 NULL, NULL, NULL, &msgs);
2217 if (!NT_STATUS_IS_OK(nt_status)) {
2218 if (NT_STATUS_EQUAL(nt_status,
2219 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2222 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2225 return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
2226 msgs[0], r->in.level, r->in.info);
2231 lsa_DeleteTrustedDomain
2233 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2234 struct lsa_DeleteTrustedDomain *r)
2237 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2238 struct lsa_DeleteObject del;
2239 struct dcesrv_handle *h;
2241 opn.in.handle = r->in.handle;
2242 opn.in.sid = r->in.dom_sid;
2243 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2244 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2245 if (!opn.out.trustdom_handle) {
2246 return NT_STATUS_NO_MEMORY;
2248 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2249 if (!NT_STATUS_IS_OK(status)) {
2253 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2254 talloc_steal(mem_ctx, h);
2256 del.in.handle = opn.out.trustdom_handle;
2257 del.out.handle = opn.out.trustdom_handle;
2258 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2259 if (!NT_STATUS_IS_OK(status)) {
2262 return NT_STATUS_OK;
2265 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2266 struct ldb_message *msg,
2267 struct lsa_TrustDomainInfoInfoEx *info_ex)
2269 info_ex->domain_name.string
2270 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2271 info_ex->netbios_name.string
2272 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2274 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2275 info_ex->trust_direction
2276 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2278 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2279 info_ex->trust_attributes
2280 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2281 return NT_STATUS_OK;
2285 lsa_QueryTrustedDomainInfo
2287 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2288 struct lsa_QueryTrustedDomainInfo *r)
2290 union lsa_TrustedDomainInfo *info = NULL;
2291 struct dcesrv_handle *h;
2292 struct lsa_trusted_domain_state *trusted_domain_state;
2293 struct ldb_message *msg;
2295 struct ldb_message **res;
2296 const char *attrs[] = {
2299 "securityIdentifier",
2303 "msDs-supportedEncryptionTypes",
2307 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2309 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2311 /* pull all the user attributes */
2312 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2313 trusted_domain_state->trusted_domain_dn, &res, attrs);
2315 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2319 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2321 return NT_STATUS_NO_MEMORY;
2323 *r->out.info = info;
2325 switch (r->in.level) {
2326 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2327 info->name.netbios_name.string
2328 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2330 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2331 info->posix_offset.posix_offset
2332 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2334 #if 0 /* Win2k3 doesn't implement this */
2335 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2336 r->out.info->info_basic.netbios_name.string
2337 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2338 r->out.info->info_basic.sid
2339 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2342 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2343 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2345 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2346 ZERO_STRUCT(info->full_info);
2347 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2348 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2349 ZERO_STRUCT(info->full_info2_internal);
2350 info->full_info2_internal.posix_offset.posix_offset
2351 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2352 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2354 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2355 info->enc_types.enc_types
2356 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2359 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2360 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2361 /* oops, we don't want to return the info after all */
2363 *r->out.info = NULL;
2364 return NT_STATUS_INVALID_PARAMETER;
2366 /* oops, we don't want to return the info after all */
2368 *r->out.info = NULL;
2369 return NT_STATUS_INVALID_INFO_CLASS;
2372 return NT_STATUS_OK;
2377 lsa_QueryTrustedDomainInfoBySid
2379 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2380 struct lsa_QueryTrustedDomainInfoBySid *r)
2383 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2384 struct lsa_QueryTrustedDomainInfo query;
2385 struct dcesrv_handle *h;
2387 opn.in.handle = r->in.handle;
2388 opn.in.sid = r->in.dom_sid;
2389 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2390 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2391 if (!opn.out.trustdom_handle) {
2392 return NT_STATUS_NO_MEMORY;
2394 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2395 if (!NT_STATUS_IS_OK(status)) {
2399 /* Ensure this handle goes away at the end of this call */
2400 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2401 talloc_steal(mem_ctx, h);
2403 query.in.trustdom_handle = opn.out.trustdom_handle;
2404 query.in.level = r->in.level;
2405 query.out.info = r->out.info;
2406 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2407 if (!NT_STATUS_IS_OK(status)) {
2411 return NT_STATUS_OK;
2415 lsa_SetTrustedDomainInfoByName
2417 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2418 TALLOC_CTX *mem_ctx,
2419 struct lsa_SetTrustedDomainInfoByName *r)
2421 struct dcesrv_handle *policy_handle;
2422 struct lsa_policy_state *policy_state;
2423 struct ldb_message **msgs;
2426 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2427 policy_state = policy_handle->data;
2429 /* get the trusted domain object */
2430 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2431 policy_state->domain_dn,
2432 r->in.trusted_domain->string,
2433 r->in.trusted_domain->string,
2435 if (!NT_STATUS_IS_OK(nt_status)) {
2436 if (NT_STATUS_EQUAL(nt_status,
2437 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2440 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2443 return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2444 msgs[0], r->in.level, r->in.info);
2448 lsa_QueryTrustedDomainInfoByName
2450 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2451 TALLOC_CTX *mem_ctx,
2452 struct lsa_QueryTrustedDomainInfoByName *r)
2455 struct lsa_OpenTrustedDomainByName opn = {{0},{0}};
2456 struct lsa_QueryTrustedDomainInfo query;
2457 struct dcesrv_handle *h;
2459 opn.in.handle = r->in.handle;
2460 opn.in.name = *r->in.trusted_domain;
2461 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2462 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2463 if (!opn.out.trustdom_handle) {
2464 return NT_STATUS_NO_MEMORY;
2466 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2467 if (!NT_STATUS_IS_OK(status)) {
2471 /* Ensure this handle goes away at the end of this call */
2472 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2473 talloc_steal(mem_ctx, h);
2475 query.in.trustdom_handle = opn.out.trustdom_handle;
2476 query.in.level = r->in.level;
2477 query.out.info = r->out.info;
2478 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2479 if (!NT_STATUS_IS_OK(status)) {
2483 return NT_STATUS_OK;
2487 lsa_CloseTrustedDomainEx
2489 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2490 TALLOC_CTX *mem_ctx,
2491 struct lsa_CloseTrustedDomainEx *r)
2493 /* The result of a bad hair day from an IDL programmer? Not
2494 * implmented in Win2k3. You should always just lsa_Close
2496 return NT_STATUS_NOT_IMPLEMENTED;
2501 comparison function for sorting lsa_DomainInformation array
2503 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2505 return strcasecmp_m(e1->name.string, e2->name.string);
2511 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2512 struct lsa_EnumTrustDom *r)
2514 struct dcesrv_handle *policy_handle;
2515 struct lsa_DomainInfo *entries;
2516 struct lsa_policy_state *policy_state;
2517 struct ldb_message **domains;
2518 const char *attrs[] = {
2520 "securityIdentifier",
2527 *r->out.resume_handle = 0;
2529 r->out.domains->domains = NULL;
2530 r->out.domains->count = 0;
2532 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2534 policy_state = policy_handle->data;
2536 /* search for all users in this domain. This could possibly be cached and
2537 resumed based on resume_key */
2538 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2539 "objectclass=trustedDomain");
2541 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2544 /* convert to lsa_TrustInformation format */
2545 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2547 return NT_STATUS_NO_MEMORY;
2549 for (i=0;i<count;i++) {
2550 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2551 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2554 /* sort the results by name */
2555 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2557 if (*r->in.resume_handle >= count) {
2558 *r->out.resume_handle = -1;
2560 return NT_STATUS_NO_MORE_ENTRIES;
2563 /* return the rest, limit by max_size. Note that we
2564 use the w2k3 element size value of 60 */
2565 r->out.domains->count = count - *r->in.resume_handle;
2566 r->out.domains->count = MIN(r->out.domains->count,
2567 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2569 r->out.domains->domains = entries + *r->in.resume_handle;
2571 if (r->out.domains->count < count - *r->in.resume_handle) {
2572 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2573 return STATUS_MORE_ENTRIES;
2576 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2577 * always be larger than the previous input resume handle, in
2578 * particular when hitting the last query it is vital to set the
2579 * resume handle correctly to avoid infinite client loops, as
2580 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2581 * status is NT_STATUS_OK - gd */
2583 *r->out.resume_handle = (uint32_t)-1;
2585 return NT_STATUS_OK;
2589 comparison function for sorting lsa_DomainInformation array
2591 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2593 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2597 lsa_EnumTrustedDomainsEx
2599 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2600 struct lsa_EnumTrustedDomainsEx *r)
2602 struct dcesrv_handle *policy_handle;
2603 struct lsa_TrustDomainInfoInfoEx *entries;
2604 struct lsa_policy_state *policy_state;
2605 struct ldb_message **domains;
2606 const char *attrs[] = {
2609 "securityIdentifier",
2619 *r->out.resume_handle = 0;
2621 r->out.domains->domains = NULL;
2622 r->out.domains->count = 0;
2624 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2626 policy_state = policy_handle->data;
2628 /* search for all users in this domain. This could possibly be cached and
2629 resumed based on resume_key */
2630 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2631 "objectclass=trustedDomain");
2633 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2636 /* convert to lsa_DomainInformation format */
2637 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2639 return NT_STATUS_NO_MEMORY;
2641 for (i=0;i<count;i++) {
2642 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2643 if (!NT_STATUS_IS_OK(nt_status)) {
2648 /* sort the results by name */
2649 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2651 if (*r->in.resume_handle >= count) {
2652 *r->out.resume_handle = -1;
2654 return NT_STATUS_NO_MORE_ENTRIES;
2657 /* return the rest, limit by max_size. Note that we
2658 use the w2k3 element size value of 60 */
2659 r->out.domains->count = count - *r->in.resume_handle;
2660 r->out.domains->count = MIN(r->out.domains->count,
2661 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2663 r->out.domains->domains = entries + *r->in.resume_handle;
2665 if (r->out.domains->count < count - *r->in.resume_handle) {
2666 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2667 return STATUS_MORE_ENTRIES;
2670 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2672 return NT_STATUS_OK;
2679 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2680 struct lsa_OpenAccount *r)
2682 struct dcesrv_handle *h, *ah;
2683 struct lsa_policy_state *state;
2684 struct lsa_account_state *astate;
2686 ZERO_STRUCTP(r->out.acct_handle);
2688 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2692 astate = talloc(dce_call->conn, struct lsa_account_state);
2693 if (astate == NULL) {
2694 return NT_STATUS_NO_MEMORY;
2697 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2698 if (astate->account_sid == NULL) {
2699 talloc_free(astate);
2700 return NT_STATUS_NO_MEMORY;
2703 astate->policy = talloc_reference(astate, state);
2704 astate->access_mask = r->in.access_mask;
2707 * For now we grant all requested access.
2709 * We will fail at the ldb layer later.
2711 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2712 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2713 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2715 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2717 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2718 __func__, dom_sid_string(mem_ctx, astate->account_sid),
2719 (unsigned)r->in.access_mask,
2720 (unsigned)astate->access_mask));
2722 ah = dcesrv_handle_create(dce_call, LSA_HANDLE_ACCOUNT);
2724 talloc_free(astate);
2725 return NT_STATUS_NO_MEMORY;
2728 ah->data = talloc_steal(ah, astate);
2730 *r->out.acct_handle = ah->wire_handle;
2732 return NT_STATUS_OK;
2737 lsa_EnumPrivsAccount
2739 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2740 TALLOC_CTX *mem_ctx,
2741 struct lsa_EnumPrivsAccount *r)
2743 struct dcesrv_handle *h;
2744 struct lsa_account_state *astate;
2747 struct ldb_message **res;
2748 const char * const attrs[] = { "privilege", NULL};
2749 struct ldb_message_element *el;
2751 struct lsa_PrivilegeSet *privs;
2753 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2757 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2758 if (privs == NULL) {
2759 return NT_STATUS_NO_MEMORY;
2765 *r->out.privs = privs;
2767 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2768 if (sidstr == NULL) {
2769 return NT_STATUS_NO_MEMORY;
2772 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2773 "objectSid=%s", sidstr);
2775 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2778 return NT_STATUS_OK;
2781 el = ldb_msg_find_element(res[0], "privilege");
2782 if (el == NULL || el->num_values == 0) {
2783 return NT_STATUS_OK;
2786 privs->set = talloc_array(privs,
2787 struct lsa_LUIDAttribute, el->num_values);
2788 if (privs->set == NULL) {
2789 return NT_STATUS_NO_MEMORY;
2793 for (i=0;i<el->num_values;i++) {
2794 int id = sec_privilege_id((const char *)el->values[i].data);
2795 if (id == SEC_PRIV_INVALID) {
2796 /* Perhaps an account right, not a privilege */
2799 privs->set[j].attribute = 0;
2800 privs->set[j].luid.low = id;
2801 privs->set[j].luid.high = 0;
2807 return NT_STATUS_OK;
2811 lsa_EnumAccountRights
2813 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2814 TALLOC_CTX *mem_ctx,
2815 struct lsa_EnumAccountRights *r)
2817 struct dcesrv_handle *h;
2818 struct lsa_policy_state *state;
2821 struct ldb_message **res;
2822 const char * const attrs[] = { "privilege", NULL};
2824 struct ldb_message_element *el;
2826 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2830 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2831 if (sidstr == NULL) {
2832 return NT_STATUS_NO_MEMORY;
2835 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2836 "(&(objectSid=%s)(privilege=*))", sidstr);
2838 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2841 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2842 dom_sid_string(mem_ctx, r->in.sid),
2843 ldb_errstring(state->pdb)));
2844 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2847 el = ldb_msg_find_element(res[0], "privilege");
2848 if (el == NULL || el->num_values == 0) {
2849 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2852 r->out.rights->count = el->num_values;
2853 r->out.rights->names = talloc_array(r->out.rights,
2854 struct lsa_StringLarge, r->out.rights->count);
2855 if (r->out.rights->names == NULL) {
2856 return NT_STATUS_NO_MEMORY;
2859 for (i=0;i<el->num_values;i++) {
2860 r->out.rights->names[i].string = (const char *)el->values[i].data;
2863 return NT_STATUS_OK;
2869 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2871 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2872 TALLOC_CTX *mem_ctx,
2873 struct lsa_policy_state *state,
2875 struct dom_sid *sid,
2876 const struct lsa_RightSet *rights)
2878 struct auth_session_info *session_info =
2879 dcesrv_call_session_info(dce_call);
2880 const char *sidstr, *sidndrstr;
2881 struct ldb_message *msg;
2882 struct ldb_message_element *el;
2885 struct lsa_EnumAccountRights r2;
2888 if (security_session_user_level(session_info, NULL) <
2889 SECURITY_ADMINISTRATOR) {
2890 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2891 return NT_STATUS_ACCESS_DENIED;
2894 msg = ldb_msg_new(mem_ctx);
2896 return NT_STATUS_NO_MEMORY;
2899 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2900 if (sidndrstr == NULL) {
2902 return NT_STATUS_NO_MEMORY;
2905 sidstr = dom_sid_string(msg, sid);
2906 if (sidstr == NULL) {
2908 return NT_STATUS_NO_MEMORY;
2911 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2912 if (dnstr == NULL) {
2914 return NT_STATUS_NO_MEMORY;
2917 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2918 if (msg->dn == NULL) {
2920 return NT_STATUS_NO_MEMORY;
2923 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2926 r2.in.handle = &state->handle->wire_handle;
2928 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2930 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2931 if (!NT_STATUS_IS_OK(status)) {
2932 ZERO_STRUCTP(r2.out.rights);
2936 for (i=0;i<rights->count;i++) {
2939 ok = dcesrc_lsa_valid_AccountRight(rights->names[i].string);
2942 return NT_STATUS_NO_SUCH_PRIVILEGE;
2945 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2947 for (j=0;j<r2.out.rights->count;j++) {
2948 if (strcasecmp_m(r2.out.rights->names[j].string,
2949 rights->names[i].string) == 0) {
2953 if (j != r2.out.rights->count) continue;
2956 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2957 if (ret != LDB_SUCCESS) {
2959 return NT_STATUS_NO_MEMORY;
2963 el = ldb_msg_find_element(msg, "privilege");
2966 return NT_STATUS_OK;
2969 el->flags = ldb_flag;
2971 ret = ldb_modify(state->pdb, msg);
2972 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2973 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2975 return NT_STATUS_NO_MEMORY;
2977 ldb_msg_add_string(msg, "comment", "added via LSA");
2978 ret = ldb_add(state->pdb, msg);
2980 if (ret != LDB_SUCCESS) {
2981 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2983 return NT_STATUS_OK;
2985 DEBUG(3, ("Could not %s attributes from %s: %s",
2986 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2987 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2989 return NT_STATUS_UNEXPECTED_IO_ERROR;
2993 return NT_STATUS_OK;
2997 lsa_AddPrivilegesToAccount
2999 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3000 struct lsa_AddPrivilegesToAccount *r)
3002 struct lsa_RightSet rights;
3003 struct dcesrv_handle *h;
3004 struct lsa_account_state *astate;
3007 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3011 rights.count = r->in.privs->count;
3012 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
3013 if (rights.names == NULL) {
3014 return NT_STATUS_NO_MEMORY;
3016 for (i=0;i<rights.count;i++) {
3017 int id = r->in.privs->set[i].luid.low;
3018 if (r->in.privs->set[i].luid.high) {
3019 return NT_STATUS_NO_SUCH_PRIVILEGE;
3021 rights.names[i].string = sec_privilege_name(id);
3022 if (rights.names[i].string == NULL) {
3023 return NT_STATUS_NO_SUCH_PRIVILEGE;
3027 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3028 LDB_FLAG_MOD_ADD, astate->account_sid,
3034 lsa_RemovePrivilegesFromAccount
3036 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3037 struct lsa_RemovePrivilegesFromAccount *r)
3039 struct lsa_RightSet *rights;
3040 struct dcesrv_handle *h;
3041 struct lsa_account_state *astate;
3044 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3048 rights = talloc(mem_ctx, struct lsa_RightSet);
3050 if (r->in.remove_all == 1 &&
3051 r->in.privs == NULL) {
3052 struct lsa_EnumAccountRights r2;
3055 r2.in.handle = &astate->policy->handle->wire_handle;
3056 r2.in.sid = astate->account_sid;
3057 r2.out.rights = rights;
3059 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
3060 if (!NT_STATUS_IS_OK(status)) {
3064 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3065 LDB_FLAG_MOD_DELETE, astate->account_sid,
3069 if (r->in.remove_all != 0) {
3070 return NT_STATUS_INVALID_PARAMETER;
3073 rights->count = r->in.privs->count;
3074 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
3075 if (rights->names == NULL) {
3076 return NT_STATUS_NO_MEMORY;
3078 for (i=0;i<rights->count;i++) {
3079 int id = r->in.privs->set[i].luid.low;
3080 if (r->in.privs->set[i].luid.high) {
3081 return NT_STATUS_NO_SUCH_PRIVILEGE;
3083 rights->names[i].string = sec_privilege_name(id);
3084 if (rights->names[i].string == NULL) {
3085 return NT_STATUS_NO_SUCH_PRIVILEGE;
3089 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3090 LDB_FLAG_MOD_DELETE, astate->account_sid,
3096 lsa_GetQuotasForAccount
3098 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3099 struct lsa_GetQuotasForAccount *r)
3101 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3106 lsa_SetQuotasForAccount
3108 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3109 struct lsa_SetQuotasForAccount *r)
3111 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3116 lsa_GetSystemAccessAccount
3118 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3119 struct lsa_GetSystemAccessAccount *r)
3121 struct dcesrv_handle *h;
3122 struct lsa_account_state *astate;
3125 struct ldb_message **res;
3126 const char * const attrs[] = { "privilege", NULL};
3127 struct ldb_message_element *el;
3130 *(r->out.access_mask) = 0x00000000;
3132 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3136 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
3137 if (sidstr == NULL) {
3138 return NT_STATUS_NO_MEMORY;
3141 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
3142 "objectSid=%s", sidstr);
3144 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3147 return NT_STATUS_OK;
3150 el = ldb_msg_find_element(res[0], "privilege");
3151 if (el == NULL || el->num_values == 0) {
3152 return NT_STATUS_OK;
3155 for (i=0;i<el->num_values;i++) {
3156 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
3157 if (right_bit == 0) {
3158 /* Perhaps an privilege, not a right */
3161 *(r->out.access_mask) |= right_bit;
3164 return NT_STATUS_OK;
3169 lsa_SetSystemAccessAccount
3171 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3172 struct lsa_SetSystemAccessAccount *r)
3174 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3179 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3180 struct lsa_CreateSecret *r)
3182 struct auth_session_info *session_info =
3183 dcesrv_call_session_info(dce_call);
3184 struct dcesrv_handle *policy_handle;
3185 struct lsa_policy_state *policy_state;
3186 struct lsa_secret_state *secret_state;
3187 struct dcesrv_handle *handle;
3188 struct ldb_message **msgs, *msg;
3189 struct ldb_context *samdb = NULL;
3190 const char *attrs[] = {
3198 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3199 ZERO_STRUCTP(r->out.sec_handle);
3201 switch (security_session_user_level(session_info, NULL))
3203 case SECURITY_SYSTEM:
3204 case SECURITY_ADMINISTRATOR:
3207 /* Users and annonymous are not allowed create secrets */
3208 return NT_STATUS_ACCESS_DENIED;
3211 policy_state = policy_handle->data;
3213 if (!r->in.name.string) {
3214 return NT_STATUS_INVALID_PARAMETER;
3217 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3218 NT_STATUS_HAVE_NO_MEMORY(secret_state);
3219 secret_state->policy = policy_state;
3221 msg = ldb_msg_new(mem_ctx);
3223 return NT_STATUS_NO_MEMORY;
3226 if (strncmp("G$", r->in.name.string, 2) == 0) {
3229 secret_state->global = true;
3231 name = &r->in.name.string[2];
3232 if (strlen(name) == 0) {
3233 return NT_STATUS_INVALID_PARAMETER;
3236 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3237 ldb_binary_encode_string(mem_ctx, name));
3238 NT_STATUS_HAVE_NO_MEMORY(name2);
3241 * We need to connect to the database as system, as this is
3242 * one of the rare RPC calls that must read the secrets
3243 * (and this is denied otherwise)
3245 * We also save the current remote session details so they can
3246 * used by the audit logging module. This allows the audit
3247 * logging to report the remote users details, rather than the
3248 * system users details.
3250 samdb = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
3251 secret_state->sam_ldb = talloc_reference(secret_state, samdb);
3252 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3254 /* search for the secret record */
3255 ret = gendb_search(secret_state->sam_ldb,
3256 mem_ctx, policy_state->system_dn, &msgs, attrs,
3257 "(&(cn=%s)(objectclass=secret))",
3260 return NT_STATUS_OBJECT_NAME_COLLISION;
3264 DEBUG(0,("Failure searching for CN=%s: %s\n",
3265 name2, ldb_errstring(secret_state->sam_ldb)));
3266 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3269 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3270 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3271 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3272 return NT_STATUS_NO_MEMORY;
3275 ret = ldb_msg_add_string(msg, "cn", name2);
3276 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3278 secret_state->global = false;
3280 name = r->in.name.string;
3281 if (strlen(name) == 0) {
3282 return NT_STATUS_INVALID_PARAMETER;
3285 secret_state->sam_ldb = talloc_reference(secret_state,
3286 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3287 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3289 /* search for the secret record */
3290 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3291 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3293 "(&(cn=%s)(objectclass=secret))",
3294 ldb_binary_encode_string(mem_ctx, name));
3296 return NT_STATUS_OBJECT_NAME_COLLISION;
3300 DEBUG(0,("Failure searching for CN=%s: %s\n",
3301 name, ldb_errstring(secret_state->sam_ldb)));
3302 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3305 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3306 "cn=%s,cn=LSA Secrets", name);
3307 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3308 ret = ldb_msg_add_string(msg, "cn", name);
3309 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3312 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3313 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3315 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3316 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3318 /* create the secret */
3319 ret = ldb_add(secret_state->sam_ldb, msg);
3320 if (ret != LDB_SUCCESS) {
3321 DEBUG(0,("Failed to create secret record %s: %s\n",
3322 ldb_dn_get_linearized(msg->dn),
3323 ldb_errstring(secret_state->sam_ldb)));
3324 return NT_STATUS_ACCESS_DENIED;
3327 handle = dcesrv_handle_create(dce_call, LSA_HANDLE_SECRET);
3328 NT_STATUS_HAVE_NO_MEMORY(handle);
3330 handle->data = talloc_steal(handle, secret_state);
3332 secret_state->access_mask = r->in.access_mask;
3333 secret_state->policy = talloc_reference(secret_state, policy_state);
3334 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3336 *r->out.sec_handle = handle->wire_handle;
3338 return NT_STATUS_OK;
3345 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3346 struct lsa_OpenSecret *r)
3348 struct auth_session_info *session_info =
3349 dcesrv_call_session_info(dce_call);
3350 struct dcesrv_handle *policy_handle;
3351 struct lsa_policy_state *policy_state;
3352 struct lsa_secret_state *secret_state;
3353 struct dcesrv_handle *handle;
3354 struct ldb_message **msgs;
3355 struct ldb_context *samdb = NULL;
3356 const char *attrs[] = {
3362 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3363 ZERO_STRUCTP(r->out.sec_handle);
3364 policy_state = policy_handle->data;
3366 if (!r->in.name.string) {
3367 return NT_STATUS_INVALID_PARAMETER;
3370 switch (security_session_user_level(session_info, NULL))
3372 case SECURITY_SYSTEM:
3373 case SECURITY_ADMINISTRATOR:
3376 /* Users and annonymous are not allowed to access secrets */
3377 return NT_STATUS_ACCESS_DENIED;
3380 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3381 if (!secret_state) {
3382 return NT_STATUS_NO_MEMORY;
3384 secret_state->policy = policy_state;
3386 if (strncmp("G$", r->in.name.string, 2) == 0) {
3387 name = &r->in.name.string[2];
3389 * We need to connect to the database as system, as this is
3390 * one of the rare RPC calls that must read the secrets
3391 * (and this is denied otherwise)
3393 * We also save the current remote session details so they can
3394 * used by the audit logging module. This allows the audit
3395 * logging to report the remote users details, rather than the
3396 * system users details.
3398 samdb = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
3399 secret_state->sam_ldb = talloc_reference(secret_state, samdb);
3400 secret_state->global = true;
3402 if (strlen(name) < 1) {
3403 return NT_STATUS_INVALID_PARAMETER;
3406 /* search for the secret record */
3407 ret = gendb_search(secret_state->sam_ldb,
3408 mem_ctx, policy_state->system_dn, &msgs, attrs,
3409 "(&(cn=%s Secret)(objectclass=secret))",
3410 ldb_binary_encode_string(mem_ctx, name));
3412 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3416 DEBUG(0,("Found %d records matching DN %s\n", ret,
3417 ldb_dn_get_linearized(policy_state->system_dn)));
3418 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3421 secret_state->global = false;
3422 secret_state->sam_ldb = talloc_reference(secret_state,
3423 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3425 name = r->in.name.string;
3426 if (strlen(name) < 1) {
3427 return NT_STATUS_INVALID_PARAMETER;
3430 /* search for the secret record */
3431 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3432 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3434 "(&(cn=%s)(objectclass=secret))",
3435 ldb_binary_encode_string(mem_ctx, name));
3437 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3441 DEBUG(0,("Found %d records matching CN=%s\n",
3442 ret, ldb_binary_encode_string(mem_ctx, name)));
3443 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3447 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3449 handle = dcesrv_handle_create(dce_call, LSA_HANDLE_SECRET);
3451 return NT_STATUS_NO_MEMORY;
3454 handle->data = talloc_steal(handle, secret_state);
3456 secret_state->access_mask = r->in.access_mask;
3457 secret_state->policy = talloc_reference(secret_state, policy_state);
3459 *r->out.sec_handle = handle->wire_handle;
3461 return NT_STATUS_OK;
3468 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3469 struct lsa_SetSecret *r)
3472 struct dcesrv_handle *h;
3473 struct lsa_secret_state *secret_state;
3474 struct ldb_message *msg;
3475 DATA_BLOB session_key;
3476 DATA_BLOB crypt_secret, secret;
3479 NTSTATUS status = NT_STATUS_OK;
3481 struct timeval now = timeval_current();
3482 NTTIME nt_now = timeval_to_nttime(&now);
3484 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3486 secret_state = h->data;
3488 msg = ldb_msg_new(mem_ctx);
3490 return NT_STATUS_NO_MEMORY;
3493 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3495 return NT_STATUS_NO_MEMORY;
3497 status = dcesrv_transport_session_key(dce_call, &session_key);
3498 if (!NT_STATUS_IS_OK(status)) {
3502 if (r->in.old_val) {
3504 crypt_secret.data = r->in.old_val->data;
3505 crypt_secret.length = r->in.old_val->size;
3507 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3508 if (!NT_STATUS_IS_OK(status)) {
3512 val.data = secret.data;
3513 val.length = secret.length;
3516 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3517 return NT_STATUS_NO_MEMORY;
3520 /* set old value mtime */
3521 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3522 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3523 return NT_STATUS_NO_MEMORY;
3527 /* If the old value is not set, then migrate the
3528 * current value to the old value */
3529 const struct ldb_val *old_val;
3530 NTTIME last_set_time;
3531 struct ldb_message **res;
3532 const char *attrs[] = {
3538 /* search for the secret record */
3539 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3540 secret_state->secret_dn, &res, attrs);
3542 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3546 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3547 ldb_dn_get_linearized(secret_state->secret_dn)));
3548 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3551 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3552 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3556 if (ldb_msg_add_value(msg, "priorValue",
3557 old_val, NULL) != LDB_SUCCESS) {
3558 return NT_STATUS_NO_MEMORY;
3561 if (samdb_msg_add_delete(secret_state->sam_ldb,
3562 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3563 return NT_STATUS_NO_MEMORY;
3567 /* set old value mtime */
3568 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3569 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3570 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3571 return NT_STATUS_NO_MEMORY;
3574 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3575 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3576 return NT_STATUS_NO_MEMORY;
3581 if (r->in.new_val) {
3583 crypt_secret.data = r->in.new_val->data;
3584 crypt_secret.length = r->in.new_val->size;
3586 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3587 if (!NT_STATUS_IS_OK(status)) {
3591 val.data = secret.data;
3592 val.length = secret.length;
3595 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3596 return NT_STATUS_NO_MEMORY;
3599 /* set new value mtime */
3600 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3601 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3602 return NT_STATUS_NO_MEMORY;
3605 /* NULL out the NEW value */
3606 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3607 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3608 return NT_STATUS_NO_MEMORY;
3610 if (samdb_msg_add_delete(secret_state->sam_ldb,
3611 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3612 return NT_STATUS_NO_MEMORY;
3616 /* modify the samdb record */
3617 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3618 if (ret != LDB_SUCCESS) {
3619 return dsdb_ldb_err_to_ntstatus(ret);
3622 return NT_STATUS_OK;
3629 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3630 struct lsa_QuerySecret *r)
3632 struct auth_session_info *session_info =
3633 dcesrv_call_session_info(dce_call);
3634 struct dcesrv_handle *h;
3635 struct lsa_secret_state *secret_state;
3636 struct ldb_message *msg;
3637 DATA_BLOB session_key;
3638 DATA_BLOB crypt_secret, secret;
3640 struct ldb_message **res;
3641 const char *attrs[] = {
3651 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3653 /* Ensure user is permitted to read this... */
3654 switch (security_session_user_level(session_info, NULL))
3656 case SECURITY_SYSTEM:
3657 case SECURITY_ADMINISTRATOR:
3660 /* Users and annonymous are not allowed to read secrets */
3661 return NT_STATUS_ACCESS_DENIED;
3664 secret_state = h->data;
3666 /* pull all the user attributes */
3667 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3668 secret_state->secret_dn, &res, attrs);
3670 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3674 nt_status = dcesrv_transport_session_key(dce_call, &session_key);
3675 if (!NT_STATUS_IS_OK(nt_status)) {
3679 if (r->in.old_val) {
3680 const struct ldb_val *prior_val;
3681 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3682 if (!r->out.old_val) {
3683 return NT_STATUS_NO_MEMORY;
3685 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3687 if (prior_val && prior_val->length) {
3688 secret.data = prior_val->data;
3689 secret.length = prior_val->length;
3692 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3693 if (!crypt_secret.length) {
3694 return NT_STATUS_NO_MEMORY;
3696 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3697 if (!r->out.old_val->buf) {
3698 return NT_STATUS_NO_MEMORY;
3700 r->out.old_val->buf->size = crypt_secret.length;
3701 r->out.old_val->buf->length = crypt_secret.length;
3702 r->out.old_val->buf->data = crypt_secret.data;
3706 if (r->in.old_mtime) {
3707 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3708 if (!r->out.old_mtime) {
3709 return NT_STATUS_NO_MEMORY;
3711 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3714 if (r->in.new_val) {
3715 const struct ldb_val *new_val;
3716 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3717 if (!r->out.new_val) {
3718 return NT_STATUS_NO_MEMORY;
3721 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3723 if (new_val && new_val->length) {
3724 secret.data = new_val->data;
3725 secret.length = new_val->length;
3728 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3729 if (!crypt_secret.length) {
3730 return NT_STATUS_NO_MEMORY;
3732 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3733 if (!r->out.new_val->buf) {
3734 return NT_STATUS_NO_MEMORY;
3736 r->out.new_val->buf->length = crypt_secret.length;
3737 r->out.new_val->buf->size = crypt_secret.length;
3738 r->out.new_val->buf->data = crypt_secret.data;
3742 if (r->in.new_mtime) {
3743 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3744 if (!r->out.new_mtime) {
3745 return NT_STATUS_NO_MEMORY;
3747 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3750 return NT_STATUS_OK;
3757 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3758 TALLOC_CTX *mem_ctx,
3759 struct lsa_LookupPrivValue *r)
3761 struct dcesrv_handle *h;
3764 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3766 id = sec_privilege_id(r->in.name->string);
3767 if (id == SEC_PRIV_INVALID) {
3768 return NT_STATUS_NO_SUCH_PRIVILEGE;
3771 r->out.luid->low = id;
3772 r->out.luid->high = 0;
3774 return NT_STATUS_OK;
3781 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3782 TALLOC_CTX *mem_ctx,
3783 struct lsa_LookupPrivName *r)
3785 struct dcesrv_handle *h;
3786 struct lsa_StringLarge *name;
3787 const char *privname;
3789 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3791 if (r->in.luid->high != 0) {
3792 return NT_STATUS_NO_SUCH_PRIVILEGE;
3795 privname = sec_privilege_name(r->in.luid->low);
3796 if (privname == NULL) {
3797 return NT_STATUS_NO_SUCH_PRIVILEGE;
3800 name = talloc(mem_ctx, struct lsa_StringLarge);
3802 return NT_STATUS_NO_MEMORY;
3805 name->string = privname;
3807 *r->out.name = name;
3809 return NT_STATUS_OK;
3814 lsa_LookupPrivDisplayName
3816 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3817 TALLOC_CTX *mem_ctx,
3818 struct lsa_LookupPrivDisplayName *r)
3820 struct dcesrv_handle *h;
3821 struct lsa_StringLarge *disp_name = NULL;
3822 enum sec_privilege id;
3824 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3826 id = sec_privilege_id(r->in.name->string);
3827 if (id == SEC_PRIV_INVALID) {
3828 return NT_STATUS_NO_SUCH_PRIVILEGE;
3831 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3832 if (disp_name == NULL) {
3833 return NT_STATUS_NO_MEMORY;
3836 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3837 if (disp_name->string == NULL) {
3838 return NT_STATUS_INTERNAL_ERROR;
3841 *r->out.disp_name = disp_name;
3842 *r->out.returned_language_id = 0;
3844 return NT_STATUS_OK;
3849 lsa_EnumAccountsWithUserRight
3851 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3852 TALLOC_CTX *mem_ctx,
3853 struct lsa_EnumAccountsWithUserRight *r)
3855 struct dcesrv_handle *h;
3856 struct lsa_policy_state *state;
3858 struct ldb_message **res;
3859 const char * const attrs[] = { "objectSid", NULL};
3860 const char *privname;
3863 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3867 if (r->in.name == NULL) {
3868 return NT_STATUS_NO_SUCH_PRIVILEGE;
3871 privname = r->in.name->string;
3873 ok = dcesrc_lsa_valid_AccountRight(privname);
3875 return NT_STATUS_NO_SUCH_PRIVILEGE;
3878 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3879 "privilege=%s", privname);
3881 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3884 return NT_STATUS_NO_MORE_ENTRIES;
3887 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3888 if (r->out.sids->sids == NULL) {
3889 return NT_STATUS_NO_MEMORY;
3891 for (i=0;i<ret;i++) {
3892 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3893 res[i], "objectSid");
3894 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3896 r->out.sids->num_sids = ret;
3898 return NT_STATUS_OK;
3903 lsa_AddAccountRights
3905 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3906 TALLOC_CTX *mem_ctx,
3907 struct lsa_AddAccountRights *r)
3909 struct dcesrv_handle *h;
3910 struct lsa_policy_state *state;
3912 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3916 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3918 r->in.sid, r->in.rights);
3923 lsa_RemoveAccountRights
3925 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3926 TALLOC_CTX *mem_ctx,
3927 struct lsa_RemoveAccountRights *r)
3929 struct dcesrv_handle *h;
3930 struct lsa_policy_state *state;
3932 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3936 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3937 LDB_FLAG_MOD_DELETE,
3938 r->in.sid, r->in.rights);
3943 lsa_StorePrivateData
3945 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3946 struct lsa_StorePrivateData *r)
3948 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3953 lsa_RetrievePrivateData
3955 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3956 struct lsa_RetrievePrivateData *r)
3958 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3965 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3966 struct lsa_GetUserName *r)
3968 enum dcerpc_transport_t transport =
3969 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3970 struct auth_session_info *session_info =
3971 dcesrv_call_session_info(dce_call);
3972 NTSTATUS status = NT_STATUS_OK;
3973 const char *account_name;
3974 const char *authority_name;
3975 struct lsa_String *_account_name;
3976 struct lsa_String *_authority_name = NULL;
3978 if (transport != NCACN_NP && transport != NCALRPC) {
3979 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3982 /* this is what w2k3 does */
3983 r->out.account_name = r->in.account_name;
3984 r->out.authority_name = r->in.authority_name;
3986 if (r->in.account_name
3987 && *r->in.account_name
3988 /* && *(*r->in.account_name)->string */
3990 return NT_STATUS_INVALID_PARAMETER;
3993 if (r->in.authority_name
3994 && *r->in.authority_name
3995 /* && *(*r->in.authority_name)->string */
3997 return NT_STATUS_INVALID_PARAMETER;
4000 account_name = talloc_reference(mem_ctx, session_info->info->account_name);
4001 authority_name = talloc_reference(mem_ctx, session_info->info->domain_name);
4003 _account_name = talloc(mem_ctx, struct lsa_String);
4004 NT_STATUS_HAVE_NO_MEMORY(_account_name);
4005 _account_name->string = account_name;
4007 if (r->in.authority_name) {
4008 _authority_name = talloc(mem_ctx, struct lsa_String);
4009 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
4010 _authority_name->string = authority_name;
4013 *r->out.account_name = _account_name;
4014 if (r->out.authority_name) {
4015 *r->out.authority_name = _authority_name;
4024 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
4025 TALLOC_CTX *mem_ctx,
4026 struct lsa_SetInfoPolicy2 *r)
4028 /* need to support these */
4029 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4032 static void kdc_get_policy(TALLOC_CTX *mem_ctx,
4033 struct loadparm_context *lp_ctx,
4034 struct smb_krb5_context *smb_krb5_context,
4035 struct lsa_DomainInfoKerberos *k)
4037 time_t svc_tkt_lifetime;
4038 time_t usr_tkt_lifetime;
4039 time_t renewal_lifetime;
4041 /* Our KDC always re-validates the client */
4042 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
4044 lpcfg_default_kdc_policy(mem_ctx, lp_ctx, &svc_tkt_lifetime,
4045 &usr_tkt_lifetime, &renewal_lifetime);
4047 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
4048 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
4049 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
4050 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
4051 However in the parent function we basically just did a full
4052 krb5_context init with the only purpose of getting a global
4053 config option (the max skew), it would probably make more sense
4054 to have a lp_ or ldb global option as the samba default */
4055 if (smb_krb5_context) {
4056 unix_to_nt_time(&k->clock_skew,
4057 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
4063 lsa_QueryDomainInformationPolicy
4065 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4066 TALLOC_CTX *mem_ctx,
4067 struct lsa_QueryDomainInformationPolicy *r)
4069 union lsa_DomainInformationPolicy *info;
4071 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
4073 return NT_STATUS_NO_MEMORY;
4076 switch (r->in.level) {
4077 case LSA_DOMAIN_INFO_POLICY_EFS:
4079 *r->out.info = NULL;
4080 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4081 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
4083 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
4084 struct smb_krb5_context *smb_krb5_context;
4085 int ret = smb_krb5_init_context(mem_ctx,
4086 dce_call->conn->dce_ctx->lp_ctx,
4090 *r->out.info = NULL;
4091 return NT_STATUS_INTERNAL_ERROR;
4093 kdc_get_policy(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
4096 talloc_free(smb_krb5_context);
4097 *r->out.info = info;
4098 return NT_STATUS_OK;
4102 *r->out.info = NULL;
4103 return NT_STATUS_INVALID_INFO_CLASS;
4108 lsa_SetDomInfoPolicy
4110 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4111 TALLOC_CTX *mem_ctx,
4112 struct lsa_SetDomainInformationPolicy *r)
4114 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4120 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
4121 TALLOC_CTX *mem_ctx,
4122 struct lsa_TestCall *r)
4124 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4130 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4131 struct lsa_CREDRWRITE *r)
4133 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4140 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4141 struct lsa_CREDRREAD *r)
4143 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4150 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4151 struct lsa_CREDRENUMERATE *r)
4153 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4158 lsa_CREDRWRITEDOMAINCREDENTIALS
4160 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4161 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
4163 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4168 lsa_CREDRREADDOMAINCREDENTIALS
4170 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4171 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
4173 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4180 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4181 struct lsa_CREDRDELETE *r)
4183 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4188 lsa_CREDRGETTARGETINFO
4190 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4191 struct lsa_CREDRGETTARGETINFO *r)
4193 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4198 lsa_CREDRPROFILELOADED
4200 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4201 struct lsa_CREDRPROFILELOADED *r)
4203 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4208 lsa_CREDRGETSESSIONTYPES
4210 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4211 struct lsa_CREDRGETSESSIONTYPES *r)
4213 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4218 lsa_LSARREGISTERAUDITEVENT
4220 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4221 struct lsa_LSARREGISTERAUDITEVENT *r)
4223 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4228 lsa_LSARGENAUDITEVENT
4230 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4231 struct lsa_LSARGENAUDITEVENT *r)
4233 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4238 lsa_LSARUNREGISTERAUDITEVENT
4240 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4241 struct lsa_LSARUNREGISTERAUDITEVENT *r)
4243 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4248 lsa_lsaRQueryForestTrustInformation
4250 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4251 struct lsa_lsaRQueryForestTrustInformation *r)
4253 struct dcesrv_handle *h = NULL;
4254 struct lsa_policy_state *p_state = NULL;
4255 int forest_level = DS_DOMAIN_FUNCTION_2000;
4256 const char * const trust_attrs[] = {
4257 "securityIdentifier",
4263 "msDS-TrustForestTrustInfo",
4266 struct ldb_message *trust_tdo_msg = NULL;
4267 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4268 struct ForestTrustInfo *trust_fti = NULL;
4269 struct lsa_ForestTrustInformation *trust_lfti = NULL;
4272 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4276 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4277 return NT_STATUS_INVALID_DOMAIN_STATE;
4280 forest_level = dsdb_forest_functional_level(p_state->sam_ldb);
4281 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4282 return NT_STATUS_INVALID_DOMAIN_STATE;
4285 if (r->in.trusted_domain_name->string == NULL) {
4286 return NT_STATUS_NO_SUCH_DOMAIN;
4289 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4290 r->in.trusted_domain_name->string,
4291 r->in.trusted_domain_name->string,
4292 trust_attrs, mem_ctx, &trust_tdo_msg);
4293 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4294 return NT_STATUS_NO_SUCH_DOMAIN;
4296 if (!NT_STATUS_IS_OK(status)) {
4300 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4301 if (!NT_STATUS_IS_OK(status)) {
4305 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4306 return NT_STATUS_INVALID_PARAMETER;
4309 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4310 return NT_STATUS_INVALID_PARAMETER;
4313 status = dsdb_trust_parse_forest_info(mem_ctx,
4316 if (!NT_STATUS_IS_OK(status)) {
4320 status = dsdb_trust_forest_info_to_lsa(mem_ctx, trust_fti,
4322 if (!NT_STATUS_IS_OK(status)) {
4326 *r->out.forest_trust_info = trust_lfti;
4327 return NT_STATUS_OK;
4331 lsa_lsaRSetForestTrustInformation
4333 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4334 TALLOC_CTX *mem_ctx,
4335 struct lsa_lsaRSetForestTrustInformation *r)
4337 struct dcesrv_handle *h;
4338 struct lsa_policy_state *p_state;
4339 const char * const trust_attrs[] = {
4340 "securityIdentifier",
4346 "msDS-TrustForestTrustInfo",
4349 struct ldb_message *trust_tdo_msg = NULL;
4350 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4351 struct lsa_ForestTrustInformation *step1_lfti = NULL;
4352 struct lsa_ForestTrustInformation *step2_lfti = NULL;
4353 struct ForestTrustInfo *trust_fti = NULL;
4354 struct ldb_result *trusts_res = NULL;
4356 struct lsa_TrustDomainInfoInfoEx *xref_tdo = NULL;
4357 struct lsa_ForestTrustInformation *xref_lfti = NULL;
4358 struct lsa_ForestTrustCollisionInfo *c_info = NULL;
4359 DATA_BLOB ft_blob = {};
4360 struct ldb_message *msg = NULL;
4361 struct server_id *server_ids = NULL;
4362 uint32_t num_server_ids = 0;
4364 enum ndr_err_code ndr_err;
4366 bool in_transaction = false;
4368 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4372 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4373 return NT_STATUS_INVALID_DOMAIN_STATE;
4376 if (r->in.check_only == 0) {
4377 ret = ldb_transaction_start(p_state->sam_ldb);
4378 if (ret != LDB_SUCCESS) {
4379 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4381 in_transaction = true;
4385 * abort if we are not a PDC
4387 * In future we should use a function like IsEffectiveRoleOwner()
4389 if (!samdb_is_pdc(p_state->sam_ldb)) {
4390 status = NT_STATUS_INVALID_DOMAIN_ROLE;
4394 if (r->in.trusted_domain_name->string == NULL) {
4395 status = NT_STATUS_NO_SUCH_DOMAIN;
4399 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4400 r->in.trusted_domain_name->string,
4401 r->in.trusted_domain_name->string,
4402 trust_attrs, mem_ctx, &trust_tdo_msg);
4403 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4404 status = NT_STATUS_NO_SUCH_DOMAIN;
4407 if (!NT_STATUS_IS_OK(status)) {
4411 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4412 if (!NT_STATUS_IS_OK(status)) {
4416 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4417 status = NT_STATUS_INVALID_PARAMETER;
4421 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4422 status = NT_STATUS_INVALID_PARAMETER;
4427 * verify and normalize the given forest trust info.
4429 * Step1: doesn't reorder yet, so step1_lfti might contain
4430 * NULL entries. This means dsdb_trust_verify_forest_info()
4431 * can generate collision entries with the callers index.
4433 status = dsdb_trust_normalize_forest_info_step1(mem_ctx,
4434 r->in.forest_trust_info,
4436 if (!NT_STATUS_IS_OK(status)) {
4440 c_info = talloc_zero(r->out.collision_info,
4441 struct lsa_ForestTrustCollisionInfo);
4442 if (c_info == NULL) {
4443 status = NT_STATUS_NO_MEMORY;
4448 * First check our own forest, then other domains/forests
4451 status = dsdb_trust_xref_tdo_info(mem_ctx, p_state->sam_ldb,
4453 if (!NT_STATUS_IS_OK(status)) {
4456 status = dsdb_trust_xref_forest_info(mem_ctx, p_state->sam_ldb,
4458 if (!NT_STATUS_IS_OK(status)) {
4463 * The documentation proposed to generate
4464 * LSA_FOREST_TRUST_COLLISION_XREF collisions.
4465 * But Windows always uses LSA_FOREST_TRUST_COLLISION_TDO.
4467 status = dsdb_trust_verify_forest_info(xref_tdo, xref_lfti,
4468 LSA_FOREST_TRUST_COLLISION_TDO,
4469 c_info, step1_lfti);
4470 if (!NT_STATUS_IS_OK(status)) {
4474 /* fetch all other trusted domain objects */
4475 status = dsdb_trust_search_tdos(p_state->sam_ldb,
4476 trust_tdo->domain_name.string,
4478 mem_ctx, &trusts_res);
4479 if (!NT_STATUS_IS_OK(status)) {
4484 * now check against the other domains.
4485 * and generate LSA_FOREST_TRUST_COLLISION_TDO collisions.
4487 for (i = 0; i < trusts_res->count; i++) {
4488 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
4489 struct ForestTrustInfo *fti = NULL;
4490 struct lsa_ForestTrustInformation *lfti = NULL;
4492 status = dsdb_trust_parse_tdo_info(mem_ctx,
4493 trusts_res->msgs[i],
4495 if (!NT_STATUS_IS_OK(status)) {
4499 status = dsdb_trust_parse_forest_info(tdo,
4500 trusts_res->msgs[i],
4502 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
4505 if (!NT_STATUS_IS_OK(status)) {
4509 status = dsdb_trust_forest_info_to_lsa(tdo, fti, &lfti);
4510 if (!NT_STATUS_IS_OK(status)) {
4514 status = dsdb_trust_verify_forest_info(tdo, lfti,
4515 LSA_FOREST_TRUST_COLLISION_TDO,
4516 c_info, step1_lfti);
4517 if (!NT_STATUS_IS_OK(status)) {
4524 if (r->in.check_only != 0) {
4525 status = NT_STATUS_OK;
4530 * not just a check, write info back
4534 * normalize the given forest trust info.
4536 * Step2: adds TOP_LEVEL_NAME[_EX] in reverse order,
4537 * followed by DOMAIN_INFO in reverse order. It also removes
4538 * possible NULL entries from Step1.
4540 status = dsdb_trust_normalize_forest_info_step2(mem_ctx, step1_lfti,
4542 if (!NT_STATUS_IS_OK(status)) {
4546 status = dsdb_trust_forest_info_from_lsa(mem_ctx, step2_lfti,
4548 if (!NT_STATUS_IS_OK(status)) {
4552 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, trust_fti,
4553 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4554 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4555 status = NT_STATUS_INVALID_PARAMETER;
4559 msg = ldb_msg_new(mem_ctx);
4561 status = NT_STATUS_NO_MEMORY;
4565 msg->dn = ldb_dn_copy(mem_ctx, trust_tdo_msg->dn);
4567 status = NT_STATUS_NO_MEMORY;
4571 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4572 LDB_FLAG_MOD_REPLACE, NULL);
4573 if (ret != LDB_SUCCESS) {
4574 status = NT_STATUS_NO_MEMORY;
4577 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4579 if (ret != LDB_SUCCESS) {
4580 status = NT_STATUS_NO_MEMORY;
4584 ret = ldb_modify(p_state->sam_ldb, msg);
4585 if (ret != LDB_SUCCESS) {
4586 status = dsdb_ldb_err_to_ntstatus(ret);
4588 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4589 ldb_errstring(p_state->sam_ldb)));
4594 /* ok, all fine, commit transaction and return */
4595 in_transaction = false;
4596 ret = ldb_transaction_commit(p_state->sam_ldb);
4597 if (ret != LDB_SUCCESS) {
4598 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4603 * Notify winbindd that we have a acquired forest trust info
4605 status = irpc_servers_byname(dce_call->msg_ctx,
4608 &num_server_ids, &server_ids);
4609 if (!NT_STATUS_IS_OK(status)) {
4610 DBG_ERR("irpc_servers_byname failed\n");
4614 imessaging_send(dce_call->msg_ctx, server_ids[0],
4615 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS, NULL);
4617 status = NT_STATUS_OK;
4620 if (NT_STATUS_IS_OK(status) && c_info->count != 0) {
4621 *r->out.collision_info = c_info;
4624 if (in_transaction) {
4625 ldb_transaction_cancel(p_state->sam_ldb);
4634 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4635 struct lsa_CREDRRENAME *r)
4637 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4643 lsa_LSAROPENPOLICYSCE
4645 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4646 struct lsa_LSAROPENPOLICYSCE *r)
4648 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4653 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4655 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4656 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4658 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4663 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4665 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4666 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4668 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4673 lsa_LSARADTREPORTSECURITYEVENT
4675 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4676 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4678 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4682 /* include the generated boilerplate */
4683 #include "librpc/gen_ndr/ndr_lsa_s.c"
4687 /*****************************************
4688 NOTE! The remaining calls below were
4689 removed in w2k3, so the DCESRV_FAULT()
4690 replies are the correct implementation. Do
4691 not try and fill these in with anything else
4692 ******************************************/
4695 dssetup_DsRoleDnsNameToFlatName
4697 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4698 struct dssetup_DsRoleDnsNameToFlatName *r)
4700 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4705 dssetup_DsRoleDcAsDc
4707 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4708 struct dssetup_DsRoleDcAsDc *r)
4710 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4715 dssetup_DsRoleDcAsReplica
4717 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4718 struct dssetup_DsRoleDcAsReplica *r)
4720 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4725 dssetup_DsRoleDemoteDc
4727 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4728 struct dssetup_DsRoleDemoteDc *r)
4730 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4735 dssetup_DsRoleGetDcOperationProgress
4737 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4738 struct dssetup_DsRoleGetDcOperationProgress *r)
4740 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4745 dssetup_DsRoleGetDcOperationResults
4747 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4748 struct dssetup_DsRoleGetDcOperationResults *r)
4750 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4755 dssetup_DsRoleCancel
4757 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4758 struct dssetup_DsRoleCancel *r)
4760 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4765 dssetup_DsRoleServerSaveStateForUpgrade
4767 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4768 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4770 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4775 dssetup_DsRoleUpgradeDownlevelServer
4777 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4778 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4780 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4785 dssetup_DsRoleAbortDownlevelServerUpgrade
4787 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4788 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4790 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4794 /* include the generated boilerplate */
4795 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4797 NTSTATUS dcerpc_server_lsa_init(TALLOC_CTX *ctx)
4801 ret = dcerpc_server_dssetup_init(ctx);
4802 if (!NT_STATUS_IS_OK(ret)) {
4805 ret = dcerpc_server_lsarpc_init(ctx);
4806 if (!NT_STATUS_IS_OK(ret)) {