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 if (!NT_STATUS_IS_OK(status)) {
92 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
93 if (domain_admins_sid == NULL) {
95 return NT_STATUS_NO_MEMORY;
98 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
99 if (domain_admins_sid_str == NULL) {
100 TALLOC_FREE(tmp_ctx);
101 return NT_STATUS_NO_MEMORY;
104 sidstr = dom_sid_string(tmp_ctx, sid);
105 if (sidstr == NULL) {
106 TALLOC_FREE(tmp_ctx);
107 return NT_STATUS_NO_MEMORY;
110 *sd = security_descriptor_dacl_create(mem_ctx,
114 SEC_ACE_TYPE_ACCESS_ALLOWED,
115 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
117 SID_BUILTIN_ADMINISTRATORS,
118 SEC_ACE_TYPE_ACCESS_ALLOWED,
121 SID_BUILTIN_ACCOUNT_OPERATORS,
122 SEC_ACE_TYPE_ACCESS_ALLOWED,
125 domain_admins_sid_str,
126 SEC_ACE_TYPE_ACCESS_ALLOWED,
130 SEC_ACE_TYPE_ACCESS_ALLOWED,
134 talloc_free(tmp_ctx);
136 NT_STATUS_HAVE_NO_MEMORY(*sd);
142 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
144 struct lsa_EnumAccountRights *r);
146 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
148 struct lsa_policy_state *state,
151 const struct lsa_RightSet *rights);
156 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
159 enum dcerpc_transport_t transport =
160 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
161 struct dcesrv_handle *h;
163 if (transport != NCACN_NP && transport != NCALRPC) {
164 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
167 *r->out.handle = *r->in.handle;
169 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
173 ZERO_STRUCTP(r->out.handle);
182 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
183 struct lsa_Delete *r)
185 return NT_STATUS_NOT_SUPPORTED;
192 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
193 struct lsa_DeleteObject *r)
195 struct dcesrv_handle *h;
198 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
200 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
201 struct lsa_secret_state *secret_state = h->data;
203 /* Ensure user is permitted to delete this... */
204 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
206 case SECURITY_SYSTEM:
207 case SECURITY_ADMINISTRATOR:
210 /* Users and anonymous are not allowed to delete things */
211 return NT_STATUS_ACCESS_DENIED;
214 ret = ldb_delete(secret_state->sam_ldb,
215 secret_state->secret_dn);
216 if (ret != LDB_SUCCESS) {
217 return NT_STATUS_INVALID_HANDLE;
220 ZERO_STRUCTP(r->out.handle);
224 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
225 struct lsa_trusted_domain_state *trusted_domain_state =
226 talloc_get_type(h->data, struct lsa_trusted_domain_state);
227 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
228 if (ret != LDB_SUCCESS) {
229 return NT_STATUS_INTERNAL_DB_CORRUPTION;
232 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
233 trusted_domain_state->trusted_domain_dn);
234 if (ret != LDB_SUCCESS) {
235 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
236 return NT_STATUS_INVALID_HANDLE;
239 if (trusted_domain_state->trusted_domain_user_dn) {
240 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
241 trusted_domain_state->trusted_domain_user_dn);
242 if (ret != LDB_SUCCESS) {
243 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
244 return NT_STATUS_INVALID_HANDLE;
248 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
249 if (ret != LDB_SUCCESS) {
250 return NT_STATUS_INTERNAL_DB_CORRUPTION;
253 ZERO_STRUCTP(r->out.handle);
257 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
258 struct lsa_RightSet *rights;
259 struct lsa_account_state *astate;
260 struct lsa_EnumAccountRights r2;
263 rights = talloc(mem_ctx, struct lsa_RightSet);
265 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
269 r2.in.handle = &astate->policy->handle->wire_handle;
270 r2.in.sid = astate->account_sid;
271 r2.out.rights = rights;
273 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
274 but we have a LSA_HANDLE_ACCOUNT here, so this call
276 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
277 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
281 if (!NT_STATUS_IS_OK(status)) {
285 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
286 LDB_FLAG_MOD_DELETE, astate->account_sid,
288 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
292 if (!NT_STATUS_IS_OK(status)) {
296 ZERO_STRUCTP(r->out.handle);
301 return NT_STATUS_INVALID_HANDLE;
308 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
309 struct lsa_EnumPrivs *r)
311 struct dcesrv_handle *h;
313 enum sec_privilege priv;
314 const char *privname;
316 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
318 i = *r->in.resume_handle;
320 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
321 r->out.privs->count < r->in.max_count) {
322 struct lsa_PrivEntry *e;
323 privname = sec_privilege_name(priv);
324 r->out.privs->privs = talloc_realloc(r->out.privs,
326 struct lsa_PrivEntry,
327 r->out.privs->count+1);
328 if (r->out.privs->privs == NULL) {
329 return NT_STATUS_NO_MEMORY;
331 e = &r->out.privs->privs[r->out.privs->count];
334 e->name.string = privname;
335 r->out.privs->count++;
339 *r->out.resume_handle = i;
348 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
349 struct lsa_QuerySecurity *r)
351 struct dcesrv_handle *h;
352 struct security_descriptor *sd;
356 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
358 sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
360 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
361 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
362 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
363 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid,
364 LSA_ACCOUNT_ALL_ACCESS);
366 return NT_STATUS_INVALID_HANDLE;
368 NT_STATUS_NOT_OK_RETURN(status);
370 (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
371 NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
373 (*r->out.sdbuf)->sd = sd;
382 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
383 struct lsa_SetSecObj *r)
385 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
392 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
393 struct lsa_ChangePassword *r)
395 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
399 dssetup_DsRoleGetPrimaryDomainInformation
401 This is not an LSA call, but is the only call left on the DSSETUP
402 pipe (after the pipe was truncated), and needs lsa_get_policy_state
404 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
406 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
408 union dssetup_DsRoleInfo *info;
410 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
411 W_ERROR_HAVE_NO_MEMORY(info);
413 switch (r->in.level) {
414 case DS_ROLE_BASIC_INFORMATION:
416 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
418 const char *domain = NULL;
419 const char *dns_domain = NULL;
420 const char *forest = NULL;
421 struct GUID domain_guid;
422 struct lsa_policy_state *state;
424 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
425 if (!NT_STATUS_IS_OK(status)) {
426 return ntstatus_to_werror(status);
429 ZERO_STRUCT(domain_guid);
431 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
432 case ROLE_STANDALONE:
433 role = DS_ROLE_STANDALONE_SERVER;
435 case ROLE_DOMAIN_MEMBER:
436 role = DS_ROLE_MEMBER_SERVER;
438 case ROLE_ACTIVE_DIRECTORY_DC:
439 if (samdb_is_pdc(state->sam_ldb)) {
440 role = DS_ROLE_PRIMARY_DC;
442 role = DS_ROLE_BACKUP_DC;
447 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
448 case ROLE_STANDALONE:
449 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
450 W_ERROR_HAVE_NO_MEMORY(domain);
452 case ROLE_DOMAIN_MEMBER:
453 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
454 W_ERROR_HAVE_NO_MEMORY(domain);
455 /* TODO: what is with dns_domain and forest and guid? */
457 case ROLE_ACTIVE_DIRECTORY_DC:
458 flags = DS_ROLE_PRIMARY_DS_RUNNING;
460 if (state->mixed_domain == 1) {
461 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
464 domain = state->domain_name;
465 dns_domain = state->domain_dns;
466 forest = state->forest_dns;
468 domain_guid = state->domain_guid;
469 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
473 info->basic.role = role;
474 info->basic.flags = flags;
475 info->basic.domain = domain;
476 info->basic.dns_domain = dns_domain;
477 info->basic.forest = forest;
478 info->basic.domain_guid = domain_guid;
483 case DS_ROLE_UPGRADE_STATUS:
485 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
486 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
491 case DS_ROLE_OP_STATUS:
493 info->opstatus.status = DS_ROLE_OP_IDLE;
499 return WERR_INVALID_PARAM;
504 fill in the AccountDomain info
506 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
507 struct lsa_DomainInfo *info)
509 info->name.string = state->domain_name;
510 info->sid = state->domain_sid;
516 fill in the DNS domain info
518 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
519 struct lsa_DnsDomainInfo *info)
521 info->name.string = state->domain_name;
522 info->sid = state->domain_sid;
523 info->dns_domain.string = state->domain_dns;
524 info->dns_forest.string = state->forest_dns;
525 info->domain_guid = state->domain_guid;
533 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
534 struct lsa_QueryInfoPolicy2 *r)
536 struct lsa_policy_state *state;
537 struct dcesrv_handle *h;
538 union lsa_PolicyInformation *info;
542 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
546 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
548 return NT_STATUS_NO_MEMORY;
552 switch (r->in.level) {
553 case LSA_POLICY_INFO_AUDIT_LOG:
554 /* we don't need to fill in any of this */
555 ZERO_STRUCT(info->audit_log);
557 case LSA_POLICY_INFO_AUDIT_EVENTS:
558 /* we don't need to fill in any of this */
559 ZERO_STRUCT(info->audit_events);
561 case LSA_POLICY_INFO_PD:
562 /* we don't need to fill in any of this */
563 ZERO_STRUCT(info->pd);
566 case LSA_POLICY_INFO_DOMAIN:
567 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
568 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
569 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
570 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
571 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
573 case LSA_POLICY_INFO_ROLE:
574 info->role.role = LSA_ROLE_PRIMARY;
577 case LSA_POLICY_INFO_DNS:
578 case LSA_POLICY_INFO_DNS_INT:
579 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
581 case LSA_POLICY_INFO_REPLICA:
582 ZERO_STRUCT(info->replica);
585 case LSA_POLICY_INFO_QUOTA:
586 ZERO_STRUCT(info->quota);
589 case LSA_POLICY_INFO_MOD:
590 case LSA_POLICY_INFO_AUDIT_FULL_SET:
591 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
592 /* windows gives INVALID_PARAMETER */
594 return NT_STATUS_INVALID_PARAMETER;
598 return NT_STATUS_INVALID_INFO_CLASS;
604 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
605 struct lsa_QueryInfoPolicy *r)
607 struct lsa_QueryInfoPolicy2 r2;
612 r2.in.handle = r->in.handle;
613 r2.in.level = r->in.level;
614 r2.out.info = r->out.info;
616 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
624 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
625 struct lsa_SetInfoPolicy *r)
627 /* need to support this */
628 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
635 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
636 struct lsa_ClearAuditLog *r)
638 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
645 This call does not seem to have any long-term effects, hence no database operations
647 we need to talk to the MS product group to find out what this account database means!
649 answer is that the lsa database is totally separate from the SAM and
650 ldap databases. We are going to need a separate ldb to store these
651 accounts. The SIDs on this account bear no relation to the SIDs in
654 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
655 struct lsa_CreateAccount *r)
657 struct lsa_account_state *astate;
659 struct lsa_policy_state *state;
660 struct dcesrv_handle *h, *ah;
662 ZERO_STRUCTP(r->out.acct_handle);
664 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
668 astate = talloc(dce_call->conn, struct lsa_account_state);
669 if (astate == NULL) {
670 return NT_STATUS_NO_MEMORY;
673 astate->account_sid = dom_sid_dup(astate, r->in.sid);
674 if (astate->account_sid == NULL) {
676 return NT_STATUS_NO_MEMORY;
679 astate->policy = talloc_reference(astate, state);
680 astate->access_mask = r->in.access_mask;
682 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
685 return NT_STATUS_NO_MEMORY;
688 ah->data = talloc_steal(ah, astate);
690 *r->out.acct_handle = ah->wire_handle;
699 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
700 struct lsa_EnumAccounts *r)
702 struct dcesrv_handle *h;
703 struct lsa_policy_state *state;
705 struct ldb_message **res;
706 const char * const attrs[] = { "objectSid", NULL};
709 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
713 /* NOTE: This call must only return accounts that have at least
716 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
717 "(&(objectSid=*)(privilege=*))");
719 return NT_STATUS_INTERNAL_DB_CORRUPTION;
722 if (*r->in.resume_handle >= ret) {
723 return NT_STATUS_NO_MORE_ENTRIES;
726 count = ret - *r->in.resume_handle;
727 if (count > r->in.num_entries) {
728 count = r->in.num_entries;
732 return NT_STATUS_NO_MORE_ENTRIES;
735 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
736 if (r->out.sids->sids == NULL) {
737 return NT_STATUS_NO_MEMORY;
740 for (i=0;i<count;i++) {
741 r->out.sids->sids[i].sid =
742 samdb_result_dom_sid(r->out.sids->sids,
743 res[i + *r->in.resume_handle],
745 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
748 r->out.sids->num_sids = count;
749 *r->out.resume_handle = count + *r->in.resume_handle;
754 /* This decrypts and returns Trusted Domain Auth Information Internal data */
755 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
756 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
757 struct trustDomainPasswords *auth_struct)
759 DATA_BLOB session_key = data_blob(NULL, 0);
760 enum ndr_err_code ndr_err;
763 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
764 if (!NT_STATUS_IS_OK(nt_status)) {
768 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
769 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
771 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
772 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
773 return NT_STATUS_INVALID_PARAMETER;
779 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
781 struct trustAuthInOutBlob *iopw,
782 DATA_BLOB *trustauth_blob)
784 enum ndr_err_code ndr_err;
786 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
788 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
789 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
790 return NT_STATUS_INVALID_PARAMETER;
796 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
797 struct ldb_context *sam_ldb,
798 struct ldb_dn *base_dn,
799 const char *netbios_name,
800 struct trustAuthInOutBlob *in,
801 struct ldb_dn **user_dn)
803 struct ldb_message *msg;
808 dn = ldb_dn_copy(mem_ctx, base_dn);
810 return NT_STATUS_NO_MEMORY;
812 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
813 return NT_STATUS_NO_MEMORY;
816 msg = ldb_msg_new(mem_ctx);
818 return NT_STATUS_NO_MEMORY;
822 ret = ldb_msg_add_string(msg, "objectClass", "user");
823 if (ret != LDB_SUCCESS) {
824 return NT_STATUS_NO_MEMORY;
827 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
828 if (ret != LDB_SUCCESS) {
829 return NT_STATUS_NO_MEMORY;
832 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
833 UF_INTERDOMAIN_TRUST_ACCOUNT);
834 if (ret != LDB_SUCCESS) {
835 return NT_STATUS_NO_MEMORY;
838 for (i = 0; i < in->count; i++) {
839 const char *attribute;
841 switch (in->current.array[i].AuthType) {
842 case TRUST_AUTH_TYPE_NT4OWF:
843 attribute = "unicodePwd";
844 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
847 case TRUST_AUTH_TYPE_CLEAR:
848 attribute = "clearTextPassword";
849 v.data = in->current.array[i].AuthInfo.clear.password;
850 v.length = in->current.array[i].AuthInfo.clear.size;
856 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
857 if (ret != LDB_SUCCESS) {
858 return NT_STATUS_NO_MEMORY;
862 /* create the trusted_domain user account */
863 ret = ldb_add(sam_ldb, msg);
864 if (ret != LDB_SUCCESS) {
865 DEBUG(0,("Failed to create user record %s: %s\n",
866 ldb_dn_get_linearized(msg->dn),
867 ldb_errstring(sam_ldb)));
870 case LDB_ERR_ENTRY_ALREADY_EXISTS:
871 return NT_STATUS_DOMAIN_EXISTS;
872 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
873 return NT_STATUS_ACCESS_DENIED;
875 return NT_STATUS_INTERNAL_DB_CORRUPTION;
886 lsa_CreateTrustedDomainEx2
888 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
890 struct lsa_CreateTrustedDomainEx2 *r,
892 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
894 struct dcesrv_handle *policy_handle;
895 struct lsa_policy_state *policy_state;
896 struct lsa_trusted_domain_state *trusted_domain_state;
897 struct dcesrv_handle *handle;
898 struct ldb_message **msgs, *msg;
899 const char *attrs[] = {
902 const char *netbios_name;
903 const char *dns_name;
905 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
906 struct trustDomainPasswords auth_struct;
909 struct ldb_context *sam_ldb;
911 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
912 ZERO_STRUCTP(r->out.trustdom_handle);
914 policy_state = policy_handle->data;
915 sam_ldb = policy_state->sam_ldb;
917 netbios_name = r->in.info->netbios_name.string;
919 return NT_STATUS_INVALID_PARAMETER;
922 dns_name = r->in.info->domain_name.string;
924 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
925 if (!trusted_domain_state) {
926 return NT_STATUS_NO_MEMORY;
928 trusted_domain_state->policy = policy_state;
930 if (strcasecmp(netbios_name, "BUILTIN") == 0
931 || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
932 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
933 return NT_STATUS_INVALID_PARAMETER;
936 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
937 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
938 || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
939 || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
940 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
941 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
944 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
945 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
946 /* No secrets are created at this time, for this function */
947 auth_struct.outgoing.count = 0;
948 auth_struct.incoming.count = 0;
949 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
950 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
951 r->in.auth_info_internal->auth_blob.size);
952 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
953 &auth_blob, &auth_struct);
954 if (!NT_STATUS_IS_OK(nt_status)) {
957 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
959 if (unencrypted_auth_info->incoming_count > 1) {
960 return NT_STATUS_INVALID_PARAMETER;
963 /* more investigation required here, do not create secrets for
965 auth_struct.outgoing.count = 0;
966 auth_struct.incoming.count = 0;
968 return NT_STATUS_INVALID_PARAMETER;
971 if (auth_struct.incoming.count) {
972 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
973 &auth_struct.incoming,
975 if (!NT_STATUS_IS_OK(nt_status)) {
979 trustAuthIncoming = data_blob(NULL, 0);
982 if (auth_struct.outgoing.count) {
983 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
984 &auth_struct.outgoing,
986 if (!NT_STATUS_IS_OK(nt_status)) {
990 trustAuthOutgoing = data_blob(NULL, 0);
993 ret = ldb_transaction_start(sam_ldb);
994 if (ret != LDB_SUCCESS) {
995 return NT_STATUS_INTERNAL_DB_CORRUPTION;
999 char *dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1000 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1001 /* search for the trusted_domain record */
1002 ret = gendb_search(sam_ldb,
1003 mem_ctx, policy_state->system_dn, &msgs, attrs,
1004 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1005 dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
1007 ldb_transaction_cancel(sam_ldb);
1008 return NT_STATUS_OBJECT_NAME_COLLISION;
1011 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1012 /* search for the trusted_domain record */
1013 ret = gendb_search(sam_ldb,
1014 mem_ctx, policy_state->system_dn, &msgs, attrs,
1015 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1016 netbios_encoded, netbios_encoded, netbios_encoded);
1018 ldb_transaction_cancel(sam_ldb);
1019 return NT_STATUS_OBJECT_NAME_COLLISION;
1024 ldb_transaction_cancel(sam_ldb);
1025 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1028 name = dns_name ? dns_name : netbios_name;
1030 msg = ldb_msg_new(mem_ctx);
1032 return NT_STATUS_NO_MEMORY;
1035 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1036 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1037 ldb_transaction_cancel(sam_ldb);
1038 return NT_STATUS_NO_MEMORY;
1041 ldb_msg_add_string(msg, "flatname", netbios_name);
1043 if (r->in.info->sid) {
1044 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1045 if (ret != LDB_SUCCESS) {
1046 ldb_transaction_cancel(sam_ldb);
1047 return NT_STATUS_INVALID_PARAMETER;
1051 ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1053 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1055 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1057 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1060 ldb_msg_add_string(msg, "trustPartner", dns_name);
1063 if (trustAuthIncoming.data) {
1064 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1065 if (ret != LDB_SUCCESS) {
1066 ldb_transaction_cancel(sam_ldb);
1067 return NT_STATUS_NO_MEMORY;
1070 if (trustAuthOutgoing.data) {
1071 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1072 if (ret != LDB_SUCCESS) {
1073 ldb_transaction_cancel(sam_ldb);
1074 return NT_STATUS_NO_MEMORY;
1078 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1080 /* create the trusted_domain */
1081 ret = ldb_add(sam_ldb, msg);
1085 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1086 ldb_transaction_cancel(sam_ldb);
1087 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1088 ldb_dn_get_linearized(msg->dn),
1089 ldb_errstring(sam_ldb)));
1090 return NT_STATUS_DOMAIN_EXISTS;
1091 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1092 ldb_transaction_cancel(sam_ldb);
1093 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1094 ldb_dn_get_linearized(msg->dn),
1095 ldb_errstring(sam_ldb)));
1096 return NT_STATUS_ACCESS_DENIED;
1098 ldb_transaction_cancel(sam_ldb);
1099 DEBUG(0,("Failed to create user record %s: %s\n",
1100 ldb_dn_get_linearized(msg->dn),
1101 ldb_errstring(sam_ldb)));
1102 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1105 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1106 struct ldb_dn *user_dn;
1107 /* Inbound trusts must also create a cn=users object to match */
1108 nt_status = add_trust_user(mem_ctx, sam_ldb,
1109 policy_state->domain_dn,
1111 &auth_struct.incoming,
1113 if (!NT_STATUS_IS_OK(nt_status)) {
1114 ldb_transaction_cancel(sam_ldb);
1118 /* save the trust user dn */
1119 trusted_domain_state->trusted_domain_user_dn
1120 = talloc_steal(trusted_domain_state, user_dn);
1123 ret = ldb_transaction_commit(sam_ldb);
1124 if (ret != LDB_SUCCESS) {
1125 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1128 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1130 return NT_STATUS_NO_MEMORY;
1133 handle->data = talloc_steal(handle, trusted_domain_state);
1135 trusted_domain_state->access_mask = r->in.access_mask;
1136 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1138 *r->out.trustdom_handle = handle->wire_handle;
1140 return NT_STATUS_OK;
1144 lsa_CreateTrustedDomainEx2
1146 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1147 TALLOC_CTX *mem_ctx,
1148 struct lsa_CreateTrustedDomainEx2 *r)
1150 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1153 lsa_CreateTrustedDomainEx
1155 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1156 TALLOC_CTX *mem_ctx,
1157 struct lsa_CreateTrustedDomainEx *r)
1159 struct lsa_CreateTrustedDomainEx2 r2;
1161 r2.in.policy_handle = r->in.policy_handle;
1162 r2.in.info = r->in.info;
1163 r2.out.trustdom_handle = r->out.trustdom_handle;
1164 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1168 lsa_CreateTrustedDomain
1170 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1171 struct lsa_CreateTrustedDomain *r)
1173 struct lsa_CreateTrustedDomainEx2 r2;
1175 r2.in.policy_handle = r->in.policy_handle;
1176 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1178 return NT_STATUS_NO_MEMORY;
1181 r2.in.info->domain_name.string = NULL;
1182 r2.in.info->netbios_name = r->in.info->name;
1183 r2.in.info->sid = r->in.info->sid;
1184 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1185 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1186 r2.in.info->trust_attributes = 0;
1188 r2.in.access_mask = r->in.access_mask;
1189 r2.out.trustdom_handle = r->out.trustdom_handle;
1191 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1195 lsa_OpenTrustedDomain
1197 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1198 struct lsa_OpenTrustedDomain *r)
1200 struct dcesrv_handle *policy_handle;
1202 struct lsa_policy_state *policy_state;
1203 struct lsa_trusted_domain_state *trusted_domain_state;
1204 struct dcesrv_handle *handle;
1205 struct ldb_message **msgs;
1206 const char *attrs[] = {
1212 const char *sid_string;
1215 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1216 ZERO_STRUCTP(r->out.trustdom_handle);
1217 policy_state = policy_handle->data;
1219 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1220 if (!trusted_domain_state) {
1221 return NT_STATUS_NO_MEMORY;
1223 trusted_domain_state->policy = policy_state;
1225 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1227 return NT_STATUS_NO_MEMORY;
1230 /* search for the trusted_domain record */
1231 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1232 mem_ctx, policy_state->system_dn, &msgs, attrs,
1233 "(&(securityIdentifier=%s)(objectclass=trustedDomain))",
1236 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1240 DEBUG(0,("Found %d records matching DN %s\n", ret,
1241 ldb_dn_get_linearized(policy_state->system_dn)));
1242 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1245 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1247 trusted_domain_state->trusted_domain_user_dn = NULL;
1249 if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1250 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1251 /* search for the trusted_domain record */
1252 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1253 mem_ctx, policy_state->domain_dn, &msgs, attrs,
1254 "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%u))",
1255 flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1257 trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1260 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1262 return NT_STATUS_NO_MEMORY;
1265 handle->data = talloc_steal(handle, trusted_domain_state);
1267 trusted_domain_state->access_mask = r->in.access_mask;
1268 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1270 *r->out.trustdom_handle = handle->wire_handle;
1272 return NT_STATUS_OK;
1277 lsa_OpenTrustedDomainByName
1279 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1280 TALLOC_CTX *mem_ctx,
1281 struct lsa_OpenTrustedDomainByName *r)
1283 struct dcesrv_handle *policy_handle;
1285 struct lsa_policy_state *policy_state;
1286 struct lsa_trusted_domain_state *trusted_domain_state;
1287 struct dcesrv_handle *handle;
1288 struct ldb_message **msgs;
1289 const char *attrs[] = {
1295 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1296 ZERO_STRUCTP(r->out.trustdom_handle);
1297 policy_state = policy_handle->data;
1299 if (!r->in.name.string) {
1300 return NT_STATUS_INVALID_PARAMETER;
1303 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1304 if (!trusted_domain_state) {
1305 return NT_STATUS_NO_MEMORY;
1307 trusted_domain_state->policy = policy_state;
1309 /* search for the trusted_domain record */
1310 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1311 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1312 mem_ctx, policy_state->system_dn, &msgs, attrs,
1313 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1314 "(objectclass=trustedDomain))",
1315 td_name, td_name, td_name);
1317 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1321 DEBUG(0,("Found %d records matching DN %s\n", ret,
1322 ldb_dn_get_linearized(policy_state->system_dn)));
1323 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1326 /* TODO: perform access checks */
1328 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1330 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1332 return NT_STATUS_NO_MEMORY;
1335 handle->data = talloc_steal(handle, trusted_domain_state);
1337 trusted_domain_state->access_mask = r->in.access_mask;
1338 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1340 *r->out.trustdom_handle = handle->wire_handle;
1342 return NT_STATUS_OK;
1348 lsa_SetTrustedDomainInfo
1350 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1351 struct lsa_SetTrustedDomainInfo *r)
1353 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1358 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1359 * otherwise at least one must be provided */
1360 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1361 struct ldb_dn *basedn, const char *dns_domain,
1362 const char *netbios, struct dom_sid2 *sid,
1363 struct ldb_message ***msgs)
1365 const char *attrs[] = { "flatname", "trustPartner",
1366 "securityIdentifier", "trustDirection",
1367 "trustType", "trustAttributes",
1369 "msDs-supportedEncryptionTypes", NULL };
1372 char *sidstr = NULL;
1377 if (dns_domain || netbios || sid) {
1378 filter = talloc_strdup(mem_ctx,
1379 "(&(objectclass=trustedDomain)(|");
1381 filter = talloc_strdup(mem_ctx,
1382 "(objectclass=trustedDomain)");
1385 return NT_STATUS_NO_MEMORY;
1389 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1391 return NT_STATUS_NO_MEMORY;
1393 filter = talloc_asprintf_append(filter,
1394 "(trustPartner=%s)", dns);
1396 return NT_STATUS_NO_MEMORY;
1400 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1402 return NT_STATUS_NO_MEMORY;
1404 filter = talloc_asprintf_append(filter,
1405 "(flatname=%s)", nbn);
1407 return NT_STATUS_NO_MEMORY;
1411 sidstr = dom_sid_string(mem_ctx, sid);
1413 return NT_STATUS_INVALID_PARAMETER;
1415 filter = talloc_asprintf_append(filter,
1416 "(securityIdentifier=%s)",
1419 return NT_STATUS_NO_MEMORY;
1422 if (dns_domain || netbios || sid) {
1423 filter = talloc_asprintf_append(filter, "))");
1425 return NT_STATUS_NO_MEMORY;
1429 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1431 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1435 return NT_STATUS_OBJECT_NAME_COLLISION;
1438 return NT_STATUS_OK;
1441 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1442 struct ldb_context *sam_ldb,
1443 struct ldb_message *orig,
1444 struct ldb_message *dest,
1445 const char *attribute,
1447 uint32_t *orig_value)
1449 const struct ldb_val *orig_val;
1450 uint32_t orig_uint = 0;
1451 unsigned int flags = 0;
1454 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1455 if (!orig_val || !orig_val->data) {
1456 /* add new attribute */
1457 flags = LDB_FLAG_MOD_ADD;
1461 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1462 if (errno != 0 || orig_uint != value) {
1463 /* replace also if can't get value */
1464 flags = LDB_FLAG_MOD_REPLACE;
1469 /* stored value is identical, nothing to change */
1473 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1474 if (ret != LDB_SUCCESS) {
1475 return NT_STATUS_NO_MEMORY;
1478 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1479 if (ret != LDB_SUCCESS) {
1480 return NT_STATUS_NO_MEMORY;
1485 *orig_value = orig_uint;
1487 return NT_STATUS_OK;
1490 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1491 struct ldb_context *sam_ldb,
1492 struct ldb_dn *base_dn,
1494 const char *netbios_name,
1495 struct trustAuthInOutBlob *in)
1497 const char *attrs[] = { "userAccountControl", NULL };
1498 struct ldb_message **msgs;
1499 struct ldb_message *msg;
1504 ret = gendb_search(sam_ldb, mem_ctx,
1505 base_dn, &msgs, attrs,
1506 "samAccountName=%s$", netbios_name);
1508 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1513 return NT_STATUS_OK;
1516 /* ok no existing user, add it from scratch */
1517 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1518 netbios_name, in, NULL);
1521 /* check user is what we are looking for */
1522 uac = ldb_msg_find_attr_as_uint(msgs[0],
1523 "userAccountControl", 0);
1524 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1525 return NT_STATUS_OBJECT_NAME_COLLISION;
1529 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1532 return NT_STATUS_OK;
1533 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1534 return NT_STATUS_ACCESS_DENIED;
1536 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1540 /* entry exists, just modify secret if any */
1541 if (in == NULL || in->count == 0) {
1542 return NT_STATUS_OK;
1545 msg = ldb_msg_new(mem_ctx);
1547 return NT_STATUS_NO_MEMORY;
1549 msg->dn = msgs[0]->dn;
1551 for (i = 0; i < in->count; i++) {
1552 const char *attribute;
1554 switch (in->current.array[i].AuthType) {
1555 case TRUST_AUTH_TYPE_NT4OWF:
1556 attribute = "unicodePwd";
1557 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1560 case TRUST_AUTH_TYPE_CLEAR:
1561 attribute = "clearTextPassword";
1562 v.data = in->current.array[i].AuthInfo.clear.password;
1563 v.length = in->current.array[i].AuthInfo.clear.size;
1569 ret = ldb_msg_add_empty(msg, attribute,
1570 LDB_FLAG_MOD_REPLACE, NULL);
1571 if (ret != LDB_SUCCESS) {
1572 return NT_STATUS_NO_MEMORY;
1575 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1576 if (ret != LDB_SUCCESS) {
1577 return NT_STATUS_NO_MEMORY;
1581 /* create the trusted_domain user account */
1582 ret = ldb_modify(sam_ldb, msg);
1583 if (ret != LDB_SUCCESS) {
1584 DEBUG(0,("Failed to create user record %s: %s\n",
1585 ldb_dn_get_linearized(msg->dn),
1586 ldb_errstring(sam_ldb)));
1589 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1590 return NT_STATUS_DOMAIN_EXISTS;
1591 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1592 return NT_STATUS_ACCESS_DENIED;
1594 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1598 return NT_STATUS_OK;
1602 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1603 struct lsa_policy_state *p_state,
1604 TALLOC_CTX *mem_ctx,
1605 struct ldb_message *dom_msg,
1606 enum lsa_TrustDomInfoEnum level,
1607 union lsa_TrustedDomainInfo *info)
1609 uint32_t *posix_offset = NULL;
1610 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1611 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1612 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1613 uint32_t *enc_types = NULL;
1614 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1615 struct trustDomainPasswords auth_struct;
1616 struct trustAuthInOutBlob *current_passwords = NULL;
1618 struct ldb_message **msgs;
1619 struct ldb_message *msg;
1620 bool add_outgoing = false;
1621 bool add_incoming = false;
1622 bool del_outgoing = false;
1623 bool del_incoming = false;
1624 bool in_transaction = false;
1629 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1630 posix_offset = &info->posix_offset.posix_offset;
1632 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1633 info_ex = &info->info_ex;
1635 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1636 auth_info = &info->auth_info;
1638 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1639 posix_offset = &info->full_info.posix_offset.posix_offset;
1640 info_ex = &info->full_info.info_ex;
1641 auth_info = &info->full_info.auth_info;
1643 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1644 auth_info_int = &info->auth_info_internal;
1646 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1647 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1648 info_ex = &info->full_info_internal.info_ex;
1649 auth_info_int = &info->full_info_internal.auth_info;
1651 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1652 enc_types = &info->enc_types.enc_types;
1655 return NT_STATUS_INVALID_PARAMETER;
1659 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1661 &trustAuthOutgoing);
1662 if (!NT_STATUS_IS_OK(nt_status)) {
1665 if (trustAuthIncoming.data) {
1666 /* This does the decode of some of this twice, but it is easier that way */
1667 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1668 auth_info->incoming_count,
1669 auth_info->incoming_current_auth_info,
1671 ¤t_passwords);
1672 if (!NT_STATUS_IS_OK(nt_status)) {
1678 /* decode auth_info_int if set */
1679 if (auth_info_int) {
1681 /* now decrypt blob */
1682 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1683 auth_info_int->auth_blob.size);
1685 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1686 &auth_blob, &auth_struct);
1687 if (!NT_STATUS_IS_OK(nt_status)) {
1693 /* verify data matches */
1694 if (info_ex->trust_attributes &
1695 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1696 /* TODO: check what behavior level we have */
1697 if (strcasecmp_m(p_state->domain_dns,
1698 p_state->forest_dns) != 0) {
1699 return NT_STATUS_INVALID_DOMAIN_STATE;
1703 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1704 if (ret == LDB_SUCCESS && am_rodc) {
1705 return NT_STATUS_NO_SUCH_DOMAIN;
1708 /* verify only one object matches the dns/netbios/sid
1709 * triplet and that this is the one we already have */
1710 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1712 info_ex->domain_name.string,
1713 info_ex->netbios_name.string,
1714 info_ex->sid, &msgs);
1715 if (!NT_STATUS_IS_OK(nt_status)) {
1718 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1719 return NT_STATUS_OBJECT_NAME_COLLISION;
1724 /* TODO: should we fetch previous values from the existing entry
1725 * and append them ? */
1726 if (auth_info_int && auth_struct.incoming.count) {
1727 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1728 &auth_struct.incoming,
1729 &trustAuthIncoming);
1730 if (!NT_STATUS_IS_OK(nt_status)) {
1734 current_passwords = &auth_struct.incoming;
1737 trustAuthIncoming = data_blob(NULL, 0);
1740 if (auth_info_int && auth_struct.outgoing.count) {
1741 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1742 &auth_struct.outgoing,
1743 &trustAuthOutgoing);
1744 if (!NT_STATUS_IS_OK(nt_status)) {
1748 trustAuthOutgoing = data_blob(NULL, 0);
1751 msg = ldb_msg_new(mem_ctx);
1753 return NT_STATUS_NO_MEMORY;
1755 msg->dn = dom_msg->dn;
1758 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1761 *posix_offset, NULL);
1762 if (!NT_STATUS_IS_OK(nt_status)) {
1769 uint32_t changed_attrs;
1773 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1776 info_ex->trust_direction,
1778 if (!NT_STATUS_IS_OK(nt_status)) {
1782 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1783 if (auth_info != NULL && trustAuthIncoming.length > 0) {
1784 add_incoming = true;
1787 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1788 if (auth_info != NULL && trustAuthOutgoing.length > 0) {
1789 add_outgoing = true;
1793 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1794 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1795 del_incoming = true;
1797 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1798 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1799 del_outgoing = true;
1802 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1803 if (origtype == -1 || origtype != info_ex->trust_type) {
1804 DEBUG(1, ("Attempted to change trust type! "
1805 "Operation not handled\n"));
1806 return NT_STATUS_INVALID_PARAMETER;
1809 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1812 info_ex->trust_attributes,
1814 if (!NT_STATUS_IS_OK(nt_status)) {
1817 /* TODO: check forestFunctionality from ldb opaque */
1818 /* TODO: check what is set makes sense */
1820 changed_attrs = origattrs ^ info_ex->trust_attributes;
1821 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1823 * For now we only allow
1824 * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
1826 * TODO: we may need to support more attribute changes
1828 DEBUG(1, ("Attempted to change trust attributes "
1829 "(0x%08x != 0x%08x)! "
1830 "Operation not handled yet...\n",
1831 (unsigned)origattrs,
1832 (unsigned)info_ex->trust_attributes));
1833 return NT_STATUS_INVALID_PARAMETER;
1838 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1840 "msDS-SupportedEncryptionTypes",
1842 if (!NT_STATUS_IS_OK(nt_status)) {
1847 if (add_incoming || del_incoming) {
1848 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1849 LDB_FLAG_MOD_REPLACE, NULL);
1850 if (ret != LDB_SUCCESS) {
1851 return NT_STATUS_NO_MEMORY;
1854 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1855 &trustAuthIncoming, NULL);
1856 if (ret != LDB_SUCCESS) {
1857 return NT_STATUS_NO_MEMORY;
1861 if (add_outgoing || del_outgoing) {
1862 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1863 LDB_FLAG_MOD_REPLACE, NULL);
1864 if (ret != LDB_SUCCESS) {
1865 return NT_STATUS_NO_MEMORY;
1868 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1869 &trustAuthOutgoing, NULL);
1870 if (ret != LDB_SUCCESS) {
1871 return NT_STATUS_NO_MEMORY;
1876 /* start transaction */
1877 ret = ldb_transaction_start(p_state->sam_ldb);
1878 if (ret != LDB_SUCCESS) {
1879 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1881 in_transaction = true;
1883 if (msg->num_elements) {
1884 ret = ldb_modify(p_state->sam_ldb, msg);
1885 if (ret != LDB_SUCCESS) {
1886 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1887 ldb_dn_get_linearized(msg->dn),
1888 ldb_errstring(p_state->sam_ldb)));
1889 nt_status = dsdb_ldb_err_to_ntstatus(ret);
1894 if (add_incoming || del_incoming) {
1895 const char *netbios_name;
1897 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1899 if (!netbios_name) {
1900 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1904 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
1905 nt_status = update_trust_user(mem_ctx,
1911 if (!NT_STATUS_IS_OK(nt_status)) {
1916 /* ok, all fine, commit transaction and return */
1917 ret = ldb_transaction_commit(p_state->sam_ldb);
1918 if (ret != LDB_SUCCESS) {
1919 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1921 in_transaction = false;
1923 nt_status = NT_STATUS_OK;
1926 if (in_transaction) {
1927 ldb_transaction_cancel(p_state->sam_ldb);
1933 lsa_SetInfomrationTrustedDomain
1935 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1936 struct dcesrv_call_state *dce_call,
1937 TALLOC_CTX *mem_ctx,
1938 struct lsa_SetInformationTrustedDomain *r)
1940 struct dcesrv_handle *h;
1941 struct lsa_trusted_domain_state *td_state;
1942 struct ldb_message **msgs;
1945 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1946 LSA_HANDLE_TRUSTED_DOMAIN);
1948 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1950 /* get the trusted domain object */
1951 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1952 td_state->trusted_domain_dn,
1953 NULL, NULL, NULL, &msgs);
1954 if (!NT_STATUS_IS_OK(nt_status)) {
1955 if (NT_STATUS_EQUAL(nt_status,
1956 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1959 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1962 return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
1963 msgs[0], r->in.level, r->in.info);
1968 lsa_DeleteTrustedDomain
1970 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1971 struct lsa_DeleteTrustedDomain *r)
1974 struct lsa_OpenTrustedDomain opn;
1975 struct lsa_DeleteObject del;
1976 struct dcesrv_handle *h;
1978 opn.in.handle = r->in.handle;
1979 opn.in.sid = r->in.dom_sid;
1980 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1981 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1982 if (!opn.out.trustdom_handle) {
1983 return NT_STATUS_NO_MEMORY;
1985 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1986 if (!NT_STATUS_IS_OK(status)) {
1990 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1991 talloc_steal(mem_ctx, h);
1993 del.in.handle = opn.out.trustdom_handle;
1994 del.out.handle = opn.out.trustdom_handle;
1995 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1996 if (!NT_STATUS_IS_OK(status)) {
1999 return NT_STATUS_OK;
2002 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2003 struct ldb_message *msg,
2004 struct lsa_TrustDomainInfoInfoEx *info_ex)
2006 info_ex->domain_name.string
2007 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2008 info_ex->netbios_name.string
2009 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2011 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2012 info_ex->trust_direction
2013 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2015 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2016 info_ex->trust_attributes
2017 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2018 return NT_STATUS_OK;
2022 lsa_QueryTrustedDomainInfo
2024 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2025 struct lsa_QueryTrustedDomainInfo *r)
2027 union lsa_TrustedDomainInfo *info = NULL;
2028 struct dcesrv_handle *h;
2029 struct lsa_trusted_domain_state *trusted_domain_state;
2030 struct ldb_message *msg;
2032 struct ldb_message **res;
2033 const char *attrs[] = {
2036 "securityIdentifier",
2040 "msDs-supportedEncryptionTypes",
2044 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2046 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2048 /* pull all the user attributes */
2049 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2050 trusted_domain_state->trusted_domain_dn, &res, attrs);
2052 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2056 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2058 return NT_STATUS_NO_MEMORY;
2060 *r->out.info = info;
2062 switch (r->in.level) {
2063 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2064 info->name.netbios_name.string
2065 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2067 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2068 info->posix_offset.posix_offset
2069 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2071 #if 0 /* Win2k3 doesn't implement this */
2072 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2073 r->out.info->info_basic.netbios_name.string
2074 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2075 r->out.info->info_basic.sid
2076 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2079 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2080 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2082 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2083 ZERO_STRUCT(info->full_info);
2084 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2085 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2086 ZERO_STRUCT(info->full_info2_internal);
2087 info->full_info2_internal.posix_offset.posix_offset
2088 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2089 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2091 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2092 info->enc_types.enc_types
2093 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2096 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2097 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2098 /* oops, we don't want to return the info after all */
2100 *r->out.info = NULL;
2101 return NT_STATUS_INVALID_PARAMETER;
2103 /* oops, we don't want to return the info after all */
2105 *r->out.info = NULL;
2106 return NT_STATUS_INVALID_INFO_CLASS;
2109 return NT_STATUS_OK;
2114 lsa_QueryTrustedDomainInfoBySid
2116 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2117 struct lsa_QueryTrustedDomainInfoBySid *r)
2120 struct lsa_OpenTrustedDomain opn;
2121 struct lsa_QueryTrustedDomainInfo query;
2122 struct dcesrv_handle *h;
2124 opn.in.handle = r->in.handle;
2125 opn.in.sid = r->in.dom_sid;
2126 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2127 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2128 if (!opn.out.trustdom_handle) {
2129 return NT_STATUS_NO_MEMORY;
2131 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2132 if (!NT_STATUS_IS_OK(status)) {
2136 /* Ensure this handle goes away at the end of this call */
2137 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2138 talloc_steal(mem_ctx, h);
2140 query.in.trustdom_handle = opn.out.trustdom_handle;
2141 query.in.level = r->in.level;
2142 query.out.info = r->out.info;
2143 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2144 if (!NT_STATUS_IS_OK(status)) {
2148 return NT_STATUS_OK;
2152 lsa_SetTrustedDomainInfoByName
2154 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2155 TALLOC_CTX *mem_ctx,
2156 struct lsa_SetTrustedDomainInfoByName *r)
2158 struct dcesrv_handle *policy_handle;
2159 struct lsa_policy_state *policy_state;
2160 struct ldb_message **msgs;
2163 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2164 policy_state = policy_handle->data;
2166 /* get the trusted domain object */
2167 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2168 policy_state->domain_dn,
2169 r->in.trusted_domain->string,
2170 r->in.trusted_domain->string,
2172 if (!NT_STATUS_IS_OK(nt_status)) {
2173 if (NT_STATUS_EQUAL(nt_status,
2174 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2177 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2180 return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2181 msgs[0], r->in.level, r->in.info);
2185 lsa_QueryTrustedDomainInfoByName
2187 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2188 TALLOC_CTX *mem_ctx,
2189 struct lsa_QueryTrustedDomainInfoByName *r)
2192 struct lsa_OpenTrustedDomainByName opn;
2193 struct lsa_QueryTrustedDomainInfo query;
2194 struct dcesrv_handle *h;
2196 opn.in.handle = r->in.handle;
2197 opn.in.name = *r->in.trusted_domain;
2198 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2199 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2200 if (!opn.out.trustdom_handle) {
2201 return NT_STATUS_NO_MEMORY;
2203 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2204 if (!NT_STATUS_IS_OK(status)) {
2208 /* Ensure this handle goes away at the end of this call */
2209 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2210 talloc_steal(mem_ctx, h);
2212 query.in.trustdom_handle = opn.out.trustdom_handle;
2213 query.in.level = r->in.level;
2214 query.out.info = r->out.info;
2215 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2216 if (!NT_STATUS_IS_OK(status)) {
2220 return NT_STATUS_OK;
2224 lsa_CloseTrustedDomainEx
2226 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2227 TALLOC_CTX *mem_ctx,
2228 struct lsa_CloseTrustedDomainEx *r)
2230 /* The result of a bad hair day from an IDL programmer? Not
2231 * implmented in Win2k3. You should always just lsa_Close
2233 return NT_STATUS_NOT_IMPLEMENTED;
2238 comparison function for sorting lsa_DomainInformation array
2240 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2242 return strcasecmp_m(e1->name.string, e2->name.string);
2248 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2249 struct lsa_EnumTrustDom *r)
2251 struct dcesrv_handle *policy_handle;
2252 struct lsa_DomainInfo *entries;
2253 struct lsa_policy_state *policy_state;
2254 struct ldb_message **domains;
2255 const char *attrs[] = {
2257 "securityIdentifier",
2264 *r->out.resume_handle = 0;
2266 r->out.domains->domains = NULL;
2267 r->out.domains->count = 0;
2269 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2271 policy_state = policy_handle->data;
2273 /* search for all users in this domain. This could possibly be cached and
2274 resumed based on resume_key */
2275 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2276 "objectclass=trustedDomain");
2278 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2281 /* convert to lsa_TrustInformation format */
2282 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2284 return NT_STATUS_NO_MEMORY;
2286 for (i=0;i<count;i++) {
2287 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2288 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2291 /* sort the results by name */
2292 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2294 if (*r->in.resume_handle >= count) {
2295 *r->out.resume_handle = -1;
2297 return NT_STATUS_NO_MORE_ENTRIES;
2300 /* return the rest, limit by max_size. Note that we
2301 use the w2k3 element size value of 60 */
2302 r->out.domains->count = count - *r->in.resume_handle;
2303 r->out.domains->count = MIN(r->out.domains->count,
2304 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2306 r->out.domains->domains = entries + *r->in.resume_handle;
2307 r->out.domains->count = r->out.domains->count;
2309 if (r->out.domains->count < count - *r->in.resume_handle) {
2310 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2311 return STATUS_MORE_ENTRIES;
2314 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2315 * always be larger than the previous input resume handle, in
2316 * particular when hitting the last query it is vital to set the
2317 * resume handle correctly to avoid infinite client loops, as
2318 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2319 * status is NT_STATUS_OK - gd */
2321 *r->out.resume_handle = (uint32_t)-1;
2323 return NT_STATUS_OK;
2327 comparison function for sorting lsa_DomainInformation array
2329 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2331 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2335 lsa_EnumTrustedDomainsEx
2337 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2338 struct lsa_EnumTrustedDomainsEx *r)
2340 struct dcesrv_handle *policy_handle;
2341 struct lsa_TrustDomainInfoInfoEx *entries;
2342 struct lsa_policy_state *policy_state;
2343 struct ldb_message **domains;
2344 const char *attrs[] = {
2347 "securityIdentifier",
2357 *r->out.resume_handle = 0;
2359 r->out.domains->domains = NULL;
2360 r->out.domains->count = 0;
2362 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2364 policy_state = policy_handle->data;
2366 /* search for all users in this domain. This could possibly be cached and
2367 resumed based on resume_key */
2368 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2369 "objectclass=trustedDomain");
2371 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2374 /* convert to lsa_DomainInformation format */
2375 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2377 return NT_STATUS_NO_MEMORY;
2379 for (i=0;i<count;i++) {
2380 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2381 if (!NT_STATUS_IS_OK(nt_status)) {
2386 /* sort the results by name */
2387 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2389 if (*r->in.resume_handle >= count) {
2390 *r->out.resume_handle = -1;
2392 return NT_STATUS_NO_MORE_ENTRIES;
2395 /* return the rest, limit by max_size. Note that we
2396 use the w2k3 element size value of 60 */
2397 r->out.domains->count = count - *r->in.resume_handle;
2398 r->out.domains->count = MIN(r->out.domains->count,
2399 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2401 r->out.domains->domains = entries + *r->in.resume_handle;
2402 r->out.domains->count = r->out.domains->count;
2404 if (r->out.domains->count < count - *r->in.resume_handle) {
2405 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2406 return STATUS_MORE_ENTRIES;
2409 return NT_STATUS_OK;
2416 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2417 struct lsa_OpenAccount *r)
2419 struct dcesrv_handle *h, *ah;
2420 struct lsa_policy_state *state;
2421 struct lsa_account_state *astate;
2423 ZERO_STRUCTP(r->out.acct_handle);
2425 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2429 astate = talloc(dce_call->conn, struct lsa_account_state);
2430 if (astate == NULL) {
2431 return NT_STATUS_NO_MEMORY;
2434 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2435 if (astate->account_sid == NULL) {
2436 talloc_free(astate);
2437 return NT_STATUS_NO_MEMORY;
2440 astate->policy = talloc_reference(astate, state);
2441 astate->access_mask = r->in.access_mask;
2443 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2445 talloc_free(astate);
2446 return NT_STATUS_NO_MEMORY;
2449 ah->data = talloc_steal(ah, astate);
2451 *r->out.acct_handle = ah->wire_handle;
2453 return NT_STATUS_OK;
2458 lsa_EnumPrivsAccount
2460 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2461 TALLOC_CTX *mem_ctx,
2462 struct lsa_EnumPrivsAccount *r)
2464 struct dcesrv_handle *h;
2465 struct lsa_account_state *astate;
2468 struct ldb_message **res;
2469 const char * const attrs[] = { "privilege", NULL};
2470 struct ldb_message_element *el;
2472 struct lsa_PrivilegeSet *privs;
2474 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2478 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2479 if (privs == NULL) {
2480 return NT_STATUS_NO_MEMORY;
2486 *r->out.privs = privs;
2488 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2489 if (sidstr == NULL) {
2490 return NT_STATUS_NO_MEMORY;
2493 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2494 "objectSid=%s", sidstr);
2496 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2499 return NT_STATUS_OK;
2502 el = ldb_msg_find_element(res[0], "privilege");
2503 if (el == NULL || el->num_values == 0) {
2504 return NT_STATUS_OK;
2507 privs->set = talloc_array(privs,
2508 struct lsa_LUIDAttribute, el->num_values);
2509 if (privs->set == NULL) {
2510 return NT_STATUS_NO_MEMORY;
2514 for (i=0;i<el->num_values;i++) {
2515 int id = sec_privilege_id((const char *)el->values[i].data);
2516 if (id == SEC_PRIV_INVALID) {
2517 /* Perhaps an account right, not a privilege */
2520 privs->set[j].attribute = 0;
2521 privs->set[j].luid.low = id;
2522 privs->set[j].luid.high = 0;
2528 return NT_STATUS_OK;
2532 lsa_EnumAccountRights
2534 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2535 TALLOC_CTX *mem_ctx,
2536 struct lsa_EnumAccountRights *r)
2538 struct dcesrv_handle *h;
2539 struct lsa_policy_state *state;
2542 struct ldb_message **res;
2543 const char * const attrs[] = { "privilege", NULL};
2545 struct ldb_message_element *el;
2547 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2551 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2552 if (sidstr == NULL) {
2553 return NT_STATUS_NO_MEMORY;
2556 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2557 "(&(objectSid=%s)(privilege=*))", sidstr);
2559 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2562 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2563 dom_sid_string(mem_ctx, r->in.sid),
2564 ldb_errstring(state->pdb)));
2565 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2568 el = ldb_msg_find_element(res[0], "privilege");
2569 if (el == NULL || el->num_values == 0) {
2570 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2573 r->out.rights->count = el->num_values;
2574 r->out.rights->names = talloc_array(r->out.rights,
2575 struct lsa_StringLarge, r->out.rights->count);
2576 if (r->out.rights->names == NULL) {
2577 return NT_STATUS_NO_MEMORY;
2580 for (i=0;i<el->num_values;i++) {
2581 r->out.rights->names[i].string = (const char *)el->values[i].data;
2584 return NT_STATUS_OK;
2590 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2592 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2593 TALLOC_CTX *mem_ctx,
2594 struct lsa_policy_state *state,
2596 struct dom_sid *sid,
2597 const struct lsa_RightSet *rights)
2599 const char *sidstr, *sidndrstr;
2600 struct ldb_message *msg;
2601 struct ldb_message_element *el;
2604 struct lsa_EnumAccountRights r2;
2607 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2608 SECURITY_ADMINISTRATOR) {
2609 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2610 return NT_STATUS_ACCESS_DENIED;
2613 msg = ldb_msg_new(mem_ctx);
2615 return NT_STATUS_NO_MEMORY;
2618 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2619 if (sidndrstr == NULL) {
2621 return NT_STATUS_NO_MEMORY;
2624 sidstr = dom_sid_string(msg, sid);
2625 if (sidstr == NULL) {
2627 return NT_STATUS_NO_MEMORY;
2630 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2631 if (dnstr == NULL) {
2633 return NT_STATUS_NO_MEMORY;
2636 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2637 if (msg->dn == NULL) {
2639 return NT_STATUS_NO_MEMORY;
2642 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2645 r2.in.handle = &state->handle->wire_handle;
2647 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2649 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2650 if (!NT_STATUS_IS_OK(status)) {
2651 ZERO_STRUCTP(r2.out.rights);
2655 for (i=0;i<rights->count;i++) {
2656 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2657 if (sec_right_bit(rights->names[i].string) == 0) {
2659 return NT_STATUS_NO_SUCH_PRIVILEGE;
2663 return NT_STATUS_NO_SUCH_PRIVILEGE;
2666 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2668 for (j=0;j<r2.out.rights->count;j++) {
2669 if (strcasecmp_m(r2.out.rights->names[j].string,
2670 rights->names[i].string) == 0) {
2674 if (j != r2.out.rights->count) continue;
2677 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2678 if (ret != LDB_SUCCESS) {
2680 return NT_STATUS_NO_MEMORY;
2684 el = ldb_msg_find_element(msg, "privilege");
2687 return NT_STATUS_OK;
2690 el->flags = ldb_flag;
2692 ret = ldb_modify(state->pdb, msg);
2693 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2694 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2696 return NT_STATUS_NO_MEMORY;
2698 ldb_msg_add_string(msg, "comment", "added via LSA");
2699 ret = ldb_add(state->pdb, msg);
2701 if (ret != LDB_SUCCESS) {
2702 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2704 return NT_STATUS_OK;
2706 DEBUG(3, ("Could not %s attributes from %s: %s",
2707 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2708 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2710 return NT_STATUS_UNEXPECTED_IO_ERROR;
2714 return NT_STATUS_OK;
2718 lsa_AddPrivilegesToAccount
2720 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2721 struct lsa_AddPrivilegesToAccount *r)
2723 struct lsa_RightSet rights;
2724 struct dcesrv_handle *h;
2725 struct lsa_account_state *astate;
2728 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2732 rights.count = r->in.privs->count;
2733 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2734 if (rights.names == NULL) {
2735 return NT_STATUS_NO_MEMORY;
2737 for (i=0;i<rights.count;i++) {
2738 int id = r->in.privs->set[i].luid.low;
2739 if (r->in.privs->set[i].luid.high) {
2740 return NT_STATUS_NO_SUCH_PRIVILEGE;
2742 rights.names[i].string = sec_privilege_name(id);
2743 if (rights.names[i].string == NULL) {
2744 return NT_STATUS_NO_SUCH_PRIVILEGE;
2748 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2749 LDB_FLAG_MOD_ADD, astate->account_sid,
2755 lsa_RemovePrivilegesFromAccount
2757 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2758 struct lsa_RemovePrivilegesFromAccount *r)
2760 struct lsa_RightSet *rights;
2761 struct dcesrv_handle *h;
2762 struct lsa_account_state *astate;
2765 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2769 rights = talloc(mem_ctx, struct lsa_RightSet);
2771 if (r->in.remove_all == 1 &&
2772 r->in.privs == NULL) {
2773 struct lsa_EnumAccountRights r2;
2776 r2.in.handle = &astate->policy->handle->wire_handle;
2777 r2.in.sid = astate->account_sid;
2778 r2.out.rights = rights;
2780 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2781 if (!NT_STATUS_IS_OK(status)) {
2785 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2786 LDB_FLAG_MOD_DELETE, astate->account_sid,
2790 if (r->in.remove_all != 0) {
2791 return NT_STATUS_INVALID_PARAMETER;
2794 rights->count = r->in.privs->count;
2795 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2796 if (rights->names == NULL) {
2797 return NT_STATUS_NO_MEMORY;
2799 for (i=0;i<rights->count;i++) {
2800 int id = r->in.privs->set[i].luid.low;
2801 if (r->in.privs->set[i].luid.high) {
2802 return NT_STATUS_NO_SUCH_PRIVILEGE;
2804 rights->names[i].string = sec_privilege_name(id);
2805 if (rights->names[i].string == NULL) {
2806 return NT_STATUS_NO_SUCH_PRIVILEGE;
2810 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2811 LDB_FLAG_MOD_DELETE, astate->account_sid,
2817 lsa_GetQuotasForAccount
2819 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2820 struct lsa_GetQuotasForAccount *r)
2822 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2827 lsa_SetQuotasForAccount
2829 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2830 struct lsa_SetQuotasForAccount *r)
2832 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2837 lsa_GetSystemAccessAccount
2839 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2840 struct lsa_GetSystemAccessAccount *r)
2842 struct dcesrv_handle *h;
2843 struct lsa_account_state *astate;
2846 struct ldb_message **res;
2847 const char * const attrs[] = { "privilege", NULL};
2848 struct ldb_message_element *el;
2851 *(r->out.access_mask) = 0x00000000;
2853 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2857 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2858 if (sidstr == NULL) {
2859 return NT_STATUS_NO_MEMORY;
2862 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2863 "objectSid=%s", sidstr);
2865 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2868 return NT_STATUS_OK;
2871 el = ldb_msg_find_element(res[0], "privilege");
2872 if (el == NULL || el->num_values == 0) {
2873 return NT_STATUS_OK;
2876 for (i=0;i<el->num_values;i++) {
2877 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2878 if (right_bit == 0) {
2879 /* Perhaps an privilege, not a right */
2882 *(r->out.access_mask) |= right_bit;
2885 return NT_STATUS_OK;
2890 lsa_SetSystemAccessAccount
2892 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2893 struct lsa_SetSystemAccessAccount *r)
2895 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2902 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2903 struct lsa_CreateSecret *r)
2905 struct dcesrv_handle *policy_handle;
2906 struct lsa_policy_state *policy_state;
2907 struct lsa_secret_state *secret_state;
2908 struct dcesrv_handle *handle;
2909 struct ldb_message **msgs, *msg;
2910 const char *attrs[] = {
2918 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2919 ZERO_STRUCTP(r->out.sec_handle);
2921 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2923 case SECURITY_SYSTEM:
2924 case SECURITY_ADMINISTRATOR:
2927 /* Users and annonymous are not allowed create secrets */
2928 return NT_STATUS_ACCESS_DENIED;
2931 policy_state = policy_handle->data;
2933 if (!r->in.name.string) {
2934 return NT_STATUS_INVALID_PARAMETER;
2937 secret_state = talloc(mem_ctx, struct lsa_secret_state);
2938 NT_STATUS_HAVE_NO_MEMORY(secret_state);
2939 secret_state->policy = policy_state;
2941 msg = ldb_msg_new(mem_ctx);
2943 return NT_STATUS_NO_MEMORY;
2946 if (strncmp("G$", r->in.name.string, 2) == 0) {
2949 secret_state->global = true;
2951 name = &r->in.name.string[2];
2952 if (strlen(name) == 0) {
2953 return NT_STATUS_INVALID_PARAMETER;
2956 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2957 ldb_binary_encode_string(mem_ctx, name));
2958 NT_STATUS_HAVE_NO_MEMORY(name2);
2960 /* We need to connect to the database as system, as this is one
2961 * of the rare RPC calls that must read the secrets (and this
2962 * is denied otherwise) */
2963 secret_state->sam_ldb = talloc_reference(secret_state,
2964 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));
2965 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2967 /* search for the secret record */
2968 ret = gendb_search(secret_state->sam_ldb,
2969 mem_ctx, policy_state->system_dn, &msgs, attrs,
2970 "(&(cn=%s)(objectclass=secret))",
2973 return NT_STATUS_OBJECT_NAME_COLLISION;
2977 DEBUG(0,("Failure searching for CN=%s: %s\n",
2978 name2, ldb_errstring(secret_state->sam_ldb)));
2979 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2982 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2983 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2984 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2985 return NT_STATUS_NO_MEMORY;
2988 ret = ldb_msg_add_string(msg, "cn", name2);
2989 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2991 secret_state->global = false;
2993 name = r->in.name.string;
2994 if (strlen(name) == 0) {
2995 return NT_STATUS_INVALID_PARAMETER;
2998 secret_state->sam_ldb = talloc_reference(secret_state,
2999 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3000 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3002 /* search for the secret record */
3003 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3004 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3006 "(&(cn=%s)(objectclass=secret))",
3007 ldb_binary_encode_string(mem_ctx, name));
3009 return NT_STATUS_OBJECT_NAME_COLLISION;
3013 DEBUG(0,("Failure searching for CN=%s: %s\n",
3014 name, ldb_errstring(secret_state->sam_ldb)));
3015 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3018 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3019 "cn=%s,cn=LSA Secrets", name);
3020 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3021 ret = ldb_msg_add_string(msg, "cn", name);
3022 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3025 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3026 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3028 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3029 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3031 /* create the secret */
3032 ret = ldb_add(secret_state->sam_ldb, msg);
3033 if (ret != LDB_SUCCESS) {
3034 DEBUG(0,("Failed to create secret record %s: %s\n",
3035 ldb_dn_get_linearized(msg->dn),
3036 ldb_errstring(secret_state->sam_ldb)));
3037 return NT_STATUS_ACCESS_DENIED;
3040 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3041 NT_STATUS_HAVE_NO_MEMORY(handle);
3043 handle->data = talloc_steal(handle, secret_state);
3045 secret_state->access_mask = r->in.access_mask;
3046 secret_state->policy = talloc_reference(secret_state, policy_state);
3047 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3049 *r->out.sec_handle = handle->wire_handle;
3051 return NT_STATUS_OK;
3058 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3059 struct lsa_OpenSecret *r)
3061 struct dcesrv_handle *policy_handle;
3063 struct lsa_policy_state *policy_state;
3064 struct lsa_secret_state *secret_state;
3065 struct dcesrv_handle *handle;
3066 struct ldb_message **msgs;
3067 const char *attrs[] = {
3075 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3076 ZERO_STRUCTP(r->out.sec_handle);
3077 policy_state = policy_handle->data;
3079 if (!r->in.name.string) {
3080 return NT_STATUS_INVALID_PARAMETER;
3083 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3085 case SECURITY_SYSTEM:
3086 case SECURITY_ADMINISTRATOR:
3089 /* Users and annonymous are not allowed to access secrets */
3090 return NT_STATUS_ACCESS_DENIED;
3093 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3094 if (!secret_state) {
3095 return NT_STATUS_NO_MEMORY;
3097 secret_state->policy = policy_state;
3099 if (strncmp("G$", r->in.name.string, 2) == 0) {
3100 name = &r->in.name.string[2];
3101 /* 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) */
3102 secret_state->sam_ldb = talloc_reference(secret_state,
3103 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));
3104 secret_state->global = true;
3106 if (strlen(name) < 1) {
3107 return NT_STATUS_INVALID_PARAMETER;
3110 /* search for the secret record */
3111 ret = gendb_search(secret_state->sam_ldb,
3112 mem_ctx, policy_state->system_dn, &msgs, attrs,
3113 "(&(cn=%s Secret)(objectclass=secret))",
3114 ldb_binary_encode_string(mem_ctx, name));
3116 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3120 DEBUG(0,("Found %d records matching DN %s\n", ret,
3121 ldb_dn_get_linearized(policy_state->system_dn)));
3122 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3125 secret_state->global = false;
3126 secret_state->sam_ldb = talloc_reference(secret_state,
3127 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3129 name = r->in.name.string;
3130 if (strlen(name) < 1) {
3131 return NT_STATUS_INVALID_PARAMETER;
3134 /* search for the secret record */
3135 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3136 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3138 "(&(cn=%s)(objectclass=secret))",
3139 ldb_binary_encode_string(mem_ctx, name));
3141 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3145 DEBUG(0,("Found %d records matching CN=%s\n",
3146 ret, ldb_binary_encode_string(mem_ctx, name)));
3147 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3151 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3153 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3155 return NT_STATUS_NO_MEMORY;
3158 handle->data = talloc_steal(handle, secret_state);
3160 secret_state->access_mask = r->in.access_mask;
3161 secret_state->policy = talloc_reference(secret_state, policy_state);
3163 *r->out.sec_handle = handle->wire_handle;
3165 return NT_STATUS_OK;
3172 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3173 struct lsa_SetSecret *r)
3176 struct dcesrv_handle *h;
3177 struct lsa_secret_state *secret_state;
3178 struct ldb_message *msg;
3179 DATA_BLOB session_key;
3180 DATA_BLOB crypt_secret, secret;
3183 NTSTATUS status = NT_STATUS_OK;
3185 struct timeval now = timeval_current();
3186 NTTIME nt_now = timeval_to_nttime(&now);
3188 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3190 secret_state = h->data;
3192 msg = ldb_msg_new(mem_ctx);
3194 return NT_STATUS_NO_MEMORY;
3197 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3199 return NT_STATUS_NO_MEMORY;
3201 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3202 if (!NT_STATUS_IS_OK(status)) {
3206 if (r->in.old_val) {
3208 crypt_secret.data = r->in.old_val->data;
3209 crypt_secret.length = r->in.old_val->size;
3211 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3212 if (!NT_STATUS_IS_OK(status)) {
3216 val.data = secret.data;
3217 val.length = secret.length;
3220 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3221 return NT_STATUS_NO_MEMORY;
3224 /* set old value mtime */
3225 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3226 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3227 return NT_STATUS_NO_MEMORY;
3231 /* If the old value is not set, then migrate the
3232 * current value to the old value */
3233 const struct ldb_val *old_val;
3234 NTTIME last_set_time;
3235 struct ldb_message **res;
3236 const char *attrs[] = {
3242 /* search for the secret record */
3243 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3244 secret_state->secret_dn, &res, attrs);
3246 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3250 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3251 ldb_dn_get_linearized(secret_state->secret_dn)));
3252 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3255 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3256 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3260 if (ldb_msg_add_value(msg, "priorValue",
3261 old_val, NULL) != LDB_SUCCESS) {
3262 return NT_STATUS_NO_MEMORY;
3265 if (samdb_msg_add_delete(secret_state->sam_ldb,
3266 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3267 return NT_STATUS_NO_MEMORY;
3271 /* set old value mtime */
3272 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3273 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3274 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3275 return NT_STATUS_NO_MEMORY;
3278 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3279 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3280 return NT_STATUS_NO_MEMORY;
3285 if (r->in.new_val) {
3287 crypt_secret.data = r->in.new_val->data;
3288 crypt_secret.length = r->in.new_val->size;
3290 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3291 if (!NT_STATUS_IS_OK(status)) {
3295 val.data = secret.data;
3296 val.length = secret.length;
3299 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3300 return NT_STATUS_NO_MEMORY;
3303 /* set new value mtime */
3304 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3305 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3306 return NT_STATUS_NO_MEMORY;
3309 /* NULL out the NEW value */
3310 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3311 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3312 return NT_STATUS_NO_MEMORY;
3314 if (samdb_msg_add_delete(secret_state->sam_ldb,
3315 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3316 return NT_STATUS_NO_MEMORY;
3320 /* modify the samdb record */
3321 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3322 if (ret != LDB_SUCCESS) {
3323 return dsdb_ldb_err_to_ntstatus(ret);
3326 return NT_STATUS_OK;
3333 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3334 struct lsa_QuerySecret *r)
3336 struct dcesrv_handle *h;
3337 struct lsa_secret_state *secret_state;
3338 struct ldb_message *msg;
3339 DATA_BLOB session_key;
3340 DATA_BLOB crypt_secret, secret;
3342 struct ldb_message **res;
3343 const char *attrs[] = {
3353 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3355 /* Ensure user is permitted to read this... */
3356 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3358 case SECURITY_SYSTEM:
3359 case SECURITY_ADMINISTRATOR:
3362 /* Users and annonymous are not allowed to read secrets */
3363 return NT_STATUS_ACCESS_DENIED;
3366 secret_state = h->data;
3368 /* pull all the user attributes */
3369 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3370 secret_state->secret_dn, &res, attrs);
3372 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3376 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3377 if (!NT_STATUS_IS_OK(nt_status)) {
3381 if (r->in.old_val) {
3382 const struct ldb_val *prior_val;
3383 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3384 if (!r->out.old_val) {
3385 return NT_STATUS_NO_MEMORY;
3387 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3389 if (prior_val && prior_val->length) {
3390 secret.data = prior_val->data;
3391 secret.length = prior_val->length;
3394 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3395 if (!crypt_secret.length) {
3396 return NT_STATUS_NO_MEMORY;
3398 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3399 if (!r->out.old_val->buf) {
3400 return NT_STATUS_NO_MEMORY;
3402 r->out.old_val->buf->size = crypt_secret.length;
3403 r->out.old_val->buf->length = crypt_secret.length;
3404 r->out.old_val->buf->data = crypt_secret.data;
3408 if (r->in.old_mtime) {
3409 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3410 if (!r->out.old_mtime) {
3411 return NT_STATUS_NO_MEMORY;
3413 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3416 if (r->in.new_val) {
3417 const struct ldb_val *new_val;
3418 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3419 if (!r->out.new_val) {
3420 return NT_STATUS_NO_MEMORY;
3423 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3425 if (new_val && new_val->length) {
3426 secret.data = new_val->data;
3427 secret.length = new_val->length;
3430 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3431 if (!crypt_secret.length) {
3432 return NT_STATUS_NO_MEMORY;
3434 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3435 if (!r->out.new_val->buf) {
3436 return NT_STATUS_NO_MEMORY;
3438 r->out.new_val->buf->length = crypt_secret.length;
3439 r->out.new_val->buf->size = crypt_secret.length;
3440 r->out.new_val->buf->data = crypt_secret.data;
3444 if (r->in.new_mtime) {
3445 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3446 if (!r->out.new_mtime) {
3447 return NT_STATUS_NO_MEMORY;
3449 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3452 return NT_STATUS_OK;
3459 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3460 TALLOC_CTX *mem_ctx,
3461 struct lsa_LookupPrivValue *r)
3463 struct dcesrv_handle *h;
3466 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3468 id = sec_privilege_id(r->in.name->string);
3469 if (id == SEC_PRIV_INVALID) {
3470 return NT_STATUS_NO_SUCH_PRIVILEGE;
3473 r->out.luid->low = id;
3474 r->out.luid->high = 0;
3476 return NT_STATUS_OK;
3483 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3484 TALLOC_CTX *mem_ctx,
3485 struct lsa_LookupPrivName *r)
3487 struct dcesrv_handle *h;
3488 struct lsa_StringLarge *name;
3489 const char *privname;
3491 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3493 if (r->in.luid->high != 0) {
3494 return NT_STATUS_NO_SUCH_PRIVILEGE;
3497 privname = sec_privilege_name(r->in.luid->low);
3498 if (privname == NULL) {
3499 return NT_STATUS_NO_SUCH_PRIVILEGE;
3502 name = talloc(mem_ctx, struct lsa_StringLarge);
3504 return NT_STATUS_NO_MEMORY;
3507 name->string = privname;
3509 *r->out.name = name;
3511 return NT_STATUS_OK;
3516 lsa_LookupPrivDisplayName
3518 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3519 TALLOC_CTX *mem_ctx,
3520 struct lsa_LookupPrivDisplayName *r)
3522 struct dcesrv_handle *h;
3523 struct lsa_StringLarge *disp_name = NULL;
3524 enum sec_privilege id;
3526 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3528 id = sec_privilege_id(r->in.name->string);
3529 if (id == SEC_PRIV_INVALID) {
3530 return NT_STATUS_NO_SUCH_PRIVILEGE;
3533 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3534 if (disp_name == NULL) {
3535 return NT_STATUS_NO_MEMORY;
3538 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3539 if (disp_name->string == NULL) {
3540 return NT_STATUS_INTERNAL_ERROR;
3543 *r->out.disp_name = disp_name;
3544 *r->out.returned_language_id = 0;
3546 return NT_STATUS_OK;
3551 lsa_EnumAccountsWithUserRight
3553 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3554 TALLOC_CTX *mem_ctx,
3555 struct lsa_EnumAccountsWithUserRight *r)
3557 struct dcesrv_handle *h;
3558 struct lsa_policy_state *state;
3560 struct ldb_message **res;
3561 const char * const attrs[] = { "objectSid", NULL};
3562 const char *privname;
3564 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3568 if (r->in.name == NULL) {
3569 return NT_STATUS_NO_SUCH_PRIVILEGE;
3572 privname = r->in.name->string;
3573 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3574 return NT_STATUS_NO_SUCH_PRIVILEGE;
3577 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3578 "privilege=%s", privname);
3580 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3583 return NT_STATUS_NO_MORE_ENTRIES;
3586 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3587 if (r->out.sids->sids == NULL) {
3588 return NT_STATUS_NO_MEMORY;
3590 for (i=0;i<ret;i++) {
3591 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3592 res[i], "objectSid");
3593 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3595 r->out.sids->num_sids = ret;
3597 return NT_STATUS_OK;
3602 lsa_AddAccountRights
3604 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3605 TALLOC_CTX *mem_ctx,
3606 struct lsa_AddAccountRights *r)
3608 struct dcesrv_handle *h;
3609 struct lsa_policy_state *state;
3611 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3615 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3617 r->in.sid, r->in.rights);
3622 lsa_RemoveAccountRights
3624 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3625 TALLOC_CTX *mem_ctx,
3626 struct lsa_RemoveAccountRights *r)
3628 struct dcesrv_handle *h;
3629 struct lsa_policy_state *state;
3631 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3635 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3636 LDB_FLAG_MOD_DELETE,
3637 r->in.sid, r->in.rights);
3642 lsa_StorePrivateData
3644 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3645 struct lsa_StorePrivateData *r)
3647 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3652 lsa_RetrievePrivateData
3654 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3655 struct lsa_RetrievePrivateData *r)
3657 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3664 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3665 struct lsa_GetUserName *r)
3667 enum dcerpc_transport_t transport =
3668 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3669 NTSTATUS status = NT_STATUS_OK;
3670 const char *account_name;
3671 const char *authority_name;
3672 struct lsa_String *_account_name;
3673 struct lsa_String *_authority_name = NULL;
3675 if (transport != NCACN_NP && transport != NCALRPC) {
3676 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3679 /* this is what w2k3 does */
3680 r->out.account_name = r->in.account_name;
3681 r->out.authority_name = r->in.authority_name;
3683 if (r->in.account_name
3684 && *r->in.account_name
3685 /* && *(*r->in.account_name)->string */
3687 return NT_STATUS_INVALID_PARAMETER;
3690 if (r->in.authority_name
3691 && *r->in.authority_name
3692 /* && *(*r->in.authority_name)->string */
3694 return NT_STATUS_INVALID_PARAMETER;
3697 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3698 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3700 _account_name = talloc(mem_ctx, struct lsa_String);
3701 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3702 _account_name->string = account_name;
3704 if (r->in.authority_name) {
3705 _authority_name = talloc(mem_ctx, struct lsa_String);
3706 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3707 _authority_name->string = authority_name;
3710 *r->out.account_name = _account_name;
3711 if (r->out.authority_name) {
3712 *r->out.authority_name = _authority_name;
3721 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3722 TALLOC_CTX *mem_ctx,
3723 struct lsa_SetInfoPolicy2 *r)
3725 /* need to support these */
3726 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3729 static void kdc_get_policy(struct loadparm_context *lp_ctx,
3730 struct smb_krb5_context *smb_krb5_context,
3731 struct lsa_DomainInfoKerberos *k)
3733 time_t svc_tkt_lifetime;
3734 time_t usr_tkt_lifetime;
3735 time_t renewal_lifetime;
3737 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
3739 /* Our KDC always re-validates the client */
3740 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
3742 lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
3743 &usr_tkt_lifetime, &renewal_lifetime);
3745 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
3746 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
3747 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
3748 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
3749 However in the parent function we basically just did a full
3750 krb5_context init with the only purpose of getting a global
3751 config option (the max skew), it would probably make more sense
3752 to have a lp_ or ldb global option as the samba default */
3753 if (smb_krb5_context) {
3754 unix_to_nt_time(&k->clock_skew,
3755 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
3761 lsa_QueryDomainInformationPolicy
3763 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3764 TALLOC_CTX *mem_ctx,
3765 struct lsa_QueryDomainInformationPolicy *r)
3767 union lsa_DomainInformationPolicy *info;
3769 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3771 return NT_STATUS_NO_MEMORY;
3774 switch (r->in.level) {
3775 case LSA_DOMAIN_INFO_POLICY_EFS:
3777 *r->out.info = NULL;
3778 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3779 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3781 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3782 struct smb_krb5_context *smb_krb5_context;
3783 int ret = smb_krb5_init_context(mem_ctx,
3784 dce_call->conn->dce_ctx->lp_ctx,
3788 *r->out.info = NULL;
3789 return NT_STATUS_INTERNAL_ERROR;
3791 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3794 talloc_free(smb_krb5_context);
3795 *r->out.info = info;
3796 return NT_STATUS_OK;
3800 *r->out.info = NULL;
3801 return NT_STATUS_INVALID_INFO_CLASS;
3806 lsa_SetDomInfoPolicy
3808 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3809 TALLOC_CTX *mem_ctx,
3810 struct lsa_SetDomainInformationPolicy *r)
3812 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3818 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3819 TALLOC_CTX *mem_ctx,
3820 struct lsa_TestCall *r)
3822 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3828 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3829 struct lsa_CREDRWRITE *r)
3831 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3838 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3839 struct lsa_CREDRREAD *r)
3841 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3848 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3849 struct lsa_CREDRENUMERATE *r)
3851 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3856 lsa_CREDRWRITEDOMAINCREDENTIALS
3858 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3859 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3861 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3866 lsa_CREDRREADDOMAINCREDENTIALS
3868 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3869 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3871 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3878 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3879 struct lsa_CREDRDELETE *r)
3881 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3886 lsa_CREDRGETTARGETINFO
3888 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3889 struct lsa_CREDRGETTARGETINFO *r)
3891 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3896 lsa_CREDRPROFILELOADED
3898 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3899 struct lsa_CREDRPROFILELOADED *r)
3901 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3906 lsa_CREDRGETSESSIONTYPES
3908 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3909 struct lsa_CREDRGETSESSIONTYPES *r)
3911 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3916 lsa_LSARREGISTERAUDITEVENT
3918 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3919 struct lsa_LSARREGISTERAUDITEVENT *r)
3921 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3926 lsa_LSARGENAUDITEVENT
3928 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3929 struct lsa_LSARGENAUDITEVENT *r)
3931 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3936 lsa_LSARUNREGISTERAUDITEVENT
3938 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3939 struct lsa_LSARUNREGISTERAUDITEVENT *r)
3941 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3946 lsa_lsaRQueryForestTrustInformation
3948 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3949 struct lsa_lsaRQueryForestTrustInformation *r)
3951 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3954 #define DNS_CMP_MATCH 0
3955 #define DNS_CMP_FIRST_IS_CHILD 1
3956 #define DNS_CMP_SECOND_IS_CHILD 2
3957 #define DNS_CMP_NO_MATCH 3
3959 /* this function assumes names are well formed DNS names.
3960 * it doesn't validate them */
3961 static int dns_cmp(const char *s1, size_t l1,
3962 const char *s2, size_t l2)
3964 const char *p1, *p2;
3969 if (strcasecmp_m(s1, s2) == 0) {
3970 return DNS_CMP_MATCH;
3972 return DNS_CMP_NO_MATCH;
3980 cret = DNS_CMP_FIRST_IS_CHILD;
3986 cret = DNS_CMP_SECOND_IS_CHILD;
3989 if (p1[t1 - t2 - 1] != '.') {
3990 return DNS_CMP_NO_MATCH;
3993 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3997 return DNS_CMP_NO_MATCH;
4000 /* decode all TDOs forest trust info blobs */
4001 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
4002 struct ldb_message *msg,
4003 struct ForestTrustInfo *info)
4005 const struct ldb_val *ft_blob;
4006 enum ndr_err_code ndr_err;
4008 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
4009 if (!ft_blob || !ft_blob->data) {
4010 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4012 /* ldb_val is equivalent to DATA_BLOB */
4013 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
4014 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
4015 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4016 return NT_STATUS_INVALID_DOMAIN_STATE;
4019 return NT_STATUS_OK;
4022 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
4023 struct ForestTrustInfo *fti)
4025 struct ForestTrustDataDomainInfo *info;
4026 struct ForestTrustInfoRecord *rec;
4030 fti->records = talloc_array(fti,
4031 struct ForestTrustInfoRecordArmor, 2);
4032 if (!fti->records) {
4033 return NT_STATUS_NO_MEMORY;
4037 rec = &fti->records[0].record;
4041 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
4043 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
4044 if (!rec->data.name.string) {
4045 return NT_STATUS_NO_MEMORY;
4047 rec->data.name.size = strlen(rec->data.name.string);
4050 rec = &fti->records[1].record;
4054 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
4056 info = &rec->data.info;
4058 info->sid = *ps->domain_sid;
4059 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
4060 if (!info->dns_name.string) {
4061 return NT_STATUS_NO_MEMORY;
4063 info->dns_name.size = strlen(info->dns_name.string);
4064 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
4065 if (!info->netbios_name.string) {
4066 return NT_STATUS_NO_MEMORY;
4068 info->netbios_name.size = strlen(info->netbios_name.string);
4070 return NT_STATUS_OK;
4073 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
4074 struct lsa_ForestTrustInformation *lfti,
4075 struct ForestTrustInfo *fti)
4077 struct lsa_ForestTrustRecord *lrec;
4078 struct ForestTrustInfoRecord *rec;
4079 struct lsa_StringLarge *tln;
4080 struct lsa_ForestTrustDomainInfo *info;
4084 fti->count = lfti->count;
4085 fti->records = talloc_array(mem_ctx,
4086 struct ForestTrustInfoRecordArmor,
4088 if (!fti->records) {
4089 return NT_STATUS_NO_MEMORY;
4091 for (i = 0; i < fti->count; i++) {
4092 lrec = lfti->entries[i];
4093 rec = &fti->records[i].record;
4095 rec->flags = lrec->flags;
4096 rec->timestamp = lrec->time;
4097 rec->type = lrec->type;
4099 switch (lrec->type) {
4100 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4101 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4102 tln = &lrec->forest_trust_data.top_level_name;
4103 rec->data.name.string =
4104 talloc_strdup(mem_ctx, tln->string);
4105 if (!rec->data.name.string) {
4106 return NT_STATUS_NO_MEMORY;
4108 rec->data.name.size = strlen(rec->data.name.string);
4110 case LSA_FOREST_TRUST_DOMAIN_INFO:
4111 info = &lrec->forest_trust_data.domain_info;
4112 rec->data.info.sid = *info->domain_sid;
4113 rec->data.info.dns_name.string =
4114 talloc_strdup(mem_ctx,
4115 info->dns_domain_name.string);
4116 if (!rec->data.info.dns_name.string) {
4117 return NT_STATUS_NO_MEMORY;
4119 rec->data.info.dns_name.size =
4120 strlen(rec->data.info.dns_name.string);
4121 rec->data.info.netbios_name.string =
4122 talloc_strdup(mem_ctx,
4123 info->netbios_domain_name.string);
4124 if (!rec->data.info.netbios_name.string) {
4125 return NT_STATUS_NO_MEMORY;
4127 rec->data.info.netbios_name.size =
4128 strlen(rec->data.info.netbios_name.string);
4131 return NT_STATUS_INVALID_DOMAIN_STATE;
4135 return NT_STATUS_OK;
4138 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4139 uint32_t idx, uint32_t collision_type,
4140 uint32_t conflict_type, const char *tdo_name);
4142 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4143 const char *tdo_name,
4144 struct ForestTrustInfo *tdo_fti,
4145 struct ForestTrustInfo *new_fti,
4146 struct lsa_ForestTrustCollisionInfo *c_info)
4148 struct ForestTrustInfoRecord *nrec;
4149 struct ForestTrustInfoRecord *trec;
4150 const char *dns_name;
4151 const char *nb_name;
4152 struct dom_sid *sid;
4156 NTSTATUS nt_status = NT_STATUS_OK;
4157 uint32_t new_fti_idx;
4159 /* use always TDO type, until we understand when Xref can be used */
4160 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4168 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4170 nrec = &new_fti->records[new_fti_idx].record;
4173 tln_conflict = false;
4174 sid_conflict = false;
4175 nb_conflict = false;
4178 switch (nrec->type) {
4179 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4180 /* exclusions do not conflict by definition */
4183 case FOREST_TRUST_TOP_LEVEL_NAME:
4184 dns_name = nrec->data.name.string;
4185 dns_len = nrec->data.name.size;
4188 case LSA_FOREST_TRUST_DOMAIN_INFO:
4189 dns_name = nrec->data.info.dns_name.string;
4190 dns_len = nrec->data.info.dns_name.size;
4191 nb_name = nrec->data.info.netbios_name.string;
4192 sid = &nrec->data.info.sid;
4196 if (!dns_name) continue;
4198 /* check if this is already taken and not excluded */
4199 for (i = 0; i < tdo_fti->count; i++) {
4200 trec = &tdo_fti->records[i].record;
4202 switch (trec->type) {
4203 case FOREST_TRUST_TOP_LEVEL_NAME:
4205 tname = trec->data.name.string;
4206 tlen = trec->data.name.size;
4208 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4210 tname = trec->data.name.string;
4211 tlen = trec->data.name.size;
4213 case FOREST_TRUST_DOMAIN_INFO:
4215 tname = trec->data.info.dns_name.string;
4216 tlen = trec->data.info.dns_name.size;
4218 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4221 /* if it matches exclusion,
4222 * it doesn't conflict */
4228 case DNS_CMP_FIRST_IS_CHILD:
4229 case DNS_CMP_SECOND_IS_CHILD:
4230 tln_conflict = true;
4236 /* explicit exclusion, no dns name conflict here */
4238 tln_conflict = false;
4241 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4245 /* also test for domain info */
4246 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4247 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4248 sid_conflict = true;
4250 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4251 (nb_name != NULL) &&
4252 strcasecmp_m(trec->data.info.netbios_name.string,
4259 nt_status = add_collision(c_info, new_fti_idx,
4261 LSA_TLN_DISABLED_CONFLICT,
4263 if (!NT_STATUS_IS_OK(nt_status)) {
4268 nt_status = add_collision(c_info, new_fti_idx,
4270 LSA_SID_DISABLED_CONFLICT,
4272 if (!NT_STATUS_IS_OK(nt_status)) {
4277 nt_status = add_collision(c_info, new_fti_idx,
4279 LSA_NB_DISABLED_CONFLICT,
4281 if (!NT_STATUS_IS_OK(nt_status)) {
4291 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4292 uint32_t idx, uint32_t collision_type,
4293 uint32_t conflict_type, const char *tdo_name)
4295 struct lsa_ForestTrustCollisionRecord **es;
4296 uint32_t i = c_info->count;
4298 es = talloc_realloc(c_info, c_info->entries,
4299 struct lsa_ForestTrustCollisionRecord *, i + 1);
4301 return NT_STATUS_NO_MEMORY;
4303 c_info->entries = es;
4304 c_info->count = i + 1;
4306 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4308 return NT_STATUS_NO_MEMORY;
4312 es[i]->type = collision_type;
4313 es[i]->flags.flags = conflict_type;
4314 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4315 if (!es[i]->name.string) {
4316 return NT_STATUS_NO_MEMORY;
4318 es[i]->name.size = strlen(es[i]->name.string);
4320 return NT_STATUS_OK;
4324 lsa_lsaRSetForestTrustInformation
4326 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4327 TALLOC_CTX *mem_ctx,
4328 struct lsa_lsaRSetForestTrustInformation *r)
4330 struct dcesrv_handle *h;
4331 struct lsa_policy_state *p_state;
4332 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4333 "msDS-TrustForestTrustInfo", NULL };
4334 struct ldb_message **dom_res = NULL;
4335 struct ldb_dn *tdo_dn;
4336 struct ldb_message *msg;
4338 const char *td_name;
4339 uint32_t trust_attributes;
4340 struct lsa_ForestTrustCollisionInfo *c_info;
4341 struct ForestTrustInfo *nfti;
4342 struct ForestTrustInfo *fti;
4344 enum ndr_err_code ndr_err;
4349 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4353 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4354 return NT_STATUS_INVALID_DOMAIN_STATE;
4357 /* abort if we are not a PDC */
4358 if (!samdb_is_pdc(p_state->sam_ldb)) {
4359 return NT_STATUS_INVALID_DOMAIN_ROLE;
4362 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4363 if (ret == LDB_SUCCESS && am_rodc) {
4364 return NT_STATUS_NO_SUCH_DOMAIN;
4367 /* check caller has TRUSTED_SET_AUTH */
4369 /* fetch all trusted domain objects */
4370 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4372 &dom_res, trust_attrs,
4373 "(objectclass=trustedDomain)");
4375 return NT_STATUS_NO_SUCH_DOMAIN;
4378 for (i = 0; i < num_res; i++) {
4379 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4380 "trustPartner", NULL);
4382 return NT_STATUS_INVALID_DOMAIN_STATE;
4384 if (strcasecmp_m(td_name,
4385 r->in.trusted_domain_name->string) == 0) {
4390 return NT_STATUS_NO_SUCH_DOMAIN;
4393 tdo_dn = dom_res[i]->dn;
4395 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4396 "trustAttributes", 0);
4397 if (!(trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4398 return NT_STATUS_INVALID_PARAMETER;
4401 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4402 return NT_STATUS_INVALID_PARAMETER;
4405 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4407 return NT_STATUS_NO_MEMORY;
4410 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4411 if (!NT_STATUS_IS_OK(nt_status)) {
4415 c_info = talloc_zero(r->out.collision_info,
4416 struct lsa_ForestTrustCollisionInfo);
4418 return NT_STATUS_NO_MEMORY;
4421 /* first check own info, then other domains */
4422 fti = talloc(mem_ctx, struct ForestTrustInfo);
4424 return NT_STATUS_NO_MEMORY;
4427 nt_status = own_ft_info(p_state, fti);
4428 if (!NT_STATUS_IS_OK(nt_status)) {
4432 nt_status = check_ft_info(c_info, p_state->domain_dns,
4434 if (!NT_STATUS_IS_OK(nt_status)) {
4438 for (i = 0; i < num_res; i++) {
4439 fti = talloc(mem_ctx, struct ForestTrustInfo);
4441 return NT_STATUS_NO_MEMORY;
4444 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4445 if (!NT_STATUS_IS_OK(nt_status)) {
4446 if (NT_STATUS_EQUAL(nt_status,
4447 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4453 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4454 "trustPartner", NULL);
4456 return NT_STATUS_INVALID_DOMAIN_STATE;
4459 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4460 if (!NT_STATUS_IS_OK(nt_status)) {
4465 *r->out.collision_info = c_info;
4467 if (r->in.check_only != 0) {
4468 return NT_STATUS_OK;
4471 /* not just a check, write info back */
4473 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4474 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4475 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4476 return NT_STATUS_INVALID_PARAMETER;
4479 msg = ldb_msg_new(mem_ctx);
4481 return NT_STATUS_NO_MEMORY;
4484 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4486 return NT_STATUS_NO_MEMORY;
4489 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4490 LDB_FLAG_MOD_REPLACE, NULL);
4491 if (ret != LDB_SUCCESS) {
4492 return NT_STATUS_NO_MEMORY;
4494 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4496 if (ret != LDB_SUCCESS) {
4497 return NT_STATUS_NO_MEMORY;
4500 ret = ldb_modify(p_state->sam_ldb, msg);
4501 if (ret != LDB_SUCCESS) {
4502 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4503 ldb_errstring(p_state->sam_ldb)));
4506 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4507 return NT_STATUS_ACCESS_DENIED;
4509 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4513 return NT_STATUS_OK;
4519 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4520 struct lsa_CREDRRENAME *r)
4522 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4528 lsa_LSAROPENPOLICYSCE
4530 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4531 struct lsa_LSAROPENPOLICYSCE *r)
4533 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4538 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4540 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4541 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4543 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4548 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4550 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4551 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4553 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4558 lsa_LSARADTREPORTSECURITYEVENT
4560 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4561 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4563 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4567 /* include the generated boilerplate */
4568 #include "librpc/gen_ndr/ndr_lsa_s.c"
4572 /*****************************************
4573 NOTE! The remaining calls below were
4574 removed in w2k3, so the DCESRV_FAULT()
4575 replies are the correct implementation. Do
4576 not try and fill these in with anything else
4577 ******************************************/
4580 dssetup_DsRoleDnsNameToFlatName
4582 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4583 struct dssetup_DsRoleDnsNameToFlatName *r)
4585 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4590 dssetup_DsRoleDcAsDc
4592 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4593 struct dssetup_DsRoleDcAsDc *r)
4595 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4600 dssetup_DsRoleDcAsReplica
4602 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4603 struct dssetup_DsRoleDcAsReplica *r)
4605 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4610 dssetup_DsRoleDemoteDc
4612 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4613 struct dssetup_DsRoleDemoteDc *r)
4615 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4620 dssetup_DsRoleGetDcOperationProgress
4622 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4623 struct dssetup_DsRoleGetDcOperationProgress *r)
4625 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4630 dssetup_DsRoleGetDcOperationResults
4632 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4633 struct dssetup_DsRoleGetDcOperationResults *r)
4635 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4640 dssetup_DsRoleCancel
4642 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4643 struct dssetup_DsRoleCancel *r)
4645 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4650 dssetup_DsRoleServerSaveStateForUpgrade
4652 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4653 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4655 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4660 dssetup_DsRoleUpgradeDownlevelServer
4662 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4663 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4665 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4670 dssetup_DsRoleAbortDownlevelServerUpgrade
4672 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4673 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4675 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4679 /* include the generated boilerplate */
4680 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4682 NTSTATUS dcerpc_server_lsa_init(void)
4686 ret = dcerpc_server_dssetup_init();
4687 if (!NT_STATUS_IS_OK(ret)) {
4690 ret = dcerpc_server_lsarpc_init();
4691 if (!NT_STATUS_IS_OK(ret)) {