Fix the O3 developer build
[Samba.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
blobe7b0aaef068c338a5833ca66844308bd160ffb8a
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 const char *name;
1010 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1011 struct trustDomainPasswords auth_struct;
1012 int ret;
1013 NTSTATUS nt_status;
1014 struct ldb_context *sam_ldb;
1015 struct server_id *server_ids = NULL;
1016 uint32_t num_server_ids = 0;
1017 NTSTATUS status;
1019 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
1020 ZERO_STRUCTP(r->out.trustdom_handle);
1022 policy_state = policy_handle->data;
1023 sam_ldb = policy_state->sam_ldb;
1025 netbios_name = r->in.info->netbios_name.string;
1026 if (!netbios_name) {
1027 return NT_STATUS_INVALID_PARAMETER;
1030 dns_name = r->in.info->domain_name.string;
1032 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1033 if (!trusted_domain_state) {
1034 return NT_STATUS_NO_MEMORY;
1036 trusted_domain_state->policy = policy_state;
1038 if (strcasecmp(netbios_name, "BUILTIN") == 0
1039 || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
1040 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
1041 return NT_STATUS_INVALID_PARAMETER;
1044 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
1045 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
1046 || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
1047 || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
1048 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
1049 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
1052 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
1053 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
1054 /* No secrets are created at this time, for this function */
1055 auth_struct.outgoing.count = 0;
1056 auth_struct.incoming.count = 0;
1057 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
1058 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
1059 r->in.auth_info_internal->auth_blob.size);
1060 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1061 &auth_blob, &auth_struct);
1062 if (!NT_STATUS_IS_OK(nt_status)) {
1063 return nt_status;
1065 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
1067 if (unencrypted_auth_info->incoming_count > 1) {
1068 return NT_STATUS_INVALID_PARAMETER;
1071 /* more investigation required here, do not create secrets for
1072 * now */
1073 auth_struct.outgoing.count = 0;
1074 auth_struct.incoming.count = 0;
1075 } else {
1076 return NT_STATUS_INVALID_PARAMETER;
1079 if (auth_struct.incoming.count) {
1080 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1081 &auth_struct.incoming,
1082 &trustAuthIncoming);
1083 if (!NT_STATUS_IS_OK(nt_status)) {
1084 return nt_status;
1086 } else {
1087 trustAuthIncoming = data_blob(NULL, 0);
1090 if (auth_struct.outgoing.count) {
1091 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1092 &auth_struct.outgoing,
1093 &trustAuthOutgoing);
1094 if (!NT_STATUS_IS_OK(nt_status)) {
1095 return nt_status;
1097 } else {
1098 trustAuthOutgoing = data_blob(NULL, 0);
1101 ret = ldb_transaction_start(sam_ldb);
1102 if (ret != LDB_SUCCESS) {
1103 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1106 if (dns_name) {
1107 char *dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1108 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1109 /* search for the trusted_domain record */
1110 ret = gendb_search(sam_ldb,
1111 mem_ctx, policy_state->system_dn, &msgs, attrs,
1112 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1113 dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
1114 if (ret > 0) {
1115 ldb_transaction_cancel(sam_ldb);
1116 return NT_STATUS_OBJECT_NAME_COLLISION;
1118 } else {
1119 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1120 /* search for the trusted_domain record */
1121 ret = gendb_search(sam_ldb,
1122 mem_ctx, policy_state->system_dn, &msgs, attrs,
1123 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1124 netbios_encoded, netbios_encoded, netbios_encoded);
1125 if (ret > 0) {
1126 ldb_transaction_cancel(sam_ldb);
1127 return NT_STATUS_OBJECT_NAME_COLLISION;
1131 if (ret < 0 ) {
1132 ldb_transaction_cancel(sam_ldb);
1133 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1136 name = dns_name ? dns_name : netbios_name;
1138 msg = ldb_msg_new(mem_ctx);
1139 if (msg == NULL) {
1140 return NT_STATUS_NO_MEMORY;
1143 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1144 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1145 ldb_transaction_cancel(sam_ldb);
1146 return NT_STATUS_NO_MEMORY;
1149 ldb_msg_add_string(msg, "flatname", netbios_name);
1151 if (r->in.info->sid) {
1152 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1153 if (ret != LDB_SUCCESS) {
1154 ldb_transaction_cancel(sam_ldb);
1155 return NT_STATUS_INVALID_PARAMETER;
1159 ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1161 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1163 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1165 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1167 if (dns_name) {
1168 ldb_msg_add_string(msg, "trustPartner", dns_name);
1171 if (trustAuthIncoming.data) {
1172 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1173 if (ret != LDB_SUCCESS) {
1174 ldb_transaction_cancel(sam_ldb);
1175 return NT_STATUS_NO_MEMORY;
1178 if (trustAuthOutgoing.data) {
1179 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1180 if (ret != LDB_SUCCESS) {
1181 ldb_transaction_cancel(sam_ldb);
1182 return NT_STATUS_NO_MEMORY;
1186 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1188 /* create the trusted_domain */
1189 ret = ldb_add(sam_ldb, msg);
1190 switch (ret) {
1191 case LDB_SUCCESS:
1192 break;
1193 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1194 ldb_transaction_cancel(sam_ldb);
1195 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1196 ldb_dn_get_linearized(msg->dn),
1197 ldb_errstring(sam_ldb)));
1198 return NT_STATUS_DOMAIN_EXISTS;
1199 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1200 ldb_transaction_cancel(sam_ldb);
1201 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1202 ldb_dn_get_linearized(msg->dn),
1203 ldb_errstring(sam_ldb)));
1204 return NT_STATUS_ACCESS_DENIED;
1205 default:
1206 ldb_transaction_cancel(sam_ldb);
1207 DEBUG(0,("Failed to create user record %s: %s\n",
1208 ldb_dn_get_linearized(msg->dn),
1209 ldb_errstring(sam_ldb)));
1210 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1213 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1214 struct ldb_dn *user_dn;
1215 /* Inbound trusts must also create a cn=users object to match */
1216 nt_status = add_trust_user(mem_ctx, sam_ldb,
1217 policy_state->domain_dn,
1218 netbios_name,
1219 &auth_struct.incoming,
1220 &user_dn);
1221 if (!NT_STATUS_IS_OK(nt_status)) {
1222 ldb_transaction_cancel(sam_ldb);
1223 return nt_status;
1226 /* save the trust user dn */
1227 trusted_domain_state->trusted_domain_user_dn
1228 = talloc_steal(trusted_domain_state, user_dn);
1231 ret = ldb_transaction_commit(sam_ldb);
1232 if (ret != LDB_SUCCESS) {
1233 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1237 * Notify winbindd that we have a new trust
1239 status = irpc_servers_byname(dce_call->msg_ctx,
1240 mem_ctx,
1241 "winbind_server",
1242 &num_server_ids, &server_ids);
1243 if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
1244 enum ndr_err_code ndr_err;
1245 DATA_BLOB b = {};
1247 ndr_err = ndr_push_struct_blob(&b, mem_ctx, r->in.info,
1248 (ndr_push_flags_fn_t)ndr_push_lsa_TrustDomainInfoInfoEx);
1249 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1250 imessaging_send(dce_call->msg_ctx, server_ids[0],
1251 MSG_WINBIND_NEW_TRUSTED_DOMAIN, &b);
1254 TALLOC_FREE(server_ids);
1256 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1257 if (!handle) {
1258 return NT_STATUS_NO_MEMORY;
1261 handle->data = talloc_steal(handle, trusted_domain_state);
1263 trusted_domain_state->access_mask = r->in.access_mask;
1264 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1266 *r->out.trustdom_handle = handle->wire_handle;
1268 return NT_STATUS_OK;
1272 lsa_CreateTrustedDomainEx2
1274 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1275 TALLOC_CTX *mem_ctx,
1276 struct lsa_CreateTrustedDomainEx2 *r)
1278 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1281 lsa_CreateTrustedDomainEx
1283 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1284 TALLOC_CTX *mem_ctx,
1285 struct lsa_CreateTrustedDomainEx *r)
1287 struct lsa_CreateTrustedDomainEx2 r2;
1289 r2.in.policy_handle = r->in.policy_handle;
1290 r2.in.info = r->in.info;
1291 r2.out.trustdom_handle = r->out.trustdom_handle;
1292 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1296 lsa_CreateTrustedDomain
1298 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1299 struct lsa_CreateTrustedDomain *r)
1301 struct lsa_CreateTrustedDomainEx2 r2;
1303 r2.in.policy_handle = r->in.policy_handle;
1304 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1305 if (!r2.in.info) {
1306 return NT_STATUS_NO_MEMORY;
1309 r2.in.info->domain_name.string = NULL;
1310 r2.in.info->netbios_name = r->in.info->name;
1311 r2.in.info->sid = r->in.info->sid;
1312 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1313 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1314 r2.in.info->trust_attributes = 0;
1316 r2.in.access_mask = r->in.access_mask;
1317 r2.out.trustdom_handle = r->out.trustdom_handle;
1319 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1322 static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
1323 struct dcesrv_call_state *dce_call,
1324 TALLOC_CTX *tmp_mem,
1325 struct lsa_policy_state *policy_state,
1326 const char *filter,
1327 uint32_t access_mask,
1328 struct dcesrv_handle **_handle)
1330 struct lsa_trusted_domain_state *trusted_domain_state;
1331 struct dcesrv_handle *handle;
1332 struct ldb_message **msgs;
1333 const char *attrs[] = {
1334 "trustDirection",
1335 "flatname",
1336 NULL
1338 uint32_t direction;
1339 int ret;
1341 /* TODO: perform access checks */
1343 /* search for the trusted_domain record */
1344 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1345 policy_state->system_dn,
1346 &msgs, attrs, "%s", filter);
1347 if (ret == 0) {
1348 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1351 if (ret != 1) {
1352 DEBUG(0,("Found %d records matching %s under %s\n", ret,
1353 filter,
1354 ldb_dn_get_linearized(policy_state->system_dn)));
1355 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1358 trusted_domain_state = talloc_zero(tmp_mem,
1359 struct lsa_trusted_domain_state);
1360 if (!trusted_domain_state) {
1361 return NT_STATUS_NO_MEMORY;
1363 trusted_domain_state->policy = policy_state;
1365 trusted_domain_state->trusted_domain_dn =
1366 talloc_steal(trusted_domain_state, msgs[0]->dn);
1368 direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1369 if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1370 const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1371 "flatname", NULL);
1373 /* search for the trusted_domain account */
1374 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1375 policy_state->domain_dn,
1376 &msgs, attrs,
1377 "(&(samaccountname=%s$)(objectclass=user)"
1378 "(userAccountControl:%s:=%u))",
1379 flatname,
1380 LDB_OID_COMPARATOR_AND,
1381 UF_INTERDOMAIN_TRUST_ACCOUNT);
1382 if (ret == 1) {
1383 trusted_domain_state->trusted_domain_user_dn =
1384 talloc_steal(trusted_domain_state, msgs[0]->dn);
1388 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1389 if (!handle) {
1390 return NT_STATUS_NO_MEMORY;
1393 handle->data = talloc_steal(handle, trusted_domain_state);
1395 trusted_domain_state->access_mask = access_mask;
1396 trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1397 policy_state);
1399 *_handle = handle;
1401 return NT_STATUS_OK;
1405 lsa_OpenTrustedDomain
1407 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1408 struct lsa_OpenTrustedDomain *r)
1410 struct dcesrv_handle *policy_handle;
1411 struct lsa_policy_state *policy_state;
1412 struct dcesrv_handle *handle;
1413 const char *sid_string;
1414 char *filter;
1415 NTSTATUS status;
1417 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1418 ZERO_STRUCTP(r->out.trustdom_handle);
1419 policy_state = policy_handle->data;
1421 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1422 if (!sid_string) {
1423 return NT_STATUS_NO_MEMORY;
1426 filter = talloc_asprintf(mem_ctx,
1427 "(&(securityIdentifier=%s)"
1428 "(objectclass=trustedDomain))",
1429 sid_string);
1430 if (filter == NULL) {
1431 return NT_STATUS_NO_MEMORY;
1434 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1435 policy_state,
1436 filter,
1437 r->in.access_mask,
1438 &handle);
1439 if (!NT_STATUS_IS_OK(status)) {
1440 return status;
1443 *r->out.trustdom_handle = handle->wire_handle;
1445 return NT_STATUS_OK;
1450 lsa_OpenTrustedDomainByName
1452 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1453 TALLOC_CTX *mem_ctx,
1454 struct lsa_OpenTrustedDomainByName *r)
1456 struct dcesrv_handle *policy_handle;
1457 struct lsa_policy_state *policy_state;
1458 struct dcesrv_handle *handle;
1459 char *td_name;
1460 char *filter;
1461 NTSTATUS status;
1463 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1464 ZERO_STRUCTP(r->out.trustdom_handle);
1465 policy_state = policy_handle->data;
1467 if (!r->in.name.string) {
1468 return NT_STATUS_INVALID_PARAMETER;
1471 /* search for the trusted_domain record */
1472 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1473 if (td_name == NULL) {
1474 return NT_STATUS_NO_MEMORY;
1477 filter = talloc_asprintf(mem_ctx,
1478 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1479 "(objectclass=trustedDomain))",
1480 td_name, td_name, td_name);
1481 if (filter == NULL) {
1482 return NT_STATUS_NO_MEMORY;
1485 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1486 policy_state,
1487 filter,
1488 r->in.access_mask,
1489 &handle);
1490 if (!NT_STATUS_IS_OK(status)) {
1491 return status;
1494 *r->out.trustdom_handle = handle->wire_handle;
1496 return NT_STATUS_OK;
1502 lsa_SetTrustedDomainInfo
1504 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1505 struct lsa_SetTrustedDomainInfo *r)
1507 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1512 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1513 * otherwise at least one must be provided */
1514 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1515 struct ldb_dn *basedn, const char *dns_domain,
1516 const char *netbios, struct dom_sid2 *sid,
1517 struct ldb_message ***msgs)
1519 const char *attrs[] = { "flatname", "trustPartner",
1520 "securityIdentifier", "trustDirection",
1521 "trustType", "trustAttributes",
1522 "trustPosixOffset",
1523 "msDs-supportedEncryptionTypes",
1524 "msDS-TrustForestTrustInfo",
1525 NULL
1527 char *dns = NULL;
1528 char *nbn = NULL;
1529 char *sidstr = NULL;
1530 char *filter;
1531 int ret;
1534 if (dns_domain || netbios || sid) {
1535 filter = talloc_strdup(mem_ctx,
1536 "(&(objectclass=trustedDomain)(|");
1537 } else {
1538 filter = talloc_strdup(mem_ctx,
1539 "(objectclass=trustedDomain)");
1541 if (!filter) {
1542 return NT_STATUS_NO_MEMORY;
1545 if (dns_domain) {
1546 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1547 if (!dns) {
1548 return NT_STATUS_NO_MEMORY;
1550 filter = talloc_asprintf_append(filter,
1551 "(trustPartner=%s)", dns);
1552 if (!filter) {
1553 return NT_STATUS_NO_MEMORY;
1556 if (netbios) {
1557 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1558 if (!nbn) {
1559 return NT_STATUS_NO_MEMORY;
1561 filter = talloc_asprintf_append(filter,
1562 "(flatname=%s)", nbn);
1563 if (!filter) {
1564 return NT_STATUS_NO_MEMORY;
1567 if (sid) {
1568 sidstr = dom_sid_string(mem_ctx, sid);
1569 if (!sidstr) {
1570 return NT_STATUS_INVALID_PARAMETER;
1572 filter = talloc_asprintf_append(filter,
1573 "(securityIdentifier=%s)",
1574 sidstr);
1575 if (!filter) {
1576 return NT_STATUS_NO_MEMORY;
1579 if (dns_domain || netbios || sid) {
1580 filter = talloc_asprintf_append(filter, "))");
1581 if (!filter) {
1582 return NT_STATUS_NO_MEMORY;
1586 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1587 if (ret == 0) {
1588 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1591 if (ret != 1) {
1592 return NT_STATUS_OBJECT_NAME_COLLISION;
1595 return NT_STATUS_OK;
1598 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1599 struct ldb_context *sam_ldb,
1600 struct ldb_message *orig,
1601 struct ldb_message *dest,
1602 const char *attribute,
1603 uint32_t value,
1604 uint32_t *orig_value)
1606 const struct ldb_val *orig_val;
1607 uint32_t orig_uint = 0;
1608 unsigned int flags = 0;
1609 int ret;
1611 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1612 if (!orig_val || !orig_val->data) {
1613 /* add new attribute */
1614 flags = LDB_FLAG_MOD_ADD;
1616 } else {
1617 errno = 0;
1618 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1619 if (errno != 0 || orig_uint != value) {
1620 /* replace also if can't get value */
1621 flags = LDB_FLAG_MOD_REPLACE;
1625 if (flags == 0) {
1626 /* stored value is identical, nothing to change */
1627 goto done;
1630 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1631 if (ret != LDB_SUCCESS) {
1632 return NT_STATUS_NO_MEMORY;
1635 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1636 if (ret != LDB_SUCCESS) {
1637 return NT_STATUS_NO_MEMORY;
1640 done:
1641 if (orig_value) {
1642 *orig_value = orig_uint;
1644 return NT_STATUS_OK;
1647 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1648 struct ldb_context *sam_ldb,
1649 struct ldb_dn *base_dn,
1650 bool delete_user,
1651 const char *netbios_name,
1652 struct trustAuthInOutBlob *in)
1654 const char *attrs[] = { "userAccountControl", NULL };
1655 struct ldb_message **msgs;
1656 struct ldb_message *msg;
1657 uint32_t uac;
1658 uint32_t i;
1659 int ret;
1661 ret = gendb_search(sam_ldb, mem_ctx,
1662 base_dn, &msgs, attrs,
1663 "samAccountName=%s$", netbios_name);
1664 if (ret > 1) {
1665 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1668 if (ret == 0) {
1669 if (delete_user) {
1670 return NT_STATUS_OK;
1673 /* ok no existing user, add it from scratch */
1674 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1675 netbios_name, in, NULL);
1678 /* check user is what we are looking for */
1679 uac = ldb_msg_find_attr_as_uint(msgs[0],
1680 "userAccountControl", 0);
1681 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1682 return NT_STATUS_OBJECT_NAME_COLLISION;
1685 if (delete_user) {
1686 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1687 switch (ret) {
1688 case LDB_SUCCESS:
1689 return NT_STATUS_OK;
1690 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1691 return NT_STATUS_ACCESS_DENIED;
1692 default:
1693 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1697 /* entry exists, just modify secret if any */
1698 if (in == NULL || in->count == 0) {
1699 return NT_STATUS_OK;
1702 msg = ldb_msg_new(mem_ctx);
1703 if (!msg) {
1704 return NT_STATUS_NO_MEMORY;
1706 msg->dn = msgs[0]->dn;
1708 for (i = 0; i < in->count; i++) {
1709 const char *attribute;
1710 struct ldb_val v;
1711 switch (in->current.array[i].AuthType) {
1712 case TRUST_AUTH_TYPE_NT4OWF:
1713 attribute = "unicodePwd";
1714 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1715 v.length = 16;
1716 break;
1717 case TRUST_AUTH_TYPE_CLEAR:
1718 attribute = "clearTextPassword";
1719 v.data = in->current.array[i].AuthInfo.clear.password;
1720 v.length = in->current.array[i].AuthInfo.clear.size;
1721 break;
1722 default:
1723 continue;
1726 ret = ldb_msg_add_empty(msg, attribute,
1727 LDB_FLAG_MOD_REPLACE, NULL);
1728 if (ret != LDB_SUCCESS) {
1729 return NT_STATUS_NO_MEMORY;
1732 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1733 if (ret != LDB_SUCCESS) {
1734 return NT_STATUS_NO_MEMORY;
1738 /* create the trusted_domain user account */
1739 ret = ldb_modify(sam_ldb, msg);
1740 if (ret != LDB_SUCCESS) {
1741 DEBUG(0,("Failed to create user record %s: %s\n",
1742 ldb_dn_get_linearized(msg->dn),
1743 ldb_errstring(sam_ldb)));
1745 switch (ret) {
1746 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1747 return NT_STATUS_DOMAIN_EXISTS;
1748 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1749 return NT_STATUS_ACCESS_DENIED;
1750 default:
1751 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1755 return NT_STATUS_OK;
1759 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1760 struct lsa_policy_state *p_state,
1761 TALLOC_CTX *mem_ctx,
1762 struct ldb_message *dom_msg,
1763 enum lsa_TrustDomInfoEnum level,
1764 union lsa_TrustedDomainInfo *info)
1766 uint32_t *posix_offset = NULL;
1767 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1768 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1769 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1770 uint32_t *enc_types = NULL;
1771 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1772 struct trustDomainPasswords auth_struct;
1773 struct trustAuthInOutBlob *current_passwords = NULL;
1774 NTSTATUS nt_status;
1775 struct ldb_message **msgs;
1776 struct ldb_message *msg;
1777 bool add_outgoing = false;
1778 bool add_incoming = false;
1779 bool del_outgoing = false;
1780 bool del_incoming = false;
1781 bool del_forest_info = false;
1782 bool in_transaction = false;
1783 int ret;
1784 bool am_rodc;
1786 switch (level) {
1787 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1788 posix_offset = &info->posix_offset.posix_offset;
1789 break;
1790 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1791 info_ex = &info->info_ex;
1792 break;
1793 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1794 auth_info = &info->auth_info;
1795 break;
1796 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1797 posix_offset = &info->full_info.posix_offset.posix_offset;
1798 info_ex = &info->full_info.info_ex;
1799 auth_info = &info->full_info.auth_info;
1800 break;
1801 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1802 auth_info_int = &info->auth_info_internal;
1803 break;
1804 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1805 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1806 info_ex = &info->full_info_internal.info_ex;
1807 auth_info_int = &info->full_info_internal.auth_info;
1808 break;
1809 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1810 enc_types = &info->enc_types.enc_types;
1811 break;
1812 default:
1813 return NT_STATUS_INVALID_PARAMETER;
1816 if (auth_info) {
1817 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1818 &trustAuthIncoming,
1819 &trustAuthOutgoing);
1820 if (!NT_STATUS_IS_OK(nt_status)) {
1821 return nt_status;
1823 if (trustAuthIncoming.data) {
1824 /* This does the decode of some of this twice, but it is easier that way */
1825 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1826 auth_info->incoming_count,
1827 auth_info->incoming_current_auth_info,
1828 NULL,
1829 &current_passwords);
1830 if (!NT_STATUS_IS_OK(nt_status)) {
1831 return nt_status;
1836 /* decode auth_info_int if set */
1837 if (auth_info_int) {
1839 /* now decrypt blob */
1840 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1841 auth_info_int->auth_blob.size);
1843 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1844 &auth_blob, &auth_struct);
1845 if (!NT_STATUS_IS_OK(nt_status)) {
1846 return nt_status;
1850 if (info_ex) {
1851 /* verify data matches */
1852 if (info_ex->trust_attributes &
1853 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1854 /* TODO: check what behavior level we have */
1855 if (strcasecmp_m(p_state->domain_dns,
1856 p_state->forest_dns) != 0) {
1857 return NT_STATUS_INVALID_DOMAIN_STATE;
1861 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1862 if (ret == LDB_SUCCESS && am_rodc) {
1863 return NT_STATUS_NO_SUCH_DOMAIN;
1866 /* verify only one object matches the dns/netbios/sid
1867 * triplet and that this is the one we already have */
1868 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1869 p_state->system_dn,
1870 info_ex->domain_name.string,
1871 info_ex->netbios_name.string,
1872 info_ex->sid, &msgs);
1873 if (!NT_STATUS_IS_OK(nt_status)) {
1874 return nt_status;
1876 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1877 return NT_STATUS_OBJECT_NAME_COLLISION;
1879 talloc_free(msgs);
1882 /* TODO: should we fetch previous values from the existing entry
1883 * and append them ? */
1884 if (auth_info_int && auth_struct.incoming.count) {
1885 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1886 &auth_struct.incoming,
1887 &trustAuthIncoming);
1888 if (!NT_STATUS_IS_OK(nt_status)) {
1889 return nt_status;
1892 current_passwords = &auth_struct.incoming;
1894 } else {
1895 trustAuthIncoming = data_blob(NULL, 0);
1898 if (auth_info_int && auth_struct.outgoing.count) {
1899 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1900 &auth_struct.outgoing,
1901 &trustAuthOutgoing);
1902 if (!NT_STATUS_IS_OK(nt_status)) {
1903 return nt_status;
1905 } else {
1906 trustAuthOutgoing = data_blob(NULL, 0);
1909 msg = ldb_msg_new(mem_ctx);
1910 if (msg == NULL) {
1911 return NT_STATUS_NO_MEMORY;
1913 msg->dn = dom_msg->dn;
1915 if (posix_offset) {
1916 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1917 dom_msg, msg,
1918 "trustPosixOffset",
1919 *posix_offset, NULL);
1920 if (!NT_STATUS_IS_OK(nt_status)) {
1921 return nt_status;
1925 if (info_ex) {
1926 uint32_t origattrs;
1927 uint32_t changed_attrs;
1928 uint32_t origdir;
1929 int origtype;
1931 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1932 dom_msg, msg,
1933 "trustDirection",
1934 info_ex->trust_direction,
1935 &origdir);
1936 if (!NT_STATUS_IS_OK(nt_status)) {
1937 return nt_status;
1940 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1941 if (auth_info != NULL && trustAuthIncoming.length > 0) {
1942 add_incoming = true;
1945 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1946 if (auth_info != NULL && trustAuthOutgoing.length > 0) {
1947 add_outgoing = true;
1951 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1952 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1953 del_incoming = true;
1955 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1956 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1957 del_outgoing = true;
1960 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1961 if (origtype == -1 || origtype != info_ex->trust_type) {
1962 DEBUG(1, ("Attempted to change trust type! "
1963 "Operation not handled\n"));
1964 return NT_STATUS_INVALID_PARAMETER;
1967 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1968 dom_msg, msg,
1969 "trustAttributes",
1970 info_ex->trust_attributes,
1971 &origattrs);
1972 if (!NT_STATUS_IS_OK(nt_status)) {
1973 return nt_status;
1975 /* TODO: check forestFunctionality from ldb opaque */
1976 /* TODO: check what is set makes sense */
1978 changed_attrs = origattrs ^ info_ex->trust_attributes;
1979 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1981 * For now we only allow
1982 * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
1984 * TODO: we may need to support more attribute changes
1986 DEBUG(1, ("Attempted to change trust attributes "
1987 "(0x%08x != 0x%08x)! "
1988 "Operation not handled yet...\n",
1989 (unsigned)origattrs,
1990 (unsigned)info_ex->trust_attributes));
1991 return NT_STATUS_INVALID_PARAMETER;
1994 if (!(info_ex->trust_attributes &
1995 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
1997 struct ldb_message_element *orig_forest_el = NULL;
1999 orig_forest_el = ldb_msg_find_element(dom_msg,
2000 "msDS-TrustForestTrustInfo");
2001 if (orig_forest_el != NULL) {
2002 del_forest_info = true;
2007 if (enc_types) {
2008 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2009 dom_msg, msg,
2010 "msDS-SupportedEncryptionTypes",
2011 *enc_types, NULL);
2012 if (!NT_STATUS_IS_OK(nt_status)) {
2013 return nt_status;
2017 if (add_incoming || del_incoming) {
2018 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
2019 LDB_FLAG_MOD_REPLACE, NULL);
2020 if (ret != LDB_SUCCESS) {
2021 return NT_STATUS_NO_MEMORY;
2023 if (add_incoming) {
2024 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
2025 &trustAuthIncoming, NULL);
2026 if (ret != LDB_SUCCESS) {
2027 return NT_STATUS_NO_MEMORY;
2031 if (add_outgoing || del_outgoing) {
2032 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2033 LDB_FLAG_MOD_REPLACE, NULL);
2034 if (ret != LDB_SUCCESS) {
2035 return NT_STATUS_NO_MEMORY;
2037 if (add_outgoing) {
2038 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
2039 &trustAuthOutgoing, NULL);
2040 if (ret != LDB_SUCCESS) {
2041 return NT_STATUS_NO_MEMORY;
2045 if (del_forest_info) {
2046 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
2047 LDB_FLAG_MOD_REPLACE, NULL);
2048 if (ret != LDB_SUCCESS) {
2049 return NT_STATUS_NO_MEMORY;
2053 /* start transaction */
2054 ret = ldb_transaction_start(p_state->sam_ldb);
2055 if (ret != LDB_SUCCESS) {
2056 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2058 in_transaction = true;
2060 if (msg->num_elements) {
2061 ret = ldb_modify(p_state->sam_ldb, msg);
2062 if (ret != LDB_SUCCESS) {
2063 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
2064 ldb_dn_get_linearized(msg->dn),
2065 ldb_errstring(p_state->sam_ldb)));
2066 nt_status = dsdb_ldb_err_to_ntstatus(ret);
2067 goto done;
2071 if (add_incoming || del_incoming) {
2072 const char *netbios_name;
2074 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
2075 "flatname", NULL);
2076 if (!netbios_name) {
2077 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
2078 goto done;
2081 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
2082 nt_status = update_trust_user(mem_ctx,
2083 p_state->sam_ldb,
2084 p_state->domain_dn,
2085 del_incoming,
2086 netbios_name,
2087 current_passwords);
2088 if (!NT_STATUS_IS_OK(nt_status)) {
2089 goto done;
2093 /* ok, all fine, commit transaction and return */
2094 ret = ldb_transaction_commit(p_state->sam_ldb);
2095 if (ret != LDB_SUCCESS) {
2096 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2098 in_transaction = false;
2100 nt_status = NT_STATUS_OK;
2102 done:
2103 if (in_transaction) {
2104 ldb_transaction_cancel(p_state->sam_ldb);
2106 return nt_status;
2110 lsa_SetInfomrationTrustedDomain
2112 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
2113 struct dcesrv_call_state *dce_call,
2114 TALLOC_CTX *mem_ctx,
2115 struct lsa_SetInformationTrustedDomain *r)
2117 struct dcesrv_handle *h;
2118 struct lsa_trusted_domain_state *td_state;
2119 struct ldb_message **msgs;
2120 NTSTATUS nt_status;
2122 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
2123 LSA_HANDLE_TRUSTED_DOMAIN);
2125 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2127 /* get the trusted domain object */
2128 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
2129 td_state->trusted_domain_dn,
2130 NULL, NULL, NULL, &msgs);
2131 if (!NT_STATUS_IS_OK(nt_status)) {
2132 if (NT_STATUS_EQUAL(nt_status,
2133 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2134 return nt_status;
2136 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2139 return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
2140 msgs[0], r->in.level, r->in.info);
2145 lsa_DeleteTrustedDomain
2147 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2148 struct lsa_DeleteTrustedDomain *r)
2150 NTSTATUS status;
2151 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2152 struct lsa_DeleteObject del;
2153 struct dcesrv_handle *h;
2155 opn.in.handle = r->in.handle;
2156 opn.in.sid = r->in.dom_sid;
2157 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2158 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2159 if (!opn.out.trustdom_handle) {
2160 return NT_STATUS_NO_MEMORY;
2162 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2163 if (!NT_STATUS_IS_OK(status)) {
2164 return status;
2167 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2168 talloc_steal(mem_ctx, h);
2170 del.in.handle = opn.out.trustdom_handle;
2171 del.out.handle = opn.out.trustdom_handle;
2172 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2173 if (!NT_STATUS_IS_OK(status)) {
2174 return status;
2176 return NT_STATUS_OK;
2179 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2180 struct ldb_message *msg,
2181 struct lsa_TrustDomainInfoInfoEx *info_ex)
2183 info_ex->domain_name.string
2184 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2185 info_ex->netbios_name.string
2186 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2187 info_ex->sid
2188 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2189 info_ex->trust_direction
2190 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2191 info_ex->trust_type
2192 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2193 info_ex->trust_attributes
2194 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2195 return NT_STATUS_OK;
2199 lsa_QueryTrustedDomainInfo
2201 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2202 struct lsa_QueryTrustedDomainInfo *r)
2204 union lsa_TrustedDomainInfo *info = NULL;
2205 struct dcesrv_handle *h;
2206 struct lsa_trusted_domain_state *trusted_domain_state;
2207 struct ldb_message *msg;
2208 int ret;
2209 struct ldb_message **res;
2210 const char *attrs[] = {
2211 "flatname",
2212 "trustPartner",
2213 "securityIdentifier",
2214 "trustDirection",
2215 "trustType",
2216 "trustAttributes",
2217 "msDs-supportedEncryptionTypes",
2218 NULL
2221 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2223 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2225 /* pull all the user attributes */
2226 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2227 trusted_domain_state->trusted_domain_dn, &res, attrs);
2228 if (ret != 1) {
2229 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2231 msg = res[0];
2233 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2234 if (!info) {
2235 return NT_STATUS_NO_MEMORY;
2237 *r->out.info = info;
2239 switch (r->in.level) {
2240 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2241 info->name.netbios_name.string
2242 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2243 break;
2244 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2245 info->posix_offset.posix_offset
2246 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2247 break;
2248 #if 0 /* Win2k3 doesn't implement this */
2249 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2250 r->out.info->info_basic.netbios_name.string
2251 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2252 r->out.info->info_basic.sid
2253 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2254 break;
2255 #endif
2256 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2257 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2259 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2260 ZERO_STRUCT(info->full_info);
2261 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2262 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2263 ZERO_STRUCT(info->full_info2_internal);
2264 info->full_info2_internal.posix_offset.posix_offset
2265 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2266 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2268 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2269 info->enc_types.enc_types
2270 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2271 break;
2273 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2274 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2275 /* oops, we don't want to return the info after all */
2276 talloc_free(info);
2277 *r->out.info = NULL;
2278 return NT_STATUS_INVALID_PARAMETER;
2279 default:
2280 /* oops, we don't want to return the info after all */
2281 talloc_free(info);
2282 *r->out.info = NULL;
2283 return NT_STATUS_INVALID_INFO_CLASS;
2286 return NT_STATUS_OK;
2291 lsa_QueryTrustedDomainInfoBySid
2293 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2294 struct lsa_QueryTrustedDomainInfoBySid *r)
2296 NTSTATUS status;
2297 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2298 struct lsa_QueryTrustedDomainInfo query;
2299 struct dcesrv_handle *h;
2301 opn.in.handle = r->in.handle;
2302 opn.in.sid = r->in.dom_sid;
2303 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2304 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2305 if (!opn.out.trustdom_handle) {
2306 return NT_STATUS_NO_MEMORY;
2308 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2309 if (!NT_STATUS_IS_OK(status)) {
2310 return status;
2313 /* Ensure this handle goes away at the end of this call */
2314 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2315 talloc_steal(mem_ctx, h);
2317 query.in.trustdom_handle = opn.out.trustdom_handle;
2318 query.in.level = r->in.level;
2319 query.out.info = r->out.info;
2320 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2321 if (!NT_STATUS_IS_OK(status)) {
2322 return status;
2325 return NT_STATUS_OK;
2329 lsa_SetTrustedDomainInfoByName
2331 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2332 TALLOC_CTX *mem_ctx,
2333 struct lsa_SetTrustedDomainInfoByName *r)
2335 struct dcesrv_handle *policy_handle;
2336 struct lsa_policy_state *policy_state;
2337 struct ldb_message **msgs;
2338 NTSTATUS nt_status;
2340 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2341 policy_state = policy_handle->data;
2343 /* get the trusted domain object */
2344 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2345 policy_state->domain_dn,
2346 r->in.trusted_domain->string,
2347 r->in.trusted_domain->string,
2348 NULL, &msgs);
2349 if (!NT_STATUS_IS_OK(nt_status)) {
2350 if (NT_STATUS_EQUAL(nt_status,
2351 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2352 return nt_status;
2354 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2357 return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2358 msgs[0], r->in.level, r->in.info);
2362 lsa_QueryTrustedDomainInfoByName
2364 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2365 TALLOC_CTX *mem_ctx,
2366 struct lsa_QueryTrustedDomainInfoByName *r)
2368 NTSTATUS status;
2369 struct lsa_OpenTrustedDomainByName opn = {{0},{0}};
2370 struct lsa_QueryTrustedDomainInfo query;
2371 struct dcesrv_handle *h;
2373 opn.in.handle = r->in.handle;
2374 opn.in.name = *r->in.trusted_domain;
2375 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2376 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2377 if (!opn.out.trustdom_handle) {
2378 return NT_STATUS_NO_MEMORY;
2380 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2381 if (!NT_STATUS_IS_OK(status)) {
2382 return status;
2385 /* Ensure this handle goes away at the end of this call */
2386 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2387 talloc_steal(mem_ctx, h);
2389 query.in.trustdom_handle = opn.out.trustdom_handle;
2390 query.in.level = r->in.level;
2391 query.out.info = r->out.info;
2392 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2393 if (!NT_STATUS_IS_OK(status)) {
2394 return status;
2397 return NT_STATUS_OK;
2401 lsa_CloseTrustedDomainEx
2403 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2404 TALLOC_CTX *mem_ctx,
2405 struct lsa_CloseTrustedDomainEx *r)
2407 /* The result of a bad hair day from an IDL programmer? Not
2408 * implmented in Win2k3. You should always just lsa_Close
2409 * anyway. */
2410 return NT_STATUS_NOT_IMPLEMENTED;
2415 comparison function for sorting lsa_DomainInformation array
2417 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2419 return strcasecmp_m(e1->name.string, e2->name.string);
2423 lsa_EnumTrustDom
2425 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2426 struct lsa_EnumTrustDom *r)
2428 struct dcesrv_handle *policy_handle;
2429 struct lsa_DomainInfo *entries;
2430 struct lsa_policy_state *policy_state;
2431 struct ldb_message **domains;
2432 const char *attrs[] = {
2433 "flatname",
2434 "securityIdentifier",
2435 NULL
2439 int count, i;
2441 *r->out.resume_handle = 0;
2443 r->out.domains->domains = NULL;
2444 r->out.domains->count = 0;
2446 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2448 policy_state = policy_handle->data;
2450 /* search for all users in this domain. This could possibly be cached and
2451 resumed based on resume_key */
2452 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2453 "objectclass=trustedDomain");
2454 if (count < 0) {
2455 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2458 /* convert to lsa_TrustInformation format */
2459 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2460 if (!entries) {
2461 return NT_STATUS_NO_MEMORY;
2463 for (i=0;i<count;i++) {
2464 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2465 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2468 /* sort the results by name */
2469 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2471 if (*r->in.resume_handle >= count) {
2472 *r->out.resume_handle = -1;
2474 return NT_STATUS_NO_MORE_ENTRIES;
2477 /* return the rest, limit by max_size. Note that we
2478 use the w2k3 element size value of 60 */
2479 r->out.domains->count = count - *r->in.resume_handle;
2480 r->out.domains->count = MIN(r->out.domains->count,
2481 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2483 r->out.domains->domains = entries + *r->in.resume_handle;
2484 r->out.domains->count = r->out.domains->count;
2486 if (r->out.domains->count < count - *r->in.resume_handle) {
2487 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2488 return STATUS_MORE_ENTRIES;
2491 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2492 * always be larger than the previous input resume handle, in
2493 * particular when hitting the last query it is vital to set the
2494 * resume handle correctly to avoid infinite client loops, as
2495 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2496 * status is NT_STATUS_OK - gd */
2498 *r->out.resume_handle = (uint32_t)-1;
2500 return NT_STATUS_OK;
2504 comparison function for sorting lsa_DomainInformation array
2506 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2508 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2512 lsa_EnumTrustedDomainsEx
2514 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2515 struct lsa_EnumTrustedDomainsEx *r)
2517 struct dcesrv_handle *policy_handle;
2518 struct lsa_TrustDomainInfoInfoEx *entries;
2519 struct lsa_policy_state *policy_state;
2520 struct ldb_message **domains;
2521 const char *attrs[] = {
2522 "flatname",
2523 "trustPartner",
2524 "securityIdentifier",
2525 "trustDirection",
2526 "trustType",
2527 "trustAttributes",
2528 NULL
2530 NTSTATUS nt_status;
2532 int count, i;
2534 *r->out.resume_handle = 0;
2536 r->out.domains->domains = NULL;
2537 r->out.domains->count = 0;
2539 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2541 policy_state = policy_handle->data;
2543 /* search for all users in this domain. This could possibly be cached and
2544 resumed based on resume_key */
2545 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2546 "objectclass=trustedDomain");
2547 if (count < 0) {
2548 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2551 /* convert to lsa_DomainInformation format */
2552 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2553 if (!entries) {
2554 return NT_STATUS_NO_MEMORY;
2556 for (i=0;i<count;i++) {
2557 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2558 if (!NT_STATUS_IS_OK(nt_status)) {
2559 return nt_status;
2563 /* sort the results by name */
2564 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2566 if (*r->in.resume_handle >= count) {
2567 *r->out.resume_handle = -1;
2569 return NT_STATUS_NO_MORE_ENTRIES;
2572 /* return the rest, limit by max_size. Note that we
2573 use the w2k3 element size value of 60 */
2574 r->out.domains->count = count - *r->in.resume_handle;
2575 r->out.domains->count = MIN(r->out.domains->count,
2576 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2578 r->out.domains->domains = entries + *r->in.resume_handle;
2579 r->out.domains->count = r->out.domains->count;
2581 if (r->out.domains->count < count - *r->in.resume_handle) {
2582 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2583 return STATUS_MORE_ENTRIES;
2586 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2588 return NT_STATUS_OK;
2593 lsa_OpenAccount
2595 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2596 struct lsa_OpenAccount *r)
2598 struct dcesrv_handle *h, *ah;
2599 struct lsa_policy_state *state;
2600 struct lsa_account_state *astate;
2602 ZERO_STRUCTP(r->out.acct_handle);
2604 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2606 state = h->data;
2608 astate = talloc(dce_call->conn, struct lsa_account_state);
2609 if (astate == NULL) {
2610 return NT_STATUS_NO_MEMORY;
2613 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2614 if (astate->account_sid == NULL) {
2615 talloc_free(astate);
2616 return NT_STATUS_NO_MEMORY;
2619 astate->policy = talloc_reference(astate, state);
2620 astate->access_mask = r->in.access_mask;
2623 * For now we grant all requested access.
2625 * We will fail at the ldb layer later.
2627 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2628 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2629 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2631 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2633 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2634 __func__, dom_sid_string(mem_ctx, astate->account_sid),
2635 (unsigned)r->in.access_mask,
2636 (unsigned)astate->access_mask));
2638 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2639 if (!ah) {
2640 talloc_free(astate);
2641 return NT_STATUS_NO_MEMORY;
2644 ah->data = talloc_steal(ah, astate);
2646 *r->out.acct_handle = ah->wire_handle;
2648 return NT_STATUS_OK;
2653 lsa_EnumPrivsAccount
2655 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2656 TALLOC_CTX *mem_ctx,
2657 struct lsa_EnumPrivsAccount *r)
2659 struct dcesrv_handle *h;
2660 struct lsa_account_state *astate;
2661 int ret;
2662 unsigned int i, j;
2663 struct ldb_message **res;
2664 const char * const attrs[] = { "privilege", NULL};
2665 struct ldb_message_element *el;
2666 const char *sidstr;
2667 struct lsa_PrivilegeSet *privs;
2669 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2671 astate = h->data;
2673 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2674 if (privs == NULL) {
2675 return NT_STATUS_NO_MEMORY;
2677 privs->count = 0;
2678 privs->unknown = 0;
2679 privs->set = NULL;
2681 *r->out.privs = privs;
2683 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2684 if (sidstr == NULL) {
2685 return NT_STATUS_NO_MEMORY;
2688 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2689 "objectSid=%s", sidstr);
2690 if (ret < 0) {
2691 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2693 if (ret != 1) {
2694 return NT_STATUS_OK;
2697 el = ldb_msg_find_element(res[0], "privilege");
2698 if (el == NULL || el->num_values == 0) {
2699 return NT_STATUS_OK;
2702 privs->set = talloc_array(privs,
2703 struct lsa_LUIDAttribute, el->num_values);
2704 if (privs->set == NULL) {
2705 return NT_STATUS_NO_MEMORY;
2708 j = 0;
2709 for (i=0;i<el->num_values;i++) {
2710 int id = sec_privilege_id((const char *)el->values[i].data);
2711 if (id == SEC_PRIV_INVALID) {
2712 /* Perhaps an account right, not a privilege */
2713 continue;
2715 privs->set[j].attribute = 0;
2716 privs->set[j].luid.low = id;
2717 privs->set[j].luid.high = 0;
2718 j++;
2721 privs->count = j;
2723 return NT_STATUS_OK;
2727 lsa_EnumAccountRights
2729 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2730 TALLOC_CTX *mem_ctx,
2731 struct lsa_EnumAccountRights *r)
2733 struct dcesrv_handle *h;
2734 struct lsa_policy_state *state;
2735 int ret;
2736 unsigned int i;
2737 struct ldb_message **res;
2738 const char * const attrs[] = { "privilege", NULL};
2739 const char *sidstr;
2740 struct ldb_message_element *el;
2742 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2744 state = h->data;
2746 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2747 if (sidstr == NULL) {
2748 return NT_STATUS_NO_MEMORY;
2751 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2752 "(&(objectSid=%s)(privilege=*))", sidstr);
2753 if (ret == 0) {
2754 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2756 if (ret != 1) {
2757 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2758 dom_sid_string(mem_ctx, r->in.sid),
2759 ldb_errstring(state->pdb)));
2760 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2763 el = ldb_msg_find_element(res[0], "privilege");
2764 if (el == NULL || el->num_values == 0) {
2765 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2768 r->out.rights->count = el->num_values;
2769 r->out.rights->names = talloc_array(r->out.rights,
2770 struct lsa_StringLarge, r->out.rights->count);
2771 if (r->out.rights->names == NULL) {
2772 return NT_STATUS_NO_MEMORY;
2775 for (i=0;i<el->num_values;i++) {
2776 r->out.rights->names[i].string = (const char *)el->values[i].data;
2779 return NT_STATUS_OK;
2785 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2787 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2788 TALLOC_CTX *mem_ctx,
2789 struct lsa_policy_state *state,
2790 int ldb_flag,
2791 struct dom_sid *sid,
2792 const struct lsa_RightSet *rights)
2794 const char *sidstr, *sidndrstr;
2795 struct ldb_message *msg;
2796 struct ldb_message_element *el;
2797 int ret;
2798 uint32_t i;
2799 struct lsa_EnumAccountRights r2;
2800 char *dnstr;
2802 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2803 SECURITY_ADMINISTRATOR) {
2804 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2805 return NT_STATUS_ACCESS_DENIED;
2808 msg = ldb_msg_new(mem_ctx);
2809 if (msg == NULL) {
2810 return NT_STATUS_NO_MEMORY;
2813 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2814 if (sidndrstr == NULL) {
2815 TALLOC_FREE(msg);
2816 return NT_STATUS_NO_MEMORY;
2819 sidstr = dom_sid_string(msg, sid);
2820 if (sidstr == NULL) {
2821 TALLOC_FREE(msg);
2822 return NT_STATUS_NO_MEMORY;
2825 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2826 if (dnstr == NULL) {
2827 TALLOC_FREE(msg);
2828 return NT_STATUS_NO_MEMORY;
2831 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2832 if (msg->dn == NULL) {
2833 TALLOC_FREE(msg);
2834 return NT_STATUS_NO_MEMORY;
2837 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2838 NTSTATUS status;
2840 r2.in.handle = &state->handle->wire_handle;
2841 r2.in.sid = sid;
2842 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2844 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2845 if (!NT_STATUS_IS_OK(status)) {
2846 ZERO_STRUCTP(r2.out.rights);
2850 for (i=0;i<rights->count;i++) {
2851 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2852 if (sec_right_bit(rights->names[i].string) == 0) {
2853 talloc_free(msg);
2854 return NT_STATUS_NO_SUCH_PRIVILEGE;
2857 talloc_free(msg);
2858 return NT_STATUS_NO_SUCH_PRIVILEGE;
2861 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2862 uint32_t j;
2863 for (j=0;j<r2.out.rights->count;j++) {
2864 if (strcasecmp_m(r2.out.rights->names[j].string,
2865 rights->names[i].string) == 0) {
2866 break;
2869 if (j != r2.out.rights->count) continue;
2872 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2873 if (ret != LDB_SUCCESS) {
2874 talloc_free(msg);
2875 return NT_STATUS_NO_MEMORY;
2879 el = ldb_msg_find_element(msg, "privilege");
2880 if (!el) {
2881 talloc_free(msg);
2882 return NT_STATUS_OK;
2885 el->flags = ldb_flag;
2887 ret = ldb_modify(state->pdb, msg);
2888 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2889 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2890 talloc_free(msg);
2891 return NT_STATUS_NO_MEMORY;
2893 ldb_msg_add_string(msg, "comment", "added via LSA");
2894 ret = ldb_add(state->pdb, msg);
2896 if (ret != LDB_SUCCESS) {
2897 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2898 talloc_free(msg);
2899 return NT_STATUS_OK;
2901 DEBUG(3, ("Could not %s attributes from %s: %s",
2902 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2903 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2904 talloc_free(msg);
2905 return NT_STATUS_UNEXPECTED_IO_ERROR;
2908 talloc_free(msg);
2909 return NT_STATUS_OK;
2913 lsa_AddPrivilegesToAccount
2915 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2916 struct lsa_AddPrivilegesToAccount *r)
2918 struct lsa_RightSet rights;
2919 struct dcesrv_handle *h;
2920 struct lsa_account_state *astate;
2921 uint32_t i;
2923 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2925 astate = h->data;
2927 rights.count = r->in.privs->count;
2928 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2929 if (rights.names == NULL) {
2930 return NT_STATUS_NO_MEMORY;
2932 for (i=0;i<rights.count;i++) {
2933 int id = r->in.privs->set[i].luid.low;
2934 if (r->in.privs->set[i].luid.high) {
2935 return NT_STATUS_NO_SUCH_PRIVILEGE;
2937 rights.names[i].string = sec_privilege_name(id);
2938 if (rights.names[i].string == NULL) {
2939 return NT_STATUS_NO_SUCH_PRIVILEGE;
2943 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2944 LDB_FLAG_MOD_ADD, astate->account_sid,
2945 &rights);
2950 lsa_RemovePrivilegesFromAccount
2952 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2953 struct lsa_RemovePrivilegesFromAccount *r)
2955 struct lsa_RightSet *rights;
2956 struct dcesrv_handle *h;
2957 struct lsa_account_state *astate;
2958 uint32_t i;
2960 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2962 astate = h->data;
2964 rights = talloc(mem_ctx, struct lsa_RightSet);
2966 if (r->in.remove_all == 1 &&
2967 r->in.privs == NULL) {
2968 struct lsa_EnumAccountRights r2;
2969 NTSTATUS status;
2971 r2.in.handle = &astate->policy->handle->wire_handle;
2972 r2.in.sid = astate->account_sid;
2973 r2.out.rights = rights;
2975 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2976 if (!NT_STATUS_IS_OK(status)) {
2977 return status;
2980 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2981 LDB_FLAG_MOD_DELETE, astate->account_sid,
2982 r2.out.rights);
2985 if (r->in.remove_all != 0) {
2986 return NT_STATUS_INVALID_PARAMETER;
2989 rights->count = r->in.privs->count;
2990 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2991 if (rights->names == NULL) {
2992 return NT_STATUS_NO_MEMORY;
2994 for (i=0;i<rights->count;i++) {
2995 int id = r->in.privs->set[i].luid.low;
2996 if (r->in.privs->set[i].luid.high) {
2997 return NT_STATUS_NO_SUCH_PRIVILEGE;
2999 rights->names[i].string = sec_privilege_name(id);
3000 if (rights->names[i].string == NULL) {
3001 return NT_STATUS_NO_SUCH_PRIVILEGE;
3005 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3006 LDB_FLAG_MOD_DELETE, astate->account_sid,
3007 rights);
3012 lsa_GetQuotasForAccount
3014 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3015 struct lsa_GetQuotasForAccount *r)
3017 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3022 lsa_SetQuotasForAccount
3024 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3025 struct lsa_SetQuotasForAccount *r)
3027 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3032 lsa_GetSystemAccessAccount
3034 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3035 struct lsa_GetSystemAccessAccount *r)
3037 struct dcesrv_handle *h;
3038 struct lsa_account_state *astate;
3039 int ret;
3040 unsigned int i;
3041 struct ldb_message **res;
3042 const char * const attrs[] = { "privilege", NULL};
3043 struct ldb_message_element *el;
3044 const char *sidstr;
3046 *(r->out.access_mask) = 0x00000000;
3048 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3050 astate = h->data;
3052 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
3053 if (sidstr == NULL) {
3054 return NT_STATUS_NO_MEMORY;
3057 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
3058 "objectSid=%s", sidstr);
3059 if (ret < 0) {
3060 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3062 if (ret != 1) {
3063 return NT_STATUS_OK;
3066 el = ldb_msg_find_element(res[0], "privilege");
3067 if (el == NULL || el->num_values == 0) {
3068 return NT_STATUS_OK;
3071 for (i=0;i<el->num_values;i++) {
3072 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
3073 if (right_bit == 0) {
3074 /* Perhaps an privilege, not a right */
3075 continue;
3077 *(r->out.access_mask) |= right_bit;
3080 return NT_STATUS_OK;
3085 lsa_SetSystemAccessAccount
3087 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3088 struct lsa_SetSystemAccessAccount *r)
3090 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3095 lsa_CreateSecret
3097 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3098 struct lsa_CreateSecret *r)
3100 struct dcesrv_handle *policy_handle;
3101 struct lsa_policy_state *policy_state;
3102 struct lsa_secret_state *secret_state;
3103 struct dcesrv_handle *handle;
3104 struct ldb_message **msgs, *msg;
3105 const char *attrs[] = {
3106 NULL
3109 const char *name;
3111 int ret;
3113 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3114 ZERO_STRUCTP(r->out.sec_handle);
3116 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3118 case SECURITY_SYSTEM:
3119 case SECURITY_ADMINISTRATOR:
3120 break;
3121 default:
3122 /* Users and annonymous are not allowed create secrets */
3123 return NT_STATUS_ACCESS_DENIED;
3126 policy_state = policy_handle->data;
3128 if (!r->in.name.string) {
3129 return NT_STATUS_INVALID_PARAMETER;
3132 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3133 NT_STATUS_HAVE_NO_MEMORY(secret_state);
3134 secret_state->policy = policy_state;
3136 msg = ldb_msg_new(mem_ctx);
3137 if (msg == NULL) {
3138 return NT_STATUS_NO_MEMORY;
3141 if (strncmp("G$", r->in.name.string, 2) == 0) {
3142 const char *name2;
3144 secret_state->global = true;
3146 name = &r->in.name.string[2];
3147 if (strlen(name) == 0) {
3148 return NT_STATUS_INVALID_PARAMETER;
3151 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3152 ldb_binary_encode_string(mem_ctx, name));
3153 NT_STATUS_HAVE_NO_MEMORY(name2);
3155 /* We need to connect to the database as system, as this is one
3156 * of the rare RPC calls that must read the secrets (and this
3157 * is denied otherwise) */
3158 secret_state->sam_ldb = talloc_reference(secret_state,
3159 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));
3160 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3162 /* search for the secret record */
3163 ret = gendb_search(secret_state->sam_ldb,
3164 mem_ctx, policy_state->system_dn, &msgs, attrs,
3165 "(&(cn=%s)(objectclass=secret))",
3166 name2);
3167 if (ret > 0) {
3168 return NT_STATUS_OBJECT_NAME_COLLISION;
3171 if (ret < 0) {
3172 DEBUG(0,("Failure searching for CN=%s: %s\n",
3173 name2, ldb_errstring(secret_state->sam_ldb)));
3174 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3177 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3178 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3179 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3180 return NT_STATUS_NO_MEMORY;
3183 ret = ldb_msg_add_string(msg, "cn", name2);
3184 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3185 } else {
3186 secret_state->global = false;
3188 name = r->in.name.string;
3189 if (strlen(name) == 0) {
3190 return NT_STATUS_INVALID_PARAMETER;
3193 secret_state->sam_ldb = talloc_reference(secret_state,
3194 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3195 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3197 /* search for the secret record */
3198 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3199 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3200 &msgs, attrs,
3201 "(&(cn=%s)(objectclass=secret))",
3202 ldb_binary_encode_string(mem_ctx, name));
3203 if (ret > 0) {
3204 return NT_STATUS_OBJECT_NAME_COLLISION;
3207 if (ret < 0) {
3208 DEBUG(0,("Failure searching for CN=%s: %s\n",
3209 name, ldb_errstring(secret_state->sam_ldb)));
3210 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3213 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3214 "cn=%s,cn=LSA Secrets", name);
3215 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3216 ret = ldb_msg_add_string(msg, "cn", name);
3217 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3220 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3221 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3223 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3224 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3226 /* create the secret */
3227 ret = ldb_add(secret_state->sam_ldb, msg);
3228 if (ret != LDB_SUCCESS) {
3229 DEBUG(0,("Failed to create secret record %s: %s\n",
3230 ldb_dn_get_linearized(msg->dn),
3231 ldb_errstring(secret_state->sam_ldb)));
3232 return NT_STATUS_ACCESS_DENIED;
3235 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3236 NT_STATUS_HAVE_NO_MEMORY(handle);
3238 handle->data = talloc_steal(handle, secret_state);
3240 secret_state->access_mask = r->in.access_mask;
3241 secret_state->policy = talloc_reference(secret_state, policy_state);
3242 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3244 *r->out.sec_handle = handle->wire_handle;
3246 return NT_STATUS_OK;
3251 lsa_OpenSecret
3253 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3254 struct lsa_OpenSecret *r)
3256 struct dcesrv_handle *policy_handle;
3258 struct lsa_policy_state *policy_state;
3259 struct lsa_secret_state *secret_state;
3260 struct dcesrv_handle *handle;
3261 struct ldb_message **msgs;
3262 const char *attrs[] = {
3263 NULL
3266 const char *name;
3268 int ret;
3270 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3271 ZERO_STRUCTP(r->out.sec_handle);
3272 policy_state = policy_handle->data;
3274 if (!r->in.name.string) {
3275 return NT_STATUS_INVALID_PARAMETER;
3278 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3280 case SECURITY_SYSTEM:
3281 case SECURITY_ADMINISTRATOR:
3282 break;
3283 default:
3284 /* Users and annonymous are not allowed to access secrets */
3285 return NT_STATUS_ACCESS_DENIED;
3288 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3289 if (!secret_state) {
3290 return NT_STATUS_NO_MEMORY;
3292 secret_state->policy = policy_state;
3294 if (strncmp("G$", r->in.name.string, 2) == 0) {
3295 name = &r->in.name.string[2];
3296 /* 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) */
3297 secret_state->sam_ldb = talloc_reference(secret_state,
3298 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));
3299 secret_state->global = true;
3301 if (strlen(name) < 1) {
3302 return NT_STATUS_INVALID_PARAMETER;
3305 /* search for the secret record */
3306 ret = gendb_search(secret_state->sam_ldb,
3307 mem_ctx, policy_state->system_dn, &msgs, attrs,
3308 "(&(cn=%s Secret)(objectclass=secret))",
3309 ldb_binary_encode_string(mem_ctx, name));
3310 if (ret == 0) {
3311 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3314 if (ret != 1) {
3315 DEBUG(0,("Found %d records matching DN %s\n", ret,
3316 ldb_dn_get_linearized(policy_state->system_dn)));
3317 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3319 } else {
3320 secret_state->global = false;
3321 secret_state->sam_ldb = talloc_reference(secret_state,
3322 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3324 name = r->in.name.string;
3325 if (strlen(name) < 1) {
3326 return NT_STATUS_INVALID_PARAMETER;
3329 /* search for the secret record */
3330 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3331 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3332 &msgs, attrs,
3333 "(&(cn=%s)(objectclass=secret))",
3334 ldb_binary_encode_string(mem_ctx, name));
3335 if (ret == 0) {
3336 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3339 if (ret != 1) {
3340 DEBUG(0,("Found %d records matching CN=%s\n",
3341 ret, ldb_binary_encode_string(mem_ctx, name)));
3342 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3346 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3348 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3349 if (!handle) {
3350 return NT_STATUS_NO_MEMORY;
3353 handle->data = talloc_steal(handle, secret_state);
3355 secret_state->access_mask = r->in.access_mask;
3356 secret_state->policy = talloc_reference(secret_state, policy_state);
3358 *r->out.sec_handle = handle->wire_handle;
3360 return NT_STATUS_OK;
3365 lsa_SetSecret
3367 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3368 struct lsa_SetSecret *r)
3371 struct dcesrv_handle *h;
3372 struct lsa_secret_state *secret_state;
3373 struct ldb_message *msg;
3374 DATA_BLOB session_key;
3375 DATA_BLOB crypt_secret, secret;
3376 struct ldb_val val;
3377 int ret;
3378 NTSTATUS status = NT_STATUS_OK;
3380 struct timeval now = timeval_current();
3381 NTTIME nt_now = timeval_to_nttime(&now);
3383 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3385 secret_state = h->data;
3387 msg = ldb_msg_new(mem_ctx);
3388 if (msg == NULL) {
3389 return NT_STATUS_NO_MEMORY;
3392 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3393 if (!msg->dn) {
3394 return NT_STATUS_NO_MEMORY;
3396 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3397 if (!NT_STATUS_IS_OK(status)) {
3398 return status;
3401 if (r->in.old_val) {
3402 /* Decrypt */
3403 crypt_secret.data = r->in.old_val->data;
3404 crypt_secret.length = r->in.old_val->size;
3406 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3407 if (!NT_STATUS_IS_OK(status)) {
3408 return status;
3411 val.data = secret.data;
3412 val.length = secret.length;
3414 /* set value */
3415 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3416 return NT_STATUS_NO_MEMORY;
3419 /* set old value mtime */
3420 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3421 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3422 return NT_STATUS_NO_MEMORY;
3425 } else {
3426 /* If the old value is not set, then migrate the
3427 * current value to the old value */
3428 const struct ldb_val *old_val;
3429 NTTIME last_set_time;
3430 struct ldb_message **res;
3431 const char *attrs[] = {
3432 "currentValue",
3433 "lastSetTime",
3434 NULL
3437 /* search for the secret record */
3438 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3439 secret_state->secret_dn, &res, attrs);
3440 if (ret == 0) {
3441 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3444 if (ret != 1) {
3445 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3446 ldb_dn_get_linearized(secret_state->secret_dn)));
3447 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3450 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3451 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3453 if (old_val) {
3454 /* set old value */
3455 if (ldb_msg_add_value(msg, "priorValue",
3456 old_val, NULL) != LDB_SUCCESS) {
3457 return NT_STATUS_NO_MEMORY;
3459 } else {
3460 if (samdb_msg_add_delete(secret_state->sam_ldb,
3461 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3462 return NT_STATUS_NO_MEMORY;
3466 /* set old value mtime */
3467 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3468 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3469 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3470 return NT_STATUS_NO_MEMORY;
3472 } else {
3473 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3474 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3475 return NT_STATUS_NO_MEMORY;
3480 if (r->in.new_val) {
3481 /* Decrypt */
3482 crypt_secret.data = r->in.new_val->data;
3483 crypt_secret.length = r->in.new_val->size;
3485 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3486 if (!NT_STATUS_IS_OK(status)) {
3487 return status;
3490 val.data = secret.data;
3491 val.length = secret.length;
3493 /* set value */
3494 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3495 return NT_STATUS_NO_MEMORY;
3498 /* set new value mtime */
3499 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3500 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3501 return NT_STATUS_NO_MEMORY;
3503 } else {
3504 /* NULL out the NEW value */
3505 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3506 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3507 return NT_STATUS_NO_MEMORY;
3509 if (samdb_msg_add_delete(secret_state->sam_ldb,
3510 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3511 return NT_STATUS_NO_MEMORY;
3515 /* modify the samdb record */
3516 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3517 if (ret != LDB_SUCCESS) {
3518 return dsdb_ldb_err_to_ntstatus(ret);
3521 return NT_STATUS_OK;
3526 lsa_QuerySecret
3528 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3529 struct lsa_QuerySecret *r)
3531 struct dcesrv_handle *h;
3532 struct lsa_secret_state *secret_state;
3533 struct ldb_message *msg;
3534 DATA_BLOB session_key;
3535 DATA_BLOB crypt_secret, secret;
3536 int ret;
3537 struct ldb_message **res;
3538 const char *attrs[] = {
3539 "currentValue",
3540 "priorValue",
3541 "lastSetTime",
3542 "priorSetTime",
3543 NULL
3546 NTSTATUS nt_status;
3548 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3550 /* Ensure user is permitted to read this... */
3551 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3553 case SECURITY_SYSTEM:
3554 case SECURITY_ADMINISTRATOR:
3555 break;
3556 default:
3557 /* Users and annonymous are not allowed to read secrets */
3558 return NT_STATUS_ACCESS_DENIED;
3561 secret_state = h->data;
3563 /* pull all the user attributes */
3564 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3565 secret_state->secret_dn, &res, attrs);
3566 if (ret != 1) {
3567 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3569 msg = res[0];
3571 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3572 if (!NT_STATUS_IS_OK(nt_status)) {
3573 return nt_status;
3576 if (r->in.old_val) {
3577 const struct ldb_val *prior_val;
3578 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3579 if (!r->out.old_val) {
3580 return NT_STATUS_NO_MEMORY;
3582 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3584 if (prior_val && prior_val->length) {
3585 secret.data = prior_val->data;
3586 secret.length = prior_val->length;
3588 /* Encrypt */
3589 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3590 if (!crypt_secret.length) {
3591 return NT_STATUS_NO_MEMORY;
3593 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3594 if (!r->out.old_val->buf) {
3595 return NT_STATUS_NO_MEMORY;
3597 r->out.old_val->buf->size = crypt_secret.length;
3598 r->out.old_val->buf->length = crypt_secret.length;
3599 r->out.old_val->buf->data = crypt_secret.data;
3603 if (r->in.old_mtime) {
3604 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3605 if (!r->out.old_mtime) {
3606 return NT_STATUS_NO_MEMORY;
3608 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3611 if (r->in.new_val) {
3612 const struct ldb_val *new_val;
3613 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3614 if (!r->out.new_val) {
3615 return NT_STATUS_NO_MEMORY;
3618 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3620 if (new_val && new_val->length) {
3621 secret.data = new_val->data;
3622 secret.length = new_val->length;
3624 /* Encrypt */
3625 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3626 if (!crypt_secret.length) {
3627 return NT_STATUS_NO_MEMORY;
3629 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3630 if (!r->out.new_val->buf) {
3631 return NT_STATUS_NO_MEMORY;
3633 r->out.new_val->buf->length = crypt_secret.length;
3634 r->out.new_val->buf->size = crypt_secret.length;
3635 r->out.new_val->buf->data = crypt_secret.data;
3639 if (r->in.new_mtime) {
3640 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3641 if (!r->out.new_mtime) {
3642 return NT_STATUS_NO_MEMORY;
3644 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3647 return NT_STATUS_OK;
3652 lsa_LookupPrivValue
3654 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3655 TALLOC_CTX *mem_ctx,
3656 struct lsa_LookupPrivValue *r)
3658 struct dcesrv_handle *h;
3659 int id;
3661 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3663 id = sec_privilege_id(r->in.name->string);
3664 if (id == SEC_PRIV_INVALID) {
3665 return NT_STATUS_NO_SUCH_PRIVILEGE;
3668 r->out.luid->low = id;
3669 r->out.luid->high = 0;
3671 return NT_STATUS_OK;
3676 lsa_LookupPrivName
3678 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3679 TALLOC_CTX *mem_ctx,
3680 struct lsa_LookupPrivName *r)
3682 struct dcesrv_handle *h;
3683 struct lsa_StringLarge *name;
3684 const char *privname;
3686 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3688 if (r->in.luid->high != 0) {
3689 return NT_STATUS_NO_SUCH_PRIVILEGE;
3692 privname = sec_privilege_name(r->in.luid->low);
3693 if (privname == NULL) {
3694 return NT_STATUS_NO_SUCH_PRIVILEGE;
3697 name = talloc(mem_ctx, struct lsa_StringLarge);
3698 if (name == NULL) {
3699 return NT_STATUS_NO_MEMORY;
3702 name->string = privname;
3704 *r->out.name = name;
3706 return NT_STATUS_OK;
3711 lsa_LookupPrivDisplayName
3713 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3714 TALLOC_CTX *mem_ctx,
3715 struct lsa_LookupPrivDisplayName *r)
3717 struct dcesrv_handle *h;
3718 struct lsa_StringLarge *disp_name = NULL;
3719 enum sec_privilege id;
3721 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3723 id = sec_privilege_id(r->in.name->string);
3724 if (id == SEC_PRIV_INVALID) {
3725 return NT_STATUS_NO_SUCH_PRIVILEGE;
3728 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3729 if (disp_name == NULL) {
3730 return NT_STATUS_NO_MEMORY;
3733 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3734 if (disp_name->string == NULL) {
3735 return NT_STATUS_INTERNAL_ERROR;
3738 *r->out.disp_name = disp_name;
3739 *r->out.returned_language_id = 0;
3741 return NT_STATUS_OK;
3746 lsa_EnumAccountsWithUserRight
3748 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3749 TALLOC_CTX *mem_ctx,
3750 struct lsa_EnumAccountsWithUserRight *r)
3752 struct dcesrv_handle *h;
3753 struct lsa_policy_state *state;
3754 int ret, i;
3755 struct ldb_message **res;
3756 const char * const attrs[] = { "objectSid", NULL};
3757 const char *privname;
3759 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3761 state = h->data;
3763 if (r->in.name == NULL) {
3764 return NT_STATUS_NO_SUCH_PRIVILEGE;
3767 privname = r->in.name->string;
3768 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3769 return NT_STATUS_NO_SUCH_PRIVILEGE;
3772 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3773 "privilege=%s", privname);
3774 if (ret < 0) {
3775 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3777 if (ret == 0) {
3778 return NT_STATUS_NO_MORE_ENTRIES;
3781 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3782 if (r->out.sids->sids == NULL) {
3783 return NT_STATUS_NO_MEMORY;
3785 for (i=0;i<ret;i++) {
3786 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3787 res[i], "objectSid");
3788 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3790 r->out.sids->num_sids = ret;
3792 return NT_STATUS_OK;
3797 lsa_AddAccountRights
3799 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3800 TALLOC_CTX *mem_ctx,
3801 struct lsa_AddAccountRights *r)
3803 struct dcesrv_handle *h;
3804 struct lsa_policy_state *state;
3806 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3808 state = h->data;
3810 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3811 LDB_FLAG_MOD_ADD,
3812 r->in.sid, r->in.rights);
3817 lsa_RemoveAccountRights
3819 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3820 TALLOC_CTX *mem_ctx,
3821 struct lsa_RemoveAccountRights *r)
3823 struct dcesrv_handle *h;
3824 struct lsa_policy_state *state;
3826 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3828 state = h->data;
3830 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3831 LDB_FLAG_MOD_DELETE,
3832 r->in.sid, r->in.rights);
3837 lsa_StorePrivateData
3839 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3840 struct lsa_StorePrivateData *r)
3842 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3847 lsa_RetrievePrivateData
3849 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3850 struct lsa_RetrievePrivateData *r)
3852 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3857 lsa_GetUserName
3859 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3860 struct lsa_GetUserName *r)
3862 enum dcerpc_transport_t transport =
3863 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3864 NTSTATUS status = NT_STATUS_OK;
3865 const char *account_name;
3866 const char *authority_name;
3867 struct lsa_String *_account_name;
3868 struct lsa_String *_authority_name = NULL;
3870 if (transport != NCACN_NP && transport != NCALRPC) {
3871 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3874 /* this is what w2k3 does */
3875 r->out.account_name = r->in.account_name;
3876 r->out.authority_name = r->in.authority_name;
3878 if (r->in.account_name
3879 && *r->in.account_name
3880 /* && *(*r->in.account_name)->string */
3882 return NT_STATUS_INVALID_PARAMETER;
3885 if (r->in.authority_name
3886 && *r->in.authority_name
3887 /* && *(*r->in.authority_name)->string */
3889 return NT_STATUS_INVALID_PARAMETER;
3892 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3893 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3895 _account_name = talloc(mem_ctx, struct lsa_String);
3896 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3897 _account_name->string = account_name;
3899 if (r->in.authority_name) {
3900 _authority_name = talloc(mem_ctx, struct lsa_String);
3901 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3902 _authority_name->string = authority_name;
3905 *r->out.account_name = _account_name;
3906 if (r->out.authority_name) {
3907 *r->out.authority_name = _authority_name;
3910 return status;
3914 lsa_SetInfoPolicy2
3916 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3917 TALLOC_CTX *mem_ctx,
3918 struct lsa_SetInfoPolicy2 *r)
3920 /* need to support these */
3921 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3924 static void kdc_get_policy(struct loadparm_context *lp_ctx,
3925 struct smb_krb5_context *smb_krb5_context,
3926 struct lsa_DomainInfoKerberos *k)
3928 time_t svc_tkt_lifetime;
3929 time_t usr_tkt_lifetime;
3930 time_t renewal_lifetime;
3932 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
3934 /* Our KDC always re-validates the client */
3935 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
3937 lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
3938 &usr_tkt_lifetime, &renewal_lifetime);
3940 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
3941 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
3942 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
3943 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
3944 However in the parent function we basically just did a full
3945 krb5_context init with the only purpose of getting a global
3946 config option (the max skew), it would probably make more sense
3947 to have a lp_ or ldb global option as the samba default */
3948 if (smb_krb5_context) {
3949 unix_to_nt_time(&k->clock_skew,
3950 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
3952 #endif
3953 k->reserved = 0;
3956 lsa_QueryDomainInformationPolicy
3958 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3959 TALLOC_CTX *mem_ctx,
3960 struct lsa_QueryDomainInformationPolicy *r)
3962 union lsa_DomainInformationPolicy *info;
3964 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3965 if (!info) {
3966 return NT_STATUS_NO_MEMORY;
3969 switch (r->in.level) {
3970 case LSA_DOMAIN_INFO_POLICY_EFS:
3971 talloc_free(info);
3972 *r->out.info = NULL;
3973 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3974 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3976 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3977 struct smb_krb5_context *smb_krb5_context;
3978 int ret = smb_krb5_init_context(mem_ctx,
3979 dce_call->conn->dce_ctx->lp_ctx,
3980 &smb_krb5_context);
3981 if (ret != 0) {
3982 talloc_free(info);
3983 *r->out.info = NULL;
3984 return NT_STATUS_INTERNAL_ERROR;
3986 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3987 smb_krb5_context,
3989 talloc_free(smb_krb5_context);
3990 *r->out.info = info;
3991 return NT_STATUS_OK;
3993 default:
3994 talloc_free(info);
3995 *r->out.info = NULL;
3996 return NT_STATUS_INVALID_INFO_CLASS;
4001 lsa_SetDomInfoPolicy
4003 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4004 TALLOC_CTX *mem_ctx,
4005 struct lsa_SetDomainInformationPolicy *r)
4007 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4011 lsa_TestCall
4013 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
4014 TALLOC_CTX *mem_ctx,
4015 struct lsa_TestCall *r)
4017 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4021 lsa_CREDRWRITE
4023 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4024 struct lsa_CREDRWRITE *r)
4026 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4031 lsa_CREDRREAD
4033 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4034 struct lsa_CREDRREAD *r)
4036 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4041 lsa_CREDRENUMERATE
4043 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4044 struct lsa_CREDRENUMERATE *r)
4046 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4051 lsa_CREDRWRITEDOMAINCREDENTIALS
4053 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4054 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
4056 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4061 lsa_CREDRREADDOMAINCREDENTIALS
4063 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4064 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
4066 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4071 lsa_CREDRDELETE
4073 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4074 struct lsa_CREDRDELETE *r)
4076 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4081 lsa_CREDRGETTARGETINFO
4083 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4084 struct lsa_CREDRGETTARGETINFO *r)
4086 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4091 lsa_CREDRPROFILELOADED
4093 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4094 struct lsa_CREDRPROFILELOADED *r)
4096 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4101 lsa_CREDRGETSESSIONTYPES
4103 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4104 struct lsa_CREDRGETSESSIONTYPES *r)
4106 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4111 lsa_LSARREGISTERAUDITEVENT
4113 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4114 struct lsa_LSARREGISTERAUDITEVENT *r)
4116 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4121 lsa_LSARGENAUDITEVENT
4123 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4124 struct lsa_LSARGENAUDITEVENT *r)
4126 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4131 lsa_LSARUNREGISTERAUDITEVENT
4133 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4134 struct lsa_LSARUNREGISTERAUDITEVENT *r)
4136 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4141 lsa_lsaRQueryForestTrustInformation
4143 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4144 struct lsa_lsaRQueryForestTrustInformation *r)
4146 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4149 #define DNS_CMP_MATCH 0
4150 #define DNS_CMP_FIRST_IS_CHILD 1
4151 #define DNS_CMP_SECOND_IS_CHILD 2
4152 #define DNS_CMP_NO_MATCH 3
4154 /* this function assumes names are well formed DNS names.
4155 * it doesn't validate them */
4156 static int dns_cmp(const char *s1, size_t l1,
4157 const char *s2, size_t l2)
4159 const char *p1, *p2;
4160 size_t t1, t2;
4161 int cret;
4163 if (l1 == l2) {
4164 if (strcasecmp_m(s1, s2) == 0) {
4165 return DNS_CMP_MATCH;
4167 return DNS_CMP_NO_MATCH;
4170 if (l1 > l2) {
4171 p1 = s1;
4172 p2 = s2;
4173 t1 = l1;
4174 t2 = l2;
4175 cret = DNS_CMP_FIRST_IS_CHILD;
4176 } else {
4177 p1 = s2;
4178 p2 = s1;
4179 t1 = l2;
4180 t2 = l1;
4181 cret = DNS_CMP_SECOND_IS_CHILD;
4184 if (p1[t1 - t2 - 1] != '.') {
4185 return DNS_CMP_NO_MATCH;
4188 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
4189 return cret;
4192 return DNS_CMP_NO_MATCH;
4195 /* decode all TDOs forest trust info blobs */
4196 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
4197 struct ldb_message *msg,
4198 struct ForestTrustInfo *info)
4200 const struct ldb_val *ft_blob;
4201 enum ndr_err_code ndr_err;
4203 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
4204 if (!ft_blob || !ft_blob->data) {
4205 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4207 /* ldb_val is equivalent to DATA_BLOB */
4208 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
4209 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
4210 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4211 return NT_STATUS_INVALID_DOMAIN_STATE;
4214 return NT_STATUS_OK;
4217 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
4218 struct ForestTrustInfo *fti)
4220 struct ForestTrustDataDomainInfo *info;
4221 struct ForestTrustInfoRecord *rec;
4223 fti->version = 1;
4224 fti->count = 2;
4225 fti->records = talloc_array(fti,
4226 struct ForestTrustInfoRecordArmor, 2);
4227 if (!fti->records) {
4228 return NT_STATUS_NO_MEMORY;
4231 /* TLN info */
4232 rec = &fti->records[0].record;
4234 rec->flags = 0;
4235 rec->timestamp = 0;
4236 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
4238 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
4239 if (!rec->data.name.string) {
4240 return NT_STATUS_NO_MEMORY;
4242 rec->data.name.size = strlen(rec->data.name.string);
4244 /* DOMAIN info */
4245 rec = &fti->records[1].record;
4247 rec->flags = 0;
4248 rec->timestamp = 0;
4249 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
4251 info = &rec->data.info;
4253 info->sid = *ps->domain_sid;
4254 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
4255 if (!info->dns_name.string) {
4256 return NT_STATUS_NO_MEMORY;
4258 info->dns_name.size = strlen(info->dns_name.string);
4259 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
4260 if (!info->netbios_name.string) {
4261 return NT_STATUS_NO_MEMORY;
4263 info->netbios_name.size = strlen(info->netbios_name.string);
4265 return NT_STATUS_OK;
4268 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
4269 struct lsa_ForestTrustInformation *lfti,
4270 struct ForestTrustInfo *fti)
4272 struct lsa_ForestTrustRecord *lrec;
4273 struct ForestTrustInfoRecord *rec;
4274 struct lsa_StringLarge *tln;
4275 struct lsa_ForestTrustDomainInfo *info;
4276 uint32_t i;
4278 fti->version = 1;
4279 fti->count = lfti->count;
4280 fti->records = talloc_array(mem_ctx,
4281 struct ForestTrustInfoRecordArmor,
4282 fti->count);
4283 if (!fti->records) {
4284 return NT_STATUS_NO_MEMORY;
4286 for (i = 0; i < fti->count; i++) {
4287 lrec = lfti->entries[i];
4288 rec = &fti->records[i].record;
4290 rec->flags = lrec->flags;
4291 rec->timestamp = lrec->time;
4292 rec->type = lrec->type;
4294 switch (lrec->type) {
4295 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4296 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4297 tln = &lrec->forest_trust_data.top_level_name;
4298 rec->data.name.string =
4299 talloc_strdup(mem_ctx, tln->string);
4300 if (!rec->data.name.string) {
4301 return NT_STATUS_NO_MEMORY;
4303 rec->data.name.size = strlen(rec->data.name.string);
4304 break;
4305 case LSA_FOREST_TRUST_DOMAIN_INFO:
4306 info = &lrec->forest_trust_data.domain_info;
4307 rec->data.info.sid = *info->domain_sid;
4308 rec->data.info.dns_name.string =
4309 talloc_strdup(mem_ctx,
4310 info->dns_domain_name.string);
4311 if (!rec->data.info.dns_name.string) {
4312 return NT_STATUS_NO_MEMORY;
4314 rec->data.info.dns_name.size =
4315 strlen(rec->data.info.dns_name.string);
4316 rec->data.info.netbios_name.string =
4317 talloc_strdup(mem_ctx,
4318 info->netbios_domain_name.string);
4319 if (!rec->data.info.netbios_name.string) {
4320 return NT_STATUS_NO_MEMORY;
4322 rec->data.info.netbios_name.size =
4323 strlen(rec->data.info.netbios_name.string);
4324 break;
4325 default:
4326 return NT_STATUS_INVALID_DOMAIN_STATE;
4330 return NT_STATUS_OK;
4333 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4334 uint32_t idx, uint32_t collision_type,
4335 uint32_t conflict_type, const char *tdo_name);
4337 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4338 const char *tdo_name,
4339 struct ForestTrustInfo *tdo_fti,
4340 struct ForestTrustInfo *new_fti,
4341 struct lsa_ForestTrustCollisionInfo *c_info)
4343 struct ForestTrustInfoRecord *nrec;
4344 struct ForestTrustInfoRecord *trec;
4345 const char *dns_name;
4346 const char *nb_name;
4347 struct dom_sid *sid = NULL;
4348 const char *tname = NULL;
4349 size_t dns_len;
4350 size_t tlen = 0;
4351 NTSTATUS nt_status = NT_STATUS_OK;
4352 uint32_t new_fti_idx;
4353 uint32_t i;
4354 /* use always TDO type, until we understand when Xref can be used */
4355 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4356 bool tln_conflict;
4357 bool sid_conflict;
4358 bool nb_conflict;
4359 bool exclusion;
4360 bool ex_rule = false;
4361 int ret;
4363 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4365 nrec = &new_fti->records[new_fti_idx].record;
4366 dns_name = NULL;
4367 nb_name = NULL;
4368 tln_conflict = false;
4369 sid_conflict = false;
4370 nb_conflict = false;
4371 exclusion = false;
4373 switch (nrec->type) {
4374 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4375 /* exclusions do not conflict by definition */
4376 break;
4378 case FOREST_TRUST_TOP_LEVEL_NAME:
4379 dns_name = nrec->data.name.string;
4380 dns_len = nrec->data.name.size;
4381 break;
4383 case LSA_FOREST_TRUST_DOMAIN_INFO:
4384 dns_name = nrec->data.info.dns_name.string;
4385 dns_len = nrec->data.info.dns_name.size;
4386 nb_name = nrec->data.info.netbios_name.string;
4387 sid = &nrec->data.info.sid;
4388 break;
4391 if (!dns_name) continue;
4393 /* check if this is already taken and not excluded */
4394 for (i = 0; i < tdo_fti->count; i++) {
4395 trec = &tdo_fti->records[i].record;
4397 switch (trec->type) {
4398 case FOREST_TRUST_TOP_LEVEL_NAME:
4399 ex_rule = false;
4400 tname = trec->data.name.string;
4401 tlen = trec->data.name.size;
4402 break;
4403 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4404 ex_rule = true;
4405 tname = trec->data.name.string;
4406 tlen = trec->data.name.size;
4407 break;
4408 case FOREST_TRUST_DOMAIN_INFO:
4409 ex_rule = false;
4410 tname = trec->data.info.dns_name.string;
4411 tlen = trec->data.info.dns_name.size;
4413 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4414 switch (ret) {
4415 case DNS_CMP_MATCH:
4416 /* if it matches exclusion,
4417 * it doesn't conflict */
4418 if (ex_rule) {
4419 exclusion = true;
4420 break;
4422 /* fall through */
4423 case DNS_CMP_FIRST_IS_CHILD:
4424 case DNS_CMP_SECOND_IS_CHILD:
4425 tln_conflict = true;
4426 /* fall through */
4427 default:
4428 break;
4431 /* explicit exclusion, no dns name conflict here */
4432 if (exclusion) {
4433 tln_conflict = false;
4436 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4437 continue;
4440 /* also test for domain info */
4441 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4442 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4443 sid_conflict = true;
4445 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4446 (nb_name != NULL) &&
4447 strcasecmp_m(trec->data.info.netbios_name.string,
4448 nb_name) == 0) {
4449 nb_conflict = true;
4453 if (tln_conflict) {
4454 nt_status = add_collision(c_info, new_fti_idx,
4455 collision_type,
4456 LSA_TLN_DISABLED_CONFLICT,
4457 tdo_name);
4458 if (!NT_STATUS_IS_OK(nt_status)) {
4459 goto done;
4462 if (sid_conflict) {
4463 nt_status = add_collision(c_info, new_fti_idx,
4464 collision_type,
4465 LSA_SID_DISABLED_CONFLICT,
4466 tdo_name);
4467 if (!NT_STATUS_IS_OK(nt_status)) {
4468 goto done;
4471 if (nb_conflict) {
4472 nt_status = add_collision(c_info, new_fti_idx,
4473 collision_type,
4474 LSA_NB_DISABLED_CONFLICT,
4475 tdo_name);
4476 if (!NT_STATUS_IS_OK(nt_status)) {
4477 goto done;
4482 done:
4483 return nt_status;
4486 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4487 uint32_t idx, uint32_t collision_type,
4488 uint32_t conflict_type, const char *tdo_name)
4490 struct lsa_ForestTrustCollisionRecord **es;
4491 uint32_t i = c_info->count;
4493 es = talloc_realloc(c_info, c_info->entries,
4494 struct lsa_ForestTrustCollisionRecord *, i + 1);
4495 if (!es) {
4496 return NT_STATUS_NO_MEMORY;
4498 c_info->entries = es;
4499 c_info->count = i + 1;
4501 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4502 if (!es[i]) {
4503 return NT_STATUS_NO_MEMORY;
4506 es[i]->index = idx;
4507 es[i]->type = collision_type;
4508 es[i]->flags = conflict_type;
4509 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4510 if (!es[i]->name.string) {
4511 return NT_STATUS_NO_MEMORY;
4513 es[i]->name.size = strlen(es[i]->name.string);
4515 return NT_STATUS_OK;
4519 lsa_lsaRSetForestTrustInformation
4521 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4522 TALLOC_CTX *mem_ctx,
4523 struct lsa_lsaRSetForestTrustInformation *r)
4525 struct dcesrv_handle *h;
4526 struct lsa_policy_state *p_state;
4527 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4528 "msDS-TrustForestTrustInfo", NULL };
4529 struct ldb_message **dom_res = NULL;
4530 struct ldb_dn *tdo_dn;
4531 struct ldb_message *msg;
4532 int num_res, i;
4533 const char *td_name;
4534 uint32_t trust_attributes;
4535 struct lsa_ForestTrustCollisionInfo *c_info;
4536 struct ForestTrustInfo *nfti;
4537 struct ForestTrustInfo *fti;
4538 DATA_BLOB ft_blob;
4539 enum ndr_err_code ndr_err;
4540 NTSTATUS nt_status;
4541 bool am_rodc;
4542 int ret;
4544 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4546 p_state = h->data;
4548 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4549 return NT_STATUS_INVALID_DOMAIN_STATE;
4552 /* abort if we are not a PDC */
4553 if (!samdb_is_pdc(p_state->sam_ldb)) {
4554 return NT_STATUS_INVALID_DOMAIN_ROLE;
4557 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4558 if (ret == LDB_SUCCESS && am_rodc) {
4559 return NT_STATUS_NO_SUCH_DOMAIN;
4562 /* check caller has TRUSTED_SET_AUTH */
4564 /* fetch all trusted domain objects */
4565 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4566 p_state->system_dn,
4567 &dom_res, trust_attrs,
4568 "(objectclass=trustedDomain)");
4569 if (num_res == 0) {
4570 return NT_STATUS_NO_SUCH_DOMAIN;
4573 for (i = 0; i < num_res; i++) {
4574 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4575 "trustPartner", NULL);
4576 if (!td_name) {
4577 return NT_STATUS_INVALID_DOMAIN_STATE;
4579 if (strcasecmp_m(td_name,
4580 r->in.trusted_domain_name->string) == 0) {
4581 break;
4584 if (i >= num_res) {
4585 return NT_STATUS_NO_SUCH_DOMAIN;
4588 tdo_dn = dom_res[i]->dn;
4590 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4591 "trustAttributes", 0);
4592 if (!(trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4593 return NT_STATUS_INVALID_PARAMETER;
4596 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4597 return NT_STATUS_INVALID_PARAMETER;
4600 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4601 if (!nfti) {
4602 return NT_STATUS_NO_MEMORY;
4605 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4606 if (!NT_STATUS_IS_OK(nt_status)) {
4607 return nt_status;
4610 c_info = talloc_zero(r->out.collision_info,
4611 struct lsa_ForestTrustCollisionInfo);
4612 if (!c_info) {
4613 return NT_STATUS_NO_MEMORY;
4616 /* first check own info, then other domains */
4617 fti = talloc(mem_ctx, struct ForestTrustInfo);
4618 if (!fti) {
4619 return NT_STATUS_NO_MEMORY;
4622 nt_status = own_ft_info(p_state, fti);
4623 if (!NT_STATUS_IS_OK(nt_status)) {
4624 return nt_status;
4627 nt_status = check_ft_info(c_info, p_state->domain_dns,
4628 fti, nfti, c_info);
4629 if (!NT_STATUS_IS_OK(nt_status)) {
4630 return nt_status;
4633 for (i = 0; i < num_res; i++) {
4634 fti = talloc(mem_ctx, struct ForestTrustInfo);
4635 if (!fti) {
4636 return NT_STATUS_NO_MEMORY;
4639 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4640 if (!NT_STATUS_IS_OK(nt_status)) {
4641 if (NT_STATUS_EQUAL(nt_status,
4642 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4643 continue;
4645 return nt_status;
4648 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4649 "trustPartner", NULL);
4650 if (!td_name) {
4651 return NT_STATUS_INVALID_DOMAIN_STATE;
4654 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4655 if (!NT_STATUS_IS_OK(nt_status)) {
4656 return nt_status;
4660 if (c_info->count != 0) {
4661 *r->out.collision_info = c_info;
4664 if (r->in.check_only != 0) {
4665 return NT_STATUS_OK;
4668 /* not just a check, write info back */
4670 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4671 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4672 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4673 return NT_STATUS_INVALID_PARAMETER;
4676 msg = ldb_msg_new(mem_ctx);
4677 if (msg == NULL) {
4678 return NT_STATUS_NO_MEMORY;
4681 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4682 if (!msg->dn) {
4683 return NT_STATUS_NO_MEMORY;
4686 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4687 LDB_FLAG_MOD_REPLACE, NULL);
4688 if (ret != LDB_SUCCESS) {
4689 return NT_STATUS_NO_MEMORY;
4691 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4692 &ft_blob, NULL);
4693 if (ret != LDB_SUCCESS) {
4694 return NT_STATUS_NO_MEMORY;
4697 ret = ldb_modify(p_state->sam_ldb, msg);
4698 if (ret != LDB_SUCCESS) {
4699 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4700 ldb_errstring(p_state->sam_ldb)));
4702 switch (ret) {
4703 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4704 return NT_STATUS_ACCESS_DENIED;
4705 default:
4706 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4710 return NT_STATUS_OK;
4714 lsa_CREDRRENAME
4716 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4717 struct lsa_CREDRRENAME *r)
4719 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4725 lsa_LSAROPENPOLICYSCE
4727 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4728 struct lsa_LSAROPENPOLICYSCE *r)
4730 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4735 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4737 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4738 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4740 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4745 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4747 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4748 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4750 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4755 lsa_LSARADTREPORTSECURITYEVENT
4757 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4758 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4760 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4764 /* include the generated boilerplate */
4765 #include "librpc/gen_ndr/ndr_lsa_s.c"
4769 /*****************************************
4770 NOTE! The remaining calls below were
4771 removed in w2k3, so the DCESRV_FAULT()
4772 replies are the correct implementation. Do
4773 not try and fill these in with anything else
4774 ******************************************/
4777 dssetup_DsRoleDnsNameToFlatName
4779 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4780 struct dssetup_DsRoleDnsNameToFlatName *r)
4782 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4787 dssetup_DsRoleDcAsDc
4789 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4790 struct dssetup_DsRoleDcAsDc *r)
4792 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4797 dssetup_DsRoleDcAsReplica
4799 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4800 struct dssetup_DsRoleDcAsReplica *r)
4802 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4807 dssetup_DsRoleDemoteDc
4809 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4810 struct dssetup_DsRoleDemoteDc *r)
4812 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4817 dssetup_DsRoleGetDcOperationProgress
4819 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4820 struct dssetup_DsRoleGetDcOperationProgress *r)
4822 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4827 dssetup_DsRoleGetDcOperationResults
4829 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4830 struct dssetup_DsRoleGetDcOperationResults *r)
4832 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4837 dssetup_DsRoleCancel
4839 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4840 struct dssetup_DsRoleCancel *r)
4842 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4847 dssetup_DsRoleServerSaveStateForUpgrade
4849 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4850 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4852 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4857 dssetup_DsRoleUpgradeDownlevelServer
4859 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4860 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4862 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4867 dssetup_DsRoleAbortDownlevelServerUpgrade
4869 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4870 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4872 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4876 /* include the generated boilerplate */
4877 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4879 NTSTATUS dcerpc_server_lsa_init(void)
4881 NTSTATUS ret;
4883 ret = dcerpc_server_dssetup_init();
4884 if (!NT_STATUS_IS_OK(ret)) {
4885 return ret;
4887 ret = dcerpc_server_lsarpc_init();
4888 if (!NT_STATUS_IS_OK(ret)) {
4889 return ret;
4891 return ret;