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 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid, tmp_ctx);
92 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
93 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid_str, tmp_ctx);
95 sidstr = dom_sid_string(tmp_ctx, sid);
96 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, tmp_ctx);
98 *sd = security_descriptor_dacl_create(mem_ctx,
102 SEC_ACE_TYPE_ACCESS_ALLOWED,
103 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
105 SID_BUILTIN_ADMINISTRATORS,
106 SEC_ACE_TYPE_ACCESS_ALLOWED,
109 SID_BUILTIN_ACCOUNT_OPERATORS,
110 SEC_ACE_TYPE_ACCESS_ALLOWED,
113 domain_admins_sid_str,
114 SEC_ACE_TYPE_ACCESS_ALLOWED,
118 SEC_ACE_TYPE_ACCESS_ALLOWED,
122 talloc_free(tmp_ctx);
124 NT_STATUS_HAVE_NO_MEMORY(*sd);
130 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
132 struct lsa_EnumAccountRights *r);
134 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
136 struct lsa_policy_state *state,
139 const struct lsa_RightSet *rights);
144 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
147 enum dcerpc_transport_t transport = dce_call->conn->endpoint->ep_description->transport;
148 struct dcesrv_handle *h;
150 if (transport != NCACN_NP && transport != NCALRPC) {
151 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
154 *r->out.handle = *r->in.handle;
156 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
160 ZERO_STRUCTP(r->out.handle);
169 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
170 struct lsa_Delete *r)
172 return NT_STATUS_NOT_SUPPORTED;
179 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
180 struct lsa_DeleteObject *r)
182 struct dcesrv_handle *h;
185 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
187 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
188 struct lsa_secret_state *secret_state = h->data;
190 /* Ensure user is permitted to delete this... */
191 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
193 case SECURITY_SYSTEM:
194 case SECURITY_ADMINISTRATOR:
197 /* Users and anonymous are not allowed to delete things */
198 return NT_STATUS_ACCESS_DENIED;
201 ret = ldb_delete(secret_state->sam_ldb,
202 secret_state->secret_dn);
203 if (ret != LDB_SUCCESS) {
204 return NT_STATUS_INVALID_HANDLE;
207 ZERO_STRUCTP(r->out.handle);
211 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
212 struct lsa_trusted_domain_state *trusted_domain_state =
213 talloc_get_type(h->data, struct lsa_trusted_domain_state);
214 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
215 if (ret != LDB_SUCCESS) {
216 return NT_STATUS_INTERNAL_DB_CORRUPTION;
219 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
220 trusted_domain_state->trusted_domain_dn);
221 if (ret != LDB_SUCCESS) {
222 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
223 return NT_STATUS_INVALID_HANDLE;
226 if (trusted_domain_state->trusted_domain_user_dn) {
227 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
228 trusted_domain_state->trusted_domain_user_dn);
229 if (ret != LDB_SUCCESS) {
230 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
231 return NT_STATUS_INVALID_HANDLE;
235 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
236 if (ret != LDB_SUCCESS) {
237 return NT_STATUS_INTERNAL_DB_CORRUPTION;
240 ZERO_STRUCTP(r->out.handle);
244 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
245 struct lsa_RightSet *rights;
246 struct lsa_account_state *astate;
247 struct lsa_EnumAccountRights r2;
250 rights = talloc(mem_ctx, struct lsa_RightSet);
252 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
256 r2.in.handle = &astate->policy->handle->wire_handle;
257 r2.in.sid = astate->account_sid;
258 r2.out.rights = rights;
260 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
261 but we have a LSA_HANDLE_ACCOUNT here, so this call
263 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
264 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
268 if (!NT_STATUS_IS_OK(status)) {
272 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
273 LDB_FLAG_MOD_DELETE, astate->account_sid,
275 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
279 if (!NT_STATUS_IS_OK(status)) {
283 ZERO_STRUCTP(r->out.handle);
288 return NT_STATUS_INVALID_HANDLE;
295 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
296 struct lsa_EnumPrivs *r)
298 struct dcesrv_handle *h;
300 enum sec_privilege priv;
301 const char *privname;
303 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
305 i = *r->in.resume_handle;
307 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
308 r->out.privs->count < r->in.max_count) {
309 struct lsa_PrivEntry *e;
310 privname = sec_privilege_name(priv);
311 r->out.privs->privs = talloc_realloc(r->out.privs,
313 struct lsa_PrivEntry,
314 r->out.privs->count+1);
315 if (r->out.privs->privs == NULL) {
316 return NT_STATUS_NO_MEMORY;
318 e = &r->out.privs->privs[r->out.privs->count];
321 e->name.string = privname;
322 r->out.privs->count++;
326 *r->out.resume_handle = i;
335 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
336 struct lsa_QuerySecurity *r)
338 struct dcesrv_handle *h;
339 struct security_descriptor *sd;
343 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
345 sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
347 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
348 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
349 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
350 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid,
351 LSA_ACCOUNT_ALL_ACCESS);
353 return NT_STATUS_INVALID_HANDLE;
355 NT_STATUS_NOT_OK_RETURN(status);
357 (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
358 NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
360 (*r->out.sdbuf)->sd = sd;
369 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
370 struct lsa_SetSecObj *r)
372 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
379 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
380 struct lsa_ChangePassword *r)
382 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
386 dssetup_DsRoleGetPrimaryDomainInformation
388 This is not an LSA call, but is the only call left on the DSSETUP
389 pipe (after the pipe was truncated), and needs lsa_get_policy_state
391 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
393 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
395 union dssetup_DsRoleInfo *info;
397 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
398 W_ERROR_HAVE_NO_MEMORY(info);
400 switch (r->in.level) {
401 case DS_ROLE_BASIC_INFORMATION:
403 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
405 const char *domain = NULL;
406 const char *dns_domain = NULL;
407 const char *forest = NULL;
408 struct GUID domain_guid;
409 struct lsa_policy_state *state;
411 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
412 if (!NT_STATUS_IS_OK(status)) {
413 return ntstatus_to_werror(status);
416 ZERO_STRUCT(domain_guid);
418 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
419 case ROLE_STANDALONE:
420 role = DS_ROLE_STANDALONE_SERVER;
422 case ROLE_DOMAIN_MEMBER:
423 role = DS_ROLE_MEMBER_SERVER;
425 case ROLE_ACTIVE_DIRECTORY_DC:
426 if (samdb_is_pdc(state->sam_ldb)) {
427 role = DS_ROLE_PRIMARY_DC;
429 role = DS_ROLE_BACKUP_DC;
434 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
435 case ROLE_STANDALONE:
436 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
437 W_ERROR_HAVE_NO_MEMORY(domain);
439 case ROLE_DOMAIN_MEMBER:
440 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
441 W_ERROR_HAVE_NO_MEMORY(domain);
442 /* TODO: what is with dns_domain and forest and guid? */
444 case ROLE_ACTIVE_DIRECTORY_DC:
445 flags = DS_ROLE_PRIMARY_DS_RUNNING;
447 if (state->mixed_domain == 1) {
448 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
451 domain = state->domain_name;
452 dns_domain = state->domain_dns;
453 forest = state->forest_dns;
455 domain_guid = state->domain_guid;
456 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
460 info->basic.role = role;
461 info->basic.flags = flags;
462 info->basic.domain = domain;
463 info->basic.dns_domain = dns_domain;
464 info->basic.forest = forest;
465 info->basic.domain_guid = domain_guid;
470 case DS_ROLE_UPGRADE_STATUS:
472 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
473 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
478 case DS_ROLE_OP_STATUS:
480 info->opstatus.status = DS_ROLE_OP_IDLE;
486 return WERR_INVALID_PARAM;
491 fill in the AccountDomain info
493 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
494 struct lsa_DomainInfo *info)
496 info->name.string = state->domain_name;
497 info->sid = state->domain_sid;
503 fill in the DNS domain info
505 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
506 struct lsa_DnsDomainInfo *info)
508 info->name.string = state->domain_name;
509 info->sid = state->domain_sid;
510 info->dns_domain.string = state->domain_dns;
511 info->dns_forest.string = state->forest_dns;
512 info->domain_guid = state->domain_guid;
520 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
521 struct lsa_QueryInfoPolicy2 *r)
523 struct lsa_policy_state *state;
524 struct dcesrv_handle *h;
525 union lsa_PolicyInformation *info;
529 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
533 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
535 return NT_STATUS_NO_MEMORY;
539 switch (r->in.level) {
540 case LSA_POLICY_INFO_AUDIT_LOG:
541 /* we don't need to fill in any of this */
542 ZERO_STRUCT(info->audit_log);
544 case LSA_POLICY_INFO_AUDIT_EVENTS:
545 /* we don't need to fill in any of this */
546 ZERO_STRUCT(info->audit_events);
548 case LSA_POLICY_INFO_PD:
549 /* we don't need to fill in any of this */
550 ZERO_STRUCT(info->pd);
553 case LSA_POLICY_INFO_DOMAIN:
554 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
555 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
556 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
557 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
558 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
560 case LSA_POLICY_INFO_ROLE:
561 info->role.role = LSA_ROLE_PRIMARY;
564 case LSA_POLICY_INFO_DNS:
565 case LSA_POLICY_INFO_DNS_INT:
566 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
568 case LSA_POLICY_INFO_REPLICA:
569 ZERO_STRUCT(info->replica);
572 case LSA_POLICY_INFO_QUOTA:
573 ZERO_STRUCT(info->quota);
576 case LSA_POLICY_INFO_MOD:
577 case LSA_POLICY_INFO_AUDIT_FULL_SET:
578 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
579 /* windows gives INVALID_PARAMETER */
581 return NT_STATUS_INVALID_PARAMETER;
585 return NT_STATUS_INVALID_INFO_CLASS;
591 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
592 struct lsa_QueryInfoPolicy *r)
594 struct lsa_QueryInfoPolicy2 r2;
599 r2.in.handle = r->in.handle;
600 r2.in.level = r->in.level;
601 r2.out.info = r->out.info;
603 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
611 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
612 struct lsa_SetInfoPolicy *r)
614 /* need to support this */
615 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
622 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
623 struct lsa_ClearAuditLog *r)
625 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
632 This call does not seem to have any long-term effects, hence no database operations
634 we need to talk to the MS product group to find out what this account database means!
636 answer is that the lsa database is totally separate from the SAM and
637 ldap databases. We are going to need a separate ldb to store these
638 accounts. The SIDs on this account bear no relation to the SIDs in
641 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
642 struct lsa_CreateAccount *r)
644 struct lsa_account_state *astate;
646 struct lsa_policy_state *state;
647 struct dcesrv_handle *h, *ah;
649 ZERO_STRUCTP(r->out.acct_handle);
651 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
655 astate = talloc(dce_call->conn, struct lsa_account_state);
656 if (astate == NULL) {
657 return NT_STATUS_NO_MEMORY;
660 astate->account_sid = dom_sid_dup(astate, r->in.sid);
661 if (astate->account_sid == NULL) {
663 return NT_STATUS_NO_MEMORY;
666 astate->policy = talloc_reference(astate, state);
667 astate->access_mask = r->in.access_mask;
669 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
672 return NT_STATUS_NO_MEMORY;
675 ah->data = talloc_steal(ah, astate);
677 *r->out.acct_handle = ah->wire_handle;
686 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
687 struct lsa_EnumAccounts *r)
689 struct dcesrv_handle *h;
690 struct lsa_policy_state *state;
692 struct ldb_message **res;
693 const char * const attrs[] = { "objectSid", NULL};
696 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
700 /* NOTE: This call must only return accounts that have at least
703 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
704 "(&(objectSid=*)(privilege=*))");
706 return NT_STATUS_INTERNAL_DB_CORRUPTION;
709 if (*r->in.resume_handle >= ret) {
710 return NT_STATUS_NO_MORE_ENTRIES;
713 count = ret - *r->in.resume_handle;
714 if (count > r->in.num_entries) {
715 count = r->in.num_entries;
719 return NT_STATUS_NO_MORE_ENTRIES;
722 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
723 if (r->out.sids->sids == NULL) {
724 return NT_STATUS_NO_MEMORY;
727 for (i=0;i<count;i++) {
728 r->out.sids->sids[i].sid =
729 samdb_result_dom_sid(r->out.sids->sids,
730 res[i + *r->in.resume_handle],
732 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
735 r->out.sids->num_sids = count;
736 *r->out.resume_handle = count + *r->in.resume_handle;
741 /* This decrypts and returns Trusted Domain Auth Information Internal data */
742 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
743 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
744 struct trustDomainPasswords *auth_struct)
746 DATA_BLOB session_key = data_blob(NULL, 0);
747 enum ndr_err_code ndr_err;
750 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
751 if (!NT_STATUS_IS_OK(nt_status)) {
755 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
756 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
758 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
759 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
760 return NT_STATUS_INVALID_PARAMETER;
766 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
768 struct trustAuthInOutBlob *iopw,
769 DATA_BLOB *trustauth_blob)
771 enum ndr_err_code ndr_err;
773 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
775 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
776 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
777 return NT_STATUS_INVALID_PARAMETER;
783 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
784 struct ldb_context *sam_ldb,
785 struct ldb_dn *base_dn,
786 const char *netbios_name,
787 struct trustAuthInOutBlob *in,
788 struct ldb_dn **user_dn)
790 struct ldb_message *msg;
795 dn = ldb_dn_copy(mem_ctx, base_dn);
797 return NT_STATUS_NO_MEMORY;
799 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
800 return NT_STATUS_NO_MEMORY;
803 msg = ldb_msg_new(mem_ctx);
805 return NT_STATUS_NO_MEMORY;
809 ret = ldb_msg_add_string(msg, "objectClass", "user");
810 if (ret != LDB_SUCCESS) {
811 return NT_STATUS_NO_MEMORY;
814 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
815 if (ret != LDB_SUCCESS) {
816 return NT_STATUS_NO_MEMORY;
819 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
820 UF_INTERDOMAIN_TRUST_ACCOUNT);
821 if (ret != LDB_SUCCESS) {
822 return NT_STATUS_NO_MEMORY;
825 for (i = 0; i < in->count; i++) {
826 const char *attribute;
828 switch (in->current.array[i].AuthType) {
829 case TRUST_AUTH_TYPE_NT4OWF:
830 attribute = "unicodePwd";
831 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
834 case TRUST_AUTH_TYPE_CLEAR:
835 attribute = "clearTextPassword";
836 v.data = in->current.array[i].AuthInfo.clear.password;
837 v.length = in->current.array[i].AuthInfo.clear.size;
843 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
844 if (ret != LDB_SUCCESS) {
845 return NT_STATUS_NO_MEMORY;
849 /* create the trusted_domain user account */
850 ret = ldb_add(sam_ldb, msg);
851 if (ret != LDB_SUCCESS) {
852 DEBUG(0,("Failed to create user record %s: %s\n",
853 ldb_dn_get_linearized(msg->dn),
854 ldb_errstring(sam_ldb)));
857 case LDB_ERR_ENTRY_ALREADY_EXISTS:
858 return NT_STATUS_DOMAIN_EXISTS;
859 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
860 return NT_STATUS_ACCESS_DENIED;
862 return NT_STATUS_INTERNAL_DB_CORRUPTION;
873 lsa_CreateTrustedDomainEx2
875 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
877 struct lsa_CreateTrustedDomainEx2 *r,
879 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
881 struct dcesrv_handle *policy_handle;
882 struct lsa_policy_state *policy_state;
883 struct lsa_trusted_domain_state *trusted_domain_state;
884 struct dcesrv_handle *handle;
885 struct ldb_message **msgs, *msg;
886 const char *attrs[] = {
889 const char *netbios_name;
890 const char *dns_name;
892 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
893 struct trustDomainPasswords auth_struct;
896 struct ldb_context *sam_ldb;
898 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
899 ZERO_STRUCTP(r->out.trustdom_handle);
901 policy_state = policy_handle->data;
902 sam_ldb = policy_state->sam_ldb;
904 netbios_name = r->in.info->netbios_name.string;
906 return NT_STATUS_INVALID_PARAMETER;
909 dns_name = r->in.info->domain_name.string;
911 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
912 if (!trusted_domain_state) {
913 return NT_STATUS_NO_MEMORY;
915 trusted_domain_state->policy = policy_state;
917 if (strcasecmp(netbios_name, "BUILTIN") == 0
918 || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
919 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
920 return NT_STATUS_INVALID_PARAMETER;
923 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
924 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
925 || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
926 || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
927 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
928 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
931 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
932 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
933 /* No secrets are created at this time, for this function */
934 auth_struct.outgoing.count = 0;
935 auth_struct.incoming.count = 0;
936 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
937 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
938 r->in.auth_info_internal->auth_blob.size);
939 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
940 &auth_blob, &auth_struct);
941 if (!NT_STATUS_IS_OK(nt_status)) {
944 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
946 if (unencrypted_auth_info->incoming_count > 1) {
947 return NT_STATUS_INVALID_PARAMETER;
950 /* more investigation required here, do not create secrets for
952 auth_struct.outgoing.count = 0;
953 auth_struct.incoming.count = 0;
955 return NT_STATUS_INVALID_PARAMETER;
958 if (auth_struct.incoming.count) {
959 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
960 &auth_struct.incoming,
962 if (!NT_STATUS_IS_OK(nt_status)) {
966 trustAuthIncoming = data_blob(NULL, 0);
969 if (auth_struct.outgoing.count) {
970 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
971 &auth_struct.outgoing,
973 if (!NT_STATUS_IS_OK(nt_status)) {
977 trustAuthOutgoing = data_blob(NULL, 0);
980 ret = ldb_transaction_start(sam_ldb);
981 if (ret != LDB_SUCCESS) {
982 return NT_STATUS_INTERNAL_DB_CORRUPTION;
986 char *dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
987 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
988 /* search for the trusted_domain record */
989 ret = gendb_search(sam_ldb,
990 mem_ctx, policy_state->system_dn, &msgs, attrs,
991 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
992 dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
994 ldb_transaction_cancel(sam_ldb);
995 return NT_STATUS_OBJECT_NAME_COLLISION;
998 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
999 /* search for the trusted_domain record */
1000 ret = gendb_search(sam_ldb,
1001 mem_ctx, policy_state->system_dn, &msgs, attrs,
1002 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1003 netbios_encoded, netbios_encoded, netbios_encoded);
1005 ldb_transaction_cancel(sam_ldb);
1006 return NT_STATUS_OBJECT_NAME_COLLISION;
1011 ldb_transaction_cancel(sam_ldb);
1012 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1015 name = dns_name ? dns_name : netbios_name;
1017 msg = ldb_msg_new(mem_ctx);
1019 return NT_STATUS_NO_MEMORY;
1022 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1023 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1024 ldb_transaction_cancel(sam_ldb);
1025 return NT_STATUS_NO_MEMORY;
1028 ldb_msg_add_string(msg, "flatname", netbios_name);
1030 if (r->in.info->sid) {
1031 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1032 if (ret != LDB_SUCCESS) {
1033 ldb_transaction_cancel(sam_ldb);
1034 return NT_STATUS_INVALID_PARAMETER;
1038 ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1040 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1042 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1044 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1047 ldb_msg_add_string(msg, "trustPartner", dns_name);
1050 if (trustAuthIncoming.data) {
1051 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1052 if (ret != LDB_SUCCESS) {
1053 ldb_transaction_cancel(sam_ldb);
1054 return NT_STATUS_NO_MEMORY;
1057 if (trustAuthOutgoing.data) {
1058 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1059 if (ret != LDB_SUCCESS) {
1060 ldb_transaction_cancel(sam_ldb);
1061 return NT_STATUS_NO_MEMORY;
1065 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1067 /* create the trusted_domain */
1068 ret = ldb_add(sam_ldb, msg);
1072 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1073 ldb_transaction_cancel(sam_ldb);
1074 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1075 ldb_dn_get_linearized(msg->dn),
1076 ldb_errstring(sam_ldb)));
1077 return NT_STATUS_DOMAIN_EXISTS;
1078 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1079 ldb_transaction_cancel(sam_ldb);
1080 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1081 ldb_dn_get_linearized(msg->dn),
1082 ldb_errstring(sam_ldb)));
1083 return NT_STATUS_ACCESS_DENIED;
1085 ldb_transaction_cancel(sam_ldb);
1086 DEBUG(0,("Failed to create user record %s: %s\n",
1087 ldb_dn_get_linearized(msg->dn),
1088 ldb_errstring(sam_ldb)));
1089 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1092 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1093 struct ldb_dn *user_dn;
1094 /* Inbound trusts must also create a cn=users object to match */
1095 nt_status = add_trust_user(mem_ctx, sam_ldb,
1096 policy_state->domain_dn,
1098 &auth_struct.incoming,
1100 if (!NT_STATUS_IS_OK(nt_status)) {
1101 ldb_transaction_cancel(sam_ldb);
1105 /* save the trust user dn */
1106 trusted_domain_state->trusted_domain_user_dn
1107 = talloc_steal(trusted_domain_state, user_dn);
1110 ret = ldb_transaction_commit(sam_ldb);
1111 if (ret != LDB_SUCCESS) {
1112 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1115 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1117 return NT_STATUS_NO_MEMORY;
1120 handle->data = talloc_steal(handle, trusted_domain_state);
1122 trusted_domain_state->access_mask = r->in.access_mask;
1123 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1125 *r->out.trustdom_handle = handle->wire_handle;
1127 return NT_STATUS_OK;
1131 lsa_CreateTrustedDomainEx2
1133 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1134 TALLOC_CTX *mem_ctx,
1135 struct lsa_CreateTrustedDomainEx2 *r)
1137 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1140 lsa_CreateTrustedDomainEx
1142 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1143 TALLOC_CTX *mem_ctx,
1144 struct lsa_CreateTrustedDomainEx *r)
1146 struct lsa_CreateTrustedDomainEx2 r2;
1148 r2.in.policy_handle = r->in.policy_handle;
1149 r2.in.info = r->in.info;
1150 r2.out.trustdom_handle = r->out.trustdom_handle;
1151 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1155 lsa_CreateTrustedDomain
1157 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1158 struct lsa_CreateTrustedDomain *r)
1160 struct lsa_CreateTrustedDomainEx2 r2;
1162 r2.in.policy_handle = r->in.policy_handle;
1163 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1165 return NT_STATUS_NO_MEMORY;
1168 r2.in.info->domain_name.string = NULL;
1169 r2.in.info->netbios_name = r->in.info->name;
1170 r2.in.info->sid = r->in.info->sid;
1171 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1172 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1173 r2.in.info->trust_attributes = 0;
1175 r2.in.access_mask = r->in.access_mask;
1176 r2.out.trustdom_handle = r->out.trustdom_handle;
1178 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1182 lsa_OpenTrustedDomain
1184 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1185 struct lsa_OpenTrustedDomain *r)
1187 struct dcesrv_handle *policy_handle;
1189 struct lsa_policy_state *policy_state;
1190 struct lsa_trusted_domain_state *trusted_domain_state;
1191 struct dcesrv_handle *handle;
1192 struct ldb_message **msgs;
1193 const char *attrs[] = {
1199 const char *sid_string;
1202 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1203 ZERO_STRUCTP(r->out.trustdom_handle);
1204 policy_state = policy_handle->data;
1206 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1207 if (!trusted_domain_state) {
1208 return NT_STATUS_NO_MEMORY;
1210 trusted_domain_state->policy = policy_state;
1212 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1214 return NT_STATUS_NO_MEMORY;
1217 /* search for the trusted_domain record */
1218 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1219 mem_ctx, policy_state->system_dn, &msgs, attrs,
1220 "(&(securityIdentifier=%s)(objectclass=trustedDomain))",
1223 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1227 DEBUG(0,("Found %d records matching DN %s\n", ret,
1228 ldb_dn_get_linearized(policy_state->system_dn)));
1229 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1232 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1234 trusted_domain_state->trusted_domain_user_dn = NULL;
1236 if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1237 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1238 /* search for the trusted_domain record */
1239 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1240 mem_ctx, policy_state->domain_dn, &msgs, attrs,
1241 "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%u))",
1242 flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1244 trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1247 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1249 return NT_STATUS_NO_MEMORY;
1252 handle->data = talloc_steal(handle, trusted_domain_state);
1254 trusted_domain_state->access_mask = r->in.access_mask;
1255 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1257 *r->out.trustdom_handle = handle->wire_handle;
1259 return NT_STATUS_OK;
1264 lsa_OpenTrustedDomainByName
1266 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1267 TALLOC_CTX *mem_ctx,
1268 struct lsa_OpenTrustedDomainByName *r)
1270 struct dcesrv_handle *policy_handle;
1272 struct lsa_policy_state *policy_state;
1273 struct lsa_trusted_domain_state *trusted_domain_state;
1274 struct dcesrv_handle *handle;
1275 struct ldb_message **msgs;
1276 const char *attrs[] = {
1282 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1283 ZERO_STRUCTP(r->out.trustdom_handle);
1284 policy_state = policy_handle->data;
1286 if (!r->in.name.string) {
1287 return NT_STATUS_INVALID_PARAMETER;
1290 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1291 if (!trusted_domain_state) {
1292 return NT_STATUS_NO_MEMORY;
1294 trusted_domain_state->policy = policy_state;
1296 /* search for the trusted_domain record */
1297 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1298 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1299 mem_ctx, policy_state->system_dn, &msgs, attrs,
1300 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1301 "(objectclass=trustedDomain))",
1302 td_name, td_name, td_name);
1304 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1308 DEBUG(0,("Found %d records matching DN %s\n", ret,
1309 ldb_dn_get_linearized(policy_state->system_dn)));
1310 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1313 /* TODO: perform access checks */
1315 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1317 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1319 return NT_STATUS_NO_MEMORY;
1322 handle->data = talloc_steal(handle, trusted_domain_state);
1324 trusted_domain_state->access_mask = r->in.access_mask;
1325 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1327 *r->out.trustdom_handle = handle->wire_handle;
1329 return NT_STATUS_OK;
1335 lsa_SetTrustedDomainInfo
1337 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1338 struct lsa_SetTrustedDomainInfo *r)
1340 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1345 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1346 * otherwise at least one must be provided */
1347 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1348 struct ldb_dn *basedn, const char *dns_domain,
1349 const char *netbios, struct dom_sid2 *sid,
1350 struct ldb_message ***msgs)
1352 const char *attrs[] = { "flatname", "trustPartner",
1353 "securityIdentifier", "trustDirection",
1354 "trustType", "trustAttributes",
1356 "msDs-supportedEncryptionTypes", NULL };
1359 char *sidstr = NULL;
1364 if (dns_domain || netbios || sid) {
1365 filter = talloc_strdup(mem_ctx,
1366 "(&(objectclass=trustedDomain)(|");
1368 filter = talloc_strdup(mem_ctx,
1369 "(objectclass=trustedDomain)");
1372 return NT_STATUS_NO_MEMORY;
1376 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1378 return NT_STATUS_NO_MEMORY;
1380 filter = talloc_asprintf_append(filter,
1381 "(trustPartner=%s)", dns);
1383 return NT_STATUS_NO_MEMORY;
1387 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1389 return NT_STATUS_NO_MEMORY;
1391 filter = talloc_asprintf_append(filter,
1392 "(flatname=%s)", nbn);
1394 return NT_STATUS_NO_MEMORY;
1398 sidstr = dom_sid_string(mem_ctx, sid);
1400 return NT_STATUS_INVALID_PARAMETER;
1402 filter = talloc_asprintf_append(filter,
1403 "(securityIdentifier=%s)",
1406 return NT_STATUS_NO_MEMORY;
1409 if (dns_domain || netbios || sid) {
1410 filter = talloc_asprintf_append(filter, "))");
1412 return NT_STATUS_NO_MEMORY;
1416 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1418 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1422 return NT_STATUS_OBJECT_NAME_COLLISION;
1425 return NT_STATUS_OK;
1428 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1429 struct ldb_context *sam_ldb,
1430 struct ldb_message *orig,
1431 struct ldb_message *dest,
1432 const char *attribute,
1434 uint32_t *orig_value)
1436 const struct ldb_val *orig_val;
1437 uint32_t orig_uint = 0;
1438 unsigned int flags = 0;
1441 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1442 if (!orig_val || !orig_val->data) {
1443 /* add new attribute */
1444 flags = LDB_FLAG_MOD_ADD;
1448 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1449 if (errno != 0 || orig_uint != value) {
1450 /* replace also if can't get value */
1451 flags = LDB_FLAG_MOD_REPLACE;
1456 /* stored value is identical, nothing to change */
1460 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1461 if (ret != LDB_SUCCESS) {
1462 return NT_STATUS_NO_MEMORY;
1465 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1466 if (ret != LDB_SUCCESS) {
1467 return NT_STATUS_NO_MEMORY;
1472 *orig_value = orig_uint;
1474 return NT_STATUS_OK;
1477 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1478 struct ldb_context *sam_ldb,
1479 struct ldb_dn *base_dn,
1481 const char *netbios_name,
1482 struct trustAuthInOutBlob *in)
1484 const char *attrs[] = { "userAccountControl", NULL };
1485 struct ldb_message **msgs;
1486 struct ldb_message *msg;
1491 ret = gendb_search(sam_ldb, mem_ctx,
1492 base_dn, &msgs, attrs,
1493 "samAccountName=%s$", netbios_name);
1495 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1500 return NT_STATUS_OK;
1503 /* ok no existing user, add it from scratch */
1504 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1505 netbios_name, in, NULL);
1508 /* check user is what we are looking for */
1509 uac = ldb_msg_find_attr_as_uint(msgs[0],
1510 "userAccountControl", 0);
1511 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1512 return NT_STATUS_OBJECT_NAME_COLLISION;
1516 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1519 return NT_STATUS_OK;
1520 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1521 return NT_STATUS_ACCESS_DENIED;
1523 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1527 /* entry exists, just modify secret if any */
1528 if (in == NULL || in->count == 0) {
1529 return NT_STATUS_OK;
1532 msg = ldb_msg_new(mem_ctx);
1534 return NT_STATUS_NO_MEMORY;
1536 msg->dn = msgs[0]->dn;
1538 for (i = 0; i < in->count; i++) {
1539 const char *attribute;
1541 switch (in->current.array[i].AuthType) {
1542 case TRUST_AUTH_TYPE_NT4OWF:
1543 attribute = "unicodePwd";
1544 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1547 case TRUST_AUTH_TYPE_CLEAR:
1548 attribute = "clearTextPassword";
1549 v.data = in->current.array[i].AuthInfo.clear.password;
1550 v.length = in->current.array[i].AuthInfo.clear.size;
1556 ret = ldb_msg_add_empty(msg, attribute,
1557 LDB_FLAG_MOD_REPLACE, NULL);
1558 if (ret != LDB_SUCCESS) {
1559 return NT_STATUS_NO_MEMORY;
1562 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1563 if (ret != LDB_SUCCESS) {
1564 return NT_STATUS_NO_MEMORY;
1568 /* create the trusted_domain user account */
1569 ret = ldb_modify(sam_ldb, msg);
1570 if (ret != LDB_SUCCESS) {
1571 DEBUG(0,("Failed to create user record %s: %s\n",
1572 ldb_dn_get_linearized(msg->dn),
1573 ldb_errstring(sam_ldb)));
1576 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1577 return NT_STATUS_DOMAIN_EXISTS;
1578 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1579 return NT_STATUS_ACCESS_DENIED;
1581 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1585 return NT_STATUS_OK;
1589 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1590 struct dcesrv_handle *p_handle,
1591 TALLOC_CTX *mem_ctx,
1592 struct ldb_message *dom_msg,
1593 enum lsa_TrustDomInfoEnum level,
1594 union lsa_TrustedDomainInfo *info)
1596 struct lsa_policy_state *p_state = p_handle->data;
1597 uint32_t *posix_offset = NULL;
1598 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1599 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1600 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1601 uint32_t *enc_types = NULL;
1602 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1603 struct trustDomainPasswords auth_struct;
1604 struct trustAuthInOutBlob *current_passwords = NULL;
1606 struct ldb_message **msgs;
1607 struct ldb_message *msg;
1608 bool add_outgoing = false;
1609 bool add_incoming = false;
1610 bool del_outgoing = false;
1611 bool del_incoming = false;
1612 bool in_transaction = false;
1617 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1618 posix_offset = &info->posix_offset.posix_offset;
1620 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1621 info_ex = &info->info_ex;
1623 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1624 auth_info = &info->auth_info;
1626 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1627 posix_offset = &info->full_info.posix_offset.posix_offset;
1628 info_ex = &info->full_info.info_ex;
1629 auth_info = &info->full_info.auth_info;
1631 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1632 auth_info_int = &info->auth_info_internal;
1634 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1635 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1636 info_ex = &info->full_info_internal.info_ex;
1637 auth_info_int = &info->full_info_internal.auth_info;
1639 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1640 enc_types = &info->enc_types.enc_types;
1643 return NT_STATUS_INVALID_PARAMETER;
1647 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1649 &trustAuthOutgoing);
1650 if (!NT_STATUS_IS_OK(nt_status)) {
1653 if (trustAuthIncoming.data) {
1654 /* This does the decode of some of this twice, but it is easier that way */
1655 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1656 auth_info->incoming_count,
1657 auth_info->incoming_current_auth_info,
1659 ¤t_passwords);
1660 if (!NT_STATUS_IS_OK(nt_status)) {
1666 /* decode auth_info_int if set */
1667 if (auth_info_int) {
1669 /* now decrypt blob */
1670 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1671 auth_info_int->auth_blob.size);
1673 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1674 &auth_blob, &auth_struct);
1675 if (!NT_STATUS_IS_OK(nt_status)) {
1681 /* verify data matches */
1682 if (info_ex->trust_attributes &
1683 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1684 /* TODO: check what behavior level we have */
1685 if (strcasecmp_m(p_state->domain_dns,
1686 p_state->forest_dns) != 0) {
1687 return NT_STATUS_INVALID_DOMAIN_STATE;
1691 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1692 if (ret == LDB_SUCCESS && am_rodc) {
1693 return NT_STATUS_NO_SUCH_DOMAIN;
1696 /* verify only one object matches the dns/netbios/sid
1697 * triplet and that this is the one we already have */
1698 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1700 info_ex->domain_name.string,
1701 info_ex->netbios_name.string,
1702 info_ex->sid, &msgs);
1703 if (!NT_STATUS_IS_OK(nt_status)) {
1706 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1707 return NT_STATUS_OBJECT_NAME_COLLISION;
1712 /* TODO: should we fetch previous values from the existing entry
1713 * and append them ? */
1714 if (auth_info_int && auth_struct.incoming.count) {
1715 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1716 &auth_struct.incoming,
1717 &trustAuthIncoming);
1718 if (!NT_STATUS_IS_OK(nt_status)) {
1722 current_passwords = &auth_struct.incoming;
1725 trustAuthIncoming = data_blob(NULL, 0);
1728 if (auth_info_int && auth_struct.outgoing.count) {
1729 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1730 &auth_struct.outgoing,
1731 &trustAuthOutgoing);
1732 if (!NT_STATUS_IS_OK(nt_status)) {
1736 trustAuthOutgoing = data_blob(NULL, 0);
1739 msg = ldb_msg_new(mem_ctx);
1741 return NT_STATUS_NO_MEMORY;
1743 msg->dn = dom_msg->dn;
1746 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1749 *posix_offset, NULL);
1750 if (!NT_STATUS_IS_OK(nt_status)) {
1760 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1763 info_ex->trust_direction,
1765 if (!NT_STATUS_IS_OK(nt_status)) {
1769 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1770 add_incoming = true;
1772 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1773 add_outgoing = true;
1776 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1777 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1778 del_incoming = true;
1780 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1781 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1782 del_outgoing = true;
1785 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1786 if (origtype == -1 || origtype != info_ex->trust_type) {
1787 DEBUG(1, ("Attempted to change trust type! "
1788 "Operation not handled\n"));
1789 return NT_STATUS_INVALID_PARAMETER;
1792 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1795 info_ex->trust_attributes,
1797 if (!NT_STATUS_IS_OK(nt_status)) {
1800 /* TODO: check forestFunctionality from ldb opaque */
1801 /* TODO: check what is set makes sense */
1802 /* for now refuse changes */
1803 if (origattrs == -1 ||
1804 origattrs != info_ex->trust_attributes) {
1805 DEBUG(1, ("Attempted to change trust attributes! "
1806 "Operation not handled\n"));
1807 return NT_STATUS_INVALID_PARAMETER;
1812 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1814 "msDS-SupportedEncryptionTypes",
1816 if (!NT_STATUS_IS_OK(nt_status)) {
1821 if (add_incoming && trustAuthIncoming.data) {
1822 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1823 LDB_FLAG_MOD_REPLACE, NULL);
1824 if (ret != LDB_SUCCESS) {
1825 return NT_STATUS_NO_MEMORY;
1827 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1828 &trustAuthIncoming, NULL);
1829 if (ret != LDB_SUCCESS) {
1830 return NT_STATUS_NO_MEMORY;
1833 if (add_outgoing && trustAuthOutgoing.data) {
1834 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1835 LDB_FLAG_MOD_REPLACE, NULL);
1836 if (ret != LDB_SUCCESS) {
1837 return NT_STATUS_NO_MEMORY;
1839 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1840 &trustAuthOutgoing, NULL);
1841 if (ret != LDB_SUCCESS) {
1842 return NT_STATUS_NO_MEMORY;
1846 /* start transaction */
1847 ret = ldb_transaction_start(p_state->sam_ldb);
1848 if (ret != LDB_SUCCESS) {
1849 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1851 in_transaction = true;
1853 if (msg->num_elements) {
1854 ret = ldb_modify(p_state->sam_ldb, msg);
1855 if (ret != LDB_SUCCESS) {
1856 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1857 ldb_dn_get_linearized(msg->dn),
1858 ldb_errstring(p_state->sam_ldb)));
1859 nt_status = dsdb_ldb_err_to_ntstatus(ret);
1864 if (add_incoming || del_incoming) {
1865 const char *netbios_name;
1867 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1869 if (!netbios_name) {
1870 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1874 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
1875 nt_status = update_trust_user(mem_ctx,
1881 if (!NT_STATUS_IS_OK(nt_status)) {
1886 /* ok, all fine, commit transaction and return */
1887 ret = ldb_transaction_commit(p_state->sam_ldb);
1888 if (ret != LDB_SUCCESS) {
1889 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1891 in_transaction = false;
1893 nt_status = NT_STATUS_OK;
1896 if (in_transaction) {
1897 ldb_transaction_cancel(p_state->sam_ldb);
1903 lsa_SetInfomrationTrustedDomain
1905 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1906 struct dcesrv_call_state *dce_call,
1907 TALLOC_CTX *mem_ctx,
1908 struct lsa_SetInformationTrustedDomain *r)
1910 struct dcesrv_handle *h;
1911 struct lsa_trusted_domain_state *td_state;
1912 struct ldb_message **msgs;
1915 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1916 LSA_HANDLE_TRUSTED_DOMAIN);
1918 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1920 /* get the trusted domain object */
1921 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1922 td_state->trusted_domain_dn,
1923 NULL, NULL, NULL, &msgs);
1924 if (!NT_STATUS_IS_OK(nt_status)) {
1925 if (NT_STATUS_EQUAL(nt_status,
1926 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1929 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1932 return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1933 msgs[0], r->in.level, r->in.info);
1938 lsa_DeleteTrustedDomain
1940 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1941 struct lsa_DeleteTrustedDomain *r)
1944 struct lsa_OpenTrustedDomain opn;
1945 struct lsa_DeleteObject del;
1946 struct dcesrv_handle *h;
1948 opn.in.handle = r->in.handle;
1949 opn.in.sid = r->in.dom_sid;
1950 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1951 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1952 if (!opn.out.trustdom_handle) {
1953 return NT_STATUS_NO_MEMORY;
1955 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1956 if (!NT_STATUS_IS_OK(status)) {
1960 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1961 talloc_steal(mem_ctx, h);
1963 del.in.handle = opn.out.trustdom_handle;
1964 del.out.handle = opn.out.trustdom_handle;
1965 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1966 if (!NT_STATUS_IS_OK(status)) {
1969 return NT_STATUS_OK;
1972 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
1973 struct ldb_message *msg,
1974 struct lsa_TrustDomainInfoInfoEx *info_ex)
1976 info_ex->domain_name.string
1977 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1978 info_ex->netbios_name.string
1979 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1981 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1982 info_ex->trust_direction
1983 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1985 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1986 info_ex->trust_attributes
1987 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
1988 return NT_STATUS_OK;
1992 lsa_QueryTrustedDomainInfo
1994 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1995 struct lsa_QueryTrustedDomainInfo *r)
1997 union lsa_TrustedDomainInfo *info = NULL;
1998 struct dcesrv_handle *h;
1999 struct lsa_trusted_domain_state *trusted_domain_state;
2000 struct ldb_message *msg;
2002 struct ldb_message **res;
2003 const char *attrs[] = {
2006 "securityIdentifier",
2010 "msDs-supportedEncryptionTypes",
2014 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2016 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2018 /* pull all the user attributes */
2019 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2020 trusted_domain_state->trusted_domain_dn, &res, attrs);
2022 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2026 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2028 return NT_STATUS_NO_MEMORY;
2030 *r->out.info = info;
2032 switch (r->in.level) {
2033 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2034 info->name.netbios_name.string
2035 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2037 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2038 info->posix_offset.posix_offset
2039 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2041 #if 0 /* Win2k3 doesn't implement this */
2042 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2043 r->out.info->info_basic.netbios_name.string
2044 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2045 r->out.info->info_basic.sid
2046 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2049 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2050 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2052 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2053 ZERO_STRUCT(info->full_info);
2054 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2055 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2056 ZERO_STRUCT(info->full_info2_internal);
2057 info->full_info2_internal.posix_offset.posix_offset
2058 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2059 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2061 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2062 info->enc_types.enc_types
2063 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2066 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2067 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2068 /* oops, we don't want to return the info after all */
2070 *r->out.info = NULL;
2071 return NT_STATUS_INVALID_PARAMETER;
2073 /* oops, we don't want to return the info after all */
2075 *r->out.info = NULL;
2076 return NT_STATUS_INVALID_INFO_CLASS;
2079 return NT_STATUS_OK;
2084 lsa_QueryTrustedDomainInfoBySid
2086 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2087 struct lsa_QueryTrustedDomainInfoBySid *r)
2090 struct lsa_OpenTrustedDomain opn;
2091 struct lsa_QueryTrustedDomainInfo query;
2092 struct dcesrv_handle *h;
2094 opn.in.handle = r->in.handle;
2095 opn.in.sid = r->in.dom_sid;
2096 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2097 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2098 if (!opn.out.trustdom_handle) {
2099 return NT_STATUS_NO_MEMORY;
2101 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2102 if (!NT_STATUS_IS_OK(status)) {
2106 /* Ensure this handle goes away at the end of this call */
2107 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2108 talloc_steal(mem_ctx, h);
2110 query.in.trustdom_handle = opn.out.trustdom_handle;
2111 query.in.level = r->in.level;
2112 query.out.info = r->out.info;
2113 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2114 if (!NT_STATUS_IS_OK(status)) {
2118 return NT_STATUS_OK;
2122 lsa_SetTrustedDomainInfoByName
2124 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2125 TALLOC_CTX *mem_ctx,
2126 struct lsa_SetTrustedDomainInfoByName *r)
2128 struct dcesrv_handle *policy_handle;
2129 struct lsa_policy_state *policy_state;
2130 struct ldb_message **msgs;
2133 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2134 policy_state = policy_handle->data;
2136 /* get the trusted domain object */
2137 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2138 policy_state->domain_dn,
2139 r->in.trusted_domain->string,
2140 r->in.trusted_domain->string,
2142 if (!NT_STATUS_IS_OK(nt_status)) {
2143 if (NT_STATUS_EQUAL(nt_status,
2144 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2147 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2150 return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2151 msgs[0], r->in.level, r->in.info);
2155 lsa_QueryTrustedDomainInfoByName
2157 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2158 TALLOC_CTX *mem_ctx,
2159 struct lsa_QueryTrustedDomainInfoByName *r)
2162 struct lsa_OpenTrustedDomainByName opn;
2163 struct lsa_QueryTrustedDomainInfo query;
2164 struct dcesrv_handle *h;
2166 opn.in.handle = r->in.handle;
2167 opn.in.name = *r->in.trusted_domain;
2168 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2169 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2170 if (!opn.out.trustdom_handle) {
2171 return NT_STATUS_NO_MEMORY;
2173 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2174 if (!NT_STATUS_IS_OK(status)) {
2178 /* Ensure this handle goes away at the end of this call */
2179 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2180 talloc_steal(mem_ctx, h);
2182 query.in.trustdom_handle = opn.out.trustdom_handle;
2183 query.in.level = r->in.level;
2184 query.out.info = r->out.info;
2185 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2186 if (!NT_STATUS_IS_OK(status)) {
2190 return NT_STATUS_OK;
2194 lsa_CloseTrustedDomainEx
2196 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2197 TALLOC_CTX *mem_ctx,
2198 struct lsa_CloseTrustedDomainEx *r)
2200 /* The result of a bad hair day from an IDL programmer? Not
2201 * implmented in Win2k3. You should always just lsa_Close
2203 return NT_STATUS_NOT_IMPLEMENTED;
2208 comparison function for sorting lsa_DomainInformation array
2210 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2212 return strcasecmp_m(e1->name.string, e2->name.string);
2218 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2219 struct lsa_EnumTrustDom *r)
2221 struct dcesrv_handle *policy_handle;
2222 struct lsa_DomainInfo *entries;
2223 struct lsa_policy_state *policy_state;
2224 struct ldb_message **domains;
2225 const char *attrs[] = {
2227 "securityIdentifier",
2234 *r->out.resume_handle = 0;
2236 r->out.domains->domains = NULL;
2237 r->out.domains->count = 0;
2239 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2241 policy_state = policy_handle->data;
2243 /* search for all users in this domain. This could possibly be cached and
2244 resumed based on resume_key */
2245 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2246 "objectclass=trustedDomain");
2248 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2251 /* convert to lsa_TrustInformation format */
2252 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2254 return NT_STATUS_NO_MEMORY;
2256 for (i=0;i<count;i++) {
2257 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2258 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2261 /* sort the results by name */
2262 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2264 if (*r->in.resume_handle >= count) {
2265 *r->out.resume_handle = -1;
2267 return NT_STATUS_NO_MORE_ENTRIES;
2270 /* return the rest, limit by max_size. Note that we
2271 use the w2k3 element size value of 60 */
2272 r->out.domains->count = count - *r->in.resume_handle;
2273 r->out.domains->count = MIN(r->out.domains->count,
2274 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2276 r->out.domains->domains = entries + *r->in.resume_handle;
2277 r->out.domains->count = r->out.domains->count;
2279 if (r->out.domains->count < count - *r->in.resume_handle) {
2280 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2281 return STATUS_MORE_ENTRIES;
2284 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2285 * always be larger than the previous input resume handle, in
2286 * particular when hitting the last query it is vital to set the
2287 * resume handle correctly to avoid infinite client loops, as
2288 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2289 * status is NT_STATUS_OK - gd */
2291 *r->out.resume_handle = (uint32_t)-1;
2293 return NT_STATUS_OK;
2297 comparison function for sorting lsa_DomainInformation array
2299 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2301 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2305 lsa_EnumTrustedDomainsEx
2307 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2308 struct lsa_EnumTrustedDomainsEx *r)
2310 struct dcesrv_handle *policy_handle;
2311 struct lsa_TrustDomainInfoInfoEx *entries;
2312 struct lsa_policy_state *policy_state;
2313 struct ldb_message **domains;
2314 const char *attrs[] = {
2317 "securityIdentifier",
2327 *r->out.resume_handle = 0;
2329 r->out.domains->domains = NULL;
2330 r->out.domains->count = 0;
2332 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2334 policy_state = policy_handle->data;
2336 /* search for all users in this domain. This could possibly be cached and
2337 resumed based on resume_key */
2338 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2339 "objectclass=trustedDomain");
2341 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2344 /* convert to lsa_DomainInformation format */
2345 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2347 return NT_STATUS_NO_MEMORY;
2349 for (i=0;i<count;i++) {
2350 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2351 if (!NT_STATUS_IS_OK(nt_status)) {
2356 /* sort the results by name */
2357 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2359 if (*r->in.resume_handle >= count) {
2360 *r->out.resume_handle = -1;
2362 return NT_STATUS_NO_MORE_ENTRIES;
2365 /* return the rest, limit by max_size. Note that we
2366 use the w2k3 element size value of 60 */
2367 r->out.domains->count = count - *r->in.resume_handle;
2368 r->out.domains->count = MIN(r->out.domains->count,
2369 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2371 r->out.domains->domains = entries + *r->in.resume_handle;
2372 r->out.domains->count = r->out.domains->count;
2374 if (r->out.domains->count < count - *r->in.resume_handle) {
2375 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2376 return STATUS_MORE_ENTRIES;
2379 return NT_STATUS_OK;
2386 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2387 struct lsa_OpenAccount *r)
2389 struct dcesrv_handle *h, *ah;
2390 struct lsa_policy_state *state;
2391 struct lsa_account_state *astate;
2393 ZERO_STRUCTP(r->out.acct_handle);
2395 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2399 astate = talloc(dce_call->conn, struct lsa_account_state);
2400 if (astate == NULL) {
2401 return NT_STATUS_NO_MEMORY;
2404 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2405 if (astate->account_sid == NULL) {
2406 talloc_free(astate);
2407 return NT_STATUS_NO_MEMORY;
2410 astate->policy = talloc_reference(astate, state);
2411 astate->access_mask = r->in.access_mask;
2413 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2415 talloc_free(astate);
2416 return NT_STATUS_NO_MEMORY;
2419 ah->data = talloc_steal(ah, astate);
2421 *r->out.acct_handle = ah->wire_handle;
2423 return NT_STATUS_OK;
2428 lsa_EnumPrivsAccount
2430 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2431 TALLOC_CTX *mem_ctx,
2432 struct lsa_EnumPrivsAccount *r)
2434 struct dcesrv_handle *h;
2435 struct lsa_account_state *astate;
2438 struct ldb_message **res;
2439 const char * const attrs[] = { "privilege", NULL};
2440 struct ldb_message_element *el;
2442 struct lsa_PrivilegeSet *privs;
2444 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2448 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2449 if (privs == NULL) {
2450 return NT_STATUS_NO_MEMORY;
2456 *r->out.privs = privs;
2458 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2459 if (sidstr == NULL) {
2460 return NT_STATUS_NO_MEMORY;
2463 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2464 "objectSid=%s", sidstr);
2466 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2469 return NT_STATUS_OK;
2472 el = ldb_msg_find_element(res[0], "privilege");
2473 if (el == NULL || el->num_values == 0) {
2474 return NT_STATUS_OK;
2477 privs->set = talloc_array(privs,
2478 struct lsa_LUIDAttribute, el->num_values);
2479 if (privs->set == NULL) {
2480 return NT_STATUS_NO_MEMORY;
2484 for (i=0;i<el->num_values;i++) {
2485 int id = sec_privilege_id((const char *)el->values[i].data);
2486 if (id == SEC_PRIV_INVALID) {
2487 /* Perhaps an account right, not a privilege */
2490 privs->set[j].attribute = 0;
2491 privs->set[j].luid.low = id;
2492 privs->set[j].luid.high = 0;
2498 return NT_STATUS_OK;
2502 lsa_EnumAccountRights
2504 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2505 TALLOC_CTX *mem_ctx,
2506 struct lsa_EnumAccountRights *r)
2508 struct dcesrv_handle *h;
2509 struct lsa_policy_state *state;
2512 struct ldb_message **res;
2513 const char * const attrs[] = { "privilege", NULL};
2515 struct ldb_message_element *el;
2517 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2521 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2522 if (sidstr == NULL) {
2523 return NT_STATUS_NO_MEMORY;
2526 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2527 "(&(objectSid=%s)(privilege=*))", sidstr);
2529 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2532 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2533 dom_sid_string(mem_ctx, r->in.sid),
2534 ldb_errstring(state->pdb)));
2535 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2538 el = ldb_msg_find_element(res[0], "privilege");
2539 if (el == NULL || el->num_values == 0) {
2540 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2543 r->out.rights->count = el->num_values;
2544 r->out.rights->names = talloc_array(r->out.rights,
2545 struct lsa_StringLarge, r->out.rights->count);
2546 if (r->out.rights->names == NULL) {
2547 return NT_STATUS_NO_MEMORY;
2550 for (i=0;i<el->num_values;i++) {
2551 r->out.rights->names[i].string = (const char *)el->values[i].data;
2554 return NT_STATUS_OK;
2560 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2562 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2563 TALLOC_CTX *mem_ctx,
2564 struct lsa_policy_state *state,
2566 struct dom_sid *sid,
2567 const struct lsa_RightSet *rights)
2569 const char *sidstr, *sidndrstr;
2570 struct ldb_message *msg;
2571 struct ldb_message_element *el;
2574 struct lsa_EnumAccountRights r2;
2577 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2578 SECURITY_ADMINISTRATOR) {
2579 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2580 return NT_STATUS_ACCESS_DENIED;
2583 msg = ldb_msg_new(mem_ctx);
2585 return NT_STATUS_NO_MEMORY;
2588 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2589 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
2591 sidstr = dom_sid_string(msg, sid);
2592 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
2594 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2595 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
2597 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2598 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
2600 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2603 r2.in.handle = &state->handle->wire_handle;
2605 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2607 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2608 if (!NT_STATUS_IS_OK(status)) {
2609 ZERO_STRUCTP(r2.out.rights);
2613 for (i=0;i<rights->count;i++) {
2614 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2615 if (sec_right_bit(rights->names[i].string) == 0) {
2617 return NT_STATUS_NO_SUCH_PRIVILEGE;
2621 return NT_STATUS_NO_SUCH_PRIVILEGE;
2624 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2626 for (j=0;j<r2.out.rights->count;j++) {
2627 if (strcasecmp_m(r2.out.rights->names[j].string,
2628 rights->names[i].string) == 0) {
2632 if (j != r2.out.rights->count) continue;
2635 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2636 if (ret != LDB_SUCCESS) {
2638 return NT_STATUS_NO_MEMORY;
2642 el = ldb_msg_find_element(msg, "privilege");
2645 return NT_STATUS_OK;
2648 el->flags = ldb_flag;
2650 ret = ldb_modify(state->pdb, msg);
2651 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2652 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2654 return NT_STATUS_NO_MEMORY;
2656 ldb_msg_add_string(msg, "comment", "added via LSA");
2657 ret = ldb_add(state->pdb, msg);
2659 if (ret != LDB_SUCCESS) {
2660 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2662 return NT_STATUS_OK;
2664 DEBUG(3, ("Could not %s attributes from %s: %s",
2665 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2666 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2668 return NT_STATUS_UNEXPECTED_IO_ERROR;
2672 return NT_STATUS_OK;
2676 lsa_AddPrivilegesToAccount
2678 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2679 struct lsa_AddPrivilegesToAccount *r)
2681 struct lsa_RightSet rights;
2682 struct dcesrv_handle *h;
2683 struct lsa_account_state *astate;
2686 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2690 rights.count = r->in.privs->count;
2691 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2692 if (rights.names == NULL) {
2693 return NT_STATUS_NO_MEMORY;
2695 for (i=0;i<rights.count;i++) {
2696 int id = r->in.privs->set[i].luid.low;
2697 if (r->in.privs->set[i].luid.high) {
2698 return NT_STATUS_NO_SUCH_PRIVILEGE;
2700 rights.names[i].string = sec_privilege_name(id);
2701 if (rights.names[i].string == NULL) {
2702 return NT_STATUS_NO_SUCH_PRIVILEGE;
2706 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2707 LDB_FLAG_MOD_ADD, astate->account_sid,
2713 lsa_RemovePrivilegesFromAccount
2715 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2716 struct lsa_RemovePrivilegesFromAccount *r)
2718 struct lsa_RightSet *rights;
2719 struct dcesrv_handle *h;
2720 struct lsa_account_state *astate;
2723 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2727 rights = talloc(mem_ctx, struct lsa_RightSet);
2729 if (r->in.remove_all == 1 &&
2730 r->in.privs == NULL) {
2731 struct lsa_EnumAccountRights r2;
2734 r2.in.handle = &astate->policy->handle->wire_handle;
2735 r2.in.sid = astate->account_sid;
2736 r2.out.rights = rights;
2738 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2739 if (!NT_STATUS_IS_OK(status)) {
2743 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2744 LDB_FLAG_MOD_DELETE, astate->account_sid,
2748 if (r->in.remove_all != 0) {
2749 return NT_STATUS_INVALID_PARAMETER;
2752 rights->count = r->in.privs->count;
2753 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2754 if (rights->names == NULL) {
2755 return NT_STATUS_NO_MEMORY;
2757 for (i=0;i<rights->count;i++) {
2758 int id = r->in.privs->set[i].luid.low;
2759 if (r->in.privs->set[i].luid.high) {
2760 return NT_STATUS_NO_SUCH_PRIVILEGE;
2762 rights->names[i].string = sec_privilege_name(id);
2763 if (rights->names[i].string == NULL) {
2764 return NT_STATUS_NO_SUCH_PRIVILEGE;
2768 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2769 LDB_FLAG_MOD_DELETE, astate->account_sid,
2775 lsa_GetQuotasForAccount
2777 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2778 struct lsa_GetQuotasForAccount *r)
2780 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2785 lsa_SetQuotasForAccount
2787 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2788 struct lsa_SetQuotasForAccount *r)
2790 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2795 lsa_GetSystemAccessAccount
2797 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2798 struct lsa_GetSystemAccessAccount *r)
2800 struct dcesrv_handle *h;
2801 struct lsa_account_state *astate;
2804 struct ldb_message **res;
2805 const char * const attrs[] = { "privilege", NULL};
2806 struct ldb_message_element *el;
2809 *(r->out.access_mask) = 0x00000000;
2811 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2815 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2816 if (sidstr == NULL) {
2817 return NT_STATUS_NO_MEMORY;
2820 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2821 "objectSid=%s", sidstr);
2823 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2826 return NT_STATUS_OK;
2829 el = ldb_msg_find_element(res[0], "privilege");
2830 if (el == NULL || el->num_values == 0) {
2831 return NT_STATUS_OK;
2834 for (i=0;i<el->num_values;i++) {
2835 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2836 if (right_bit == 0) {
2837 /* Perhaps an privilege, not a right */
2840 *(r->out.access_mask) |= right_bit;
2843 return NT_STATUS_OK;
2848 lsa_SetSystemAccessAccount
2850 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2851 struct lsa_SetSystemAccessAccount *r)
2853 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2860 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2861 struct lsa_CreateSecret *r)
2863 struct dcesrv_handle *policy_handle;
2864 struct lsa_policy_state *policy_state;
2865 struct lsa_secret_state *secret_state;
2866 struct dcesrv_handle *handle;
2867 struct ldb_message **msgs, *msg;
2868 const char *attrs[] = {
2876 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2877 ZERO_STRUCTP(r->out.sec_handle);
2879 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2881 case SECURITY_SYSTEM:
2882 case SECURITY_ADMINISTRATOR:
2885 /* Users and annonymous are not allowed create secrets */
2886 return NT_STATUS_ACCESS_DENIED;
2889 policy_state = policy_handle->data;
2891 if (!r->in.name.string) {
2892 return NT_STATUS_INVALID_PARAMETER;
2895 secret_state = talloc(mem_ctx, struct lsa_secret_state);
2896 NT_STATUS_HAVE_NO_MEMORY(secret_state);
2897 secret_state->policy = policy_state;
2899 msg = ldb_msg_new(mem_ctx);
2901 return NT_STATUS_NO_MEMORY;
2904 if (strncmp("G$", r->in.name.string, 2) == 0) {
2907 secret_state->global = true;
2909 name = &r->in.name.string[2];
2910 if (strlen(name) == 0) {
2911 return NT_STATUS_INVALID_PARAMETER;
2914 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2915 ldb_binary_encode_string(mem_ctx, name));
2916 NT_STATUS_HAVE_NO_MEMORY(name2);
2918 /* We need to connect to the database as system, as this is one
2919 * of the rare RPC calls that must read the secrets (and this
2920 * is denied otherwise) */
2921 secret_state->sam_ldb = talloc_reference(secret_state,
2922 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));
2923 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2925 /* search for the secret record */
2926 ret = gendb_search(secret_state->sam_ldb,
2927 mem_ctx, policy_state->system_dn, &msgs, attrs,
2928 "(&(cn=%s)(objectclass=secret))",
2931 return NT_STATUS_OBJECT_NAME_COLLISION;
2935 DEBUG(0,("Failure searching for CN=%s: %s\n",
2936 name2, ldb_errstring(secret_state->sam_ldb)));
2937 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2940 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2941 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2942 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2943 return NT_STATUS_NO_MEMORY;
2946 ret = ldb_msg_add_string(msg, "cn", name2);
2947 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2949 secret_state->global = false;
2951 name = r->in.name.string;
2952 if (strlen(name) == 0) {
2953 return NT_STATUS_INVALID_PARAMETER;
2956 secret_state->sam_ldb = talloc_reference(secret_state,
2957 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
2958 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2960 /* search for the secret record */
2961 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2962 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2964 "(&(cn=%s)(objectclass=secret))",
2965 ldb_binary_encode_string(mem_ctx, name));
2967 return NT_STATUS_OBJECT_NAME_COLLISION;
2971 DEBUG(0,("Failure searching for CN=%s: %s\n",
2972 name, ldb_errstring(secret_state->sam_ldb)));
2973 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2976 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
2977 "cn=%s,cn=LSA Secrets", name);
2978 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2979 ret = ldb_msg_add_string(msg, "cn", name);
2980 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2983 ret = ldb_msg_add_string(msg, "objectClass", "secret");
2984 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2986 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2987 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
2989 /* create the secret */
2990 ret = ldb_add(secret_state->sam_ldb, msg);
2991 if (ret != LDB_SUCCESS) {
2992 DEBUG(0,("Failed to create secret record %s: %s\n",
2993 ldb_dn_get_linearized(msg->dn),
2994 ldb_errstring(secret_state->sam_ldb)));
2995 return NT_STATUS_ACCESS_DENIED;
2998 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2999 NT_STATUS_HAVE_NO_MEMORY(handle);
3001 handle->data = talloc_steal(handle, secret_state);
3003 secret_state->access_mask = r->in.access_mask;
3004 secret_state->policy = talloc_reference(secret_state, policy_state);
3005 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3007 *r->out.sec_handle = handle->wire_handle;
3009 return NT_STATUS_OK;
3016 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3017 struct lsa_OpenSecret *r)
3019 struct dcesrv_handle *policy_handle;
3021 struct lsa_policy_state *policy_state;
3022 struct lsa_secret_state *secret_state;
3023 struct dcesrv_handle *handle;
3024 struct ldb_message **msgs;
3025 const char *attrs[] = {
3033 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3034 ZERO_STRUCTP(r->out.sec_handle);
3035 policy_state = policy_handle->data;
3037 if (!r->in.name.string) {
3038 return NT_STATUS_INVALID_PARAMETER;
3041 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3043 case SECURITY_SYSTEM:
3044 case SECURITY_ADMINISTRATOR:
3047 /* Users and annonymous are not allowed to access secrets */
3048 return NT_STATUS_ACCESS_DENIED;
3051 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3052 if (!secret_state) {
3053 return NT_STATUS_NO_MEMORY;
3055 secret_state->policy = policy_state;
3057 if (strncmp("G$", r->in.name.string, 2) == 0) {
3058 name = &r->in.name.string[2];
3059 /* 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) */
3060 secret_state->sam_ldb = talloc_reference(secret_state,
3061 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));
3062 secret_state->global = true;
3064 if (strlen(name) < 1) {
3065 return NT_STATUS_INVALID_PARAMETER;
3068 /* search for the secret record */
3069 ret = gendb_search(secret_state->sam_ldb,
3070 mem_ctx, policy_state->system_dn, &msgs, attrs,
3071 "(&(cn=%s Secret)(objectclass=secret))",
3072 ldb_binary_encode_string(mem_ctx, name));
3074 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3078 DEBUG(0,("Found %d records matching DN %s\n", ret,
3079 ldb_dn_get_linearized(policy_state->system_dn)));
3080 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3083 secret_state->global = false;
3084 secret_state->sam_ldb = talloc_reference(secret_state,
3085 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3087 name = r->in.name.string;
3088 if (strlen(name) < 1) {
3089 return NT_STATUS_INVALID_PARAMETER;
3092 /* search for the secret record */
3093 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3094 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3096 "(&(cn=%s)(objectclass=secret))",
3097 ldb_binary_encode_string(mem_ctx, name));
3099 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3103 DEBUG(0,("Found %d records matching CN=%s\n",
3104 ret, ldb_binary_encode_string(mem_ctx, name)));
3105 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3109 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3111 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3113 return NT_STATUS_NO_MEMORY;
3116 handle->data = talloc_steal(handle, secret_state);
3118 secret_state->access_mask = r->in.access_mask;
3119 secret_state->policy = talloc_reference(secret_state, policy_state);
3121 *r->out.sec_handle = handle->wire_handle;
3123 return NT_STATUS_OK;
3130 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3131 struct lsa_SetSecret *r)
3134 struct dcesrv_handle *h;
3135 struct lsa_secret_state *secret_state;
3136 struct ldb_message *msg;
3137 DATA_BLOB session_key;
3138 DATA_BLOB crypt_secret, secret;
3141 NTSTATUS status = NT_STATUS_OK;
3143 struct timeval now = timeval_current();
3144 NTTIME nt_now = timeval_to_nttime(&now);
3146 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3148 secret_state = h->data;
3150 msg = ldb_msg_new(mem_ctx);
3152 return NT_STATUS_NO_MEMORY;
3155 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3157 return NT_STATUS_NO_MEMORY;
3159 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3160 if (!NT_STATUS_IS_OK(status)) {
3164 if (r->in.old_val) {
3166 crypt_secret.data = r->in.old_val->data;
3167 crypt_secret.length = r->in.old_val->size;
3169 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3170 if (!NT_STATUS_IS_OK(status)) {
3174 val.data = secret.data;
3175 val.length = secret.length;
3178 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3179 return NT_STATUS_NO_MEMORY;
3182 /* set old value mtime */
3183 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3184 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3185 return NT_STATUS_NO_MEMORY;
3189 /* If the old value is not set, then migrate the
3190 * current value to the old value */
3191 const struct ldb_val *old_val;
3192 NTTIME last_set_time;
3193 struct ldb_message **res;
3194 const char *attrs[] = {
3200 /* search for the secret record */
3201 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3202 secret_state->secret_dn, &res, attrs);
3204 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3208 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3209 ldb_dn_get_linearized(secret_state->secret_dn)));
3210 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3213 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3214 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3218 if (ldb_msg_add_value(msg, "priorValue",
3219 old_val, NULL) != LDB_SUCCESS) {
3220 return NT_STATUS_NO_MEMORY;
3223 if (samdb_msg_add_delete(secret_state->sam_ldb,
3224 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3225 return NT_STATUS_NO_MEMORY;
3229 /* set old value mtime */
3230 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3231 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3232 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3233 return NT_STATUS_NO_MEMORY;
3236 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3237 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3238 return NT_STATUS_NO_MEMORY;
3243 if (r->in.new_val) {
3245 crypt_secret.data = r->in.new_val->data;
3246 crypt_secret.length = r->in.new_val->size;
3248 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3249 if (!NT_STATUS_IS_OK(status)) {
3253 val.data = secret.data;
3254 val.length = secret.length;
3257 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3258 return NT_STATUS_NO_MEMORY;
3261 /* set new value mtime */
3262 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3263 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3264 return NT_STATUS_NO_MEMORY;
3267 /* NULL out the NEW value */
3268 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3269 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3270 return NT_STATUS_NO_MEMORY;
3272 if (samdb_msg_add_delete(secret_state->sam_ldb,
3273 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3274 return NT_STATUS_NO_MEMORY;
3278 /* modify the samdb record */
3279 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3280 if (ret != LDB_SUCCESS) {
3281 return dsdb_ldb_err_to_ntstatus(ret);
3284 return NT_STATUS_OK;
3291 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3292 struct lsa_QuerySecret *r)
3294 struct dcesrv_handle *h;
3295 struct lsa_secret_state *secret_state;
3296 struct ldb_message *msg;
3297 DATA_BLOB session_key;
3298 DATA_BLOB crypt_secret, secret;
3300 struct ldb_message **res;
3301 const char *attrs[] = {
3311 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3313 /* Ensure user is permitted to read this... */
3314 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3316 case SECURITY_SYSTEM:
3317 case SECURITY_ADMINISTRATOR:
3320 /* Users and annonymous are not allowed to read secrets */
3321 return NT_STATUS_ACCESS_DENIED;
3324 secret_state = h->data;
3326 /* pull all the user attributes */
3327 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3328 secret_state->secret_dn, &res, attrs);
3330 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3334 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3335 if (!NT_STATUS_IS_OK(nt_status)) {
3339 if (r->in.old_val) {
3340 const struct ldb_val *prior_val;
3341 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3342 if (!r->out.old_val) {
3343 return NT_STATUS_NO_MEMORY;
3345 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
3347 if (prior_val && prior_val->length) {
3348 secret.data = prior_val->data;
3349 secret.length = prior_val->length;
3352 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3353 if (!crypt_secret.length) {
3354 return NT_STATUS_NO_MEMORY;
3356 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3357 if (!r->out.old_val->buf) {
3358 return NT_STATUS_NO_MEMORY;
3360 r->out.old_val->buf->size = crypt_secret.length;
3361 r->out.old_val->buf->length = crypt_secret.length;
3362 r->out.old_val->buf->data = crypt_secret.data;
3366 if (r->in.old_mtime) {
3367 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3368 if (!r->out.old_mtime) {
3369 return NT_STATUS_NO_MEMORY;
3371 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
3374 if (r->in.new_val) {
3375 const struct ldb_val *new_val;
3376 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3377 if (!r->out.new_val) {
3378 return NT_STATUS_NO_MEMORY;
3381 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3383 if (new_val && new_val->length) {
3384 secret.data = new_val->data;
3385 secret.length = new_val->length;
3388 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3389 if (!crypt_secret.length) {
3390 return NT_STATUS_NO_MEMORY;
3392 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3393 if (!r->out.new_val->buf) {
3394 return NT_STATUS_NO_MEMORY;
3396 r->out.new_val->buf->length = crypt_secret.length;
3397 r->out.new_val->buf->size = crypt_secret.length;
3398 r->out.new_val->buf->data = crypt_secret.data;
3402 if (r->in.new_mtime) {
3403 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3404 if (!r->out.new_mtime) {
3405 return NT_STATUS_NO_MEMORY;
3407 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3410 return NT_STATUS_OK;
3417 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3418 TALLOC_CTX *mem_ctx,
3419 struct lsa_LookupPrivValue *r)
3421 struct dcesrv_handle *h;
3424 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3426 id = sec_privilege_id(r->in.name->string);
3427 if (id == SEC_PRIV_INVALID) {
3428 return NT_STATUS_NO_SUCH_PRIVILEGE;
3431 r->out.luid->low = id;
3432 r->out.luid->high = 0;
3434 return NT_STATUS_OK;
3441 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3442 TALLOC_CTX *mem_ctx,
3443 struct lsa_LookupPrivName *r)
3445 struct dcesrv_handle *h;
3446 struct lsa_StringLarge *name;
3447 const char *privname;
3449 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3451 if (r->in.luid->high != 0) {
3452 return NT_STATUS_NO_SUCH_PRIVILEGE;
3455 privname = sec_privilege_name(r->in.luid->low);
3456 if (privname == NULL) {
3457 return NT_STATUS_NO_SUCH_PRIVILEGE;
3460 name = talloc(mem_ctx, struct lsa_StringLarge);
3462 return NT_STATUS_NO_MEMORY;
3465 name->string = privname;
3467 *r->out.name = name;
3469 return NT_STATUS_OK;
3474 lsa_LookupPrivDisplayName
3476 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3477 TALLOC_CTX *mem_ctx,
3478 struct lsa_LookupPrivDisplayName *r)
3480 struct dcesrv_handle *h;
3481 struct lsa_StringLarge *disp_name = NULL;
3482 enum sec_privilege id;
3484 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3486 id = sec_privilege_id(r->in.name->string);
3487 if (id == SEC_PRIV_INVALID) {
3488 return NT_STATUS_NO_SUCH_PRIVILEGE;
3491 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3492 if (disp_name == NULL) {
3493 return NT_STATUS_NO_MEMORY;
3496 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3497 if (disp_name->string == NULL) {
3498 return NT_STATUS_INTERNAL_ERROR;
3501 *r->out.disp_name = disp_name;
3502 *r->out.returned_language_id = 0;
3504 return NT_STATUS_OK;
3509 lsa_EnumAccountsWithUserRight
3511 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3512 TALLOC_CTX *mem_ctx,
3513 struct lsa_EnumAccountsWithUserRight *r)
3515 struct dcesrv_handle *h;
3516 struct lsa_policy_state *state;
3518 struct ldb_message **res;
3519 const char * const attrs[] = { "objectSid", NULL};
3520 const char *privname;
3522 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3526 if (r->in.name == NULL) {
3527 return NT_STATUS_NO_SUCH_PRIVILEGE;
3530 privname = r->in.name->string;
3531 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3532 return NT_STATUS_NO_SUCH_PRIVILEGE;
3535 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3536 "privilege=%s", privname);
3538 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3541 return NT_STATUS_NO_MORE_ENTRIES;
3544 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3545 if (r->out.sids->sids == NULL) {
3546 return NT_STATUS_NO_MEMORY;
3548 for (i=0;i<ret;i++) {
3549 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3550 res[i], "objectSid");
3551 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3553 r->out.sids->num_sids = ret;
3555 return NT_STATUS_OK;
3560 lsa_AddAccountRights
3562 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3563 TALLOC_CTX *mem_ctx,
3564 struct lsa_AddAccountRights *r)
3566 struct dcesrv_handle *h;
3567 struct lsa_policy_state *state;
3569 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3573 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3575 r->in.sid, r->in.rights);
3580 lsa_RemoveAccountRights
3582 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3583 TALLOC_CTX *mem_ctx,
3584 struct lsa_RemoveAccountRights *r)
3586 struct dcesrv_handle *h;
3587 struct lsa_policy_state *state;
3589 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3593 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3594 LDB_FLAG_MOD_DELETE,
3595 r->in.sid, r->in.rights);
3600 lsa_StorePrivateData
3602 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3603 struct lsa_StorePrivateData *r)
3605 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3610 lsa_RetrievePrivateData
3612 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3613 struct lsa_RetrievePrivateData *r)
3615 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3622 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3623 struct lsa_GetUserName *r)
3625 enum dcerpc_transport_t transport = dce_call->conn->endpoint->ep_description->transport;
3626 NTSTATUS status = NT_STATUS_OK;
3627 const char *account_name;
3628 const char *authority_name;
3629 struct lsa_String *_account_name;
3630 struct lsa_String *_authority_name = NULL;
3632 if (transport != NCACN_NP && transport != NCALRPC) {
3633 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3636 /* this is what w2k3 does */
3637 r->out.account_name = r->in.account_name;
3638 r->out.authority_name = r->in.authority_name;
3640 if (r->in.account_name
3641 && *r->in.account_name
3642 /* && *(*r->in.account_name)->string */
3644 return NT_STATUS_INVALID_PARAMETER;
3647 if (r->in.authority_name
3648 && *r->in.authority_name
3649 /* && *(*r->in.authority_name)->string */
3651 return NT_STATUS_INVALID_PARAMETER;
3654 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3655 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3657 _account_name = talloc(mem_ctx, struct lsa_String);
3658 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3659 _account_name->string = account_name;
3661 if (r->in.authority_name) {
3662 _authority_name = talloc(mem_ctx, struct lsa_String);
3663 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3664 _authority_name->string = authority_name;
3667 *r->out.account_name = _account_name;
3668 if (r->out.authority_name) {
3669 *r->out.authority_name = _authority_name;
3678 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3679 TALLOC_CTX *mem_ctx,
3680 struct lsa_SetInfoPolicy2 *r)
3682 /* need to support these */
3683 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3686 static void kdc_get_policy(struct loadparm_context *lp_ctx,
3687 struct smb_krb5_context *smb_krb5_context,
3688 struct lsa_DomainInfoKerberos *k)
3690 time_t svc_tkt_lifetime;
3691 time_t usr_tkt_lifetime;
3692 time_t renewal_lifetime;
3694 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
3696 /* Our KDC always re-validates the client */
3697 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
3699 lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
3700 &usr_tkt_lifetime, &renewal_lifetime);
3702 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
3703 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
3704 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
3705 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
3706 However in the parent function we basically just did a full
3707 krb5_context init with the only purpose of getting a global
3708 config option (the max skew), it would probably make more sense
3709 to have a lp_ or ldb global option as the samba default */
3710 if (smb_krb5_context) {
3711 unix_to_nt_time(&k->clock_skew,
3712 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
3718 lsa_QueryDomainInformationPolicy
3720 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3721 TALLOC_CTX *mem_ctx,
3722 struct lsa_QueryDomainInformationPolicy *r)
3724 union lsa_DomainInformationPolicy *info;
3726 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3728 return NT_STATUS_NO_MEMORY;
3731 switch (r->in.level) {
3732 case LSA_DOMAIN_INFO_POLICY_EFS:
3734 *r->out.info = NULL;
3735 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3736 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3738 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3739 struct smb_krb5_context *smb_krb5_context;
3740 int ret = smb_krb5_init_context(mem_ctx,
3741 dce_call->event_ctx,
3742 dce_call->conn->dce_ctx->lp_ctx,
3746 *r->out.info = NULL;
3747 return NT_STATUS_INTERNAL_ERROR;
3749 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3752 talloc_free(smb_krb5_context);
3753 *r->out.info = info;
3754 return NT_STATUS_OK;
3758 *r->out.info = NULL;
3759 return NT_STATUS_INVALID_INFO_CLASS;
3764 lsa_SetDomInfoPolicy
3766 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3767 TALLOC_CTX *mem_ctx,
3768 struct lsa_SetDomainInformationPolicy *r)
3770 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3776 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3777 TALLOC_CTX *mem_ctx,
3778 struct lsa_TestCall *r)
3780 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3786 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3787 struct lsa_CREDRWRITE *r)
3789 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3796 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3797 struct lsa_CREDRREAD *r)
3799 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3806 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3807 struct lsa_CREDRENUMERATE *r)
3809 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3814 lsa_CREDRWRITEDOMAINCREDENTIALS
3816 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3817 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3819 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3824 lsa_CREDRREADDOMAINCREDENTIALS
3826 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3827 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3829 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3836 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3837 struct lsa_CREDRDELETE *r)
3839 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3844 lsa_CREDRGETTARGETINFO
3846 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3847 struct lsa_CREDRGETTARGETINFO *r)
3849 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3854 lsa_CREDRPROFILELOADED
3856 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3857 struct lsa_CREDRPROFILELOADED *r)
3859 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3864 lsa_CREDRGETSESSIONTYPES
3866 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3867 struct lsa_CREDRGETSESSIONTYPES *r)
3869 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3874 lsa_LSARREGISTERAUDITEVENT
3876 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3877 struct lsa_LSARREGISTERAUDITEVENT *r)
3879 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3884 lsa_LSARGENAUDITEVENT
3886 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3887 struct lsa_LSARGENAUDITEVENT *r)
3889 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3894 lsa_LSARUNREGISTERAUDITEVENT
3896 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3897 struct lsa_LSARUNREGISTERAUDITEVENT *r)
3899 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3904 lsa_lsaRQueryForestTrustInformation
3906 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3907 struct lsa_lsaRQueryForestTrustInformation *r)
3909 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3912 #define DNS_CMP_MATCH 0
3913 #define DNS_CMP_FIRST_IS_CHILD 1
3914 #define DNS_CMP_SECOND_IS_CHILD 2
3915 #define DNS_CMP_NO_MATCH 3
3917 /* this function assumes names are well formed DNS names.
3918 * it doesn't validate them */
3919 static int dns_cmp(const char *s1, size_t l1,
3920 const char *s2, size_t l2)
3922 const char *p1, *p2;
3927 if (strcasecmp_m(s1, s2) == 0) {
3928 return DNS_CMP_MATCH;
3930 return DNS_CMP_NO_MATCH;
3938 cret = DNS_CMP_FIRST_IS_CHILD;
3944 cret = DNS_CMP_SECOND_IS_CHILD;
3947 if (p1[t1 - t2 - 1] != '.') {
3948 return DNS_CMP_NO_MATCH;
3951 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3955 return DNS_CMP_NO_MATCH;
3958 /* decode all TDOs forest trust info blobs */
3959 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3960 struct ldb_message *msg,
3961 struct ForestTrustInfo *info)
3963 const struct ldb_val *ft_blob;
3964 enum ndr_err_code ndr_err;
3966 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3967 if (!ft_blob || !ft_blob->data) {
3968 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3970 /* ldb_val is equivalent to DATA_BLOB */
3971 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3972 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3973 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3974 return NT_STATUS_INVALID_DOMAIN_STATE;
3977 return NT_STATUS_OK;
3980 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
3981 struct ForestTrustInfo *fti)
3983 struct ForestTrustDataDomainInfo *info;
3984 struct ForestTrustInfoRecord *rec;
3988 fti->records = talloc_array(fti,
3989 struct ForestTrustInfoRecordArmor, 2);
3990 if (!fti->records) {
3991 return NT_STATUS_NO_MEMORY;
3995 rec = &fti->records[0].record;
3999 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
4001 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
4002 if (!rec->data.name.string) {
4003 return NT_STATUS_NO_MEMORY;
4005 rec->data.name.size = strlen(rec->data.name.string);
4008 rec = &fti->records[1].record;
4012 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
4014 info = &rec->data.info;
4016 info->sid = *ps->domain_sid;
4017 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
4018 if (!info->dns_name.string) {
4019 return NT_STATUS_NO_MEMORY;
4021 info->dns_name.size = strlen(info->dns_name.string);
4022 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
4023 if (!info->netbios_name.string) {
4024 return NT_STATUS_NO_MEMORY;
4026 info->netbios_name.size = strlen(info->netbios_name.string);
4028 return NT_STATUS_OK;
4031 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
4032 struct lsa_ForestTrustInformation *lfti,
4033 struct ForestTrustInfo *fti)
4035 struct lsa_ForestTrustRecord *lrec;
4036 struct ForestTrustInfoRecord *rec;
4037 struct lsa_StringLarge *tln;
4038 struct lsa_ForestTrustDomainInfo *info;
4042 fti->count = lfti->count;
4043 fti->records = talloc_array(mem_ctx,
4044 struct ForestTrustInfoRecordArmor,
4046 if (!fti->records) {
4047 return NT_STATUS_NO_MEMORY;
4049 for (i = 0; i < fti->count; i++) {
4050 lrec = lfti->entries[i];
4051 rec = &fti->records[i].record;
4053 rec->flags = lrec->flags;
4054 rec->timestamp = lrec->time;
4055 rec->type = lrec->type;
4057 switch (lrec->type) {
4058 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4059 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4060 tln = &lrec->forest_trust_data.top_level_name;
4061 rec->data.name.string =
4062 talloc_strdup(mem_ctx, tln->string);
4063 if (!rec->data.name.string) {
4064 return NT_STATUS_NO_MEMORY;
4066 rec->data.name.size = strlen(rec->data.name.string);
4068 case LSA_FOREST_TRUST_DOMAIN_INFO:
4069 info = &lrec->forest_trust_data.domain_info;
4070 rec->data.info.sid = *info->domain_sid;
4071 rec->data.info.dns_name.string =
4072 talloc_strdup(mem_ctx,
4073 info->dns_domain_name.string);
4074 if (!rec->data.info.dns_name.string) {
4075 return NT_STATUS_NO_MEMORY;
4077 rec->data.info.dns_name.size =
4078 strlen(rec->data.info.dns_name.string);
4079 rec->data.info.netbios_name.string =
4080 talloc_strdup(mem_ctx,
4081 info->netbios_domain_name.string);
4082 if (!rec->data.info.netbios_name.string) {
4083 return NT_STATUS_NO_MEMORY;
4085 rec->data.info.netbios_name.size =
4086 strlen(rec->data.info.netbios_name.string);
4089 return NT_STATUS_INVALID_DOMAIN_STATE;
4093 return NT_STATUS_OK;
4096 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4097 uint32_t idx, uint32_t collision_type,
4098 uint32_t conflict_type, const char *tdo_name);
4100 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4101 const char *tdo_name,
4102 struct ForestTrustInfo *tdo_fti,
4103 struct ForestTrustInfo *new_fti,
4104 struct lsa_ForestTrustCollisionInfo *c_info)
4106 struct ForestTrustInfoRecord *nrec;
4107 struct ForestTrustInfoRecord *trec;
4108 const char *dns_name;
4109 const char *nb_name;
4110 struct dom_sid *sid;
4114 NTSTATUS nt_status = NT_STATUS_OK;
4115 uint32_t new_fti_idx;
4117 /* use always TDO type, until we understand when Xref can be used */
4118 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4126 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4128 nrec = &new_fti->records[new_fti_idx].record;
4130 tln_conflict = false;
4131 sid_conflict = false;
4132 nb_conflict = false;
4135 switch (nrec->type) {
4136 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4137 /* exclusions do not conflict by definition */
4140 case FOREST_TRUST_TOP_LEVEL_NAME:
4141 dns_name = nrec->data.name.string;
4142 dns_len = nrec->data.name.size;
4145 case LSA_FOREST_TRUST_DOMAIN_INFO:
4146 dns_name = nrec->data.info.dns_name.string;
4147 dns_len = nrec->data.info.dns_name.size;
4148 nb_name = nrec->data.info.netbios_name.string;
4149 sid = &nrec->data.info.sid;
4153 if (!dns_name) continue;
4155 /* check if this is already taken and not excluded */
4156 for (i = 0; i < tdo_fti->count; i++) {
4157 trec = &tdo_fti->records[i].record;
4159 switch (trec->type) {
4160 case FOREST_TRUST_TOP_LEVEL_NAME:
4162 tname = trec->data.name.string;
4163 tlen = trec->data.name.size;
4165 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4167 tname = trec->data.name.string;
4168 tlen = trec->data.name.size;
4170 case FOREST_TRUST_DOMAIN_INFO:
4172 tname = trec->data.info.dns_name.string;
4173 tlen = trec->data.info.dns_name.size;
4175 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4178 /* if it matches exclusion,
4179 * it doesn't conflict */
4185 case DNS_CMP_FIRST_IS_CHILD:
4186 case DNS_CMP_SECOND_IS_CHILD:
4187 tln_conflict = true;
4193 /* explicit exclusion, no dns name conflict here */
4195 tln_conflict = false;
4198 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4202 /* also test for domain info */
4203 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4204 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4205 sid_conflict = true;
4207 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4208 strcasecmp_m(trec->data.info.netbios_name.string,
4215 nt_status = add_collision(c_info, new_fti_idx,
4217 LSA_TLN_DISABLED_CONFLICT,
4219 if (!NT_STATUS_IS_OK(nt_status)) {
4224 nt_status = add_collision(c_info, new_fti_idx,
4226 LSA_SID_DISABLED_CONFLICT,
4228 if (!NT_STATUS_IS_OK(nt_status)) {
4233 nt_status = add_collision(c_info, new_fti_idx,
4235 LSA_NB_DISABLED_CONFLICT,
4237 if (!NT_STATUS_IS_OK(nt_status)) {
4247 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4248 uint32_t idx, uint32_t collision_type,
4249 uint32_t conflict_type, const char *tdo_name)
4251 struct lsa_ForestTrustCollisionRecord **es;
4252 uint32_t i = c_info->count;
4254 es = talloc_realloc(c_info, c_info->entries,
4255 struct lsa_ForestTrustCollisionRecord *, i + 1);
4257 return NT_STATUS_NO_MEMORY;
4259 c_info->entries = es;
4260 c_info->count = i + 1;
4262 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4264 return NT_STATUS_NO_MEMORY;
4268 es[i]->type = collision_type;
4269 es[i]->flags.flags = conflict_type;
4270 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4271 if (!es[i]->name.string) {
4272 return NT_STATUS_NO_MEMORY;
4274 es[i]->name.size = strlen(es[i]->name.string);
4276 return NT_STATUS_OK;
4280 lsa_lsaRSetForestTrustInformation
4282 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4283 TALLOC_CTX *mem_ctx,
4284 struct lsa_lsaRSetForestTrustInformation *r)
4286 struct dcesrv_handle *h;
4287 struct lsa_policy_state *p_state;
4288 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4289 "msDS-TrustForestTrustInfo", NULL };
4290 struct ldb_message **dom_res = NULL;
4291 struct ldb_dn *tdo_dn;
4292 struct ldb_message *msg;
4294 const char *td_name;
4295 uint32_t trust_attributes;
4296 struct lsa_ForestTrustCollisionInfo *c_info;
4297 struct ForestTrustInfo *nfti;
4298 struct ForestTrustInfo *fti;
4300 enum ndr_err_code ndr_err;
4305 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4309 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4310 return NT_STATUS_INVALID_DOMAIN_STATE;
4313 /* abort if we are not a PDC */
4314 if (!samdb_is_pdc(p_state->sam_ldb)) {
4315 return NT_STATUS_INVALID_DOMAIN_ROLE;
4318 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4319 if (ret == LDB_SUCCESS && am_rodc) {
4320 return NT_STATUS_NO_SUCH_DOMAIN;
4323 /* check caller has TRUSTED_SET_AUTH */
4325 /* fetch all trusted domain objects */
4326 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4328 &dom_res, trust_attrs,
4329 "(objectclass=trustedDomain)");
4331 return NT_STATUS_NO_SUCH_DOMAIN;
4334 for (i = 0; i < num_res; i++) {
4335 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4336 "trustPartner", NULL);
4338 return NT_STATUS_INVALID_DOMAIN_STATE;
4340 if (strcasecmp_m(td_name,
4341 r->in.trusted_domain_name->string) == 0) {
4346 return NT_STATUS_NO_SUCH_DOMAIN;
4349 tdo_dn = dom_res[i]->dn;
4351 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4352 "trustAttributes", 0);
4353 if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4354 return NT_STATUS_INVALID_PARAMETER;
4357 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4358 return NT_STATUS_INVALID_PARAMETER;
4361 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4363 return NT_STATUS_NO_MEMORY;
4366 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4367 if (!NT_STATUS_IS_OK(nt_status)) {
4371 c_info = talloc_zero(r->out.collision_info,
4372 struct lsa_ForestTrustCollisionInfo);
4374 return NT_STATUS_NO_MEMORY;
4377 /* first check own info, then other domains */
4378 fti = talloc(mem_ctx, struct ForestTrustInfo);
4380 return NT_STATUS_NO_MEMORY;
4383 nt_status = own_ft_info(p_state, fti);
4384 if (!NT_STATUS_IS_OK(nt_status)) {
4388 nt_status = check_ft_info(c_info, p_state->domain_dns,
4390 if (!NT_STATUS_IS_OK(nt_status)) {
4394 for (i = 0; i < num_res; i++) {
4395 fti = talloc(mem_ctx, struct ForestTrustInfo);
4397 return NT_STATUS_NO_MEMORY;
4400 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4401 if (!NT_STATUS_IS_OK(nt_status)) {
4402 if (NT_STATUS_EQUAL(nt_status,
4403 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4409 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4410 "trustPartner", NULL);
4412 return NT_STATUS_INVALID_DOMAIN_STATE;
4415 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4416 if (!NT_STATUS_IS_OK(nt_status)) {
4421 *r->out.collision_info = c_info;
4423 if (r->in.check_only != 0) {
4424 return NT_STATUS_OK;
4427 /* not just a check, write info back */
4429 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4430 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4431 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4432 return NT_STATUS_INVALID_PARAMETER;
4435 msg = ldb_msg_new(mem_ctx);
4437 return NT_STATUS_NO_MEMORY;
4440 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4442 return NT_STATUS_NO_MEMORY;
4445 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4446 LDB_FLAG_MOD_REPLACE, NULL);
4447 if (ret != LDB_SUCCESS) {
4448 return NT_STATUS_NO_MEMORY;
4450 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4452 if (ret != LDB_SUCCESS) {
4453 return NT_STATUS_NO_MEMORY;
4456 ret = ldb_modify(p_state->sam_ldb, msg);
4457 if (ret != LDB_SUCCESS) {
4458 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4459 ldb_errstring(p_state->sam_ldb)));
4462 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4463 return NT_STATUS_ACCESS_DENIED;
4465 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4469 return NT_STATUS_OK;
4475 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4476 struct lsa_CREDRRENAME *r)
4478 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4484 lsa_LSAROPENPOLICYSCE
4486 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4487 struct lsa_LSAROPENPOLICYSCE *r)
4489 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4494 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4496 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4497 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4499 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4504 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4506 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4507 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4509 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4514 lsa_LSARADTREPORTSECURITYEVENT
4516 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4517 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4519 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4523 /* include the generated boilerplate */
4524 #include "librpc/gen_ndr/ndr_lsa_s.c"
4528 /*****************************************
4529 NOTE! The remaining calls below were
4530 removed in w2k3, so the DCESRV_FAULT()
4531 replies are the correct implementation. Do
4532 not try and fill these in with anything else
4533 ******************************************/
4536 dssetup_DsRoleDnsNameToFlatName
4538 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4539 struct dssetup_DsRoleDnsNameToFlatName *r)
4541 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4546 dssetup_DsRoleDcAsDc
4548 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4549 struct dssetup_DsRoleDcAsDc *r)
4551 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4556 dssetup_DsRoleDcAsReplica
4558 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4559 struct dssetup_DsRoleDcAsReplica *r)
4561 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4566 dssetup_DsRoleDemoteDc
4568 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4569 struct dssetup_DsRoleDemoteDc *r)
4571 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4576 dssetup_DsRoleGetDcOperationProgress
4578 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4579 struct dssetup_DsRoleGetDcOperationProgress *r)
4581 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4586 dssetup_DsRoleGetDcOperationResults
4588 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4589 struct dssetup_DsRoleGetDcOperationResults *r)
4591 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4596 dssetup_DsRoleCancel
4598 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4599 struct dssetup_DsRoleCancel *r)
4601 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4606 dssetup_DsRoleServerSaveStateForUpgrade
4608 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4609 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4611 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4616 dssetup_DsRoleUpgradeDownlevelServer
4618 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4619 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4621 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4626 dssetup_DsRoleAbortDownlevelServerUpgrade
4628 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4629 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4631 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4635 /* include the generated boilerplate */
4636 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4638 NTSTATUS dcerpc_server_lsa_init(void)
4642 ret = dcerpc_server_dssetup_init();
4643 if (!NT_STATUS_IS_OK(ret)) {
4646 ret = dcerpc_server_lsarpc_init();
4647 if (!NT_STATUS_IS_OK(ret)) {