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"
35 #include "lib/messaging/irpc.h"
38 this type allows us to distinguish handle types
42 state associated with a lsa_OpenAccount() operation
44 struct lsa_account_state {
45 struct lsa_policy_state *policy;
47 struct dom_sid *account_sid;
52 state associated with a lsa_OpenSecret() operation
54 struct lsa_secret_state {
55 struct lsa_policy_state *policy;
57 struct ldb_dn *secret_dn;
58 struct ldb_context *sam_ldb;
63 state associated with a lsa_OpenTrustedDomain() operation
65 struct lsa_trusted_domain_state {
66 struct lsa_policy_state *policy;
68 struct ldb_dn *trusted_domain_dn;
69 struct ldb_dn *trusted_domain_user_dn;
73 this is based on the samba3 function make_lsa_object_sd()
74 It uses the same logic, but with samba4 helper functions
76 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
77 struct security_descriptor **sd,
83 struct dom_sid *domain_sid, *domain_admins_sid;
84 const char *domain_admins_sid_str, *sidstr;
85 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
87 status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
88 if (!NT_STATUS_IS_OK(status)) {
93 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
94 if (domain_admins_sid == NULL) {
96 return NT_STATUS_NO_MEMORY;
99 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
100 if (domain_admins_sid_str == NULL) {
101 TALLOC_FREE(tmp_ctx);
102 return NT_STATUS_NO_MEMORY;
105 sidstr = dom_sid_string(tmp_ctx, sid);
106 if (sidstr == NULL) {
107 TALLOC_FREE(tmp_ctx);
108 return NT_STATUS_NO_MEMORY;
111 *sd = security_descriptor_dacl_create(mem_ctx,
115 SEC_ACE_TYPE_ACCESS_ALLOWED,
116 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
118 SID_BUILTIN_ADMINISTRATORS,
119 SEC_ACE_TYPE_ACCESS_ALLOWED,
122 SID_BUILTIN_ACCOUNT_OPERATORS,
123 SEC_ACE_TYPE_ACCESS_ALLOWED,
126 domain_admins_sid_str,
127 SEC_ACE_TYPE_ACCESS_ALLOWED,
131 SEC_ACE_TYPE_ACCESS_ALLOWED,
135 talloc_free(tmp_ctx);
137 NT_STATUS_HAVE_NO_MEMORY(*sd);
143 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
145 struct lsa_EnumAccountRights *r);
147 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
149 struct lsa_policy_state *state,
152 const struct lsa_RightSet *rights);
157 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
160 enum dcerpc_transport_t transport =
161 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
162 struct dcesrv_handle *h;
164 if (transport != NCACN_NP && transport != NCALRPC) {
165 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
168 *r->out.handle = *r->in.handle;
170 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
174 ZERO_STRUCTP(r->out.handle);
183 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
184 struct lsa_Delete *r)
186 return NT_STATUS_NOT_SUPPORTED;
193 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
194 struct lsa_DeleteObject *r)
196 struct dcesrv_handle *h;
199 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
201 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
202 struct lsa_secret_state *secret_state = h->data;
204 /* Ensure user is permitted to delete this... */
205 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
207 case SECURITY_SYSTEM:
208 case SECURITY_ADMINISTRATOR:
211 /* Users and anonymous are not allowed to delete things */
212 return NT_STATUS_ACCESS_DENIED;
215 ret = ldb_delete(secret_state->sam_ldb,
216 secret_state->secret_dn);
217 if (ret != LDB_SUCCESS) {
218 return NT_STATUS_INVALID_HANDLE;
221 ZERO_STRUCTP(r->out.handle);
225 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
226 struct lsa_trusted_domain_state *trusted_domain_state =
227 talloc_get_type(h->data, struct lsa_trusted_domain_state);
228 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
229 if (ret != LDB_SUCCESS) {
230 return NT_STATUS_INTERNAL_DB_CORRUPTION;
233 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
234 trusted_domain_state->trusted_domain_dn);
235 if (ret != LDB_SUCCESS) {
236 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
237 return NT_STATUS_INVALID_HANDLE;
240 if (trusted_domain_state->trusted_domain_user_dn) {
241 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
242 trusted_domain_state->trusted_domain_user_dn);
243 if (ret != LDB_SUCCESS) {
244 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
245 return NT_STATUS_INVALID_HANDLE;
249 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
250 if (ret != LDB_SUCCESS) {
251 return NT_STATUS_INTERNAL_DB_CORRUPTION;
254 ZERO_STRUCTP(r->out.handle);
258 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
259 struct lsa_RightSet *rights;
260 struct lsa_account_state *astate;
261 struct lsa_EnumAccountRights r2;
264 rights = talloc(mem_ctx, struct lsa_RightSet);
266 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
270 r2.in.handle = &astate->policy->handle->wire_handle;
271 r2.in.sid = astate->account_sid;
272 r2.out.rights = rights;
274 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
275 but we have a LSA_HANDLE_ACCOUNT here, so this call
277 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
278 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
282 if (!NT_STATUS_IS_OK(status)) {
286 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
287 LDB_FLAG_MOD_DELETE, astate->account_sid,
289 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
293 if (!NT_STATUS_IS_OK(status)) {
297 ZERO_STRUCTP(r->out.handle);
302 return NT_STATUS_INVALID_HANDLE;
309 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
310 struct lsa_EnumPrivs *r)
312 struct dcesrv_handle *h;
314 enum sec_privilege priv;
315 const char *privname;
317 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
319 i = *r->in.resume_handle;
321 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
322 r->out.privs->count < r->in.max_count) {
323 struct lsa_PrivEntry *e;
324 privname = sec_privilege_name(priv);
325 r->out.privs->privs = talloc_realloc(r->out.privs,
327 struct lsa_PrivEntry,
328 r->out.privs->count+1);
329 if (r->out.privs->privs == NULL) {
330 return NT_STATUS_NO_MEMORY;
332 e = &r->out.privs->privs[r->out.privs->count];
335 e->name.string = privname;
336 r->out.privs->count++;
340 *r->out.resume_handle = i;
349 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
350 struct lsa_QuerySecurity *r)
352 struct dcesrv_handle *h;
353 const struct security_descriptor *sd = NULL;
354 uint32_t access_granted = 0;
355 struct sec_desc_buf *sdbuf = NULL;
359 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
361 sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
363 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
364 struct lsa_policy_state *pstate = h->data;
367 access_granted = pstate->access_mask;
369 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
370 struct lsa_account_state *astate = h->data;
371 struct security_descriptor *_sd = NULL;
373 status = dcesrv_build_lsa_sd(mem_ctx, &_sd, sid,
374 LSA_ACCOUNT_ALL_ACCESS);
375 if (!NT_STATUS_IS_OK(status)) {
379 access_granted = astate->access_mask;
381 return NT_STATUS_INVALID_HANDLE;
384 sdbuf = talloc_zero(mem_ctx, struct sec_desc_buf);
386 return NT_STATUS_NO_MEMORY;
389 status = security_descriptor_for_client(sdbuf, sd, r->in.sec_info,
390 access_granted, &sdbuf->sd);
391 if (!NT_STATUS_IS_OK(status)) {
395 *r->out.sdbuf = sdbuf;
404 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
405 struct lsa_SetSecObj *r)
407 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
414 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
415 struct lsa_ChangePassword *r)
417 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
421 dssetup_DsRoleGetPrimaryDomainInformation
423 This is not an LSA call, but is the only call left on the DSSETUP
424 pipe (after the pipe was truncated), and needs lsa_get_policy_state
426 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
428 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
430 union dssetup_DsRoleInfo *info;
432 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
433 W_ERROR_HAVE_NO_MEMORY(info);
435 switch (r->in.level) {
436 case DS_ROLE_BASIC_INFORMATION:
438 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
440 const char *domain = NULL;
441 const char *dns_domain = NULL;
442 const char *forest = NULL;
443 struct GUID domain_guid;
444 struct lsa_policy_state *state;
446 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
447 0, /* we skip access checks */
449 if (!NT_STATUS_IS_OK(status)) {
450 return ntstatus_to_werror(status);
453 ZERO_STRUCT(domain_guid);
455 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
456 case ROLE_STANDALONE:
457 role = DS_ROLE_STANDALONE_SERVER;
459 case ROLE_DOMAIN_MEMBER:
460 role = DS_ROLE_MEMBER_SERVER;
462 case ROLE_ACTIVE_DIRECTORY_DC:
463 if (samdb_is_pdc(state->sam_ldb)) {
464 role = DS_ROLE_PRIMARY_DC;
466 role = DS_ROLE_BACKUP_DC;
471 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
472 case ROLE_STANDALONE:
473 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
474 W_ERROR_HAVE_NO_MEMORY(domain);
476 case ROLE_DOMAIN_MEMBER:
477 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
478 W_ERROR_HAVE_NO_MEMORY(domain);
479 /* TODO: what is with dns_domain and forest and guid? */
481 case ROLE_ACTIVE_DIRECTORY_DC:
482 flags = DS_ROLE_PRIMARY_DS_RUNNING;
484 if (state->mixed_domain == 1) {
485 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
488 domain = state->domain_name;
489 dns_domain = state->domain_dns;
490 forest = state->forest_dns;
492 domain_guid = state->domain_guid;
493 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
497 info->basic.role = role;
498 info->basic.flags = flags;
499 info->basic.domain = domain;
500 info->basic.dns_domain = dns_domain;
501 info->basic.forest = forest;
502 info->basic.domain_guid = domain_guid;
507 case DS_ROLE_UPGRADE_STATUS:
509 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
510 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
515 case DS_ROLE_OP_STATUS:
517 info->opstatus.status = DS_ROLE_OP_IDLE;
523 return WERR_INVALID_PARAM;
528 fill in the AccountDomain info
530 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
531 struct lsa_DomainInfo *info)
533 info->name.string = state->domain_name;
534 info->sid = state->domain_sid;
540 fill in the DNS domain info
542 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
543 struct lsa_DnsDomainInfo *info)
545 info->name.string = state->domain_name;
546 info->sid = state->domain_sid;
547 info->dns_domain.string = state->domain_dns;
548 info->dns_forest.string = state->forest_dns;
549 info->domain_guid = state->domain_guid;
557 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
558 struct lsa_QueryInfoPolicy2 *r)
560 struct lsa_policy_state *state;
561 struct dcesrv_handle *h;
562 union lsa_PolicyInformation *info;
566 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
570 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
572 return NT_STATUS_NO_MEMORY;
576 switch (r->in.level) {
577 case LSA_POLICY_INFO_AUDIT_LOG:
578 /* we don't need to fill in any of this */
579 ZERO_STRUCT(info->audit_log);
581 case LSA_POLICY_INFO_AUDIT_EVENTS:
582 /* we don't need to fill in any of this */
583 ZERO_STRUCT(info->audit_events);
585 case LSA_POLICY_INFO_PD:
586 /* we don't need to fill in any of this */
587 ZERO_STRUCT(info->pd);
590 case LSA_POLICY_INFO_DOMAIN:
591 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
592 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
593 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
594 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
595 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
597 case LSA_POLICY_INFO_ROLE:
598 info->role.role = LSA_ROLE_PRIMARY;
601 case LSA_POLICY_INFO_DNS:
602 case LSA_POLICY_INFO_DNS_INT:
603 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
605 case LSA_POLICY_INFO_REPLICA:
606 ZERO_STRUCT(info->replica);
609 case LSA_POLICY_INFO_QUOTA:
610 ZERO_STRUCT(info->quota);
613 case LSA_POLICY_INFO_MOD:
614 case LSA_POLICY_INFO_AUDIT_FULL_SET:
615 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
616 /* windows gives INVALID_PARAMETER */
618 return NT_STATUS_INVALID_PARAMETER;
622 return NT_STATUS_INVALID_INFO_CLASS;
628 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
629 struct lsa_QueryInfoPolicy *r)
631 struct lsa_QueryInfoPolicy2 r2;
636 r2.in.handle = r->in.handle;
637 r2.in.level = r->in.level;
638 r2.out.info = r->out.info;
640 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
648 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
649 struct lsa_SetInfoPolicy *r)
651 /* need to support this */
652 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
659 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
660 struct lsa_ClearAuditLog *r)
662 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
666 static const struct generic_mapping dcesrv_lsa_account_mapping = {
670 LSA_ACCOUNT_ALL_ACCESS
676 This call does not seem to have any long-term effects, hence no database operations
678 we need to talk to the MS product group to find out what this account database means!
680 answer is that the lsa database is totally separate from the SAM and
681 ldap databases. We are going to need a separate ldb to store these
682 accounts. The SIDs on this account bear no relation to the SIDs in
685 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
686 struct lsa_CreateAccount *r)
688 struct lsa_account_state *astate;
690 struct lsa_policy_state *state;
691 struct dcesrv_handle *h, *ah;
693 ZERO_STRUCTP(r->out.acct_handle);
695 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
699 astate = talloc(dce_call->conn, struct lsa_account_state);
700 if (astate == NULL) {
701 return NT_STATUS_NO_MEMORY;
704 astate->account_sid = dom_sid_dup(astate, r->in.sid);
705 if (astate->account_sid == NULL) {
707 return NT_STATUS_NO_MEMORY;
710 astate->policy = talloc_reference(astate, state);
711 astate->access_mask = r->in.access_mask;
714 * For now we grant all requested access.
716 * We will fail at the ldb layer later.
718 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
719 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
720 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
722 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
724 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X].\n",
725 __func__, dom_sid_string(mem_ctx, astate->account_sid),
726 (unsigned)r->in.access_mask,
727 (unsigned)astate->access_mask));
729 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
732 return NT_STATUS_NO_MEMORY;
735 ah->data = talloc_steal(ah, astate);
737 *r->out.acct_handle = ah->wire_handle;
746 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
747 struct lsa_EnumAccounts *r)
749 struct dcesrv_handle *h;
750 struct lsa_policy_state *state;
752 struct ldb_message **res;
753 const char * const attrs[] = { "objectSid", NULL};
756 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
760 /* NOTE: This call must only return accounts that have at least
763 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
764 "(&(objectSid=*)(privilege=*))");
766 return NT_STATUS_INTERNAL_DB_CORRUPTION;
769 if (*r->in.resume_handle >= ret) {
770 return NT_STATUS_NO_MORE_ENTRIES;
773 count = ret - *r->in.resume_handle;
774 if (count > r->in.num_entries) {
775 count = r->in.num_entries;
779 return NT_STATUS_NO_MORE_ENTRIES;
782 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
783 if (r->out.sids->sids == NULL) {
784 return NT_STATUS_NO_MEMORY;
787 for (i=0;i<count;i++) {
788 r->out.sids->sids[i].sid =
789 samdb_result_dom_sid(r->out.sids->sids,
790 res[i + *r->in.resume_handle],
792 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
795 r->out.sids->num_sids = count;
796 *r->out.resume_handle = count + *r->in.resume_handle;
801 /* This decrypts and returns Trusted Domain Auth Information Internal data */
802 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
803 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
804 struct trustDomainPasswords *auth_struct)
806 DATA_BLOB session_key = data_blob(NULL, 0);
807 enum ndr_err_code ndr_err;
810 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
811 if (!NT_STATUS_IS_OK(nt_status)) {
815 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
816 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
818 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
819 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
820 return NT_STATUS_INVALID_PARAMETER;
826 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
828 struct trustAuthInOutBlob *iopw,
829 DATA_BLOB *trustauth_blob)
831 enum ndr_err_code ndr_err;
833 if (iopw->current.count != iopw->count) {
834 return NT_STATUS_INVALID_PARAMETER;
837 if (iopw->previous.count > iopw->current.count) {
838 return NT_STATUS_INVALID_PARAMETER;
841 if (iopw->previous.count == 0) {
843 * If the previous credentials are not present
844 * we need to make a copy.
846 iopw->previous = iopw->current;
849 if (iopw->previous.count < iopw->current.count) {
850 struct AuthenticationInformationArray *c = &iopw->current;
851 struct AuthenticationInformationArray *p = &iopw->previous;
854 * The previous array needs to have the same size
855 * as the current one.
857 * We may have to fill with TRUST_AUTH_TYPE_NONE
860 p->array = talloc_realloc(mem_ctx, p->array,
861 struct AuthenticationInformation,
863 if (p->array == NULL) {
864 return NT_STATUS_NO_MEMORY;
867 while (p->count < c->count) {
868 struct AuthenticationInformation *a =
869 &p->array[p->count++];
871 *a = (struct AuthenticationInformation) {
872 .LastUpdateTime = p->array[0].LastUpdateTime,
873 .AuthType = TRUST_AUTH_TYPE_NONE,
878 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
880 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
881 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
882 return NT_STATUS_INVALID_PARAMETER;
888 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
889 struct ldb_context *sam_ldb,
890 struct ldb_dn *base_dn,
891 const char *netbios_name,
892 struct trustAuthInOutBlob *in,
893 struct ldb_dn **user_dn)
895 struct ldb_request *req;
896 struct ldb_message *msg;
901 dn = ldb_dn_copy(mem_ctx, base_dn);
903 return NT_STATUS_NO_MEMORY;
905 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
906 return NT_STATUS_NO_MEMORY;
909 msg = ldb_msg_new(mem_ctx);
911 return NT_STATUS_NO_MEMORY;
915 ret = ldb_msg_add_string(msg, "objectClass", "user");
916 if (ret != LDB_SUCCESS) {
917 return NT_STATUS_NO_MEMORY;
920 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
921 if (ret != LDB_SUCCESS) {
922 return NT_STATUS_NO_MEMORY;
925 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
926 UF_INTERDOMAIN_TRUST_ACCOUNT);
927 if (ret != LDB_SUCCESS) {
928 return NT_STATUS_NO_MEMORY;
931 for (i = 0; i < in->count; i++) {
932 const char *attribute;
934 switch (in->current.array[i].AuthType) {
935 case TRUST_AUTH_TYPE_NT4OWF:
936 attribute = "unicodePwd";
937 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
940 case TRUST_AUTH_TYPE_CLEAR:
941 attribute = "clearTextPassword";
942 v.data = in->current.array[i].AuthInfo.clear.password;
943 v.length = in->current.array[i].AuthInfo.clear.size;
949 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
950 if (ret != LDB_SUCCESS) {
951 return NT_STATUS_NO_MEMORY;
955 /* create the trusted_domain user account */
956 ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
957 ldb_op_default_callback, NULL);
958 if (ret != LDB_SUCCESS) {
959 return NT_STATUS_NO_MEMORY;
962 ret = ldb_request_add_control(req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
964 if (ret != LDB_SUCCESS) {
965 return NT_STATUS_NO_MEMORY;
968 ret = dsdb_autotransaction_request(sam_ldb, req);
969 if (ret != LDB_SUCCESS) {
970 DEBUG(0,("Failed to create user record %s: %s\n",
971 ldb_dn_get_linearized(msg->dn),
972 ldb_errstring(sam_ldb)));
975 case LDB_ERR_ENTRY_ALREADY_EXISTS:
976 return NT_STATUS_DOMAIN_EXISTS;
977 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
978 return NT_STATUS_ACCESS_DENIED;
980 return NT_STATUS_INTERNAL_DB_CORRUPTION;
991 lsa_CreateTrustedDomainEx2
993 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
995 struct lsa_CreateTrustedDomainEx2 *r,
997 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
999 struct dcesrv_handle *policy_handle;
1000 struct lsa_policy_state *policy_state;
1001 struct lsa_trusted_domain_state *trusted_domain_state;
1002 struct dcesrv_handle *handle;
1003 struct ldb_message **msgs, *msg;
1004 const char *attrs[] = {
1007 const char *netbios_name;
1008 const char *dns_name;
1009 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1010 struct trustDomainPasswords auth_struct;
1013 struct ldb_context *sam_ldb;
1014 struct server_id *server_ids = NULL;
1015 uint32_t num_server_ids = 0;
1017 struct dom_sid *tmp_sid1;
1018 struct dom_sid *tmp_sid2;
1021 char *dns_encoded = NULL;
1022 char *netbios_encoded = NULL;
1023 char *sid_encoded = NULL;
1025 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
1026 ZERO_STRUCTP(r->out.trustdom_handle);
1028 policy_state = policy_handle->data;
1029 sam_ldb = policy_state->sam_ldb;
1031 netbios_name = r->in.info->netbios_name.string;
1032 if (!netbios_name) {
1033 return NT_STATUS_INVALID_PARAMETER;
1036 dns_name = r->in.info->domain_name.string;
1037 if (dns_name == NULL) {
1038 return NT_STATUS_INVALID_PARAMETER;
1041 if (r->in.info->sid == NULL) {
1042 return NT_STATUS_INVALID_SID;
1046 * We expect S-1-5-21-A-B-C, but we don't
1047 * allow S-1-5-21-0-0-0 as this is used
1048 * for claims and compound identities.
1050 * So we call dom_sid_split_rid() 3 times
1051 * and compare the result to S-1-5-21
1053 status = dom_sid_split_rid(mem_ctx, r->in.info->sid, &tmp_sid1, &tmp_rid);
1054 if (!NT_STATUS_IS_OK(status)) {
1057 status = dom_sid_split_rid(mem_ctx, tmp_sid1, &tmp_sid2, &tmp_rid);
1058 if (!NT_STATUS_IS_OK(status)) {
1061 status = dom_sid_split_rid(mem_ctx, tmp_sid2, &tmp_sid1, &tmp_rid);
1062 if (!NT_STATUS_IS_OK(status)) {
1065 ok = dom_sid_parse("S-1-5-21", tmp_sid2);
1067 return NT_STATUS_INTERNAL_ERROR;
1069 ok = dom_sid_equal(tmp_sid1, tmp_sid2);
1071 return NT_STATUS_INVALID_PARAMETER;
1073 ok = dom_sid_parse("S-1-5-21-0-0-0", tmp_sid2);
1075 return NT_STATUS_INTERNAL_ERROR;
1077 ok = !dom_sid_equal(r->in.info->sid, tmp_sid2);
1079 return NT_STATUS_INVALID_PARAMETER;
1082 dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1083 if (dns_encoded == NULL) {
1084 return NT_STATUS_NO_MEMORY;
1086 netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1087 if (netbios_encoded == NULL) {
1088 return NT_STATUS_NO_MEMORY;
1090 sid_encoded = ldap_encode_ndr_dom_sid(mem_ctx, r->in.info->sid);
1091 if (sid_encoded == NULL) {
1092 return NT_STATUS_NO_MEMORY;
1095 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1096 if (!trusted_domain_state) {
1097 return NT_STATUS_NO_MEMORY;
1099 trusted_domain_state->policy = policy_state;
1101 if (strcasecmp(netbios_name, "BUILTIN") == 0
1102 || (strcasecmp(dns_name, "BUILTIN") == 0)
1103 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
1104 return NT_STATUS_INVALID_PARAMETER;
1107 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
1108 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
1109 || strcasecmp(dns_name, policy_state->domain_dns) == 0
1110 || strcasecmp(dns_name, policy_state->domain_name) == 0
1111 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
1112 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
1115 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
1116 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
1117 /* No secrets are created at this time, for this function */
1118 auth_struct.outgoing.count = 0;
1119 auth_struct.incoming.count = 0;
1120 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
1121 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
1122 r->in.auth_info_internal->auth_blob.size);
1123 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1124 &auth_blob, &auth_struct);
1125 if (!NT_STATUS_IS_OK(nt_status)) {
1128 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
1130 if (unencrypted_auth_info->incoming_count > 1) {
1131 return NT_STATUS_INVALID_PARAMETER;
1134 /* more investigation required here, do not create secrets for
1136 auth_struct.outgoing.count = 0;
1137 auth_struct.incoming.count = 0;
1139 return NT_STATUS_INVALID_PARAMETER;
1142 if (auth_struct.incoming.count) {
1143 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1144 &auth_struct.incoming,
1145 &trustAuthIncoming);
1146 if (!NT_STATUS_IS_OK(nt_status)) {
1150 trustAuthIncoming = data_blob(NULL, 0);
1153 if (auth_struct.outgoing.count) {
1154 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1155 &auth_struct.outgoing,
1156 &trustAuthOutgoing);
1157 if (!NT_STATUS_IS_OK(nt_status)) {
1161 trustAuthOutgoing = data_blob(NULL, 0);
1164 ret = ldb_transaction_start(sam_ldb);
1165 if (ret != LDB_SUCCESS) {
1166 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1169 /* search for the trusted_domain record */
1170 ret = gendb_search(sam_ldb,
1171 mem_ctx, policy_state->system_dn, &msgs, attrs,
1172 "(&(objectClass=trustedDomain)(|"
1173 "(flatname=%s)(trustPartner=%s)"
1174 "(flatname=%s)(trustPartner=%s)"
1175 "(securityIdentifier=%s)))",
1176 dns_encoded, dns_encoded,
1177 netbios_encoded, netbios_encoded,
1180 ldb_transaction_cancel(sam_ldb);
1181 return NT_STATUS_OBJECT_NAME_COLLISION;
1184 ldb_transaction_cancel(sam_ldb);
1185 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1188 msg = ldb_msg_new(mem_ctx);
1190 return NT_STATUS_NO_MEMORY;
1193 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1194 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", dns_name)) {
1195 ldb_transaction_cancel(sam_ldb);
1196 return NT_STATUS_NO_MEMORY;
1199 ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1200 if (ret != LDB_SUCCESS) {
1201 ldb_transaction_cancel(sam_ldb);
1202 return NT_STATUS_NO_MEMORY;;
1205 ret = ldb_msg_add_string(msg, "flatname", netbios_name);
1206 if (ret != LDB_SUCCESS) {
1207 ldb_transaction_cancel(sam_ldb);
1208 return NT_STATUS_NO_MEMORY;
1211 ret = ldb_msg_add_string(msg, "trustPartner", dns_name);
1212 if (ret != LDB_SUCCESS) {
1213 ldb_transaction_cancel(sam_ldb);
1214 return NT_STATUS_NO_MEMORY;;
1217 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier",
1219 if (ret != LDB_SUCCESS) {
1220 ldb_transaction_cancel(sam_ldb);
1221 return NT_STATUS_NO_MEMORY;;
1224 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1225 if (ret != LDB_SUCCESS) {
1226 ldb_transaction_cancel(sam_ldb);
1227 return NT_STATUS_NO_MEMORY;;
1230 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1231 if (ret != LDB_SUCCESS) {
1232 ldb_transaction_cancel(sam_ldb);
1233 return NT_STATUS_NO_MEMORY;;
1236 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1237 if (ret != LDB_SUCCESS) {
1238 ldb_transaction_cancel(sam_ldb);
1239 return NT_STATUS_NO_MEMORY;;
1242 if (trustAuthIncoming.data) {
1243 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1244 if (ret != LDB_SUCCESS) {
1245 ldb_transaction_cancel(sam_ldb);
1246 return NT_STATUS_NO_MEMORY;
1249 if (trustAuthOutgoing.data) {
1250 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1251 if (ret != LDB_SUCCESS) {
1252 ldb_transaction_cancel(sam_ldb);
1253 return NT_STATUS_NO_MEMORY;
1257 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1259 /* create the trusted_domain */
1260 ret = ldb_add(sam_ldb, msg);
1264 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1265 ldb_transaction_cancel(sam_ldb);
1266 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1267 ldb_dn_get_linearized(msg->dn),
1268 ldb_errstring(sam_ldb)));
1269 return NT_STATUS_DOMAIN_EXISTS;
1270 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1271 ldb_transaction_cancel(sam_ldb);
1272 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1273 ldb_dn_get_linearized(msg->dn),
1274 ldb_errstring(sam_ldb)));
1275 return NT_STATUS_ACCESS_DENIED;
1277 ldb_transaction_cancel(sam_ldb);
1278 DEBUG(0,("Failed to create user record %s: %s\n",
1279 ldb_dn_get_linearized(msg->dn),
1280 ldb_errstring(sam_ldb)));
1281 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1284 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1285 struct ldb_dn *user_dn;
1286 /* Inbound trusts must also create a cn=users object to match */
1287 nt_status = add_trust_user(mem_ctx, sam_ldb,
1288 policy_state->domain_dn,
1290 &auth_struct.incoming,
1292 if (!NT_STATUS_IS_OK(nt_status)) {
1293 ldb_transaction_cancel(sam_ldb);
1297 /* save the trust user dn */
1298 trusted_domain_state->trusted_domain_user_dn
1299 = talloc_steal(trusted_domain_state, user_dn);
1302 ret = ldb_transaction_commit(sam_ldb);
1303 if (ret != LDB_SUCCESS) {
1304 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1308 * Notify winbindd that we have a new trust
1310 status = irpc_servers_byname(dce_call->msg_ctx,
1313 &num_server_ids, &server_ids);
1314 if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
1315 enum ndr_err_code ndr_err;
1318 ndr_err = ndr_push_struct_blob(&b, mem_ctx, r->in.info,
1319 (ndr_push_flags_fn_t)ndr_push_lsa_TrustDomainInfoInfoEx);
1320 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1321 imessaging_send(dce_call->msg_ctx, server_ids[0],
1322 MSG_WINBIND_NEW_TRUSTED_DOMAIN, &b);
1325 TALLOC_FREE(server_ids);
1327 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1329 return NT_STATUS_NO_MEMORY;
1332 handle->data = talloc_steal(handle, trusted_domain_state);
1334 trusted_domain_state->access_mask = r->in.access_mask;
1335 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1337 *r->out.trustdom_handle = handle->wire_handle;
1339 return NT_STATUS_OK;
1343 lsa_CreateTrustedDomainEx2
1345 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1346 TALLOC_CTX *mem_ctx,
1347 struct lsa_CreateTrustedDomainEx2 *r)
1349 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1352 lsa_CreateTrustedDomainEx
1354 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1355 TALLOC_CTX *mem_ctx,
1356 struct lsa_CreateTrustedDomainEx *r)
1358 struct lsa_CreateTrustedDomainEx2 r2;
1360 r2.in.policy_handle = r->in.policy_handle;
1361 r2.in.info = r->in.info;
1362 r2.out.trustdom_handle = r->out.trustdom_handle;
1363 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1367 lsa_CreateTrustedDomain
1369 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1370 struct lsa_CreateTrustedDomain *r)
1372 struct lsa_CreateTrustedDomainEx2 r2;
1374 r2.in.policy_handle = r->in.policy_handle;
1375 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1377 return NT_STATUS_NO_MEMORY;
1380 r2.in.info->domain_name = r->in.info->name;
1381 r2.in.info->netbios_name = r->in.info->name;
1382 r2.in.info->sid = r->in.info->sid;
1383 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1384 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1385 r2.in.info->trust_attributes = 0;
1387 r2.in.access_mask = r->in.access_mask;
1388 r2.out.trustdom_handle = r->out.trustdom_handle;
1390 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1393 static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
1394 struct dcesrv_call_state *dce_call,
1395 TALLOC_CTX *tmp_mem,
1396 struct lsa_policy_state *policy_state,
1398 uint32_t access_mask,
1399 struct dcesrv_handle **_handle)
1401 struct lsa_trusted_domain_state *trusted_domain_state;
1402 struct dcesrv_handle *handle;
1403 struct ldb_message **msgs;
1404 const char *attrs[] = {
1412 /* TODO: perform access checks */
1414 /* search for the trusted_domain record */
1415 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1416 policy_state->system_dn,
1417 &msgs, attrs, "%s", filter);
1419 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1423 DEBUG(0,("Found %d records matching %s under %s\n", ret,
1425 ldb_dn_get_linearized(policy_state->system_dn)));
1426 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1429 trusted_domain_state = talloc_zero(tmp_mem,
1430 struct lsa_trusted_domain_state);
1431 if (!trusted_domain_state) {
1432 return NT_STATUS_NO_MEMORY;
1434 trusted_domain_state->policy = policy_state;
1436 trusted_domain_state->trusted_domain_dn =
1437 talloc_steal(trusted_domain_state, msgs[0]->dn);
1439 direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1440 if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1441 const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1444 /* search for the trusted_domain account */
1445 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1446 policy_state->domain_dn,
1448 "(&(samaccountname=%s$)(objectclass=user)"
1449 "(userAccountControl:%s:=%u))",
1451 LDB_OID_COMPARATOR_AND,
1452 UF_INTERDOMAIN_TRUST_ACCOUNT);
1454 trusted_domain_state->trusted_domain_user_dn =
1455 talloc_steal(trusted_domain_state, msgs[0]->dn);
1459 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1461 return NT_STATUS_NO_MEMORY;
1464 handle->data = talloc_steal(handle, trusted_domain_state);
1466 trusted_domain_state->access_mask = access_mask;
1467 trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1472 return NT_STATUS_OK;
1476 lsa_OpenTrustedDomain
1478 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1479 struct lsa_OpenTrustedDomain *r)
1481 struct dcesrv_handle *policy_handle;
1482 struct lsa_policy_state *policy_state;
1483 struct dcesrv_handle *handle;
1484 const char *sid_string;
1488 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1489 ZERO_STRUCTP(r->out.trustdom_handle);
1490 policy_state = policy_handle->data;
1492 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1494 return NT_STATUS_NO_MEMORY;
1497 filter = talloc_asprintf(mem_ctx,
1498 "(&(securityIdentifier=%s)"
1499 "(objectclass=trustedDomain))",
1501 if (filter == NULL) {
1502 return NT_STATUS_NO_MEMORY;
1505 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1510 if (!NT_STATUS_IS_OK(status)) {
1514 *r->out.trustdom_handle = handle->wire_handle;
1516 return NT_STATUS_OK;
1521 lsa_OpenTrustedDomainByName
1523 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1524 TALLOC_CTX *mem_ctx,
1525 struct lsa_OpenTrustedDomainByName *r)
1527 struct dcesrv_handle *policy_handle;
1528 struct lsa_policy_state *policy_state;
1529 struct dcesrv_handle *handle;
1534 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1535 ZERO_STRUCTP(r->out.trustdom_handle);
1536 policy_state = policy_handle->data;
1538 if (!r->in.name.string) {
1539 return NT_STATUS_INVALID_PARAMETER;
1542 /* search for the trusted_domain record */
1543 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1544 if (td_name == NULL) {
1545 return NT_STATUS_NO_MEMORY;
1548 filter = talloc_asprintf(mem_ctx,
1549 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1550 "(objectclass=trustedDomain))",
1551 td_name, td_name, td_name);
1552 if (filter == NULL) {
1553 return NT_STATUS_NO_MEMORY;
1556 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1561 if (!NT_STATUS_IS_OK(status)) {
1565 *r->out.trustdom_handle = handle->wire_handle;
1567 return NT_STATUS_OK;
1573 lsa_SetTrustedDomainInfo
1575 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1576 struct lsa_SetTrustedDomainInfo *r)
1578 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1583 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1584 * otherwise at least one must be provided */
1585 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1586 struct ldb_dn *basedn, const char *dns_domain,
1587 const char *netbios, struct dom_sid2 *sid,
1588 struct ldb_message ***msgs)
1590 const char *attrs[] = { "flatname", "trustPartner",
1591 "securityIdentifier", "trustDirection",
1592 "trustType", "trustAttributes",
1594 "msDs-supportedEncryptionTypes",
1595 "msDS-TrustForestTrustInfo",
1600 char *sidstr = NULL;
1605 if (dns_domain || netbios || sid) {
1606 filter = talloc_strdup(mem_ctx,
1607 "(&(objectclass=trustedDomain)(|");
1609 filter = talloc_strdup(mem_ctx,
1610 "(objectclass=trustedDomain)");
1613 return NT_STATUS_NO_MEMORY;
1617 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1619 return NT_STATUS_NO_MEMORY;
1621 filter = talloc_asprintf_append(filter,
1622 "(trustPartner=%s)", dns);
1624 return NT_STATUS_NO_MEMORY;
1628 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1630 return NT_STATUS_NO_MEMORY;
1632 filter = talloc_asprintf_append(filter,
1633 "(flatname=%s)", nbn);
1635 return NT_STATUS_NO_MEMORY;
1639 sidstr = dom_sid_string(mem_ctx, sid);
1641 return NT_STATUS_INVALID_PARAMETER;
1643 filter = talloc_asprintf_append(filter,
1644 "(securityIdentifier=%s)",
1647 return NT_STATUS_NO_MEMORY;
1650 if (dns_domain || netbios || sid) {
1651 filter = talloc_asprintf_append(filter, "))");
1653 return NT_STATUS_NO_MEMORY;
1657 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1659 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1663 return NT_STATUS_OBJECT_NAME_COLLISION;
1666 return NT_STATUS_OK;
1669 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1670 struct ldb_context *sam_ldb,
1671 struct ldb_message *orig,
1672 struct ldb_message *dest,
1673 const char *attribute,
1675 uint32_t *orig_value)
1677 const struct ldb_val *orig_val;
1678 uint32_t orig_uint = 0;
1679 unsigned int flags = 0;
1682 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1683 if (!orig_val || !orig_val->data) {
1684 /* add new attribute */
1685 flags = LDB_FLAG_MOD_ADD;
1689 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1690 if (errno != 0 || orig_uint != value) {
1691 /* replace also if can't get value */
1692 flags = LDB_FLAG_MOD_REPLACE;
1697 /* stored value is identical, nothing to change */
1701 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1702 if (ret != LDB_SUCCESS) {
1703 return NT_STATUS_NO_MEMORY;
1706 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1707 if (ret != LDB_SUCCESS) {
1708 return NT_STATUS_NO_MEMORY;
1713 *orig_value = orig_uint;
1715 return NT_STATUS_OK;
1718 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1719 struct ldb_context *sam_ldb,
1720 struct ldb_dn *base_dn,
1722 const char *netbios_name,
1723 struct trustAuthInOutBlob *in)
1725 const char *attrs[] = { "userAccountControl", NULL };
1726 struct ldb_message **msgs;
1727 struct ldb_message *msg;
1732 ret = gendb_search(sam_ldb, mem_ctx,
1733 base_dn, &msgs, attrs,
1734 "samAccountName=%s$", netbios_name);
1736 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1741 return NT_STATUS_OK;
1744 /* ok no existing user, add it from scratch */
1745 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1746 netbios_name, in, NULL);
1749 /* check user is what we are looking for */
1750 uac = ldb_msg_find_attr_as_uint(msgs[0],
1751 "userAccountControl", 0);
1752 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1753 return NT_STATUS_OBJECT_NAME_COLLISION;
1757 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1760 return NT_STATUS_OK;
1761 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1762 return NT_STATUS_ACCESS_DENIED;
1764 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1768 /* entry exists, just modify secret if any */
1769 if (in == NULL || in->count == 0) {
1770 return NT_STATUS_OK;
1773 msg = ldb_msg_new(mem_ctx);
1775 return NT_STATUS_NO_MEMORY;
1777 msg->dn = msgs[0]->dn;
1779 for (i = 0; i < in->count; i++) {
1780 const char *attribute;
1782 switch (in->current.array[i].AuthType) {
1783 case TRUST_AUTH_TYPE_NT4OWF:
1784 attribute = "unicodePwd";
1785 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1788 case TRUST_AUTH_TYPE_CLEAR:
1789 attribute = "clearTextPassword";
1790 v.data = in->current.array[i].AuthInfo.clear.password;
1791 v.length = in->current.array[i].AuthInfo.clear.size;
1797 ret = ldb_msg_add_empty(msg, attribute,
1798 LDB_FLAG_MOD_REPLACE, NULL);
1799 if (ret != LDB_SUCCESS) {
1800 return NT_STATUS_NO_MEMORY;
1803 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1804 if (ret != LDB_SUCCESS) {
1805 return NT_STATUS_NO_MEMORY;
1809 /* create the trusted_domain user account */
1810 ret = ldb_modify(sam_ldb, msg);
1811 if (ret != LDB_SUCCESS) {
1812 DEBUG(0,("Failed to create user record %s: %s\n",
1813 ldb_dn_get_linearized(msg->dn),
1814 ldb_errstring(sam_ldb)));
1817 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1818 return NT_STATUS_DOMAIN_EXISTS;
1819 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1820 return NT_STATUS_ACCESS_DENIED;
1822 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1826 return NT_STATUS_OK;
1830 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1831 struct lsa_policy_state *p_state,
1832 TALLOC_CTX *mem_ctx,
1833 struct ldb_message *dom_msg,
1834 enum lsa_TrustDomInfoEnum level,
1835 union lsa_TrustedDomainInfo *info)
1837 uint32_t *posix_offset = NULL;
1838 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1839 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1840 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1841 uint32_t *enc_types = NULL;
1842 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1843 struct trustDomainPasswords auth_struct;
1844 struct trustAuthInOutBlob *current_passwords = NULL;
1846 struct ldb_message **msgs;
1847 struct ldb_message *msg;
1848 bool add_outgoing = false;
1849 bool add_incoming = false;
1850 bool del_outgoing = false;
1851 bool del_incoming = false;
1852 bool del_forest_info = false;
1853 bool in_transaction = false;
1858 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1859 posix_offset = &info->posix_offset.posix_offset;
1861 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1862 info_ex = &info->info_ex;
1864 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1865 auth_info = &info->auth_info;
1867 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1868 posix_offset = &info->full_info.posix_offset.posix_offset;
1869 info_ex = &info->full_info.info_ex;
1870 auth_info = &info->full_info.auth_info;
1872 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1873 auth_info_int = &info->auth_info_internal;
1875 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1876 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1877 info_ex = &info->full_info_internal.info_ex;
1878 auth_info_int = &info->full_info_internal.auth_info;
1880 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1881 enc_types = &info->enc_types.enc_types;
1884 return NT_STATUS_INVALID_PARAMETER;
1888 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1890 &trustAuthOutgoing);
1891 if (!NT_STATUS_IS_OK(nt_status)) {
1894 if (trustAuthIncoming.data) {
1895 /* This does the decode of some of this twice, but it is easier that way */
1896 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1897 auth_info->incoming_count,
1898 auth_info->incoming_current_auth_info,
1900 ¤t_passwords);
1901 if (!NT_STATUS_IS_OK(nt_status)) {
1907 /* decode auth_info_int if set */
1908 if (auth_info_int) {
1910 /* now decrypt blob */
1911 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1912 auth_info_int->auth_blob.size);
1914 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1915 &auth_blob, &auth_struct);
1916 if (!NT_STATUS_IS_OK(nt_status)) {
1922 /* verify data matches */
1923 if (info_ex->trust_attributes &
1924 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1925 /* TODO: check what behavior level we have */
1926 if (strcasecmp_m(p_state->domain_dns,
1927 p_state->forest_dns) != 0) {
1928 return NT_STATUS_INVALID_DOMAIN_STATE;
1932 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1933 if (ret == LDB_SUCCESS && am_rodc) {
1934 return NT_STATUS_NO_SUCH_DOMAIN;
1937 /* verify only one object matches the dns/netbios/sid
1938 * triplet and that this is the one we already have */
1939 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1941 info_ex->domain_name.string,
1942 info_ex->netbios_name.string,
1943 info_ex->sid, &msgs);
1944 if (!NT_STATUS_IS_OK(nt_status)) {
1947 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1948 return NT_STATUS_OBJECT_NAME_COLLISION;
1953 /* TODO: should we fetch previous values from the existing entry
1954 * and append them ? */
1955 if (auth_info_int && auth_struct.incoming.count) {
1956 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1957 &auth_struct.incoming,
1958 &trustAuthIncoming);
1959 if (!NT_STATUS_IS_OK(nt_status)) {
1963 current_passwords = &auth_struct.incoming;
1966 trustAuthIncoming = data_blob(NULL, 0);
1969 if (auth_info_int && auth_struct.outgoing.count) {
1970 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1971 &auth_struct.outgoing,
1972 &trustAuthOutgoing);
1973 if (!NT_STATUS_IS_OK(nt_status)) {
1977 trustAuthOutgoing = data_blob(NULL, 0);
1980 msg = ldb_msg_new(mem_ctx);
1982 return NT_STATUS_NO_MEMORY;
1984 msg->dn = dom_msg->dn;
1987 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1990 *posix_offset, NULL);
1991 if (!NT_STATUS_IS_OK(nt_status)) {
1998 uint32_t changed_attrs;
2002 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2005 info_ex->trust_direction,
2007 if (!NT_STATUS_IS_OK(nt_status)) {
2011 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2012 if (auth_info != NULL && trustAuthIncoming.length > 0) {
2013 add_incoming = true;
2016 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2017 if (auth_info != NULL && trustAuthOutgoing.length > 0) {
2018 add_outgoing = true;
2022 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
2023 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
2024 del_incoming = true;
2026 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
2027 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2028 del_outgoing = true;
2031 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
2032 if (origtype == -1 || origtype != info_ex->trust_type) {
2033 DEBUG(1, ("Attempted to change trust type! "
2034 "Operation not handled\n"));
2035 return NT_STATUS_INVALID_PARAMETER;
2038 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2041 info_ex->trust_attributes,
2043 if (!NT_STATUS_IS_OK(nt_status)) {
2046 /* TODO: check forestFunctionality from ldb opaque */
2047 /* TODO: check what is set makes sense */
2049 changed_attrs = origattrs ^ info_ex->trust_attributes;
2050 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2052 * For now we only allow
2053 * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
2055 * TODO: we may need to support more attribute changes
2057 DEBUG(1, ("Attempted to change trust attributes "
2058 "(0x%08x != 0x%08x)! "
2059 "Operation not handled yet...\n",
2060 (unsigned)origattrs,
2061 (unsigned)info_ex->trust_attributes));
2062 return NT_STATUS_INVALID_PARAMETER;
2065 if (!(info_ex->trust_attributes &
2066 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
2068 struct ldb_message_element *orig_forest_el = NULL;
2070 orig_forest_el = ldb_msg_find_element(dom_msg,
2071 "msDS-TrustForestTrustInfo");
2072 if (orig_forest_el != NULL) {
2073 del_forest_info = true;
2079 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2081 "msDS-SupportedEncryptionTypes",
2083 if (!NT_STATUS_IS_OK(nt_status)) {
2088 if (add_incoming || del_incoming) {
2089 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
2090 LDB_FLAG_MOD_REPLACE, NULL);
2091 if (ret != LDB_SUCCESS) {
2092 return NT_STATUS_NO_MEMORY;
2095 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
2096 &trustAuthIncoming, NULL);
2097 if (ret != LDB_SUCCESS) {
2098 return NT_STATUS_NO_MEMORY;
2102 if (add_outgoing || del_outgoing) {
2103 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2104 LDB_FLAG_MOD_REPLACE, NULL);
2105 if (ret != LDB_SUCCESS) {
2106 return NT_STATUS_NO_MEMORY;
2109 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
2110 &trustAuthOutgoing, NULL);
2111 if (ret != LDB_SUCCESS) {
2112 return NT_STATUS_NO_MEMORY;
2116 if (del_forest_info) {
2117 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
2118 LDB_FLAG_MOD_REPLACE, NULL);
2119 if (ret != LDB_SUCCESS) {
2120 return NT_STATUS_NO_MEMORY;
2124 /* start transaction */
2125 ret = ldb_transaction_start(p_state->sam_ldb);
2126 if (ret != LDB_SUCCESS) {
2127 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2129 in_transaction = true;
2131 if (msg->num_elements) {
2132 ret = ldb_modify(p_state->sam_ldb, msg);
2133 if (ret != LDB_SUCCESS) {
2134 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
2135 ldb_dn_get_linearized(msg->dn),
2136 ldb_errstring(p_state->sam_ldb)));
2137 nt_status = dsdb_ldb_err_to_ntstatus(ret);
2142 if (add_incoming || del_incoming) {
2143 const char *netbios_name;
2145 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
2147 if (!netbios_name) {
2148 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
2152 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
2153 nt_status = update_trust_user(mem_ctx,
2159 if (!NT_STATUS_IS_OK(nt_status)) {
2164 /* ok, all fine, commit transaction and return */
2165 ret = ldb_transaction_commit(p_state->sam_ldb);
2166 if (ret != LDB_SUCCESS) {
2167 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2169 in_transaction = false;
2171 nt_status = NT_STATUS_OK;
2174 if (in_transaction) {
2175 ldb_transaction_cancel(p_state->sam_ldb);
2181 lsa_SetInfomrationTrustedDomain
2183 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
2184 struct dcesrv_call_state *dce_call,
2185 TALLOC_CTX *mem_ctx,
2186 struct lsa_SetInformationTrustedDomain *r)
2188 struct dcesrv_handle *h;
2189 struct lsa_trusted_domain_state *td_state;
2190 struct ldb_message **msgs;
2193 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
2194 LSA_HANDLE_TRUSTED_DOMAIN);
2196 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2198 /* get the trusted domain object */
2199 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
2200 td_state->trusted_domain_dn,
2201 NULL, NULL, NULL, &msgs);
2202 if (!NT_STATUS_IS_OK(nt_status)) {
2203 if (NT_STATUS_EQUAL(nt_status,
2204 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2207 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2210 return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
2211 msgs[0], r->in.level, r->in.info);
2216 lsa_DeleteTrustedDomain
2218 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2219 struct lsa_DeleteTrustedDomain *r)
2222 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2223 struct lsa_DeleteObject del;
2224 struct dcesrv_handle *h;
2226 opn.in.handle = r->in.handle;
2227 opn.in.sid = r->in.dom_sid;
2228 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2229 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2230 if (!opn.out.trustdom_handle) {
2231 return NT_STATUS_NO_MEMORY;
2233 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2234 if (!NT_STATUS_IS_OK(status)) {
2238 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2239 talloc_steal(mem_ctx, h);
2241 del.in.handle = opn.out.trustdom_handle;
2242 del.out.handle = opn.out.trustdom_handle;
2243 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2244 if (!NT_STATUS_IS_OK(status)) {
2247 return NT_STATUS_OK;
2250 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2251 struct ldb_message *msg,
2252 struct lsa_TrustDomainInfoInfoEx *info_ex)
2254 info_ex->domain_name.string
2255 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2256 info_ex->netbios_name.string
2257 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2259 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2260 info_ex->trust_direction
2261 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2263 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2264 info_ex->trust_attributes
2265 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2266 return NT_STATUS_OK;
2270 lsa_QueryTrustedDomainInfo
2272 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2273 struct lsa_QueryTrustedDomainInfo *r)
2275 union lsa_TrustedDomainInfo *info = NULL;
2276 struct dcesrv_handle *h;
2277 struct lsa_trusted_domain_state *trusted_domain_state;
2278 struct ldb_message *msg;
2280 struct ldb_message **res;
2281 const char *attrs[] = {
2284 "securityIdentifier",
2288 "msDs-supportedEncryptionTypes",
2292 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2294 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2296 /* pull all the user attributes */
2297 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2298 trusted_domain_state->trusted_domain_dn, &res, attrs);
2300 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2304 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2306 return NT_STATUS_NO_MEMORY;
2308 *r->out.info = info;
2310 switch (r->in.level) {
2311 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2312 info->name.netbios_name.string
2313 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2315 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2316 info->posix_offset.posix_offset
2317 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2319 #if 0 /* Win2k3 doesn't implement this */
2320 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2321 r->out.info->info_basic.netbios_name.string
2322 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2323 r->out.info->info_basic.sid
2324 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2327 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2328 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2330 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2331 ZERO_STRUCT(info->full_info);
2332 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2333 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2334 ZERO_STRUCT(info->full_info2_internal);
2335 info->full_info2_internal.posix_offset.posix_offset
2336 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2337 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2339 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2340 info->enc_types.enc_types
2341 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2344 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2345 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2346 /* oops, we don't want to return the info after all */
2348 *r->out.info = NULL;
2349 return NT_STATUS_INVALID_PARAMETER;
2351 /* oops, we don't want to return the info after all */
2353 *r->out.info = NULL;
2354 return NT_STATUS_INVALID_INFO_CLASS;
2357 return NT_STATUS_OK;
2362 lsa_QueryTrustedDomainInfoBySid
2364 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2365 struct lsa_QueryTrustedDomainInfoBySid *r)
2368 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2369 struct lsa_QueryTrustedDomainInfo query;
2370 struct dcesrv_handle *h;
2372 opn.in.handle = r->in.handle;
2373 opn.in.sid = r->in.dom_sid;
2374 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2375 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2376 if (!opn.out.trustdom_handle) {
2377 return NT_STATUS_NO_MEMORY;
2379 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2380 if (!NT_STATUS_IS_OK(status)) {
2384 /* Ensure this handle goes away at the end of this call */
2385 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2386 talloc_steal(mem_ctx, h);
2388 query.in.trustdom_handle = opn.out.trustdom_handle;
2389 query.in.level = r->in.level;
2390 query.out.info = r->out.info;
2391 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2392 if (!NT_STATUS_IS_OK(status)) {
2396 return NT_STATUS_OK;
2400 lsa_SetTrustedDomainInfoByName
2402 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2403 TALLOC_CTX *mem_ctx,
2404 struct lsa_SetTrustedDomainInfoByName *r)
2406 struct dcesrv_handle *policy_handle;
2407 struct lsa_policy_state *policy_state;
2408 struct ldb_message **msgs;
2411 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2412 policy_state = policy_handle->data;
2414 /* get the trusted domain object */
2415 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2416 policy_state->domain_dn,
2417 r->in.trusted_domain->string,
2418 r->in.trusted_domain->string,
2420 if (!NT_STATUS_IS_OK(nt_status)) {
2421 if (NT_STATUS_EQUAL(nt_status,
2422 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2425 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2428 return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2429 msgs[0], r->in.level, r->in.info);
2433 lsa_QueryTrustedDomainInfoByName
2435 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2436 TALLOC_CTX *mem_ctx,
2437 struct lsa_QueryTrustedDomainInfoByName *r)
2440 struct lsa_OpenTrustedDomainByName opn = {{0},{0}};
2441 struct lsa_QueryTrustedDomainInfo query;
2442 struct dcesrv_handle *h;
2444 opn.in.handle = r->in.handle;
2445 opn.in.name = *r->in.trusted_domain;
2446 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2447 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2448 if (!opn.out.trustdom_handle) {
2449 return NT_STATUS_NO_MEMORY;
2451 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2452 if (!NT_STATUS_IS_OK(status)) {
2456 /* Ensure this handle goes away at the end of this call */
2457 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2458 talloc_steal(mem_ctx, h);
2460 query.in.trustdom_handle = opn.out.trustdom_handle;
2461 query.in.level = r->in.level;
2462 query.out.info = r->out.info;
2463 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2464 if (!NT_STATUS_IS_OK(status)) {
2468 return NT_STATUS_OK;
2472 lsa_CloseTrustedDomainEx
2474 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2475 TALLOC_CTX *mem_ctx,
2476 struct lsa_CloseTrustedDomainEx *r)
2478 /* The result of a bad hair day from an IDL programmer? Not
2479 * implmented in Win2k3. You should always just lsa_Close
2481 return NT_STATUS_NOT_IMPLEMENTED;
2486 comparison function for sorting lsa_DomainInformation array
2488 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2490 return strcasecmp_m(e1->name.string, e2->name.string);
2496 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2497 struct lsa_EnumTrustDom *r)
2499 struct dcesrv_handle *policy_handle;
2500 struct lsa_DomainInfo *entries;
2501 struct lsa_policy_state *policy_state;
2502 struct ldb_message **domains;
2503 const char *attrs[] = {
2505 "securityIdentifier",
2512 *r->out.resume_handle = 0;
2514 r->out.domains->domains = NULL;
2515 r->out.domains->count = 0;
2517 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2519 policy_state = policy_handle->data;
2521 /* search for all users in this domain. This could possibly be cached and
2522 resumed based on resume_key */
2523 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2524 "objectclass=trustedDomain");
2526 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2529 /* convert to lsa_TrustInformation format */
2530 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2532 return NT_STATUS_NO_MEMORY;
2534 for (i=0;i<count;i++) {
2535 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2536 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2539 /* sort the results by name */
2540 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2542 if (*r->in.resume_handle >= count) {
2543 *r->out.resume_handle = -1;
2545 return NT_STATUS_NO_MORE_ENTRIES;
2548 /* return the rest, limit by max_size. Note that we
2549 use the w2k3 element size value of 60 */
2550 r->out.domains->count = count - *r->in.resume_handle;
2551 r->out.domains->count = MIN(r->out.domains->count,
2552 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2554 r->out.domains->domains = entries + *r->in.resume_handle;
2555 r->out.domains->count = r->out.domains->count;
2557 if (r->out.domains->count < count - *r->in.resume_handle) {
2558 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2559 return STATUS_MORE_ENTRIES;
2562 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2563 * always be larger than the previous input resume handle, in
2564 * particular when hitting the last query it is vital to set the
2565 * resume handle correctly to avoid infinite client loops, as
2566 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2567 * status is NT_STATUS_OK - gd */
2569 *r->out.resume_handle = (uint32_t)-1;
2571 return NT_STATUS_OK;
2575 comparison function for sorting lsa_DomainInformation array
2577 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2579 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2583 lsa_EnumTrustedDomainsEx
2585 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2586 struct lsa_EnumTrustedDomainsEx *r)
2588 struct dcesrv_handle *policy_handle;
2589 struct lsa_TrustDomainInfoInfoEx *entries;
2590 struct lsa_policy_state *policy_state;
2591 struct ldb_message **domains;
2592 const char *attrs[] = {
2595 "securityIdentifier",
2605 *r->out.resume_handle = 0;
2607 r->out.domains->domains = NULL;
2608 r->out.domains->count = 0;
2610 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2612 policy_state = policy_handle->data;
2614 /* search for all users in this domain. This could possibly be cached and
2615 resumed based on resume_key */
2616 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2617 "objectclass=trustedDomain");
2619 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2622 /* convert to lsa_DomainInformation format */
2623 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2625 return NT_STATUS_NO_MEMORY;
2627 for (i=0;i<count;i++) {
2628 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2629 if (!NT_STATUS_IS_OK(nt_status)) {
2634 /* sort the results by name */
2635 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2637 if (*r->in.resume_handle >= count) {
2638 *r->out.resume_handle = -1;
2640 return NT_STATUS_NO_MORE_ENTRIES;
2643 /* return the rest, limit by max_size. Note that we
2644 use the w2k3 element size value of 60 */
2645 r->out.domains->count = count - *r->in.resume_handle;
2646 r->out.domains->count = MIN(r->out.domains->count,
2647 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2649 r->out.domains->domains = entries + *r->in.resume_handle;
2650 r->out.domains->count = r->out.domains->count;
2652 if (r->out.domains->count < count - *r->in.resume_handle) {
2653 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2654 return STATUS_MORE_ENTRIES;
2657 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2659 return NT_STATUS_OK;
2666 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2667 struct lsa_OpenAccount *r)
2669 struct dcesrv_handle *h, *ah;
2670 struct lsa_policy_state *state;
2671 struct lsa_account_state *astate;
2673 ZERO_STRUCTP(r->out.acct_handle);
2675 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2679 astate = talloc(dce_call->conn, struct lsa_account_state);
2680 if (astate == NULL) {
2681 return NT_STATUS_NO_MEMORY;
2684 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2685 if (astate->account_sid == NULL) {
2686 talloc_free(astate);
2687 return NT_STATUS_NO_MEMORY;
2690 astate->policy = talloc_reference(astate, state);
2691 astate->access_mask = r->in.access_mask;
2694 * For now we grant all requested access.
2696 * We will fail at the ldb layer later.
2698 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2699 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2700 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2702 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2704 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2705 __func__, dom_sid_string(mem_ctx, astate->account_sid),
2706 (unsigned)r->in.access_mask,
2707 (unsigned)astate->access_mask));
2709 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2711 talloc_free(astate);
2712 return NT_STATUS_NO_MEMORY;
2715 ah->data = talloc_steal(ah, astate);
2717 *r->out.acct_handle = ah->wire_handle;
2719 return NT_STATUS_OK;
2724 lsa_EnumPrivsAccount
2726 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2727 TALLOC_CTX *mem_ctx,
2728 struct lsa_EnumPrivsAccount *r)
2730 struct dcesrv_handle *h;
2731 struct lsa_account_state *astate;
2734 struct ldb_message **res;
2735 const char * const attrs[] = { "privilege", NULL};
2736 struct ldb_message_element *el;
2738 struct lsa_PrivilegeSet *privs;
2740 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2744 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2745 if (privs == NULL) {
2746 return NT_STATUS_NO_MEMORY;
2752 *r->out.privs = privs;
2754 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2755 if (sidstr == NULL) {
2756 return NT_STATUS_NO_MEMORY;
2759 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2760 "objectSid=%s", sidstr);
2762 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2765 return NT_STATUS_OK;
2768 el = ldb_msg_find_element(res[0], "privilege");
2769 if (el == NULL || el->num_values == 0) {
2770 return NT_STATUS_OK;
2773 privs->set = talloc_array(privs,
2774 struct lsa_LUIDAttribute, el->num_values);
2775 if (privs->set == NULL) {
2776 return NT_STATUS_NO_MEMORY;
2780 for (i=0;i<el->num_values;i++) {
2781 int id = sec_privilege_id((const char *)el->values[i].data);
2782 if (id == SEC_PRIV_INVALID) {
2783 /* Perhaps an account right, not a privilege */
2786 privs->set[j].attribute = 0;
2787 privs->set[j].luid.low = id;
2788 privs->set[j].luid.high = 0;
2794 return NT_STATUS_OK;
2798 lsa_EnumAccountRights
2800 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2801 TALLOC_CTX *mem_ctx,
2802 struct lsa_EnumAccountRights *r)
2804 struct dcesrv_handle *h;
2805 struct lsa_policy_state *state;
2808 struct ldb_message **res;
2809 const char * const attrs[] = { "privilege", NULL};
2811 struct ldb_message_element *el;
2813 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2817 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2818 if (sidstr == NULL) {
2819 return NT_STATUS_NO_MEMORY;
2822 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2823 "(&(objectSid=%s)(privilege=*))", sidstr);
2825 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2828 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2829 dom_sid_string(mem_ctx, r->in.sid),
2830 ldb_errstring(state->pdb)));
2831 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2834 el = ldb_msg_find_element(res[0], "privilege");
2835 if (el == NULL || el->num_values == 0) {
2836 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2839 r->out.rights->count = el->num_values;
2840 r->out.rights->names = talloc_array(r->out.rights,
2841 struct lsa_StringLarge, r->out.rights->count);
2842 if (r->out.rights->names == NULL) {
2843 return NT_STATUS_NO_MEMORY;
2846 for (i=0;i<el->num_values;i++) {
2847 r->out.rights->names[i].string = (const char *)el->values[i].data;
2850 return NT_STATUS_OK;
2856 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2858 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2859 TALLOC_CTX *mem_ctx,
2860 struct lsa_policy_state *state,
2862 struct dom_sid *sid,
2863 const struct lsa_RightSet *rights)
2865 const char *sidstr, *sidndrstr;
2866 struct ldb_message *msg;
2867 struct ldb_message_element *el;
2870 struct lsa_EnumAccountRights r2;
2873 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2874 SECURITY_ADMINISTRATOR) {
2875 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2876 return NT_STATUS_ACCESS_DENIED;
2879 msg = ldb_msg_new(mem_ctx);
2881 return NT_STATUS_NO_MEMORY;
2884 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2885 if (sidndrstr == NULL) {
2887 return NT_STATUS_NO_MEMORY;
2890 sidstr = dom_sid_string(msg, sid);
2891 if (sidstr == NULL) {
2893 return NT_STATUS_NO_MEMORY;
2896 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2897 if (dnstr == NULL) {
2899 return NT_STATUS_NO_MEMORY;
2902 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2903 if (msg->dn == NULL) {
2905 return NT_STATUS_NO_MEMORY;
2908 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2911 r2.in.handle = &state->handle->wire_handle;
2913 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2915 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2916 if (!NT_STATUS_IS_OK(status)) {
2917 ZERO_STRUCTP(r2.out.rights);
2921 for (i=0;i<rights->count;i++) {
2922 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2923 if (sec_right_bit(rights->names[i].string) == 0) {
2925 return NT_STATUS_NO_SUCH_PRIVILEGE;
2929 return NT_STATUS_NO_SUCH_PRIVILEGE;
2932 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2934 for (j=0;j<r2.out.rights->count;j++) {
2935 if (strcasecmp_m(r2.out.rights->names[j].string,
2936 rights->names[i].string) == 0) {
2940 if (j != r2.out.rights->count) continue;
2943 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2944 if (ret != LDB_SUCCESS) {
2946 return NT_STATUS_NO_MEMORY;
2950 el = ldb_msg_find_element(msg, "privilege");
2953 return NT_STATUS_OK;
2956 el->flags = ldb_flag;
2958 ret = ldb_modify(state->pdb, msg);
2959 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2960 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2962 return NT_STATUS_NO_MEMORY;
2964 ldb_msg_add_string(msg, "comment", "added via LSA");
2965 ret = ldb_add(state->pdb, msg);
2967 if (ret != LDB_SUCCESS) {
2968 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2970 return NT_STATUS_OK;
2972 DEBUG(3, ("Could not %s attributes from %s: %s",
2973 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2974 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2976 return NT_STATUS_UNEXPECTED_IO_ERROR;
2980 return NT_STATUS_OK;
2984 lsa_AddPrivilegesToAccount
2986 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2987 struct lsa_AddPrivilegesToAccount *r)
2989 struct lsa_RightSet rights;
2990 struct dcesrv_handle *h;
2991 struct lsa_account_state *astate;
2994 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2998 rights.count = r->in.privs->count;
2999 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
3000 if (rights.names == NULL) {
3001 return NT_STATUS_NO_MEMORY;
3003 for (i=0;i<rights.count;i++) {
3004 int id = r->in.privs->set[i].luid.low;
3005 if (r->in.privs->set[i].luid.high) {
3006 return NT_STATUS_NO_SUCH_PRIVILEGE;
3008 rights.names[i].string = sec_privilege_name(id);
3009 if (rights.names[i].string == NULL) {
3010 return NT_STATUS_NO_SUCH_PRIVILEGE;
3014 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3015 LDB_FLAG_MOD_ADD, astate->account_sid,
3021 lsa_RemovePrivilegesFromAccount
3023 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3024 struct lsa_RemovePrivilegesFromAccount *r)
3026 struct lsa_RightSet *rights;
3027 struct dcesrv_handle *h;
3028 struct lsa_account_state *astate;
3031 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3035 rights = talloc(mem_ctx, struct lsa_RightSet);
3037 if (r->in.remove_all == 1 &&
3038 r->in.privs == NULL) {
3039 struct lsa_EnumAccountRights r2;
3042 r2.in.handle = &astate->policy->handle->wire_handle;
3043 r2.in.sid = astate->account_sid;
3044 r2.out.rights = rights;
3046 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
3047 if (!NT_STATUS_IS_OK(status)) {
3051 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3052 LDB_FLAG_MOD_DELETE, astate->account_sid,
3056 if (r->in.remove_all != 0) {
3057 return NT_STATUS_INVALID_PARAMETER;
3060 rights->count = r->in.privs->count;
3061 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
3062 if (rights->names == NULL) {
3063 return NT_STATUS_NO_MEMORY;
3065 for (i=0;i<rights->count;i++) {
3066 int id = r->in.privs->set[i].luid.low;
3067 if (r->in.privs->set[i].luid.high) {
3068 return NT_STATUS_NO_SUCH_PRIVILEGE;
3070 rights->names[i].string = sec_privilege_name(id);
3071 if (rights->names[i].string == NULL) {
3072 return NT_STATUS_NO_SUCH_PRIVILEGE;
3076 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3077 LDB_FLAG_MOD_DELETE, astate->account_sid,
3083 lsa_GetQuotasForAccount
3085 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3086 struct lsa_GetQuotasForAccount *r)
3088 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3093 lsa_SetQuotasForAccount
3095 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3096 struct lsa_SetQuotasForAccount *r)
3098 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3103 lsa_GetSystemAccessAccount
3105 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3106 struct lsa_GetSystemAccessAccount *r)
3108 struct dcesrv_handle *h;
3109 struct lsa_account_state *astate;
3112 struct ldb_message **res;
3113 const char * const attrs[] = { "privilege", NULL};
3114 struct ldb_message_element *el;
3117 *(r->out.access_mask) = 0x00000000;
3119 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3123 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
3124 if (sidstr == NULL) {
3125 return NT_STATUS_NO_MEMORY;
3128 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
3129 "objectSid=%s", sidstr);
3131 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3134 return NT_STATUS_OK;
3137 el = ldb_msg_find_element(res[0], "privilege");
3138 if (el == NULL || el->num_values == 0) {
3139 return NT_STATUS_OK;
3142 for (i=0;i<el->num_values;i++) {
3143 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
3144 if (right_bit == 0) {
3145 /* Perhaps an privilege, not a right */
3148 *(r->out.access_mask) |= right_bit;
3151 return NT_STATUS_OK;
3156 lsa_SetSystemAccessAccount
3158 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3159 struct lsa_SetSystemAccessAccount *r)
3161 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3168 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3169 struct lsa_CreateSecret *r)
3171 struct dcesrv_handle *policy_handle;
3172 struct lsa_policy_state *policy_state;
3173 struct lsa_secret_state *secret_state;
3174 struct dcesrv_handle *handle;
3175 struct ldb_message **msgs, *msg;
3176 const char *attrs[] = {
3184 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3185 ZERO_STRUCTP(r->out.sec_handle);
3187 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3189 case SECURITY_SYSTEM:
3190 case SECURITY_ADMINISTRATOR:
3193 /* Users and annonymous are not allowed create secrets */
3194 return NT_STATUS_ACCESS_DENIED;
3197 policy_state = policy_handle->data;
3199 if (!r->in.name.string) {
3200 return NT_STATUS_INVALID_PARAMETER;
3203 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3204 NT_STATUS_HAVE_NO_MEMORY(secret_state);
3205 secret_state->policy = policy_state;
3207 msg = ldb_msg_new(mem_ctx);
3209 return NT_STATUS_NO_MEMORY;
3212 if (strncmp("G$", r->in.name.string, 2) == 0) {
3215 secret_state->global = true;
3217 name = &r->in.name.string[2];
3218 if (strlen(name) == 0) {
3219 return NT_STATUS_INVALID_PARAMETER;
3222 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3223 ldb_binary_encode_string(mem_ctx, name));
3224 NT_STATUS_HAVE_NO_MEMORY(name2);
3226 /* We need to connect to the database as system, as this is one
3227 * of the rare RPC calls that must read the secrets (and this
3228 * is denied otherwise) */
3229 secret_state->sam_ldb = talloc_reference(secret_state,
3230 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));
3231 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3233 /* search for the secret record */
3234 ret = gendb_search(secret_state->sam_ldb,
3235 mem_ctx, policy_state->system_dn, &msgs, attrs,
3236 "(&(cn=%s)(objectclass=secret))",
3239 return NT_STATUS_OBJECT_NAME_COLLISION;
3243 DEBUG(0,("Failure searching for CN=%s: %s\n",
3244 name2, ldb_errstring(secret_state->sam_ldb)));
3245 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3248 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3249 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3250 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3251 return NT_STATUS_NO_MEMORY;
3254 ret = ldb_msg_add_string(msg, "cn", name2);
3255 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3257 secret_state->global = false;
3259 name = r->in.name.string;
3260 if (strlen(name) == 0) {
3261 return NT_STATUS_INVALID_PARAMETER;
3264 secret_state->sam_ldb = talloc_reference(secret_state,
3265 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3266 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3268 /* search for the secret record */
3269 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3270 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3272 "(&(cn=%s)(objectclass=secret))",
3273 ldb_binary_encode_string(mem_ctx, name));
3275 return NT_STATUS_OBJECT_NAME_COLLISION;
3279 DEBUG(0,("Failure searching for CN=%s: %s\n",
3280 name, ldb_errstring(secret_state->sam_ldb)));
3281 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3284 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3285 "cn=%s,cn=LSA Secrets", name);
3286 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3287 ret = ldb_msg_add_string(msg, "cn", name);
3288 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3291 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3292 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3294 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3295 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3297 /* create the secret */
3298 ret = ldb_add(secret_state->sam_ldb, msg);
3299 if (ret != LDB_SUCCESS) {
3300 DEBUG(0,("Failed to create secret record %s: %s\n",
3301 ldb_dn_get_linearized(msg->dn),
3302 ldb_errstring(secret_state->sam_ldb)));
3303 return NT_STATUS_ACCESS_DENIED;
3306 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3307 NT_STATUS_HAVE_NO_MEMORY(handle);
3309 handle->data = talloc_steal(handle, secret_state);
3311 secret_state->access_mask = r->in.access_mask;
3312 secret_state->policy = talloc_reference(secret_state, policy_state);
3313 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3315 *r->out.sec_handle = handle->wire_handle;
3317 return NT_STATUS_OK;
3324 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3325 struct lsa_OpenSecret *r)
3327 struct dcesrv_handle *policy_handle;
3329 struct lsa_policy_state *policy_state;
3330 struct lsa_secret_state *secret_state;
3331 struct dcesrv_handle *handle;
3332 struct ldb_message **msgs;
3333 const char *attrs[] = {
3341 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3342 ZERO_STRUCTP(r->out.sec_handle);
3343 policy_state = policy_handle->data;
3345 if (!r->in.name.string) {
3346 return NT_STATUS_INVALID_PARAMETER;
3349 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3351 case SECURITY_SYSTEM:
3352 case SECURITY_ADMINISTRATOR:
3355 /* Users and annonymous are not allowed to access secrets */
3356 return NT_STATUS_ACCESS_DENIED;
3359 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3360 if (!secret_state) {
3361 return NT_STATUS_NO_MEMORY;
3363 secret_state->policy = policy_state;
3365 if (strncmp("G$", r->in.name.string, 2) == 0) {
3366 name = &r->in.name.string[2];
3367 /* 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) */
3368 secret_state->sam_ldb = talloc_reference(secret_state,
3369 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));
3370 secret_state->global = true;
3372 if (strlen(name) < 1) {
3373 return NT_STATUS_INVALID_PARAMETER;
3376 /* search for the secret record */
3377 ret = gendb_search(secret_state->sam_ldb,
3378 mem_ctx, policy_state->system_dn, &msgs, attrs,
3379 "(&(cn=%s Secret)(objectclass=secret))",
3380 ldb_binary_encode_string(mem_ctx, name));
3382 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3386 DEBUG(0,("Found %d records matching DN %s\n", ret,
3387 ldb_dn_get_linearized(policy_state->system_dn)));
3388 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3391 secret_state->global = false;
3392 secret_state->sam_ldb = talloc_reference(secret_state,
3393 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3395 name = r->in.name.string;
3396 if (strlen(name) < 1) {
3397 return NT_STATUS_INVALID_PARAMETER;
3400 /* search for the secret record */
3401 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3402 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3404 "(&(cn=%s)(objectclass=secret))",
3405 ldb_binary_encode_string(mem_ctx, name));
3407 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3411 DEBUG(0,("Found %d records matching CN=%s\n",
3412 ret, ldb_binary_encode_string(mem_ctx, name)));
3413 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3417 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3419 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3421 return NT_STATUS_NO_MEMORY;
3424 handle->data = talloc_steal(handle, secret_state);
3426 secret_state->access_mask = r->in.access_mask;
3427 secret_state->policy = talloc_reference(secret_state, policy_state);
3429 *r->out.sec_handle = handle->wire_handle;
3431 return NT_STATUS_OK;
3438 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3439 struct lsa_SetSecret *r)
3442 struct dcesrv_handle *h;
3443 struct lsa_secret_state *secret_state;
3444 struct ldb_message *msg;
3445 DATA_BLOB session_key;
3446 DATA_BLOB crypt_secret, secret;
3449 NTSTATUS status = NT_STATUS_OK;
3451 struct timeval now = timeval_current();
3452 NTTIME nt_now = timeval_to_nttime(&now);
3454 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3456 secret_state = h->data;
3458 msg = ldb_msg_new(mem_ctx);
3460 return NT_STATUS_NO_MEMORY;
3463 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3465 return NT_STATUS_NO_MEMORY;
3467 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3468 if (!NT_STATUS_IS_OK(status)) {
3472 if (r->in.old_val) {
3474 crypt_secret.data = r->in.old_val->data;
3475 crypt_secret.length = r->in.old_val->size;
3477 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3478 if (!NT_STATUS_IS_OK(status)) {
3482 val.data = secret.data;
3483 val.length = secret.length;
3486 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3487 return NT_STATUS_NO_MEMORY;
3490 /* set old value mtime */
3491 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3492 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3493 return NT_STATUS_NO_MEMORY;
3497 /* If the old value is not set, then migrate the
3498 * current value to the old value */
3499 const struct ldb_val *old_val;
3500 NTTIME last_set_time;
3501 struct ldb_message **res;
3502 const char *attrs[] = {
3508 /* search for the secret record */
3509 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3510 secret_state->secret_dn, &res, attrs);
3512 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3516 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3517 ldb_dn_get_linearized(secret_state->secret_dn)));
3518 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3521 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3522 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3526 if (ldb_msg_add_value(msg, "priorValue",
3527 old_val, NULL) != LDB_SUCCESS) {
3528 return NT_STATUS_NO_MEMORY;
3531 if (samdb_msg_add_delete(secret_state->sam_ldb,
3532 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3533 return NT_STATUS_NO_MEMORY;
3537 /* set old value mtime */
3538 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3539 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3540 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3541 return NT_STATUS_NO_MEMORY;
3544 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3545 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3546 return NT_STATUS_NO_MEMORY;
3551 if (r->in.new_val) {
3553 crypt_secret.data = r->in.new_val->data;
3554 crypt_secret.length = r->in.new_val->size;
3556 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3557 if (!NT_STATUS_IS_OK(status)) {
3561 val.data = secret.data;
3562 val.length = secret.length;
3565 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3566 return NT_STATUS_NO_MEMORY;
3569 /* set new value mtime */
3570 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3571 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3572 return NT_STATUS_NO_MEMORY;
3575 /* NULL out the NEW value */
3576 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3577 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3578 return NT_STATUS_NO_MEMORY;
3580 if (samdb_msg_add_delete(secret_state->sam_ldb,
3581 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3582 return NT_STATUS_NO_MEMORY;
3586 /* modify the samdb record */
3587 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3588 if (ret != LDB_SUCCESS) {
3589 return dsdb_ldb_err_to_ntstatus(ret);
3592 return NT_STATUS_OK;
3599 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3600 struct lsa_QuerySecret *r)
3602 struct dcesrv_handle *h;
3603 struct lsa_secret_state *secret_state;
3604 struct ldb_message *msg;
3605 DATA_BLOB session_key;
3606 DATA_BLOB crypt_secret, secret;
3608 struct ldb_message **res;
3609 const char *attrs[] = {
3619 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3621 /* Ensure user is permitted to read this... */
3622 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3624 case SECURITY_SYSTEM:
3625 case SECURITY_ADMINISTRATOR:
3628 /* Users and annonymous are not allowed to read secrets */
3629 return NT_STATUS_ACCESS_DENIED;
3632 secret_state = h->data;
3634 /* pull all the user attributes */
3635 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3636 secret_state->secret_dn, &res, attrs);
3638 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3642 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3643 if (!NT_STATUS_IS_OK(nt_status)) {
3647 if (r->in.old_val) {
3648 const struct ldb_val *prior_val;
3649 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3650 if (!r->out.old_val) {
3651 return NT_STATUS_NO_MEMORY;
3653 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3655 if (prior_val && prior_val->length) {
3656 secret.data = prior_val->data;
3657 secret.length = prior_val->length;
3660 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3661 if (!crypt_secret.length) {
3662 return NT_STATUS_NO_MEMORY;
3664 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3665 if (!r->out.old_val->buf) {
3666 return NT_STATUS_NO_MEMORY;
3668 r->out.old_val->buf->size = crypt_secret.length;
3669 r->out.old_val->buf->length = crypt_secret.length;
3670 r->out.old_val->buf->data = crypt_secret.data;
3674 if (r->in.old_mtime) {
3675 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3676 if (!r->out.old_mtime) {
3677 return NT_STATUS_NO_MEMORY;
3679 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3682 if (r->in.new_val) {
3683 const struct ldb_val *new_val;
3684 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3685 if (!r->out.new_val) {
3686 return NT_STATUS_NO_MEMORY;
3689 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3691 if (new_val && new_val->length) {
3692 secret.data = new_val->data;
3693 secret.length = new_val->length;
3696 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3697 if (!crypt_secret.length) {
3698 return NT_STATUS_NO_MEMORY;
3700 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3701 if (!r->out.new_val->buf) {
3702 return NT_STATUS_NO_MEMORY;
3704 r->out.new_val->buf->length = crypt_secret.length;
3705 r->out.new_val->buf->size = crypt_secret.length;
3706 r->out.new_val->buf->data = crypt_secret.data;
3710 if (r->in.new_mtime) {
3711 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3712 if (!r->out.new_mtime) {
3713 return NT_STATUS_NO_MEMORY;
3715 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3718 return NT_STATUS_OK;
3725 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3726 TALLOC_CTX *mem_ctx,
3727 struct lsa_LookupPrivValue *r)
3729 struct dcesrv_handle *h;
3732 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3734 id = sec_privilege_id(r->in.name->string);
3735 if (id == SEC_PRIV_INVALID) {
3736 return NT_STATUS_NO_SUCH_PRIVILEGE;
3739 r->out.luid->low = id;
3740 r->out.luid->high = 0;
3742 return NT_STATUS_OK;
3749 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3750 TALLOC_CTX *mem_ctx,
3751 struct lsa_LookupPrivName *r)
3753 struct dcesrv_handle *h;
3754 struct lsa_StringLarge *name;
3755 const char *privname;
3757 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3759 if (r->in.luid->high != 0) {
3760 return NT_STATUS_NO_SUCH_PRIVILEGE;
3763 privname = sec_privilege_name(r->in.luid->low);
3764 if (privname == NULL) {
3765 return NT_STATUS_NO_SUCH_PRIVILEGE;
3768 name = talloc(mem_ctx, struct lsa_StringLarge);
3770 return NT_STATUS_NO_MEMORY;
3773 name->string = privname;
3775 *r->out.name = name;
3777 return NT_STATUS_OK;
3782 lsa_LookupPrivDisplayName
3784 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3785 TALLOC_CTX *mem_ctx,
3786 struct lsa_LookupPrivDisplayName *r)
3788 struct dcesrv_handle *h;
3789 struct lsa_StringLarge *disp_name = NULL;
3790 enum sec_privilege id;
3792 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3794 id = sec_privilege_id(r->in.name->string);
3795 if (id == SEC_PRIV_INVALID) {
3796 return NT_STATUS_NO_SUCH_PRIVILEGE;
3799 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3800 if (disp_name == NULL) {
3801 return NT_STATUS_NO_MEMORY;
3804 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3805 if (disp_name->string == NULL) {
3806 return NT_STATUS_INTERNAL_ERROR;
3809 *r->out.disp_name = disp_name;
3810 *r->out.returned_language_id = 0;
3812 return NT_STATUS_OK;
3817 lsa_EnumAccountsWithUserRight
3819 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3820 TALLOC_CTX *mem_ctx,
3821 struct lsa_EnumAccountsWithUserRight *r)
3823 struct dcesrv_handle *h;
3824 struct lsa_policy_state *state;
3826 struct ldb_message **res;
3827 const char * const attrs[] = { "objectSid", NULL};
3828 const char *privname;
3830 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3834 if (r->in.name == NULL) {
3835 return NT_STATUS_NO_SUCH_PRIVILEGE;
3838 privname = r->in.name->string;
3839 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3840 return NT_STATUS_NO_SUCH_PRIVILEGE;
3843 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3844 "privilege=%s", privname);
3846 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3849 return NT_STATUS_NO_MORE_ENTRIES;
3852 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3853 if (r->out.sids->sids == NULL) {
3854 return NT_STATUS_NO_MEMORY;
3856 for (i=0;i<ret;i++) {
3857 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3858 res[i], "objectSid");
3859 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3861 r->out.sids->num_sids = ret;
3863 return NT_STATUS_OK;
3868 lsa_AddAccountRights
3870 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3871 TALLOC_CTX *mem_ctx,
3872 struct lsa_AddAccountRights *r)
3874 struct dcesrv_handle *h;
3875 struct lsa_policy_state *state;
3877 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3881 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3883 r->in.sid, r->in.rights);
3888 lsa_RemoveAccountRights
3890 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3891 TALLOC_CTX *mem_ctx,
3892 struct lsa_RemoveAccountRights *r)
3894 struct dcesrv_handle *h;
3895 struct lsa_policy_state *state;
3897 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3901 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3902 LDB_FLAG_MOD_DELETE,
3903 r->in.sid, r->in.rights);
3908 lsa_StorePrivateData
3910 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3911 struct lsa_StorePrivateData *r)
3913 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3918 lsa_RetrievePrivateData
3920 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3921 struct lsa_RetrievePrivateData *r)
3923 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3930 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3931 struct lsa_GetUserName *r)
3933 enum dcerpc_transport_t transport =
3934 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3935 NTSTATUS status = NT_STATUS_OK;
3936 const char *account_name;
3937 const char *authority_name;
3938 struct lsa_String *_account_name;
3939 struct lsa_String *_authority_name = NULL;
3941 if (transport != NCACN_NP && transport != NCALRPC) {
3942 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3945 /* this is what w2k3 does */
3946 r->out.account_name = r->in.account_name;
3947 r->out.authority_name = r->in.authority_name;
3949 if (r->in.account_name
3950 && *r->in.account_name
3951 /* && *(*r->in.account_name)->string */
3953 return NT_STATUS_INVALID_PARAMETER;
3956 if (r->in.authority_name
3957 && *r->in.authority_name
3958 /* && *(*r->in.authority_name)->string */
3960 return NT_STATUS_INVALID_PARAMETER;
3963 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3964 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3966 _account_name = talloc(mem_ctx, struct lsa_String);
3967 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3968 _account_name->string = account_name;
3970 if (r->in.authority_name) {
3971 _authority_name = talloc(mem_ctx, struct lsa_String);
3972 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3973 _authority_name->string = authority_name;
3976 *r->out.account_name = _account_name;
3977 if (r->out.authority_name) {
3978 *r->out.authority_name = _authority_name;
3987 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3988 TALLOC_CTX *mem_ctx,
3989 struct lsa_SetInfoPolicy2 *r)
3991 /* need to support these */
3992 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3995 static void kdc_get_policy(struct loadparm_context *lp_ctx,
3996 struct smb_krb5_context *smb_krb5_context,
3997 struct lsa_DomainInfoKerberos *k)
3999 time_t svc_tkt_lifetime;
4000 time_t usr_tkt_lifetime;
4001 time_t renewal_lifetime;
4003 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
4005 /* Our KDC always re-validates the client */
4006 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
4008 lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
4009 &usr_tkt_lifetime, &renewal_lifetime);
4011 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
4012 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
4013 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
4014 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
4015 However in the parent function we basically just did a full
4016 krb5_context init with the only purpose of getting a global
4017 config option (the max skew), it would probably make more sense
4018 to have a lp_ or ldb global option as the samba default */
4019 if (smb_krb5_context) {
4020 unix_to_nt_time(&k->clock_skew,
4021 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
4027 lsa_QueryDomainInformationPolicy
4029 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4030 TALLOC_CTX *mem_ctx,
4031 struct lsa_QueryDomainInformationPolicy *r)
4033 union lsa_DomainInformationPolicy *info;
4035 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
4037 return NT_STATUS_NO_MEMORY;
4040 switch (r->in.level) {
4041 case LSA_DOMAIN_INFO_POLICY_EFS:
4043 *r->out.info = NULL;
4044 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4045 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
4047 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
4048 struct smb_krb5_context *smb_krb5_context;
4049 int ret = smb_krb5_init_context(mem_ctx,
4050 dce_call->conn->dce_ctx->lp_ctx,
4054 *r->out.info = NULL;
4055 return NT_STATUS_INTERNAL_ERROR;
4057 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
4060 talloc_free(smb_krb5_context);
4061 *r->out.info = info;
4062 return NT_STATUS_OK;
4066 *r->out.info = NULL;
4067 return NT_STATUS_INVALID_INFO_CLASS;
4072 lsa_SetDomInfoPolicy
4074 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4075 TALLOC_CTX *mem_ctx,
4076 struct lsa_SetDomainInformationPolicy *r)
4078 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4084 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
4085 TALLOC_CTX *mem_ctx,
4086 struct lsa_TestCall *r)
4088 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4094 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4095 struct lsa_CREDRWRITE *r)
4097 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4104 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4105 struct lsa_CREDRREAD *r)
4107 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4114 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4115 struct lsa_CREDRENUMERATE *r)
4117 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4122 lsa_CREDRWRITEDOMAINCREDENTIALS
4124 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4125 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
4127 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4132 lsa_CREDRREADDOMAINCREDENTIALS
4134 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4135 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
4137 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4144 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4145 struct lsa_CREDRDELETE *r)
4147 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4152 lsa_CREDRGETTARGETINFO
4154 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4155 struct lsa_CREDRGETTARGETINFO *r)
4157 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4162 lsa_CREDRPROFILELOADED
4164 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4165 struct lsa_CREDRPROFILELOADED *r)
4167 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4172 lsa_CREDRGETSESSIONTYPES
4174 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4175 struct lsa_CREDRGETSESSIONTYPES *r)
4177 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4182 lsa_LSARREGISTERAUDITEVENT
4184 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4185 struct lsa_LSARREGISTERAUDITEVENT *r)
4187 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4192 lsa_LSARGENAUDITEVENT
4194 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4195 struct lsa_LSARGENAUDITEVENT *r)
4197 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4202 lsa_LSARUNREGISTERAUDITEVENT
4204 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4205 struct lsa_LSARUNREGISTERAUDITEVENT *r)
4207 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4212 lsa_lsaRQueryForestTrustInformation
4214 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4215 struct lsa_lsaRQueryForestTrustInformation *r)
4217 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4220 #define DNS_CMP_MATCH 0
4221 #define DNS_CMP_FIRST_IS_CHILD 1
4222 #define DNS_CMP_SECOND_IS_CHILD 2
4223 #define DNS_CMP_NO_MATCH 3
4225 /* this function assumes names are well formed DNS names.
4226 * it doesn't validate them */
4227 static int dns_cmp(const char *s1, size_t l1,
4228 const char *s2, size_t l2)
4230 const char *p1, *p2;
4235 if (strcasecmp_m(s1, s2) == 0) {
4236 return DNS_CMP_MATCH;
4238 return DNS_CMP_NO_MATCH;
4246 cret = DNS_CMP_FIRST_IS_CHILD;
4252 cret = DNS_CMP_SECOND_IS_CHILD;
4255 if (p1[t1 - t2 - 1] != '.') {
4256 return DNS_CMP_NO_MATCH;
4259 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
4263 return DNS_CMP_NO_MATCH;
4266 /* decode all TDOs forest trust info blobs */
4267 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
4268 struct ldb_message *msg,
4269 struct ForestTrustInfo *info)
4271 const struct ldb_val *ft_blob;
4272 enum ndr_err_code ndr_err;
4274 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
4275 if (!ft_blob || !ft_blob->data) {
4276 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4278 /* ldb_val is equivalent to DATA_BLOB */
4279 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
4280 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
4281 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4282 return NT_STATUS_INVALID_DOMAIN_STATE;
4285 return NT_STATUS_OK;
4288 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
4289 struct ForestTrustInfo *fti)
4291 struct ForestTrustDataDomainInfo *info;
4292 struct ForestTrustInfoRecord *rec;
4296 fti->records = talloc_array(fti,
4297 struct ForestTrustInfoRecordArmor, 2);
4298 if (!fti->records) {
4299 return NT_STATUS_NO_MEMORY;
4303 rec = &fti->records[0].record;
4307 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
4309 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
4310 if (!rec->data.name.string) {
4311 return NT_STATUS_NO_MEMORY;
4313 rec->data.name.size = strlen(rec->data.name.string);
4316 rec = &fti->records[1].record;
4320 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
4322 info = &rec->data.info;
4324 info->sid = *ps->domain_sid;
4325 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
4326 if (!info->dns_name.string) {
4327 return NT_STATUS_NO_MEMORY;
4329 info->dns_name.size = strlen(info->dns_name.string);
4330 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
4331 if (!info->netbios_name.string) {
4332 return NT_STATUS_NO_MEMORY;
4334 info->netbios_name.size = strlen(info->netbios_name.string);
4336 return NT_STATUS_OK;
4339 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
4340 struct lsa_ForestTrustInformation *lfti,
4341 struct ForestTrustInfo *fti)
4343 struct lsa_ForestTrustRecord *lrec;
4344 struct ForestTrustInfoRecord *rec;
4345 struct lsa_StringLarge *tln;
4346 struct lsa_ForestTrustDomainInfo *info;
4350 fti->count = lfti->count;
4351 fti->records = talloc_array(mem_ctx,
4352 struct ForestTrustInfoRecordArmor,
4354 if (!fti->records) {
4355 return NT_STATUS_NO_MEMORY;
4357 for (i = 0; i < fti->count; i++) {
4358 lrec = lfti->entries[i];
4359 rec = &fti->records[i].record;
4361 rec->flags = lrec->flags;
4362 rec->timestamp = lrec->time;
4363 rec->type = lrec->type;
4365 switch (lrec->type) {
4366 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4367 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4368 tln = &lrec->forest_trust_data.top_level_name;
4369 rec->data.name.string =
4370 talloc_strdup(mem_ctx, tln->string);
4371 if (!rec->data.name.string) {
4372 return NT_STATUS_NO_MEMORY;
4374 rec->data.name.size = strlen(rec->data.name.string);
4376 case LSA_FOREST_TRUST_DOMAIN_INFO:
4377 info = &lrec->forest_trust_data.domain_info;
4378 rec->data.info.sid = *info->domain_sid;
4379 rec->data.info.dns_name.string =
4380 talloc_strdup(mem_ctx,
4381 info->dns_domain_name.string);
4382 if (!rec->data.info.dns_name.string) {
4383 return NT_STATUS_NO_MEMORY;
4385 rec->data.info.dns_name.size =
4386 strlen(rec->data.info.dns_name.string);
4387 rec->data.info.netbios_name.string =
4388 talloc_strdup(mem_ctx,
4389 info->netbios_domain_name.string);
4390 if (!rec->data.info.netbios_name.string) {
4391 return NT_STATUS_NO_MEMORY;
4393 rec->data.info.netbios_name.size =
4394 strlen(rec->data.info.netbios_name.string);
4397 return NT_STATUS_INVALID_DOMAIN_STATE;
4401 return NT_STATUS_OK;
4404 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4405 uint32_t idx, uint32_t collision_type,
4406 uint32_t conflict_type, const char *tdo_name);
4408 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4409 const char *tdo_name,
4410 struct ForestTrustInfo *tdo_fti,
4411 struct ForestTrustInfo *new_fti,
4412 struct lsa_ForestTrustCollisionInfo *c_info)
4414 struct ForestTrustInfoRecord *nrec;
4415 struct ForestTrustInfoRecord *trec;
4416 const char *dns_name;
4417 const char *nb_name;
4418 struct dom_sid *sid = NULL;
4419 const char *tname = NULL;
4422 NTSTATUS nt_status = NT_STATUS_OK;
4423 uint32_t new_fti_idx;
4425 /* use always TDO type, until we understand when Xref can be used */
4426 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4431 bool ex_rule = false;
4434 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4436 nrec = &new_fti->records[new_fti_idx].record;
4439 tln_conflict = false;
4440 sid_conflict = false;
4441 nb_conflict = false;
4444 switch (nrec->type) {
4445 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4446 /* exclusions do not conflict by definition */
4449 case FOREST_TRUST_TOP_LEVEL_NAME:
4450 dns_name = nrec->data.name.string;
4451 dns_len = nrec->data.name.size;
4454 case LSA_FOREST_TRUST_DOMAIN_INFO:
4455 dns_name = nrec->data.info.dns_name.string;
4456 dns_len = nrec->data.info.dns_name.size;
4457 nb_name = nrec->data.info.netbios_name.string;
4458 sid = &nrec->data.info.sid;
4462 if (!dns_name) continue;
4464 /* check if this is already taken and not excluded */
4465 for (i = 0; i < tdo_fti->count; i++) {
4466 trec = &tdo_fti->records[i].record;
4468 switch (trec->type) {
4469 case FOREST_TRUST_TOP_LEVEL_NAME:
4471 tname = trec->data.name.string;
4472 tlen = trec->data.name.size;
4474 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4476 tname = trec->data.name.string;
4477 tlen = trec->data.name.size;
4479 case FOREST_TRUST_DOMAIN_INFO:
4481 tname = trec->data.info.dns_name.string;
4482 tlen = trec->data.info.dns_name.size;
4484 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4487 /* if it matches exclusion,
4488 * it doesn't conflict */
4494 case DNS_CMP_FIRST_IS_CHILD:
4495 case DNS_CMP_SECOND_IS_CHILD:
4496 tln_conflict = true;
4502 /* explicit exclusion, no dns name conflict here */
4504 tln_conflict = false;
4507 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4511 /* also test for domain info */
4512 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4513 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4514 sid_conflict = true;
4516 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4517 (nb_name != NULL) &&
4518 strcasecmp_m(trec->data.info.netbios_name.string,
4525 nt_status = add_collision(c_info, new_fti_idx,
4527 LSA_TLN_DISABLED_CONFLICT,
4529 if (!NT_STATUS_IS_OK(nt_status)) {
4534 nt_status = add_collision(c_info, new_fti_idx,
4536 LSA_SID_DISABLED_CONFLICT,
4538 if (!NT_STATUS_IS_OK(nt_status)) {
4543 nt_status = add_collision(c_info, new_fti_idx,
4545 LSA_NB_DISABLED_CONFLICT,
4547 if (!NT_STATUS_IS_OK(nt_status)) {
4557 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4558 uint32_t idx, uint32_t collision_type,
4559 uint32_t conflict_type, const char *tdo_name)
4561 struct lsa_ForestTrustCollisionRecord **es;
4562 uint32_t i = c_info->count;
4564 es = talloc_realloc(c_info, c_info->entries,
4565 struct lsa_ForestTrustCollisionRecord *, i + 1);
4567 return NT_STATUS_NO_MEMORY;
4569 c_info->entries = es;
4570 c_info->count = i + 1;
4572 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4574 return NT_STATUS_NO_MEMORY;
4578 es[i]->type = collision_type;
4579 es[i]->flags = conflict_type;
4580 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4581 if (!es[i]->name.string) {
4582 return NT_STATUS_NO_MEMORY;
4584 es[i]->name.size = strlen(es[i]->name.string);
4586 return NT_STATUS_OK;
4590 lsa_lsaRSetForestTrustInformation
4592 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4593 TALLOC_CTX *mem_ctx,
4594 struct lsa_lsaRSetForestTrustInformation *r)
4596 struct dcesrv_handle *h;
4597 struct lsa_policy_state *p_state;
4598 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4599 "msDS-TrustForestTrustInfo", NULL };
4600 struct ldb_message **dom_res = NULL;
4601 struct ldb_dn *tdo_dn;
4602 struct ldb_message *msg;
4604 const char *td_name;
4605 uint32_t trust_attributes;
4606 struct lsa_ForestTrustCollisionInfo *c_info;
4607 struct ForestTrustInfo *nfti;
4608 struct ForestTrustInfo *fti;
4610 enum ndr_err_code ndr_err;
4615 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4619 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4620 return NT_STATUS_INVALID_DOMAIN_STATE;
4623 /* abort if we are not a PDC */
4624 if (!samdb_is_pdc(p_state->sam_ldb)) {
4625 return NT_STATUS_INVALID_DOMAIN_ROLE;
4628 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4629 if (ret == LDB_SUCCESS && am_rodc) {
4630 return NT_STATUS_NO_SUCH_DOMAIN;
4633 /* check caller has TRUSTED_SET_AUTH */
4635 /* fetch all trusted domain objects */
4636 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4638 &dom_res, trust_attrs,
4639 "(objectclass=trustedDomain)");
4641 return NT_STATUS_NO_SUCH_DOMAIN;
4644 for (i = 0; i < num_res; i++) {
4645 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4646 "trustPartner", NULL);
4648 return NT_STATUS_INVALID_DOMAIN_STATE;
4650 if (strcasecmp_m(td_name,
4651 r->in.trusted_domain_name->string) == 0) {
4656 return NT_STATUS_NO_SUCH_DOMAIN;
4659 tdo_dn = dom_res[i]->dn;
4661 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4662 "trustAttributes", 0);
4663 if (!(trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4664 return NT_STATUS_INVALID_PARAMETER;
4667 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4668 return NT_STATUS_INVALID_PARAMETER;
4671 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4673 return NT_STATUS_NO_MEMORY;
4676 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4677 if (!NT_STATUS_IS_OK(nt_status)) {
4681 c_info = talloc_zero(r->out.collision_info,
4682 struct lsa_ForestTrustCollisionInfo);
4684 return NT_STATUS_NO_MEMORY;
4687 /* first check own info, then other domains */
4688 fti = talloc(mem_ctx, struct ForestTrustInfo);
4690 return NT_STATUS_NO_MEMORY;
4693 nt_status = own_ft_info(p_state, fti);
4694 if (!NT_STATUS_IS_OK(nt_status)) {
4698 nt_status = check_ft_info(c_info, p_state->domain_dns,
4700 if (!NT_STATUS_IS_OK(nt_status)) {
4704 for (i = 0; i < num_res; i++) {
4705 fti = talloc(mem_ctx, struct ForestTrustInfo);
4707 return NT_STATUS_NO_MEMORY;
4710 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4711 if (!NT_STATUS_IS_OK(nt_status)) {
4712 if (NT_STATUS_EQUAL(nt_status,
4713 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4719 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4720 "trustPartner", NULL);
4722 return NT_STATUS_INVALID_DOMAIN_STATE;
4725 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4726 if (!NT_STATUS_IS_OK(nt_status)) {
4731 if (c_info->count != 0) {
4732 *r->out.collision_info = c_info;
4735 if (r->in.check_only != 0) {
4736 return NT_STATUS_OK;
4739 /* not just a check, write info back */
4741 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4742 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4743 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4744 return NT_STATUS_INVALID_PARAMETER;
4747 msg = ldb_msg_new(mem_ctx);
4749 return NT_STATUS_NO_MEMORY;
4752 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4754 return NT_STATUS_NO_MEMORY;
4757 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4758 LDB_FLAG_MOD_REPLACE, NULL);
4759 if (ret != LDB_SUCCESS) {
4760 return NT_STATUS_NO_MEMORY;
4762 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4764 if (ret != LDB_SUCCESS) {
4765 return NT_STATUS_NO_MEMORY;
4768 ret = ldb_modify(p_state->sam_ldb, msg);
4769 if (ret != LDB_SUCCESS) {
4770 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4771 ldb_errstring(p_state->sam_ldb)));
4774 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4775 return NT_STATUS_ACCESS_DENIED;
4777 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4781 return NT_STATUS_OK;
4787 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4788 struct lsa_CREDRRENAME *r)
4790 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4796 lsa_LSAROPENPOLICYSCE
4798 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4799 struct lsa_LSAROPENPOLICYSCE *r)
4801 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4806 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4808 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4809 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4811 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4816 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4818 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4819 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4821 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4826 lsa_LSARADTREPORTSECURITYEVENT
4828 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4829 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4831 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4835 /* include the generated boilerplate */
4836 #include "librpc/gen_ndr/ndr_lsa_s.c"
4840 /*****************************************
4841 NOTE! The remaining calls below were
4842 removed in w2k3, so the DCESRV_FAULT()
4843 replies are the correct implementation. Do
4844 not try and fill these in with anything else
4845 ******************************************/
4848 dssetup_DsRoleDnsNameToFlatName
4850 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4851 struct dssetup_DsRoleDnsNameToFlatName *r)
4853 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4858 dssetup_DsRoleDcAsDc
4860 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4861 struct dssetup_DsRoleDcAsDc *r)
4863 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4868 dssetup_DsRoleDcAsReplica
4870 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4871 struct dssetup_DsRoleDcAsReplica *r)
4873 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4878 dssetup_DsRoleDemoteDc
4880 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4881 struct dssetup_DsRoleDemoteDc *r)
4883 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4888 dssetup_DsRoleGetDcOperationProgress
4890 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4891 struct dssetup_DsRoleGetDcOperationProgress *r)
4893 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4898 dssetup_DsRoleGetDcOperationResults
4900 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4901 struct dssetup_DsRoleGetDcOperationResults *r)
4903 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4908 dssetup_DsRoleCancel
4910 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4911 struct dssetup_DsRoleCancel *r)
4913 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4918 dssetup_DsRoleServerSaveStateForUpgrade
4920 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4921 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4923 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4928 dssetup_DsRoleUpgradeDownlevelServer
4930 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4931 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4933 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4938 dssetup_DsRoleAbortDownlevelServerUpgrade
4940 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4941 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4943 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4947 /* include the generated boilerplate */
4948 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4950 NTSTATUS dcerpc_server_lsa_init(void)
4954 ret = dcerpc_server_dssetup_init();
4955 if (!NT_STATUS_IS_OK(ret)) {
4958 ret = dcerpc_server_lsarpc_init();
4959 if (!NT_STATUS_IS_OK(ret)) {