s4:rpc_server/lsa: use dsdb_trust_*() helper functions in dcesrv_lsa_lsaRSetForestTru...
[Samba.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
blob7ab182cf7d85f1ccb58b733a718e6c6e5c481185
1 /* need access mask/acl implementation */
3 /*
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;
46 uint32_t access_mask;
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;
56 uint32_t access_mask;
57 struct ldb_dn *secret_dn;
58 struct ldb_context *sam_ldb;
59 bool global;
63 state associated with a lsa_OpenTrustedDomain() operation
65 struct lsa_trusted_domain_state {
66 struct lsa_policy_state *policy;
67 uint32_t access_mask;
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,
78 struct dom_sid *sid,
79 uint32_t sid_access)
81 NTSTATUS status;
82 uint32_t rid;
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)) {
89 TALLOC_FREE(tmp_ctx);
90 return status;
93 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
94 if (domain_admins_sid == NULL) {
95 TALLOC_FREE(tmp_ctx);
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,
112 0, sidstr, NULL,
114 SID_WORLD,
115 SEC_ACE_TYPE_ACCESS_ALLOWED,
116 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
118 SID_BUILTIN_ADMINISTRATORS,
119 SEC_ACE_TYPE_ACCESS_ALLOWED,
120 SEC_GENERIC_ALL, 0,
122 SID_BUILTIN_ACCOUNT_OPERATORS,
123 SEC_ACE_TYPE_ACCESS_ALLOWED,
124 SEC_GENERIC_ALL, 0,
126 domain_admins_sid_str,
127 SEC_ACE_TYPE_ACCESS_ALLOWED,
128 SEC_GENERIC_ALL, 0,
130 sidstr,
131 SEC_ACE_TYPE_ACCESS_ALLOWED,
132 sid_access, 0,
134 NULL);
135 talloc_free(tmp_ctx);
137 NT_STATUS_HAVE_NO_MEMORY(*sd);
139 return NT_STATUS_OK;
143 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
144 TALLOC_CTX *mem_ctx,
145 struct lsa_EnumAccountRights *r);
147 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
148 TALLOC_CTX *mem_ctx,
149 struct lsa_policy_state *state,
150 int ldb_flag,
151 struct dom_sid *sid,
152 const struct lsa_RightSet *rights);
155 lsa_Close
157 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
158 struct lsa_Close *r)
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);
172 talloc_free(h);
174 ZERO_STRUCTP(r->out.handle);
176 return NT_STATUS_OK;
181 lsa_Delete
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;
191 lsa_DeleteObject
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;
197 int ret;
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:
209 break;
210 default:
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);
223 return NT_STATUS_OK;
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);
256 return NT_STATUS_OK;
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;
262 NTSTATUS status;
264 rights = talloc(mem_ctx, struct lsa_RightSet);
266 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
268 astate = h->data;
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
276 will always fail */
277 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
278 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
279 return NT_STATUS_OK;
282 if (!NT_STATUS_IS_OK(status)) {
283 return status;
286 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
287 LDB_FLAG_MOD_DELETE, astate->account_sid,
288 r2.out.rights);
289 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
290 return NT_STATUS_OK;
293 if (!NT_STATUS_IS_OK(status)) {
294 return status;
297 ZERO_STRUCTP(r->out.handle);
299 return NT_STATUS_OK;
302 return NT_STATUS_INVALID_HANDLE;
307 lsa_EnumPrivs
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;
313 uint32_t i;
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,
326 r->out.privs->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];
333 e->luid.low = priv;
334 e->luid.high = 0;
335 e->name.string = privname;
336 r->out.privs->count++;
337 i++;
340 *r->out.resume_handle = i;
342 return NT_STATUS_OK;
347 lsa_QuerySecObj
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;
356 NTSTATUS status;
357 struct dom_sid *sid;
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;
366 sd = pstate->sd;
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)) {
376 return status;
378 sd = _sd;
379 access_granted = astate->access_mask;
380 } else {
381 return NT_STATUS_INVALID_HANDLE;
384 sdbuf = talloc_zero(mem_ctx, struct sec_desc_buf);
385 if (sdbuf == NULL) {
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)) {
392 return status;
395 *r->out.sdbuf = sdbuf;
397 return NT_STATUS_OK;
402 lsa_SetSecObj
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);
412 lsa_ChangePassword
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,
427 TALLOC_CTX *mem_ctx,
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;
439 uint32_t flags = 0;
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 */
448 &state);
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;
458 break;
459 case ROLE_DOMAIN_MEMBER:
460 role = DS_ROLE_MEMBER_SERVER;
461 break;
462 case ROLE_ACTIVE_DIRECTORY_DC:
463 if (samdb_is_pdc(state->sam_ldb)) {
464 role = DS_ROLE_PRIMARY_DC;
465 } else {
466 role = DS_ROLE_BACKUP_DC;
468 break;
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);
475 break;
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? */
480 break;
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;
494 break;
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;
504 r->out.info = info;
505 return WERR_OK;
507 case DS_ROLE_UPGRADE_STATUS:
509 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
510 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
512 r->out.info = info;
513 return WERR_OK;
515 case DS_ROLE_OP_STATUS:
517 info->opstatus.status = DS_ROLE_OP_IDLE;
519 r->out.info = info;
520 return WERR_OK;
522 default:
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;
536 return NT_STATUS_OK;
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;
551 return NT_STATUS_OK;
555 lsa_QueryInfoPolicy2
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;
564 *r->out.info = NULL;
566 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
568 state = h->data;
570 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
571 if (!info) {
572 return NT_STATUS_NO_MEMORY;
574 *r->out.info = info;
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);
580 return NT_STATUS_OK;
581 case LSA_POLICY_INFO_AUDIT_EVENTS:
582 /* we don't need to fill in any of this */
583 ZERO_STRUCT(info->audit_events);
584 return NT_STATUS_OK;
585 case LSA_POLICY_INFO_PD:
586 /* we don't need to fill in any of this */
587 ZERO_STRUCT(info->pd);
588 return NT_STATUS_OK;
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;
599 return NT_STATUS_OK;
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);
607 return NT_STATUS_OK;
609 case LSA_POLICY_INFO_QUOTA:
610 ZERO_STRUCT(info->quota);
611 return NT_STATUS_OK;
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 */
617 *r->out.info = NULL;
618 return NT_STATUS_INVALID_PARAMETER;
621 *r->out.info = NULL;
622 return NT_STATUS_INVALID_INFO_CLASS;
626 lsa_QueryInfoPolicy
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;
632 NTSTATUS status;
634 ZERO_STRUCT(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);
642 return status;
646 lsa_SetInfoPolicy
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);
657 lsa_ClearAuditLog
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 = {
667 LSA_ACCOUNT_READ,
668 LSA_ACCOUNT_WRITE,
669 LSA_ACCOUNT_EXECUTE,
670 LSA_ACCOUNT_ALL_ACCESS
674 lsa_CreateAccount
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);
697 state = h->data;
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) {
706 talloc_free(astate);
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);
730 if (!ah) {
731 talloc_free(astate);
732 return NT_STATUS_NO_MEMORY;
735 ah->data = talloc_steal(ah, astate);
737 *r->out.acct_handle = ah->wire_handle;
739 return NT_STATUS_OK;
744 lsa_EnumAccounts
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;
751 int ret;
752 struct ldb_message **res;
753 const char * const attrs[] = { "objectSid", NULL};
754 uint32_t count, i;
756 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
758 state = h->data;
760 /* NOTE: This call must only return accounts that have at least
761 one privilege set
763 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
764 "(&(objectSid=*)(privilege=*))");
765 if (ret < 0) {
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;
778 if (count == 0) {
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],
791 "objectSid");
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;
798 return NT_STATUS_OK;
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;
808 NTSTATUS nt_status;
810 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
811 if (!NT_STATUS_IS_OK(nt_status)) {
812 return 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,
817 auth_struct,
818 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
819 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
820 return NT_STATUS_INVALID_PARAMETER;
823 return NT_STATUS_OK;
826 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
827 TALLOC_CTX *mem_ctx,
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
858 * elements.
860 p->array = talloc_realloc(mem_ctx, p->array,
861 struct AuthenticationInformation,
862 c->count);
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,
879 iopw,
880 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
881 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
882 return NT_STATUS_INVALID_PARAMETER;
885 return NT_STATUS_OK;
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;
897 struct ldb_dn *dn;
898 uint32_t i;
899 int ret;
901 dn = ldb_dn_copy(mem_ctx, base_dn);
902 if (!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);
910 if (!msg) {
911 return NT_STATUS_NO_MEMORY;
913 msg->dn = dn;
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;
933 struct ldb_val v;
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;
938 v.length = 16;
939 break;
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;
944 break;
945 default:
946 continue;
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,
963 false, NULL);
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)));
974 switch (ret) {
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;
979 default:
980 return NT_STATUS_INTERNAL_DB_CORRUPTION;
984 if (user_dn) {
985 *user_dn = dn;
987 return NT_STATUS_OK;
991 lsa_CreateTrustedDomainEx2
993 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
994 TALLOC_CTX *mem_ctx,
995 struct lsa_CreateTrustedDomainEx2 *r,
996 int op,
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[] = {
1005 NULL
1007 const char *netbios_name;
1008 const char *dns_name;
1009 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1010 struct trustDomainPasswords auth_struct;
1011 int ret;
1012 NTSTATUS nt_status;
1013 struct ldb_context *sam_ldb;
1014 struct server_id *server_ids = NULL;
1015 uint32_t num_server_ids = 0;
1016 NTSTATUS status;
1017 struct dom_sid *tmp_sid1;
1018 struct dom_sid *tmp_sid2;
1019 uint32_t tmp_rid;
1020 bool ok;
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)) {
1055 return status;
1057 status = dom_sid_split_rid(mem_ctx, tmp_sid1, &tmp_sid2, &tmp_rid);
1058 if (!NT_STATUS_IS_OK(status)) {
1059 return status;
1061 status = dom_sid_split_rid(mem_ctx, tmp_sid2, &tmp_sid1, &tmp_rid);
1062 if (!NT_STATUS_IS_OK(status)) {
1063 return status;
1065 ok = dom_sid_parse("S-1-5-21", tmp_sid2);
1066 if (!ok) {
1067 return NT_STATUS_INTERNAL_ERROR;
1069 ok = dom_sid_equal(tmp_sid1, tmp_sid2);
1070 if (!ok) {
1071 return NT_STATUS_INVALID_PARAMETER;
1073 ok = dom_sid_parse("S-1-5-21-0-0-0", tmp_sid2);
1074 if (!ok) {
1075 return NT_STATUS_INTERNAL_ERROR;
1077 ok = !dom_sid_equal(r->in.info->sid, tmp_sid2);
1078 if (!ok) {
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)) {
1126 return 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
1135 * now */
1136 auth_struct.outgoing.count = 0;
1137 auth_struct.incoming.count = 0;
1138 } else {
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)) {
1147 return nt_status;
1149 } else {
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)) {
1158 return nt_status;
1160 } else {
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,
1178 sid_encoded);
1179 if (ret > 0) {
1180 ldb_transaction_cancel(sam_ldb);
1181 return NT_STATUS_OBJECT_NAME_COLLISION;
1183 if (ret < 0) {
1184 ldb_transaction_cancel(sam_ldb);
1185 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1188 msg = ldb_msg_new(mem_ctx);
1189 if (msg == NULL) {
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",
1218 r->in.info->sid);
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);
1261 switch (ret) {
1262 case LDB_SUCCESS:
1263 break;
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;
1276 default:
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,
1289 netbios_name,
1290 &auth_struct.incoming,
1291 &user_dn);
1292 if (!NT_STATUS_IS_OK(nt_status)) {
1293 ldb_transaction_cancel(sam_ldb);
1294 return nt_status;
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,
1311 mem_ctx,
1312 "winbind_server",
1313 &num_server_ids, &server_ids);
1314 if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
1315 enum ndr_err_code ndr_err;
1316 DATA_BLOB b = {};
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);
1328 if (!handle) {
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);
1376 if (!r2.in.info) {
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,
1397 const char *filter,
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[] = {
1405 "trustDirection",
1406 "flatname",
1407 NULL
1409 uint32_t direction;
1410 int ret;
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);
1418 if (ret == 0) {
1419 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1422 if (ret != 1) {
1423 DEBUG(0,("Found %d records matching %s under %s\n", ret,
1424 filter,
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],
1442 "flatname", NULL);
1444 /* search for the trusted_domain account */
1445 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1446 policy_state->domain_dn,
1447 &msgs, attrs,
1448 "(&(samaccountname=%s$)(objectclass=user)"
1449 "(userAccountControl:%s:=%u))",
1450 flatname,
1451 LDB_OID_COMPARATOR_AND,
1452 UF_INTERDOMAIN_TRUST_ACCOUNT);
1453 if (ret == 1) {
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);
1460 if (!handle) {
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,
1468 policy_state);
1470 *_handle = handle;
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;
1485 char *filter;
1486 NTSTATUS status;
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);
1493 if (!sid_string) {
1494 return NT_STATUS_NO_MEMORY;
1497 filter = talloc_asprintf(mem_ctx,
1498 "(&(securityIdentifier=%s)"
1499 "(objectclass=trustedDomain))",
1500 sid_string);
1501 if (filter == NULL) {
1502 return NT_STATUS_NO_MEMORY;
1505 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1506 policy_state,
1507 filter,
1508 r->in.access_mask,
1509 &handle);
1510 if (!NT_STATUS_IS_OK(status)) {
1511 return 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;
1530 char *td_name;
1531 char *filter;
1532 NTSTATUS status;
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,
1557 policy_state,
1558 filter,
1559 r->in.access_mask,
1560 &handle);
1561 if (!NT_STATUS_IS_OK(status)) {
1562 return 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",
1593 "trustPosixOffset",
1594 "msDs-supportedEncryptionTypes",
1595 "msDS-TrustForestTrustInfo",
1596 NULL
1598 char *dns = NULL;
1599 char *nbn = NULL;
1600 char *sidstr = NULL;
1601 char *filter;
1602 int ret;
1605 if (dns_domain || netbios || sid) {
1606 filter = talloc_strdup(mem_ctx,
1607 "(&(objectclass=trustedDomain)(|");
1608 } else {
1609 filter = talloc_strdup(mem_ctx,
1610 "(objectclass=trustedDomain)");
1612 if (!filter) {
1613 return NT_STATUS_NO_MEMORY;
1616 if (dns_domain) {
1617 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1618 if (!dns) {
1619 return NT_STATUS_NO_MEMORY;
1621 filter = talloc_asprintf_append(filter,
1622 "(trustPartner=%s)", dns);
1623 if (!filter) {
1624 return NT_STATUS_NO_MEMORY;
1627 if (netbios) {
1628 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1629 if (!nbn) {
1630 return NT_STATUS_NO_MEMORY;
1632 filter = talloc_asprintf_append(filter,
1633 "(flatname=%s)", nbn);
1634 if (!filter) {
1635 return NT_STATUS_NO_MEMORY;
1638 if (sid) {
1639 sidstr = dom_sid_string(mem_ctx, sid);
1640 if (!sidstr) {
1641 return NT_STATUS_INVALID_PARAMETER;
1643 filter = talloc_asprintf_append(filter,
1644 "(securityIdentifier=%s)",
1645 sidstr);
1646 if (!filter) {
1647 return NT_STATUS_NO_MEMORY;
1650 if (dns_domain || netbios || sid) {
1651 filter = talloc_asprintf_append(filter, "))");
1652 if (!filter) {
1653 return NT_STATUS_NO_MEMORY;
1657 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1658 if (ret == 0) {
1659 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1662 if (ret != 1) {
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,
1674 uint32_t value,
1675 uint32_t *orig_value)
1677 const struct ldb_val *orig_val;
1678 uint32_t orig_uint = 0;
1679 unsigned int flags = 0;
1680 int ret;
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;
1687 } else {
1688 errno = 0;
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;
1696 if (flags == 0) {
1697 /* stored value is identical, nothing to change */
1698 goto done;
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;
1711 done:
1712 if (orig_value) {
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,
1721 bool delete_user,
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;
1728 uint32_t uac;
1729 uint32_t i;
1730 int ret;
1732 ret = gendb_search(sam_ldb, mem_ctx,
1733 base_dn, &msgs, attrs,
1734 "samAccountName=%s$", netbios_name);
1735 if (ret > 1) {
1736 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1739 if (ret == 0) {
1740 if (delete_user) {
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;
1756 if (delete_user) {
1757 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1758 switch (ret) {
1759 case LDB_SUCCESS:
1760 return NT_STATUS_OK;
1761 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1762 return NT_STATUS_ACCESS_DENIED;
1763 default:
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);
1774 if (!msg) {
1775 return NT_STATUS_NO_MEMORY;
1777 msg->dn = msgs[0]->dn;
1779 for (i = 0; i < in->count; i++) {
1780 const char *attribute;
1781 struct ldb_val v;
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;
1786 v.length = 16;
1787 break;
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;
1792 break;
1793 default:
1794 continue;
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)));
1816 switch (ret) {
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;
1821 default:
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;
1845 NTSTATUS nt_status;
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;
1854 int ret;
1855 bool am_rodc;
1857 switch (level) {
1858 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1859 posix_offset = &info->posix_offset.posix_offset;
1860 break;
1861 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1862 info_ex = &info->info_ex;
1863 break;
1864 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1865 auth_info = &info->auth_info;
1866 break;
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;
1871 break;
1872 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1873 auth_info_int = &info->auth_info_internal;
1874 break;
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;
1879 break;
1880 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1881 enc_types = &info->enc_types.enc_types;
1882 break;
1883 default:
1884 return NT_STATUS_INVALID_PARAMETER;
1887 if (auth_info) {
1888 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1889 &trustAuthIncoming,
1890 &trustAuthOutgoing);
1891 if (!NT_STATUS_IS_OK(nt_status)) {
1892 return 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,
1899 NULL,
1900 &current_passwords);
1901 if (!NT_STATUS_IS_OK(nt_status)) {
1902 return 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)) {
1917 return nt_status;
1921 if (info_ex) {
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,
1940 p_state->system_dn,
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)) {
1945 return nt_status;
1947 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1948 return NT_STATUS_OBJECT_NAME_COLLISION;
1950 talloc_free(msgs);
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)) {
1960 return nt_status;
1963 current_passwords = &auth_struct.incoming;
1965 } else {
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)) {
1974 return nt_status;
1976 } else {
1977 trustAuthOutgoing = data_blob(NULL, 0);
1980 msg = ldb_msg_new(mem_ctx);
1981 if (msg == NULL) {
1982 return NT_STATUS_NO_MEMORY;
1984 msg->dn = dom_msg->dn;
1986 if (posix_offset) {
1987 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1988 dom_msg, msg,
1989 "trustPosixOffset",
1990 *posix_offset, NULL);
1991 if (!NT_STATUS_IS_OK(nt_status)) {
1992 return nt_status;
1996 if (info_ex) {
1997 uint32_t origattrs;
1998 uint32_t changed_attrs;
1999 uint32_t origdir;
2000 int origtype;
2002 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2003 dom_msg, msg,
2004 "trustDirection",
2005 info_ex->trust_direction,
2006 &origdir);
2007 if (!NT_STATUS_IS_OK(nt_status)) {
2008 return 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,
2039 dom_msg, msg,
2040 "trustAttributes",
2041 info_ex->trust_attributes,
2042 &origattrs);
2043 if (!NT_STATUS_IS_OK(nt_status)) {
2044 return 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;
2078 if (enc_types) {
2079 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2080 dom_msg, msg,
2081 "msDS-SupportedEncryptionTypes",
2082 *enc_types, NULL);
2083 if (!NT_STATUS_IS_OK(nt_status)) {
2084 return 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;
2094 if (add_incoming) {
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;
2108 if (add_outgoing) {
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);
2138 goto done;
2142 if (add_incoming || del_incoming) {
2143 const char *netbios_name;
2145 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
2146 "flatname", NULL);
2147 if (!netbios_name) {
2148 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
2149 goto done;
2152 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
2153 nt_status = update_trust_user(mem_ctx,
2154 p_state->sam_ldb,
2155 p_state->domain_dn,
2156 del_incoming,
2157 netbios_name,
2158 current_passwords);
2159 if (!NT_STATUS_IS_OK(nt_status)) {
2160 goto done;
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;
2173 done:
2174 if (in_transaction) {
2175 ldb_transaction_cancel(p_state->sam_ldb);
2177 return nt_status;
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;
2191 NTSTATUS nt_status;
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)) {
2205 return nt_status;
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)
2221 NTSTATUS status;
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)) {
2235 return 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)) {
2245 return 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);
2258 info_ex->sid
2259 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2260 info_ex->trust_direction
2261 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2262 info_ex->trust_type
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;
2279 int ret;
2280 struct ldb_message **res;
2281 const char *attrs[] = {
2282 "flatname",
2283 "trustPartner",
2284 "securityIdentifier",
2285 "trustDirection",
2286 "trustType",
2287 "trustAttributes",
2288 "msDs-supportedEncryptionTypes",
2289 NULL
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);
2299 if (ret != 1) {
2300 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2302 msg = res[0];
2304 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2305 if (!info) {
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);
2314 break;
2315 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2316 info->posix_offset.posix_offset
2317 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2318 break;
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");
2325 break;
2326 #endif
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);
2342 break;
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 */
2347 talloc_free(info);
2348 *r->out.info = NULL;
2349 return NT_STATUS_INVALID_PARAMETER;
2350 default:
2351 /* oops, we don't want to return the info after all */
2352 talloc_free(info);
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)
2367 NTSTATUS status;
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)) {
2381 return 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)) {
2393 return 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;
2409 NTSTATUS nt_status;
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,
2419 NULL, &msgs);
2420 if (!NT_STATUS_IS_OK(nt_status)) {
2421 if (NT_STATUS_EQUAL(nt_status,
2422 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2423 return nt_status;
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)
2439 NTSTATUS status;
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)) {
2453 return 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)) {
2465 return 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
2480 * anyway. */
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);
2494 lsa_EnumTrustDom
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[] = {
2504 "flatname",
2505 "securityIdentifier",
2506 NULL
2510 int count, i;
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");
2525 if (count < 0) {
2526 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2529 /* convert to lsa_TrustInformation format */
2530 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2531 if (!entries) {
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[] = {
2593 "flatname",
2594 "trustPartner",
2595 "securityIdentifier",
2596 "trustDirection",
2597 "trustType",
2598 "trustAttributes",
2599 NULL
2601 NTSTATUS nt_status;
2603 int count, i;
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");
2618 if (count < 0) {
2619 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2622 /* convert to lsa_DomainInformation format */
2623 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2624 if (!entries) {
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)) {
2630 return 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;
2664 lsa_OpenAccount
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);
2677 state = h->data;
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);
2710 if (!ah) {
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;
2732 int ret;
2733 unsigned int i, j;
2734 struct ldb_message **res;
2735 const char * const attrs[] = { "privilege", NULL};
2736 struct ldb_message_element *el;
2737 const char *sidstr;
2738 struct lsa_PrivilegeSet *privs;
2740 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2742 astate = h->data;
2744 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2745 if (privs == NULL) {
2746 return NT_STATUS_NO_MEMORY;
2748 privs->count = 0;
2749 privs->unknown = 0;
2750 privs->set = NULL;
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);
2761 if (ret < 0) {
2762 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2764 if (ret != 1) {
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;
2779 j = 0;
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 */
2784 continue;
2786 privs->set[j].attribute = 0;
2787 privs->set[j].luid.low = id;
2788 privs->set[j].luid.high = 0;
2789 j++;
2792 privs->count = j;
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;
2806 int ret;
2807 unsigned int i;
2808 struct ldb_message **res;
2809 const char * const attrs[] = { "privilege", NULL};
2810 const char *sidstr;
2811 struct ldb_message_element *el;
2813 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2815 state = h->data;
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);
2824 if (ret == 0) {
2825 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2827 if (ret != 1) {
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,
2861 int ldb_flag,
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;
2868 int ret;
2869 uint32_t i;
2870 struct lsa_EnumAccountRights r2;
2871 char *dnstr;
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);
2880 if (msg == NULL) {
2881 return NT_STATUS_NO_MEMORY;
2884 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2885 if (sidndrstr == NULL) {
2886 TALLOC_FREE(msg);
2887 return NT_STATUS_NO_MEMORY;
2890 sidstr = dom_sid_string(msg, sid);
2891 if (sidstr == NULL) {
2892 TALLOC_FREE(msg);
2893 return NT_STATUS_NO_MEMORY;
2896 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2897 if (dnstr == NULL) {
2898 TALLOC_FREE(msg);
2899 return NT_STATUS_NO_MEMORY;
2902 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2903 if (msg->dn == NULL) {
2904 TALLOC_FREE(msg);
2905 return NT_STATUS_NO_MEMORY;
2908 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2909 NTSTATUS status;
2911 r2.in.handle = &state->handle->wire_handle;
2912 r2.in.sid = sid;
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) {
2924 talloc_free(msg);
2925 return NT_STATUS_NO_SUCH_PRIVILEGE;
2928 talloc_free(msg);
2929 return NT_STATUS_NO_SUCH_PRIVILEGE;
2932 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2933 uint32_t j;
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) {
2937 break;
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) {
2945 talloc_free(msg);
2946 return NT_STATUS_NO_MEMORY;
2950 el = ldb_msg_find_element(msg, "privilege");
2951 if (!el) {
2952 talloc_free(msg);
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) {
2961 talloc_free(msg);
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) {
2969 talloc_free(msg);
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)));
2975 talloc_free(msg);
2976 return NT_STATUS_UNEXPECTED_IO_ERROR;
2979 talloc_free(msg);
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;
2992 uint32_t i;
2994 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2996 astate = h->data;
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,
3016 &rights);
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;
3029 uint32_t i;
3031 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3033 astate = h->data;
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;
3040 NTSTATUS status;
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)) {
3048 return status;
3051 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3052 LDB_FLAG_MOD_DELETE, astate->account_sid,
3053 r2.out.rights);
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,
3078 rights);
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;
3110 int ret;
3111 unsigned int i;
3112 struct ldb_message **res;
3113 const char * const attrs[] = { "privilege", NULL};
3114 struct ldb_message_element *el;
3115 const char *sidstr;
3117 *(r->out.access_mask) = 0x00000000;
3119 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3121 astate = h->data;
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);
3130 if (ret < 0) {
3131 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3133 if (ret != 1) {
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 */
3146 continue;
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);
3166 lsa_CreateSecret
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[] = {
3177 NULL
3180 const char *name;
3182 int ret;
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:
3191 break;
3192 default:
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);
3208 if (msg == NULL) {
3209 return NT_STATUS_NO_MEMORY;
3212 if (strncmp("G$", r->in.name.string, 2) == 0) {
3213 const char *name2;
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))",
3237 name2);
3238 if (ret > 0) {
3239 return NT_STATUS_OBJECT_NAME_COLLISION;
3242 if (ret < 0) {
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;
3256 } else {
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"),
3271 &msgs, attrs,
3272 "(&(cn=%s)(objectclass=secret))",
3273 ldb_binary_encode_string(mem_ctx, name));
3274 if (ret > 0) {
3275 return NT_STATUS_OBJECT_NAME_COLLISION;
3278 if (ret < 0) {
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;
3322 lsa_OpenSecret
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[] = {
3334 NULL
3337 const char *name;
3339 int ret;
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:
3353 break;
3354 default:
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));
3381 if (ret == 0) {
3382 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3385 if (ret != 1) {
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;
3390 } else {
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"),
3403 &msgs, attrs,
3404 "(&(cn=%s)(objectclass=secret))",
3405 ldb_binary_encode_string(mem_ctx, name));
3406 if (ret == 0) {
3407 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3410 if (ret != 1) {
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);
3420 if (!handle) {
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;
3436 lsa_SetSecret
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;
3447 struct ldb_val val;
3448 int ret;
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);
3459 if (msg == NULL) {
3460 return NT_STATUS_NO_MEMORY;
3463 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3464 if (!msg->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)) {
3469 return status;
3472 if (r->in.old_val) {
3473 /* Decrypt */
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)) {
3479 return status;
3482 val.data = secret.data;
3483 val.length = secret.length;
3485 /* set value */
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;
3496 } else {
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[] = {
3503 "currentValue",
3504 "lastSetTime",
3505 NULL
3508 /* search for the secret record */
3509 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3510 secret_state->secret_dn, &res, attrs);
3511 if (ret == 0) {
3512 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3515 if (ret != 1) {
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);
3524 if (old_val) {
3525 /* set old value */
3526 if (ldb_msg_add_value(msg, "priorValue",
3527 old_val, NULL) != LDB_SUCCESS) {
3528 return NT_STATUS_NO_MEMORY;
3530 } else {
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;
3543 } else {
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) {
3552 /* Decrypt */
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)) {
3558 return status;
3561 val.data = secret.data;
3562 val.length = secret.length;
3564 /* set value */
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;
3574 } else {
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;
3597 lsa_QuerySecret
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;
3607 int ret;
3608 struct ldb_message **res;
3609 const char *attrs[] = {
3610 "currentValue",
3611 "priorValue",
3612 "lastSetTime",
3613 "priorSetTime",
3614 NULL
3617 NTSTATUS nt_status;
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:
3626 break;
3627 default:
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);
3637 if (ret != 1) {
3638 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3640 msg = res[0];
3642 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3643 if (!NT_STATUS_IS_OK(nt_status)) {
3644 return 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;
3659 /* Encrypt */
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;
3695 /* Encrypt */
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;
3723 lsa_LookupPrivValue
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;
3730 int id;
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;
3747 lsa_LookupPrivName
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);
3769 if (name == NULL) {
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;
3825 int ret, i;
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);
3832 state = h->data;
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);
3845 if (ret < 0) {
3846 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3848 if (ret == 0) {
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);
3879 state = h->data;
3881 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3882 LDB_FLAG_MOD_ADD,
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);
3899 state = h->data;
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);
3928 lsa_GetUserName
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;
3981 return status;
3985 lsa_SetInfoPolicy2
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));
4023 #endif
4024 k->reserved = 0;
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);
4036 if (!info) {
4037 return NT_STATUS_NO_MEMORY;
4040 switch (r->in.level) {
4041 case LSA_DOMAIN_INFO_POLICY_EFS:
4042 talloc_free(info);
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,
4051 &smb_krb5_context);
4052 if (ret != 0) {
4053 talloc_free(info);
4054 *r->out.info = NULL;
4055 return NT_STATUS_INTERNAL_ERROR;
4057 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
4058 smb_krb5_context,
4060 talloc_free(smb_krb5_context);
4061 *r->out.info = info;
4062 return NT_STATUS_OK;
4064 default:
4065 talloc_free(info);
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);
4082 lsa_TestCall
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);
4092 lsa_CREDRWRITE
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);
4102 lsa_CREDRREAD
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);
4112 lsa_CREDRENUMERATE
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);
4142 lsa_CREDRDELETE
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 struct dcesrv_handle *h = NULL;
4218 struct lsa_policy_state *p_state = NULL;
4219 int forest_level = DS_DOMAIN_FUNCTION_2000;
4220 const char * const trust_attrs[] = {
4221 "securityIdentifier",
4222 "flatName",
4223 "trustPartner",
4224 "trustAttributes",
4225 "trustDirection",
4226 "trustType",
4227 "msDS-TrustForestTrustInfo",
4228 NULL
4230 struct ldb_message *trust_tdo_msg = NULL;
4231 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4232 struct ForestTrustInfo *trust_fti = NULL;
4233 struct lsa_ForestTrustInformation *trust_lfti = NULL;
4234 NTSTATUS status;
4236 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4238 p_state = h->data;
4240 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4241 return NT_STATUS_INVALID_DOMAIN_STATE;
4244 forest_level = dsdb_forest_functional_level(p_state->sam_ldb);
4245 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4246 return NT_STATUS_INVALID_DOMAIN_STATE;
4249 if (r->in.trusted_domain_name->string == NULL) {
4250 return NT_STATUS_NO_SUCH_DOMAIN;
4253 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4254 r->in.trusted_domain_name->string,
4255 r->in.trusted_domain_name->string,
4256 trust_attrs, mem_ctx, &trust_tdo_msg);
4257 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4258 return NT_STATUS_NO_SUCH_DOMAIN;
4260 if (!NT_STATUS_IS_OK(status)) {
4261 return status;
4264 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4265 if (!NT_STATUS_IS_OK(status)) {
4266 return status;
4269 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4270 return NT_STATUS_INVALID_PARAMETER;
4273 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4274 return NT_STATUS_INVALID_PARAMETER;
4277 status = dsdb_trust_parse_forest_info(mem_ctx,
4278 trust_tdo_msg,
4279 &trust_fti);
4280 if (!NT_STATUS_IS_OK(status)) {
4281 return status;
4284 status = dsdb_trust_forest_info_to_lsa(mem_ctx, trust_fti,
4285 &trust_lfti);
4286 if (!NT_STATUS_IS_OK(status)) {
4287 return status;
4290 *r->out.forest_trust_info = trust_lfti;
4291 return NT_STATUS_OK;
4294 #if 0
4295 #define DNS_CMP_MATCH 0
4296 #define DNS_CMP_FIRST_IS_CHILD 1
4297 #define DNS_CMP_SECOND_IS_CHILD 2
4298 #define DNS_CMP_NO_MATCH 3
4300 /* this function assumes names are well formed DNS names.
4301 * it doesn't validate them */
4302 static int dns_cmp(const char *s1, size_t l1,
4303 const char *s2, size_t l2)
4305 const char *p1, *p2;
4306 size_t t1, t2;
4307 int cret;
4309 if (l1 == l2) {
4310 if (strcasecmp_m(s1, s2) == 0) {
4311 return DNS_CMP_MATCH;
4313 return DNS_CMP_NO_MATCH;
4316 if (l1 > l2) {
4317 p1 = s1;
4318 p2 = s2;
4319 t1 = l1;
4320 t2 = l2;
4321 cret = DNS_CMP_FIRST_IS_CHILD;
4322 } else {
4323 p1 = s2;
4324 p2 = s1;
4325 t1 = l2;
4326 t2 = l1;
4327 cret = DNS_CMP_SECOND_IS_CHILD;
4330 if (p1[t1 - t2 - 1] != '.') {
4331 return DNS_CMP_NO_MATCH;
4334 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
4335 return cret;
4338 return DNS_CMP_NO_MATCH;
4341 /* decode all TDOs forest trust info blobs */
4342 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
4343 struct ldb_message *msg,
4344 struct ForestTrustInfo *info)
4346 const struct ldb_val *ft_blob;
4347 enum ndr_err_code ndr_err;
4349 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
4350 if (!ft_blob || !ft_blob->data) {
4351 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4353 /* ldb_val is equivalent to DATA_BLOB */
4354 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
4355 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
4356 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4357 return NT_STATUS_INVALID_DOMAIN_STATE;
4360 return NT_STATUS_OK;
4363 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
4364 struct ForestTrustInfo *fti)
4366 struct ForestTrustDataDomainInfo *info;
4367 struct ForestTrustInfoRecord *rec;
4369 fti->version = 1;
4370 fti->count = 2;
4371 fti->records = talloc_array(fti,
4372 struct ForestTrustInfoRecordArmor, 2);
4373 if (!fti->records) {
4374 return NT_STATUS_NO_MEMORY;
4377 /* TLN info */
4378 rec = &fti->records[0].record;
4380 rec->flags = 0;
4381 rec->timestamp = 0;
4382 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
4384 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
4385 if (!rec->data.name.string) {
4386 return NT_STATUS_NO_MEMORY;
4388 rec->data.name.size = strlen(rec->data.name.string);
4390 /* DOMAIN info */
4391 rec = &fti->records[1].record;
4393 rec->flags = 0;
4394 rec->timestamp = 0;
4395 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
4397 info = &rec->data.info;
4399 info->sid = *ps->domain_sid;
4400 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
4401 if (!info->dns_name.string) {
4402 return NT_STATUS_NO_MEMORY;
4404 info->dns_name.size = strlen(info->dns_name.string);
4405 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
4406 if (!info->netbios_name.string) {
4407 return NT_STATUS_NO_MEMORY;
4409 info->netbios_name.size = strlen(info->netbios_name.string);
4411 return NT_STATUS_OK;
4414 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
4415 struct lsa_ForestTrustInformation *lfti,
4416 struct ForestTrustInfo *fti)
4418 struct lsa_ForestTrustRecord *lrec;
4419 struct ForestTrustInfoRecord *rec;
4420 struct lsa_StringLarge *tln;
4421 struct lsa_ForestTrustDomainInfo *info;
4422 uint32_t i;
4424 fti->version = 1;
4425 fti->count = lfti->count;
4426 fti->records = talloc_array(mem_ctx,
4427 struct ForestTrustInfoRecordArmor,
4428 fti->count);
4429 if (!fti->records) {
4430 return NT_STATUS_NO_MEMORY;
4432 for (i = 0; i < fti->count; i++) {
4433 lrec = lfti->entries[i];
4434 rec = &fti->records[i].record;
4436 rec->flags = lrec->flags;
4437 rec->timestamp = lrec->time;
4438 rec->type = lrec->type;
4440 switch (lrec->type) {
4441 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4442 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4443 tln = &lrec->forest_trust_data.top_level_name;
4444 rec->data.name.string =
4445 talloc_strdup(mem_ctx, tln->string);
4446 if (!rec->data.name.string) {
4447 return NT_STATUS_NO_MEMORY;
4449 rec->data.name.size = strlen(rec->data.name.string);
4450 break;
4451 case LSA_FOREST_TRUST_DOMAIN_INFO:
4452 info = &lrec->forest_trust_data.domain_info;
4453 rec->data.info.sid = *info->domain_sid;
4454 rec->data.info.dns_name.string =
4455 talloc_strdup(mem_ctx,
4456 info->dns_domain_name.string);
4457 if (!rec->data.info.dns_name.string) {
4458 return NT_STATUS_NO_MEMORY;
4460 rec->data.info.dns_name.size =
4461 strlen(rec->data.info.dns_name.string);
4462 rec->data.info.netbios_name.string =
4463 talloc_strdup(mem_ctx,
4464 info->netbios_domain_name.string);
4465 if (!rec->data.info.netbios_name.string) {
4466 return NT_STATUS_NO_MEMORY;
4468 rec->data.info.netbios_name.size =
4469 strlen(rec->data.info.netbios_name.string);
4470 break;
4471 default:
4472 return NT_STATUS_INVALID_DOMAIN_STATE;
4476 return NT_STATUS_OK;
4479 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4480 uint32_t idx, uint32_t collision_type,
4481 uint32_t conflict_type, const char *tdo_name);
4483 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4484 const char *tdo_name,
4485 struct ForestTrustInfo *tdo_fti,
4486 struct ForestTrustInfo *new_fti,
4487 struct lsa_ForestTrustCollisionInfo *c_info)
4489 struct ForestTrustInfoRecord *nrec;
4490 struct ForestTrustInfoRecord *trec;
4491 const char *dns_name;
4492 const char *nb_name;
4493 struct dom_sid *sid = NULL;
4494 const char *tname = NULL;
4495 size_t dns_len;
4496 size_t tlen = 0;
4497 NTSTATUS nt_status = NT_STATUS_OK;
4498 uint32_t new_fti_idx;
4499 uint32_t i;
4500 /* use always TDO type, until we understand when Xref can be used */
4501 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4502 bool tln_conflict;
4503 bool sid_conflict;
4504 bool nb_conflict;
4505 bool exclusion;
4506 bool ex_rule = false;
4507 int ret;
4509 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4511 nrec = &new_fti->records[new_fti_idx].record;
4512 dns_name = NULL;
4513 nb_name = NULL;
4514 tln_conflict = false;
4515 sid_conflict = false;
4516 nb_conflict = false;
4517 exclusion = false;
4519 switch (nrec->type) {
4520 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4521 /* exclusions do not conflict by definition */
4522 break;
4524 case FOREST_TRUST_TOP_LEVEL_NAME:
4525 dns_name = nrec->data.name.string;
4526 dns_len = nrec->data.name.size;
4527 break;
4529 case LSA_FOREST_TRUST_DOMAIN_INFO:
4530 dns_name = nrec->data.info.dns_name.string;
4531 dns_len = nrec->data.info.dns_name.size;
4532 nb_name = nrec->data.info.netbios_name.string;
4533 sid = &nrec->data.info.sid;
4534 break;
4537 if (!dns_name) continue;
4539 /* check if this is already taken and not excluded */
4540 for (i = 0; i < tdo_fti->count; i++) {
4541 trec = &tdo_fti->records[i].record;
4543 switch (trec->type) {
4544 case FOREST_TRUST_TOP_LEVEL_NAME:
4545 ex_rule = false;
4546 tname = trec->data.name.string;
4547 tlen = trec->data.name.size;
4548 break;
4549 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4550 ex_rule = true;
4551 tname = trec->data.name.string;
4552 tlen = trec->data.name.size;
4553 break;
4554 case FOREST_TRUST_DOMAIN_INFO:
4555 ex_rule = false;
4556 tname = trec->data.info.dns_name.string;
4557 tlen = trec->data.info.dns_name.size;
4559 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4560 switch (ret) {
4561 case DNS_CMP_MATCH:
4562 /* if it matches exclusion,
4563 * it doesn't conflict */
4564 if (ex_rule) {
4565 exclusion = true;
4566 break;
4568 /* fall through */
4569 case DNS_CMP_FIRST_IS_CHILD:
4570 case DNS_CMP_SECOND_IS_CHILD:
4571 tln_conflict = true;
4572 /* fall through */
4573 default:
4574 break;
4577 /* explicit exclusion, no dns name conflict here */
4578 if (exclusion) {
4579 tln_conflict = false;
4582 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4583 continue;
4586 /* also test for domain info */
4587 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4588 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4589 sid_conflict = true;
4591 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4592 (nb_name != NULL) &&
4593 strcasecmp_m(trec->data.info.netbios_name.string,
4594 nb_name) == 0) {
4595 nb_conflict = true;
4599 if (tln_conflict) {
4600 nt_status = add_collision(c_info, new_fti_idx,
4601 collision_type,
4602 LSA_TLN_DISABLED_CONFLICT,
4603 tdo_name);
4604 if (!NT_STATUS_IS_OK(nt_status)) {
4605 goto done;
4608 if (sid_conflict) {
4609 nt_status = add_collision(c_info, new_fti_idx,
4610 collision_type,
4611 LSA_SID_DISABLED_CONFLICT,
4612 tdo_name);
4613 if (!NT_STATUS_IS_OK(nt_status)) {
4614 goto done;
4617 if (nb_conflict) {
4618 nt_status = add_collision(c_info, new_fti_idx,
4619 collision_type,
4620 LSA_NB_DISABLED_CONFLICT,
4621 tdo_name);
4622 if (!NT_STATUS_IS_OK(nt_status)) {
4623 goto done;
4628 done:
4629 return nt_status;
4632 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4633 uint32_t idx, uint32_t collision_type,
4634 uint32_t conflict_type, const char *tdo_name)
4636 struct lsa_ForestTrustCollisionRecord **es;
4637 uint32_t i = c_info->count;
4639 es = talloc_realloc(c_info, c_info->entries,
4640 struct lsa_ForestTrustCollisionRecord *, i + 1);
4641 if (!es) {
4642 return NT_STATUS_NO_MEMORY;
4644 c_info->entries = es;
4645 c_info->count = i + 1;
4647 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4648 if (!es[i]) {
4649 return NT_STATUS_NO_MEMORY;
4652 es[i]->index = idx;
4653 es[i]->type = collision_type;
4654 es[i]->flags = conflict_type;
4655 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4656 if (!es[i]->name.string) {
4657 return NT_STATUS_NO_MEMORY;
4659 es[i]->name.size = strlen(es[i]->name.string);
4661 return NT_STATUS_OK;
4663 #endif
4666 lsa_lsaRSetForestTrustInformation
4668 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4669 TALLOC_CTX *mem_ctx,
4670 struct lsa_lsaRSetForestTrustInformation *r)
4672 struct dcesrv_handle *h;
4673 struct lsa_policy_state *p_state;
4674 const char * const trust_attrs[] = {
4675 "securityIdentifier",
4676 "flatName",
4677 "trustPartner",
4678 "trustAttributes",
4679 "trustDirection",
4680 "trustType",
4681 "msDS-TrustForestTrustInfo",
4682 NULL
4684 struct ldb_message *trust_tdo_msg = NULL;
4685 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4686 struct lsa_ForestTrustInformation *step1_lfti = NULL;
4687 struct lsa_ForestTrustInformation *step2_lfti = NULL;
4688 struct ForestTrustInfo *trust_fti = NULL;
4689 struct ldb_result *trusts_res = NULL;
4690 unsigned int i;
4691 struct lsa_TrustDomainInfoInfoEx *xref_tdo = NULL;
4692 struct lsa_ForestTrustInformation *xref_lfti = NULL;
4693 struct lsa_ForestTrustCollisionInfo *c_info = NULL;
4694 DATA_BLOB ft_blob = {};
4695 struct ldb_message *msg = NULL;
4696 NTSTATUS status;
4697 enum ndr_err_code ndr_err;
4698 int ret;
4699 bool in_transaction = false;
4701 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4703 p_state = h->data;
4705 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4706 return NT_STATUS_INVALID_DOMAIN_STATE;
4709 if (r->in.check_only == 0) {
4710 ret = ldb_transaction_start(p_state->sam_ldb);
4711 if (ret != LDB_SUCCESS) {
4712 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4714 in_transaction = true;
4718 * abort if we are not a PDC
4720 * In future we should use a function like IsEffectiveRoleOwner()
4722 if (!samdb_is_pdc(p_state->sam_ldb)) {
4723 status = NT_STATUS_INVALID_DOMAIN_ROLE;
4724 goto done;
4727 if (r->in.trusted_domain_name->string == NULL) {
4728 status = NT_STATUS_NO_SUCH_DOMAIN;
4729 goto done;
4732 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4733 r->in.trusted_domain_name->string,
4734 r->in.trusted_domain_name->string,
4735 trust_attrs, mem_ctx, &trust_tdo_msg);
4736 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4737 status = NT_STATUS_NO_SUCH_DOMAIN;
4738 goto done;
4740 if (!NT_STATUS_IS_OK(status)) {
4741 goto done;
4744 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4745 if (!NT_STATUS_IS_OK(status)) {
4746 goto done;
4749 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4750 status = NT_STATUS_INVALID_PARAMETER;
4751 goto done;
4754 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4755 status = NT_STATUS_INVALID_PARAMETER;
4756 goto done;
4760 * verify and normalize the given forest trust info.
4762 * Step1: doesn't reorder yet, so step1_lfti might contain
4763 * NULL entries. This means dsdb_trust_verify_forest_info()
4764 * can generate collision entries with the callers index.
4766 status = dsdb_trust_normalize_forest_info_step1(mem_ctx,
4767 r->in.forest_trust_info,
4768 &step1_lfti);
4769 if (!NT_STATUS_IS_OK(status)) {
4770 goto done;
4773 c_info = talloc_zero(r->out.collision_info,
4774 struct lsa_ForestTrustCollisionInfo);
4775 if (c_info == NULL) {
4776 status = NT_STATUS_NO_MEMORY;
4777 goto done;
4781 * First check our own forest, then other domains/forests
4784 status = dsdb_trust_xref_tdo_info(mem_ctx, p_state->sam_ldb,
4785 &xref_tdo);
4786 if (!NT_STATUS_IS_OK(status)) {
4787 goto done;
4789 status = dsdb_trust_xref_forest_info(mem_ctx, p_state->sam_ldb,
4790 &xref_lfti);
4791 if (!NT_STATUS_IS_OK(status)) {
4792 goto done;
4796 * The documentation proposed to generate
4797 * LSA_FOREST_TRUST_COLLISION_XREF collisions.
4798 * But Windows always uses LSA_FOREST_TRUST_COLLISION_TDO.
4800 status = dsdb_trust_verify_forest_info(xref_tdo, xref_lfti,
4801 LSA_FOREST_TRUST_COLLISION_TDO,
4802 c_info, step1_lfti);
4803 if (!NT_STATUS_IS_OK(status)) {
4804 goto done;
4807 /* fetch all other trusted domain objects */
4808 status = dsdb_trust_search_tdos(p_state->sam_ldb,
4809 trust_tdo->domain_name.string,
4810 trust_attrs,
4811 mem_ctx, &trusts_res);
4812 if (!NT_STATUS_IS_OK(status)) {
4813 goto done;
4817 * now check against the other domains.
4818 * and generate LSA_FOREST_TRUST_COLLISION_TDO collisions.
4820 for (i = 0; i < trusts_res->count; i++) {
4821 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
4822 struct ForestTrustInfo *fti = NULL;
4823 struct lsa_ForestTrustInformation *lfti = NULL;
4825 status = dsdb_trust_parse_tdo_info(mem_ctx,
4826 trusts_res->msgs[i],
4827 &tdo);
4828 if (!NT_STATUS_IS_OK(status)) {
4829 goto done;
4832 status = dsdb_trust_parse_forest_info(tdo,
4833 trusts_res->msgs[i],
4834 &fti);
4835 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
4836 continue;
4838 if (!NT_STATUS_IS_OK(status)) {
4839 goto done;
4842 status = dsdb_trust_forest_info_to_lsa(tdo, fti, &lfti);
4843 if (!NT_STATUS_IS_OK(status)) {
4844 goto done;
4847 status = dsdb_trust_verify_forest_info(tdo, lfti,
4848 LSA_FOREST_TRUST_COLLISION_TDO,
4849 c_info, step1_lfti);
4850 if (!NT_STATUS_IS_OK(status)) {
4851 goto done;
4854 TALLOC_FREE(tdo);
4857 if (r->in.check_only != 0) {
4858 status = NT_STATUS_OK;
4859 goto done;
4863 * not just a check, write info back
4867 * normalize the given forest trust info.
4869 * Step2: adds TOP_LEVEL_NAME[_EX] in reverse order,
4870 * followed by DOMAIN_INFO in reverse order. It also removes
4871 * possible NULL entries from Step1.
4873 status = dsdb_trust_normalize_forest_info_step2(mem_ctx, step1_lfti,
4874 &step2_lfti);
4875 if (!NT_STATUS_IS_OK(status)) {
4876 goto done;
4879 status = dsdb_trust_forest_info_from_lsa(mem_ctx, step2_lfti,
4880 &trust_fti);
4881 if (!NT_STATUS_IS_OK(status)) {
4882 goto done;
4885 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, trust_fti,
4886 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4887 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4888 status = NT_STATUS_INVALID_PARAMETER;
4889 goto done;
4892 msg = ldb_msg_new(mem_ctx);
4893 if (msg == NULL) {
4894 status = NT_STATUS_NO_MEMORY;
4895 goto done;
4898 msg->dn = ldb_dn_copy(mem_ctx, trust_tdo_msg->dn);
4899 if (!msg->dn) {
4900 status = NT_STATUS_NO_MEMORY;
4901 goto done;
4904 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4905 LDB_FLAG_MOD_REPLACE, NULL);
4906 if (ret != LDB_SUCCESS) {
4907 status = NT_STATUS_NO_MEMORY;
4908 goto done;
4910 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4911 &ft_blob, NULL);
4912 if (ret != LDB_SUCCESS) {
4913 status = NT_STATUS_NO_MEMORY;
4914 goto done;
4917 ret = ldb_modify(p_state->sam_ldb, msg);
4918 if (ret != LDB_SUCCESS) {
4919 status = dsdb_ldb_err_to_ntstatus(ret);
4921 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4922 ldb_errstring(p_state->sam_ldb)));
4924 goto done;
4927 /* ok, all fine, commit transaction and return */
4928 in_transaction = false;
4929 ret = ldb_transaction_commit(p_state->sam_ldb);
4930 if (ret != LDB_SUCCESS) {
4931 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4932 goto done;
4935 status = NT_STATUS_OK;
4937 done:
4938 if (NT_STATUS_IS_OK(status) && c_info->count != 0) {
4939 *r->out.collision_info = c_info;
4942 if (in_transaction) {
4943 ldb_transaction_cancel(p_state->sam_ldb);
4946 return status;
4950 lsa_CREDRRENAME
4952 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4953 struct lsa_CREDRRENAME *r)
4955 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4961 lsa_LSAROPENPOLICYSCE
4963 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4964 struct lsa_LSAROPENPOLICYSCE *r)
4966 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4971 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4973 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4974 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4976 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4981 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4983 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4984 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4986 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4991 lsa_LSARADTREPORTSECURITYEVENT
4993 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4994 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4996 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
5000 /* include the generated boilerplate */
5001 #include "librpc/gen_ndr/ndr_lsa_s.c"
5005 /*****************************************
5006 NOTE! The remaining calls below were
5007 removed in w2k3, so the DCESRV_FAULT()
5008 replies are the correct implementation. Do
5009 not try and fill these in with anything else
5010 ******************************************/
5013 dssetup_DsRoleDnsNameToFlatName
5015 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
5016 struct dssetup_DsRoleDnsNameToFlatName *r)
5018 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
5023 dssetup_DsRoleDcAsDc
5025 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
5026 struct dssetup_DsRoleDcAsDc *r)
5028 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
5033 dssetup_DsRoleDcAsReplica
5035 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
5036 struct dssetup_DsRoleDcAsReplica *r)
5038 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
5043 dssetup_DsRoleDemoteDc
5045 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
5046 struct dssetup_DsRoleDemoteDc *r)
5048 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
5053 dssetup_DsRoleGetDcOperationProgress
5055 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
5056 struct dssetup_DsRoleGetDcOperationProgress *r)
5058 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
5063 dssetup_DsRoleGetDcOperationResults
5065 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
5066 struct dssetup_DsRoleGetDcOperationResults *r)
5068 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
5073 dssetup_DsRoleCancel
5075 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
5076 struct dssetup_DsRoleCancel *r)
5078 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
5083 dssetup_DsRoleServerSaveStateForUpgrade
5085 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
5086 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
5088 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
5093 dssetup_DsRoleUpgradeDownlevelServer
5095 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
5096 struct dssetup_DsRoleUpgradeDownlevelServer *r)
5098 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
5103 dssetup_DsRoleAbortDownlevelServerUpgrade
5105 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
5106 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
5108 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
5112 /* include the generated boilerplate */
5113 #include "librpc/gen_ndr/ndr_dssetup_s.c"
5115 NTSTATUS dcerpc_server_lsa_init(void)
5117 NTSTATUS ret;
5119 ret = dcerpc_server_dssetup_init();
5120 if (!NT_STATUS_IS_OK(ret)) {
5121 return ret;
5123 ret = dcerpc_server_lsarpc_init();
5124 if (!NT_STATUS_IS_OK(ret)) {
5125 return ret;
5127 return ret;