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)) {
1772 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1775 info_ex->trust_direction,
1777 if (!NT_STATUS_IS_OK(nt_status)) {
1781 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1782 if (auth_info != NULL && trustAuthIncoming.length > 0) {
1783 add_incoming = true;
1786 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1787 if (auth_info != NULL && trustAuthOutgoing.length > 0) {
1788 add_outgoing = true;
1792 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1793 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1794 del_incoming = true;
1796 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1797 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1798 del_outgoing = true;
1801 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1802 if (origtype == -1 || origtype != info_ex->trust_type) {
1803 DEBUG(1, ("Attempted to change trust type! "
1804 "Operation not handled\n"));
1805 return NT_STATUS_INVALID_PARAMETER;
1808 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1811 info_ex->trust_attributes,
1813 if (!NT_STATUS_IS_OK(nt_status)) {
1816 /* TODO: check forestFunctionality from ldb opaque */
1817 /* TODO: check what is set makes sense */
1818 /* for now refuse changes */
1819 if (origattrs == -1 ||
1820 origattrs != info_ex->trust_attributes) {
1821 DEBUG(1, ("Attempted to change trust attributes! "
1822 "Operation not handled\n"));
1823 return NT_STATUS_INVALID_PARAMETER;
1828 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1830 "msDS-SupportedEncryptionTypes",
1832 if (!NT_STATUS_IS_OK(nt_status)) {
1837 if (add_incoming || del_incoming) {
1838 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1839 LDB_FLAG_MOD_REPLACE, NULL);
1840 if (ret != LDB_SUCCESS) {
1841 return NT_STATUS_NO_MEMORY;
1844 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1845 &trustAuthIncoming, NULL);
1846 if (ret != LDB_SUCCESS) {
1847 return NT_STATUS_NO_MEMORY;
1851 if (add_outgoing || del_outgoing) {
1852 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1853 LDB_FLAG_MOD_REPLACE, NULL);
1854 if (ret != LDB_SUCCESS) {
1855 return NT_STATUS_NO_MEMORY;
1858 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1859 &trustAuthOutgoing, NULL);
1860 if (ret != LDB_SUCCESS) {
1861 return NT_STATUS_NO_MEMORY;
1866 /* start transaction */
1867 ret = ldb_transaction_start(p_state->sam_ldb);
1868 if (ret != LDB_SUCCESS) {
1869 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1871 in_transaction = true;
1873 if (msg->num_elements) {
1874 ret = ldb_modify(p_state->sam_ldb, msg);
1875 if (ret != LDB_SUCCESS) {
1876 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1877 ldb_dn_get_linearized(msg->dn),
1878 ldb_errstring(p_state->sam_ldb)));
1879 nt_status = dsdb_ldb_err_to_ntstatus(ret);
1884 if (add_incoming || del_incoming) {
1885 const char *netbios_name;
1887 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1889 if (!netbios_name) {
1890 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1894 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
1895 nt_status = update_trust_user(mem_ctx,
1901 if (!NT_STATUS_IS_OK(nt_status)) {
1906 /* ok, all fine, commit transaction and return */
1907 ret = ldb_transaction_commit(p_state->sam_ldb);
1908 if (ret != LDB_SUCCESS) {
1909 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1911 in_transaction = false;
1913 nt_status = NT_STATUS_OK;
1916 if (in_transaction) {
1917 ldb_transaction_cancel(p_state->sam_ldb);
1923 lsa_SetInfomrationTrustedDomain
1925 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1926 struct dcesrv_call_state *dce_call,
1927 TALLOC_CTX *mem_ctx,
1928 struct lsa_SetInformationTrustedDomain *r)
1930 struct dcesrv_handle *h;
1931 struct lsa_trusted_domain_state *td_state;
1932 struct ldb_message **msgs;
1935 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1936 LSA_HANDLE_TRUSTED_DOMAIN);
1938 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1940 /* get the trusted domain object */
1941 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1942 td_state->trusted_domain_dn,
1943 NULL, NULL, NULL, &msgs);
1944 if (!NT_STATUS_IS_OK(nt_status)) {
1945 if (NT_STATUS_EQUAL(nt_status,
1946 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1949 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1952 return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
1953 msgs[0], r->in.level, r->in.info);
1958 lsa_DeleteTrustedDomain
1960 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1961 struct lsa_DeleteTrustedDomain *r)
1964 struct lsa_OpenTrustedDomain opn;
1965 struct lsa_DeleteObject del;
1966 struct dcesrv_handle *h;
1968 opn.in.handle = r->in.handle;
1969 opn.in.sid = r->in.dom_sid;
1970 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1971 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1972 if (!opn.out.trustdom_handle) {
1973 return NT_STATUS_NO_MEMORY;
1975 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1976 if (!NT_STATUS_IS_OK(status)) {
1980 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1981 talloc_steal(mem_ctx, h);
1983 del.in.handle = opn.out.trustdom_handle;
1984 del.out.handle = opn.out.trustdom_handle;
1985 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1986 if (!NT_STATUS_IS_OK(status)) {
1989 return NT_STATUS_OK;
1992 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
1993 struct ldb_message *msg,
1994 struct lsa_TrustDomainInfoInfoEx *info_ex)
1996 info_ex->domain_name.string
1997 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1998 info_ex->netbios_name.string
1999 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2001 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2002 info_ex->trust_direction
2003 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2005 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2006 info_ex->trust_attributes
2007 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2008 return NT_STATUS_OK;
2012 lsa_QueryTrustedDomainInfo
2014 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2015 struct lsa_QueryTrustedDomainInfo *r)
2017 union lsa_TrustedDomainInfo *info = NULL;
2018 struct dcesrv_handle *h;
2019 struct lsa_trusted_domain_state *trusted_domain_state;
2020 struct ldb_message *msg;
2022 struct ldb_message **res;
2023 const char *attrs[] = {
2026 "securityIdentifier",
2030 "msDs-supportedEncryptionTypes",
2034 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2036 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2038 /* pull all the user attributes */
2039 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2040 trusted_domain_state->trusted_domain_dn, &res, attrs);
2042 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2046 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2048 return NT_STATUS_NO_MEMORY;
2050 *r->out.info = info;
2052 switch (r->in.level) {
2053 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2054 info->name.netbios_name.string
2055 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2057 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2058 info->posix_offset.posix_offset
2059 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2061 #if 0 /* Win2k3 doesn't implement this */
2062 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2063 r->out.info->info_basic.netbios_name.string
2064 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2065 r->out.info->info_basic.sid
2066 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2069 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2070 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2072 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2073 ZERO_STRUCT(info->full_info);
2074 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2075 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2076 ZERO_STRUCT(info->full_info2_internal);
2077 info->full_info2_internal.posix_offset.posix_offset
2078 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2079 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2081 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2082 info->enc_types.enc_types
2083 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2086 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2087 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2088 /* oops, we don't want to return the info after all */
2090 *r->out.info = NULL;
2091 return NT_STATUS_INVALID_PARAMETER;
2093 /* oops, we don't want to return the info after all */
2095 *r->out.info = NULL;
2096 return NT_STATUS_INVALID_INFO_CLASS;
2099 return NT_STATUS_OK;
2104 lsa_QueryTrustedDomainInfoBySid
2106 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2107 struct lsa_QueryTrustedDomainInfoBySid *r)
2110 struct lsa_OpenTrustedDomain opn;
2111 struct lsa_QueryTrustedDomainInfo query;
2112 struct dcesrv_handle *h;
2114 opn.in.handle = r->in.handle;
2115 opn.in.sid = r->in.dom_sid;
2116 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2117 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2118 if (!opn.out.trustdom_handle) {
2119 return NT_STATUS_NO_MEMORY;
2121 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2122 if (!NT_STATUS_IS_OK(status)) {
2126 /* Ensure this handle goes away at the end of this call */
2127 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2128 talloc_steal(mem_ctx, h);
2130 query.in.trustdom_handle = opn.out.trustdom_handle;
2131 query.in.level = r->in.level;
2132 query.out.info = r->out.info;
2133 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2134 if (!NT_STATUS_IS_OK(status)) {
2138 return NT_STATUS_OK;
2142 lsa_SetTrustedDomainInfoByName
2144 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2145 TALLOC_CTX *mem_ctx,
2146 struct lsa_SetTrustedDomainInfoByName *r)
2148 struct dcesrv_handle *policy_handle;
2149 struct lsa_policy_state *policy_state;
2150 struct ldb_message **msgs;
2153 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2154 policy_state = policy_handle->data;
2156 /* get the trusted domain object */
2157 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2158 policy_state->domain_dn,
2159 r->in.trusted_domain->string,
2160 r->in.trusted_domain->string,
2162 if (!NT_STATUS_IS_OK(nt_status)) {
2163 if (NT_STATUS_EQUAL(nt_status,
2164 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2167 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2170 return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2171 msgs[0], r->in.level, r->in.info);
2175 lsa_QueryTrustedDomainInfoByName
2177 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2178 TALLOC_CTX *mem_ctx,
2179 struct lsa_QueryTrustedDomainInfoByName *r)
2182 struct lsa_OpenTrustedDomainByName opn;
2183 struct lsa_QueryTrustedDomainInfo query;
2184 struct dcesrv_handle *h;
2186 opn.in.handle = r->in.handle;
2187 opn.in.name = *r->in.trusted_domain;
2188 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2189 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2190 if (!opn.out.trustdom_handle) {
2191 return NT_STATUS_NO_MEMORY;
2193 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2194 if (!NT_STATUS_IS_OK(status)) {
2198 /* Ensure this handle goes away at the end of this call */
2199 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2200 talloc_steal(mem_ctx, h);
2202 query.in.trustdom_handle = opn.out.trustdom_handle;
2203 query.in.level = r->in.level;
2204 query.out.info = r->out.info;
2205 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2206 if (!NT_STATUS_IS_OK(status)) {
2210 return NT_STATUS_OK;
2214 lsa_CloseTrustedDomainEx
2216 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2217 TALLOC_CTX *mem_ctx,
2218 struct lsa_CloseTrustedDomainEx *r)
2220 /* The result of a bad hair day from an IDL programmer? Not
2221 * implmented in Win2k3. You should always just lsa_Close
2223 return NT_STATUS_NOT_IMPLEMENTED;
2228 comparison function for sorting lsa_DomainInformation array
2230 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2232 return strcasecmp_m(e1->name.string, e2->name.string);
2238 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2239 struct lsa_EnumTrustDom *r)
2241 struct dcesrv_handle *policy_handle;
2242 struct lsa_DomainInfo *entries;
2243 struct lsa_policy_state *policy_state;
2244 struct ldb_message **domains;
2245 const char *attrs[] = {
2247 "securityIdentifier",
2254 *r->out.resume_handle = 0;
2256 r->out.domains->domains = NULL;
2257 r->out.domains->count = 0;
2259 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2261 policy_state = policy_handle->data;
2263 /* search for all users in this domain. This could possibly be cached and
2264 resumed based on resume_key */
2265 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2266 "objectclass=trustedDomain");
2268 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2271 /* convert to lsa_TrustInformation format */
2272 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2274 return NT_STATUS_NO_MEMORY;
2276 for (i=0;i<count;i++) {
2277 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2278 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2281 /* sort the results by name */
2282 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2284 if (*r->in.resume_handle >= count) {
2285 *r->out.resume_handle = -1;
2287 return NT_STATUS_NO_MORE_ENTRIES;
2290 /* return the rest, limit by max_size. Note that we
2291 use the w2k3 element size value of 60 */
2292 r->out.domains->count = count - *r->in.resume_handle;
2293 r->out.domains->count = MIN(r->out.domains->count,
2294 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2296 r->out.domains->domains = entries + *r->in.resume_handle;
2297 r->out.domains->count = r->out.domains->count;
2299 if (r->out.domains->count < count - *r->in.resume_handle) {
2300 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2301 return STATUS_MORE_ENTRIES;
2304 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2305 * always be larger than the previous input resume handle, in
2306 * particular when hitting the last query it is vital to set the
2307 * resume handle correctly to avoid infinite client loops, as
2308 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2309 * status is NT_STATUS_OK - gd */
2311 *r->out.resume_handle = (uint32_t)-1;
2313 return NT_STATUS_OK;
2317 comparison function for sorting lsa_DomainInformation array
2319 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2321 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2325 lsa_EnumTrustedDomainsEx
2327 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2328 struct lsa_EnumTrustedDomainsEx *r)
2330 struct dcesrv_handle *policy_handle;
2331 struct lsa_TrustDomainInfoInfoEx *entries;
2332 struct lsa_policy_state *policy_state;
2333 struct ldb_message **domains;
2334 const char *attrs[] = {
2337 "securityIdentifier",
2347 *r->out.resume_handle = 0;
2349 r->out.domains->domains = NULL;
2350 r->out.domains->count = 0;
2352 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2354 policy_state = policy_handle->data;
2356 /* search for all users in this domain. This could possibly be cached and
2357 resumed based on resume_key */
2358 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2359 "objectclass=trustedDomain");
2361 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2364 /* convert to lsa_DomainInformation format */
2365 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2367 return NT_STATUS_NO_MEMORY;
2369 for (i=0;i<count;i++) {
2370 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2371 if (!NT_STATUS_IS_OK(nt_status)) {
2376 /* sort the results by name */
2377 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2379 if (*r->in.resume_handle >= count) {
2380 *r->out.resume_handle = -1;
2382 return NT_STATUS_NO_MORE_ENTRIES;
2385 /* return the rest, limit by max_size. Note that we
2386 use the w2k3 element size value of 60 */
2387 r->out.domains->count = count - *r->in.resume_handle;
2388 r->out.domains->count = MIN(r->out.domains->count,
2389 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2391 r->out.domains->domains = entries + *r->in.resume_handle;
2392 r->out.domains->count = r->out.domains->count;
2394 if (r->out.domains->count < count - *r->in.resume_handle) {
2395 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2396 return STATUS_MORE_ENTRIES;
2399 return NT_STATUS_OK;
2406 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2407 struct lsa_OpenAccount *r)
2409 struct dcesrv_handle *h, *ah;
2410 struct lsa_policy_state *state;
2411 struct lsa_account_state *astate;
2413 ZERO_STRUCTP(r->out.acct_handle);
2415 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2419 astate = talloc(dce_call->conn, struct lsa_account_state);
2420 if (astate == NULL) {
2421 return NT_STATUS_NO_MEMORY;
2424 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2425 if (astate->account_sid == NULL) {
2426 talloc_free(astate);
2427 return NT_STATUS_NO_MEMORY;
2430 astate->policy = talloc_reference(astate, state);
2431 astate->access_mask = r->in.access_mask;
2433 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2435 talloc_free(astate);
2436 return NT_STATUS_NO_MEMORY;
2439 ah->data = talloc_steal(ah, astate);
2441 *r->out.acct_handle = ah->wire_handle;
2443 return NT_STATUS_OK;
2448 lsa_EnumPrivsAccount
2450 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2451 TALLOC_CTX *mem_ctx,
2452 struct lsa_EnumPrivsAccount *r)
2454 struct dcesrv_handle *h;
2455 struct lsa_account_state *astate;
2458 struct ldb_message **res;
2459 const char * const attrs[] = { "privilege", NULL};
2460 struct ldb_message_element *el;
2462 struct lsa_PrivilegeSet *privs;
2464 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2468 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2469 if (privs == NULL) {
2470 return NT_STATUS_NO_MEMORY;
2476 *r->out.privs = privs;
2478 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2479 if (sidstr == NULL) {
2480 return NT_STATUS_NO_MEMORY;
2483 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2484 "objectSid=%s", sidstr);
2486 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2489 return NT_STATUS_OK;
2492 el = ldb_msg_find_element(res[0], "privilege");
2493 if (el == NULL || el->num_values == 0) {
2494 return NT_STATUS_OK;
2497 privs->set = talloc_array(privs,
2498 struct lsa_LUIDAttribute, el->num_values);
2499 if (privs->set == NULL) {
2500 return NT_STATUS_NO_MEMORY;
2504 for (i=0;i<el->num_values;i++) {
2505 int id = sec_privilege_id((const char *)el->values[i].data);
2506 if (id == SEC_PRIV_INVALID) {
2507 /* Perhaps an account right, not a privilege */
2510 privs->set[j].attribute = 0;
2511 privs->set[j].luid.low = id;
2512 privs->set[j].luid.high = 0;
2518 return NT_STATUS_OK;
2522 lsa_EnumAccountRights
2524 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2525 TALLOC_CTX *mem_ctx,
2526 struct lsa_EnumAccountRights *r)
2528 struct dcesrv_handle *h;
2529 struct lsa_policy_state *state;
2532 struct ldb_message **res;
2533 const char * const attrs[] = { "privilege", NULL};
2535 struct ldb_message_element *el;
2537 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2541 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2542 if (sidstr == NULL) {
2543 return NT_STATUS_NO_MEMORY;
2546 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2547 "(&(objectSid=%s)(privilege=*))", sidstr);
2549 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2552 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2553 dom_sid_string(mem_ctx, r->in.sid),
2554 ldb_errstring(state->pdb)));
2555 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2558 el = ldb_msg_find_element(res[0], "privilege");
2559 if (el == NULL || el->num_values == 0) {
2560 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2563 r->out.rights->count = el->num_values;
2564 r->out.rights->names = talloc_array(r->out.rights,
2565 struct lsa_StringLarge, r->out.rights->count);
2566 if (r->out.rights->names == NULL) {
2567 return NT_STATUS_NO_MEMORY;
2570 for (i=0;i<el->num_values;i++) {
2571 r->out.rights->names[i].string = (const char *)el->values[i].data;
2574 return NT_STATUS_OK;
2580 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2582 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2583 TALLOC_CTX *mem_ctx,
2584 struct lsa_policy_state *state,
2586 struct dom_sid *sid,
2587 const struct lsa_RightSet *rights)
2589 const char *sidstr, *sidndrstr;
2590 struct ldb_message *msg;
2591 struct ldb_message_element *el;
2594 struct lsa_EnumAccountRights r2;
2597 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2598 SECURITY_ADMINISTRATOR) {
2599 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2600 return NT_STATUS_ACCESS_DENIED;
2603 msg = ldb_msg_new(mem_ctx);
2605 return NT_STATUS_NO_MEMORY;
2608 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2609 if (sidndrstr == NULL) {
2611 return NT_STATUS_NO_MEMORY;
2614 sidstr = dom_sid_string(msg, sid);
2615 if (sidstr == NULL) {
2617 return NT_STATUS_NO_MEMORY;
2620 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2621 if (dnstr == NULL) {
2623 return NT_STATUS_NO_MEMORY;
2626 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2627 if (msg->dn == NULL) {
2629 return NT_STATUS_NO_MEMORY;
2632 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2635 r2.in.handle = &state->handle->wire_handle;
2637 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2639 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2640 if (!NT_STATUS_IS_OK(status)) {
2641 ZERO_STRUCTP(r2.out.rights);
2645 for (i=0;i<rights->count;i++) {
2646 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2647 if (sec_right_bit(rights->names[i].string) == 0) {
2649 return NT_STATUS_NO_SUCH_PRIVILEGE;
2653 return NT_STATUS_NO_SUCH_PRIVILEGE;
2656 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2658 for (j=0;j<r2.out.rights->count;j++) {
2659 if (strcasecmp_m(r2.out.rights->names[j].string,
2660 rights->names[i].string) == 0) {
2664 if (j != r2.out.rights->count) continue;
2667 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2668 if (ret != LDB_SUCCESS) {
2670 return NT_STATUS_NO_MEMORY;
2674 el = ldb_msg_find_element(msg, "privilege");
2677 return NT_STATUS_OK;
2680 el->flags = ldb_flag;
2682 ret = ldb_modify(state->pdb, msg);
2683 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2684 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2686 return NT_STATUS_NO_MEMORY;
2688 ldb_msg_add_string(msg, "comment", "added via LSA");
2689 ret = ldb_add(state->pdb, msg);
2691 if (ret != LDB_SUCCESS) {
2692 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2694 return NT_STATUS_OK;
2696 DEBUG(3, ("Could not %s attributes from %s: %s",
2697 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2698 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2700 return NT_STATUS_UNEXPECTED_IO_ERROR;
2704 return NT_STATUS_OK;
2708 lsa_AddPrivilegesToAccount
2710 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2711 struct lsa_AddPrivilegesToAccount *r)
2713 struct lsa_RightSet rights;
2714 struct dcesrv_handle *h;
2715 struct lsa_account_state *astate;
2718 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2722 rights.count = r->in.privs->count;
2723 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2724 if (rights.names == NULL) {
2725 return NT_STATUS_NO_MEMORY;
2727 for (i=0;i<rights.count;i++) {
2728 int id = r->in.privs->set[i].luid.low;
2729 if (r->in.privs->set[i].luid.high) {
2730 return NT_STATUS_NO_SUCH_PRIVILEGE;
2732 rights.names[i].string = sec_privilege_name(id);
2733 if (rights.names[i].string == NULL) {
2734 return NT_STATUS_NO_SUCH_PRIVILEGE;
2738 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2739 LDB_FLAG_MOD_ADD, astate->account_sid,
2745 lsa_RemovePrivilegesFromAccount
2747 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2748 struct lsa_RemovePrivilegesFromAccount *r)
2750 struct lsa_RightSet *rights;
2751 struct dcesrv_handle *h;
2752 struct lsa_account_state *astate;
2755 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2759 rights = talloc(mem_ctx, struct lsa_RightSet);
2761 if (r->in.remove_all == 1 &&
2762 r->in.privs == NULL) {
2763 struct lsa_EnumAccountRights r2;
2766 r2.in.handle = &astate->policy->handle->wire_handle;
2767 r2.in.sid = astate->account_sid;
2768 r2.out.rights = rights;
2770 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2771 if (!NT_STATUS_IS_OK(status)) {
2775 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2776 LDB_FLAG_MOD_DELETE, astate->account_sid,
2780 if (r->in.remove_all != 0) {
2781 return NT_STATUS_INVALID_PARAMETER;
2784 rights->count = r->in.privs->count;
2785 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2786 if (rights->names == NULL) {
2787 return NT_STATUS_NO_MEMORY;
2789 for (i=0;i<rights->count;i++) {
2790 int id = r->in.privs->set[i].luid.low;
2791 if (r->in.privs->set[i].luid.high) {
2792 return NT_STATUS_NO_SUCH_PRIVILEGE;
2794 rights->names[i].string = sec_privilege_name(id);
2795 if (rights->names[i].string == NULL) {
2796 return NT_STATUS_NO_SUCH_PRIVILEGE;
2800 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2801 LDB_FLAG_MOD_DELETE, astate->account_sid,
2807 lsa_GetQuotasForAccount
2809 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2810 struct lsa_GetQuotasForAccount *r)
2812 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2817 lsa_SetQuotasForAccount
2819 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2820 struct lsa_SetQuotasForAccount *r)
2822 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2827 lsa_GetSystemAccessAccount
2829 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2830 struct lsa_GetSystemAccessAccount *r)
2832 struct dcesrv_handle *h;
2833 struct lsa_account_state *astate;
2836 struct ldb_message **res;
2837 const char * const attrs[] = { "privilege", NULL};
2838 struct ldb_message_element *el;
2841 *(r->out.access_mask) = 0x00000000;
2843 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2847 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2848 if (sidstr == NULL) {
2849 return NT_STATUS_NO_MEMORY;
2852 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2853 "objectSid=%s", sidstr);
2855 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2858 return NT_STATUS_OK;
2861 el = ldb_msg_find_element(res[0], "privilege");
2862 if (el == NULL || el->num_values == 0) {
2863 return NT_STATUS_OK;
2866 for (i=0;i<el->num_values;i++) {
2867 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2868 if (right_bit == 0) {
2869 /* Perhaps an privilege, not a right */
2872 *(r->out.access_mask) |= right_bit;
2875 return NT_STATUS_OK;
2880 lsa_SetSystemAccessAccount
2882 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2883 struct lsa_SetSystemAccessAccount *r)
2885 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2892 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2893 struct lsa_CreateSecret *r)
2895 struct dcesrv_handle *policy_handle;
2896 struct lsa_policy_state *policy_state;
2897 struct lsa_secret_state *secret_state;
2898 struct dcesrv_handle *handle;
2899 struct ldb_message **msgs, *msg;
2900 const char *attrs[] = {
2908 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2909 ZERO_STRUCTP(r->out.sec_handle);
2911 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2913 case SECURITY_SYSTEM:
2914 case SECURITY_ADMINISTRATOR:
2917 /* Users and annonymous are not allowed create secrets */
2918 return NT_STATUS_ACCESS_DENIED;
2921 policy_state = policy_handle->data;
2923 if (!r->in.name.string) {
2924 return NT_STATUS_INVALID_PARAMETER;
2927 secret_state = talloc(mem_ctx, struct lsa_secret_state);
2928 NT_STATUS_HAVE_NO_MEMORY(secret_state);
2929 secret_state->policy = policy_state;
2931 msg = ldb_msg_new(mem_ctx);
2933 return NT_STATUS_NO_MEMORY;
2936 if (strncmp("G$", r->in.name.string, 2) == 0) {
2939 secret_state->global = true;
2941 name = &r->in.name.string[2];
2942 if (strlen(name) == 0) {
2943 return NT_STATUS_INVALID_PARAMETER;
2946 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2947 ldb_binary_encode_string(mem_ctx, name));
2948 NT_STATUS_HAVE_NO_MEMORY(name2);
2950 /* We need to connect to the database as system, as this is one
2951 * of the rare RPC calls that must read the secrets (and this
2952 * is denied otherwise) */
2953 secret_state->sam_ldb = talloc_reference(secret_state,
2954 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));
2955 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2957 /* search for the secret record */
2958 ret = gendb_search(secret_state->sam_ldb,
2959 mem_ctx, policy_state->system_dn, &msgs, attrs,
2960 "(&(cn=%s)(objectclass=secret))",
2963 return NT_STATUS_OBJECT_NAME_COLLISION;
2967 DEBUG(0,("Failure searching for CN=%s: %s\n",
2968 name2, ldb_errstring(secret_state->sam_ldb)));
2969 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2972 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2973 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2974 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2975 return NT_STATUS_NO_MEMORY;
2978 ret = ldb_msg_add_string(msg, "cn", name2);
2979 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2981 secret_state->global = false;
2983 name = r->in.name.string;
2984 if (strlen(name) == 0) {
2985 return NT_STATUS_INVALID_PARAMETER;
2988 secret_state->sam_ldb = talloc_reference(secret_state,
2989 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
2990 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2992 /* search for the secret record */
2993 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2994 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2996 "(&(cn=%s)(objectclass=secret))",
2997 ldb_binary_encode_string(mem_ctx, name));
2999 return NT_STATUS_OBJECT_NAME_COLLISION;
3003 DEBUG(0,("Failure searching for CN=%s: %s\n",
3004 name, ldb_errstring(secret_state->sam_ldb)));
3005 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3008 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3009 "cn=%s,cn=LSA Secrets", name);
3010 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3011 ret = ldb_msg_add_string(msg, "cn", name);
3012 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3015 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3016 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3018 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3019 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3021 /* create the secret */
3022 ret = ldb_add(secret_state->sam_ldb, msg);
3023 if (ret != LDB_SUCCESS) {
3024 DEBUG(0,("Failed to create secret record %s: %s\n",
3025 ldb_dn_get_linearized(msg->dn),
3026 ldb_errstring(secret_state->sam_ldb)));
3027 return NT_STATUS_ACCESS_DENIED;
3030 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3031 NT_STATUS_HAVE_NO_MEMORY(handle);
3033 handle->data = talloc_steal(handle, secret_state);
3035 secret_state->access_mask = r->in.access_mask;
3036 secret_state->policy = talloc_reference(secret_state, policy_state);
3037 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3039 *r->out.sec_handle = handle->wire_handle;
3041 return NT_STATUS_OK;
3048 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3049 struct lsa_OpenSecret *r)
3051 struct dcesrv_handle *policy_handle;
3053 struct lsa_policy_state *policy_state;
3054 struct lsa_secret_state *secret_state;
3055 struct dcesrv_handle *handle;
3056 struct ldb_message **msgs;
3057 const char *attrs[] = {
3065 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3066 ZERO_STRUCTP(r->out.sec_handle);
3067 policy_state = policy_handle->data;
3069 if (!r->in.name.string) {
3070 return NT_STATUS_INVALID_PARAMETER;
3073 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3075 case SECURITY_SYSTEM:
3076 case SECURITY_ADMINISTRATOR:
3079 /* Users and annonymous are not allowed to access secrets */
3080 return NT_STATUS_ACCESS_DENIED;
3083 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3084 if (!secret_state) {
3085 return NT_STATUS_NO_MEMORY;
3087 secret_state->policy = policy_state;
3089 if (strncmp("G$", r->in.name.string, 2) == 0) {
3090 name = &r->in.name.string[2];
3091 /* 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) */
3092 secret_state->sam_ldb = talloc_reference(secret_state,
3093 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));
3094 secret_state->global = true;
3096 if (strlen(name) < 1) {
3097 return NT_STATUS_INVALID_PARAMETER;
3100 /* search for the secret record */
3101 ret = gendb_search(secret_state->sam_ldb,
3102 mem_ctx, policy_state->system_dn, &msgs, attrs,
3103 "(&(cn=%s Secret)(objectclass=secret))",
3104 ldb_binary_encode_string(mem_ctx, name));
3106 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3110 DEBUG(0,("Found %d records matching DN %s\n", ret,
3111 ldb_dn_get_linearized(policy_state->system_dn)));
3112 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3115 secret_state->global = false;
3116 secret_state->sam_ldb = talloc_reference(secret_state,
3117 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3119 name = r->in.name.string;
3120 if (strlen(name) < 1) {
3121 return NT_STATUS_INVALID_PARAMETER;
3124 /* search for the secret record */
3125 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3126 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3128 "(&(cn=%s)(objectclass=secret))",
3129 ldb_binary_encode_string(mem_ctx, name));
3131 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3135 DEBUG(0,("Found %d records matching CN=%s\n",
3136 ret, ldb_binary_encode_string(mem_ctx, name)));
3137 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3141 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3143 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3145 return NT_STATUS_NO_MEMORY;
3148 handle->data = talloc_steal(handle, secret_state);
3150 secret_state->access_mask = r->in.access_mask;
3151 secret_state->policy = talloc_reference(secret_state, policy_state);
3153 *r->out.sec_handle = handle->wire_handle;
3155 return NT_STATUS_OK;
3162 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3163 struct lsa_SetSecret *r)
3166 struct dcesrv_handle *h;
3167 struct lsa_secret_state *secret_state;
3168 struct ldb_message *msg;
3169 DATA_BLOB session_key;
3170 DATA_BLOB crypt_secret, secret;
3173 NTSTATUS status = NT_STATUS_OK;
3175 struct timeval now = timeval_current();
3176 NTTIME nt_now = timeval_to_nttime(&now);
3178 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3180 secret_state = h->data;
3182 msg = ldb_msg_new(mem_ctx);
3184 return NT_STATUS_NO_MEMORY;
3187 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3189 return NT_STATUS_NO_MEMORY;
3191 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3192 if (!NT_STATUS_IS_OK(status)) {
3196 if (r->in.old_val) {
3198 crypt_secret.data = r->in.old_val->data;
3199 crypt_secret.length = r->in.old_val->size;
3201 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3202 if (!NT_STATUS_IS_OK(status)) {
3206 val.data = secret.data;
3207 val.length = secret.length;
3210 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3211 return NT_STATUS_NO_MEMORY;
3214 /* set old value mtime */
3215 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3216 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3217 return NT_STATUS_NO_MEMORY;
3221 /* If the old value is not set, then migrate the
3222 * current value to the old value */
3223 const struct ldb_val *old_val;
3224 NTTIME last_set_time;
3225 struct ldb_message **res;
3226 const char *attrs[] = {
3232 /* search for the secret record */
3233 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3234 secret_state->secret_dn, &res, attrs);
3236 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3240 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3241 ldb_dn_get_linearized(secret_state->secret_dn)));
3242 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3245 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3246 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3250 if (ldb_msg_add_value(msg, "priorValue",
3251 old_val, NULL) != LDB_SUCCESS) {
3252 return NT_STATUS_NO_MEMORY;
3255 if (samdb_msg_add_delete(secret_state->sam_ldb,
3256 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3257 return NT_STATUS_NO_MEMORY;
3261 /* set old value mtime */
3262 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3263 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3264 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3265 return NT_STATUS_NO_MEMORY;
3268 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3269 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3270 return NT_STATUS_NO_MEMORY;
3275 if (r->in.new_val) {
3277 crypt_secret.data = r->in.new_val->data;
3278 crypt_secret.length = r->in.new_val->size;
3280 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3281 if (!NT_STATUS_IS_OK(status)) {
3285 val.data = secret.data;
3286 val.length = secret.length;
3289 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3290 return NT_STATUS_NO_MEMORY;
3293 /* set new value mtime */
3294 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3295 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3296 return NT_STATUS_NO_MEMORY;
3299 /* NULL out the NEW value */
3300 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3301 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3302 return NT_STATUS_NO_MEMORY;
3304 if (samdb_msg_add_delete(secret_state->sam_ldb,
3305 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3306 return NT_STATUS_NO_MEMORY;
3310 /* modify the samdb record */
3311 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3312 if (ret != LDB_SUCCESS) {
3313 return dsdb_ldb_err_to_ntstatus(ret);
3316 return NT_STATUS_OK;
3323 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3324 struct lsa_QuerySecret *r)
3326 struct dcesrv_handle *h;
3327 struct lsa_secret_state *secret_state;
3328 struct ldb_message *msg;
3329 DATA_BLOB session_key;
3330 DATA_BLOB crypt_secret, secret;
3332 struct ldb_message **res;
3333 const char *attrs[] = {
3343 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3345 /* Ensure user is permitted to read this... */
3346 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3348 case SECURITY_SYSTEM:
3349 case SECURITY_ADMINISTRATOR:
3352 /* Users and annonymous are not allowed to read secrets */
3353 return NT_STATUS_ACCESS_DENIED;
3356 secret_state = h->data;
3358 /* pull all the user attributes */
3359 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3360 secret_state->secret_dn, &res, attrs);
3362 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3366 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3367 if (!NT_STATUS_IS_OK(nt_status)) {
3371 if (r->in.old_val) {
3372 const struct ldb_val *prior_val;
3373 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3374 if (!r->out.old_val) {
3375 return NT_STATUS_NO_MEMORY;
3377 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3379 if (prior_val && prior_val->length) {
3380 secret.data = prior_val->data;
3381 secret.length = prior_val->length;
3384 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3385 if (!crypt_secret.length) {
3386 return NT_STATUS_NO_MEMORY;
3388 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3389 if (!r->out.old_val->buf) {
3390 return NT_STATUS_NO_MEMORY;
3392 r->out.old_val->buf->size = crypt_secret.length;
3393 r->out.old_val->buf->length = crypt_secret.length;
3394 r->out.old_val->buf->data = crypt_secret.data;
3398 if (r->in.old_mtime) {
3399 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3400 if (!r->out.old_mtime) {
3401 return NT_STATUS_NO_MEMORY;
3403 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3406 if (r->in.new_val) {
3407 const struct ldb_val *new_val;
3408 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3409 if (!r->out.new_val) {
3410 return NT_STATUS_NO_MEMORY;
3413 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3415 if (new_val && new_val->length) {
3416 secret.data = new_val->data;
3417 secret.length = new_val->length;
3420 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3421 if (!crypt_secret.length) {
3422 return NT_STATUS_NO_MEMORY;
3424 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3425 if (!r->out.new_val->buf) {
3426 return NT_STATUS_NO_MEMORY;
3428 r->out.new_val->buf->length = crypt_secret.length;
3429 r->out.new_val->buf->size = crypt_secret.length;
3430 r->out.new_val->buf->data = crypt_secret.data;
3434 if (r->in.new_mtime) {
3435 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3436 if (!r->out.new_mtime) {
3437 return NT_STATUS_NO_MEMORY;
3439 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3442 return NT_STATUS_OK;
3449 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3450 TALLOC_CTX *mem_ctx,
3451 struct lsa_LookupPrivValue *r)
3453 struct dcesrv_handle *h;
3456 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3458 id = sec_privilege_id(r->in.name->string);
3459 if (id == SEC_PRIV_INVALID) {
3460 return NT_STATUS_NO_SUCH_PRIVILEGE;
3463 r->out.luid->low = id;
3464 r->out.luid->high = 0;
3466 return NT_STATUS_OK;
3473 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3474 TALLOC_CTX *mem_ctx,
3475 struct lsa_LookupPrivName *r)
3477 struct dcesrv_handle *h;
3478 struct lsa_StringLarge *name;
3479 const char *privname;
3481 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3483 if (r->in.luid->high != 0) {
3484 return NT_STATUS_NO_SUCH_PRIVILEGE;
3487 privname = sec_privilege_name(r->in.luid->low);
3488 if (privname == NULL) {
3489 return NT_STATUS_NO_SUCH_PRIVILEGE;
3492 name = talloc(mem_ctx, struct lsa_StringLarge);
3494 return NT_STATUS_NO_MEMORY;
3497 name->string = privname;
3499 *r->out.name = name;
3501 return NT_STATUS_OK;
3506 lsa_LookupPrivDisplayName
3508 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3509 TALLOC_CTX *mem_ctx,
3510 struct lsa_LookupPrivDisplayName *r)
3512 struct dcesrv_handle *h;
3513 struct lsa_StringLarge *disp_name = NULL;
3514 enum sec_privilege id;
3516 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3518 id = sec_privilege_id(r->in.name->string);
3519 if (id == SEC_PRIV_INVALID) {
3520 return NT_STATUS_NO_SUCH_PRIVILEGE;
3523 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3524 if (disp_name == NULL) {
3525 return NT_STATUS_NO_MEMORY;
3528 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3529 if (disp_name->string == NULL) {
3530 return NT_STATUS_INTERNAL_ERROR;
3533 *r->out.disp_name = disp_name;
3534 *r->out.returned_language_id = 0;
3536 return NT_STATUS_OK;
3541 lsa_EnumAccountsWithUserRight
3543 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3544 TALLOC_CTX *mem_ctx,
3545 struct lsa_EnumAccountsWithUserRight *r)
3547 struct dcesrv_handle *h;
3548 struct lsa_policy_state *state;
3550 struct ldb_message **res;
3551 const char * const attrs[] = { "objectSid", NULL};
3552 const char *privname;
3554 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3558 if (r->in.name == NULL) {
3559 return NT_STATUS_NO_SUCH_PRIVILEGE;
3562 privname = r->in.name->string;
3563 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3564 return NT_STATUS_NO_SUCH_PRIVILEGE;
3567 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3568 "privilege=%s", privname);
3570 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3573 return NT_STATUS_NO_MORE_ENTRIES;
3576 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3577 if (r->out.sids->sids == NULL) {
3578 return NT_STATUS_NO_MEMORY;
3580 for (i=0;i<ret;i++) {
3581 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3582 res[i], "objectSid");
3583 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3585 r->out.sids->num_sids = ret;
3587 return NT_STATUS_OK;
3592 lsa_AddAccountRights
3594 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3595 TALLOC_CTX *mem_ctx,
3596 struct lsa_AddAccountRights *r)
3598 struct dcesrv_handle *h;
3599 struct lsa_policy_state *state;
3601 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3605 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3607 r->in.sid, r->in.rights);
3612 lsa_RemoveAccountRights
3614 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3615 TALLOC_CTX *mem_ctx,
3616 struct lsa_RemoveAccountRights *r)
3618 struct dcesrv_handle *h;
3619 struct lsa_policy_state *state;
3621 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3625 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3626 LDB_FLAG_MOD_DELETE,
3627 r->in.sid, r->in.rights);
3632 lsa_StorePrivateData
3634 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3635 struct lsa_StorePrivateData *r)
3637 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3642 lsa_RetrievePrivateData
3644 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3645 struct lsa_RetrievePrivateData *r)
3647 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3654 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3655 struct lsa_GetUserName *r)
3657 enum dcerpc_transport_t transport =
3658 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3659 NTSTATUS status = NT_STATUS_OK;
3660 const char *account_name;
3661 const char *authority_name;
3662 struct lsa_String *_account_name;
3663 struct lsa_String *_authority_name = NULL;
3665 if (transport != NCACN_NP && transport != NCALRPC) {
3666 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3669 /* this is what w2k3 does */
3670 r->out.account_name = r->in.account_name;
3671 r->out.authority_name = r->in.authority_name;
3673 if (r->in.account_name
3674 && *r->in.account_name
3675 /* && *(*r->in.account_name)->string */
3677 return NT_STATUS_INVALID_PARAMETER;
3680 if (r->in.authority_name
3681 && *r->in.authority_name
3682 /* && *(*r->in.authority_name)->string */
3684 return NT_STATUS_INVALID_PARAMETER;
3687 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3688 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3690 _account_name = talloc(mem_ctx, struct lsa_String);
3691 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3692 _account_name->string = account_name;
3694 if (r->in.authority_name) {
3695 _authority_name = talloc(mem_ctx, struct lsa_String);
3696 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3697 _authority_name->string = authority_name;
3700 *r->out.account_name = _account_name;
3701 if (r->out.authority_name) {
3702 *r->out.authority_name = _authority_name;
3711 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3712 TALLOC_CTX *mem_ctx,
3713 struct lsa_SetInfoPolicy2 *r)
3715 /* need to support these */
3716 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3719 static void kdc_get_policy(struct loadparm_context *lp_ctx,
3720 struct smb_krb5_context *smb_krb5_context,
3721 struct lsa_DomainInfoKerberos *k)
3723 time_t svc_tkt_lifetime;
3724 time_t usr_tkt_lifetime;
3725 time_t renewal_lifetime;
3727 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
3729 /* Our KDC always re-validates the client */
3730 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
3732 lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
3733 &usr_tkt_lifetime, &renewal_lifetime);
3735 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
3736 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
3737 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
3738 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
3739 However in the parent function we basically just did a full
3740 krb5_context init with the only purpose of getting a global
3741 config option (the max skew), it would probably make more sense
3742 to have a lp_ or ldb global option as the samba default */
3743 if (smb_krb5_context) {
3744 unix_to_nt_time(&k->clock_skew,
3745 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
3751 lsa_QueryDomainInformationPolicy
3753 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3754 TALLOC_CTX *mem_ctx,
3755 struct lsa_QueryDomainInformationPolicy *r)
3757 union lsa_DomainInformationPolicy *info;
3759 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3761 return NT_STATUS_NO_MEMORY;
3764 switch (r->in.level) {
3765 case LSA_DOMAIN_INFO_POLICY_EFS:
3767 *r->out.info = NULL;
3768 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3769 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3771 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3772 struct smb_krb5_context *smb_krb5_context;
3773 int ret = smb_krb5_init_context(mem_ctx,
3774 dce_call->conn->dce_ctx->lp_ctx,
3778 *r->out.info = NULL;
3779 return NT_STATUS_INTERNAL_ERROR;
3781 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3784 talloc_free(smb_krb5_context);
3785 *r->out.info = info;
3786 return NT_STATUS_OK;
3790 *r->out.info = NULL;
3791 return NT_STATUS_INVALID_INFO_CLASS;
3796 lsa_SetDomInfoPolicy
3798 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3799 TALLOC_CTX *mem_ctx,
3800 struct lsa_SetDomainInformationPolicy *r)
3802 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3808 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3809 TALLOC_CTX *mem_ctx,
3810 struct lsa_TestCall *r)
3812 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3818 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3819 struct lsa_CREDRWRITE *r)
3821 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3828 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3829 struct lsa_CREDRREAD *r)
3831 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3838 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3839 struct lsa_CREDRENUMERATE *r)
3841 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3846 lsa_CREDRWRITEDOMAINCREDENTIALS
3848 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3849 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3851 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3856 lsa_CREDRREADDOMAINCREDENTIALS
3858 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3859 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3861 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3868 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3869 struct lsa_CREDRDELETE *r)
3871 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3876 lsa_CREDRGETTARGETINFO
3878 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3879 struct lsa_CREDRGETTARGETINFO *r)
3881 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3886 lsa_CREDRPROFILELOADED
3888 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3889 struct lsa_CREDRPROFILELOADED *r)
3891 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3896 lsa_CREDRGETSESSIONTYPES
3898 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3899 struct lsa_CREDRGETSESSIONTYPES *r)
3901 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3906 lsa_LSARREGISTERAUDITEVENT
3908 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3909 struct lsa_LSARREGISTERAUDITEVENT *r)
3911 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3916 lsa_LSARGENAUDITEVENT
3918 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3919 struct lsa_LSARGENAUDITEVENT *r)
3921 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3926 lsa_LSARUNREGISTERAUDITEVENT
3928 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3929 struct lsa_LSARUNREGISTERAUDITEVENT *r)
3931 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3936 lsa_lsaRQueryForestTrustInformation
3938 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3939 struct lsa_lsaRQueryForestTrustInformation *r)
3941 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3944 #define DNS_CMP_MATCH 0
3945 #define DNS_CMP_FIRST_IS_CHILD 1
3946 #define DNS_CMP_SECOND_IS_CHILD 2
3947 #define DNS_CMP_NO_MATCH 3
3949 /* this function assumes names are well formed DNS names.
3950 * it doesn't validate them */
3951 static int dns_cmp(const char *s1, size_t l1,
3952 const char *s2, size_t l2)
3954 const char *p1, *p2;
3959 if (strcasecmp_m(s1, s2) == 0) {
3960 return DNS_CMP_MATCH;
3962 return DNS_CMP_NO_MATCH;
3970 cret = DNS_CMP_FIRST_IS_CHILD;
3976 cret = DNS_CMP_SECOND_IS_CHILD;
3979 if (p1[t1 - t2 - 1] != '.') {
3980 return DNS_CMP_NO_MATCH;
3983 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3987 return DNS_CMP_NO_MATCH;
3990 /* decode all TDOs forest trust info blobs */
3991 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3992 struct ldb_message *msg,
3993 struct ForestTrustInfo *info)
3995 const struct ldb_val *ft_blob;
3996 enum ndr_err_code ndr_err;
3998 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3999 if (!ft_blob || !ft_blob->data) {
4000 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4002 /* ldb_val is equivalent to DATA_BLOB */
4003 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
4004 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
4005 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4006 return NT_STATUS_INVALID_DOMAIN_STATE;
4009 return NT_STATUS_OK;
4012 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
4013 struct ForestTrustInfo *fti)
4015 struct ForestTrustDataDomainInfo *info;
4016 struct ForestTrustInfoRecord *rec;
4020 fti->records = talloc_array(fti,
4021 struct ForestTrustInfoRecordArmor, 2);
4022 if (!fti->records) {
4023 return NT_STATUS_NO_MEMORY;
4027 rec = &fti->records[0].record;
4031 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
4033 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
4034 if (!rec->data.name.string) {
4035 return NT_STATUS_NO_MEMORY;
4037 rec->data.name.size = strlen(rec->data.name.string);
4040 rec = &fti->records[1].record;
4044 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
4046 info = &rec->data.info;
4048 info->sid = *ps->domain_sid;
4049 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
4050 if (!info->dns_name.string) {
4051 return NT_STATUS_NO_MEMORY;
4053 info->dns_name.size = strlen(info->dns_name.string);
4054 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
4055 if (!info->netbios_name.string) {
4056 return NT_STATUS_NO_MEMORY;
4058 info->netbios_name.size = strlen(info->netbios_name.string);
4060 return NT_STATUS_OK;
4063 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
4064 struct lsa_ForestTrustInformation *lfti,
4065 struct ForestTrustInfo *fti)
4067 struct lsa_ForestTrustRecord *lrec;
4068 struct ForestTrustInfoRecord *rec;
4069 struct lsa_StringLarge *tln;
4070 struct lsa_ForestTrustDomainInfo *info;
4074 fti->count = lfti->count;
4075 fti->records = talloc_array(mem_ctx,
4076 struct ForestTrustInfoRecordArmor,
4078 if (!fti->records) {
4079 return NT_STATUS_NO_MEMORY;
4081 for (i = 0; i < fti->count; i++) {
4082 lrec = lfti->entries[i];
4083 rec = &fti->records[i].record;
4085 rec->flags = lrec->flags;
4086 rec->timestamp = lrec->time;
4087 rec->type = lrec->type;
4089 switch (lrec->type) {
4090 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4091 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4092 tln = &lrec->forest_trust_data.top_level_name;
4093 rec->data.name.string =
4094 talloc_strdup(mem_ctx, tln->string);
4095 if (!rec->data.name.string) {
4096 return NT_STATUS_NO_MEMORY;
4098 rec->data.name.size = strlen(rec->data.name.string);
4100 case LSA_FOREST_TRUST_DOMAIN_INFO:
4101 info = &lrec->forest_trust_data.domain_info;
4102 rec->data.info.sid = *info->domain_sid;
4103 rec->data.info.dns_name.string =
4104 talloc_strdup(mem_ctx,
4105 info->dns_domain_name.string);
4106 if (!rec->data.info.dns_name.string) {
4107 return NT_STATUS_NO_MEMORY;
4109 rec->data.info.dns_name.size =
4110 strlen(rec->data.info.dns_name.string);
4111 rec->data.info.netbios_name.string =
4112 talloc_strdup(mem_ctx,
4113 info->netbios_domain_name.string);
4114 if (!rec->data.info.netbios_name.string) {
4115 return NT_STATUS_NO_MEMORY;
4117 rec->data.info.netbios_name.size =
4118 strlen(rec->data.info.netbios_name.string);
4121 return NT_STATUS_INVALID_DOMAIN_STATE;
4125 return NT_STATUS_OK;
4128 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4129 uint32_t idx, uint32_t collision_type,
4130 uint32_t conflict_type, const char *tdo_name);
4132 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4133 const char *tdo_name,
4134 struct ForestTrustInfo *tdo_fti,
4135 struct ForestTrustInfo *new_fti,
4136 struct lsa_ForestTrustCollisionInfo *c_info)
4138 struct ForestTrustInfoRecord *nrec;
4139 struct ForestTrustInfoRecord *trec;
4140 const char *dns_name;
4141 const char *nb_name;
4142 struct dom_sid *sid;
4146 NTSTATUS nt_status = NT_STATUS_OK;
4147 uint32_t new_fti_idx;
4149 /* use always TDO type, until we understand when Xref can be used */
4150 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4158 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4160 nrec = &new_fti->records[new_fti_idx].record;
4162 tln_conflict = false;
4163 sid_conflict = false;
4164 nb_conflict = false;
4167 switch (nrec->type) {
4168 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4169 /* exclusions do not conflict by definition */
4172 case FOREST_TRUST_TOP_LEVEL_NAME:
4173 dns_name = nrec->data.name.string;
4174 dns_len = nrec->data.name.size;
4177 case LSA_FOREST_TRUST_DOMAIN_INFO:
4178 dns_name = nrec->data.info.dns_name.string;
4179 dns_len = nrec->data.info.dns_name.size;
4180 nb_name = nrec->data.info.netbios_name.string;
4181 sid = &nrec->data.info.sid;
4185 if (!dns_name) continue;
4187 /* check if this is already taken and not excluded */
4188 for (i = 0; i < tdo_fti->count; i++) {
4189 trec = &tdo_fti->records[i].record;
4191 switch (trec->type) {
4192 case FOREST_TRUST_TOP_LEVEL_NAME:
4194 tname = trec->data.name.string;
4195 tlen = trec->data.name.size;
4197 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4199 tname = trec->data.name.string;
4200 tlen = trec->data.name.size;
4202 case FOREST_TRUST_DOMAIN_INFO:
4204 tname = trec->data.info.dns_name.string;
4205 tlen = trec->data.info.dns_name.size;
4207 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4210 /* if it matches exclusion,
4211 * it doesn't conflict */
4217 case DNS_CMP_FIRST_IS_CHILD:
4218 case DNS_CMP_SECOND_IS_CHILD:
4219 tln_conflict = true;
4225 /* explicit exclusion, no dns name conflict here */
4227 tln_conflict = false;
4230 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4234 /* also test for domain info */
4235 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4236 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4237 sid_conflict = true;
4239 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4240 strcasecmp_m(trec->data.info.netbios_name.string,
4247 nt_status = add_collision(c_info, new_fti_idx,
4249 LSA_TLN_DISABLED_CONFLICT,
4251 if (!NT_STATUS_IS_OK(nt_status)) {
4256 nt_status = add_collision(c_info, new_fti_idx,
4258 LSA_SID_DISABLED_CONFLICT,
4260 if (!NT_STATUS_IS_OK(nt_status)) {
4265 nt_status = add_collision(c_info, new_fti_idx,
4267 LSA_NB_DISABLED_CONFLICT,
4269 if (!NT_STATUS_IS_OK(nt_status)) {
4279 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4280 uint32_t idx, uint32_t collision_type,
4281 uint32_t conflict_type, const char *tdo_name)
4283 struct lsa_ForestTrustCollisionRecord **es;
4284 uint32_t i = c_info->count;
4286 es = talloc_realloc(c_info, c_info->entries,
4287 struct lsa_ForestTrustCollisionRecord *, i + 1);
4289 return NT_STATUS_NO_MEMORY;
4291 c_info->entries = es;
4292 c_info->count = i + 1;
4294 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4296 return NT_STATUS_NO_MEMORY;
4300 es[i]->type = collision_type;
4301 es[i]->flags.flags = conflict_type;
4302 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4303 if (!es[i]->name.string) {
4304 return NT_STATUS_NO_MEMORY;
4306 es[i]->name.size = strlen(es[i]->name.string);
4308 return NT_STATUS_OK;
4312 lsa_lsaRSetForestTrustInformation
4314 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4315 TALLOC_CTX *mem_ctx,
4316 struct lsa_lsaRSetForestTrustInformation *r)
4318 struct dcesrv_handle *h;
4319 struct lsa_policy_state *p_state;
4320 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4321 "msDS-TrustForestTrustInfo", NULL };
4322 struct ldb_message **dom_res = NULL;
4323 struct ldb_dn *tdo_dn;
4324 struct ldb_message *msg;
4326 const char *td_name;
4327 uint32_t trust_attributes;
4328 struct lsa_ForestTrustCollisionInfo *c_info;
4329 struct ForestTrustInfo *nfti;
4330 struct ForestTrustInfo *fti;
4332 enum ndr_err_code ndr_err;
4337 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4341 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4342 return NT_STATUS_INVALID_DOMAIN_STATE;
4345 /* abort if we are not a PDC */
4346 if (!samdb_is_pdc(p_state->sam_ldb)) {
4347 return NT_STATUS_INVALID_DOMAIN_ROLE;
4350 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4351 if (ret == LDB_SUCCESS && am_rodc) {
4352 return NT_STATUS_NO_SUCH_DOMAIN;
4355 /* check caller has TRUSTED_SET_AUTH */
4357 /* fetch all trusted domain objects */
4358 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4360 &dom_res, trust_attrs,
4361 "(objectclass=trustedDomain)");
4363 return NT_STATUS_NO_SUCH_DOMAIN;
4366 for (i = 0; i < num_res; i++) {
4367 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4368 "trustPartner", NULL);
4370 return NT_STATUS_INVALID_DOMAIN_STATE;
4372 if (strcasecmp_m(td_name,
4373 r->in.trusted_domain_name->string) == 0) {
4378 return NT_STATUS_NO_SUCH_DOMAIN;
4381 tdo_dn = dom_res[i]->dn;
4383 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4384 "trustAttributes", 0);
4385 if (!(trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4386 return NT_STATUS_INVALID_PARAMETER;
4389 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4390 return NT_STATUS_INVALID_PARAMETER;
4393 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4395 return NT_STATUS_NO_MEMORY;
4398 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4399 if (!NT_STATUS_IS_OK(nt_status)) {
4403 c_info = talloc_zero(r->out.collision_info,
4404 struct lsa_ForestTrustCollisionInfo);
4406 return NT_STATUS_NO_MEMORY;
4409 /* first check own info, then other domains */
4410 fti = talloc(mem_ctx, struct ForestTrustInfo);
4412 return NT_STATUS_NO_MEMORY;
4415 nt_status = own_ft_info(p_state, fti);
4416 if (!NT_STATUS_IS_OK(nt_status)) {
4420 nt_status = check_ft_info(c_info, p_state->domain_dns,
4422 if (!NT_STATUS_IS_OK(nt_status)) {
4426 for (i = 0; i < num_res; i++) {
4427 fti = talloc(mem_ctx, struct ForestTrustInfo);
4429 return NT_STATUS_NO_MEMORY;
4432 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4433 if (!NT_STATUS_IS_OK(nt_status)) {
4434 if (NT_STATUS_EQUAL(nt_status,
4435 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4441 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4442 "trustPartner", NULL);
4444 return NT_STATUS_INVALID_DOMAIN_STATE;
4447 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4448 if (!NT_STATUS_IS_OK(nt_status)) {
4453 *r->out.collision_info = c_info;
4455 if (r->in.check_only != 0) {
4456 return NT_STATUS_OK;
4459 /* not just a check, write info back */
4461 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4462 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4463 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4464 return NT_STATUS_INVALID_PARAMETER;
4467 msg = ldb_msg_new(mem_ctx);
4469 return NT_STATUS_NO_MEMORY;
4472 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4474 return NT_STATUS_NO_MEMORY;
4477 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4478 LDB_FLAG_MOD_REPLACE, NULL);
4479 if (ret != LDB_SUCCESS) {
4480 return NT_STATUS_NO_MEMORY;
4482 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4484 if (ret != LDB_SUCCESS) {
4485 return NT_STATUS_NO_MEMORY;
4488 ret = ldb_modify(p_state->sam_ldb, msg);
4489 if (ret != LDB_SUCCESS) {
4490 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4491 ldb_errstring(p_state->sam_ldb)));
4494 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4495 return NT_STATUS_ACCESS_DENIED;
4497 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4501 return NT_STATUS_OK;
4507 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4508 struct lsa_CREDRRENAME *r)
4510 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4516 lsa_LSAROPENPOLICYSCE
4518 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4519 struct lsa_LSAROPENPOLICYSCE *r)
4521 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4526 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4528 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4529 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4531 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4536 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4538 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4539 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4541 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4546 lsa_LSARADTREPORTSECURITYEVENT
4548 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4549 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4551 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4555 /* include the generated boilerplate */
4556 #include "librpc/gen_ndr/ndr_lsa_s.c"
4560 /*****************************************
4561 NOTE! The remaining calls below were
4562 removed in w2k3, so the DCESRV_FAULT()
4563 replies are the correct implementation. Do
4564 not try and fill these in with anything else
4565 ******************************************/
4568 dssetup_DsRoleDnsNameToFlatName
4570 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4571 struct dssetup_DsRoleDnsNameToFlatName *r)
4573 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4578 dssetup_DsRoleDcAsDc
4580 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4581 struct dssetup_DsRoleDcAsDc *r)
4583 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4588 dssetup_DsRoleDcAsReplica
4590 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4591 struct dssetup_DsRoleDcAsReplica *r)
4593 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4598 dssetup_DsRoleDemoteDc
4600 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4601 struct dssetup_DsRoleDemoteDc *r)
4603 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4608 dssetup_DsRoleGetDcOperationProgress
4610 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4611 struct dssetup_DsRoleGetDcOperationProgress *r)
4613 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4618 dssetup_DsRoleGetDcOperationResults
4620 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4621 struct dssetup_DsRoleGetDcOperationResults *r)
4623 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4628 dssetup_DsRoleCancel
4630 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4631 struct dssetup_DsRoleCancel *r)
4633 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4638 dssetup_DsRoleServerSaveStateForUpgrade
4640 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4641 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4643 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4648 dssetup_DsRoleUpgradeDownlevelServer
4650 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4651 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4653 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4658 dssetup_DsRoleAbortDownlevelServerUpgrade
4660 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4661 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4663 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4667 /* include the generated boilerplate */
4668 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4670 NTSTATUS dcerpc_server_lsa_init(void)
4674 ret = dcerpc_server_dssetup_init();
4675 if (!NT_STATUS_IS_OK(ret)) {
4678 ret = dcerpc_server_lsarpc_init();
4679 if (!NT_STATUS_IS_OK(ret)) {