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 add_incoming = true;
1784 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1785 add_outgoing = true;
1788 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1789 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1790 del_incoming = true;
1792 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1793 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1794 del_outgoing = true;
1797 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1798 if (origtype == -1 || origtype != info_ex->trust_type) {
1799 DEBUG(1, ("Attempted to change trust type! "
1800 "Operation not handled\n"));
1801 return NT_STATUS_INVALID_PARAMETER;
1804 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1807 info_ex->trust_attributes,
1809 if (!NT_STATUS_IS_OK(nt_status)) {
1812 /* TODO: check forestFunctionality from ldb opaque */
1813 /* TODO: check what is set makes sense */
1814 /* for now refuse changes */
1815 if (origattrs == -1 ||
1816 origattrs != info_ex->trust_attributes) {
1817 DEBUG(1, ("Attempted to change trust attributes! "
1818 "Operation not handled\n"));
1819 return NT_STATUS_INVALID_PARAMETER;
1824 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1826 "msDS-SupportedEncryptionTypes",
1828 if (!NT_STATUS_IS_OK(nt_status)) {
1833 if (add_incoming && trustAuthIncoming.data) {
1834 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1835 LDB_FLAG_MOD_REPLACE, NULL);
1836 if (ret != LDB_SUCCESS) {
1837 return NT_STATUS_NO_MEMORY;
1839 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1840 &trustAuthIncoming, NULL);
1841 if (ret != LDB_SUCCESS) {
1842 return NT_STATUS_NO_MEMORY;
1845 if (add_outgoing && trustAuthOutgoing.data) {
1846 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1847 LDB_FLAG_MOD_REPLACE, NULL);
1848 if (ret != LDB_SUCCESS) {
1849 return NT_STATUS_NO_MEMORY;
1851 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1852 &trustAuthOutgoing, NULL);
1853 if (ret != LDB_SUCCESS) {
1854 return NT_STATUS_NO_MEMORY;
1858 /* start transaction */
1859 ret = ldb_transaction_start(p_state->sam_ldb);
1860 if (ret != LDB_SUCCESS) {
1861 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1863 in_transaction = true;
1865 if (msg->num_elements) {
1866 ret = ldb_modify(p_state->sam_ldb, msg);
1867 if (ret != LDB_SUCCESS) {
1868 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1869 ldb_dn_get_linearized(msg->dn),
1870 ldb_errstring(p_state->sam_ldb)));
1871 nt_status = dsdb_ldb_err_to_ntstatus(ret);
1876 if (add_incoming || del_incoming) {
1877 const char *netbios_name;
1879 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1881 if (!netbios_name) {
1882 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1886 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
1887 nt_status = update_trust_user(mem_ctx,
1893 if (!NT_STATUS_IS_OK(nt_status)) {
1898 /* ok, all fine, commit transaction and return */
1899 ret = ldb_transaction_commit(p_state->sam_ldb);
1900 if (ret != LDB_SUCCESS) {
1901 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1903 in_transaction = false;
1905 nt_status = NT_STATUS_OK;
1908 if (in_transaction) {
1909 ldb_transaction_cancel(p_state->sam_ldb);
1915 lsa_SetInfomrationTrustedDomain
1917 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1918 struct dcesrv_call_state *dce_call,
1919 TALLOC_CTX *mem_ctx,
1920 struct lsa_SetInformationTrustedDomain *r)
1922 struct dcesrv_handle *h;
1923 struct lsa_trusted_domain_state *td_state;
1924 struct ldb_message **msgs;
1927 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1928 LSA_HANDLE_TRUSTED_DOMAIN);
1930 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1932 /* get the trusted domain object */
1933 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1934 td_state->trusted_domain_dn,
1935 NULL, NULL, NULL, &msgs);
1936 if (!NT_STATUS_IS_OK(nt_status)) {
1937 if (NT_STATUS_EQUAL(nt_status,
1938 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1941 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1944 return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
1945 msgs[0], r->in.level, r->in.info);
1950 lsa_DeleteTrustedDomain
1952 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1953 struct lsa_DeleteTrustedDomain *r)
1956 struct lsa_OpenTrustedDomain opn;
1957 struct lsa_DeleteObject del;
1958 struct dcesrv_handle *h;
1960 opn.in.handle = r->in.handle;
1961 opn.in.sid = r->in.dom_sid;
1962 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1963 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1964 if (!opn.out.trustdom_handle) {
1965 return NT_STATUS_NO_MEMORY;
1967 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1968 if (!NT_STATUS_IS_OK(status)) {
1972 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1973 talloc_steal(mem_ctx, h);
1975 del.in.handle = opn.out.trustdom_handle;
1976 del.out.handle = opn.out.trustdom_handle;
1977 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1978 if (!NT_STATUS_IS_OK(status)) {
1981 return NT_STATUS_OK;
1984 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
1985 struct ldb_message *msg,
1986 struct lsa_TrustDomainInfoInfoEx *info_ex)
1988 info_ex->domain_name.string
1989 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1990 info_ex->netbios_name.string
1991 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1993 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1994 info_ex->trust_direction
1995 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1997 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1998 info_ex->trust_attributes
1999 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2000 return NT_STATUS_OK;
2004 lsa_QueryTrustedDomainInfo
2006 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2007 struct lsa_QueryTrustedDomainInfo *r)
2009 union lsa_TrustedDomainInfo *info = NULL;
2010 struct dcesrv_handle *h;
2011 struct lsa_trusted_domain_state *trusted_domain_state;
2012 struct ldb_message *msg;
2014 struct ldb_message **res;
2015 const char *attrs[] = {
2018 "securityIdentifier",
2022 "msDs-supportedEncryptionTypes",
2026 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2028 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2030 /* pull all the user attributes */
2031 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2032 trusted_domain_state->trusted_domain_dn, &res, attrs);
2034 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2038 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2040 return NT_STATUS_NO_MEMORY;
2042 *r->out.info = info;
2044 switch (r->in.level) {
2045 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2046 info->name.netbios_name.string
2047 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2049 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2050 info->posix_offset.posix_offset
2051 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2053 #if 0 /* Win2k3 doesn't implement this */
2054 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2055 r->out.info->info_basic.netbios_name.string
2056 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2057 r->out.info->info_basic.sid
2058 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2061 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2062 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2064 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2065 ZERO_STRUCT(info->full_info);
2066 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2067 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2068 ZERO_STRUCT(info->full_info2_internal);
2069 info->full_info2_internal.posix_offset.posix_offset
2070 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2071 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2073 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2074 info->enc_types.enc_types
2075 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2078 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2079 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2080 /* oops, we don't want to return the info after all */
2082 *r->out.info = NULL;
2083 return NT_STATUS_INVALID_PARAMETER;
2085 /* oops, we don't want to return the info after all */
2087 *r->out.info = NULL;
2088 return NT_STATUS_INVALID_INFO_CLASS;
2091 return NT_STATUS_OK;
2096 lsa_QueryTrustedDomainInfoBySid
2098 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2099 struct lsa_QueryTrustedDomainInfoBySid *r)
2102 struct lsa_OpenTrustedDomain opn;
2103 struct lsa_QueryTrustedDomainInfo query;
2104 struct dcesrv_handle *h;
2106 opn.in.handle = r->in.handle;
2107 opn.in.sid = r->in.dom_sid;
2108 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2109 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2110 if (!opn.out.trustdom_handle) {
2111 return NT_STATUS_NO_MEMORY;
2113 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2114 if (!NT_STATUS_IS_OK(status)) {
2118 /* Ensure this handle goes away at the end of this call */
2119 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2120 talloc_steal(mem_ctx, h);
2122 query.in.trustdom_handle = opn.out.trustdom_handle;
2123 query.in.level = r->in.level;
2124 query.out.info = r->out.info;
2125 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2126 if (!NT_STATUS_IS_OK(status)) {
2130 return NT_STATUS_OK;
2134 lsa_SetTrustedDomainInfoByName
2136 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2137 TALLOC_CTX *mem_ctx,
2138 struct lsa_SetTrustedDomainInfoByName *r)
2140 struct dcesrv_handle *policy_handle;
2141 struct lsa_policy_state *policy_state;
2142 struct ldb_message **msgs;
2145 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2146 policy_state = policy_handle->data;
2148 /* get the trusted domain object */
2149 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2150 policy_state->domain_dn,
2151 r->in.trusted_domain->string,
2152 r->in.trusted_domain->string,
2154 if (!NT_STATUS_IS_OK(nt_status)) {
2155 if (NT_STATUS_EQUAL(nt_status,
2156 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2159 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2162 return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2163 msgs[0], r->in.level, r->in.info);
2167 lsa_QueryTrustedDomainInfoByName
2169 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2170 TALLOC_CTX *mem_ctx,
2171 struct lsa_QueryTrustedDomainInfoByName *r)
2174 struct lsa_OpenTrustedDomainByName opn;
2175 struct lsa_QueryTrustedDomainInfo query;
2176 struct dcesrv_handle *h;
2178 opn.in.handle = r->in.handle;
2179 opn.in.name = *r->in.trusted_domain;
2180 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2181 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2182 if (!opn.out.trustdom_handle) {
2183 return NT_STATUS_NO_MEMORY;
2185 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2186 if (!NT_STATUS_IS_OK(status)) {
2190 /* Ensure this handle goes away at the end of this call */
2191 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2192 talloc_steal(mem_ctx, h);
2194 query.in.trustdom_handle = opn.out.trustdom_handle;
2195 query.in.level = r->in.level;
2196 query.out.info = r->out.info;
2197 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2198 if (!NT_STATUS_IS_OK(status)) {
2202 return NT_STATUS_OK;
2206 lsa_CloseTrustedDomainEx
2208 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2209 TALLOC_CTX *mem_ctx,
2210 struct lsa_CloseTrustedDomainEx *r)
2212 /* The result of a bad hair day from an IDL programmer? Not
2213 * implmented in Win2k3. You should always just lsa_Close
2215 return NT_STATUS_NOT_IMPLEMENTED;
2220 comparison function for sorting lsa_DomainInformation array
2222 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2224 return strcasecmp_m(e1->name.string, e2->name.string);
2230 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2231 struct lsa_EnumTrustDom *r)
2233 struct dcesrv_handle *policy_handle;
2234 struct lsa_DomainInfo *entries;
2235 struct lsa_policy_state *policy_state;
2236 struct ldb_message **domains;
2237 const char *attrs[] = {
2239 "securityIdentifier",
2246 *r->out.resume_handle = 0;
2248 r->out.domains->domains = NULL;
2249 r->out.domains->count = 0;
2251 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2253 policy_state = policy_handle->data;
2255 /* search for all users in this domain. This could possibly be cached and
2256 resumed based on resume_key */
2257 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2258 "objectclass=trustedDomain");
2260 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2263 /* convert to lsa_TrustInformation format */
2264 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2266 return NT_STATUS_NO_MEMORY;
2268 for (i=0;i<count;i++) {
2269 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2270 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2273 /* sort the results by name */
2274 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2276 if (*r->in.resume_handle >= count) {
2277 *r->out.resume_handle = -1;
2279 return NT_STATUS_NO_MORE_ENTRIES;
2282 /* return the rest, limit by max_size. Note that we
2283 use the w2k3 element size value of 60 */
2284 r->out.domains->count = count - *r->in.resume_handle;
2285 r->out.domains->count = MIN(r->out.domains->count,
2286 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2288 r->out.domains->domains = entries + *r->in.resume_handle;
2289 r->out.domains->count = r->out.domains->count;
2291 if (r->out.domains->count < count - *r->in.resume_handle) {
2292 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2293 return STATUS_MORE_ENTRIES;
2296 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2297 * always be larger than the previous input resume handle, in
2298 * particular when hitting the last query it is vital to set the
2299 * resume handle correctly to avoid infinite client loops, as
2300 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2301 * status is NT_STATUS_OK - gd */
2303 *r->out.resume_handle = (uint32_t)-1;
2305 return NT_STATUS_OK;
2309 comparison function for sorting lsa_DomainInformation array
2311 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2313 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2317 lsa_EnumTrustedDomainsEx
2319 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2320 struct lsa_EnumTrustedDomainsEx *r)
2322 struct dcesrv_handle *policy_handle;
2323 struct lsa_TrustDomainInfoInfoEx *entries;
2324 struct lsa_policy_state *policy_state;
2325 struct ldb_message **domains;
2326 const char *attrs[] = {
2329 "securityIdentifier",
2339 *r->out.resume_handle = 0;
2341 r->out.domains->domains = NULL;
2342 r->out.domains->count = 0;
2344 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2346 policy_state = policy_handle->data;
2348 /* search for all users in this domain. This could possibly be cached and
2349 resumed based on resume_key */
2350 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2351 "objectclass=trustedDomain");
2353 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2356 /* convert to lsa_DomainInformation format */
2357 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2359 return NT_STATUS_NO_MEMORY;
2361 for (i=0;i<count;i++) {
2362 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2363 if (!NT_STATUS_IS_OK(nt_status)) {
2368 /* sort the results by name */
2369 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2371 if (*r->in.resume_handle >= count) {
2372 *r->out.resume_handle = -1;
2374 return NT_STATUS_NO_MORE_ENTRIES;
2377 /* return the rest, limit by max_size. Note that we
2378 use the w2k3 element size value of 60 */
2379 r->out.domains->count = count - *r->in.resume_handle;
2380 r->out.domains->count = MIN(r->out.domains->count,
2381 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2383 r->out.domains->domains = entries + *r->in.resume_handle;
2384 r->out.domains->count = r->out.domains->count;
2386 if (r->out.domains->count < count - *r->in.resume_handle) {
2387 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2388 return STATUS_MORE_ENTRIES;
2391 return NT_STATUS_OK;
2398 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2399 struct lsa_OpenAccount *r)
2401 struct dcesrv_handle *h, *ah;
2402 struct lsa_policy_state *state;
2403 struct lsa_account_state *astate;
2405 ZERO_STRUCTP(r->out.acct_handle);
2407 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2411 astate = talloc(dce_call->conn, struct lsa_account_state);
2412 if (astate == NULL) {
2413 return NT_STATUS_NO_MEMORY;
2416 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2417 if (astate->account_sid == NULL) {
2418 talloc_free(astate);
2419 return NT_STATUS_NO_MEMORY;
2422 astate->policy = talloc_reference(astate, state);
2423 astate->access_mask = r->in.access_mask;
2425 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2427 talloc_free(astate);
2428 return NT_STATUS_NO_MEMORY;
2431 ah->data = talloc_steal(ah, astate);
2433 *r->out.acct_handle = ah->wire_handle;
2435 return NT_STATUS_OK;
2440 lsa_EnumPrivsAccount
2442 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2443 TALLOC_CTX *mem_ctx,
2444 struct lsa_EnumPrivsAccount *r)
2446 struct dcesrv_handle *h;
2447 struct lsa_account_state *astate;
2450 struct ldb_message **res;
2451 const char * const attrs[] = { "privilege", NULL};
2452 struct ldb_message_element *el;
2454 struct lsa_PrivilegeSet *privs;
2456 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2460 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2461 if (privs == NULL) {
2462 return NT_STATUS_NO_MEMORY;
2468 *r->out.privs = privs;
2470 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2471 if (sidstr == NULL) {
2472 return NT_STATUS_NO_MEMORY;
2475 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2476 "objectSid=%s", sidstr);
2478 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2481 return NT_STATUS_OK;
2484 el = ldb_msg_find_element(res[0], "privilege");
2485 if (el == NULL || el->num_values == 0) {
2486 return NT_STATUS_OK;
2489 privs->set = talloc_array(privs,
2490 struct lsa_LUIDAttribute, el->num_values);
2491 if (privs->set == NULL) {
2492 return NT_STATUS_NO_MEMORY;
2496 for (i=0;i<el->num_values;i++) {
2497 int id = sec_privilege_id((const char *)el->values[i].data);
2498 if (id == SEC_PRIV_INVALID) {
2499 /* Perhaps an account right, not a privilege */
2502 privs->set[j].attribute = 0;
2503 privs->set[j].luid.low = id;
2504 privs->set[j].luid.high = 0;
2510 return NT_STATUS_OK;
2514 lsa_EnumAccountRights
2516 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2517 TALLOC_CTX *mem_ctx,
2518 struct lsa_EnumAccountRights *r)
2520 struct dcesrv_handle *h;
2521 struct lsa_policy_state *state;
2524 struct ldb_message **res;
2525 const char * const attrs[] = { "privilege", NULL};
2527 struct ldb_message_element *el;
2529 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2533 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2534 if (sidstr == NULL) {
2535 return NT_STATUS_NO_MEMORY;
2538 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2539 "(&(objectSid=%s)(privilege=*))", sidstr);
2541 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2544 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2545 dom_sid_string(mem_ctx, r->in.sid),
2546 ldb_errstring(state->pdb)));
2547 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2550 el = ldb_msg_find_element(res[0], "privilege");
2551 if (el == NULL || el->num_values == 0) {
2552 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2555 r->out.rights->count = el->num_values;
2556 r->out.rights->names = talloc_array(r->out.rights,
2557 struct lsa_StringLarge, r->out.rights->count);
2558 if (r->out.rights->names == NULL) {
2559 return NT_STATUS_NO_MEMORY;
2562 for (i=0;i<el->num_values;i++) {
2563 r->out.rights->names[i].string = (const char *)el->values[i].data;
2566 return NT_STATUS_OK;
2572 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2574 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2575 TALLOC_CTX *mem_ctx,
2576 struct lsa_policy_state *state,
2578 struct dom_sid *sid,
2579 const struct lsa_RightSet *rights)
2581 const char *sidstr, *sidndrstr;
2582 struct ldb_message *msg;
2583 struct ldb_message_element *el;
2586 struct lsa_EnumAccountRights r2;
2589 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2590 SECURITY_ADMINISTRATOR) {
2591 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2592 return NT_STATUS_ACCESS_DENIED;
2595 msg = ldb_msg_new(mem_ctx);
2597 return NT_STATUS_NO_MEMORY;
2600 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2601 if (sidndrstr == NULL) {
2603 return NT_STATUS_NO_MEMORY;
2606 sidstr = dom_sid_string(msg, sid);
2607 if (sidstr == NULL) {
2609 return NT_STATUS_NO_MEMORY;
2612 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2613 if (dnstr == NULL) {
2615 return NT_STATUS_NO_MEMORY;
2618 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2619 if (msg->dn == NULL) {
2621 return NT_STATUS_NO_MEMORY;
2624 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2627 r2.in.handle = &state->handle->wire_handle;
2629 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2631 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2632 if (!NT_STATUS_IS_OK(status)) {
2633 ZERO_STRUCTP(r2.out.rights);
2637 for (i=0;i<rights->count;i++) {
2638 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2639 if (sec_right_bit(rights->names[i].string) == 0) {
2641 return NT_STATUS_NO_SUCH_PRIVILEGE;
2645 return NT_STATUS_NO_SUCH_PRIVILEGE;
2648 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2650 for (j=0;j<r2.out.rights->count;j++) {
2651 if (strcasecmp_m(r2.out.rights->names[j].string,
2652 rights->names[i].string) == 0) {
2656 if (j != r2.out.rights->count) continue;
2659 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2660 if (ret != LDB_SUCCESS) {
2662 return NT_STATUS_NO_MEMORY;
2666 el = ldb_msg_find_element(msg, "privilege");
2669 return NT_STATUS_OK;
2672 el->flags = ldb_flag;
2674 ret = ldb_modify(state->pdb, msg);
2675 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2676 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2678 return NT_STATUS_NO_MEMORY;
2680 ldb_msg_add_string(msg, "comment", "added via LSA");
2681 ret = ldb_add(state->pdb, msg);
2683 if (ret != LDB_SUCCESS) {
2684 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2686 return NT_STATUS_OK;
2688 DEBUG(3, ("Could not %s attributes from %s: %s",
2689 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2690 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2692 return NT_STATUS_UNEXPECTED_IO_ERROR;
2696 return NT_STATUS_OK;
2700 lsa_AddPrivilegesToAccount
2702 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2703 struct lsa_AddPrivilegesToAccount *r)
2705 struct lsa_RightSet rights;
2706 struct dcesrv_handle *h;
2707 struct lsa_account_state *astate;
2710 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2714 rights.count = r->in.privs->count;
2715 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2716 if (rights.names == NULL) {
2717 return NT_STATUS_NO_MEMORY;
2719 for (i=0;i<rights.count;i++) {
2720 int id = r->in.privs->set[i].luid.low;
2721 if (r->in.privs->set[i].luid.high) {
2722 return NT_STATUS_NO_SUCH_PRIVILEGE;
2724 rights.names[i].string = sec_privilege_name(id);
2725 if (rights.names[i].string == NULL) {
2726 return NT_STATUS_NO_SUCH_PRIVILEGE;
2730 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2731 LDB_FLAG_MOD_ADD, astate->account_sid,
2737 lsa_RemovePrivilegesFromAccount
2739 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2740 struct lsa_RemovePrivilegesFromAccount *r)
2742 struct lsa_RightSet *rights;
2743 struct dcesrv_handle *h;
2744 struct lsa_account_state *astate;
2747 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2751 rights = talloc(mem_ctx, struct lsa_RightSet);
2753 if (r->in.remove_all == 1 &&
2754 r->in.privs == NULL) {
2755 struct lsa_EnumAccountRights r2;
2758 r2.in.handle = &astate->policy->handle->wire_handle;
2759 r2.in.sid = astate->account_sid;
2760 r2.out.rights = rights;
2762 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2763 if (!NT_STATUS_IS_OK(status)) {
2767 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2768 LDB_FLAG_MOD_DELETE, astate->account_sid,
2772 if (r->in.remove_all != 0) {
2773 return NT_STATUS_INVALID_PARAMETER;
2776 rights->count = r->in.privs->count;
2777 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2778 if (rights->names == NULL) {
2779 return NT_STATUS_NO_MEMORY;
2781 for (i=0;i<rights->count;i++) {
2782 int id = r->in.privs->set[i].luid.low;
2783 if (r->in.privs->set[i].luid.high) {
2784 return NT_STATUS_NO_SUCH_PRIVILEGE;
2786 rights->names[i].string = sec_privilege_name(id);
2787 if (rights->names[i].string == NULL) {
2788 return NT_STATUS_NO_SUCH_PRIVILEGE;
2792 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2793 LDB_FLAG_MOD_DELETE, astate->account_sid,
2799 lsa_GetQuotasForAccount
2801 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2802 struct lsa_GetQuotasForAccount *r)
2804 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2809 lsa_SetQuotasForAccount
2811 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2812 struct lsa_SetQuotasForAccount *r)
2814 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2819 lsa_GetSystemAccessAccount
2821 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2822 struct lsa_GetSystemAccessAccount *r)
2824 struct dcesrv_handle *h;
2825 struct lsa_account_state *astate;
2828 struct ldb_message **res;
2829 const char * const attrs[] = { "privilege", NULL};
2830 struct ldb_message_element *el;
2833 *(r->out.access_mask) = 0x00000000;
2835 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2839 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2840 if (sidstr == NULL) {
2841 return NT_STATUS_NO_MEMORY;
2844 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2845 "objectSid=%s", sidstr);
2847 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2850 return NT_STATUS_OK;
2853 el = ldb_msg_find_element(res[0], "privilege");
2854 if (el == NULL || el->num_values == 0) {
2855 return NT_STATUS_OK;
2858 for (i=0;i<el->num_values;i++) {
2859 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2860 if (right_bit == 0) {
2861 /* Perhaps an privilege, not a right */
2864 *(r->out.access_mask) |= right_bit;
2867 return NT_STATUS_OK;
2872 lsa_SetSystemAccessAccount
2874 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2875 struct lsa_SetSystemAccessAccount *r)
2877 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2884 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2885 struct lsa_CreateSecret *r)
2887 struct dcesrv_handle *policy_handle;
2888 struct lsa_policy_state *policy_state;
2889 struct lsa_secret_state *secret_state;
2890 struct dcesrv_handle *handle;
2891 struct ldb_message **msgs, *msg;
2892 const char *attrs[] = {
2900 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2901 ZERO_STRUCTP(r->out.sec_handle);
2903 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2905 case SECURITY_SYSTEM:
2906 case SECURITY_ADMINISTRATOR:
2909 /* Users and annonymous are not allowed create secrets */
2910 return NT_STATUS_ACCESS_DENIED;
2913 policy_state = policy_handle->data;
2915 if (!r->in.name.string) {
2916 return NT_STATUS_INVALID_PARAMETER;
2919 secret_state = talloc(mem_ctx, struct lsa_secret_state);
2920 NT_STATUS_HAVE_NO_MEMORY(secret_state);
2921 secret_state->policy = policy_state;
2923 msg = ldb_msg_new(mem_ctx);
2925 return NT_STATUS_NO_MEMORY;
2928 if (strncmp("G$", r->in.name.string, 2) == 0) {
2931 secret_state->global = true;
2933 name = &r->in.name.string[2];
2934 if (strlen(name) == 0) {
2935 return NT_STATUS_INVALID_PARAMETER;
2938 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2939 ldb_binary_encode_string(mem_ctx, name));
2940 NT_STATUS_HAVE_NO_MEMORY(name2);
2942 /* We need to connect to the database as system, as this is one
2943 * of the rare RPC calls that must read the secrets (and this
2944 * is denied otherwise) */
2945 secret_state->sam_ldb = talloc_reference(secret_state,
2946 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));
2947 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2949 /* search for the secret record */
2950 ret = gendb_search(secret_state->sam_ldb,
2951 mem_ctx, policy_state->system_dn, &msgs, attrs,
2952 "(&(cn=%s)(objectclass=secret))",
2955 return NT_STATUS_OBJECT_NAME_COLLISION;
2959 DEBUG(0,("Failure searching for CN=%s: %s\n",
2960 name2, ldb_errstring(secret_state->sam_ldb)));
2961 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2964 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2965 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2966 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2967 return NT_STATUS_NO_MEMORY;
2970 ret = ldb_msg_add_string(msg, "cn", name2);
2971 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2973 secret_state->global = false;
2975 name = r->in.name.string;
2976 if (strlen(name) == 0) {
2977 return NT_STATUS_INVALID_PARAMETER;
2980 secret_state->sam_ldb = talloc_reference(secret_state,
2981 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
2982 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2984 /* search for the secret record */
2985 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2986 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2988 "(&(cn=%s)(objectclass=secret))",
2989 ldb_binary_encode_string(mem_ctx, name));
2991 return NT_STATUS_OBJECT_NAME_COLLISION;
2995 DEBUG(0,("Failure searching for CN=%s: %s\n",
2996 name, ldb_errstring(secret_state->sam_ldb)));
2997 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3000 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3001 "cn=%s,cn=LSA Secrets", name);
3002 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3003 ret = ldb_msg_add_string(msg, "cn", name);
3004 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3007 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3008 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3010 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3011 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3013 /* create the secret */
3014 ret = ldb_add(secret_state->sam_ldb, msg);
3015 if (ret != LDB_SUCCESS) {
3016 DEBUG(0,("Failed to create secret record %s: %s\n",
3017 ldb_dn_get_linearized(msg->dn),
3018 ldb_errstring(secret_state->sam_ldb)));
3019 return NT_STATUS_ACCESS_DENIED;
3022 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3023 NT_STATUS_HAVE_NO_MEMORY(handle);
3025 handle->data = talloc_steal(handle, secret_state);
3027 secret_state->access_mask = r->in.access_mask;
3028 secret_state->policy = talloc_reference(secret_state, policy_state);
3029 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3031 *r->out.sec_handle = handle->wire_handle;
3033 return NT_STATUS_OK;
3040 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3041 struct lsa_OpenSecret *r)
3043 struct dcesrv_handle *policy_handle;
3045 struct lsa_policy_state *policy_state;
3046 struct lsa_secret_state *secret_state;
3047 struct dcesrv_handle *handle;
3048 struct ldb_message **msgs;
3049 const char *attrs[] = {
3057 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3058 ZERO_STRUCTP(r->out.sec_handle);
3059 policy_state = policy_handle->data;
3061 if (!r->in.name.string) {
3062 return NT_STATUS_INVALID_PARAMETER;
3065 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3067 case SECURITY_SYSTEM:
3068 case SECURITY_ADMINISTRATOR:
3071 /* Users and annonymous are not allowed to access secrets */
3072 return NT_STATUS_ACCESS_DENIED;
3075 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3076 if (!secret_state) {
3077 return NT_STATUS_NO_MEMORY;
3079 secret_state->policy = policy_state;
3081 if (strncmp("G$", r->in.name.string, 2) == 0) {
3082 name = &r->in.name.string[2];
3083 /* 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) */
3084 secret_state->sam_ldb = talloc_reference(secret_state,
3085 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));
3086 secret_state->global = true;
3088 if (strlen(name) < 1) {
3089 return NT_STATUS_INVALID_PARAMETER;
3092 /* search for the secret record */
3093 ret = gendb_search(secret_state->sam_ldb,
3094 mem_ctx, policy_state->system_dn, &msgs, attrs,
3095 "(&(cn=%s Secret)(objectclass=secret))",
3096 ldb_binary_encode_string(mem_ctx, name));
3098 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3102 DEBUG(0,("Found %d records matching DN %s\n", ret,
3103 ldb_dn_get_linearized(policy_state->system_dn)));
3104 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3107 secret_state->global = false;
3108 secret_state->sam_ldb = talloc_reference(secret_state,
3109 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3111 name = r->in.name.string;
3112 if (strlen(name) < 1) {
3113 return NT_STATUS_INVALID_PARAMETER;
3116 /* search for the secret record */
3117 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3118 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3120 "(&(cn=%s)(objectclass=secret))",
3121 ldb_binary_encode_string(mem_ctx, name));
3123 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3127 DEBUG(0,("Found %d records matching CN=%s\n",
3128 ret, ldb_binary_encode_string(mem_ctx, name)));
3129 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3133 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3135 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3137 return NT_STATUS_NO_MEMORY;
3140 handle->data = talloc_steal(handle, secret_state);
3142 secret_state->access_mask = r->in.access_mask;
3143 secret_state->policy = talloc_reference(secret_state, policy_state);
3145 *r->out.sec_handle = handle->wire_handle;
3147 return NT_STATUS_OK;
3154 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3155 struct lsa_SetSecret *r)
3158 struct dcesrv_handle *h;
3159 struct lsa_secret_state *secret_state;
3160 struct ldb_message *msg;
3161 DATA_BLOB session_key;
3162 DATA_BLOB crypt_secret, secret;
3165 NTSTATUS status = NT_STATUS_OK;
3167 struct timeval now = timeval_current();
3168 NTTIME nt_now = timeval_to_nttime(&now);
3170 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3172 secret_state = h->data;
3174 msg = ldb_msg_new(mem_ctx);
3176 return NT_STATUS_NO_MEMORY;
3179 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3181 return NT_STATUS_NO_MEMORY;
3183 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3184 if (!NT_STATUS_IS_OK(status)) {
3188 if (r->in.old_val) {
3190 crypt_secret.data = r->in.old_val->data;
3191 crypt_secret.length = r->in.old_val->size;
3193 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3194 if (!NT_STATUS_IS_OK(status)) {
3198 val.data = secret.data;
3199 val.length = secret.length;
3202 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3203 return NT_STATUS_NO_MEMORY;
3206 /* set old value mtime */
3207 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3208 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3209 return NT_STATUS_NO_MEMORY;
3213 /* If the old value is not set, then migrate the
3214 * current value to the old value */
3215 const struct ldb_val *old_val;
3216 NTTIME last_set_time;
3217 struct ldb_message **res;
3218 const char *attrs[] = {
3224 /* search for the secret record */
3225 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3226 secret_state->secret_dn, &res, attrs);
3228 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3232 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3233 ldb_dn_get_linearized(secret_state->secret_dn)));
3234 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3237 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3238 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3242 if (ldb_msg_add_value(msg, "priorValue",
3243 old_val, NULL) != LDB_SUCCESS) {
3244 return NT_STATUS_NO_MEMORY;
3247 if (samdb_msg_add_delete(secret_state->sam_ldb,
3248 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3249 return NT_STATUS_NO_MEMORY;
3253 /* set old value mtime */
3254 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3255 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3256 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3257 return NT_STATUS_NO_MEMORY;
3260 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3261 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3262 return NT_STATUS_NO_MEMORY;
3267 if (r->in.new_val) {
3269 crypt_secret.data = r->in.new_val->data;
3270 crypt_secret.length = r->in.new_val->size;
3272 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3273 if (!NT_STATUS_IS_OK(status)) {
3277 val.data = secret.data;
3278 val.length = secret.length;
3281 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3282 return NT_STATUS_NO_MEMORY;
3285 /* set new value mtime */
3286 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3287 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3288 return NT_STATUS_NO_MEMORY;
3291 /* NULL out the NEW value */
3292 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3293 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3294 return NT_STATUS_NO_MEMORY;
3296 if (samdb_msg_add_delete(secret_state->sam_ldb,
3297 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3298 return NT_STATUS_NO_MEMORY;
3302 /* modify the samdb record */
3303 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3304 if (ret != LDB_SUCCESS) {
3305 return dsdb_ldb_err_to_ntstatus(ret);
3308 return NT_STATUS_OK;
3315 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3316 struct lsa_QuerySecret *r)
3318 struct dcesrv_handle *h;
3319 struct lsa_secret_state *secret_state;
3320 struct ldb_message *msg;
3321 DATA_BLOB session_key;
3322 DATA_BLOB crypt_secret, secret;
3324 struct ldb_message **res;
3325 const char *attrs[] = {
3335 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3337 /* Ensure user is permitted to read this... */
3338 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3340 case SECURITY_SYSTEM:
3341 case SECURITY_ADMINISTRATOR:
3344 /* Users and annonymous are not allowed to read secrets */
3345 return NT_STATUS_ACCESS_DENIED;
3348 secret_state = h->data;
3350 /* pull all the user attributes */
3351 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3352 secret_state->secret_dn, &res, attrs);
3354 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3358 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3359 if (!NT_STATUS_IS_OK(nt_status)) {
3363 if (r->in.old_val) {
3364 const struct ldb_val *prior_val;
3365 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3366 if (!r->out.old_val) {
3367 return NT_STATUS_NO_MEMORY;
3369 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3371 if (prior_val && prior_val->length) {
3372 secret.data = prior_val->data;
3373 secret.length = prior_val->length;
3376 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3377 if (!crypt_secret.length) {
3378 return NT_STATUS_NO_MEMORY;
3380 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3381 if (!r->out.old_val->buf) {
3382 return NT_STATUS_NO_MEMORY;
3384 r->out.old_val->buf->size = crypt_secret.length;
3385 r->out.old_val->buf->length = crypt_secret.length;
3386 r->out.old_val->buf->data = crypt_secret.data;
3390 if (r->in.old_mtime) {
3391 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3392 if (!r->out.old_mtime) {
3393 return NT_STATUS_NO_MEMORY;
3395 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3398 if (r->in.new_val) {
3399 const struct ldb_val *new_val;
3400 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3401 if (!r->out.new_val) {
3402 return NT_STATUS_NO_MEMORY;
3405 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3407 if (new_val && new_val->length) {
3408 secret.data = new_val->data;
3409 secret.length = new_val->length;
3412 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3413 if (!crypt_secret.length) {
3414 return NT_STATUS_NO_MEMORY;
3416 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3417 if (!r->out.new_val->buf) {
3418 return NT_STATUS_NO_MEMORY;
3420 r->out.new_val->buf->length = crypt_secret.length;
3421 r->out.new_val->buf->size = crypt_secret.length;
3422 r->out.new_val->buf->data = crypt_secret.data;
3426 if (r->in.new_mtime) {
3427 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3428 if (!r->out.new_mtime) {
3429 return NT_STATUS_NO_MEMORY;
3431 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3434 return NT_STATUS_OK;
3441 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3442 TALLOC_CTX *mem_ctx,
3443 struct lsa_LookupPrivValue *r)
3445 struct dcesrv_handle *h;
3448 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3450 id = sec_privilege_id(r->in.name->string);
3451 if (id == SEC_PRIV_INVALID) {
3452 return NT_STATUS_NO_SUCH_PRIVILEGE;
3455 r->out.luid->low = id;
3456 r->out.luid->high = 0;
3458 return NT_STATUS_OK;
3465 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3466 TALLOC_CTX *mem_ctx,
3467 struct lsa_LookupPrivName *r)
3469 struct dcesrv_handle *h;
3470 struct lsa_StringLarge *name;
3471 const char *privname;
3473 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3475 if (r->in.luid->high != 0) {
3476 return NT_STATUS_NO_SUCH_PRIVILEGE;
3479 privname = sec_privilege_name(r->in.luid->low);
3480 if (privname == NULL) {
3481 return NT_STATUS_NO_SUCH_PRIVILEGE;
3484 name = talloc(mem_ctx, struct lsa_StringLarge);
3486 return NT_STATUS_NO_MEMORY;
3489 name->string = privname;
3491 *r->out.name = name;
3493 return NT_STATUS_OK;
3498 lsa_LookupPrivDisplayName
3500 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3501 TALLOC_CTX *mem_ctx,
3502 struct lsa_LookupPrivDisplayName *r)
3504 struct dcesrv_handle *h;
3505 struct lsa_StringLarge *disp_name = NULL;
3506 enum sec_privilege id;
3508 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3510 id = sec_privilege_id(r->in.name->string);
3511 if (id == SEC_PRIV_INVALID) {
3512 return NT_STATUS_NO_SUCH_PRIVILEGE;
3515 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3516 if (disp_name == NULL) {
3517 return NT_STATUS_NO_MEMORY;
3520 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3521 if (disp_name->string == NULL) {
3522 return NT_STATUS_INTERNAL_ERROR;
3525 *r->out.disp_name = disp_name;
3526 *r->out.returned_language_id = 0;
3528 return NT_STATUS_OK;
3533 lsa_EnumAccountsWithUserRight
3535 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3536 TALLOC_CTX *mem_ctx,
3537 struct lsa_EnumAccountsWithUserRight *r)
3539 struct dcesrv_handle *h;
3540 struct lsa_policy_state *state;
3542 struct ldb_message **res;
3543 const char * const attrs[] = { "objectSid", NULL};
3544 const char *privname;
3546 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3550 if (r->in.name == NULL) {
3551 return NT_STATUS_NO_SUCH_PRIVILEGE;
3554 privname = r->in.name->string;
3555 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3556 return NT_STATUS_NO_SUCH_PRIVILEGE;
3559 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3560 "privilege=%s", privname);
3562 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3565 return NT_STATUS_NO_MORE_ENTRIES;
3568 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3569 if (r->out.sids->sids == NULL) {
3570 return NT_STATUS_NO_MEMORY;
3572 for (i=0;i<ret;i++) {
3573 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3574 res[i], "objectSid");
3575 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3577 r->out.sids->num_sids = ret;
3579 return NT_STATUS_OK;
3584 lsa_AddAccountRights
3586 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3587 TALLOC_CTX *mem_ctx,
3588 struct lsa_AddAccountRights *r)
3590 struct dcesrv_handle *h;
3591 struct lsa_policy_state *state;
3593 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3597 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3599 r->in.sid, r->in.rights);
3604 lsa_RemoveAccountRights
3606 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3607 TALLOC_CTX *mem_ctx,
3608 struct lsa_RemoveAccountRights *r)
3610 struct dcesrv_handle *h;
3611 struct lsa_policy_state *state;
3613 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3617 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3618 LDB_FLAG_MOD_DELETE,
3619 r->in.sid, r->in.rights);
3624 lsa_StorePrivateData
3626 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3627 struct lsa_StorePrivateData *r)
3629 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3634 lsa_RetrievePrivateData
3636 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3637 struct lsa_RetrievePrivateData *r)
3639 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3646 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3647 struct lsa_GetUserName *r)
3649 enum dcerpc_transport_t transport =
3650 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3651 NTSTATUS status = NT_STATUS_OK;
3652 const char *account_name;
3653 const char *authority_name;
3654 struct lsa_String *_account_name;
3655 struct lsa_String *_authority_name = NULL;
3657 if (transport != NCACN_NP && transport != NCALRPC) {
3658 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3661 /* this is what w2k3 does */
3662 r->out.account_name = r->in.account_name;
3663 r->out.authority_name = r->in.authority_name;
3665 if (r->in.account_name
3666 && *r->in.account_name
3667 /* && *(*r->in.account_name)->string */
3669 return NT_STATUS_INVALID_PARAMETER;
3672 if (r->in.authority_name
3673 && *r->in.authority_name
3674 /* && *(*r->in.authority_name)->string */
3676 return NT_STATUS_INVALID_PARAMETER;
3679 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3680 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3682 _account_name = talloc(mem_ctx, struct lsa_String);
3683 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3684 _account_name->string = account_name;
3686 if (r->in.authority_name) {
3687 _authority_name = talloc(mem_ctx, struct lsa_String);
3688 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3689 _authority_name->string = authority_name;
3692 *r->out.account_name = _account_name;
3693 if (r->out.authority_name) {
3694 *r->out.authority_name = _authority_name;
3703 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3704 TALLOC_CTX *mem_ctx,
3705 struct lsa_SetInfoPolicy2 *r)
3707 /* need to support these */
3708 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3711 static void kdc_get_policy(struct loadparm_context *lp_ctx,
3712 struct smb_krb5_context *smb_krb5_context,
3713 struct lsa_DomainInfoKerberos *k)
3715 time_t svc_tkt_lifetime;
3716 time_t usr_tkt_lifetime;
3717 time_t renewal_lifetime;
3719 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
3721 /* Our KDC always re-validates the client */
3722 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
3724 lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
3725 &usr_tkt_lifetime, &renewal_lifetime);
3727 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
3728 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
3729 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
3730 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
3731 However in the parent function we basically just did a full
3732 krb5_context init with the only purpose of getting a global
3733 config option (the max skew), it would probably make more sense
3734 to have a lp_ or ldb global option as the samba default */
3735 if (smb_krb5_context) {
3736 unix_to_nt_time(&k->clock_skew,
3737 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
3743 lsa_QueryDomainInformationPolicy
3745 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3746 TALLOC_CTX *mem_ctx,
3747 struct lsa_QueryDomainInformationPolicy *r)
3749 union lsa_DomainInformationPolicy *info;
3751 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3753 return NT_STATUS_NO_MEMORY;
3756 switch (r->in.level) {
3757 case LSA_DOMAIN_INFO_POLICY_EFS:
3759 *r->out.info = NULL;
3760 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3761 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3763 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3764 struct smb_krb5_context *smb_krb5_context;
3765 int ret = smb_krb5_init_context(mem_ctx,
3766 dce_call->conn->dce_ctx->lp_ctx,
3770 *r->out.info = NULL;
3771 return NT_STATUS_INTERNAL_ERROR;
3773 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3776 talloc_free(smb_krb5_context);
3777 *r->out.info = info;
3778 return NT_STATUS_OK;
3782 *r->out.info = NULL;
3783 return NT_STATUS_INVALID_INFO_CLASS;
3788 lsa_SetDomInfoPolicy
3790 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3791 TALLOC_CTX *mem_ctx,
3792 struct lsa_SetDomainInformationPolicy *r)
3794 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3800 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3801 TALLOC_CTX *mem_ctx,
3802 struct lsa_TestCall *r)
3804 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3810 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3811 struct lsa_CREDRWRITE *r)
3813 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3820 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3821 struct lsa_CREDRREAD *r)
3823 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3830 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3831 struct lsa_CREDRENUMERATE *r)
3833 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3838 lsa_CREDRWRITEDOMAINCREDENTIALS
3840 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3841 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3843 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3848 lsa_CREDRREADDOMAINCREDENTIALS
3850 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3851 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3853 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3860 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3861 struct lsa_CREDRDELETE *r)
3863 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3868 lsa_CREDRGETTARGETINFO
3870 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3871 struct lsa_CREDRGETTARGETINFO *r)
3873 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3878 lsa_CREDRPROFILELOADED
3880 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3881 struct lsa_CREDRPROFILELOADED *r)
3883 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3888 lsa_CREDRGETSESSIONTYPES
3890 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3891 struct lsa_CREDRGETSESSIONTYPES *r)
3893 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3898 lsa_LSARREGISTERAUDITEVENT
3900 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3901 struct lsa_LSARREGISTERAUDITEVENT *r)
3903 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3908 lsa_LSARGENAUDITEVENT
3910 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3911 struct lsa_LSARGENAUDITEVENT *r)
3913 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3918 lsa_LSARUNREGISTERAUDITEVENT
3920 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3921 struct lsa_LSARUNREGISTERAUDITEVENT *r)
3923 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3928 lsa_lsaRQueryForestTrustInformation
3930 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3931 struct lsa_lsaRQueryForestTrustInformation *r)
3933 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3936 #define DNS_CMP_MATCH 0
3937 #define DNS_CMP_FIRST_IS_CHILD 1
3938 #define DNS_CMP_SECOND_IS_CHILD 2
3939 #define DNS_CMP_NO_MATCH 3
3941 /* this function assumes names are well formed DNS names.
3942 * it doesn't validate them */
3943 static int dns_cmp(const char *s1, size_t l1,
3944 const char *s2, size_t l2)
3946 const char *p1, *p2;
3951 if (strcasecmp_m(s1, s2) == 0) {
3952 return DNS_CMP_MATCH;
3954 return DNS_CMP_NO_MATCH;
3962 cret = DNS_CMP_FIRST_IS_CHILD;
3968 cret = DNS_CMP_SECOND_IS_CHILD;
3971 if (p1[t1 - t2 - 1] != '.') {
3972 return DNS_CMP_NO_MATCH;
3975 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3979 return DNS_CMP_NO_MATCH;
3982 /* decode all TDOs forest trust info blobs */
3983 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3984 struct ldb_message *msg,
3985 struct ForestTrustInfo *info)
3987 const struct ldb_val *ft_blob;
3988 enum ndr_err_code ndr_err;
3990 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3991 if (!ft_blob || !ft_blob->data) {
3992 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3994 /* ldb_val is equivalent to DATA_BLOB */
3995 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3996 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3997 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3998 return NT_STATUS_INVALID_DOMAIN_STATE;
4001 return NT_STATUS_OK;
4004 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
4005 struct ForestTrustInfo *fti)
4007 struct ForestTrustDataDomainInfo *info;
4008 struct ForestTrustInfoRecord *rec;
4012 fti->records = talloc_array(fti,
4013 struct ForestTrustInfoRecordArmor, 2);
4014 if (!fti->records) {
4015 return NT_STATUS_NO_MEMORY;
4019 rec = &fti->records[0].record;
4023 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
4025 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
4026 if (!rec->data.name.string) {
4027 return NT_STATUS_NO_MEMORY;
4029 rec->data.name.size = strlen(rec->data.name.string);
4032 rec = &fti->records[1].record;
4036 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
4038 info = &rec->data.info;
4040 info->sid = *ps->domain_sid;
4041 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
4042 if (!info->dns_name.string) {
4043 return NT_STATUS_NO_MEMORY;
4045 info->dns_name.size = strlen(info->dns_name.string);
4046 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
4047 if (!info->netbios_name.string) {
4048 return NT_STATUS_NO_MEMORY;
4050 info->netbios_name.size = strlen(info->netbios_name.string);
4052 return NT_STATUS_OK;
4055 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
4056 struct lsa_ForestTrustInformation *lfti,
4057 struct ForestTrustInfo *fti)
4059 struct lsa_ForestTrustRecord *lrec;
4060 struct ForestTrustInfoRecord *rec;
4061 struct lsa_StringLarge *tln;
4062 struct lsa_ForestTrustDomainInfo *info;
4066 fti->count = lfti->count;
4067 fti->records = talloc_array(mem_ctx,
4068 struct ForestTrustInfoRecordArmor,
4070 if (!fti->records) {
4071 return NT_STATUS_NO_MEMORY;
4073 for (i = 0; i < fti->count; i++) {
4074 lrec = lfti->entries[i];
4075 rec = &fti->records[i].record;
4077 rec->flags = lrec->flags;
4078 rec->timestamp = lrec->time;
4079 rec->type = lrec->type;
4081 switch (lrec->type) {
4082 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4083 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4084 tln = &lrec->forest_trust_data.top_level_name;
4085 rec->data.name.string =
4086 talloc_strdup(mem_ctx, tln->string);
4087 if (!rec->data.name.string) {
4088 return NT_STATUS_NO_MEMORY;
4090 rec->data.name.size = strlen(rec->data.name.string);
4092 case LSA_FOREST_TRUST_DOMAIN_INFO:
4093 info = &lrec->forest_trust_data.domain_info;
4094 rec->data.info.sid = *info->domain_sid;
4095 rec->data.info.dns_name.string =
4096 talloc_strdup(mem_ctx,
4097 info->dns_domain_name.string);
4098 if (!rec->data.info.dns_name.string) {
4099 return NT_STATUS_NO_MEMORY;
4101 rec->data.info.dns_name.size =
4102 strlen(rec->data.info.dns_name.string);
4103 rec->data.info.netbios_name.string =
4104 talloc_strdup(mem_ctx,
4105 info->netbios_domain_name.string);
4106 if (!rec->data.info.netbios_name.string) {
4107 return NT_STATUS_NO_MEMORY;
4109 rec->data.info.netbios_name.size =
4110 strlen(rec->data.info.netbios_name.string);
4113 return NT_STATUS_INVALID_DOMAIN_STATE;
4117 return NT_STATUS_OK;
4120 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4121 uint32_t idx, uint32_t collision_type,
4122 uint32_t conflict_type, const char *tdo_name);
4124 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4125 const char *tdo_name,
4126 struct ForestTrustInfo *tdo_fti,
4127 struct ForestTrustInfo *new_fti,
4128 struct lsa_ForestTrustCollisionInfo *c_info)
4130 struct ForestTrustInfoRecord *nrec;
4131 struct ForestTrustInfoRecord *trec;
4132 const char *dns_name;
4133 const char *nb_name;
4134 struct dom_sid *sid;
4138 NTSTATUS nt_status = NT_STATUS_OK;
4139 uint32_t new_fti_idx;
4141 /* use always TDO type, until we understand when Xref can be used */
4142 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4150 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4152 nrec = &new_fti->records[new_fti_idx].record;
4154 tln_conflict = false;
4155 sid_conflict = false;
4156 nb_conflict = false;
4159 switch (nrec->type) {
4160 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4161 /* exclusions do not conflict by definition */
4164 case FOREST_TRUST_TOP_LEVEL_NAME:
4165 dns_name = nrec->data.name.string;
4166 dns_len = nrec->data.name.size;
4169 case LSA_FOREST_TRUST_DOMAIN_INFO:
4170 dns_name = nrec->data.info.dns_name.string;
4171 dns_len = nrec->data.info.dns_name.size;
4172 nb_name = nrec->data.info.netbios_name.string;
4173 sid = &nrec->data.info.sid;
4177 if (!dns_name) continue;
4179 /* check if this is already taken and not excluded */
4180 for (i = 0; i < tdo_fti->count; i++) {
4181 trec = &tdo_fti->records[i].record;
4183 switch (trec->type) {
4184 case FOREST_TRUST_TOP_LEVEL_NAME:
4186 tname = trec->data.name.string;
4187 tlen = trec->data.name.size;
4189 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4191 tname = trec->data.name.string;
4192 tlen = trec->data.name.size;
4194 case FOREST_TRUST_DOMAIN_INFO:
4196 tname = trec->data.info.dns_name.string;
4197 tlen = trec->data.info.dns_name.size;
4199 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4202 /* if it matches exclusion,
4203 * it doesn't conflict */
4209 case DNS_CMP_FIRST_IS_CHILD:
4210 case DNS_CMP_SECOND_IS_CHILD:
4211 tln_conflict = true;
4217 /* explicit exclusion, no dns name conflict here */
4219 tln_conflict = false;
4222 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4226 /* also test for domain info */
4227 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4228 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4229 sid_conflict = true;
4231 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4232 strcasecmp_m(trec->data.info.netbios_name.string,
4239 nt_status = add_collision(c_info, new_fti_idx,
4241 LSA_TLN_DISABLED_CONFLICT,
4243 if (!NT_STATUS_IS_OK(nt_status)) {
4248 nt_status = add_collision(c_info, new_fti_idx,
4250 LSA_SID_DISABLED_CONFLICT,
4252 if (!NT_STATUS_IS_OK(nt_status)) {
4257 nt_status = add_collision(c_info, new_fti_idx,
4259 LSA_NB_DISABLED_CONFLICT,
4261 if (!NT_STATUS_IS_OK(nt_status)) {
4271 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4272 uint32_t idx, uint32_t collision_type,
4273 uint32_t conflict_type, const char *tdo_name)
4275 struct lsa_ForestTrustCollisionRecord **es;
4276 uint32_t i = c_info->count;
4278 es = talloc_realloc(c_info, c_info->entries,
4279 struct lsa_ForestTrustCollisionRecord *, i + 1);
4281 return NT_STATUS_NO_MEMORY;
4283 c_info->entries = es;
4284 c_info->count = i + 1;
4286 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4288 return NT_STATUS_NO_MEMORY;
4292 es[i]->type = collision_type;
4293 es[i]->flags.flags = conflict_type;
4294 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4295 if (!es[i]->name.string) {
4296 return NT_STATUS_NO_MEMORY;
4298 es[i]->name.size = strlen(es[i]->name.string);
4300 return NT_STATUS_OK;
4304 lsa_lsaRSetForestTrustInformation
4306 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4307 TALLOC_CTX *mem_ctx,
4308 struct lsa_lsaRSetForestTrustInformation *r)
4310 struct dcesrv_handle *h;
4311 struct lsa_policy_state *p_state;
4312 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4313 "msDS-TrustForestTrustInfo", NULL };
4314 struct ldb_message **dom_res = NULL;
4315 struct ldb_dn *tdo_dn;
4316 struct ldb_message *msg;
4318 const char *td_name;
4319 uint32_t trust_attributes;
4320 struct lsa_ForestTrustCollisionInfo *c_info;
4321 struct ForestTrustInfo *nfti;
4322 struct ForestTrustInfo *fti;
4324 enum ndr_err_code ndr_err;
4329 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4333 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4334 return NT_STATUS_INVALID_DOMAIN_STATE;
4337 /* abort if we are not a PDC */
4338 if (!samdb_is_pdc(p_state->sam_ldb)) {
4339 return NT_STATUS_INVALID_DOMAIN_ROLE;
4342 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4343 if (ret == LDB_SUCCESS && am_rodc) {
4344 return NT_STATUS_NO_SUCH_DOMAIN;
4347 /* check caller has TRUSTED_SET_AUTH */
4349 /* fetch all trusted domain objects */
4350 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4352 &dom_res, trust_attrs,
4353 "(objectclass=trustedDomain)");
4355 return NT_STATUS_NO_SUCH_DOMAIN;
4358 for (i = 0; i < num_res; i++) {
4359 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4360 "trustPartner", NULL);
4362 return NT_STATUS_INVALID_DOMAIN_STATE;
4364 if (strcasecmp_m(td_name,
4365 r->in.trusted_domain_name->string) == 0) {
4370 return NT_STATUS_NO_SUCH_DOMAIN;
4373 tdo_dn = dom_res[i]->dn;
4375 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4376 "trustAttributes", 0);
4377 if (!(trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4378 return NT_STATUS_INVALID_PARAMETER;
4381 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4382 return NT_STATUS_INVALID_PARAMETER;
4385 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4387 return NT_STATUS_NO_MEMORY;
4390 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4391 if (!NT_STATUS_IS_OK(nt_status)) {
4395 c_info = talloc_zero(r->out.collision_info,
4396 struct lsa_ForestTrustCollisionInfo);
4398 return NT_STATUS_NO_MEMORY;
4401 /* first check own info, then other domains */
4402 fti = talloc(mem_ctx, struct ForestTrustInfo);
4404 return NT_STATUS_NO_MEMORY;
4407 nt_status = own_ft_info(p_state, fti);
4408 if (!NT_STATUS_IS_OK(nt_status)) {
4412 nt_status = check_ft_info(c_info, p_state->domain_dns,
4414 if (!NT_STATUS_IS_OK(nt_status)) {
4418 for (i = 0; i < num_res; i++) {
4419 fti = talloc(mem_ctx, struct ForestTrustInfo);
4421 return NT_STATUS_NO_MEMORY;
4424 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4425 if (!NT_STATUS_IS_OK(nt_status)) {
4426 if (NT_STATUS_EQUAL(nt_status,
4427 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4433 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4434 "trustPartner", NULL);
4436 return NT_STATUS_INVALID_DOMAIN_STATE;
4439 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4440 if (!NT_STATUS_IS_OK(nt_status)) {
4445 *r->out.collision_info = c_info;
4447 if (r->in.check_only != 0) {
4448 return NT_STATUS_OK;
4451 /* not just a check, write info back */
4453 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4454 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4455 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4456 return NT_STATUS_INVALID_PARAMETER;
4459 msg = ldb_msg_new(mem_ctx);
4461 return NT_STATUS_NO_MEMORY;
4464 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4466 return NT_STATUS_NO_MEMORY;
4469 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4470 LDB_FLAG_MOD_REPLACE, NULL);
4471 if (ret != LDB_SUCCESS) {
4472 return NT_STATUS_NO_MEMORY;
4474 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4476 if (ret != LDB_SUCCESS) {
4477 return NT_STATUS_NO_MEMORY;
4480 ret = ldb_modify(p_state->sam_ldb, msg);
4481 if (ret != LDB_SUCCESS) {
4482 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4483 ldb_errstring(p_state->sam_ldb)));
4486 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4487 return NT_STATUS_ACCESS_DENIED;
4489 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4493 return NT_STATUS_OK;
4499 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4500 struct lsa_CREDRRENAME *r)
4502 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4508 lsa_LSAROPENPOLICYSCE
4510 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4511 struct lsa_LSAROPENPOLICYSCE *r)
4513 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4518 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4520 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4521 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4523 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4528 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4530 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4531 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4533 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4538 lsa_LSARADTREPORTSECURITYEVENT
4540 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4541 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4543 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4547 /* include the generated boilerplate */
4548 #include "librpc/gen_ndr/ndr_lsa_s.c"
4552 /*****************************************
4553 NOTE! The remaining calls below were
4554 removed in w2k3, so the DCESRV_FAULT()
4555 replies are the correct implementation. Do
4556 not try and fill these in with anything else
4557 ******************************************/
4560 dssetup_DsRoleDnsNameToFlatName
4562 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4563 struct dssetup_DsRoleDnsNameToFlatName *r)
4565 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4570 dssetup_DsRoleDcAsDc
4572 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4573 struct dssetup_DsRoleDcAsDc *r)
4575 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4580 dssetup_DsRoleDcAsReplica
4582 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4583 struct dssetup_DsRoleDcAsReplica *r)
4585 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4590 dssetup_DsRoleDemoteDc
4592 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4593 struct dssetup_DsRoleDemoteDc *r)
4595 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4600 dssetup_DsRoleGetDcOperationProgress
4602 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4603 struct dssetup_DsRoleGetDcOperationProgress *r)
4605 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4610 dssetup_DsRoleGetDcOperationResults
4612 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4613 struct dssetup_DsRoleGetDcOperationResults *r)
4615 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4620 dssetup_DsRoleCancel
4622 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4623 struct dssetup_DsRoleCancel *r)
4625 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4630 dssetup_DsRoleServerSaveStateForUpgrade
4632 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4633 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4635 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4640 dssetup_DsRoleUpgradeDownlevelServer
4642 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4643 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4645 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4650 dssetup_DsRoleAbortDownlevelServerUpgrade
4652 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4653 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4655 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4659 /* include the generated boilerplate */
4660 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4662 NTSTATUS dcerpc_server_lsa_init(void)
4666 ret = dcerpc_server_dssetup_init();
4667 if (!NT_STATUS_IS_OK(ret)) {
4670 ret = dcerpc_server_lsarpc_init();
4671 if (!NT_STATUS_IS_OK(ret)) {