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"
37 this type allows us to distinguish handle types
41 state associated with a lsa_OpenAccount() operation
43 struct lsa_account_state {
44 struct lsa_policy_state *policy;
46 struct dom_sid *account_sid;
51 state associated with a lsa_OpenSecret() operation
53 struct lsa_secret_state {
54 struct lsa_policy_state *policy;
56 struct ldb_dn *secret_dn;
57 struct ldb_context *sam_ldb;
62 state associated with a lsa_OpenTrustedDomain() operation
64 struct lsa_trusted_domain_state {
65 struct lsa_policy_state *policy;
67 struct ldb_dn *trusted_domain_dn;
68 struct ldb_dn *trusted_domain_user_dn;
72 this is based on the samba3 function make_lsa_object_sd()
73 It uses the same logic, but with samba4 helper functions
75 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
76 struct security_descriptor **sd,
82 struct dom_sid *domain_sid, *domain_admins_sid;
83 const char *domain_admins_sid_str, *sidstr;
84 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
86 status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
87 NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
89 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
90 if (domain_admins_sid == NULL) {
92 return NT_STATUS_NO_MEMORY;
95 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
96 if (domain_admins_sid_str == NULL) {
98 return NT_STATUS_NO_MEMORY;
101 sidstr = dom_sid_string(tmp_ctx, sid);
102 if (sidstr == NULL) {
103 TALLOC_FREE(tmp_ctx);
104 return NT_STATUS_NO_MEMORY;
107 *sd = security_descriptor_dacl_create(mem_ctx,
111 SEC_ACE_TYPE_ACCESS_ALLOWED,
112 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
114 SID_BUILTIN_ADMINISTRATORS,
115 SEC_ACE_TYPE_ACCESS_ALLOWED,
118 SID_BUILTIN_ACCOUNT_OPERATORS,
119 SEC_ACE_TYPE_ACCESS_ALLOWED,
122 domain_admins_sid_str,
123 SEC_ACE_TYPE_ACCESS_ALLOWED,
127 SEC_ACE_TYPE_ACCESS_ALLOWED,
131 talloc_free(tmp_ctx);
133 NT_STATUS_HAVE_NO_MEMORY(*sd);
139 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
141 struct lsa_EnumAccountRights *r);
143 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
145 struct lsa_policy_state *state,
148 const struct lsa_RightSet *rights);
153 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
156 enum dcerpc_transport_t transport =
157 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
158 struct dcesrv_handle *h;
160 if (transport != NCACN_NP && transport != NCALRPC) {
161 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
164 *r->out.handle = *r->in.handle;
166 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
170 ZERO_STRUCTP(r->out.handle);
179 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
180 struct lsa_Delete *r)
182 return NT_STATUS_NOT_SUPPORTED;
189 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
190 struct lsa_DeleteObject *r)
192 struct dcesrv_handle *h;
195 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
197 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
198 struct lsa_secret_state *secret_state = h->data;
200 /* Ensure user is permitted to delete this... */
201 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
203 case SECURITY_SYSTEM:
204 case SECURITY_ADMINISTRATOR:
207 /* Users and anonymous are not allowed to delete things */
208 return NT_STATUS_ACCESS_DENIED;
211 ret = ldb_delete(secret_state->sam_ldb,
212 secret_state->secret_dn);
213 if (ret != LDB_SUCCESS) {
214 return NT_STATUS_INVALID_HANDLE;
217 ZERO_STRUCTP(r->out.handle);
221 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
222 struct lsa_trusted_domain_state *trusted_domain_state =
223 talloc_get_type(h->data, struct lsa_trusted_domain_state);
224 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
225 if (ret != LDB_SUCCESS) {
226 return NT_STATUS_INTERNAL_DB_CORRUPTION;
229 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
230 trusted_domain_state->trusted_domain_dn);
231 if (ret != LDB_SUCCESS) {
232 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
233 return NT_STATUS_INVALID_HANDLE;
236 if (trusted_domain_state->trusted_domain_user_dn) {
237 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
238 trusted_domain_state->trusted_domain_user_dn);
239 if (ret != LDB_SUCCESS) {
240 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
241 return NT_STATUS_INVALID_HANDLE;
245 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
246 if (ret != LDB_SUCCESS) {
247 return NT_STATUS_INTERNAL_DB_CORRUPTION;
250 ZERO_STRUCTP(r->out.handle);
254 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
255 struct lsa_RightSet *rights;
256 struct lsa_account_state *astate;
257 struct lsa_EnumAccountRights r2;
260 rights = talloc(mem_ctx, struct lsa_RightSet);
262 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
266 r2.in.handle = &astate->policy->handle->wire_handle;
267 r2.in.sid = astate->account_sid;
268 r2.out.rights = rights;
270 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
271 but we have a LSA_HANDLE_ACCOUNT here, so this call
273 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
274 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
278 if (!NT_STATUS_IS_OK(status)) {
282 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
283 LDB_FLAG_MOD_DELETE, astate->account_sid,
285 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
289 if (!NT_STATUS_IS_OK(status)) {
293 ZERO_STRUCTP(r->out.handle);
298 return NT_STATUS_INVALID_HANDLE;
305 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
306 struct lsa_EnumPrivs *r)
308 struct dcesrv_handle *h;
310 enum sec_privilege priv;
311 const char *privname;
313 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
315 i = *r->in.resume_handle;
317 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
318 r->out.privs->count < r->in.max_count) {
319 struct lsa_PrivEntry *e;
320 privname = sec_privilege_name(priv);
321 r->out.privs->privs = talloc_realloc(r->out.privs,
323 struct lsa_PrivEntry,
324 r->out.privs->count+1);
325 if (r->out.privs->privs == NULL) {
326 return NT_STATUS_NO_MEMORY;
328 e = &r->out.privs->privs[r->out.privs->count];
331 e->name.string = privname;
332 r->out.privs->count++;
336 *r->out.resume_handle = i;
345 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
346 struct lsa_QuerySecurity *r)
348 struct dcesrv_handle *h;
349 struct security_descriptor *sd;
353 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
355 sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
357 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
358 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
359 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
360 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid,
361 LSA_ACCOUNT_ALL_ACCESS);
363 return NT_STATUS_INVALID_HANDLE;
365 NT_STATUS_NOT_OK_RETURN(status);
367 (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
368 NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
370 (*r->out.sdbuf)->sd = sd;
379 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
380 struct lsa_SetSecObj *r)
382 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
389 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
390 struct lsa_ChangePassword *r)
392 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
396 dssetup_DsRoleGetPrimaryDomainInformation
398 This is not an LSA call, but is the only call left on the DSSETUP
399 pipe (after the pipe was truncated), and needs lsa_get_policy_state
401 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
403 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
405 union dssetup_DsRoleInfo *info;
407 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
408 W_ERROR_HAVE_NO_MEMORY(info);
410 switch (r->in.level) {
411 case DS_ROLE_BASIC_INFORMATION:
413 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
415 const char *domain = NULL;
416 const char *dns_domain = NULL;
417 const char *forest = NULL;
418 struct GUID domain_guid;
419 struct lsa_policy_state *state;
421 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
422 if (!NT_STATUS_IS_OK(status)) {
423 return ntstatus_to_werror(status);
426 ZERO_STRUCT(domain_guid);
428 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
429 case ROLE_STANDALONE:
430 role = DS_ROLE_STANDALONE_SERVER;
432 case ROLE_DOMAIN_MEMBER:
433 role = DS_ROLE_MEMBER_SERVER;
435 case ROLE_ACTIVE_DIRECTORY_DC:
436 if (samdb_is_pdc(state->sam_ldb)) {
437 role = DS_ROLE_PRIMARY_DC;
439 role = DS_ROLE_BACKUP_DC;
444 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
445 case ROLE_STANDALONE:
446 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
447 W_ERROR_HAVE_NO_MEMORY(domain);
449 case ROLE_DOMAIN_MEMBER:
450 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
451 W_ERROR_HAVE_NO_MEMORY(domain);
452 /* TODO: what is with dns_domain and forest and guid? */
454 case ROLE_ACTIVE_DIRECTORY_DC:
455 flags = DS_ROLE_PRIMARY_DS_RUNNING;
457 if (state->mixed_domain == 1) {
458 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
461 domain = state->domain_name;
462 dns_domain = state->domain_dns;
463 forest = state->forest_dns;
465 domain_guid = state->domain_guid;
466 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
470 info->basic.role = role;
471 info->basic.flags = flags;
472 info->basic.domain = domain;
473 info->basic.dns_domain = dns_domain;
474 info->basic.forest = forest;
475 info->basic.domain_guid = domain_guid;
480 case DS_ROLE_UPGRADE_STATUS:
482 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
483 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
488 case DS_ROLE_OP_STATUS:
490 info->opstatus.status = DS_ROLE_OP_IDLE;
496 return WERR_INVALID_PARAM;
501 fill in the AccountDomain info
503 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
504 struct lsa_DomainInfo *info)
506 info->name.string = state->domain_name;
507 info->sid = state->domain_sid;
513 fill in the DNS domain info
515 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
516 struct lsa_DnsDomainInfo *info)
518 info->name.string = state->domain_name;
519 info->sid = state->domain_sid;
520 info->dns_domain.string = state->domain_dns;
521 info->dns_forest.string = state->forest_dns;
522 info->domain_guid = state->domain_guid;
530 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
531 struct lsa_QueryInfoPolicy2 *r)
533 struct lsa_policy_state *state;
534 struct dcesrv_handle *h;
535 union lsa_PolicyInformation *info;
539 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
543 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
545 return NT_STATUS_NO_MEMORY;
549 switch (r->in.level) {
550 case LSA_POLICY_INFO_AUDIT_LOG:
551 /* we don't need to fill in any of this */
552 ZERO_STRUCT(info->audit_log);
554 case LSA_POLICY_INFO_AUDIT_EVENTS:
555 /* we don't need to fill in any of this */
556 ZERO_STRUCT(info->audit_events);
558 case LSA_POLICY_INFO_PD:
559 /* we don't need to fill in any of this */
560 ZERO_STRUCT(info->pd);
563 case LSA_POLICY_INFO_DOMAIN:
564 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
565 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
566 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
567 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
568 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
570 case LSA_POLICY_INFO_ROLE:
571 info->role.role = LSA_ROLE_PRIMARY;
574 case LSA_POLICY_INFO_DNS:
575 case LSA_POLICY_INFO_DNS_INT:
576 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
578 case LSA_POLICY_INFO_REPLICA:
579 ZERO_STRUCT(info->replica);
582 case LSA_POLICY_INFO_QUOTA:
583 ZERO_STRUCT(info->quota);
586 case LSA_POLICY_INFO_MOD:
587 case LSA_POLICY_INFO_AUDIT_FULL_SET:
588 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
589 /* windows gives INVALID_PARAMETER */
591 return NT_STATUS_INVALID_PARAMETER;
595 return NT_STATUS_INVALID_INFO_CLASS;
601 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
602 struct lsa_QueryInfoPolicy *r)
604 struct lsa_QueryInfoPolicy2 r2;
609 r2.in.handle = r->in.handle;
610 r2.in.level = r->in.level;
611 r2.out.info = r->out.info;
613 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
621 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
622 struct lsa_SetInfoPolicy *r)
624 /* need to support this */
625 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
632 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
633 struct lsa_ClearAuditLog *r)
635 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
642 This call does not seem to have any long-term effects, hence no database operations
644 we need to talk to the MS product group to find out what this account database means!
646 answer is that the lsa database is totally separate from the SAM and
647 ldap databases. We are going to need a separate ldb to store these
648 accounts. The SIDs on this account bear no relation to the SIDs in
651 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
652 struct lsa_CreateAccount *r)
654 struct lsa_account_state *astate;
656 struct lsa_policy_state *state;
657 struct dcesrv_handle *h, *ah;
659 ZERO_STRUCTP(r->out.acct_handle);
661 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
665 astate = talloc(dce_call->conn, struct lsa_account_state);
666 if (astate == NULL) {
667 return NT_STATUS_NO_MEMORY;
670 astate->account_sid = dom_sid_dup(astate, r->in.sid);
671 if (astate->account_sid == NULL) {
673 return NT_STATUS_NO_MEMORY;
676 astate->policy = talloc_reference(astate, state);
677 astate->access_mask = r->in.access_mask;
679 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
682 return NT_STATUS_NO_MEMORY;
685 ah->data = talloc_steal(ah, astate);
687 *r->out.acct_handle = ah->wire_handle;
696 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
697 struct lsa_EnumAccounts *r)
699 struct dcesrv_handle *h;
700 struct lsa_policy_state *state;
702 struct ldb_message **res;
703 const char * const attrs[] = { "objectSid", NULL};
706 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
710 /* NOTE: This call must only return accounts that have at least
713 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
714 "(&(objectSid=*)(privilege=*))");
716 return NT_STATUS_INTERNAL_DB_CORRUPTION;
719 if (*r->in.resume_handle >= ret) {
720 return NT_STATUS_NO_MORE_ENTRIES;
723 count = ret - *r->in.resume_handle;
724 if (count > r->in.num_entries) {
725 count = r->in.num_entries;
729 return NT_STATUS_NO_MORE_ENTRIES;
732 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
733 if (r->out.sids->sids == NULL) {
734 return NT_STATUS_NO_MEMORY;
737 for (i=0;i<count;i++) {
738 r->out.sids->sids[i].sid =
739 samdb_result_dom_sid(r->out.sids->sids,
740 res[i + *r->in.resume_handle],
742 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
745 r->out.sids->num_sids = count;
746 *r->out.resume_handle = count + *r->in.resume_handle;
751 /* This decrypts and returns Trusted Domain Auth Information Internal data */
752 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
753 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
754 struct trustDomainPasswords *auth_struct)
756 DATA_BLOB session_key = data_blob(NULL, 0);
757 enum ndr_err_code ndr_err;
760 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
761 if (!NT_STATUS_IS_OK(nt_status)) {
765 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
766 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
768 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
769 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
770 return NT_STATUS_INVALID_PARAMETER;
776 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
778 struct trustAuthInOutBlob *iopw,
779 DATA_BLOB *trustauth_blob)
781 enum ndr_err_code ndr_err;
783 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
785 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
786 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
787 return NT_STATUS_INVALID_PARAMETER;
793 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
794 struct ldb_context *sam_ldb,
795 struct ldb_dn *base_dn,
796 const char *netbios_name,
797 struct trustAuthInOutBlob *in,
798 struct ldb_dn **user_dn)
800 struct ldb_message *msg;
805 dn = ldb_dn_copy(mem_ctx, base_dn);
807 return NT_STATUS_NO_MEMORY;
809 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
810 return NT_STATUS_NO_MEMORY;
813 msg = ldb_msg_new(mem_ctx);
815 return NT_STATUS_NO_MEMORY;
819 ret = ldb_msg_add_string(msg, "objectClass", "user");
820 if (ret != LDB_SUCCESS) {
821 return NT_STATUS_NO_MEMORY;
824 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
825 if (ret != LDB_SUCCESS) {
826 return NT_STATUS_NO_MEMORY;
829 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
830 UF_INTERDOMAIN_TRUST_ACCOUNT);
831 if (ret != LDB_SUCCESS) {
832 return NT_STATUS_NO_MEMORY;
835 for (i = 0; i < in->count; i++) {
836 const char *attribute;
838 switch (in->current.array[i].AuthType) {
839 case TRUST_AUTH_TYPE_NT4OWF:
840 attribute = "unicodePwd";
841 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
844 case TRUST_AUTH_TYPE_CLEAR:
845 attribute = "clearTextPassword";
846 v.data = in->current.array[i].AuthInfo.clear.password;
847 v.length = in->current.array[i].AuthInfo.clear.size;
853 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
854 if (ret != LDB_SUCCESS) {
855 return NT_STATUS_NO_MEMORY;
859 /* create the trusted_domain user account */
860 ret = ldb_add(sam_ldb, msg);
861 if (ret != LDB_SUCCESS) {
862 DEBUG(0,("Failed to create user record %s: %s\n",
863 ldb_dn_get_linearized(msg->dn),
864 ldb_errstring(sam_ldb)));
867 case LDB_ERR_ENTRY_ALREADY_EXISTS:
868 return NT_STATUS_DOMAIN_EXISTS;
869 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
870 return NT_STATUS_ACCESS_DENIED;
872 return NT_STATUS_INTERNAL_DB_CORRUPTION;
883 lsa_CreateTrustedDomainEx2
885 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
887 struct lsa_CreateTrustedDomainEx2 *r,
889 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
891 struct dcesrv_handle *policy_handle;
892 struct lsa_policy_state *policy_state;
893 struct lsa_trusted_domain_state *trusted_domain_state;
894 struct dcesrv_handle *handle;
895 struct ldb_message **msgs, *msg;
896 const char *attrs[] = {
899 const char *netbios_name;
900 const char *dns_name;
902 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
903 struct trustDomainPasswords auth_struct;
906 struct ldb_context *sam_ldb;
908 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
909 ZERO_STRUCTP(r->out.trustdom_handle);
911 policy_state = policy_handle->data;
912 sam_ldb = policy_state->sam_ldb;
914 netbios_name = r->in.info->netbios_name.string;
916 return NT_STATUS_INVALID_PARAMETER;
919 dns_name = r->in.info->domain_name.string;
921 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
922 if (!trusted_domain_state) {
923 return NT_STATUS_NO_MEMORY;
925 trusted_domain_state->policy = policy_state;
927 if (strcasecmp(netbios_name, "BUILTIN") == 0
928 || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
929 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
930 return NT_STATUS_INVALID_PARAMETER;
933 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
934 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
935 || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
936 || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
937 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
938 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
941 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
942 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
943 /* No secrets are created at this time, for this function */
944 auth_struct.outgoing.count = 0;
945 auth_struct.incoming.count = 0;
946 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
947 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
948 r->in.auth_info_internal->auth_blob.size);
949 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
950 &auth_blob, &auth_struct);
951 if (!NT_STATUS_IS_OK(nt_status)) {
954 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
956 if (unencrypted_auth_info->incoming_count > 1) {
957 return NT_STATUS_INVALID_PARAMETER;
960 /* more investigation required here, do not create secrets for
962 auth_struct.outgoing.count = 0;
963 auth_struct.incoming.count = 0;
965 return NT_STATUS_INVALID_PARAMETER;
968 if (auth_struct.incoming.count) {
969 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
970 &auth_struct.incoming,
972 if (!NT_STATUS_IS_OK(nt_status)) {
976 trustAuthIncoming = data_blob(NULL, 0);
979 if (auth_struct.outgoing.count) {
980 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
981 &auth_struct.outgoing,
983 if (!NT_STATUS_IS_OK(nt_status)) {
987 trustAuthOutgoing = data_blob(NULL, 0);
990 ret = ldb_transaction_start(sam_ldb);
991 if (ret != LDB_SUCCESS) {
992 return NT_STATUS_INTERNAL_DB_CORRUPTION;
996 char *dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
997 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
998 /* search for the trusted_domain record */
999 ret = gendb_search(sam_ldb,
1000 mem_ctx, policy_state->system_dn, &msgs, attrs,
1001 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1002 dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
1004 ldb_transaction_cancel(sam_ldb);
1005 return NT_STATUS_OBJECT_NAME_COLLISION;
1008 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1009 /* search for the trusted_domain record */
1010 ret = gendb_search(sam_ldb,
1011 mem_ctx, policy_state->system_dn, &msgs, attrs,
1012 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1013 netbios_encoded, netbios_encoded, netbios_encoded);
1015 ldb_transaction_cancel(sam_ldb);
1016 return NT_STATUS_OBJECT_NAME_COLLISION;
1021 ldb_transaction_cancel(sam_ldb);
1022 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1025 name = dns_name ? dns_name : netbios_name;
1027 msg = ldb_msg_new(mem_ctx);
1029 return NT_STATUS_NO_MEMORY;
1032 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1033 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1034 ldb_transaction_cancel(sam_ldb);
1035 return NT_STATUS_NO_MEMORY;
1038 ldb_msg_add_string(msg, "flatname", netbios_name);
1040 if (r->in.info->sid) {
1041 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1042 if (ret != LDB_SUCCESS) {
1043 ldb_transaction_cancel(sam_ldb);
1044 return NT_STATUS_INVALID_PARAMETER;
1048 ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1050 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1052 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1054 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1057 ldb_msg_add_string(msg, "trustPartner", dns_name);
1060 if (trustAuthIncoming.data) {
1061 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1062 if (ret != LDB_SUCCESS) {
1063 ldb_transaction_cancel(sam_ldb);
1064 return NT_STATUS_NO_MEMORY;
1067 if (trustAuthOutgoing.data) {
1068 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1069 if (ret != LDB_SUCCESS) {
1070 ldb_transaction_cancel(sam_ldb);
1071 return NT_STATUS_NO_MEMORY;
1075 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1077 /* create the trusted_domain */
1078 ret = ldb_add(sam_ldb, msg);
1082 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1083 ldb_transaction_cancel(sam_ldb);
1084 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1085 ldb_dn_get_linearized(msg->dn),
1086 ldb_errstring(sam_ldb)));
1087 return NT_STATUS_DOMAIN_EXISTS;
1088 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1089 ldb_transaction_cancel(sam_ldb);
1090 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1091 ldb_dn_get_linearized(msg->dn),
1092 ldb_errstring(sam_ldb)));
1093 return NT_STATUS_ACCESS_DENIED;
1095 ldb_transaction_cancel(sam_ldb);
1096 DEBUG(0,("Failed to create user record %s: %s\n",
1097 ldb_dn_get_linearized(msg->dn),
1098 ldb_errstring(sam_ldb)));
1099 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1102 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1103 struct ldb_dn *user_dn;
1104 /* Inbound trusts must also create a cn=users object to match */
1105 nt_status = add_trust_user(mem_ctx, sam_ldb,
1106 policy_state->domain_dn,
1108 &auth_struct.incoming,
1110 if (!NT_STATUS_IS_OK(nt_status)) {
1111 ldb_transaction_cancel(sam_ldb);
1115 /* save the trust user dn */
1116 trusted_domain_state->trusted_domain_user_dn
1117 = talloc_steal(trusted_domain_state, user_dn);
1120 ret = ldb_transaction_commit(sam_ldb);
1121 if (ret != LDB_SUCCESS) {
1122 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1125 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1127 return NT_STATUS_NO_MEMORY;
1130 handle->data = talloc_steal(handle, trusted_domain_state);
1132 trusted_domain_state->access_mask = r->in.access_mask;
1133 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1135 *r->out.trustdom_handle = handle->wire_handle;
1137 return NT_STATUS_OK;
1141 lsa_CreateTrustedDomainEx2
1143 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1144 TALLOC_CTX *mem_ctx,
1145 struct lsa_CreateTrustedDomainEx2 *r)
1147 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1150 lsa_CreateTrustedDomainEx
1152 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1153 TALLOC_CTX *mem_ctx,
1154 struct lsa_CreateTrustedDomainEx *r)
1156 struct lsa_CreateTrustedDomainEx2 r2;
1158 r2.in.policy_handle = r->in.policy_handle;
1159 r2.in.info = r->in.info;
1160 r2.out.trustdom_handle = r->out.trustdom_handle;
1161 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1165 lsa_CreateTrustedDomain
1167 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1168 struct lsa_CreateTrustedDomain *r)
1170 struct lsa_CreateTrustedDomainEx2 r2;
1172 r2.in.policy_handle = r->in.policy_handle;
1173 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1175 return NT_STATUS_NO_MEMORY;
1178 r2.in.info->domain_name.string = NULL;
1179 r2.in.info->netbios_name = r->in.info->name;
1180 r2.in.info->sid = r->in.info->sid;
1181 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1182 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1183 r2.in.info->trust_attributes = 0;
1185 r2.in.access_mask = r->in.access_mask;
1186 r2.out.trustdom_handle = r->out.trustdom_handle;
1188 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1192 lsa_OpenTrustedDomain
1194 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1195 struct lsa_OpenTrustedDomain *r)
1197 struct dcesrv_handle *policy_handle;
1199 struct lsa_policy_state *policy_state;
1200 struct lsa_trusted_domain_state *trusted_domain_state;
1201 struct dcesrv_handle *handle;
1202 struct ldb_message **msgs;
1203 const char *attrs[] = {
1209 const char *sid_string;
1212 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1213 ZERO_STRUCTP(r->out.trustdom_handle);
1214 policy_state = policy_handle->data;
1216 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1217 if (!trusted_domain_state) {
1218 return NT_STATUS_NO_MEMORY;
1220 trusted_domain_state->policy = policy_state;
1222 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1224 return NT_STATUS_NO_MEMORY;
1227 /* search for the trusted_domain record */
1228 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1229 mem_ctx, policy_state->system_dn, &msgs, attrs,
1230 "(&(securityIdentifier=%s)(objectclass=trustedDomain))",
1233 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1237 DEBUG(0,("Found %d records matching DN %s\n", ret,
1238 ldb_dn_get_linearized(policy_state->system_dn)));
1239 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1242 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1244 trusted_domain_state->trusted_domain_user_dn = NULL;
1246 if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1247 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1248 /* search for the trusted_domain record */
1249 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1250 mem_ctx, policy_state->domain_dn, &msgs, attrs,
1251 "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%u))",
1252 flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1254 trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1257 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1259 return NT_STATUS_NO_MEMORY;
1262 handle->data = talloc_steal(handle, trusted_domain_state);
1264 trusted_domain_state->access_mask = r->in.access_mask;
1265 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1267 *r->out.trustdom_handle = handle->wire_handle;
1269 return NT_STATUS_OK;
1274 lsa_OpenTrustedDomainByName
1276 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1277 TALLOC_CTX *mem_ctx,
1278 struct lsa_OpenTrustedDomainByName *r)
1280 struct dcesrv_handle *policy_handle;
1282 struct lsa_policy_state *policy_state;
1283 struct lsa_trusted_domain_state *trusted_domain_state;
1284 struct dcesrv_handle *handle;
1285 struct ldb_message **msgs;
1286 const char *attrs[] = {
1292 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1293 ZERO_STRUCTP(r->out.trustdom_handle);
1294 policy_state = policy_handle->data;
1296 if (!r->in.name.string) {
1297 return NT_STATUS_INVALID_PARAMETER;
1300 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1301 if (!trusted_domain_state) {
1302 return NT_STATUS_NO_MEMORY;
1304 trusted_domain_state->policy = policy_state;
1306 /* search for the trusted_domain record */
1307 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1308 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1309 mem_ctx, policy_state->system_dn, &msgs, attrs,
1310 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1311 "(objectclass=trustedDomain))",
1312 td_name, td_name, td_name);
1314 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1318 DEBUG(0,("Found %d records matching DN %s\n", ret,
1319 ldb_dn_get_linearized(policy_state->system_dn)));
1320 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1323 /* TODO: perform access checks */
1325 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1327 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1329 return NT_STATUS_NO_MEMORY;
1332 handle->data = talloc_steal(handle, trusted_domain_state);
1334 trusted_domain_state->access_mask = r->in.access_mask;
1335 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1337 *r->out.trustdom_handle = handle->wire_handle;
1339 return NT_STATUS_OK;
1345 lsa_SetTrustedDomainInfo
1347 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1348 struct lsa_SetTrustedDomainInfo *r)
1350 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1355 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1356 * otherwise at least one must be provided */
1357 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1358 struct ldb_dn *basedn, const char *dns_domain,
1359 const char *netbios, struct dom_sid2 *sid,
1360 struct ldb_message ***msgs)
1362 const char *attrs[] = { "flatname", "trustPartner",
1363 "securityIdentifier", "trustDirection",
1364 "trustType", "trustAttributes",
1366 "msDs-supportedEncryptionTypes", NULL };
1369 char *sidstr = NULL;
1374 if (dns_domain || netbios || sid) {
1375 filter = talloc_strdup(mem_ctx,
1376 "(&(objectclass=trustedDomain)(|");
1378 filter = talloc_strdup(mem_ctx,
1379 "(objectclass=trustedDomain)");
1382 return NT_STATUS_NO_MEMORY;
1386 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1388 return NT_STATUS_NO_MEMORY;
1390 filter = talloc_asprintf_append(filter,
1391 "(trustPartner=%s)", dns);
1393 return NT_STATUS_NO_MEMORY;
1397 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1399 return NT_STATUS_NO_MEMORY;
1401 filter = talloc_asprintf_append(filter,
1402 "(flatname=%s)", nbn);
1404 return NT_STATUS_NO_MEMORY;
1408 sidstr = dom_sid_string(mem_ctx, sid);
1410 return NT_STATUS_INVALID_PARAMETER;
1412 filter = talloc_asprintf_append(filter,
1413 "(securityIdentifier=%s)",
1416 return NT_STATUS_NO_MEMORY;
1419 if (dns_domain || netbios || sid) {
1420 filter = talloc_asprintf_append(filter, "))");
1422 return NT_STATUS_NO_MEMORY;
1426 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1428 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1432 return NT_STATUS_OBJECT_NAME_COLLISION;
1435 return NT_STATUS_OK;
1438 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1439 struct ldb_context *sam_ldb,
1440 struct ldb_message *orig,
1441 struct ldb_message *dest,
1442 const char *attribute,
1444 uint32_t *orig_value)
1446 const struct ldb_val *orig_val;
1447 uint32_t orig_uint = 0;
1448 unsigned int flags = 0;
1451 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1452 if (!orig_val || !orig_val->data) {
1453 /* add new attribute */
1454 flags = LDB_FLAG_MOD_ADD;
1458 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1459 if (errno != 0 || orig_uint != value) {
1460 /* replace also if can't get value */
1461 flags = LDB_FLAG_MOD_REPLACE;
1466 /* stored value is identical, nothing to change */
1470 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1471 if (ret != LDB_SUCCESS) {
1472 return NT_STATUS_NO_MEMORY;
1475 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1476 if (ret != LDB_SUCCESS) {
1477 return NT_STATUS_NO_MEMORY;
1482 *orig_value = orig_uint;
1484 return NT_STATUS_OK;
1487 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1488 struct ldb_context *sam_ldb,
1489 struct ldb_dn *base_dn,
1491 const char *netbios_name,
1492 struct trustAuthInOutBlob *in)
1494 const char *attrs[] = { "userAccountControl", NULL };
1495 struct ldb_message **msgs;
1496 struct ldb_message *msg;
1501 ret = gendb_search(sam_ldb, mem_ctx,
1502 base_dn, &msgs, attrs,
1503 "samAccountName=%s$", netbios_name);
1505 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1510 return NT_STATUS_OK;
1513 /* ok no existing user, add it from scratch */
1514 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1515 netbios_name, in, NULL);
1518 /* check user is what we are looking for */
1519 uac = ldb_msg_find_attr_as_uint(msgs[0],
1520 "userAccountControl", 0);
1521 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1522 return NT_STATUS_OBJECT_NAME_COLLISION;
1526 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1529 return NT_STATUS_OK;
1530 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1531 return NT_STATUS_ACCESS_DENIED;
1533 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1537 /* entry exists, just modify secret if any */
1538 if (in == NULL || in->count == 0) {
1539 return NT_STATUS_OK;
1542 msg = ldb_msg_new(mem_ctx);
1544 return NT_STATUS_NO_MEMORY;
1546 msg->dn = msgs[0]->dn;
1548 for (i = 0; i < in->count; i++) {
1549 const char *attribute;
1551 switch (in->current.array[i].AuthType) {
1552 case TRUST_AUTH_TYPE_NT4OWF:
1553 attribute = "unicodePwd";
1554 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1557 case TRUST_AUTH_TYPE_CLEAR:
1558 attribute = "clearTextPassword";
1559 v.data = in->current.array[i].AuthInfo.clear.password;
1560 v.length = in->current.array[i].AuthInfo.clear.size;
1566 ret = ldb_msg_add_empty(msg, attribute,
1567 LDB_FLAG_MOD_REPLACE, NULL);
1568 if (ret != LDB_SUCCESS) {
1569 return NT_STATUS_NO_MEMORY;
1572 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1573 if (ret != LDB_SUCCESS) {
1574 return NT_STATUS_NO_MEMORY;
1578 /* create the trusted_domain user account */
1579 ret = ldb_modify(sam_ldb, msg);
1580 if (ret != LDB_SUCCESS) {
1581 DEBUG(0,("Failed to create user record %s: %s\n",
1582 ldb_dn_get_linearized(msg->dn),
1583 ldb_errstring(sam_ldb)));
1586 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1587 return NT_STATUS_DOMAIN_EXISTS;
1588 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1589 return NT_STATUS_ACCESS_DENIED;
1591 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1595 return NT_STATUS_OK;
1599 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1600 struct dcesrv_handle *p_handle,
1601 TALLOC_CTX *mem_ctx,
1602 struct ldb_message *dom_msg,
1603 enum lsa_TrustDomInfoEnum level,
1604 union lsa_TrustedDomainInfo *info)
1606 struct lsa_policy_state *p_state = p_handle->data;
1607 uint32_t *posix_offset = NULL;
1608 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1609 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1610 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1611 uint32_t *enc_types = NULL;
1612 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1613 struct trustDomainPasswords auth_struct;
1614 struct trustAuthInOutBlob *current_passwords = NULL;
1616 struct ldb_message **msgs;
1617 struct ldb_message *msg;
1618 bool add_outgoing = false;
1619 bool add_incoming = false;
1620 bool del_outgoing = false;
1621 bool del_incoming = false;
1622 bool in_transaction = false;
1627 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1628 posix_offset = &info->posix_offset.posix_offset;
1630 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1631 info_ex = &info->info_ex;
1633 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1634 auth_info = &info->auth_info;
1636 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1637 posix_offset = &info->full_info.posix_offset.posix_offset;
1638 info_ex = &info->full_info.info_ex;
1639 auth_info = &info->full_info.auth_info;
1641 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1642 auth_info_int = &info->auth_info_internal;
1644 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1645 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1646 info_ex = &info->full_info_internal.info_ex;
1647 auth_info_int = &info->full_info_internal.auth_info;
1649 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1650 enc_types = &info->enc_types.enc_types;
1653 return NT_STATUS_INVALID_PARAMETER;
1657 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1659 &trustAuthOutgoing);
1660 if (!NT_STATUS_IS_OK(nt_status)) {
1663 if (trustAuthIncoming.data) {
1664 /* This does the decode of some of this twice, but it is easier that way */
1665 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1666 auth_info->incoming_count,
1667 auth_info->incoming_current_auth_info,
1669 ¤t_passwords);
1670 if (!NT_STATUS_IS_OK(nt_status)) {
1676 /* decode auth_info_int if set */
1677 if (auth_info_int) {
1679 /* now decrypt blob */
1680 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1681 auth_info_int->auth_blob.size);
1683 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1684 &auth_blob, &auth_struct);
1685 if (!NT_STATUS_IS_OK(nt_status)) {
1691 /* verify data matches */
1692 if (info_ex->trust_attributes &
1693 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1694 /* TODO: check what behavior level we have */
1695 if (strcasecmp_m(p_state->domain_dns,
1696 p_state->forest_dns) != 0) {
1697 return NT_STATUS_INVALID_DOMAIN_STATE;
1701 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1702 if (ret == LDB_SUCCESS && am_rodc) {
1703 return NT_STATUS_NO_SUCH_DOMAIN;
1706 /* verify only one object matches the dns/netbios/sid
1707 * triplet and that this is the one we already have */
1708 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1710 info_ex->domain_name.string,
1711 info_ex->netbios_name.string,
1712 info_ex->sid, &msgs);
1713 if (!NT_STATUS_IS_OK(nt_status)) {
1716 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1717 return NT_STATUS_OBJECT_NAME_COLLISION;
1722 /* TODO: should we fetch previous values from the existing entry
1723 * and append them ? */
1724 if (auth_info_int && auth_struct.incoming.count) {
1725 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1726 &auth_struct.incoming,
1727 &trustAuthIncoming);
1728 if (!NT_STATUS_IS_OK(nt_status)) {
1732 current_passwords = &auth_struct.incoming;
1735 trustAuthIncoming = data_blob(NULL, 0);
1738 if (auth_info_int && auth_struct.outgoing.count) {
1739 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1740 &auth_struct.outgoing,
1741 &trustAuthOutgoing);
1742 if (!NT_STATUS_IS_OK(nt_status)) {
1746 trustAuthOutgoing = data_blob(NULL, 0);
1749 msg = ldb_msg_new(mem_ctx);
1751 return NT_STATUS_NO_MEMORY;
1753 msg->dn = dom_msg->dn;
1756 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1759 *posix_offset, NULL);
1760 if (!NT_STATUS_IS_OK(nt_status)) {
1770 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1773 info_ex->trust_direction,
1775 if (!NT_STATUS_IS_OK(nt_status)) {
1779 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1780 add_incoming = true;
1782 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1783 add_outgoing = true;
1786 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1787 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1788 del_incoming = true;
1790 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1791 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1792 del_outgoing = true;
1795 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1796 if (origtype == -1 || origtype != info_ex->trust_type) {
1797 DEBUG(1, ("Attempted to change trust type! "
1798 "Operation not handled\n"));
1799 return NT_STATUS_INVALID_PARAMETER;
1802 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1805 info_ex->trust_attributes,
1807 if (!NT_STATUS_IS_OK(nt_status)) {
1810 /* TODO: check forestFunctionality from ldb opaque */
1811 /* TODO: check what is set makes sense */
1812 /* for now refuse changes */
1813 if (origattrs == -1 ||
1814 origattrs != info_ex->trust_attributes) {
1815 DEBUG(1, ("Attempted to change trust attributes! "
1816 "Operation not handled\n"));
1817 return NT_STATUS_INVALID_PARAMETER;
1822 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1824 "msDS-SupportedEncryptionTypes",
1826 if (!NT_STATUS_IS_OK(nt_status)) {
1831 if (add_incoming && trustAuthIncoming.data) {
1832 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1833 LDB_FLAG_MOD_REPLACE, NULL);
1834 if (ret != LDB_SUCCESS) {
1835 return NT_STATUS_NO_MEMORY;
1837 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1838 &trustAuthIncoming, NULL);
1839 if (ret != LDB_SUCCESS) {
1840 return NT_STATUS_NO_MEMORY;
1843 if (add_outgoing && trustAuthOutgoing.data) {
1844 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1845 LDB_FLAG_MOD_REPLACE, NULL);
1846 if (ret != LDB_SUCCESS) {
1847 return NT_STATUS_NO_MEMORY;
1849 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1850 &trustAuthOutgoing, NULL);
1851 if (ret != LDB_SUCCESS) {
1852 return NT_STATUS_NO_MEMORY;
1856 /* start transaction */
1857 ret = ldb_transaction_start(p_state->sam_ldb);
1858 if (ret != LDB_SUCCESS) {
1859 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1861 in_transaction = true;
1863 if (msg->num_elements) {
1864 ret = ldb_modify(p_state->sam_ldb, msg);
1865 if (ret != LDB_SUCCESS) {
1866 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1867 ldb_dn_get_linearized(msg->dn),
1868 ldb_errstring(p_state->sam_ldb)));
1869 nt_status = dsdb_ldb_err_to_ntstatus(ret);
1874 if (add_incoming || del_incoming) {
1875 const char *netbios_name;
1877 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1879 if (!netbios_name) {
1880 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1884 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
1885 nt_status = update_trust_user(mem_ctx,
1891 if (!NT_STATUS_IS_OK(nt_status)) {
1896 /* ok, all fine, commit transaction and return */
1897 ret = ldb_transaction_commit(p_state->sam_ldb);
1898 if (ret != LDB_SUCCESS) {
1899 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1901 in_transaction = false;
1903 nt_status = NT_STATUS_OK;
1906 if (in_transaction) {
1907 ldb_transaction_cancel(p_state->sam_ldb);
1913 lsa_SetInfomrationTrustedDomain
1915 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1916 struct dcesrv_call_state *dce_call,
1917 TALLOC_CTX *mem_ctx,
1918 struct lsa_SetInformationTrustedDomain *r)
1920 struct dcesrv_handle *h;
1921 struct lsa_trusted_domain_state *td_state;
1922 struct ldb_message **msgs;
1925 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1926 LSA_HANDLE_TRUSTED_DOMAIN);
1928 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1930 /* get the trusted domain object */
1931 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1932 td_state->trusted_domain_dn,
1933 NULL, NULL, NULL, &msgs);
1934 if (!NT_STATUS_IS_OK(nt_status)) {
1935 if (NT_STATUS_EQUAL(nt_status,
1936 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1939 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1942 return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1943 msgs[0], r->in.level, r->in.info);
1948 lsa_DeleteTrustedDomain
1950 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1951 struct lsa_DeleteTrustedDomain *r)
1954 struct lsa_OpenTrustedDomain opn;
1955 struct lsa_DeleteObject del;
1956 struct dcesrv_handle *h;
1958 opn.in.handle = r->in.handle;
1959 opn.in.sid = r->in.dom_sid;
1960 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1961 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1962 if (!opn.out.trustdom_handle) {
1963 return NT_STATUS_NO_MEMORY;
1965 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1966 if (!NT_STATUS_IS_OK(status)) {
1970 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1971 talloc_steal(mem_ctx, h);
1973 del.in.handle = opn.out.trustdom_handle;
1974 del.out.handle = opn.out.trustdom_handle;
1975 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1976 if (!NT_STATUS_IS_OK(status)) {
1979 return NT_STATUS_OK;
1982 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
1983 struct ldb_message *msg,
1984 struct lsa_TrustDomainInfoInfoEx *info_ex)
1986 info_ex->domain_name.string
1987 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1988 info_ex->netbios_name.string
1989 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1991 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1992 info_ex->trust_direction
1993 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1995 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1996 info_ex->trust_attributes
1997 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
1998 return NT_STATUS_OK;
2002 lsa_QueryTrustedDomainInfo
2004 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2005 struct lsa_QueryTrustedDomainInfo *r)
2007 union lsa_TrustedDomainInfo *info = NULL;
2008 struct dcesrv_handle *h;
2009 struct lsa_trusted_domain_state *trusted_domain_state;
2010 struct ldb_message *msg;
2012 struct ldb_message **res;
2013 const char *attrs[] = {
2016 "securityIdentifier",
2020 "msDs-supportedEncryptionTypes",
2024 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2026 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2028 /* pull all the user attributes */
2029 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2030 trusted_domain_state->trusted_domain_dn, &res, attrs);
2032 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2036 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2038 return NT_STATUS_NO_MEMORY;
2040 *r->out.info = info;
2042 switch (r->in.level) {
2043 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2044 info->name.netbios_name.string
2045 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2047 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2048 info->posix_offset.posix_offset
2049 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2051 #if 0 /* Win2k3 doesn't implement this */
2052 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2053 r->out.info->info_basic.netbios_name.string
2054 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2055 r->out.info->info_basic.sid
2056 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2059 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2060 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2062 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2063 ZERO_STRUCT(info->full_info);
2064 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2065 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2066 ZERO_STRUCT(info->full_info2_internal);
2067 info->full_info2_internal.posix_offset.posix_offset
2068 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2069 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2071 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2072 info->enc_types.enc_types
2073 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2076 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2077 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2078 /* oops, we don't want to return the info after all */
2080 *r->out.info = NULL;
2081 return NT_STATUS_INVALID_PARAMETER;
2083 /* oops, we don't want to return the info after all */
2085 *r->out.info = NULL;
2086 return NT_STATUS_INVALID_INFO_CLASS;
2089 return NT_STATUS_OK;
2094 lsa_QueryTrustedDomainInfoBySid
2096 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2097 struct lsa_QueryTrustedDomainInfoBySid *r)
2100 struct lsa_OpenTrustedDomain opn;
2101 struct lsa_QueryTrustedDomainInfo query;
2102 struct dcesrv_handle *h;
2104 opn.in.handle = r->in.handle;
2105 opn.in.sid = r->in.dom_sid;
2106 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2107 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2108 if (!opn.out.trustdom_handle) {
2109 return NT_STATUS_NO_MEMORY;
2111 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2112 if (!NT_STATUS_IS_OK(status)) {
2116 /* Ensure this handle goes away at the end of this call */
2117 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2118 talloc_steal(mem_ctx, h);
2120 query.in.trustdom_handle = opn.out.trustdom_handle;
2121 query.in.level = r->in.level;
2122 query.out.info = r->out.info;
2123 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2124 if (!NT_STATUS_IS_OK(status)) {
2128 return NT_STATUS_OK;
2132 lsa_SetTrustedDomainInfoByName
2134 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2135 TALLOC_CTX *mem_ctx,
2136 struct lsa_SetTrustedDomainInfoByName *r)
2138 struct dcesrv_handle *policy_handle;
2139 struct lsa_policy_state *policy_state;
2140 struct ldb_message **msgs;
2143 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2144 policy_state = policy_handle->data;
2146 /* get the trusted domain object */
2147 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2148 policy_state->domain_dn,
2149 r->in.trusted_domain->string,
2150 r->in.trusted_domain->string,
2152 if (!NT_STATUS_IS_OK(nt_status)) {
2153 if (NT_STATUS_EQUAL(nt_status,
2154 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2157 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2160 return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2161 msgs[0], r->in.level, r->in.info);
2165 lsa_QueryTrustedDomainInfoByName
2167 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2168 TALLOC_CTX *mem_ctx,
2169 struct lsa_QueryTrustedDomainInfoByName *r)
2172 struct lsa_OpenTrustedDomainByName opn;
2173 struct lsa_QueryTrustedDomainInfo query;
2174 struct dcesrv_handle *h;
2176 opn.in.handle = r->in.handle;
2177 opn.in.name = *r->in.trusted_domain;
2178 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2179 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2180 if (!opn.out.trustdom_handle) {
2181 return NT_STATUS_NO_MEMORY;
2183 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2184 if (!NT_STATUS_IS_OK(status)) {
2188 /* Ensure this handle goes away at the end of this call */
2189 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2190 talloc_steal(mem_ctx, h);
2192 query.in.trustdom_handle = opn.out.trustdom_handle;
2193 query.in.level = r->in.level;
2194 query.out.info = r->out.info;
2195 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2196 if (!NT_STATUS_IS_OK(status)) {
2200 return NT_STATUS_OK;
2204 lsa_CloseTrustedDomainEx
2206 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2207 TALLOC_CTX *mem_ctx,
2208 struct lsa_CloseTrustedDomainEx *r)
2210 /* The result of a bad hair day from an IDL programmer? Not
2211 * implmented in Win2k3. You should always just lsa_Close
2213 return NT_STATUS_NOT_IMPLEMENTED;
2218 comparison function for sorting lsa_DomainInformation array
2220 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2222 return strcasecmp_m(e1->name.string, e2->name.string);
2228 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2229 struct lsa_EnumTrustDom *r)
2231 struct dcesrv_handle *policy_handle;
2232 struct lsa_DomainInfo *entries;
2233 struct lsa_policy_state *policy_state;
2234 struct ldb_message **domains;
2235 const char *attrs[] = {
2237 "securityIdentifier",
2244 *r->out.resume_handle = 0;
2246 r->out.domains->domains = NULL;
2247 r->out.domains->count = 0;
2249 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2251 policy_state = policy_handle->data;
2253 /* search for all users in this domain. This could possibly be cached and
2254 resumed based on resume_key */
2255 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2256 "objectclass=trustedDomain");
2258 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2261 /* convert to lsa_TrustInformation format */
2262 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2264 return NT_STATUS_NO_MEMORY;
2266 for (i=0;i<count;i++) {
2267 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2268 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2271 /* sort the results by name */
2272 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2274 if (*r->in.resume_handle >= count) {
2275 *r->out.resume_handle = -1;
2277 return NT_STATUS_NO_MORE_ENTRIES;
2280 /* return the rest, limit by max_size. Note that we
2281 use the w2k3 element size value of 60 */
2282 r->out.domains->count = count - *r->in.resume_handle;
2283 r->out.domains->count = MIN(r->out.domains->count,
2284 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2286 r->out.domains->domains = entries + *r->in.resume_handle;
2287 r->out.domains->count = r->out.domains->count;
2289 if (r->out.domains->count < count - *r->in.resume_handle) {
2290 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2291 return STATUS_MORE_ENTRIES;
2294 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2295 * always be larger than the previous input resume handle, in
2296 * particular when hitting the last query it is vital to set the
2297 * resume handle correctly to avoid infinite client loops, as
2298 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2299 * status is NT_STATUS_OK - gd */
2301 *r->out.resume_handle = (uint32_t)-1;
2303 return NT_STATUS_OK;
2307 comparison function for sorting lsa_DomainInformation array
2309 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2311 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2315 lsa_EnumTrustedDomainsEx
2317 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2318 struct lsa_EnumTrustedDomainsEx *r)
2320 struct dcesrv_handle *policy_handle;
2321 struct lsa_TrustDomainInfoInfoEx *entries;
2322 struct lsa_policy_state *policy_state;
2323 struct ldb_message **domains;
2324 const char *attrs[] = {
2327 "securityIdentifier",
2337 *r->out.resume_handle = 0;
2339 r->out.domains->domains = NULL;
2340 r->out.domains->count = 0;
2342 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2344 policy_state = policy_handle->data;
2346 /* search for all users in this domain. This could possibly be cached and
2347 resumed based on resume_key */
2348 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2349 "objectclass=trustedDomain");
2351 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2354 /* convert to lsa_DomainInformation format */
2355 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2357 return NT_STATUS_NO_MEMORY;
2359 for (i=0;i<count;i++) {
2360 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2361 if (!NT_STATUS_IS_OK(nt_status)) {
2366 /* sort the results by name */
2367 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2369 if (*r->in.resume_handle >= count) {
2370 *r->out.resume_handle = -1;
2372 return NT_STATUS_NO_MORE_ENTRIES;
2375 /* return the rest, limit by max_size. Note that we
2376 use the w2k3 element size value of 60 */
2377 r->out.domains->count = count - *r->in.resume_handle;
2378 r->out.domains->count = MIN(r->out.domains->count,
2379 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2381 r->out.domains->domains = entries + *r->in.resume_handle;
2382 r->out.domains->count = r->out.domains->count;
2384 if (r->out.domains->count < count - *r->in.resume_handle) {
2385 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2386 return STATUS_MORE_ENTRIES;
2389 return NT_STATUS_OK;
2396 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2397 struct lsa_OpenAccount *r)
2399 struct dcesrv_handle *h, *ah;
2400 struct lsa_policy_state *state;
2401 struct lsa_account_state *astate;
2403 ZERO_STRUCTP(r->out.acct_handle);
2405 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2409 astate = talloc(dce_call->conn, struct lsa_account_state);
2410 if (astate == NULL) {
2411 return NT_STATUS_NO_MEMORY;
2414 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2415 if (astate->account_sid == NULL) {
2416 talloc_free(astate);
2417 return NT_STATUS_NO_MEMORY;
2420 astate->policy = talloc_reference(astate, state);
2421 astate->access_mask = r->in.access_mask;
2423 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2425 talloc_free(astate);
2426 return NT_STATUS_NO_MEMORY;
2429 ah->data = talloc_steal(ah, astate);
2431 *r->out.acct_handle = ah->wire_handle;
2433 return NT_STATUS_OK;
2438 lsa_EnumPrivsAccount
2440 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2441 TALLOC_CTX *mem_ctx,
2442 struct lsa_EnumPrivsAccount *r)
2444 struct dcesrv_handle *h;
2445 struct lsa_account_state *astate;
2448 struct ldb_message **res;
2449 const char * const attrs[] = { "privilege", NULL};
2450 struct ldb_message_element *el;
2452 struct lsa_PrivilegeSet *privs;
2454 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2458 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2459 if (privs == NULL) {
2460 return NT_STATUS_NO_MEMORY;
2466 *r->out.privs = privs;
2468 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2469 if (sidstr == NULL) {
2470 return NT_STATUS_NO_MEMORY;
2473 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2474 "objectSid=%s", sidstr);
2476 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2479 return NT_STATUS_OK;
2482 el = ldb_msg_find_element(res[0], "privilege");
2483 if (el == NULL || el->num_values == 0) {
2484 return NT_STATUS_OK;
2487 privs->set = talloc_array(privs,
2488 struct lsa_LUIDAttribute, el->num_values);
2489 if (privs->set == NULL) {
2490 return NT_STATUS_NO_MEMORY;
2494 for (i=0;i<el->num_values;i++) {
2495 int id = sec_privilege_id((const char *)el->values[i].data);
2496 if (id == SEC_PRIV_INVALID) {
2497 /* Perhaps an account right, not a privilege */
2500 privs->set[j].attribute = 0;
2501 privs->set[j].luid.low = id;
2502 privs->set[j].luid.high = 0;
2508 return NT_STATUS_OK;
2512 lsa_EnumAccountRights
2514 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2515 TALLOC_CTX *mem_ctx,
2516 struct lsa_EnumAccountRights *r)
2518 struct dcesrv_handle *h;
2519 struct lsa_policy_state *state;
2522 struct ldb_message **res;
2523 const char * const attrs[] = { "privilege", NULL};
2525 struct ldb_message_element *el;
2527 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2531 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2532 if (sidstr == NULL) {
2533 return NT_STATUS_NO_MEMORY;
2536 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2537 "(&(objectSid=%s)(privilege=*))", sidstr);
2539 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2542 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2543 dom_sid_string(mem_ctx, r->in.sid),
2544 ldb_errstring(state->pdb)));
2545 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2548 el = ldb_msg_find_element(res[0], "privilege");
2549 if (el == NULL || el->num_values == 0) {
2550 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2553 r->out.rights->count = el->num_values;
2554 r->out.rights->names = talloc_array(r->out.rights,
2555 struct lsa_StringLarge, r->out.rights->count);
2556 if (r->out.rights->names == NULL) {
2557 return NT_STATUS_NO_MEMORY;
2560 for (i=0;i<el->num_values;i++) {
2561 r->out.rights->names[i].string = (const char *)el->values[i].data;
2564 return NT_STATUS_OK;
2570 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2572 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2573 TALLOC_CTX *mem_ctx,
2574 struct lsa_policy_state *state,
2576 struct dom_sid *sid,
2577 const struct lsa_RightSet *rights)
2579 const char *sidstr, *sidndrstr;
2580 struct ldb_message *msg;
2581 struct ldb_message_element *el;
2584 struct lsa_EnumAccountRights r2;
2587 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2588 SECURITY_ADMINISTRATOR) {
2589 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2590 return NT_STATUS_ACCESS_DENIED;
2593 msg = ldb_msg_new(mem_ctx);
2595 return NT_STATUS_NO_MEMORY;
2598 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2599 if (sidndrstr == NULL) {
2601 return NT_STATUS_NO_MEMORY;
2604 sidstr = dom_sid_string(msg, sid);
2605 if (sidstr == NULL) {
2607 return NT_STATUS_NO_MEMORY;
2610 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2611 if (dnstr == NULL) {
2613 return NT_STATUS_NO_MEMORY;
2616 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2617 if (msg->dn == NULL) {
2619 return NT_STATUS_NO_MEMORY;
2622 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2625 r2.in.handle = &state->handle->wire_handle;
2627 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2629 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2630 if (!NT_STATUS_IS_OK(status)) {
2631 ZERO_STRUCTP(r2.out.rights);
2635 for (i=0;i<rights->count;i++) {
2636 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2637 if (sec_right_bit(rights->names[i].string) == 0) {
2639 return NT_STATUS_NO_SUCH_PRIVILEGE;
2643 return NT_STATUS_NO_SUCH_PRIVILEGE;
2646 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2648 for (j=0;j<r2.out.rights->count;j++) {
2649 if (strcasecmp_m(r2.out.rights->names[j].string,
2650 rights->names[i].string) == 0) {
2654 if (j != r2.out.rights->count) continue;
2657 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2658 if (ret != LDB_SUCCESS) {
2660 return NT_STATUS_NO_MEMORY;
2664 el = ldb_msg_find_element(msg, "privilege");
2667 return NT_STATUS_OK;
2670 el->flags = ldb_flag;
2672 ret = ldb_modify(state->pdb, msg);
2673 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2674 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2676 return NT_STATUS_NO_MEMORY;
2678 ldb_msg_add_string(msg, "comment", "added via LSA");
2679 ret = ldb_add(state->pdb, msg);
2681 if (ret != LDB_SUCCESS) {
2682 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2684 return NT_STATUS_OK;
2686 DEBUG(3, ("Could not %s attributes from %s: %s",
2687 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2688 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2690 return NT_STATUS_UNEXPECTED_IO_ERROR;
2694 return NT_STATUS_OK;
2698 lsa_AddPrivilegesToAccount
2700 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2701 struct lsa_AddPrivilegesToAccount *r)
2703 struct lsa_RightSet rights;
2704 struct dcesrv_handle *h;
2705 struct lsa_account_state *astate;
2708 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2712 rights.count = r->in.privs->count;
2713 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2714 if (rights.names == NULL) {
2715 return NT_STATUS_NO_MEMORY;
2717 for (i=0;i<rights.count;i++) {
2718 int id = r->in.privs->set[i].luid.low;
2719 if (r->in.privs->set[i].luid.high) {
2720 return NT_STATUS_NO_SUCH_PRIVILEGE;
2722 rights.names[i].string = sec_privilege_name(id);
2723 if (rights.names[i].string == NULL) {
2724 return NT_STATUS_NO_SUCH_PRIVILEGE;
2728 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2729 LDB_FLAG_MOD_ADD, astate->account_sid,
2735 lsa_RemovePrivilegesFromAccount
2737 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2738 struct lsa_RemovePrivilegesFromAccount *r)
2740 struct lsa_RightSet *rights;
2741 struct dcesrv_handle *h;
2742 struct lsa_account_state *astate;
2745 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2749 rights = talloc(mem_ctx, struct lsa_RightSet);
2751 if (r->in.remove_all == 1 &&
2752 r->in.privs == NULL) {
2753 struct lsa_EnumAccountRights r2;
2756 r2.in.handle = &astate->policy->handle->wire_handle;
2757 r2.in.sid = astate->account_sid;
2758 r2.out.rights = rights;
2760 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2761 if (!NT_STATUS_IS_OK(status)) {
2765 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2766 LDB_FLAG_MOD_DELETE, astate->account_sid,
2770 if (r->in.remove_all != 0) {
2771 return NT_STATUS_INVALID_PARAMETER;
2774 rights->count = r->in.privs->count;
2775 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2776 if (rights->names == NULL) {
2777 return NT_STATUS_NO_MEMORY;
2779 for (i=0;i<rights->count;i++) {
2780 int id = r->in.privs->set[i].luid.low;
2781 if (r->in.privs->set[i].luid.high) {
2782 return NT_STATUS_NO_SUCH_PRIVILEGE;
2784 rights->names[i].string = sec_privilege_name(id);
2785 if (rights->names[i].string == NULL) {
2786 return NT_STATUS_NO_SUCH_PRIVILEGE;
2790 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2791 LDB_FLAG_MOD_DELETE, astate->account_sid,
2797 lsa_GetQuotasForAccount
2799 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2800 struct lsa_GetQuotasForAccount *r)
2802 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2807 lsa_SetQuotasForAccount
2809 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2810 struct lsa_SetQuotasForAccount *r)
2812 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2817 lsa_GetSystemAccessAccount
2819 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2820 struct lsa_GetSystemAccessAccount *r)
2822 struct dcesrv_handle *h;
2823 struct lsa_account_state *astate;
2826 struct ldb_message **res;
2827 const char * const attrs[] = { "privilege", NULL};
2828 struct ldb_message_element *el;
2831 *(r->out.access_mask) = 0x00000000;
2833 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2837 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2838 if (sidstr == NULL) {
2839 return NT_STATUS_NO_MEMORY;
2842 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2843 "objectSid=%s", sidstr);
2845 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2848 return NT_STATUS_OK;
2851 el = ldb_msg_find_element(res[0], "privilege");
2852 if (el == NULL || el->num_values == 0) {
2853 return NT_STATUS_OK;
2856 for (i=0;i<el->num_values;i++) {
2857 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2858 if (right_bit == 0) {
2859 /* Perhaps an privilege, not a right */
2862 *(r->out.access_mask) |= right_bit;
2865 return NT_STATUS_OK;
2870 lsa_SetSystemAccessAccount
2872 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2873 struct lsa_SetSystemAccessAccount *r)
2875 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2882 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2883 struct lsa_CreateSecret *r)
2885 struct dcesrv_handle *policy_handle;
2886 struct lsa_policy_state *policy_state;
2887 struct lsa_secret_state *secret_state;
2888 struct dcesrv_handle *handle;
2889 struct ldb_message **msgs, *msg;
2890 const char *attrs[] = {
2898 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2899 ZERO_STRUCTP(r->out.sec_handle);
2901 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2903 case SECURITY_SYSTEM:
2904 case SECURITY_ADMINISTRATOR:
2907 /* Users and annonymous are not allowed create secrets */
2908 return NT_STATUS_ACCESS_DENIED;
2911 policy_state = policy_handle->data;
2913 if (!r->in.name.string) {
2914 return NT_STATUS_INVALID_PARAMETER;
2917 secret_state = talloc(mem_ctx, struct lsa_secret_state);
2918 NT_STATUS_HAVE_NO_MEMORY(secret_state);
2919 secret_state->policy = policy_state;
2921 msg = ldb_msg_new(mem_ctx);
2923 return NT_STATUS_NO_MEMORY;
2926 if (strncmp("G$", r->in.name.string, 2) == 0) {
2929 secret_state->global = true;
2931 name = &r->in.name.string[2];
2932 if (strlen(name) == 0) {
2933 return NT_STATUS_INVALID_PARAMETER;
2936 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2937 ldb_binary_encode_string(mem_ctx, name));
2938 NT_STATUS_HAVE_NO_MEMORY(name2);
2940 /* We need to connect to the database as system, as this is one
2941 * of the rare RPC calls that must read the secrets (and this
2942 * is denied otherwise) */
2943 secret_state->sam_ldb = talloc_reference(secret_state,
2944 samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
2945 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2947 /* search for the secret record */
2948 ret = gendb_search(secret_state->sam_ldb,
2949 mem_ctx, policy_state->system_dn, &msgs, attrs,
2950 "(&(cn=%s)(objectclass=secret))",
2953 return NT_STATUS_OBJECT_NAME_COLLISION;
2957 DEBUG(0,("Failure searching for CN=%s: %s\n",
2958 name2, ldb_errstring(secret_state->sam_ldb)));
2959 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2962 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2963 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2964 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2965 return NT_STATUS_NO_MEMORY;
2968 ret = ldb_msg_add_string(msg, "cn", name2);
2969 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2971 secret_state->global = false;
2973 name = r->in.name.string;
2974 if (strlen(name) == 0) {
2975 return NT_STATUS_INVALID_PARAMETER;
2978 secret_state->sam_ldb = talloc_reference(secret_state,
2979 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
2980 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2982 /* search for the secret record */
2983 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2984 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2986 "(&(cn=%s)(objectclass=secret))",
2987 ldb_binary_encode_string(mem_ctx, name));
2989 return NT_STATUS_OBJECT_NAME_COLLISION;
2993 DEBUG(0,("Failure searching for CN=%s: %s\n",
2994 name, ldb_errstring(secret_state->sam_ldb)));
2995 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2998 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
2999 "cn=%s,cn=LSA Secrets", name);
3000 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3001 ret = ldb_msg_add_string(msg, "cn", name);
3002 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3005 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3006 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3008 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3009 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3011 /* create the secret */
3012 ret = ldb_add(secret_state->sam_ldb, msg);
3013 if (ret != LDB_SUCCESS) {
3014 DEBUG(0,("Failed to create secret record %s: %s\n",
3015 ldb_dn_get_linearized(msg->dn),
3016 ldb_errstring(secret_state->sam_ldb)));
3017 return NT_STATUS_ACCESS_DENIED;
3020 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3021 NT_STATUS_HAVE_NO_MEMORY(handle);
3023 handle->data = talloc_steal(handle, secret_state);
3025 secret_state->access_mask = r->in.access_mask;
3026 secret_state->policy = talloc_reference(secret_state, policy_state);
3027 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3029 *r->out.sec_handle = handle->wire_handle;
3031 return NT_STATUS_OK;
3038 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3039 struct lsa_OpenSecret *r)
3041 struct dcesrv_handle *policy_handle;
3043 struct lsa_policy_state *policy_state;
3044 struct lsa_secret_state *secret_state;
3045 struct dcesrv_handle *handle;
3046 struct ldb_message **msgs;
3047 const char *attrs[] = {
3055 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3056 ZERO_STRUCTP(r->out.sec_handle);
3057 policy_state = policy_handle->data;
3059 if (!r->in.name.string) {
3060 return NT_STATUS_INVALID_PARAMETER;
3063 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3065 case SECURITY_SYSTEM:
3066 case SECURITY_ADMINISTRATOR:
3069 /* Users and annonymous are not allowed to access secrets */
3070 return NT_STATUS_ACCESS_DENIED;
3073 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3074 if (!secret_state) {
3075 return NT_STATUS_NO_MEMORY;
3077 secret_state->policy = policy_state;
3079 if (strncmp("G$", r->in.name.string, 2) == 0) {
3080 name = &r->in.name.string[2];
3081 /* We need to connect to the database as system, as this is one of the rare RPC calls that must read the secrets (and this is denied otherwise) */
3082 secret_state->sam_ldb = talloc_reference(secret_state,
3083 samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
3084 secret_state->global = true;
3086 if (strlen(name) < 1) {
3087 return NT_STATUS_INVALID_PARAMETER;
3090 /* search for the secret record */
3091 ret = gendb_search(secret_state->sam_ldb,
3092 mem_ctx, policy_state->system_dn, &msgs, attrs,
3093 "(&(cn=%s Secret)(objectclass=secret))",
3094 ldb_binary_encode_string(mem_ctx, name));
3096 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3100 DEBUG(0,("Found %d records matching DN %s\n", ret,
3101 ldb_dn_get_linearized(policy_state->system_dn)));
3102 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3105 secret_state->global = false;
3106 secret_state->sam_ldb = talloc_reference(secret_state,
3107 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3109 name = r->in.name.string;
3110 if (strlen(name) < 1) {
3111 return NT_STATUS_INVALID_PARAMETER;
3114 /* search for the secret record */
3115 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3116 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3118 "(&(cn=%s)(objectclass=secret))",
3119 ldb_binary_encode_string(mem_ctx, name));
3121 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3125 DEBUG(0,("Found %d records matching CN=%s\n",
3126 ret, ldb_binary_encode_string(mem_ctx, name)));
3127 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3131 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3133 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3135 return NT_STATUS_NO_MEMORY;
3138 handle->data = talloc_steal(handle, secret_state);
3140 secret_state->access_mask = r->in.access_mask;
3141 secret_state->policy = talloc_reference(secret_state, policy_state);
3143 *r->out.sec_handle = handle->wire_handle;
3145 return NT_STATUS_OK;
3152 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3153 struct lsa_SetSecret *r)
3156 struct dcesrv_handle *h;
3157 struct lsa_secret_state *secret_state;
3158 struct ldb_message *msg;
3159 DATA_BLOB session_key;
3160 DATA_BLOB crypt_secret, secret;
3163 NTSTATUS status = NT_STATUS_OK;
3165 struct timeval now = timeval_current();
3166 NTTIME nt_now = timeval_to_nttime(&now);
3168 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3170 secret_state = h->data;
3172 msg = ldb_msg_new(mem_ctx);
3174 return NT_STATUS_NO_MEMORY;
3177 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3179 return NT_STATUS_NO_MEMORY;
3181 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3182 if (!NT_STATUS_IS_OK(status)) {
3186 if (r->in.old_val) {
3188 crypt_secret.data = r->in.old_val->data;
3189 crypt_secret.length = r->in.old_val->size;
3191 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3192 if (!NT_STATUS_IS_OK(status)) {
3196 val.data = secret.data;
3197 val.length = secret.length;
3200 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3201 return NT_STATUS_NO_MEMORY;
3204 /* set old value mtime */
3205 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3206 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3207 return NT_STATUS_NO_MEMORY;
3211 /* If the old value is not set, then migrate the
3212 * current value to the old value */
3213 const struct ldb_val *old_val;
3214 NTTIME last_set_time;
3215 struct ldb_message **res;
3216 const char *attrs[] = {
3222 /* search for the secret record */
3223 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3224 secret_state->secret_dn, &res, attrs);
3226 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3230 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3231 ldb_dn_get_linearized(secret_state->secret_dn)));
3232 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3235 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3236 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3240 if (ldb_msg_add_value(msg, "priorValue",
3241 old_val, NULL) != LDB_SUCCESS) {
3242 return NT_STATUS_NO_MEMORY;
3245 if (samdb_msg_add_delete(secret_state->sam_ldb,
3246 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3247 return NT_STATUS_NO_MEMORY;
3251 /* set old value mtime */
3252 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3253 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3254 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3255 return NT_STATUS_NO_MEMORY;
3258 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3259 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3260 return NT_STATUS_NO_MEMORY;
3265 if (r->in.new_val) {
3267 crypt_secret.data = r->in.new_val->data;
3268 crypt_secret.length = r->in.new_val->size;
3270 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3271 if (!NT_STATUS_IS_OK(status)) {
3275 val.data = secret.data;
3276 val.length = secret.length;
3279 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3280 return NT_STATUS_NO_MEMORY;
3283 /* set new value mtime */
3284 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3285 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3286 return NT_STATUS_NO_MEMORY;
3289 /* NULL out the NEW value */
3290 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3291 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3292 return NT_STATUS_NO_MEMORY;
3294 if (samdb_msg_add_delete(secret_state->sam_ldb,
3295 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3296 return NT_STATUS_NO_MEMORY;
3300 /* modify the samdb record */
3301 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3302 if (ret != LDB_SUCCESS) {
3303 return dsdb_ldb_err_to_ntstatus(ret);
3306 return NT_STATUS_OK;
3313 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3314 struct lsa_QuerySecret *r)
3316 struct dcesrv_handle *h;
3317 struct lsa_secret_state *secret_state;
3318 struct ldb_message *msg;
3319 DATA_BLOB session_key;
3320 DATA_BLOB crypt_secret, secret;
3322 struct ldb_message **res;
3323 const char *attrs[] = {
3333 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3335 /* Ensure user is permitted to read this... */
3336 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3338 case SECURITY_SYSTEM:
3339 case SECURITY_ADMINISTRATOR:
3342 /* Users and annonymous are not allowed to read secrets */
3343 return NT_STATUS_ACCESS_DENIED;
3346 secret_state = h->data;
3348 /* pull all the user attributes */
3349 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3350 secret_state->secret_dn, &res, attrs);
3352 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3356 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3357 if (!NT_STATUS_IS_OK(nt_status)) {
3361 if (r->in.old_val) {
3362 const struct ldb_val *prior_val;
3363 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3364 if (!r->out.old_val) {
3365 return NT_STATUS_NO_MEMORY;
3367 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3369 if (prior_val && prior_val->length) {
3370 secret.data = prior_val->data;
3371 secret.length = prior_val->length;
3374 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3375 if (!crypt_secret.length) {
3376 return NT_STATUS_NO_MEMORY;
3378 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3379 if (!r->out.old_val->buf) {
3380 return NT_STATUS_NO_MEMORY;
3382 r->out.old_val->buf->size = crypt_secret.length;
3383 r->out.old_val->buf->length = crypt_secret.length;
3384 r->out.old_val->buf->data = crypt_secret.data;
3388 if (r->in.old_mtime) {
3389 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3390 if (!r->out.old_mtime) {
3391 return NT_STATUS_NO_MEMORY;
3393 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3396 if (r->in.new_val) {
3397 const struct ldb_val *new_val;
3398 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3399 if (!r->out.new_val) {
3400 return NT_STATUS_NO_MEMORY;
3403 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3405 if (new_val && new_val->length) {
3406 secret.data = new_val->data;
3407 secret.length = new_val->length;
3410 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3411 if (!crypt_secret.length) {
3412 return NT_STATUS_NO_MEMORY;
3414 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3415 if (!r->out.new_val->buf) {
3416 return NT_STATUS_NO_MEMORY;
3418 r->out.new_val->buf->length = crypt_secret.length;
3419 r->out.new_val->buf->size = crypt_secret.length;
3420 r->out.new_val->buf->data = crypt_secret.data;
3424 if (r->in.new_mtime) {
3425 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3426 if (!r->out.new_mtime) {
3427 return NT_STATUS_NO_MEMORY;
3429 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3432 return NT_STATUS_OK;
3439 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3440 TALLOC_CTX *mem_ctx,
3441 struct lsa_LookupPrivValue *r)
3443 struct dcesrv_handle *h;
3446 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3448 id = sec_privilege_id(r->in.name->string);
3449 if (id == SEC_PRIV_INVALID) {
3450 return NT_STATUS_NO_SUCH_PRIVILEGE;
3453 r->out.luid->low = id;
3454 r->out.luid->high = 0;
3456 return NT_STATUS_OK;
3463 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3464 TALLOC_CTX *mem_ctx,
3465 struct lsa_LookupPrivName *r)
3467 struct dcesrv_handle *h;
3468 struct lsa_StringLarge *name;
3469 const char *privname;
3471 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3473 if (r->in.luid->high != 0) {
3474 return NT_STATUS_NO_SUCH_PRIVILEGE;
3477 privname = sec_privilege_name(r->in.luid->low);
3478 if (privname == NULL) {
3479 return NT_STATUS_NO_SUCH_PRIVILEGE;
3482 name = talloc(mem_ctx, struct lsa_StringLarge);
3484 return NT_STATUS_NO_MEMORY;
3487 name->string = privname;
3489 *r->out.name = name;
3491 return NT_STATUS_OK;
3496 lsa_LookupPrivDisplayName
3498 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3499 TALLOC_CTX *mem_ctx,
3500 struct lsa_LookupPrivDisplayName *r)
3502 struct dcesrv_handle *h;
3503 struct lsa_StringLarge *disp_name = NULL;
3504 enum sec_privilege id;
3506 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3508 id = sec_privilege_id(r->in.name->string);
3509 if (id == SEC_PRIV_INVALID) {
3510 return NT_STATUS_NO_SUCH_PRIVILEGE;
3513 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3514 if (disp_name == NULL) {
3515 return NT_STATUS_NO_MEMORY;
3518 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3519 if (disp_name->string == NULL) {
3520 return NT_STATUS_INTERNAL_ERROR;
3523 *r->out.disp_name = disp_name;
3524 *r->out.returned_language_id = 0;
3526 return NT_STATUS_OK;
3531 lsa_EnumAccountsWithUserRight
3533 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3534 TALLOC_CTX *mem_ctx,
3535 struct lsa_EnumAccountsWithUserRight *r)
3537 struct dcesrv_handle *h;
3538 struct lsa_policy_state *state;
3540 struct ldb_message **res;
3541 const char * const attrs[] = { "objectSid", NULL};
3542 const char *privname;
3544 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3548 if (r->in.name == NULL) {
3549 return NT_STATUS_NO_SUCH_PRIVILEGE;
3552 privname = r->in.name->string;
3553 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3554 return NT_STATUS_NO_SUCH_PRIVILEGE;
3557 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3558 "privilege=%s", privname);
3560 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3563 return NT_STATUS_NO_MORE_ENTRIES;
3566 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3567 if (r->out.sids->sids == NULL) {
3568 return NT_STATUS_NO_MEMORY;
3570 for (i=0;i<ret;i++) {
3571 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3572 res[i], "objectSid");
3573 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3575 r->out.sids->num_sids = ret;
3577 return NT_STATUS_OK;
3582 lsa_AddAccountRights
3584 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3585 TALLOC_CTX *mem_ctx,
3586 struct lsa_AddAccountRights *r)
3588 struct dcesrv_handle *h;
3589 struct lsa_policy_state *state;
3591 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3595 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3597 r->in.sid, r->in.rights);
3602 lsa_RemoveAccountRights
3604 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3605 TALLOC_CTX *mem_ctx,
3606 struct lsa_RemoveAccountRights *r)
3608 struct dcesrv_handle *h;
3609 struct lsa_policy_state *state;
3611 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3615 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3616 LDB_FLAG_MOD_DELETE,
3617 r->in.sid, r->in.rights);
3622 lsa_StorePrivateData
3624 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3625 struct lsa_StorePrivateData *r)
3627 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3632 lsa_RetrievePrivateData
3634 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3635 struct lsa_RetrievePrivateData *r)
3637 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3644 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3645 struct lsa_GetUserName *r)
3647 enum dcerpc_transport_t transport =
3648 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3649 NTSTATUS status = NT_STATUS_OK;
3650 const char *account_name;
3651 const char *authority_name;
3652 struct lsa_String *_account_name;
3653 struct lsa_String *_authority_name = NULL;
3655 if (transport != NCACN_NP && transport != NCALRPC) {
3656 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3659 /* this is what w2k3 does */
3660 r->out.account_name = r->in.account_name;
3661 r->out.authority_name = r->in.authority_name;
3663 if (r->in.account_name
3664 && *r->in.account_name
3665 /* && *(*r->in.account_name)->string */
3667 return NT_STATUS_INVALID_PARAMETER;
3670 if (r->in.authority_name
3671 && *r->in.authority_name
3672 /* && *(*r->in.authority_name)->string */
3674 return NT_STATUS_INVALID_PARAMETER;
3677 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3678 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3680 _account_name = talloc(mem_ctx, struct lsa_String);
3681 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3682 _account_name->string = account_name;
3684 if (r->in.authority_name) {
3685 _authority_name = talloc(mem_ctx, struct lsa_String);
3686 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3687 _authority_name->string = authority_name;
3690 *r->out.account_name = _account_name;
3691 if (r->out.authority_name) {
3692 *r->out.authority_name = _authority_name;
3701 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3702 TALLOC_CTX *mem_ctx,
3703 struct lsa_SetInfoPolicy2 *r)
3705 /* need to support these */
3706 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3709 static void kdc_get_policy(struct loadparm_context *lp_ctx,
3710 struct smb_krb5_context *smb_krb5_context,
3711 struct lsa_DomainInfoKerberos *k)
3713 time_t svc_tkt_lifetime;
3714 time_t usr_tkt_lifetime;
3715 time_t renewal_lifetime;
3717 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
3719 /* Our KDC always re-validates the client */
3720 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
3722 lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
3723 &usr_tkt_lifetime, &renewal_lifetime);
3725 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
3726 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
3727 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
3728 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
3729 However in the parent function we basically just did a full
3730 krb5_context init with the only purpose of getting a global
3731 config option (the max skew), it would probably make more sense
3732 to have a lp_ or ldb global option as the samba default */
3733 if (smb_krb5_context) {
3734 unix_to_nt_time(&k->clock_skew,
3735 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
3741 lsa_QueryDomainInformationPolicy
3743 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3744 TALLOC_CTX *mem_ctx,
3745 struct lsa_QueryDomainInformationPolicy *r)
3747 union lsa_DomainInformationPolicy *info;
3749 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3751 return NT_STATUS_NO_MEMORY;
3754 switch (r->in.level) {
3755 case LSA_DOMAIN_INFO_POLICY_EFS:
3757 *r->out.info = NULL;
3758 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3759 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3761 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3762 struct smb_krb5_context *smb_krb5_context;
3763 int ret = smb_krb5_init_context(mem_ctx,
3764 dce_call->event_ctx,
3765 dce_call->conn->dce_ctx->lp_ctx,
3769 *r->out.info = NULL;
3770 return NT_STATUS_INTERNAL_ERROR;
3772 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3775 talloc_free(smb_krb5_context);
3776 *r->out.info = info;
3777 return NT_STATUS_OK;
3781 *r->out.info = NULL;
3782 return NT_STATUS_INVALID_INFO_CLASS;
3787 lsa_SetDomInfoPolicy
3789 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3790 TALLOC_CTX *mem_ctx,
3791 struct lsa_SetDomainInformationPolicy *r)
3793 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3799 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3800 TALLOC_CTX *mem_ctx,
3801 struct lsa_TestCall *r)
3803 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3809 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3810 struct lsa_CREDRWRITE *r)
3812 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3819 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3820 struct lsa_CREDRREAD *r)
3822 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3829 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3830 struct lsa_CREDRENUMERATE *r)
3832 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3837 lsa_CREDRWRITEDOMAINCREDENTIALS
3839 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3840 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3842 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3847 lsa_CREDRREADDOMAINCREDENTIALS
3849 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3850 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3852 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3859 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3860 struct lsa_CREDRDELETE *r)
3862 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3867 lsa_CREDRGETTARGETINFO
3869 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3870 struct lsa_CREDRGETTARGETINFO *r)
3872 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3877 lsa_CREDRPROFILELOADED
3879 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3880 struct lsa_CREDRPROFILELOADED *r)
3882 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3887 lsa_CREDRGETSESSIONTYPES
3889 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3890 struct lsa_CREDRGETSESSIONTYPES *r)
3892 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3897 lsa_LSARREGISTERAUDITEVENT
3899 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3900 struct lsa_LSARREGISTERAUDITEVENT *r)
3902 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3907 lsa_LSARGENAUDITEVENT
3909 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3910 struct lsa_LSARGENAUDITEVENT *r)
3912 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3917 lsa_LSARUNREGISTERAUDITEVENT
3919 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3920 struct lsa_LSARUNREGISTERAUDITEVENT *r)
3922 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3927 lsa_lsaRQueryForestTrustInformation
3929 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3930 struct lsa_lsaRQueryForestTrustInformation *r)
3932 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3935 #define DNS_CMP_MATCH 0
3936 #define DNS_CMP_FIRST_IS_CHILD 1
3937 #define DNS_CMP_SECOND_IS_CHILD 2
3938 #define DNS_CMP_NO_MATCH 3
3940 /* this function assumes names are well formed DNS names.
3941 * it doesn't validate them */
3942 static int dns_cmp(const char *s1, size_t l1,
3943 const char *s2, size_t l2)
3945 const char *p1, *p2;
3950 if (strcasecmp_m(s1, s2) == 0) {
3951 return DNS_CMP_MATCH;
3953 return DNS_CMP_NO_MATCH;
3961 cret = DNS_CMP_FIRST_IS_CHILD;
3967 cret = DNS_CMP_SECOND_IS_CHILD;
3970 if (p1[t1 - t2 - 1] != '.') {
3971 return DNS_CMP_NO_MATCH;
3974 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3978 return DNS_CMP_NO_MATCH;
3981 /* decode all TDOs forest trust info blobs */
3982 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3983 struct ldb_message *msg,
3984 struct ForestTrustInfo *info)
3986 const struct ldb_val *ft_blob;
3987 enum ndr_err_code ndr_err;
3989 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3990 if (!ft_blob || !ft_blob->data) {
3991 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3993 /* ldb_val is equivalent to DATA_BLOB */
3994 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3995 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3996 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3997 return NT_STATUS_INVALID_DOMAIN_STATE;
4000 return NT_STATUS_OK;
4003 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
4004 struct ForestTrustInfo *fti)
4006 struct ForestTrustDataDomainInfo *info;
4007 struct ForestTrustInfoRecord *rec;
4011 fti->records = talloc_array(fti,
4012 struct ForestTrustInfoRecordArmor, 2);
4013 if (!fti->records) {
4014 return NT_STATUS_NO_MEMORY;
4018 rec = &fti->records[0].record;
4022 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
4024 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
4025 if (!rec->data.name.string) {
4026 return NT_STATUS_NO_MEMORY;
4028 rec->data.name.size = strlen(rec->data.name.string);
4031 rec = &fti->records[1].record;
4035 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
4037 info = &rec->data.info;
4039 info->sid = *ps->domain_sid;
4040 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
4041 if (!info->dns_name.string) {
4042 return NT_STATUS_NO_MEMORY;
4044 info->dns_name.size = strlen(info->dns_name.string);
4045 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
4046 if (!info->netbios_name.string) {
4047 return NT_STATUS_NO_MEMORY;
4049 info->netbios_name.size = strlen(info->netbios_name.string);
4051 return NT_STATUS_OK;
4054 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
4055 struct lsa_ForestTrustInformation *lfti,
4056 struct ForestTrustInfo *fti)
4058 struct lsa_ForestTrustRecord *lrec;
4059 struct ForestTrustInfoRecord *rec;
4060 struct lsa_StringLarge *tln;
4061 struct lsa_ForestTrustDomainInfo *info;
4065 fti->count = lfti->count;
4066 fti->records = talloc_array(mem_ctx,
4067 struct ForestTrustInfoRecordArmor,
4069 if (!fti->records) {
4070 return NT_STATUS_NO_MEMORY;
4072 for (i = 0; i < fti->count; i++) {
4073 lrec = lfti->entries[i];
4074 rec = &fti->records[i].record;
4076 rec->flags = lrec->flags;
4077 rec->timestamp = lrec->time;
4078 rec->type = lrec->type;
4080 switch (lrec->type) {
4081 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4082 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4083 tln = &lrec->forest_trust_data.top_level_name;
4084 rec->data.name.string =
4085 talloc_strdup(mem_ctx, tln->string);
4086 if (!rec->data.name.string) {
4087 return NT_STATUS_NO_MEMORY;
4089 rec->data.name.size = strlen(rec->data.name.string);
4091 case LSA_FOREST_TRUST_DOMAIN_INFO:
4092 info = &lrec->forest_trust_data.domain_info;
4093 rec->data.info.sid = *info->domain_sid;
4094 rec->data.info.dns_name.string =
4095 talloc_strdup(mem_ctx,
4096 info->dns_domain_name.string);
4097 if (!rec->data.info.dns_name.string) {
4098 return NT_STATUS_NO_MEMORY;
4100 rec->data.info.dns_name.size =
4101 strlen(rec->data.info.dns_name.string);
4102 rec->data.info.netbios_name.string =
4103 talloc_strdup(mem_ctx,
4104 info->netbios_domain_name.string);
4105 if (!rec->data.info.netbios_name.string) {
4106 return NT_STATUS_NO_MEMORY;
4108 rec->data.info.netbios_name.size =
4109 strlen(rec->data.info.netbios_name.string);
4112 return NT_STATUS_INVALID_DOMAIN_STATE;
4116 return NT_STATUS_OK;
4119 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4120 uint32_t idx, uint32_t collision_type,
4121 uint32_t conflict_type, const char *tdo_name);
4123 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4124 const char *tdo_name,
4125 struct ForestTrustInfo *tdo_fti,
4126 struct ForestTrustInfo *new_fti,
4127 struct lsa_ForestTrustCollisionInfo *c_info)
4129 struct ForestTrustInfoRecord *nrec;
4130 struct ForestTrustInfoRecord *trec;
4131 const char *dns_name;
4132 const char *nb_name;
4133 struct dom_sid *sid;
4137 NTSTATUS nt_status = NT_STATUS_OK;
4138 uint32_t new_fti_idx;
4140 /* use always TDO type, until we understand when Xref can be used */
4141 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4149 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4151 nrec = &new_fti->records[new_fti_idx].record;
4153 tln_conflict = false;
4154 sid_conflict = false;
4155 nb_conflict = false;
4158 switch (nrec->type) {
4159 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4160 /* exclusions do not conflict by definition */
4163 case FOREST_TRUST_TOP_LEVEL_NAME:
4164 dns_name = nrec->data.name.string;
4165 dns_len = nrec->data.name.size;
4168 case LSA_FOREST_TRUST_DOMAIN_INFO:
4169 dns_name = nrec->data.info.dns_name.string;
4170 dns_len = nrec->data.info.dns_name.size;
4171 nb_name = nrec->data.info.netbios_name.string;
4172 sid = &nrec->data.info.sid;
4176 if (!dns_name) continue;
4178 /* check if this is already taken and not excluded */
4179 for (i = 0; i < tdo_fti->count; i++) {
4180 trec = &tdo_fti->records[i].record;
4182 switch (trec->type) {
4183 case FOREST_TRUST_TOP_LEVEL_NAME:
4185 tname = trec->data.name.string;
4186 tlen = trec->data.name.size;
4188 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4190 tname = trec->data.name.string;
4191 tlen = trec->data.name.size;
4193 case FOREST_TRUST_DOMAIN_INFO:
4195 tname = trec->data.info.dns_name.string;
4196 tlen = trec->data.info.dns_name.size;
4198 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4201 /* if it matches exclusion,
4202 * it doesn't conflict */
4208 case DNS_CMP_FIRST_IS_CHILD:
4209 case DNS_CMP_SECOND_IS_CHILD:
4210 tln_conflict = true;
4216 /* explicit exclusion, no dns name conflict here */
4218 tln_conflict = false;
4221 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4225 /* also test for domain info */
4226 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4227 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4228 sid_conflict = true;
4230 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4231 strcasecmp_m(trec->data.info.netbios_name.string,
4238 nt_status = add_collision(c_info, new_fti_idx,
4240 LSA_TLN_DISABLED_CONFLICT,
4242 if (!NT_STATUS_IS_OK(nt_status)) {
4247 nt_status = add_collision(c_info, new_fti_idx,
4249 LSA_SID_DISABLED_CONFLICT,
4251 if (!NT_STATUS_IS_OK(nt_status)) {
4256 nt_status = add_collision(c_info, new_fti_idx,
4258 LSA_NB_DISABLED_CONFLICT,
4260 if (!NT_STATUS_IS_OK(nt_status)) {
4270 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4271 uint32_t idx, uint32_t collision_type,
4272 uint32_t conflict_type, const char *tdo_name)
4274 struct lsa_ForestTrustCollisionRecord **es;
4275 uint32_t i = c_info->count;
4277 es = talloc_realloc(c_info, c_info->entries,
4278 struct lsa_ForestTrustCollisionRecord *, i + 1);
4280 return NT_STATUS_NO_MEMORY;
4282 c_info->entries = es;
4283 c_info->count = i + 1;
4285 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4287 return NT_STATUS_NO_MEMORY;
4291 es[i]->type = collision_type;
4292 es[i]->flags.flags = conflict_type;
4293 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4294 if (!es[i]->name.string) {
4295 return NT_STATUS_NO_MEMORY;
4297 es[i]->name.size = strlen(es[i]->name.string);
4299 return NT_STATUS_OK;
4303 lsa_lsaRSetForestTrustInformation
4305 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4306 TALLOC_CTX *mem_ctx,
4307 struct lsa_lsaRSetForestTrustInformation *r)
4309 struct dcesrv_handle *h;
4310 struct lsa_policy_state *p_state;
4311 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4312 "msDS-TrustForestTrustInfo", NULL };
4313 struct ldb_message **dom_res = NULL;
4314 struct ldb_dn *tdo_dn;
4315 struct ldb_message *msg;
4317 const char *td_name;
4318 uint32_t trust_attributes;
4319 struct lsa_ForestTrustCollisionInfo *c_info;
4320 struct ForestTrustInfo *nfti;
4321 struct ForestTrustInfo *fti;
4323 enum ndr_err_code ndr_err;
4328 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4332 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4333 return NT_STATUS_INVALID_DOMAIN_STATE;
4336 /* abort if we are not a PDC */
4337 if (!samdb_is_pdc(p_state->sam_ldb)) {
4338 return NT_STATUS_INVALID_DOMAIN_ROLE;
4341 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4342 if (ret == LDB_SUCCESS && am_rodc) {
4343 return NT_STATUS_NO_SUCH_DOMAIN;
4346 /* check caller has TRUSTED_SET_AUTH */
4348 /* fetch all trusted domain objects */
4349 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4351 &dom_res, trust_attrs,
4352 "(objectclass=trustedDomain)");
4354 return NT_STATUS_NO_SUCH_DOMAIN;
4357 for (i = 0; i < num_res; i++) {
4358 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4359 "trustPartner", NULL);
4361 return NT_STATUS_INVALID_DOMAIN_STATE;
4363 if (strcasecmp_m(td_name,
4364 r->in.trusted_domain_name->string) == 0) {
4369 return NT_STATUS_NO_SUCH_DOMAIN;
4372 tdo_dn = dom_res[i]->dn;
4374 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4375 "trustAttributes", 0);
4376 if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4377 return NT_STATUS_INVALID_PARAMETER;
4380 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4381 return NT_STATUS_INVALID_PARAMETER;
4384 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4386 return NT_STATUS_NO_MEMORY;
4389 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4390 if (!NT_STATUS_IS_OK(nt_status)) {
4394 c_info = talloc_zero(r->out.collision_info,
4395 struct lsa_ForestTrustCollisionInfo);
4397 return NT_STATUS_NO_MEMORY;
4400 /* first check own info, then other domains */
4401 fti = talloc(mem_ctx, struct ForestTrustInfo);
4403 return NT_STATUS_NO_MEMORY;
4406 nt_status = own_ft_info(p_state, fti);
4407 if (!NT_STATUS_IS_OK(nt_status)) {
4411 nt_status = check_ft_info(c_info, p_state->domain_dns,
4413 if (!NT_STATUS_IS_OK(nt_status)) {
4417 for (i = 0; i < num_res; i++) {
4418 fti = talloc(mem_ctx, struct ForestTrustInfo);
4420 return NT_STATUS_NO_MEMORY;
4423 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4424 if (!NT_STATUS_IS_OK(nt_status)) {
4425 if (NT_STATUS_EQUAL(nt_status,
4426 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4432 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4433 "trustPartner", NULL);
4435 return NT_STATUS_INVALID_DOMAIN_STATE;
4438 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4439 if (!NT_STATUS_IS_OK(nt_status)) {
4444 *r->out.collision_info = c_info;
4446 if (r->in.check_only != 0) {
4447 return NT_STATUS_OK;
4450 /* not just a check, write info back */
4452 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4453 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4454 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4455 return NT_STATUS_INVALID_PARAMETER;
4458 msg = ldb_msg_new(mem_ctx);
4460 return NT_STATUS_NO_MEMORY;
4463 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4465 return NT_STATUS_NO_MEMORY;
4468 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4469 LDB_FLAG_MOD_REPLACE, NULL);
4470 if (ret != LDB_SUCCESS) {
4471 return NT_STATUS_NO_MEMORY;
4473 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4475 if (ret != LDB_SUCCESS) {
4476 return NT_STATUS_NO_MEMORY;
4479 ret = ldb_modify(p_state->sam_ldb, msg);
4480 if (ret != LDB_SUCCESS) {
4481 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4482 ldb_errstring(p_state->sam_ldb)));
4485 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4486 return NT_STATUS_ACCESS_DENIED;
4488 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4492 return NT_STATUS_OK;
4498 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4499 struct lsa_CREDRRENAME *r)
4501 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4507 lsa_LSAROPENPOLICYSCE
4509 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4510 struct lsa_LSAROPENPOLICYSCE *r)
4512 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4517 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4519 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4520 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4522 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4527 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4529 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4530 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4532 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4537 lsa_LSARADTREPORTSECURITYEVENT
4539 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4540 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4542 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4546 /* include the generated boilerplate */
4547 #include "librpc/gen_ndr/ndr_lsa_s.c"
4551 /*****************************************
4552 NOTE! The remaining calls below were
4553 removed in w2k3, so the DCESRV_FAULT()
4554 replies are the correct implementation. Do
4555 not try and fill these in with anything else
4556 ******************************************/
4559 dssetup_DsRoleDnsNameToFlatName
4561 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4562 struct dssetup_DsRoleDnsNameToFlatName *r)
4564 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4569 dssetup_DsRoleDcAsDc
4571 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4572 struct dssetup_DsRoleDcAsDc *r)
4574 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4579 dssetup_DsRoleDcAsReplica
4581 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4582 struct dssetup_DsRoleDcAsReplica *r)
4584 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4589 dssetup_DsRoleDemoteDc
4591 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4592 struct dssetup_DsRoleDemoteDc *r)
4594 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4599 dssetup_DsRoleGetDcOperationProgress
4601 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4602 struct dssetup_DsRoleGetDcOperationProgress *r)
4604 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4609 dssetup_DsRoleGetDcOperationResults
4611 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4612 struct dssetup_DsRoleGetDcOperationResults *r)
4614 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4619 dssetup_DsRoleCancel
4621 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4622 struct dssetup_DsRoleCancel *r)
4624 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4629 dssetup_DsRoleServerSaveStateForUpgrade
4631 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4632 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4634 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4639 dssetup_DsRoleUpgradeDownlevelServer
4641 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4642 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4644 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4649 dssetup_DsRoleAbortDownlevelServerUpgrade
4651 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4652 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4654 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4658 /* include the generated boilerplate */
4659 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4661 NTSTATUS dcerpc_server_lsa_init(void)
4665 ret = dcerpc_server_dssetup_init();
4666 if (!NT_STATUS_IS_OK(ret)) {
4669 ret = dcerpc_server_lsarpc_init();
4670 if (!NT_STATUS_IS_OK(ret)) {