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 dcesrv_handle *p_handle,
1604 TALLOC_CTX *mem_ctx,
1605 struct ldb_message *dom_msg,
1606 enum lsa_TrustDomInfoEnum level,
1607 union lsa_TrustedDomainInfo *info)
1609 struct lsa_policy_state *p_state = p_handle->data;
1610 uint32_t *posix_offset = NULL;
1611 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1612 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1613 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1614 uint32_t *enc_types = NULL;
1615 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1616 struct trustDomainPasswords auth_struct;
1617 struct trustAuthInOutBlob *current_passwords = NULL;
1619 struct ldb_message **msgs;
1620 struct ldb_message *msg;
1621 bool add_outgoing = false;
1622 bool add_incoming = false;
1623 bool del_outgoing = false;
1624 bool del_incoming = false;
1625 bool in_transaction = false;
1630 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1631 posix_offset = &info->posix_offset.posix_offset;
1633 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1634 info_ex = &info->info_ex;
1636 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1637 auth_info = &info->auth_info;
1639 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1640 posix_offset = &info->full_info.posix_offset.posix_offset;
1641 info_ex = &info->full_info.info_ex;
1642 auth_info = &info->full_info.auth_info;
1644 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1645 auth_info_int = &info->auth_info_internal;
1647 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1648 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1649 info_ex = &info->full_info_internal.info_ex;
1650 auth_info_int = &info->full_info_internal.auth_info;
1652 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1653 enc_types = &info->enc_types.enc_types;
1656 return NT_STATUS_INVALID_PARAMETER;
1660 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1662 &trustAuthOutgoing);
1663 if (!NT_STATUS_IS_OK(nt_status)) {
1666 if (trustAuthIncoming.data) {
1667 /* This does the decode of some of this twice, but it is easier that way */
1668 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1669 auth_info->incoming_count,
1670 auth_info->incoming_current_auth_info,
1672 ¤t_passwords);
1673 if (!NT_STATUS_IS_OK(nt_status)) {
1679 /* decode auth_info_int if set */
1680 if (auth_info_int) {
1682 /* now decrypt blob */
1683 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1684 auth_info_int->auth_blob.size);
1686 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1687 &auth_blob, &auth_struct);
1688 if (!NT_STATUS_IS_OK(nt_status)) {
1694 /* verify data matches */
1695 if (info_ex->trust_attributes &
1696 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1697 /* TODO: check what behavior level we have */
1698 if (strcasecmp_m(p_state->domain_dns,
1699 p_state->forest_dns) != 0) {
1700 return NT_STATUS_INVALID_DOMAIN_STATE;
1704 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1705 if (ret == LDB_SUCCESS && am_rodc) {
1706 return NT_STATUS_NO_SUCH_DOMAIN;
1709 /* verify only one object matches the dns/netbios/sid
1710 * triplet and that this is the one we already have */
1711 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1713 info_ex->domain_name.string,
1714 info_ex->netbios_name.string,
1715 info_ex->sid, &msgs);
1716 if (!NT_STATUS_IS_OK(nt_status)) {
1719 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1720 return NT_STATUS_OBJECT_NAME_COLLISION;
1725 /* TODO: should we fetch previous values from the existing entry
1726 * and append them ? */
1727 if (auth_info_int && auth_struct.incoming.count) {
1728 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1729 &auth_struct.incoming,
1730 &trustAuthIncoming);
1731 if (!NT_STATUS_IS_OK(nt_status)) {
1735 current_passwords = &auth_struct.incoming;
1738 trustAuthIncoming = data_blob(NULL, 0);
1741 if (auth_info_int && auth_struct.outgoing.count) {
1742 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1743 &auth_struct.outgoing,
1744 &trustAuthOutgoing);
1745 if (!NT_STATUS_IS_OK(nt_status)) {
1749 trustAuthOutgoing = data_blob(NULL, 0);
1752 msg = ldb_msg_new(mem_ctx);
1754 return NT_STATUS_NO_MEMORY;
1756 msg->dn = dom_msg->dn;
1759 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1762 *posix_offset, NULL);
1763 if (!NT_STATUS_IS_OK(nt_status)) {
1773 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1776 info_ex->trust_direction,
1778 if (!NT_STATUS_IS_OK(nt_status)) {
1782 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1783 add_incoming = true;
1785 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1786 add_outgoing = true;
1789 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1790 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1791 del_incoming = true;
1793 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1794 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1795 del_outgoing = true;
1798 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1799 if (origtype == -1 || origtype != info_ex->trust_type) {
1800 DEBUG(1, ("Attempted to change trust type! "
1801 "Operation not handled\n"));
1802 return NT_STATUS_INVALID_PARAMETER;
1805 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1808 info_ex->trust_attributes,
1810 if (!NT_STATUS_IS_OK(nt_status)) {
1813 /* TODO: check forestFunctionality from ldb opaque */
1814 /* TODO: check what is set makes sense */
1815 /* for now refuse changes */
1816 if (origattrs == -1 ||
1817 origattrs != info_ex->trust_attributes) {
1818 DEBUG(1, ("Attempted to change trust attributes! "
1819 "Operation not handled\n"));
1820 return NT_STATUS_INVALID_PARAMETER;
1825 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1827 "msDS-SupportedEncryptionTypes",
1829 if (!NT_STATUS_IS_OK(nt_status)) {
1834 if (add_incoming && trustAuthIncoming.data) {
1835 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1836 LDB_FLAG_MOD_REPLACE, NULL);
1837 if (ret != LDB_SUCCESS) {
1838 return NT_STATUS_NO_MEMORY;
1840 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1841 &trustAuthIncoming, NULL);
1842 if (ret != LDB_SUCCESS) {
1843 return NT_STATUS_NO_MEMORY;
1846 if (add_outgoing && trustAuthOutgoing.data) {
1847 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1848 LDB_FLAG_MOD_REPLACE, NULL);
1849 if (ret != LDB_SUCCESS) {
1850 return NT_STATUS_NO_MEMORY;
1852 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1853 &trustAuthOutgoing, NULL);
1854 if (ret != LDB_SUCCESS) {
1855 return NT_STATUS_NO_MEMORY;
1859 /* start transaction */
1860 ret = ldb_transaction_start(p_state->sam_ldb);
1861 if (ret != LDB_SUCCESS) {
1862 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1864 in_transaction = true;
1866 if (msg->num_elements) {
1867 ret = ldb_modify(p_state->sam_ldb, msg);
1868 if (ret != LDB_SUCCESS) {
1869 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1870 ldb_dn_get_linearized(msg->dn),
1871 ldb_errstring(p_state->sam_ldb)));
1872 nt_status = dsdb_ldb_err_to_ntstatus(ret);
1877 if (add_incoming || del_incoming) {
1878 const char *netbios_name;
1880 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1882 if (!netbios_name) {
1883 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1887 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
1888 nt_status = update_trust_user(mem_ctx,
1894 if (!NT_STATUS_IS_OK(nt_status)) {
1899 /* ok, all fine, commit transaction and return */
1900 ret = ldb_transaction_commit(p_state->sam_ldb);
1901 if (ret != LDB_SUCCESS) {
1902 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1904 in_transaction = false;
1906 nt_status = NT_STATUS_OK;
1909 if (in_transaction) {
1910 ldb_transaction_cancel(p_state->sam_ldb);
1916 lsa_SetInfomrationTrustedDomain
1918 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1919 struct dcesrv_call_state *dce_call,
1920 TALLOC_CTX *mem_ctx,
1921 struct lsa_SetInformationTrustedDomain *r)
1923 struct dcesrv_handle *h;
1924 struct lsa_trusted_domain_state *td_state;
1925 struct ldb_message **msgs;
1928 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1929 LSA_HANDLE_TRUSTED_DOMAIN);
1931 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1933 /* get the trusted domain object */
1934 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1935 td_state->trusted_domain_dn,
1936 NULL, NULL, NULL, &msgs);
1937 if (!NT_STATUS_IS_OK(nt_status)) {
1938 if (NT_STATUS_EQUAL(nt_status,
1939 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1942 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1945 return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1946 msgs[0], r->in.level, r->in.info);
1951 lsa_DeleteTrustedDomain
1953 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1954 struct lsa_DeleteTrustedDomain *r)
1957 struct lsa_OpenTrustedDomain opn;
1958 struct lsa_DeleteObject del;
1959 struct dcesrv_handle *h;
1961 opn.in.handle = r->in.handle;
1962 opn.in.sid = r->in.dom_sid;
1963 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1964 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1965 if (!opn.out.trustdom_handle) {
1966 return NT_STATUS_NO_MEMORY;
1968 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1969 if (!NT_STATUS_IS_OK(status)) {
1973 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1974 talloc_steal(mem_ctx, h);
1976 del.in.handle = opn.out.trustdom_handle;
1977 del.out.handle = opn.out.trustdom_handle;
1978 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1979 if (!NT_STATUS_IS_OK(status)) {
1982 return NT_STATUS_OK;
1985 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
1986 struct ldb_message *msg,
1987 struct lsa_TrustDomainInfoInfoEx *info_ex)
1989 info_ex->domain_name.string
1990 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1991 info_ex->netbios_name.string
1992 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1994 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1995 info_ex->trust_direction
1996 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1998 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1999 info_ex->trust_attributes
2000 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2001 return NT_STATUS_OK;
2005 lsa_QueryTrustedDomainInfo
2007 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2008 struct lsa_QueryTrustedDomainInfo *r)
2010 union lsa_TrustedDomainInfo *info = NULL;
2011 struct dcesrv_handle *h;
2012 struct lsa_trusted_domain_state *trusted_domain_state;
2013 struct ldb_message *msg;
2015 struct ldb_message **res;
2016 const char *attrs[] = {
2019 "securityIdentifier",
2023 "msDs-supportedEncryptionTypes",
2027 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2029 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2031 /* pull all the user attributes */
2032 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2033 trusted_domain_state->trusted_domain_dn, &res, attrs);
2035 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2039 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2041 return NT_STATUS_NO_MEMORY;
2043 *r->out.info = info;
2045 switch (r->in.level) {
2046 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2047 info->name.netbios_name.string
2048 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2050 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2051 info->posix_offset.posix_offset
2052 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2054 #if 0 /* Win2k3 doesn't implement this */
2055 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2056 r->out.info->info_basic.netbios_name.string
2057 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2058 r->out.info->info_basic.sid
2059 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2062 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2063 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2065 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2066 ZERO_STRUCT(info->full_info);
2067 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2068 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2069 ZERO_STRUCT(info->full_info2_internal);
2070 info->full_info2_internal.posix_offset.posix_offset
2071 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2072 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2074 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2075 info->enc_types.enc_types
2076 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2079 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2080 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2081 /* oops, we don't want to return the info after all */
2083 *r->out.info = NULL;
2084 return NT_STATUS_INVALID_PARAMETER;
2086 /* oops, we don't want to return the info after all */
2088 *r->out.info = NULL;
2089 return NT_STATUS_INVALID_INFO_CLASS;
2092 return NT_STATUS_OK;
2097 lsa_QueryTrustedDomainInfoBySid
2099 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2100 struct lsa_QueryTrustedDomainInfoBySid *r)
2103 struct lsa_OpenTrustedDomain opn;
2104 struct lsa_QueryTrustedDomainInfo query;
2105 struct dcesrv_handle *h;
2107 opn.in.handle = r->in.handle;
2108 opn.in.sid = r->in.dom_sid;
2109 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2110 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2111 if (!opn.out.trustdom_handle) {
2112 return NT_STATUS_NO_MEMORY;
2114 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2115 if (!NT_STATUS_IS_OK(status)) {
2119 /* Ensure this handle goes away at the end of this call */
2120 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2121 talloc_steal(mem_ctx, h);
2123 query.in.trustdom_handle = opn.out.trustdom_handle;
2124 query.in.level = r->in.level;
2125 query.out.info = r->out.info;
2126 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2127 if (!NT_STATUS_IS_OK(status)) {
2131 return NT_STATUS_OK;
2135 lsa_SetTrustedDomainInfoByName
2137 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2138 TALLOC_CTX *mem_ctx,
2139 struct lsa_SetTrustedDomainInfoByName *r)
2141 struct dcesrv_handle *policy_handle;
2142 struct lsa_policy_state *policy_state;
2143 struct ldb_message **msgs;
2146 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2147 policy_state = policy_handle->data;
2149 /* get the trusted domain object */
2150 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2151 policy_state->domain_dn,
2152 r->in.trusted_domain->string,
2153 r->in.trusted_domain->string,
2155 if (!NT_STATUS_IS_OK(nt_status)) {
2156 if (NT_STATUS_EQUAL(nt_status,
2157 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2160 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2163 return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2164 msgs[0], r->in.level, r->in.info);
2168 lsa_QueryTrustedDomainInfoByName
2170 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2171 TALLOC_CTX *mem_ctx,
2172 struct lsa_QueryTrustedDomainInfoByName *r)
2175 struct lsa_OpenTrustedDomainByName opn;
2176 struct lsa_QueryTrustedDomainInfo query;
2177 struct dcesrv_handle *h;
2179 opn.in.handle = r->in.handle;
2180 opn.in.name = *r->in.trusted_domain;
2181 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2182 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2183 if (!opn.out.trustdom_handle) {
2184 return NT_STATUS_NO_MEMORY;
2186 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2187 if (!NT_STATUS_IS_OK(status)) {
2191 /* Ensure this handle goes away at the end of this call */
2192 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2193 talloc_steal(mem_ctx, h);
2195 query.in.trustdom_handle = opn.out.trustdom_handle;
2196 query.in.level = r->in.level;
2197 query.out.info = r->out.info;
2198 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2199 if (!NT_STATUS_IS_OK(status)) {
2203 return NT_STATUS_OK;
2207 lsa_CloseTrustedDomainEx
2209 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2210 TALLOC_CTX *mem_ctx,
2211 struct lsa_CloseTrustedDomainEx *r)
2213 /* The result of a bad hair day from an IDL programmer? Not
2214 * implmented in Win2k3. You should always just lsa_Close
2216 return NT_STATUS_NOT_IMPLEMENTED;
2221 comparison function for sorting lsa_DomainInformation array
2223 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2225 return strcasecmp_m(e1->name.string, e2->name.string);
2231 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2232 struct lsa_EnumTrustDom *r)
2234 struct dcesrv_handle *policy_handle;
2235 struct lsa_DomainInfo *entries;
2236 struct lsa_policy_state *policy_state;
2237 struct ldb_message **domains;
2238 const char *attrs[] = {
2240 "securityIdentifier",
2247 *r->out.resume_handle = 0;
2249 r->out.domains->domains = NULL;
2250 r->out.domains->count = 0;
2252 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2254 policy_state = policy_handle->data;
2256 /* search for all users in this domain. This could possibly be cached and
2257 resumed based on resume_key */
2258 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2259 "objectclass=trustedDomain");
2261 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2264 /* convert to lsa_TrustInformation format */
2265 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2267 return NT_STATUS_NO_MEMORY;
2269 for (i=0;i<count;i++) {
2270 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2271 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2274 /* sort the results by name */
2275 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2277 if (*r->in.resume_handle >= count) {
2278 *r->out.resume_handle = -1;
2280 return NT_STATUS_NO_MORE_ENTRIES;
2283 /* return the rest, limit by max_size. Note that we
2284 use the w2k3 element size value of 60 */
2285 r->out.domains->count = count - *r->in.resume_handle;
2286 r->out.domains->count = MIN(r->out.domains->count,
2287 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2289 r->out.domains->domains = entries + *r->in.resume_handle;
2290 r->out.domains->count = r->out.domains->count;
2292 if (r->out.domains->count < count - *r->in.resume_handle) {
2293 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2294 return STATUS_MORE_ENTRIES;
2297 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2298 * always be larger than the previous input resume handle, in
2299 * particular when hitting the last query it is vital to set the
2300 * resume handle correctly to avoid infinite client loops, as
2301 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2302 * status is NT_STATUS_OK - gd */
2304 *r->out.resume_handle = (uint32_t)-1;
2306 return NT_STATUS_OK;
2310 comparison function for sorting lsa_DomainInformation array
2312 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2314 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2318 lsa_EnumTrustedDomainsEx
2320 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2321 struct lsa_EnumTrustedDomainsEx *r)
2323 struct dcesrv_handle *policy_handle;
2324 struct lsa_TrustDomainInfoInfoEx *entries;
2325 struct lsa_policy_state *policy_state;
2326 struct ldb_message **domains;
2327 const char *attrs[] = {
2330 "securityIdentifier",
2340 *r->out.resume_handle = 0;
2342 r->out.domains->domains = NULL;
2343 r->out.domains->count = 0;
2345 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2347 policy_state = policy_handle->data;
2349 /* search for all users in this domain. This could possibly be cached and
2350 resumed based on resume_key */
2351 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2352 "objectclass=trustedDomain");
2354 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2357 /* convert to lsa_DomainInformation format */
2358 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2360 return NT_STATUS_NO_MEMORY;
2362 for (i=0;i<count;i++) {
2363 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2364 if (!NT_STATUS_IS_OK(nt_status)) {
2369 /* sort the results by name */
2370 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2372 if (*r->in.resume_handle >= count) {
2373 *r->out.resume_handle = -1;
2375 return NT_STATUS_NO_MORE_ENTRIES;
2378 /* return the rest, limit by max_size. Note that we
2379 use the w2k3 element size value of 60 */
2380 r->out.domains->count = count - *r->in.resume_handle;
2381 r->out.domains->count = MIN(r->out.domains->count,
2382 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2384 r->out.domains->domains = entries + *r->in.resume_handle;
2385 r->out.domains->count = r->out.domains->count;
2387 if (r->out.domains->count < count - *r->in.resume_handle) {
2388 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2389 return STATUS_MORE_ENTRIES;
2392 return NT_STATUS_OK;
2399 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2400 struct lsa_OpenAccount *r)
2402 struct dcesrv_handle *h, *ah;
2403 struct lsa_policy_state *state;
2404 struct lsa_account_state *astate;
2406 ZERO_STRUCTP(r->out.acct_handle);
2408 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2412 astate = talloc(dce_call->conn, struct lsa_account_state);
2413 if (astate == NULL) {
2414 return NT_STATUS_NO_MEMORY;
2417 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2418 if (astate->account_sid == NULL) {
2419 talloc_free(astate);
2420 return NT_STATUS_NO_MEMORY;
2423 astate->policy = talloc_reference(astate, state);
2424 astate->access_mask = r->in.access_mask;
2426 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2428 talloc_free(astate);
2429 return NT_STATUS_NO_MEMORY;
2432 ah->data = talloc_steal(ah, astate);
2434 *r->out.acct_handle = ah->wire_handle;
2436 return NT_STATUS_OK;
2441 lsa_EnumPrivsAccount
2443 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2444 TALLOC_CTX *mem_ctx,
2445 struct lsa_EnumPrivsAccount *r)
2447 struct dcesrv_handle *h;
2448 struct lsa_account_state *astate;
2451 struct ldb_message **res;
2452 const char * const attrs[] = { "privilege", NULL};
2453 struct ldb_message_element *el;
2455 struct lsa_PrivilegeSet *privs;
2457 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2461 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2462 if (privs == NULL) {
2463 return NT_STATUS_NO_MEMORY;
2469 *r->out.privs = privs;
2471 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2472 if (sidstr == NULL) {
2473 return NT_STATUS_NO_MEMORY;
2476 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2477 "objectSid=%s", sidstr);
2479 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2482 return NT_STATUS_OK;
2485 el = ldb_msg_find_element(res[0], "privilege");
2486 if (el == NULL || el->num_values == 0) {
2487 return NT_STATUS_OK;
2490 privs->set = talloc_array(privs,
2491 struct lsa_LUIDAttribute, el->num_values);
2492 if (privs->set == NULL) {
2493 return NT_STATUS_NO_MEMORY;
2497 for (i=0;i<el->num_values;i++) {
2498 int id = sec_privilege_id((const char *)el->values[i].data);
2499 if (id == SEC_PRIV_INVALID) {
2500 /* Perhaps an account right, not a privilege */
2503 privs->set[j].attribute = 0;
2504 privs->set[j].luid.low = id;
2505 privs->set[j].luid.high = 0;
2511 return NT_STATUS_OK;
2515 lsa_EnumAccountRights
2517 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2518 TALLOC_CTX *mem_ctx,
2519 struct lsa_EnumAccountRights *r)
2521 struct dcesrv_handle *h;
2522 struct lsa_policy_state *state;
2525 struct ldb_message **res;
2526 const char * const attrs[] = { "privilege", NULL};
2528 struct ldb_message_element *el;
2530 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2534 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2535 if (sidstr == NULL) {
2536 return NT_STATUS_NO_MEMORY;
2539 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2540 "(&(objectSid=%s)(privilege=*))", sidstr);
2542 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2545 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2546 dom_sid_string(mem_ctx, r->in.sid),
2547 ldb_errstring(state->pdb)));
2548 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2551 el = ldb_msg_find_element(res[0], "privilege");
2552 if (el == NULL || el->num_values == 0) {
2553 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2556 r->out.rights->count = el->num_values;
2557 r->out.rights->names = talloc_array(r->out.rights,
2558 struct lsa_StringLarge, r->out.rights->count);
2559 if (r->out.rights->names == NULL) {
2560 return NT_STATUS_NO_MEMORY;
2563 for (i=0;i<el->num_values;i++) {
2564 r->out.rights->names[i].string = (const char *)el->values[i].data;
2567 return NT_STATUS_OK;
2573 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2575 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2576 TALLOC_CTX *mem_ctx,
2577 struct lsa_policy_state *state,
2579 struct dom_sid *sid,
2580 const struct lsa_RightSet *rights)
2582 const char *sidstr, *sidndrstr;
2583 struct ldb_message *msg;
2584 struct ldb_message_element *el;
2587 struct lsa_EnumAccountRights r2;
2590 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2591 SECURITY_ADMINISTRATOR) {
2592 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2593 return NT_STATUS_ACCESS_DENIED;
2596 msg = ldb_msg_new(mem_ctx);
2598 return NT_STATUS_NO_MEMORY;
2601 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2602 if (sidndrstr == NULL) {
2604 return NT_STATUS_NO_MEMORY;
2607 sidstr = dom_sid_string(msg, sid);
2608 if (sidstr == NULL) {
2610 return NT_STATUS_NO_MEMORY;
2613 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2614 if (dnstr == NULL) {
2616 return NT_STATUS_NO_MEMORY;
2619 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2620 if (msg->dn == NULL) {
2622 return NT_STATUS_NO_MEMORY;
2625 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2628 r2.in.handle = &state->handle->wire_handle;
2630 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2632 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2633 if (!NT_STATUS_IS_OK(status)) {
2634 ZERO_STRUCTP(r2.out.rights);
2638 for (i=0;i<rights->count;i++) {
2639 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2640 if (sec_right_bit(rights->names[i].string) == 0) {
2642 return NT_STATUS_NO_SUCH_PRIVILEGE;
2646 return NT_STATUS_NO_SUCH_PRIVILEGE;
2649 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2651 for (j=0;j<r2.out.rights->count;j++) {
2652 if (strcasecmp_m(r2.out.rights->names[j].string,
2653 rights->names[i].string) == 0) {
2657 if (j != r2.out.rights->count) continue;
2660 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2661 if (ret != LDB_SUCCESS) {
2663 return NT_STATUS_NO_MEMORY;
2667 el = ldb_msg_find_element(msg, "privilege");
2670 return NT_STATUS_OK;
2673 el->flags = ldb_flag;
2675 ret = ldb_modify(state->pdb, msg);
2676 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2677 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2679 return NT_STATUS_NO_MEMORY;
2681 ldb_msg_add_string(msg, "comment", "added via LSA");
2682 ret = ldb_add(state->pdb, msg);
2684 if (ret != LDB_SUCCESS) {
2685 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2687 return NT_STATUS_OK;
2689 DEBUG(3, ("Could not %s attributes from %s: %s",
2690 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2691 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2693 return NT_STATUS_UNEXPECTED_IO_ERROR;
2697 return NT_STATUS_OK;
2701 lsa_AddPrivilegesToAccount
2703 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2704 struct lsa_AddPrivilegesToAccount *r)
2706 struct lsa_RightSet rights;
2707 struct dcesrv_handle *h;
2708 struct lsa_account_state *astate;
2711 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2715 rights.count = r->in.privs->count;
2716 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2717 if (rights.names == NULL) {
2718 return NT_STATUS_NO_MEMORY;
2720 for (i=0;i<rights.count;i++) {
2721 int id = r->in.privs->set[i].luid.low;
2722 if (r->in.privs->set[i].luid.high) {
2723 return NT_STATUS_NO_SUCH_PRIVILEGE;
2725 rights.names[i].string = sec_privilege_name(id);
2726 if (rights.names[i].string == NULL) {
2727 return NT_STATUS_NO_SUCH_PRIVILEGE;
2731 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2732 LDB_FLAG_MOD_ADD, astate->account_sid,
2738 lsa_RemovePrivilegesFromAccount
2740 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2741 struct lsa_RemovePrivilegesFromAccount *r)
2743 struct lsa_RightSet *rights;
2744 struct dcesrv_handle *h;
2745 struct lsa_account_state *astate;
2748 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2752 rights = talloc(mem_ctx, struct lsa_RightSet);
2754 if (r->in.remove_all == 1 &&
2755 r->in.privs == NULL) {
2756 struct lsa_EnumAccountRights r2;
2759 r2.in.handle = &astate->policy->handle->wire_handle;
2760 r2.in.sid = astate->account_sid;
2761 r2.out.rights = rights;
2763 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2764 if (!NT_STATUS_IS_OK(status)) {
2768 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2769 LDB_FLAG_MOD_DELETE, astate->account_sid,
2773 if (r->in.remove_all != 0) {
2774 return NT_STATUS_INVALID_PARAMETER;
2777 rights->count = r->in.privs->count;
2778 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2779 if (rights->names == NULL) {
2780 return NT_STATUS_NO_MEMORY;
2782 for (i=0;i<rights->count;i++) {
2783 int id = r->in.privs->set[i].luid.low;
2784 if (r->in.privs->set[i].luid.high) {
2785 return NT_STATUS_NO_SUCH_PRIVILEGE;
2787 rights->names[i].string = sec_privilege_name(id);
2788 if (rights->names[i].string == NULL) {
2789 return NT_STATUS_NO_SUCH_PRIVILEGE;
2793 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2794 LDB_FLAG_MOD_DELETE, astate->account_sid,
2800 lsa_GetQuotasForAccount
2802 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2803 struct lsa_GetQuotasForAccount *r)
2805 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2810 lsa_SetQuotasForAccount
2812 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2813 struct lsa_SetQuotasForAccount *r)
2815 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2820 lsa_GetSystemAccessAccount
2822 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2823 struct lsa_GetSystemAccessAccount *r)
2825 struct dcesrv_handle *h;
2826 struct lsa_account_state *astate;
2829 struct ldb_message **res;
2830 const char * const attrs[] = { "privilege", NULL};
2831 struct ldb_message_element *el;
2834 *(r->out.access_mask) = 0x00000000;
2836 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2840 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2841 if (sidstr == NULL) {
2842 return NT_STATUS_NO_MEMORY;
2845 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2846 "objectSid=%s", sidstr);
2848 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2851 return NT_STATUS_OK;
2854 el = ldb_msg_find_element(res[0], "privilege");
2855 if (el == NULL || el->num_values == 0) {
2856 return NT_STATUS_OK;
2859 for (i=0;i<el->num_values;i++) {
2860 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2861 if (right_bit == 0) {
2862 /* Perhaps an privilege, not a right */
2865 *(r->out.access_mask) |= right_bit;
2868 return NT_STATUS_OK;
2873 lsa_SetSystemAccessAccount
2875 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2876 struct lsa_SetSystemAccessAccount *r)
2878 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2885 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2886 struct lsa_CreateSecret *r)
2888 struct dcesrv_handle *policy_handle;
2889 struct lsa_policy_state *policy_state;
2890 struct lsa_secret_state *secret_state;
2891 struct dcesrv_handle *handle;
2892 struct ldb_message **msgs, *msg;
2893 const char *attrs[] = {
2901 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2902 ZERO_STRUCTP(r->out.sec_handle);
2904 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2906 case SECURITY_SYSTEM:
2907 case SECURITY_ADMINISTRATOR:
2910 /* Users and annonymous are not allowed create secrets */
2911 return NT_STATUS_ACCESS_DENIED;
2914 policy_state = policy_handle->data;
2916 if (!r->in.name.string) {
2917 return NT_STATUS_INVALID_PARAMETER;
2920 secret_state = talloc(mem_ctx, struct lsa_secret_state);
2921 NT_STATUS_HAVE_NO_MEMORY(secret_state);
2922 secret_state->policy = policy_state;
2924 msg = ldb_msg_new(mem_ctx);
2926 return NT_STATUS_NO_MEMORY;
2929 if (strncmp("G$", r->in.name.string, 2) == 0) {
2932 secret_state->global = true;
2934 name = &r->in.name.string[2];
2935 if (strlen(name) == 0) {
2936 return NT_STATUS_INVALID_PARAMETER;
2939 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2940 ldb_binary_encode_string(mem_ctx, name));
2941 NT_STATUS_HAVE_NO_MEMORY(name2);
2943 /* We need to connect to the database as system, as this is one
2944 * of the rare RPC calls that must read the secrets (and this
2945 * is denied otherwise) */
2946 secret_state->sam_ldb = talloc_reference(secret_state,
2947 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));
2948 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2950 /* search for the secret record */
2951 ret = gendb_search(secret_state->sam_ldb,
2952 mem_ctx, policy_state->system_dn, &msgs, attrs,
2953 "(&(cn=%s)(objectclass=secret))",
2956 return NT_STATUS_OBJECT_NAME_COLLISION;
2960 DEBUG(0,("Failure searching for CN=%s: %s\n",
2961 name2, ldb_errstring(secret_state->sam_ldb)));
2962 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2965 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2966 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2967 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2968 return NT_STATUS_NO_MEMORY;
2971 ret = ldb_msg_add_string(msg, "cn", name2);
2972 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2974 secret_state->global = false;
2976 name = r->in.name.string;
2977 if (strlen(name) == 0) {
2978 return NT_STATUS_INVALID_PARAMETER;
2981 secret_state->sam_ldb = talloc_reference(secret_state,
2982 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
2983 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2985 /* search for the secret record */
2986 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2987 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2989 "(&(cn=%s)(objectclass=secret))",
2990 ldb_binary_encode_string(mem_ctx, name));
2992 return NT_STATUS_OBJECT_NAME_COLLISION;
2996 DEBUG(0,("Failure searching for CN=%s: %s\n",
2997 name, ldb_errstring(secret_state->sam_ldb)));
2998 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3001 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3002 "cn=%s,cn=LSA Secrets", name);
3003 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3004 ret = ldb_msg_add_string(msg, "cn", name);
3005 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3008 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3009 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3011 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3012 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3014 /* create the secret */
3015 ret = ldb_add(secret_state->sam_ldb, msg);
3016 if (ret != LDB_SUCCESS) {
3017 DEBUG(0,("Failed to create secret record %s: %s\n",
3018 ldb_dn_get_linearized(msg->dn),
3019 ldb_errstring(secret_state->sam_ldb)));
3020 return NT_STATUS_ACCESS_DENIED;
3023 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3024 NT_STATUS_HAVE_NO_MEMORY(handle);
3026 handle->data = talloc_steal(handle, secret_state);
3028 secret_state->access_mask = r->in.access_mask;
3029 secret_state->policy = talloc_reference(secret_state, policy_state);
3030 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3032 *r->out.sec_handle = handle->wire_handle;
3034 return NT_STATUS_OK;
3041 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3042 struct lsa_OpenSecret *r)
3044 struct dcesrv_handle *policy_handle;
3046 struct lsa_policy_state *policy_state;
3047 struct lsa_secret_state *secret_state;
3048 struct dcesrv_handle *handle;
3049 struct ldb_message **msgs;
3050 const char *attrs[] = {
3058 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3059 ZERO_STRUCTP(r->out.sec_handle);
3060 policy_state = policy_handle->data;
3062 if (!r->in.name.string) {
3063 return NT_STATUS_INVALID_PARAMETER;
3066 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3068 case SECURITY_SYSTEM:
3069 case SECURITY_ADMINISTRATOR:
3072 /* Users and annonymous are not allowed to access secrets */
3073 return NT_STATUS_ACCESS_DENIED;
3076 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3077 if (!secret_state) {
3078 return NT_STATUS_NO_MEMORY;
3080 secret_state->policy = policy_state;
3082 if (strncmp("G$", r->in.name.string, 2) == 0) {
3083 name = &r->in.name.string[2];
3084 /* 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) */
3085 secret_state->sam_ldb = talloc_reference(secret_state,
3086 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));
3087 secret_state->global = true;
3089 if (strlen(name) < 1) {
3090 return NT_STATUS_INVALID_PARAMETER;
3093 /* search for the secret record */
3094 ret = gendb_search(secret_state->sam_ldb,
3095 mem_ctx, policy_state->system_dn, &msgs, attrs,
3096 "(&(cn=%s Secret)(objectclass=secret))",
3097 ldb_binary_encode_string(mem_ctx, name));
3099 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3103 DEBUG(0,("Found %d records matching DN %s\n", ret,
3104 ldb_dn_get_linearized(policy_state->system_dn)));
3105 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3108 secret_state->global = false;
3109 secret_state->sam_ldb = talloc_reference(secret_state,
3110 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3112 name = r->in.name.string;
3113 if (strlen(name) < 1) {
3114 return NT_STATUS_INVALID_PARAMETER;
3117 /* search for the secret record */
3118 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3119 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3121 "(&(cn=%s)(objectclass=secret))",
3122 ldb_binary_encode_string(mem_ctx, name));
3124 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3128 DEBUG(0,("Found %d records matching CN=%s\n",
3129 ret, ldb_binary_encode_string(mem_ctx, name)));
3130 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3134 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3136 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3138 return NT_STATUS_NO_MEMORY;
3141 handle->data = talloc_steal(handle, secret_state);
3143 secret_state->access_mask = r->in.access_mask;
3144 secret_state->policy = talloc_reference(secret_state, policy_state);
3146 *r->out.sec_handle = handle->wire_handle;
3148 return NT_STATUS_OK;
3155 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3156 struct lsa_SetSecret *r)
3159 struct dcesrv_handle *h;
3160 struct lsa_secret_state *secret_state;
3161 struct ldb_message *msg;
3162 DATA_BLOB session_key;
3163 DATA_BLOB crypt_secret, secret;
3166 NTSTATUS status = NT_STATUS_OK;
3168 struct timeval now = timeval_current();
3169 NTTIME nt_now = timeval_to_nttime(&now);
3171 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3173 secret_state = h->data;
3175 msg = ldb_msg_new(mem_ctx);
3177 return NT_STATUS_NO_MEMORY;
3180 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3182 return NT_STATUS_NO_MEMORY;
3184 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3185 if (!NT_STATUS_IS_OK(status)) {
3189 if (r->in.old_val) {
3191 crypt_secret.data = r->in.old_val->data;
3192 crypt_secret.length = r->in.old_val->size;
3194 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3195 if (!NT_STATUS_IS_OK(status)) {
3199 val.data = secret.data;
3200 val.length = secret.length;
3203 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3204 return NT_STATUS_NO_MEMORY;
3207 /* set old value mtime */
3208 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3209 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3210 return NT_STATUS_NO_MEMORY;
3214 /* If the old value is not set, then migrate the
3215 * current value to the old value */
3216 const struct ldb_val *old_val;
3217 NTTIME last_set_time;
3218 struct ldb_message **res;
3219 const char *attrs[] = {
3225 /* search for the secret record */
3226 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3227 secret_state->secret_dn, &res, attrs);
3229 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3233 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3234 ldb_dn_get_linearized(secret_state->secret_dn)));
3235 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3238 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3239 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3243 if (ldb_msg_add_value(msg, "priorValue",
3244 old_val, NULL) != LDB_SUCCESS) {
3245 return NT_STATUS_NO_MEMORY;
3248 if (samdb_msg_add_delete(secret_state->sam_ldb,
3249 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3250 return NT_STATUS_NO_MEMORY;
3254 /* set old value mtime */
3255 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3256 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3257 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3258 return NT_STATUS_NO_MEMORY;
3261 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3262 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3263 return NT_STATUS_NO_MEMORY;
3268 if (r->in.new_val) {
3270 crypt_secret.data = r->in.new_val->data;
3271 crypt_secret.length = r->in.new_val->size;
3273 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3274 if (!NT_STATUS_IS_OK(status)) {
3278 val.data = secret.data;
3279 val.length = secret.length;
3282 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3283 return NT_STATUS_NO_MEMORY;
3286 /* set new value mtime */
3287 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3288 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3289 return NT_STATUS_NO_MEMORY;
3292 /* NULL out the NEW value */
3293 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3294 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3295 return NT_STATUS_NO_MEMORY;
3297 if (samdb_msg_add_delete(secret_state->sam_ldb,
3298 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3299 return NT_STATUS_NO_MEMORY;
3303 /* modify the samdb record */
3304 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3305 if (ret != LDB_SUCCESS) {
3306 return dsdb_ldb_err_to_ntstatus(ret);
3309 return NT_STATUS_OK;
3316 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3317 struct lsa_QuerySecret *r)
3319 struct dcesrv_handle *h;
3320 struct lsa_secret_state *secret_state;
3321 struct ldb_message *msg;
3322 DATA_BLOB session_key;
3323 DATA_BLOB crypt_secret, secret;
3325 struct ldb_message **res;
3326 const char *attrs[] = {
3336 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3338 /* Ensure user is permitted to read this... */
3339 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3341 case SECURITY_SYSTEM:
3342 case SECURITY_ADMINISTRATOR:
3345 /* Users and annonymous are not allowed to read secrets */
3346 return NT_STATUS_ACCESS_DENIED;
3349 secret_state = h->data;
3351 /* pull all the user attributes */
3352 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3353 secret_state->secret_dn, &res, attrs);
3355 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3359 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3360 if (!NT_STATUS_IS_OK(nt_status)) {
3364 if (r->in.old_val) {
3365 const struct ldb_val *prior_val;
3366 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3367 if (!r->out.old_val) {
3368 return NT_STATUS_NO_MEMORY;
3370 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3372 if (prior_val && prior_val->length) {
3373 secret.data = prior_val->data;
3374 secret.length = prior_val->length;
3377 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3378 if (!crypt_secret.length) {
3379 return NT_STATUS_NO_MEMORY;
3381 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3382 if (!r->out.old_val->buf) {
3383 return NT_STATUS_NO_MEMORY;
3385 r->out.old_val->buf->size = crypt_secret.length;
3386 r->out.old_val->buf->length = crypt_secret.length;
3387 r->out.old_val->buf->data = crypt_secret.data;
3391 if (r->in.old_mtime) {
3392 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3393 if (!r->out.old_mtime) {
3394 return NT_STATUS_NO_MEMORY;
3396 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3399 if (r->in.new_val) {
3400 const struct ldb_val *new_val;
3401 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3402 if (!r->out.new_val) {
3403 return NT_STATUS_NO_MEMORY;
3406 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3408 if (new_val && new_val->length) {
3409 secret.data = new_val->data;
3410 secret.length = new_val->length;
3413 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3414 if (!crypt_secret.length) {
3415 return NT_STATUS_NO_MEMORY;
3417 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3418 if (!r->out.new_val->buf) {
3419 return NT_STATUS_NO_MEMORY;
3421 r->out.new_val->buf->length = crypt_secret.length;
3422 r->out.new_val->buf->size = crypt_secret.length;
3423 r->out.new_val->buf->data = crypt_secret.data;
3427 if (r->in.new_mtime) {
3428 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3429 if (!r->out.new_mtime) {
3430 return NT_STATUS_NO_MEMORY;
3432 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3435 return NT_STATUS_OK;
3442 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3443 TALLOC_CTX *mem_ctx,
3444 struct lsa_LookupPrivValue *r)
3446 struct dcesrv_handle *h;
3449 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3451 id = sec_privilege_id(r->in.name->string);
3452 if (id == SEC_PRIV_INVALID) {
3453 return NT_STATUS_NO_SUCH_PRIVILEGE;
3456 r->out.luid->low = id;
3457 r->out.luid->high = 0;
3459 return NT_STATUS_OK;
3466 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3467 TALLOC_CTX *mem_ctx,
3468 struct lsa_LookupPrivName *r)
3470 struct dcesrv_handle *h;
3471 struct lsa_StringLarge *name;
3472 const char *privname;
3474 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3476 if (r->in.luid->high != 0) {
3477 return NT_STATUS_NO_SUCH_PRIVILEGE;
3480 privname = sec_privilege_name(r->in.luid->low);
3481 if (privname == NULL) {
3482 return NT_STATUS_NO_SUCH_PRIVILEGE;
3485 name = talloc(mem_ctx, struct lsa_StringLarge);
3487 return NT_STATUS_NO_MEMORY;
3490 name->string = privname;
3492 *r->out.name = name;
3494 return NT_STATUS_OK;
3499 lsa_LookupPrivDisplayName
3501 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3502 TALLOC_CTX *mem_ctx,
3503 struct lsa_LookupPrivDisplayName *r)
3505 struct dcesrv_handle *h;
3506 struct lsa_StringLarge *disp_name = NULL;
3507 enum sec_privilege id;
3509 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3511 id = sec_privilege_id(r->in.name->string);
3512 if (id == SEC_PRIV_INVALID) {
3513 return NT_STATUS_NO_SUCH_PRIVILEGE;
3516 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3517 if (disp_name == NULL) {
3518 return NT_STATUS_NO_MEMORY;
3521 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3522 if (disp_name->string == NULL) {
3523 return NT_STATUS_INTERNAL_ERROR;
3526 *r->out.disp_name = disp_name;
3527 *r->out.returned_language_id = 0;
3529 return NT_STATUS_OK;
3534 lsa_EnumAccountsWithUserRight
3536 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3537 TALLOC_CTX *mem_ctx,
3538 struct lsa_EnumAccountsWithUserRight *r)
3540 struct dcesrv_handle *h;
3541 struct lsa_policy_state *state;
3543 struct ldb_message **res;
3544 const char * const attrs[] = { "objectSid", NULL};
3545 const char *privname;
3547 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3551 if (r->in.name == NULL) {
3552 return NT_STATUS_NO_SUCH_PRIVILEGE;
3555 privname = r->in.name->string;
3556 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3557 return NT_STATUS_NO_SUCH_PRIVILEGE;
3560 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3561 "privilege=%s", privname);
3563 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3566 return NT_STATUS_NO_MORE_ENTRIES;
3569 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3570 if (r->out.sids->sids == NULL) {
3571 return NT_STATUS_NO_MEMORY;
3573 for (i=0;i<ret;i++) {
3574 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3575 res[i], "objectSid");
3576 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3578 r->out.sids->num_sids = ret;
3580 return NT_STATUS_OK;
3585 lsa_AddAccountRights
3587 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3588 TALLOC_CTX *mem_ctx,
3589 struct lsa_AddAccountRights *r)
3591 struct dcesrv_handle *h;
3592 struct lsa_policy_state *state;
3594 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3598 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3600 r->in.sid, r->in.rights);
3605 lsa_RemoveAccountRights
3607 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3608 TALLOC_CTX *mem_ctx,
3609 struct lsa_RemoveAccountRights *r)
3611 struct dcesrv_handle *h;
3612 struct lsa_policy_state *state;
3614 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3618 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3619 LDB_FLAG_MOD_DELETE,
3620 r->in.sid, r->in.rights);
3625 lsa_StorePrivateData
3627 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3628 struct lsa_StorePrivateData *r)
3630 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3635 lsa_RetrievePrivateData
3637 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3638 struct lsa_RetrievePrivateData *r)
3640 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3647 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3648 struct lsa_GetUserName *r)
3650 enum dcerpc_transport_t transport =
3651 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3652 NTSTATUS status = NT_STATUS_OK;
3653 const char *account_name;
3654 const char *authority_name;
3655 struct lsa_String *_account_name;
3656 struct lsa_String *_authority_name = NULL;
3658 if (transport != NCACN_NP && transport != NCALRPC) {
3659 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3662 /* this is what w2k3 does */
3663 r->out.account_name = r->in.account_name;
3664 r->out.authority_name = r->in.authority_name;
3666 if (r->in.account_name
3667 && *r->in.account_name
3668 /* && *(*r->in.account_name)->string */
3670 return NT_STATUS_INVALID_PARAMETER;
3673 if (r->in.authority_name
3674 && *r->in.authority_name
3675 /* && *(*r->in.authority_name)->string */
3677 return NT_STATUS_INVALID_PARAMETER;
3680 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3681 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3683 _account_name = talloc(mem_ctx, struct lsa_String);
3684 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3685 _account_name->string = account_name;
3687 if (r->in.authority_name) {
3688 _authority_name = talloc(mem_ctx, struct lsa_String);
3689 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3690 _authority_name->string = authority_name;
3693 *r->out.account_name = _account_name;
3694 if (r->out.authority_name) {
3695 *r->out.authority_name = _authority_name;
3704 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3705 TALLOC_CTX *mem_ctx,
3706 struct lsa_SetInfoPolicy2 *r)
3708 /* need to support these */
3709 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3712 static void kdc_get_policy(struct loadparm_context *lp_ctx,
3713 struct smb_krb5_context *smb_krb5_context,
3714 struct lsa_DomainInfoKerberos *k)
3716 time_t svc_tkt_lifetime;
3717 time_t usr_tkt_lifetime;
3718 time_t renewal_lifetime;
3720 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
3722 /* Our KDC always re-validates the client */
3723 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
3725 lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
3726 &usr_tkt_lifetime, &renewal_lifetime);
3728 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
3729 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
3730 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
3731 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
3732 However in the parent function we basically just did a full
3733 krb5_context init with the only purpose of getting a global
3734 config option (the max skew), it would probably make more sense
3735 to have a lp_ or ldb global option as the samba default */
3736 if (smb_krb5_context) {
3737 unix_to_nt_time(&k->clock_skew,
3738 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
3744 lsa_QueryDomainInformationPolicy
3746 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3747 TALLOC_CTX *mem_ctx,
3748 struct lsa_QueryDomainInformationPolicy *r)
3750 union lsa_DomainInformationPolicy *info;
3752 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3754 return NT_STATUS_NO_MEMORY;
3757 switch (r->in.level) {
3758 case LSA_DOMAIN_INFO_POLICY_EFS:
3760 *r->out.info = NULL;
3761 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3762 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3764 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3765 struct smb_krb5_context *smb_krb5_context;
3766 int ret = smb_krb5_init_context(mem_ctx,
3767 dce_call->conn->dce_ctx->lp_ctx,
3771 *r->out.info = NULL;
3772 return NT_STATUS_INTERNAL_ERROR;
3774 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3777 talloc_free(smb_krb5_context);
3778 *r->out.info = info;
3779 return NT_STATUS_OK;
3783 *r->out.info = NULL;
3784 return NT_STATUS_INVALID_INFO_CLASS;
3789 lsa_SetDomInfoPolicy
3791 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3792 TALLOC_CTX *mem_ctx,
3793 struct lsa_SetDomainInformationPolicy *r)
3795 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3801 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3802 TALLOC_CTX *mem_ctx,
3803 struct lsa_TestCall *r)
3805 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3811 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3812 struct lsa_CREDRWRITE *r)
3814 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3821 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3822 struct lsa_CREDRREAD *r)
3824 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3831 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3832 struct lsa_CREDRENUMERATE *r)
3834 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3839 lsa_CREDRWRITEDOMAINCREDENTIALS
3841 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3842 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3844 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3849 lsa_CREDRREADDOMAINCREDENTIALS
3851 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3852 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3854 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3861 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3862 struct lsa_CREDRDELETE *r)
3864 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3869 lsa_CREDRGETTARGETINFO
3871 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3872 struct lsa_CREDRGETTARGETINFO *r)
3874 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3879 lsa_CREDRPROFILELOADED
3881 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3882 struct lsa_CREDRPROFILELOADED *r)
3884 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3889 lsa_CREDRGETSESSIONTYPES
3891 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3892 struct lsa_CREDRGETSESSIONTYPES *r)
3894 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3899 lsa_LSARREGISTERAUDITEVENT
3901 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3902 struct lsa_LSARREGISTERAUDITEVENT *r)
3904 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3909 lsa_LSARGENAUDITEVENT
3911 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3912 struct lsa_LSARGENAUDITEVENT *r)
3914 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3919 lsa_LSARUNREGISTERAUDITEVENT
3921 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3922 struct lsa_LSARUNREGISTERAUDITEVENT *r)
3924 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3929 lsa_lsaRQueryForestTrustInformation
3931 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3932 struct lsa_lsaRQueryForestTrustInformation *r)
3934 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3937 #define DNS_CMP_MATCH 0
3938 #define DNS_CMP_FIRST_IS_CHILD 1
3939 #define DNS_CMP_SECOND_IS_CHILD 2
3940 #define DNS_CMP_NO_MATCH 3
3942 /* this function assumes names are well formed DNS names.
3943 * it doesn't validate them */
3944 static int dns_cmp(const char *s1, size_t l1,
3945 const char *s2, size_t l2)
3947 const char *p1, *p2;
3952 if (strcasecmp_m(s1, s2) == 0) {
3953 return DNS_CMP_MATCH;
3955 return DNS_CMP_NO_MATCH;
3963 cret = DNS_CMP_FIRST_IS_CHILD;
3969 cret = DNS_CMP_SECOND_IS_CHILD;
3972 if (p1[t1 - t2 - 1] != '.') {
3973 return DNS_CMP_NO_MATCH;
3976 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3980 return DNS_CMP_NO_MATCH;
3983 /* decode all TDOs forest trust info blobs */
3984 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3985 struct ldb_message *msg,
3986 struct ForestTrustInfo *info)
3988 const struct ldb_val *ft_blob;
3989 enum ndr_err_code ndr_err;
3991 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3992 if (!ft_blob || !ft_blob->data) {
3993 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3995 /* ldb_val is equivalent to DATA_BLOB */
3996 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3997 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3998 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3999 return NT_STATUS_INVALID_DOMAIN_STATE;
4002 return NT_STATUS_OK;
4005 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
4006 struct ForestTrustInfo *fti)
4008 struct ForestTrustDataDomainInfo *info;
4009 struct ForestTrustInfoRecord *rec;
4013 fti->records = talloc_array(fti,
4014 struct ForestTrustInfoRecordArmor, 2);
4015 if (!fti->records) {
4016 return NT_STATUS_NO_MEMORY;
4020 rec = &fti->records[0].record;
4024 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
4026 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
4027 if (!rec->data.name.string) {
4028 return NT_STATUS_NO_MEMORY;
4030 rec->data.name.size = strlen(rec->data.name.string);
4033 rec = &fti->records[1].record;
4037 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
4039 info = &rec->data.info;
4041 info->sid = *ps->domain_sid;
4042 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
4043 if (!info->dns_name.string) {
4044 return NT_STATUS_NO_MEMORY;
4046 info->dns_name.size = strlen(info->dns_name.string);
4047 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
4048 if (!info->netbios_name.string) {
4049 return NT_STATUS_NO_MEMORY;
4051 info->netbios_name.size = strlen(info->netbios_name.string);
4053 return NT_STATUS_OK;
4056 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
4057 struct lsa_ForestTrustInformation *lfti,
4058 struct ForestTrustInfo *fti)
4060 struct lsa_ForestTrustRecord *lrec;
4061 struct ForestTrustInfoRecord *rec;
4062 struct lsa_StringLarge *tln;
4063 struct lsa_ForestTrustDomainInfo *info;
4067 fti->count = lfti->count;
4068 fti->records = talloc_array(mem_ctx,
4069 struct ForestTrustInfoRecordArmor,
4071 if (!fti->records) {
4072 return NT_STATUS_NO_MEMORY;
4074 for (i = 0; i < fti->count; i++) {
4075 lrec = lfti->entries[i];
4076 rec = &fti->records[i].record;
4078 rec->flags = lrec->flags;
4079 rec->timestamp = lrec->time;
4080 rec->type = lrec->type;
4082 switch (lrec->type) {
4083 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4084 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4085 tln = &lrec->forest_trust_data.top_level_name;
4086 rec->data.name.string =
4087 talloc_strdup(mem_ctx, tln->string);
4088 if (!rec->data.name.string) {
4089 return NT_STATUS_NO_MEMORY;
4091 rec->data.name.size = strlen(rec->data.name.string);
4093 case LSA_FOREST_TRUST_DOMAIN_INFO:
4094 info = &lrec->forest_trust_data.domain_info;
4095 rec->data.info.sid = *info->domain_sid;
4096 rec->data.info.dns_name.string =
4097 talloc_strdup(mem_ctx,
4098 info->dns_domain_name.string);
4099 if (!rec->data.info.dns_name.string) {
4100 return NT_STATUS_NO_MEMORY;
4102 rec->data.info.dns_name.size =
4103 strlen(rec->data.info.dns_name.string);
4104 rec->data.info.netbios_name.string =
4105 talloc_strdup(mem_ctx,
4106 info->netbios_domain_name.string);
4107 if (!rec->data.info.netbios_name.string) {
4108 return NT_STATUS_NO_MEMORY;
4110 rec->data.info.netbios_name.size =
4111 strlen(rec->data.info.netbios_name.string);
4114 return NT_STATUS_INVALID_DOMAIN_STATE;
4118 return NT_STATUS_OK;
4121 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4122 uint32_t idx, uint32_t collision_type,
4123 uint32_t conflict_type, const char *tdo_name);
4125 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4126 const char *tdo_name,
4127 struct ForestTrustInfo *tdo_fti,
4128 struct ForestTrustInfo *new_fti,
4129 struct lsa_ForestTrustCollisionInfo *c_info)
4131 struct ForestTrustInfoRecord *nrec;
4132 struct ForestTrustInfoRecord *trec;
4133 const char *dns_name;
4134 const char *nb_name;
4135 struct dom_sid *sid;
4139 NTSTATUS nt_status = NT_STATUS_OK;
4140 uint32_t new_fti_idx;
4142 /* use always TDO type, until we understand when Xref can be used */
4143 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4151 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4153 nrec = &new_fti->records[new_fti_idx].record;
4155 tln_conflict = false;
4156 sid_conflict = false;
4157 nb_conflict = false;
4160 switch (nrec->type) {
4161 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4162 /* exclusions do not conflict by definition */
4165 case FOREST_TRUST_TOP_LEVEL_NAME:
4166 dns_name = nrec->data.name.string;
4167 dns_len = nrec->data.name.size;
4170 case LSA_FOREST_TRUST_DOMAIN_INFO:
4171 dns_name = nrec->data.info.dns_name.string;
4172 dns_len = nrec->data.info.dns_name.size;
4173 nb_name = nrec->data.info.netbios_name.string;
4174 sid = &nrec->data.info.sid;
4178 if (!dns_name) continue;
4180 /* check if this is already taken and not excluded */
4181 for (i = 0; i < tdo_fti->count; i++) {
4182 trec = &tdo_fti->records[i].record;
4184 switch (trec->type) {
4185 case FOREST_TRUST_TOP_LEVEL_NAME:
4187 tname = trec->data.name.string;
4188 tlen = trec->data.name.size;
4190 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4192 tname = trec->data.name.string;
4193 tlen = trec->data.name.size;
4195 case FOREST_TRUST_DOMAIN_INFO:
4197 tname = trec->data.info.dns_name.string;
4198 tlen = trec->data.info.dns_name.size;
4200 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4203 /* if it matches exclusion,
4204 * it doesn't conflict */
4210 case DNS_CMP_FIRST_IS_CHILD:
4211 case DNS_CMP_SECOND_IS_CHILD:
4212 tln_conflict = true;
4218 /* explicit exclusion, no dns name conflict here */
4220 tln_conflict = false;
4223 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4227 /* also test for domain info */
4228 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4229 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4230 sid_conflict = true;
4232 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4233 strcasecmp_m(trec->data.info.netbios_name.string,
4240 nt_status = add_collision(c_info, new_fti_idx,
4242 LSA_TLN_DISABLED_CONFLICT,
4244 if (!NT_STATUS_IS_OK(nt_status)) {
4249 nt_status = add_collision(c_info, new_fti_idx,
4251 LSA_SID_DISABLED_CONFLICT,
4253 if (!NT_STATUS_IS_OK(nt_status)) {
4258 nt_status = add_collision(c_info, new_fti_idx,
4260 LSA_NB_DISABLED_CONFLICT,
4262 if (!NT_STATUS_IS_OK(nt_status)) {
4272 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4273 uint32_t idx, uint32_t collision_type,
4274 uint32_t conflict_type, const char *tdo_name)
4276 struct lsa_ForestTrustCollisionRecord **es;
4277 uint32_t i = c_info->count;
4279 es = talloc_realloc(c_info, c_info->entries,
4280 struct lsa_ForestTrustCollisionRecord *, i + 1);
4282 return NT_STATUS_NO_MEMORY;
4284 c_info->entries = es;
4285 c_info->count = i + 1;
4287 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4289 return NT_STATUS_NO_MEMORY;
4293 es[i]->type = collision_type;
4294 es[i]->flags.flags = conflict_type;
4295 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4296 if (!es[i]->name.string) {
4297 return NT_STATUS_NO_MEMORY;
4299 es[i]->name.size = strlen(es[i]->name.string);
4301 return NT_STATUS_OK;
4305 lsa_lsaRSetForestTrustInformation
4307 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4308 TALLOC_CTX *mem_ctx,
4309 struct lsa_lsaRSetForestTrustInformation *r)
4311 struct dcesrv_handle *h;
4312 struct lsa_policy_state *p_state;
4313 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4314 "msDS-TrustForestTrustInfo", NULL };
4315 struct ldb_message **dom_res = NULL;
4316 struct ldb_dn *tdo_dn;
4317 struct ldb_message *msg;
4319 const char *td_name;
4320 uint32_t trust_attributes;
4321 struct lsa_ForestTrustCollisionInfo *c_info;
4322 struct ForestTrustInfo *nfti;
4323 struct ForestTrustInfo *fti;
4325 enum ndr_err_code ndr_err;
4330 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4334 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4335 return NT_STATUS_INVALID_DOMAIN_STATE;
4338 /* abort if we are not a PDC */
4339 if (!samdb_is_pdc(p_state->sam_ldb)) {
4340 return NT_STATUS_INVALID_DOMAIN_ROLE;
4343 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4344 if (ret == LDB_SUCCESS && am_rodc) {
4345 return NT_STATUS_NO_SUCH_DOMAIN;
4348 /* check caller has TRUSTED_SET_AUTH */
4350 /* fetch all trusted domain objects */
4351 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4353 &dom_res, trust_attrs,
4354 "(objectclass=trustedDomain)");
4356 return NT_STATUS_NO_SUCH_DOMAIN;
4359 for (i = 0; i < num_res; i++) {
4360 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4361 "trustPartner", NULL);
4363 return NT_STATUS_INVALID_DOMAIN_STATE;
4365 if (strcasecmp_m(td_name,
4366 r->in.trusted_domain_name->string) == 0) {
4371 return NT_STATUS_NO_SUCH_DOMAIN;
4374 tdo_dn = dom_res[i]->dn;
4376 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4377 "trustAttributes", 0);
4378 if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4379 return NT_STATUS_INVALID_PARAMETER;
4382 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4383 return NT_STATUS_INVALID_PARAMETER;
4386 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4388 return NT_STATUS_NO_MEMORY;
4391 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4392 if (!NT_STATUS_IS_OK(nt_status)) {
4396 c_info = talloc_zero(r->out.collision_info,
4397 struct lsa_ForestTrustCollisionInfo);
4399 return NT_STATUS_NO_MEMORY;
4402 /* first check own info, then other domains */
4403 fti = talloc(mem_ctx, struct ForestTrustInfo);
4405 return NT_STATUS_NO_MEMORY;
4408 nt_status = own_ft_info(p_state, fti);
4409 if (!NT_STATUS_IS_OK(nt_status)) {
4413 nt_status = check_ft_info(c_info, p_state->domain_dns,
4415 if (!NT_STATUS_IS_OK(nt_status)) {
4419 for (i = 0; i < num_res; i++) {
4420 fti = talloc(mem_ctx, struct ForestTrustInfo);
4422 return NT_STATUS_NO_MEMORY;
4425 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4426 if (!NT_STATUS_IS_OK(nt_status)) {
4427 if (NT_STATUS_EQUAL(nt_status,
4428 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4434 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4435 "trustPartner", NULL);
4437 return NT_STATUS_INVALID_DOMAIN_STATE;
4440 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4441 if (!NT_STATUS_IS_OK(nt_status)) {
4446 *r->out.collision_info = c_info;
4448 if (r->in.check_only != 0) {
4449 return NT_STATUS_OK;
4452 /* not just a check, write info back */
4454 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4455 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4456 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4457 return NT_STATUS_INVALID_PARAMETER;
4460 msg = ldb_msg_new(mem_ctx);
4462 return NT_STATUS_NO_MEMORY;
4465 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4467 return NT_STATUS_NO_MEMORY;
4470 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4471 LDB_FLAG_MOD_REPLACE, NULL);
4472 if (ret != LDB_SUCCESS) {
4473 return NT_STATUS_NO_MEMORY;
4475 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4477 if (ret != LDB_SUCCESS) {
4478 return NT_STATUS_NO_MEMORY;
4481 ret = ldb_modify(p_state->sam_ldb, msg);
4482 if (ret != LDB_SUCCESS) {
4483 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4484 ldb_errstring(p_state->sam_ldb)));
4487 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4488 return NT_STATUS_ACCESS_DENIED;
4490 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4494 return NT_STATUS_OK;
4500 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4501 struct lsa_CREDRRENAME *r)
4503 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4509 lsa_LSAROPENPOLICYSCE
4511 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4512 struct lsa_LSAROPENPOLICYSCE *r)
4514 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4519 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4521 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4522 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4524 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4529 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4531 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4532 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4534 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4539 lsa_LSARADTREPORTSECURITYEVENT
4541 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4542 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4544 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4548 /* include the generated boilerplate */
4549 #include "librpc/gen_ndr/ndr_lsa_s.c"
4553 /*****************************************
4554 NOTE! The remaining calls below were
4555 removed in w2k3, so the DCESRV_FAULT()
4556 replies are the correct implementation. Do
4557 not try and fill these in with anything else
4558 ******************************************/
4561 dssetup_DsRoleDnsNameToFlatName
4563 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4564 struct dssetup_DsRoleDnsNameToFlatName *r)
4566 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4571 dssetup_DsRoleDcAsDc
4573 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4574 struct dssetup_DsRoleDcAsDc *r)
4576 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4581 dssetup_DsRoleDcAsReplica
4583 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4584 struct dssetup_DsRoleDcAsReplica *r)
4586 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4591 dssetup_DsRoleDemoteDc
4593 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4594 struct dssetup_DsRoleDemoteDc *r)
4596 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4601 dssetup_DsRoleGetDcOperationProgress
4603 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4604 struct dssetup_DsRoleGetDcOperationProgress *r)
4606 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4611 dssetup_DsRoleGetDcOperationResults
4613 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4614 struct dssetup_DsRoleGetDcOperationResults *r)
4616 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4621 dssetup_DsRoleCancel
4623 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4624 struct dssetup_DsRoleCancel *r)
4626 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4631 dssetup_DsRoleServerSaveStateForUpgrade
4633 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4634 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4636 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4641 dssetup_DsRoleUpgradeDownlevelServer
4643 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4644 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4646 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4651 dssetup_DsRoleAbortDownlevelServerUpgrade
4653 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4654 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4656 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4660 /* include the generated boilerplate */
4661 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4663 NTSTATUS dcerpc_server_lsa_init(void)
4667 ret = dcerpc_server_dssetup_init();
4668 if (!NT_STATUS_IS_OK(ret)) {
4671 ret = dcerpc_server_lsarpc_init();
4672 if (!NT_STATUS_IS_OK(ret)) {