selftest: add save.env.sh helper script.
[Samba.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
blob41311ed87cf2b67c9e61216c9aadbedfd0348d39
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"
36 #include "libds/common/roles.h"
38 #define DCESRV_INTERFACE_LSARPC_BIND(call, iface) \
39 dcesrv_interface_lsarpc_bind(call, iface)
40 static NTSTATUS dcesrv_interface_lsarpc_bind(struct dcesrv_call_state *dce_call,
41 const struct dcesrv_interface *iface)
43 return dcesrv_interface_bind_reject_connect(dce_call, iface);
47 this type allows us to distinguish handle types
51 state associated with a lsa_OpenAccount() operation
53 struct lsa_account_state {
54 struct lsa_policy_state *policy;
55 uint32_t access_mask;
56 struct dom_sid *account_sid;
61 state associated with a lsa_OpenSecret() operation
63 struct lsa_secret_state {
64 struct lsa_policy_state *policy;
65 uint32_t access_mask;
66 struct ldb_dn *secret_dn;
67 struct ldb_context *sam_ldb;
68 bool global;
72 state associated with a lsa_OpenTrustedDomain() operation
74 struct lsa_trusted_domain_state {
75 struct lsa_policy_state *policy;
76 uint32_t access_mask;
77 struct ldb_dn *trusted_domain_dn;
78 struct ldb_dn *trusted_domain_user_dn;
82 this is based on the samba3 function make_lsa_object_sd()
83 It uses the same logic, but with samba4 helper functions
85 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
86 struct security_descriptor **sd,
87 struct dom_sid *sid,
88 uint32_t sid_access)
90 NTSTATUS status;
91 uint32_t rid;
92 struct dom_sid *domain_sid, *domain_admins_sid;
93 const char *domain_admins_sid_str, *sidstr;
94 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
96 status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
97 if (!NT_STATUS_IS_OK(status)) {
98 TALLOC_FREE(tmp_ctx);
99 return status;
102 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
103 if (domain_admins_sid == NULL) {
104 TALLOC_FREE(tmp_ctx);
105 return NT_STATUS_NO_MEMORY;
108 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
109 if (domain_admins_sid_str == NULL) {
110 TALLOC_FREE(tmp_ctx);
111 return NT_STATUS_NO_MEMORY;
114 sidstr = dom_sid_string(tmp_ctx, sid);
115 if (sidstr == NULL) {
116 TALLOC_FREE(tmp_ctx);
117 return NT_STATUS_NO_MEMORY;
120 *sd = security_descriptor_dacl_create(mem_ctx,
121 0, sidstr, NULL,
123 SID_WORLD,
124 SEC_ACE_TYPE_ACCESS_ALLOWED,
125 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
127 SID_BUILTIN_ADMINISTRATORS,
128 SEC_ACE_TYPE_ACCESS_ALLOWED,
129 SEC_GENERIC_ALL, 0,
131 SID_BUILTIN_ACCOUNT_OPERATORS,
132 SEC_ACE_TYPE_ACCESS_ALLOWED,
133 SEC_GENERIC_ALL, 0,
135 domain_admins_sid_str,
136 SEC_ACE_TYPE_ACCESS_ALLOWED,
137 SEC_GENERIC_ALL, 0,
139 sidstr,
140 SEC_ACE_TYPE_ACCESS_ALLOWED,
141 sid_access, 0,
143 NULL);
144 talloc_free(tmp_ctx);
146 NT_STATUS_HAVE_NO_MEMORY(*sd);
148 return NT_STATUS_OK;
152 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
153 TALLOC_CTX *mem_ctx,
154 struct lsa_EnumAccountRights *r);
156 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
157 TALLOC_CTX *mem_ctx,
158 struct lsa_policy_state *state,
159 int ldb_flag,
160 struct dom_sid *sid,
161 const struct lsa_RightSet *rights);
164 lsa_Close
166 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
167 struct lsa_Close *r)
169 enum dcerpc_transport_t transport =
170 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
171 struct dcesrv_handle *h;
173 if (transport != NCACN_NP && transport != NCALRPC) {
174 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
177 *r->out.handle = *r->in.handle;
179 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
181 talloc_free(h);
183 ZERO_STRUCTP(r->out.handle);
185 return NT_STATUS_OK;
190 lsa_Delete
192 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
193 struct lsa_Delete *r)
195 return NT_STATUS_NOT_SUPPORTED;
200 lsa_DeleteObject
202 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
203 struct lsa_DeleteObject *r)
205 struct dcesrv_handle *h;
206 int ret;
208 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
210 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
211 struct lsa_secret_state *secret_state = h->data;
213 /* Ensure user is permitted to delete this... */
214 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
216 case SECURITY_SYSTEM:
217 case SECURITY_ADMINISTRATOR:
218 break;
219 default:
220 /* Users and anonymous are not allowed to delete things */
221 return NT_STATUS_ACCESS_DENIED;
224 ret = ldb_delete(secret_state->sam_ldb,
225 secret_state->secret_dn);
226 if (ret != LDB_SUCCESS) {
227 return NT_STATUS_INVALID_HANDLE;
230 ZERO_STRUCTP(r->out.handle);
232 return NT_STATUS_OK;
234 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
235 struct lsa_trusted_domain_state *trusted_domain_state =
236 talloc_get_type(h->data, struct lsa_trusted_domain_state);
237 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
238 if (ret != LDB_SUCCESS) {
239 return NT_STATUS_INTERNAL_DB_CORRUPTION;
242 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
243 trusted_domain_state->trusted_domain_dn);
244 if (ret != LDB_SUCCESS) {
245 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
246 return NT_STATUS_INVALID_HANDLE;
249 if (trusted_domain_state->trusted_domain_user_dn) {
250 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
251 trusted_domain_state->trusted_domain_user_dn);
252 if (ret != LDB_SUCCESS) {
253 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
254 return NT_STATUS_INVALID_HANDLE;
258 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
259 if (ret != LDB_SUCCESS) {
260 return NT_STATUS_INTERNAL_DB_CORRUPTION;
263 ZERO_STRUCTP(r->out.handle);
265 return NT_STATUS_OK;
267 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
268 struct lsa_RightSet *rights;
269 struct lsa_account_state *astate;
270 struct lsa_EnumAccountRights r2;
271 NTSTATUS status;
273 rights = talloc(mem_ctx, struct lsa_RightSet);
275 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
277 astate = h->data;
279 r2.in.handle = &astate->policy->handle->wire_handle;
280 r2.in.sid = astate->account_sid;
281 r2.out.rights = rights;
283 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
284 but we have a LSA_HANDLE_ACCOUNT here, so this call
285 will always fail */
286 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
287 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
288 return NT_STATUS_OK;
291 if (!NT_STATUS_IS_OK(status)) {
292 return status;
295 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
296 LDB_FLAG_MOD_DELETE, astate->account_sid,
297 r2.out.rights);
298 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
299 return NT_STATUS_OK;
302 if (!NT_STATUS_IS_OK(status)) {
303 return status;
306 ZERO_STRUCTP(r->out.handle);
308 return NT_STATUS_OK;
311 return NT_STATUS_INVALID_HANDLE;
316 lsa_EnumPrivs
318 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
319 struct lsa_EnumPrivs *r)
321 struct dcesrv_handle *h;
322 uint32_t i;
323 enum sec_privilege priv;
324 const char *privname;
326 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
328 i = *r->in.resume_handle;
330 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
331 r->out.privs->count < r->in.max_count) {
332 struct lsa_PrivEntry *e;
333 privname = sec_privilege_name(priv);
334 r->out.privs->privs = talloc_realloc(r->out.privs,
335 r->out.privs->privs,
336 struct lsa_PrivEntry,
337 r->out.privs->count+1);
338 if (r->out.privs->privs == NULL) {
339 return NT_STATUS_NO_MEMORY;
341 e = &r->out.privs->privs[r->out.privs->count];
342 e->luid.low = priv;
343 e->luid.high = 0;
344 e->name.string = privname;
345 r->out.privs->count++;
346 i++;
349 *r->out.resume_handle = i;
351 return NT_STATUS_OK;
356 lsa_QuerySecObj
358 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
359 struct lsa_QuerySecurity *r)
361 struct dcesrv_handle *h;
362 const struct security_descriptor *sd = NULL;
363 uint32_t access_granted = 0;
364 struct sec_desc_buf *sdbuf = NULL;
365 NTSTATUS status;
366 struct dom_sid *sid;
368 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
370 sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
372 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
373 struct lsa_policy_state *pstate = h->data;
375 sd = pstate->sd;
376 access_granted = pstate->access_mask;
378 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
379 struct lsa_account_state *astate = h->data;
380 struct security_descriptor *_sd = NULL;
382 status = dcesrv_build_lsa_sd(mem_ctx, &_sd, sid,
383 LSA_ACCOUNT_ALL_ACCESS);
384 if (!NT_STATUS_IS_OK(status)) {
385 return status;
387 sd = _sd;
388 access_granted = astate->access_mask;
389 } else {
390 return NT_STATUS_INVALID_HANDLE;
393 sdbuf = talloc_zero(mem_ctx, struct sec_desc_buf);
394 if (sdbuf == NULL) {
395 return NT_STATUS_NO_MEMORY;
398 status = security_descriptor_for_client(sdbuf, sd, r->in.sec_info,
399 access_granted, &sdbuf->sd);
400 if (!NT_STATUS_IS_OK(status)) {
401 return status;
404 *r->out.sdbuf = sdbuf;
406 return NT_STATUS_OK;
411 lsa_SetSecObj
413 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
414 struct lsa_SetSecObj *r)
416 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
421 lsa_ChangePassword
423 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
424 struct lsa_ChangePassword *r)
426 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
430 dssetup_DsRoleGetPrimaryDomainInformation
432 This is not an LSA call, but is the only call left on the DSSETUP
433 pipe (after the pipe was truncated), and needs lsa_get_policy_state
435 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
436 TALLOC_CTX *mem_ctx,
437 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
439 union dssetup_DsRoleInfo *info;
441 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
442 W_ERROR_HAVE_NO_MEMORY(info);
444 switch (r->in.level) {
445 case DS_ROLE_BASIC_INFORMATION:
447 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
448 uint32_t flags = 0;
449 const char *domain = NULL;
450 const char *dns_domain = NULL;
451 const char *forest = NULL;
452 struct GUID domain_guid;
453 struct lsa_policy_state *state;
455 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
456 0, /* we skip access checks */
457 &state);
458 if (!NT_STATUS_IS_OK(status)) {
459 return ntstatus_to_werror(status);
462 ZERO_STRUCT(domain_guid);
464 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
465 case ROLE_STANDALONE:
466 role = DS_ROLE_STANDALONE_SERVER;
467 break;
468 case ROLE_DOMAIN_MEMBER:
469 role = DS_ROLE_MEMBER_SERVER;
470 break;
471 case ROLE_ACTIVE_DIRECTORY_DC:
472 if (samdb_is_pdc(state->sam_ldb)) {
473 role = DS_ROLE_PRIMARY_DC;
474 } else {
475 role = DS_ROLE_BACKUP_DC;
477 break;
480 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
481 case ROLE_STANDALONE:
482 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
483 W_ERROR_HAVE_NO_MEMORY(domain);
484 break;
485 case ROLE_DOMAIN_MEMBER:
486 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
487 W_ERROR_HAVE_NO_MEMORY(domain);
488 /* TODO: what is with dns_domain and forest and guid? */
489 break;
490 case ROLE_ACTIVE_DIRECTORY_DC:
491 flags = DS_ROLE_PRIMARY_DS_RUNNING;
493 if (state->mixed_domain == 1) {
494 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
497 domain = state->domain_name;
498 dns_domain = state->domain_dns;
499 forest = state->forest_dns;
501 domain_guid = state->domain_guid;
502 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
503 break;
506 info->basic.role = role;
507 info->basic.flags = flags;
508 info->basic.domain = domain;
509 info->basic.dns_domain = dns_domain;
510 info->basic.forest = forest;
511 info->basic.domain_guid = domain_guid;
513 r->out.info = info;
514 return WERR_OK;
516 case DS_ROLE_UPGRADE_STATUS:
518 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
519 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
521 r->out.info = info;
522 return WERR_OK;
524 case DS_ROLE_OP_STATUS:
526 info->opstatus.status = DS_ROLE_OP_IDLE;
528 r->out.info = info;
529 return WERR_OK;
531 default:
532 return WERR_INVALID_PARAM;
537 fill in the AccountDomain info
539 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
540 struct lsa_DomainInfo *info)
542 info->name.string = state->domain_name;
543 info->sid = state->domain_sid;
545 return NT_STATUS_OK;
549 fill in the DNS domain info
551 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
552 struct lsa_DnsDomainInfo *info)
554 info->name.string = state->domain_name;
555 info->sid = state->domain_sid;
556 info->dns_domain.string = state->domain_dns;
557 info->dns_forest.string = state->forest_dns;
558 info->domain_guid = state->domain_guid;
560 return NT_STATUS_OK;
564 lsa_QueryInfoPolicy2
566 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
567 struct lsa_QueryInfoPolicy2 *r)
569 struct lsa_policy_state *state;
570 struct dcesrv_handle *h;
571 union lsa_PolicyInformation *info;
573 *r->out.info = NULL;
575 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
577 state = h->data;
579 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
580 if (!info) {
581 return NT_STATUS_NO_MEMORY;
583 *r->out.info = info;
585 switch (r->in.level) {
586 case LSA_POLICY_INFO_AUDIT_LOG:
587 /* we don't need to fill in any of this */
588 ZERO_STRUCT(info->audit_log);
589 return NT_STATUS_OK;
590 case LSA_POLICY_INFO_AUDIT_EVENTS:
591 /* we don't need to fill in any of this */
592 ZERO_STRUCT(info->audit_events);
593 return NT_STATUS_OK;
594 case LSA_POLICY_INFO_PD:
595 /* we don't need to fill in any of this */
596 ZERO_STRUCT(info->pd);
597 return NT_STATUS_OK;
599 case LSA_POLICY_INFO_DOMAIN:
600 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
601 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
602 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
603 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
604 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
606 case LSA_POLICY_INFO_ROLE:
607 info->role.role = LSA_ROLE_PRIMARY;
608 return NT_STATUS_OK;
610 case LSA_POLICY_INFO_DNS:
611 case LSA_POLICY_INFO_DNS_INT:
612 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
614 case LSA_POLICY_INFO_REPLICA:
615 ZERO_STRUCT(info->replica);
616 return NT_STATUS_OK;
618 case LSA_POLICY_INFO_QUOTA:
619 ZERO_STRUCT(info->quota);
620 return NT_STATUS_OK;
622 case LSA_POLICY_INFO_MOD:
623 case LSA_POLICY_INFO_AUDIT_FULL_SET:
624 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
625 /* windows gives INVALID_PARAMETER */
626 *r->out.info = NULL;
627 return NT_STATUS_INVALID_PARAMETER;
630 *r->out.info = NULL;
631 return NT_STATUS_INVALID_INFO_CLASS;
635 lsa_QueryInfoPolicy
637 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
638 struct lsa_QueryInfoPolicy *r)
640 struct lsa_QueryInfoPolicy2 r2;
641 NTSTATUS status;
643 ZERO_STRUCT(r2);
645 r2.in.handle = r->in.handle;
646 r2.in.level = r->in.level;
647 r2.out.info = r->out.info;
649 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
651 return status;
655 lsa_SetInfoPolicy
657 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
658 struct lsa_SetInfoPolicy *r)
660 /* need to support this */
661 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
666 lsa_ClearAuditLog
668 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
669 struct lsa_ClearAuditLog *r)
671 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
675 static const struct generic_mapping dcesrv_lsa_account_mapping = {
676 LSA_ACCOUNT_READ,
677 LSA_ACCOUNT_WRITE,
678 LSA_ACCOUNT_EXECUTE,
679 LSA_ACCOUNT_ALL_ACCESS
683 lsa_CreateAccount
685 This call does not seem to have any long-term effects, hence no database operations
687 we need to talk to the MS product group to find out what this account database means!
689 answer is that the lsa database is totally separate from the SAM and
690 ldap databases. We are going to need a separate ldb to store these
691 accounts. The SIDs on this account bear no relation to the SIDs in
694 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
695 struct lsa_CreateAccount *r)
697 struct lsa_account_state *astate;
699 struct lsa_policy_state *state;
700 struct dcesrv_handle *h, *ah;
702 ZERO_STRUCTP(r->out.acct_handle);
704 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
706 state = h->data;
708 astate = talloc(dce_call->conn, struct lsa_account_state);
709 if (astate == NULL) {
710 return NT_STATUS_NO_MEMORY;
713 astate->account_sid = dom_sid_dup(astate, r->in.sid);
714 if (astate->account_sid == NULL) {
715 talloc_free(astate);
716 return NT_STATUS_NO_MEMORY;
719 astate->policy = talloc_reference(astate, state);
720 astate->access_mask = r->in.access_mask;
723 * For now we grant all requested access.
725 * We will fail at the ldb layer later.
727 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
728 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
729 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
731 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
733 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X].\n",
734 __func__, dom_sid_string(mem_ctx, astate->account_sid),
735 (unsigned)r->in.access_mask,
736 (unsigned)astate->access_mask));
738 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
739 if (!ah) {
740 talloc_free(astate);
741 return NT_STATUS_NO_MEMORY;
744 ah->data = talloc_steal(ah, astate);
746 *r->out.acct_handle = ah->wire_handle;
748 return NT_STATUS_OK;
753 lsa_EnumAccounts
755 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
756 struct lsa_EnumAccounts *r)
758 struct dcesrv_handle *h;
759 struct lsa_policy_state *state;
760 int ret;
761 struct ldb_message **res;
762 const char * const attrs[] = { "objectSid", NULL};
763 uint32_t count, i;
765 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
767 state = h->data;
769 /* NOTE: This call must only return accounts that have at least
770 one privilege set
772 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
773 "(&(objectSid=*)(privilege=*))");
774 if (ret < 0) {
775 return NT_STATUS_INTERNAL_DB_CORRUPTION;
778 if (*r->in.resume_handle >= ret) {
779 return NT_STATUS_NO_MORE_ENTRIES;
782 count = ret - *r->in.resume_handle;
783 if (count > r->in.num_entries) {
784 count = r->in.num_entries;
787 if (count == 0) {
788 return NT_STATUS_NO_MORE_ENTRIES;
791 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
792 if (r->out.sids->sids == NULL) {
793 return NT_STATUS_NO_MEMORY;
796 for (i=0;i<count;i++) {
797 r->out.sids->sids[i].sid =
798 samdb_result_dom_sid(r->out.sids->sids,
799 res[i + *r->in.resume_handle],
800 "objectSid");
801 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
804 r->out.sids->num_sids = count;
805 *r->out.resume_handle = count + *r->in.resume_handle;
807 return NT_STATUS_OK;
810 /* This decrypts and returns Trusted Domain Auth Information Internal data */
811 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
812 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
813 struct trustDomainPasswords *auth_struct)
815 DATA_BLOB session_key = data_blob(NULL, 0);
816 enum ndr_err_code ndr_err;
817 NTSTATUS nt_status;
819 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
820 if (!NT_STATUS_IS_OK(nt_status)) {
821 return nt_status;
824 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
825 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
826 auth_struct,
827 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
828 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
829 return NT_STATUS_INVALID_PARAMETER;
832 return NT_STATUS_OK;
835 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
836 TALLOC_CTX *mem_ctx,
837 struct trustAuthInOutBlob *iopw,
838 DATA_BLOB *trustauth_blob)
840 enum ndr_err_code ndr_err;
842 if (iopw->current.count != iopw->count) {
843 return NT_STATUS_INVALID_PARAMETER;
846 if (iopw->previous.count > iopw->current.count) {
847 return NT_STATUS_INVALID_PARAMETER;
850 if (iopw->previous.count == 0) {
852 * If the previous credentials are not present
853 * we need to make a copy.
855 iopw->previous = iopw->current;
858 if (iopw->previous.count < iopw->current.count) {
859 struct AuthenticationInformationArray *c = &iopw->current;
860 struct AuthenticationInformationArray *p = &iopw->previous;
863 * The previous array needs to have the same size
864 * as the current one.
866 * We may have to fill with TRUST_AUTH_TYPE_NONE
867 * elements.
869 p->array = talloc_realloc(mem_ctx, p->array,
870 struct AuthenticationInformation,
871 c->count);
872 if (p->array == NULL) {
873 return NT_STATUS_NO_MEMORY;
876 while (p->count < c->count) {
877 struct AuthenticationInformation *a =
878 &p->array[p->count++];
880 *a = (struct AuthenticationInformation) {
881 .LastUpdateTime = p->array[0].LastUpdateTime,
882 .AuthType = TRUST_AUTH_TYPE_NONE,
887 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
888 iopw,
889 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
890 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
891 return NT_STATUS_INVALID_PARAMETER;
894 return NT_STATUS_OK;
897 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
898 struct ldb_context *sam_ldb,
899 struct ldb_dn *base_dn,
900 const char *netbios_name,
901 struct trustAuthInOutBlob *in,
902 struct ldb_dn **user_dn)
904 struct ldb_request *req;
905 struct ldb_message *msg;
906 struct ldb_dn *dn;
907 uint32_t i;
908 int ret;
910 dn = ldb_dn_copy(mem_ctx, base_dn);
911 if (!dn) {
912 return NT_STATUS_NO_MEMORY;
914 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
915 return NT_STATUS_NO_MEMORY;
918 msg = ldb_msg_new(mem_ctx);
919 if (!msg) {
920 return NT_STATUS_NO_MEMORY;
922 msg->dn = dn;
924 ret = ldb_msg_add_string(msg, "objectClass", "user");
925 if (ret != LDB_SUCCESS) {
926 return NT_STATUS_NO_MEMORY;
929 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
930 if (ret != LDB_SUCCESS) {
931 return NT_STATUS_NO_MEMORY;
934 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
935 UF_INTERDOMAIN_TRUST_ACCOUNT);
936 if (ret != LDB_SUCCESS) {
937 return NT_STATUS_NO_MEMORY;
940 for (i = 0; i < in->count; i++) {
941 const char *attribute;
942 struct ldb_val v;
943 switch (in->current.array[i].AuthType) {
944 case TRUST_AUTH_TYPE_NT4OWF:
945 attribute = "unicodePwd";
946 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
947 v.length = 16;
948 break;
949 case TRUST_AUTH_TYPE_CLEAR:
950 attribute = "clearTextPassword";
951 v.data = in->current.array[i].AuthInfo.clear.password;
952 v.length = in->current.array[i].AuthInfo.clear.size;
953 break;
954 default:
955 continue;
958 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
959 if (ret != LDB_SUCCESS) {
960 return NT_STATUS_NO_MEMORY;
964 /* create the trusted_domain user account */
965 ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
966 ldb_op_default_callback, NULL);
967 if (ret != LDB_SUCCESS) {
968 return NT_STATUS_NO_MEMORY;
971 ret = ldb_request_add_control(req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
972 false, NULL);
973 if (ret != LDB_SUCCESS) {
974 return NT_STATUS_NO_MEMORY;
977 ret = dsdb_autotransaction_request(sam_ldb, req);
978 if (ret != LDB_SUCCESS) {
979 DEBUG(0,("Failed to create user record %s: %s\n",
980 ldb_dn_get_linearized(msg->dn),
981 ldb_errstring(sam_ldb)));
983 switch (ret) {
984 case LDB_ERR_ENTRY_ALREADY_EXISTS:
985 return NT_STATUS_DOMAIN_EXISTS;
986 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
987 return NT_STATUS_ACCESS_DENIED;
988 default:
989 return NT_STATUS_INTERNAL_DB_CORRUPTION;
993 if (user_dn) {
994 *user_dn = dn;
996 return NT_STATUS_OK;
1000 lsa_CreateTrustedDomainEx2
1002 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
1003 TALLOC_CTX *mem_ctx,
1004 struct lsa_CreateTrustedDomainEx2 *r,
1005 int op,
1006 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
1008 struct dcesrv_handle *policy_handle;
1009 struct lsa_policy_state *policy_state;
1010 struct lsa_trusted_domain_state *trusted_domain_state;
1011 struct dcesrv_handle *handle;
1012 struct ldb_message **msgs, *msg;
1013 const char *attrs[] = {
1014 NULL
1016 const char *netbios_name;
1017 const char *dns_name;
1018 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1019 struct trustDomainPasswords auth_struct;
1020 int ret;
1021 NTSTATUS nt_status;
1022 struct ldb_context *sam_ldb;
1023 struct server_id *server_ids = NULL;
1024 uint32_t num_server_ids = 0;
1025 NTSTATUS status;
1026 struct dom_sid *tmp_sid1;
1027 struct dom_sid *tmp_sid2;
1028 uint32_t tmp_rid;
1029 bool ok;
1030 char *dns_encoded = NULL;
1031 char *netbios_encoded = NULL;
1032 char *sid_encoded = NULL;
1034 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
1035 ZERO_STRUCTP(r->out.trustdom_handle);
1037 policy_state = policy_handle->data;
1038 sam_ldb = policy_state->sam_ldb;
1040 netbios_name = r->in.info->netbios_name.string;
1041 if (!netbios_name) {
1042 return NT_STATUS_INVALID_PARAMETER;
1045 dns_name = r->in.info->domain_name.string;
1046 if (dns_name == NULL) {
1047 return NT_STATUS_INVALID_PARAMETER;
1050 if (r->in.info->sid == NULL) {
1051 return NT_STATUS_INVALID_SID;
1055 * We expect S-1-5-21-A-B-C, but we don't
1056 * allow S-1-5-21-0-0-0 as this is used
1057 * for claims and compound identities.
1059 * So we call dom_sid_split_rid() 3 times
1060 * and compare the result to S-1-5-21
1062 status = dom_sid_split_rid(mem_ctx, r->in.info->sid, &tmp_sid1, &tmp_rid);
1063 if (!NT_STATUS_IS_OK(status)) {
1064 return status;
1066 status = dom_sid_split_rid(mem_ctx, tmp_sid1, &tmp_sid2, &tmp_rid);
1067 if (!NT_STATUS_IS_OK(status)) {
1068 return status;
1070 status = dom_sid_split_rid(mem_ctx, tmp_sid2, &tmp_sid1, &tmp_rid);
1071 if (!NT_STATUS_IS_OK(status)) {
1072 return status;
1074 ok = dom_sid_parse("S-1-5-21", tmp_sid2);
1075 if (!ok) {
1076 return NT_STATUS_INTERNAL_ERROR;
1078 ok = dom_sid_equal(tmp_sid1, tmp_sid2);
1079 if (!ok) {
1080 return NT_STATUS_INVALID_PARAMETER;
1082 ok = dom_sid_parse("S-1-5-21-0-0-0", tmp_sid2);
1083 if (!ok) {
1084 return NT_STATUS_INTERNAL_ERROR;
1086 ok = !dom_sid_equal(r->in.info->sid, tmp_sid2);
1087 if (!ok) {
1088 return NT_STATUS_INVALID_PARAMETER;
1091 dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1092 if (dns_encoded == NULL) {
1093 return NT_STATUS_NO_MEMORY;
1095 netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1096 if (netbios_encoded == NULL) {
1097 return NT_STATUS_NO_MEMORY;
1099 sid_encoded = ldap_encode_ndr_dom_sid(mem_ctx, r->in.info->sid);
1100 if (sid_encoded == NULL) {
1101 return NT_STATUS_NO_MEMORY;
1104 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1105 if (!trusted_domain_state) {
1106 return NT_STATUS_NO_MEMORY;
1108 trusted_domain_state->policy = policy_state;
1110 if (strcasecmp(netbios_name, "BUILTIN") == 0
1111 || (strcasecmp(dns_name, "BUILTIN") == 0)
1112 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
1113 return NT_STATUS_INVALID_PARAMETER;
1116 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
1117 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
1118 || strcasecmp(dns_name, policy_state->domain_dns) == 0
1119 || strcasecmp(dns_name, policy_state->domain_name) == 0
1120 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
1121 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
1124 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
1125 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
1126 /* No secrets are created at this time, for this function */
1127 auth_struct.outgoing.count = 0;
1128 auth_struct.incoming.count = 0;
1129 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
1130 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
1131 r->in.auth_info_internal->auth_blob.size);
1132 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1133 &auth_blob, &auth_struct);
1134 if (!NT_STATUS_IS_OK(nt_status)) {
1135 return nt_status;
1137 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
1139 if (unencrypted_auth_info->incoming_count > 1) {
1140 return NT_STATUS_INVALID_PARAMETER;
1143 /* more investigation required here, do not create secrets for
1144 * now */
1145 auth_struct.outgoing.count = 0;
1146 auth_struct.incoming.count = 0;
1147 } else {
1148 return NT_STATUS_INVALID_PARAMETER;
1151 if (auth_struct.incoming.count) {
1152 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1153 &auth_struct.incoming,
1154 &trustAuthIncoming);
1155 if (!NT_STATUS_IS_OK(nt_status)) {
1156 return nt_status;
1158 } else {
1159 trustAuthIncoming = data_blob(NULL, 0);
1162 if (auth_struct.outgoing.count) {
1163 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1164 &auth_struct.outgoing,
1165 &trustAuthOutgoing);
1166 if (!NT_STATUS_IS_OK(nt_status)) {
1167 return nt_status;
1169 } else {
1170 trustAuthOutgoing = data_blob(NULL, 0);
1173 ret = ldb_transaction_start(sam_ldb);
1174 if (ret != LDB_SUCCESS) {
1175 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1178 /* search for the trusted_domain record */
1179 ret = gendb_search(sam_ldb,
1180 mem_ctx, policy_state->system_dn, &msgs, attrs,
1181 "(&(objectClass=trustedDomain)(|"
1182 "(flatname=%s)(trustPartner=%s)"
1183 "(flatname=%s)(trustPartner=%s)"
1184 "(securityIdentifier=%s)))",
1185 dns_encoded, dns_encoded,
1186 netbios_encoded, netbios_encoded,
1187 sid_encoded);
1188 if (ret > 0) {
1189 ldb_transaction_cancel(sam_ldb);
1190 return NT_STATUS_OBJECT_NAME_COLLISION;
1192 if (ret < 0) {
1193 ldb_transaction_cancel(sam_ldb);
1194 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1197 msg = ldb_msg_new(mem_ctx);
1198 if (msg == NULL) {
1199 return NT_STATUS_NO_MEMORY;
1202 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1203 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", dns_name)) {
1204 ldb_transaction_cancel(sam_ldb);
1205 return NT_STATUS_NO_MEMORY;
1208 ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1209 if (ret != LDB_SUCCESS) {
1210 ldb_transaction_cancel(sam_ldb);
1211 return NT_STATUS_NO_MEMORY;;
1214 ret = ldb_msg_add_string(msg, "flatname", netbios_name);
1215 if (ret != LDB_SUCCESS) {
1216 ldb_transaction_cancel(sam_ldb);
1217 return NT_STATUS_NO_MEMORY;
1220 ret = ldb_msg_add_string(msg, "trustPartner", dns_name);
1221 if (ret != LDB_SUCCESS) {
1222 ldb_transaction_cancel(sam_ldb);
1223 return NT_STATUS_NO_MEMORY;;
1226 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier",
1227 r->in.info->sid);
1228 if (ret != LDB_SUCCESS) {
1229 ldb_transaction_cancel(sam_ldb);
1230 return NT_STATUS_NO_MEMORY;;
1233 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1234 if (ret != LDB_SUCCESS) {
1235 ldb_transaction_cancel(sam_ldb);
1236 return NT_STATUS_NO_MEMORY;;
1239 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1240 if (ret != LDB_SUCCESS) {
1241 ldb_transaction_cancel(sam_ldb);
1242 return NT_STATUS_NO_MEMORY;;
1245 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1246 if (ret != LDB_SUCCESS) {
1247 ldb_transaction_cancel(sam_ldb);
1248 return NT_STATUS_NO_MEMORY;;
1251 if (trustAuthIncoming.data) {
1252 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1253 if (ret != LDB_SUCCESS) {
1254 ldb_transaction_cancel(sam_ldb);
1255 return NT_STATUS_NO_MEMORY;
1258 if (trustAuthOutgoing.data) {
1259 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1260 if (ret != LDB_SUCCESS) {
1261 ldb_transaction_cancel(sam_ldb);
1262 return NT_STATUS_NO_MEMORY;
1266 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1268 /* create the trusted_domain */
1269 ret = ldb_add(sam_ldb, msg);
1270 switch (ret) {
1271 case LDB_SUCCESS:
1272 break;
1273 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1274 ldb_transaction_cancel(sam_ldb);
1275 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1276 ldb_dn_get_linearized(msg->dn),
1277 ldb_errstring(sam_ldb)));
1278 return NT_STATUS_DOMAIN_EXISTS;
1279 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1280 ldb_transaction_cancel(sam_ldb);
1281 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1282 ldb_dn_get_linearized(msg->dn),
1283 ldb_errstring(sam_ldb)));
1284 return NT_STATUS_ACCESS_DENIED;
1285 default:
1286 ldb_transaction_cancel(sam_ldb);
1287 DEBUG(0,("Failed to create user record %s: %s\n",
1288 ldb_dn_get_linearized(msg->dn),
1289 ldb_errstring(sam_ldb)));
1290 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1293 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1294 struct ldb_dn *user_dn;
1295 /* Inbound trusts must also create a cn=users object to match */
1296 nt_status = add_trust_user(mem_ctx, sam_ldb,
1297 policy_state->domain_dn,
1298 netbios_name,
1299 &auth_struct.incoming,
1300 &user_dn);
1301 if (!NT_STATUS_IS_OK(nt_status)) {
1302 ldb_transaction_cancel(sam_ldb);
1303 return nt_status;
1306 /* save the trust user dn */
1307 trusted_domain_state->trusted_domain_user_dn
1308 = talloc_steal(trusted_domain_state, user_dn);
1311 ret = ldb_transaction_commit(sam_ldb);
1312 if (ret != LDB_SUCCESS) {
1313 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1317 * Notify winbindd that we have a new trust
1319 status = irpc_servers_byname(dce_call->msg_ctx,
1320 mem_ctx,
1321 "winbind_server",
1322 &num_server_ids, &server_ids);
1323 if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
1324 enum ndr_err_code ndr_err;
1325 DATA_BLOB b = {};
1327 ndr_err = ndr_push_struct_blob(&b, mem_ctx, r->in.info,
1328 (ndr_push_flags_fn_t)ndr_push_lsa_TrustDomainInfoInfoEx);
1329 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1330 imessaging_send(dce_call->msg_ctx, server_ids[0],
1331 MSG_WINBIND_NEW_TRUSTED_DOMAIN, &b);
1334 TALLOC_FREE(server_ids);
1336 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1337 if (!handle) {
1338 return NT_STATUS_NO_MEMORY;
1341 handle->data = talloc_steal(handle, trusted_domain_state);
1343 trusted_domain_state->access_mask = r->in.access_mask;
1344 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1346 *r->out.trustdom_handle = handle->wire_handle;
1348 return NT_STATUS_OK;
1352 lsa_CreateTrustedDomainEx2
1354 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1355 TALLOC_CTX *mem_ctx,
1356 struct lsa_CreateTrustedDomainEx2 *r)
1358 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1361 lsa_CreateTrustedDomainEx
1363 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1364 TALLOC_CTX *mem_ctx,
1365 struct lsa_CreateTrustedDomainEx *r)
1367 struct lsa_CreateTrustedDomainEx2 r2;
1369 r2.in.policy_handle = r->in.policy_handle;
1370 r2.in.info = r->in.info;
1371 r2.out.trustdom_handle = r->out.trustdom_handle;
1372 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1376 lsa_CreateTrustedDomain
1378 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1379 struct lsa_CreateTrustedDomain *r)
1381 struct lsa_CreateTrustedDomainEx2 r2;
1383 r2.in.policy_handle = r->in.policy_handle;
1384 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1385 if (!r2.in.info) {
1386 return NT_STATUS_NO_MEMORY;
1389 r2.in.info->domain_name = r->in.info->name;
1390 r2.in.info->netbios_name = r->in.info->name;
1391 r2.in.info->sid = r->in.info->sid;
1392 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1393 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1394 r2.in.info->trust_attributes = 0;
1396 r2.in.access_mask = r->in.access_mask;
1397 r2.out.trustdom_handle = r->out.trustdom_handle;
1399 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1402 static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
1403 struct dcesrv_call_state *dce_call,
1404 TALLOC_CTX *tmp_mem,
1405 struct lsa_policy_state *policy_state,
1406 const char *filter,
1407 uint32_t access_mask,
1408 struct dcesrv_handle **_handle)
1410 struct lsa_trusted_domain_state *trusted_domain_state;
1411 struct dcesrv_handle *handle;
1412 struct ldb_message **msgs;
1413 const char *attrs[] = {
1414 "trustDirection",
1415 "flatname",
1416 NULL
1418 uint32_t direction;
1419 int ret;
1421 /* TODO: perform access checks */
1423 /* search for the trusted_domain record */
1424 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1425 policy_state->system_dn,
1426 &msgs, attrs, "%s", filter);
1427 if (ret == 0) {
1428 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1431 if (ret != 1) {
1432 DEBUG(0,("Found %d records matching %s under %s\n", ret,
1433 filter,
1434 ldb_dn_get_linearized(policy_state->system_dn)));
1435 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1438 trusted_domain_state = talloc_zero(tmp_mem,
1439 struct lsa_trusted_domain_state);
1440 if (!trusted_domain_state) {
1441 return NT_STATUS_NO_MEMORY;
1443 trusted_domain_state->policy = policy_state;
1445 trusted_domain_state->trusted_domain_dn =
1446 talloc_steal(trusted_domain_state, msgs[0]->dn);
1448 direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1449 if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1450 const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1451 "flatname", NULL);
1453 /* search for the trusted_domain account */
1454 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1455 policy_state->domain_dn,
1456 &msgs, attrs,
1457 "(&(samaccountname=%s$)(objectclass=user)"
1458 "(userAccountControl:%s:=%u))",
1459 flatname,
1460 LDB_OID_COMPARATOR_AND,
1461 UF_INTERDOMAIN_TRUST_ACCOUNT);
1462 if (ret == 1) {
1463 trusted_domain_state->trusted_domain_user_dn =
1464 talloc_steal(trusted_domain_state, msgs[0]->dn);
1468 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1469 if (!handle) {
1470 return NT_STATUS_NO_MEMORY;
1473 handle->data = talloc_steal(handle, trusted_domain_state);
1475 trusted_domain_state->access_mask = access_mask;
1476 trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1477 policy_state);
1479 *_handle = handle;
1481 return NT_STATUS_OK;
1485 lsa_OpenTrustedDomain
1487 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1488 struct lsa_OpenTrustedDomain *r)
1490 struct dcesrv_handle *policy_handle;
1491 struct lsa_policy_state *policy_state;
1492 struct dcesrv_handle *handle;
1493 const char *sid_string;
1494 char *filter;
1495 NTSTATUS status;
1497 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1498 ZERO_STRUCTP(r->out.trustdom_handle);
1499 policy_state = policy_handle->data;
1501 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1502 if (!sid_string) {
1503 return NT_STATUS_NO_MEMORY;
1506 filter = talloc_asprintf(mem_ctx,
1507 "(&(securityIdentifier=%s)"
1508 "(objectclass=trustedDomain))",
1509 sid_string);
1510 if (filter == NULL) {
1511 return NT_STATUS_NO_MEMORY;
1514 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1515 policy_state,
1516 filter,
1517 r->in.access_mask,
1518 &handle);
1519 if (!NT_STATUS_IS_OK(status)) {
1520 return status;
1523 *r->out.trustdom_handle = handle->wire_handle;
1525 return NT_STATUS_OK;
1530 lsa_OpenTrustedDomainByName
1532 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1533 TALLOC_CTX *mem_ctx,
1534 struct lsa_OpenTrustedDomainByName *r)
1536 struct dcesrv_handle *policy_handle;
1537 struct lsa_policy_state *policy_state;
1538 struct dcesrv_handle *handle;
1539 char *td_name;
1540 char *filter;
1541 NTSTATUS status;
1543 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1544 ZERO_STRUCTP(r->out.trustdom_handle);
1545 policy_state = policy_handle->data;
1547 if (!r->in.name.string) {
1548 return NT_STATUS_INVALID_PARAMETER;
1551 /* search for the trusted_domain record */
1552 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1553 if (td_name == NULL) {
1554 return NT_STATUS_NO_MEMORY;
1557 filter = talloc_asprintf(mem_ctx,
1558 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1559 "(objectclass=trustedDomain))",
1560 td_name, td_name, td_name);
1561 if (filter == NULL) {
1562 return NT_STATUS_NO_MEMORY;
1565 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1566 policy_state,
1567 filter,
1568 r->in.access_mask,
1569 &handle);
1570 if (!NT_STATUS_IS_OK(status)) {
1571 return status;
1574 *r->out.trustdom_handle = handle->wire_handle;
1576 return NT_STATUS_OK;
1582 lsa_SetTrustedDomainInfo
1584 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1585 struct lsa_SetTrustedDomainInfo *r)
1587 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1592 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1593 * otherwise at least one must be provided */
1594 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1595 struct ldb_dn *basedn, const char *dns_domain,
1596 const char *netbios, struct dom_sid2 *sid,
1597 struct ldb_message ***msgs)
1599 const char *attrs[] = { "flatname", "trustPartner",
1600 "securityIdentifier", "trustDirection",
1601 "trustType", "trustAttributes",
1602 "trustPosixOffset",
1603 "msDs-supportedEncryptionTypes",
1604 "msDS-TrustForestTrustInfo",
1605 NULL
1607 char *dns = NULL;
1608 char *nbn = NULL;
1609 char *sidstr = NULL;
1610 char *filter;
1611 int ret;
1614 if (dns_domain || netbios || sid) {
1615 filter = talloc_strdup(mem_ctx,
1616 "(&(objectclass=trustedDomain)(|");
1617 } else {
1618 filter = talloc_strdup(mem_ctx,
1619 "(objectclass=trustedDomain)");
1621 if (!filter) {
1622 return NT_STATUS_NO_MEMORY;
1625 if (dns_domain) {
1626 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1627 if (!dns) {
1628 return NT_STATUS_NO_MEMORY;
1630 filter = talloc_asprintf_append(filter,
1631 "(trustPartner=%s)", dns);
1632 if (!filter) {
1633 return NT_STATUS_NO_MEMORY;
1636 if (netbios) {
1637 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1638 if (!nbn) {
1639 return NT_STATUS_NO_MEMORY;
1641 filter = talloc_asprintf_append(filter,
1642 "(flatname=%s)", nbn);
1643 if (!filter) {
1644 return NT_STATUS_NO_MEMORY;
1647 if (sid) {
1648 sidstr = dom_sid_string(mem_ctx, sid);
1649 if (!sidstr) {
1650 return NT_STATUS_INVALID_PARAMETER;
1652 filter = talloc_asprintf_append(filter,
1653 "(securityIdentifier=%s)",
1654 sidstr);
1655 if (!filter) {
1656 return NT_STATUS_NO_MEMORY;
1659 if (dns_domain || netbios || sid) {
1660 filter = talloc_asprintf_append(filter, "))");
1661 if (!filter) {
1662 return NT_STATUS_NO_MEMORY;
1666 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1667 if (ret == 0) {
1668 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1671 if (ret != 1) {
1672 return NT_STATUS_OBJECT_NAME_COLLISION;
1675 return NT_STATUS_OK;
1678 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1679 struct ldb_context *sam_ldb,
1680 struct ldb_message *orig,
1681 struct ldb_message *dest,
1682 const char *attribute,
1683 uint32_t value,
1684 uint32_t *orig_value)
1686 const struct ldb_val *orig_val;
1687 uint32_t orig_uint = 0;
1688 unsigned int flags = 0;
1689 int ret;
1691 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1692 if (!orig_val || !orig_val->data) {
1693 /* add new attribute */
1694 flags = LDB_FLAG_MOD_ADD;
1696 } else {
1697 errno = 0;
1698 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1699 if (errno != 0 || orig_uint != value) {
1700 /* replace also if can't get value */
1701 flags = LDB_FLAG_MOD_REPLACE;
1705 if (flags == 0) {
1706 /* stored value is identical, nothing to change */
1707 goto done;
1710 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1711 if (ret != LDB_SUCCESS) {
1712 return NT_STATUS_NO_MEMORY;
1715 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1716 if (ret != LDB_SUCCESS) {
1717 return NT_STATUS_NO_MEMORY;
1720 done:
1721 if (orig_value) {
1722 *orig_value = orig_uint;
1724 return NT_STATUS_OK;
1727 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1728 struct ldb_context *sam_ldb,
1729 struct ldb_dn *base_dn,
1730 bool delete_user,
1731 const char *netbios_name,
1732 struct trustAuthInOutBlob *in)
1734 const char *attrs[] = { "userAccountControl", NULL };
1735 struct ldb_message **msgs;
1736 struct ldb_message *msg;
1737 uint32_t uac;
1738 uint32_t i;
1739 int ret;
1741 ret = gendb_search(sam_ldb, mem_ctx,
1742 base_dn, &msgs, attrs,
1743 "samAccountName=%s$", netbios_name);
1744 if (ret > 1) {
1745 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1748 if (ret == 0) {
1749 if (delete_user) {
1750 return NT_STATUS_OK;
1753 /* ok no existing user, add it from scratch */
1754 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1755 netbios_name, in, NULL);
1758 /* check user is what we are looking for */
1759 uac = ldb_msg_find_attr_as_uint(msgs[0],
1760 "userAccountControl", 0);
1761 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1762 return NT_STATUS_OBJECT_NAME_COLLISION;
1765 if (delete_user) {
1766 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1767 switch (ret) {
1768 case LDB_SUCCESS:
1769 return NT_STATUS_OK;
1770 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1771 return NT_STATUS_ACCESS_DENIED;
1772 default:
1773 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1777 /* entry exists, just modify secret if any */
1778 if (in == NULL || in->count == 0) {
1779 return NT_STATUS_OK;
1782 msg = ldb_msg_new(mem_ctx);
1783 if (!msg) {
1784 return NT_STATUS_NO_MEMORY;
1786 msg->dn = msgs[0]->dn;
1788 for (i = 0; i < in->count; i++) {
1789 const char *attribute;
1790 struct ldb_val v;
1791 switch (in->current.array[i].AuthType) {
1792 case TRUST_AUTH_TYPE_NT4OWF:
1793 attribute = "unicodePwd";
1794 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1795 v.length = 16;
1796 break;
1797 case TRUST_AUTH_TYPE_CLEAR:
1798 attribute = "clearTextPassword";
1799 v.data = in->current.array[i].AuthInfo.clear.password;
1800 v.length = in->current.array[i].AuthInfo.clear.size;
1801 break;
1802 default:
1803 continue;
1806 ret = ldb_msg_add_empty(msg, attribute,
1807 LDB_FLAG_MOD_REPLACE, NULL);
1808 if (ret != LDB_SUCCESS) {
1809 return NT_STATUS_NO_MEMORY;
1812 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1813 if (ret != LDB_SUCCESS) {
1814 return NT_STATUS_NO_MEMORY;
1818 /* create the trusted_domain user account */
1819 ret = ldb_modify(sam_ldb, msg);
1820 if (ret != LDB_SUCCESS) {
1821 DEBUG(0,("Failed to create user record %s: %s\n",
1822 ldb_dn_get_linearized(msg->dn),
1823 ldb_errstring(sam_ldb)));
1825 switch (ret) {
1826 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1827 return NT_STATUS_DOMAIN_EXISTS;
1828 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1829 return NT_STATUS_ACCESS_DENIED;
1830 default:
1831 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1835 return NT_STATUS_OK;
1839 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1840 struct lsa_policy_state *p_state,
1841 TALLOC_CTX *mem_ctx,
1842 struct ldb_message *dom_msg,
1843 enum lsa_TrustDomInfoEnum level,
1844 union lsa_TrustedDomainInfo *info)
1846 uint32_t *posix_offset = NULL;
1847 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1848 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1849 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1850 uint32_t *enc_types = NULL;
1851 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1852 struct trustDomainPasswords auth_struct;
1853 struct trustAuthInOutBlob *current_passwords = NULL;
1854 NTSTATUS nt_status;
1855 struct ldb_message **msgs;
1856 struct ldb_message *msg;
1857 bool add_outgoing = false;
1858 bool add_incoming = false;
1859 bool del_outgoing = false;
1860 bool del_incoming = false;
1861 bool del_forest_info = false;
1862 bool in_transaction = false;
1863 int ret;
1864 bool am_rodc;
1866 switch (level) {
1867 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1868 posix_offset = &info->posix_offset.posix_offset;
1869 break;
1870 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1871 info_ex = &info->info_ex;
1872 break;
1873 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1874 auth_info = &info->auth_info;
1875 break;
1876 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1877 posix_offset = &info->full_info.posix_offset.posix_offset;
1878 info_ex = &info->full_info.info_ex;
1879 auth_info = &info->full_info.auth_info;
1880 break;
1881 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1882 auth_info_int = &info->auth_info_internal;
1883 break;
1884 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1885 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1886 info_ex = &info->full_info_internal.info_ex;
1887 auth_info_int = &info->full_info_internal.auth_info;
1888 break;
1889 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1890 enc_types = &info->enc_types.enc_types;
1891 break;
1892 default:
1893 return NT_STATUS_INVALID_PARAMETER;
1896 if (auth_info) {
1897 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1898 &trustAuthIncoming,
1899 &trustAuthOutgoing);
1900 if (!NT_STATUS_IS_OK(nt_status)) {
1901 return nt_status;
1903 if (trustAuthIncoming.data) {
1904 /* This does the decode of some of this twice, but it is easier that way */
1905 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1906 auth_info->incoming_count,
1907 auth_info->incoming_current_auth_info,
1908 NULL,
1909 &current_passwords);
1910 if (!NT_STATUS_IS_OK(nt_status)) {
1911 return nt_status;
1916 /* decode auth_info_int if set */
1917 if (auth_info_int) {
1919 /* now decrypt blob */
1920 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1921 auth_info_int->auth_blob.size);
1923 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1924 &auth_blob, &auth_struct);
1925 if (!NT_STATUS_IS_OK(nt_status)) {
1926 return nt_status;
1930 if (info_ex) {
1931 /* verify data matches */
1932 if (info_ex->trust_attributes &
1933 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1934 /* TODO: check what behavior level we have */
1935 if (strcasecmp_m(p_state->domain_dns,
1936 p_state->forest_dns) != 0) {
1937 return NT_STATUS_INVALID_DOMAIN_STATE;
1941 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1942 if (ret == LDB_SUCCESS && am_rodc) {
1943 return NT_STATUS_NO_SUCH_DOMAIN;
1946 /* verify only one object matches the dns/netbios/sid
1947 * triplet and that this is the one we already have */
1948 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1949 p_state->system_dn,
1950 info_ex->domain_name.string,
1951 info_ex->netbios_name.string,
1952 info_ex->sid, &msgs);
1953 if (!NT_STATUS_IS_OK(nt_status)) {
1954 return nt_status;
1956 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1957 return NT_STATUS_OBJECT_NAME_COLLISION;
1959 talloc_free(msgs);
1962 /* TODO: should we fetch previous values from the existing entry
1963 * and append them ? */
1964 if (auth_info_int && auth_struct.incoming.count) {
1965 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1966 &auth_struct.incoming,
1967 &trustAuthIncoming);
1968 if (!NT_STATUS_IS_OK(nt_status)) {
1969 return nt_status;
1972 current_passwords = &auth_struct.incoming;
1974 } else {
1975 trustAuthIncoming = data_blob(NULL, 0);
1978 if (auth_info_int && auth_struct.outgoing.count) {
1979 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1980 &auth_struct.outgoing,
1981 &trustAuthOutgoing);
1982 if (!NT_STATUS_IS_OK(nt_status)) {
1983 return nt_status;
1985 } else {
1986 trustAuthOutgoing = data_blob(NULL, 0);
1989 msg = ldb_msg_new(mem_ctx);
1990 if (msg == NULL) {
1991 return NT_STATUS_NO_MEMORY;
1993 msg->dn = dom_msg->dn;
1995 if (posix_offset) {
1996 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1997 dom_msg, msg,
1998 "trustPosixOffset",
1999 *posix_offset, NULL);
2000 if (!NT_STATUS_IS_OK(nt_status)) {
2001 return nt_status;
2005 if (info_ex) {
2006 uint32_t origattrs;
2007 uint32_t changed_attrs;
2008 uint32_t origdir;
2009 int origtype;
2011 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2012 dom_msg, msg,
2013 "trustDirection",
2014 info_ex->trust_direction,
2015 &origdir);
2016 if (!NT_STATUS_IS_OK(nt_status)) {
2017 return nt_status;
2020 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2021 if (auth_info != NULL && trustAuthIncoming.length > 0) {
2022 add_incoming = true;
2025 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2026 if (auth_info != NULL && trustAuthOutgoing.length > 0) {
2027 add_outgoing = true;
2031 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
2032 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
2033 del_incoming = true;
2035 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
2036 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2037 del_outgoing = true;
2040 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
2041 if (origtype == -1 || origtype != info_ex->trust_type) {
2042 DEBUG(1, ("Attempted to change trust type! "
2043 "Operation not handled\n"));
2044 return NT_STATUS_INVALID_PARAMETER;
2047 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2048 dom_msg, msg,
2049 "trustAttributes",
2050 info_ex->trust_attributes,
2051 &origattrs);
2052 if (!NT_STATUS_IS_OK(nt_status)) {
2053 return nt_status;
2055 /* TODO: check forestFunctionality from ldb opaque */
2056 /* TODO: check what is set makes sense */
2058 changed_attrs = origattrs ^ info_ex->trust_attributes;
2059 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2061 * For now we only allow
2062 * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
2064 * TODO: we may need to support more attribute changes
2066 DEBUG(1, ("Attempted to change trust attributes "
2067 "(0x%08x != 0x%08x)! "
2068 "Operation not handled yet...\n",
2069 (unsigned)origattrs,
2070 (unsigned)info_ex->trust_attributes));
2071 return NT_STATUS_INVALID_PARAMETER;
2074 if (!(info_ex->trust_attributes &
2075 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
2077 struct ldb_message_element *orig_forest_el = NULL;
2079 orig_forest_el = ldb_msg_find_element(dom_msg,
2080 "msDS-TrustForestTrustInfo");
2081 if (orig_forest_el != NULL) {
2082 del_forest_info = true;
2087 if (enc_types) {
2088 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2089 dom_msg, msg,
2090 "msDS-SupportedEncryptionTypes",
2091 *enc_types, NULL);
2092 if (!NT_STATUS_IS_OK(nt_status)) {
2093 return nt_status;
2097 if (add_incoming || del_incoming) {
2098 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
2099 LDB_FLAG_MOD_REPLACE, NULL);
2100 if (ret != LDB_SUCCESS) {
2101 return NT_STATUS_NO_MEMORY;
2103 if (add_incoming) {
2104 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
2105 &trustAuthIncoming, NULL);
2106 if (ret != LDB_SUCCESS) {
2107 return NT_STATUS_NO_MEMORY;
2111 if (add_outgoing || del_outgoing) {
2112 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2113 LDB_FLAG_MOD_REPLACE, NULL);
2114 if (ret != LDB_SUCCESS) {
2115 return NT_STATUS_NO_MEMORY;
2117 if (add_outgoing) {
2118 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
2119 &trustAuthOutgoing, NULL);
2120 if (ret != LDB_SUCCESS) {
2121 return NT_STATUS_NO_MEMORY;
2125 if (del_forest_info) {
2126 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
2127 LDB_FLAG_MOD_REPLACE, NULL);
2128 if (ret != LDB_SUCCESS) {
2129 return NT_STATUS_NO_MEMORY;
2133 /* start transaction */
2134 ret = ldb_transaction_start(p_state->sam_ldb);
2135 if (ret != LDB_SUCCESS) {
2136 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2138 in_transaction = true;
2140 if (msg->num_elements) {
2141 ret = ldb_modify(p_state->sam_ldb, msg);
2142 if (ret != LDB_SUCCESS) {
2143 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
2144 ldb_dn_get_linearized(msg->dn),
2145 ldb_errstring(p_state->sam_ldb)));
2146 nt_status = dsdb_ldb_err_to_ntstatus(ret);
2147 goto done;
2151 if (add_incoming || del_incoming) {
2152 const char *netbios_name;
2154 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
2155 "flatname", NULL);
2156 if (!netbios_name) {
2157 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
2158 goto done;
2161 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
2162 nt_status = update_trust_user(mem_ctx,
2163 p_state->sam_ldb,
2164 p_state->domain_dn,
2165 del_incoming,
2166 netbios_name,
2167 current_passwords);
2168 if (!NT_STATUS_IS_OK(nt_status)) {
2169 goto done;
2173 /* ok, all fine, commit transaction and return */
2174 ret = ldb_transaction_commit(p_state->sam_ldb);
2175 if (ret != LDB_SUCCESS) {
2176 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2178 in_transaction = false;
2180 nt_status = NT_STATUS_OK;
2182 done:
2183 if (in_transaction) {
2184 ldb_transaction_cancel(p_state->sam_ldb);
2186 return nt_status;
2190 lsa_SetInfomrationTrustedDomain
2192 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
2193 struct dcesrv_call_state *dce_call,
2194 TALLOC_CTX *mem_ctx,
2195 struct lsa_SetInformationTrustedDomain *r)
2197 struct dcesrv_handle *h;
2198 struct lsa_trusted_domain_state *td_state;
2199 struct ldb_message **msgs;
2200 NTSTATUS nt_status;
2202 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
2203 LSA_HANDLE_TRUSTED_DOMAIN);
2205 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2207 /* get the trusted domain object */
2208 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
2209 td_state->trusted_domain_dn,
2210 NULL, NULL, NULL, &msgs);
2211 if (!NT_STATUS_IS_OK(nt_status)) {
2212 if (NT_STATUS_EQUAL(nt_status,
2213 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2214 return nt_status;
2216 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2219 return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
2220 msgs[0], r->in.level, r->in.info);
2225 lsa_DeleteTrustedDomain
2227 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2228 struct lsa_DeleteTrustedDomain *r)
2230 NTSTATUS status;
2231 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2232 struct lsa_DeleteObject del;
2233 struct dcesrv_handle *h;
2235 opn.in.handle = r->in.handle;
2236 opn.in.sid = r->in.dom_sid;
2237 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2238 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2239 if (!opn.out.trustdom_handle) {
2240 return NT_STATUS_NO_MEMORY;
2242 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2243 if (!NT_STATUS_IS_OK(status)) {
2244 return status;
2247 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2248 talloc_steal(mem_ctx, h);
2250 del.in.handle = opn.out.trustdom_handle;
2251 del.out.handle = opn.out.trustdom_handle;
2252 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2253 if (!NT_STATUS_IS_OK(status)) {
2254 return status;
2256 return NT_STATUS_OK;
2259 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2260 struct ldb_message *msg,
2261 struct lsa_TrustDomainInfoInfoEx *info_ex)
2263 info_ex->domain_name.string
2264 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2265 info_ex->netbios_name.string
2266 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2267 info_ex->sid
2268 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2269 info_ex->trust_direction
2270 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2271 info_ex->trust_type
2272 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2273 info_ex->trust_attributes
2274 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2275 return NT_STATUS_OK;
2279 lsa_QueryTrustedDomainInfo
2281 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2282 struct lsa_QueryTrustedDomainInfo *r)
2284 union lsa_TrustedDomainInfo *info = NULL;
2285 struct dcesrv_handle *h;
2286 struct lsa_trusted_domain_state *trusted_domain_state;
2287 struct ldb_message *msg;
2288 int ret;
2289 struct ldb_message **res;
2290 const char *attrs[] = {
2291 "flatname",
2292 "trustPartner",
2293 "securityIdentifier",
2294 "trustDirection",
2295 "trustType",
2296 "trustAttributes",
2297 "msDs-supportedEncryptionTypes",
2298 NULL
2301 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2303 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2305 /* pull all the user attributes */
2306 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2307 trusted_domain_state->trusted_domain_dn, &res, attrs);
2308 if (ret != 1) {
2309 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2311 msg = res[0];
2313 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2314 if (!info) {
2315 return NT_STATUS_NO_MEMORY;
2317 *r->out.info = info;
2319 switch (r->in.level) {
2320 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2321 info->name.netbios_name.string
2322 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2323 break;
2324 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2325 info->posix_offset.posix_offset
2326 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2327 break;
2328 #if 0 /* Win2k3 doesn't implement this */
2329 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2330 r->out.info->info_basic.netbios_name.string
2331 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2332 r->out.info->info_basic.sid
2333 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2334 break;
2335 #endif
2336 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2337 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2339 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2340 ZERO_STRUCT(info->full_info);
2341 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2342 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2343 ZERO_STRUCT(info->full_info2_internal);
2344 info->full_info2_internal.posix_offset.posix_offset
2345 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2346 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2348 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2349 info->enc_types.enc_types
2350 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2351 break;
2353 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2354 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2355 /* oops, we don't want to return the info after all */
2356 talloc_free(info);
2357 *r->out.info = NULL;
2358 return NT_STATUS_INVALID_PARAMETER;
2359 default:
2360 /* oops, we don't want to return the info after all */
2361 talloc_free(info);
2362 *r->out.info = NULL;
2363 return NT_STATUS_INVALID_INFO_CLASS;
2366 return NT_STATUS_OK;
2371 lsa_QueryTrustedDomainInfoBySid
2373 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2374 struct lsa_QueryTrustedDomainInfoBySid *r)
2376 NTSTATUS status;
2377 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2378 struct lsa_QueryTrustedDomainInfo query;
2379 struct dcesrv_handle *h;
2381 opn.in.handle = r->in.handle;
2382 opn.in.sid = r->in.dom_sid;
2383 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2384 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2385 if (!opn.out.trustdom_handle) {
2386 return NT_STATUS_NO_MEMORY;
2388 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2389 if (!NT_STATUS_IS_OK(status)) {
2390 return status;
2393 /* Ensure this handle goes away at the end of this call */
2394 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2395 talloc_steal(mem_ctx, h);
2397 query.in.trustdom_handle = opn.out.trustdom_handle;
2398 query.in.level = r->in.level;
2399 query.out.info = r->out.info;
2400 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2401 if (!NT_STATUS_IS_OK(status)) {
2402 return status;
2405 return NT_STATUS_OK;
2409 lsa_SetTrustedDomainInfoByName
2411 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2412 TALLOC_CTX *mem_ctx,
2413 struct lsa_SetTrustedDomainInfoByName *r)
2415 struct dcesrv_handle *policy_handle;
2416 struct lsa_policy_state *policy_state;
2417 struct ldb_message **msgs;
2418 NTSTATUS nt_status;
2420 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2421 policy_state = policy_handle->data;
2423 /* get the trusted domain object */
2424 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2425 policy_state->domain_dn,
2426 r->in.trusted_domain->string,
2427 r->in.trusted_domain->string,
2428 NULL, &msgs);
2429 if (!NT_STATUS_IS_OK(nt_status)) {
2430 if (NT_STATUS_EQUAL(nt_status,
2431 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2432 return nt_status;
2434 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2437 return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2438 msgs[0], r->in.level, r->in.info);
2442 lsa_QueryTrustedDomainInfoByName
2444 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2445 TALLOC_CTX *mem_ctx,
2446 struct lsa_QueryTrustedDomainInfoByName *r)
2448 NTSTATUS status;
2449 struct lsa_OpenTrustedDomainByName opn = {{0},{0}};
2450 struct lsa_QueryTrustedDomainInfo query;
2451 struct dcesrv_handle *h;
2453 opn.in.handle = r->in.handle;
2454 opn.in.name = *r->in.trusted_domain;
2455 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2456 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2457 if (!opn.out.trustdom_handle) {
2458 return NT_STATUS_NO_MEMORY;
2460 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2461 if (!NT_STATUS_IS_OK(status)) {
2462 return status;
2465 /* Ensure this handle goes away at the end of this call */
2466 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2467 talloc_steal(mem_ctx, h);
2469 query.in.trustdom_handle = opn.out.trustdom_handle;
2470 query.in.level = r->in.level;
2471 query.out.info = r->out.info;
2472 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2473 if (!NT_STATUS_IS_OK(status)) {
2474 return status;
2477 return NT_STATUS_OK;
2481 lsa_CloseTrustedDomainEx
2483 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2484 TALLOC_CTX *mem_ctx,
2485 struct lsa_CloseTrustedDomainEx *r)
2487 /* The result of a bad hair day from an IDL programmer? Not
2488 * implmented in Win2k3. You should always just lsa_Close
2489 * anyway. */
2490 return NT_STATUS_NOT_IMPLEMENTED;
2495 comparison function for sorting lsa_DomainInformation array
2497 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2499 return strcasecmp_m(e1->name.string, e2->name.string);
2503 lsa_EnumTrustDom
2505 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2506 struct lsa_EnumTrustDom *r)
2508 struct dcesrv_handle *policy_handle;
2509 struct lsa_DomainInfo *entries;
2510 struct lsa_policy_state *policy_state;
2511 struct ldb_message **domains;
2512 const char *attrs[] = {
2513 "flatname",
2514 "securityIdentifier",
2515 NULL
2519 int count, i;
2521 *r->out.resume_handle = 0;
2523 r->out.domains->domains = NULL;
2524 r->out.domains->count = 0;
2526 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2528 policy_state = policy_handle->data;
2530 /* search for all users in this domain. This could possibly be cached and
2531 resumed based on resume_key */
2532 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2533 "objectclass=trustedDomain");
2534 if (count < 0) {
2535 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2538 /* convert to lsa_TrustInformation format */
2539 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2540 if (!entries) {
2541 return NT_STATUS_NO_MEMORY;
2543 for (i=0;i<count;i++) {
2544 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2545 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2548 /* sort the results by name */
2549 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2551 if (*r->in.resume_handle >= count) {
2552 *r->out.resume_handle = -1;
2554 return NT_STATUS_NO_MORE_ENTRIES;
2557 /* return the rest, limit by max_size. Note that we
2558 use the w2k3 element size value of 60 */
2559 r->out.domains->count = count - *r->in.resume_handle;
2560 r->out.domains->count = MIN(r->out.domains->count,
2561 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2563 r->out.domains->domains = entries + *r->in.resume_handle;
2564 r->out.domains->count = r->out.domains->count;
2566 if (r->out.domains->count < count - *r->in.resume_handle) {
2567 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2568 return STATUS_MORE_ENTRIES;
2571 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2572 * always be larger than the previous input resume handle, in
2573 * particular when hitting the last query it is vital to set the
2574 * resume handle correctly to avoid infinite client loops, as
2575 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2576 * status is NT_STATUS_OK - gd */
2578 *r->out.resume_handle = (uint32_t)-1;
2580 return NT_STATUS_OK;
2584 comparison function for sorting lsa_DomainInformation array
2586 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2588 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2592 lsa_EnumTrustedDomainsEx
2594 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2595 struct lsa_EnumTrustedDomainsEx *r)
2597 struct dcesrv_handle *policy_handle;
2598 struct lsa_TrustDomainInfoInfoEx *entries;
2599 struct lsa_policy_state *policy_state;
2600 struct ldb_message **domains;
2601 const char *attrs[] = {
2602 "flatname",
2603 "trustPartner",
2604 "securityIdentifier",
2605 "trustDirection",
2606 "trustType",
2607 "trustAttributes",
2608 NULL
2610 NTSTATUS nt_status;
2612 int count, i;
2614 *r->out.resume_handle = 0;
2616 r->out.domains->domains = NULL;
2617 r->out.domains->count = 0;
2619 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2621 policy_state = policy_handle->data;
2623 /* search for all users in this domain. This could possibly be cached and
2624 resumed based on resume_key */
2625 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2626 "objectclass=trustedDomain");
2627 if (count < 0) {
2628 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2631 /* convert to lsa_DomainInformation format */
2632 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2633 if (!entries) {
2634 return NT_STATUS_NO_MEMORY;
2636 for (i=0;i<count;i++) {
2637 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2638 if (!NT_STATUS_IS_OK(nt_status)) {
2639 return nt_status;
2643 /* sort the results by name */
2644 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2646 if (*r->in.resume_handle >= count) {
2647 *r->out.resume_handle = -1;
2649 return NT_STATUS_NO_MORE_ENTRIES;
2652 /* return the rest, limit by max_size. Note that we
2653 use the w2k3 element size value of 60 */
2654 r->out.domains->count = count - *r->in.resume_handle;
2655 r->out.domains->count = MIN(r->out.domains->count,
2656 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2658 r->out.domains->domains = entries + *r->in.resume_handle;
2659 r->out.domains->count = r->out.domains->count;
2661 if (r->out.domains->count < count - *r->in.resume_handle) {
2662 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2663 return STATUS_MORE_ENTRIES;
2666 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2668 return NT_STATUS_OK;
2673 lsa_OpenAccount
2675 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2676 struct lsa_OpenAccount *r)
2678 struct dcesrv_handle *h, *ah;
2679 struct lsa_policy_state *state;
2680 struct lsa_account_state *astate;
2682 ZERO_STRUCTP(r->out.acct_handle);
2684 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2686 state = h->data;
2688 astate = talloc(dce_call->conn, struct lsa_account_state);
2689 if (astate == NULL) {
2690 return NT_STATUS_NO_MEMORY;
2693 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2694 if (astate->account_sid == NULL) {
2695 talloc_free(astate);
2696 return NT_STATUS_NO_MEMORY;
2699 astate->policy = talloc_reference(astate, state);
2700 astate->access_mask = r->in.access_mask;
2703 * For now we grant all requested access.
2705 * We will fail at the ldb layer later.
2707 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2708 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2709 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2711 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2713 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2714 __func__, dom_sid_string(mem_ctx, astate->account_sid),
2715 (unsigned)r->in.access_mask,
2716 (unsigned)astate->access_mask));
2718 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2719 if (!ah) {
2720 talloc_free(astate);
2721 return NT_STATUS_NO_MEMORY;
2724 ah->data = talloc_steal(ah, astate);
2726 *r->out.acct_handle = ah->wire_handle;
2728 return NT_STATUS_OK;
2733 lsa_EnumPrivsAccount
2735 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2736 TALLOC_CTX *mem_ctx,
2737 struct lsa_EnumPrivsAccount *r)
2739 struct dcesrv_handle *h;
2740 struct lsa_account_state *astate;
2741 int ret;
2742 unsigned int i, j;
2743 struct ldb_message **res;
2744 const char * const attrs[] = { "privilege", NULL};
2745 struct ldb_message_element *el;
2746 const char *sidstr;
2747 struct lsa_PrivilegeSet *privs;
2749 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2751 astate = h->data;
2753 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2754 if (privs == NULL) {
2755 return NT_STATUS_NO_MEMORY;
2757 privs->count = 0;
2758 privs->unknown = 0;
2759 privs->set = NULL;
2761 *r->out.privs = privs;
2763 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2764 if (sidstr == NULL) {
2765 return NT_STATUS_NO_MEMORY;
2768 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2769 "objectSid=%s", sidstr);
2770 if (ret < 0) {
2771 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2773 if (ret != 1) {
2774 return NT_STATUS_OK;
2777 el = ldb_msg_find_element(res[0], "privilege");
2778 if (el == NULL || el->num_values == 0) {
2779 return NT_STATUS_OK;
2782 privs->set = talloc_array(privs,
2783 struct lsa_LUIDAttribute, el->num_values);
2784 if (privs->set == NULL) {
2785 return NT_STATUS_NO_MEMORY;
2788 j = 0;
2789 for (i=0;i<el->num_values;i++) {
2790 int id = sec_privilege_id((const char *)el->values[i].data);
2791 if (id == SEC_PRIV_INVALID) {
2792 /* Perhaps an account right, not a privilege */
2793 continue;
2795 privs->set[j].attribute = 0;
2796 privs->set[j].luid.low = id;
2797 privs->set[j].luid.high = 0;
2798 j++;
2801 privs->count = j;
2803 return NT_STATUS_OK;
2807 lsa_EnumAccountRights
2809 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2810 TALLOC_CTX *mem_ctx,
2811 struct lsa_EnumAccountRights *r)
2813 struct dcesrv_handle *h;
2814 struct lsa_policy_state *state;
2815 int ret;
2816 unsigned int i;
2817 struct ldb_message **res;
2818 const char * const attrs[] = { "privilege", NULL};
2819 const char *sidstr;
2820 struct ldb_message_element *el;
2822 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2824 state = h->data;
2826 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2827 if (sidstr == NULL) {
2828 return NT_STATUS_NO_MEMORY;
2831 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2832 "(&(objectSid=%s)(privilege=*))", sidstr);
2833 if (ret == 0) {
2834 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2836 if (ret != 1) {
2837 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2838 dom_sid_string(mem_ctx, r->in.sid),
2839 ldb_errstring(state->pdb)));
2840 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2843 el = ldb_msg_find_element(res[0], "privilege");
2844 if (el == NULL || el->num_values == 0) {
2845 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2848 r->out.rights->count = el->num_values;
2849 r->out.rights->names = talloc_array(r->out.rights,
2850 struct lsa_StringLarge, r->out.rights->count);
2851 if (r->out.rights->names == NULL) {
2852 return NT_STATUS_NO_MEMORY;
2855 for (i=0;i<el->num_values;i++) {
2856 r->out.rights->names[i].string = (const char *)el->values[i].data;
2859 return NT_STATUS_OK;
2865 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2867 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2868 TALLOC_CTX *mem_ctx,
2869 struct lsa_policy_state *state,
2870 int ldb_flag,
2871 struct dom_sid *sid,
2872 const struct lsa_RightSet *rights)
2874 const char *sidstr, *sidndrstr;
2875 struct ldb_message *msg;
2876 struct ldb_message_element *el;
2877 int ret;
2878 uint32_t i;
2879 struct lsa_EnumAccountRights r2;
2880 char *dnstr;
2882 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2883 SECURITY_ADMINISTRATOR) {
2884 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2885 return NT_STATUS_ACCESS_DENIED;
2888 msg = ldb_msg_new(mem_ctx);
2889 if (msg == NULL) {
2890 return NT_STATUS_NO_MEMORY;
2893 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2894 if (sidndrstr == NULL) {
2895 TALLOC_FREE(msg);
2896 return NT_STATUS_NO_MEMORY;
2899 sidstr = dom_sid_string(msg, sid);
2900 if (sidstr == NULL) {
2901 TALLOC_FREE(msg);
2902 return NT_STATUS_NO_MEMORY;
2905 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2906 if (dnstr == NULL) {
2907 TALLOC_FREE(msg);
2908 return NT_STATUS_NO_MEMORY;
2911 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2912 if (msg->dn == NULL) {
2913 TALLOC_FREE(msg);
2914 return NT_STATUS_NO_MEMORY;
2917 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2918 NTSTATUS status;
2920 r2.in.handle = &state->handle->wire_handle;
2921 r2.in.sid = sid;
2922 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2924 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2925 if (!NT_STATUS_IS_OK(status)) {
2926 ZERO_STRUCTP(r2.out.rights);
2930 for (i=0;i<rights->count;i++) {
2931 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2932 if (sec_right_bit(rights->names[i].string) == 0) {
2933 talloc_free(msg);
2934 return NT_STATUS_NO_SUCH_PRIVILEGE;
2937 talloc_free(msg);
2938 return NT_STATUS_NO_SUCH_PRIVILEGE;
2941 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2942 uint32_t j;
2943 for (j=0;j<r2.out.rights->count;j++) {
2944 if (strcasecmp_m(r2.out.rights->names[j].string,
2945 rights->names[i].string) == 0) {
2946 break;
2949 if (j != r2.out.rights->count) continue;
2952 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2953 if (ret != LDB_SUCCESS) {
2954 talloc_free(msg);
2955 return NT_STATUS_NO_MEMORY;
2959 el = ldb_msg_find_element(msg, "privilege");
2960 if (!el) {
2961 talloc_free(msg);
2962 return NT_STATUS_OK;
2965 el->flags = ldb_flag;
2967 ret = ldb_modify(state->pdb, msg);
2968 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2969 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2970 talloc_free(msg);
2971 return NT_STATUS_NO_MEMORY;
2973 ldb_msg_add_string(msg, "comment", "added via LSA");
2974 ret = ldb_add(state->pdb, msg);
2976 if (ret != LDB_SUCCESS) {
2977 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2978 talloc_free(msg);
2979 return NT_STATUS_OK;
2981 DEBUG(3, ("Could not %s attributes from %s: %s",
2982 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2983 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2984 talloc_free(msg);
2985 return NT_STATUS_UNEXPECTED_IO_ERROR;
2988 talloc_free(msg);
2989 return NT_STATUS_OK;
2993 lsa_AddPrivilegesToAccount
2995 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2996 struct lsa_AddPrivilegesToAccount *r)
2998 struct lsa_RightSet rights;
2999 struct dcesrv_handle *h;
3000 struct lsa_account_state *astate;
3001 uint32_t i;
3003 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3005 astate = h->data;
3007 rights.count = r->in.privs->count;
3008 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
3009 if (rights.names == NULL) {
3010 return NT_STATUS_NO_MEMORY;
3012 for (i=0;i<rights.count;i++) {
3013 int id = r->in.privs->set[i].luid.low;
3014 if (r->in.privs->set[i].luid.high) {
3015 return NT_STATUS_NO_SUCH_PRIVILEGE;
3017 rights.names[i].string = sec_privilege_name(id);
3018 if (rights.names[i].string == NULL) {
3019 return NT_STATUS_NO_SUCH_PRIVILEGE;
3023 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3024 LDB_FLAG_MOD_ADD, astate->account_sid,
3025 &rights);
3030 lsa_RemovePrivilegesFromAccount
3032 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3033 struct lsa_RemovePrivilegesFromAccount *r)
3035 struct lsa_RightSet *rights;
3036 struct dcesrv_handle *h;
3037 struct lsa_account_state *astate;
3038 uint32_t i;
3040 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3042 astate = h->data;
3044 rights = talloc(mem_ctx, struct lsa_RightSet);
3046 if (r->in.remove_all == 1 &&
3047 r->in.privs == NULL) {
3048 struct lsa_EnumAccountRights r2;
3049 NTSTATUS status;
3051 r2.in.handle = &astate->policy->handle->wire_handle;
3052 r2.in.sid = astate->account_sid;
3053 r2.out.rights = rights;
3055 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
3056 if (!NT_STATUS_IS_OK(status)) {
3057 return status;
3060 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3061 LDB_FLAG_MOD_DELETE, astate->account_sid,
3062 r2.out.rights);
3065 if (r->in.remove_all != 0) {
3066 return NT_STATUS_INVALID_PARAMETER;
3069 rights->count = r->in.privs->count;
3070 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
3071 if (rights->names == NULL) {
3072 return NT_STATUS_NO_MEMORY;
3074 for (i=0;i<rights->count;i++) {
3075 int id = r->in.privs->set[i].luid.low;
3076 if (r->in.privs->set[i].luid.high) {
3077 return NT_STATUS_NO_SUCH_PRIVILEGE;
3079 rights->names[i].string = sec_privilege_name(id);
3080 if (rights->names[i].string == NULL) {
3081 return NT_STATUS_NO_SUCH_PRIVILEGE;
3085 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3086 LDB_FLAG_MOD_DELETE, astate->account_sid,
3087 rights);
3092 lsa_GetQuotasForAccount
3094 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3095 struct lsa_GetQuotasForAccount *r)
3097 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3102 lsa_SetQuotasForAccount
3104 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3105 struct lsa_SetQuotasForAccount *r)
3107 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3112 lsa_GetSystemAccessAccount
3114 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3115 struct lsa_GetSystemAccessAccount *r)
3117 struct dcesrv_handle *h;
3118 struct lsa_account_state *astate;
3119 int ret;
3120 unsigned int i;
3121 struct ldb_message **res;
3122 const char * const attrs[] = { "privilege", NULL};
3123 struct ldb_message_element *el;
3124 const char *sidstr;
3126 *(r->out.access_mask) = 0x00000000;
3128 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3130 astate = h->data;
3132 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
3133 if (sidstr == NULL) {
3134 return NT_STATUS_NO_MEMORY;
3137 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
3138 "objectSid=%s", sidstr);
3139 if (ret < 0) {
3140 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3142 if (ret != 1) {
3143 return NT_STATUS_OK;
3146 el = ldb_msg_find_element(res[0], "privilege");
3147 if (el == NULL || el->num_values == 0) {
3148 return NT_STATUS_OK;
3151 for (i=0;i<el->num_values;i++) {
3152 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
3153 if (right_bit == 0) {
3154 /* Perhaps an privilege, not a right */
3155 continue;
3157 *(r->out.access_mask) |= right_bit;
3160 return NT_STATUS_OK;
3165 lsa_SetSystemAccessAccount
3167 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3168 struct lsa_SetSystemAccessAccount *r)
3170 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3175 lsa_CreateSecret
3177 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3178 struct lsa_CreateSecret *r)
3180 struct dcesrv_handle *policy_handle;
3181 struct lsa_policy_state *policy_state;
3182 struct lsa_secret_state *secret_state;
3183 struct dcesrv_handle *handle;
3184 struct ldb_message **msgs, *msg;
3185 const char *attrs[] = {
3186 NULL
3189 const char *name;
3191 int ret;
3193 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3194 ZERO_STRUCTP(r->out.sec_handle);
3196 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3198 case SECURITY_SYSTEM:
3199 case SECURITY_ADMINISTRATOR:
3200 break;
3201 default:
3202 /* Users and annonymous are not allowed create secrets */
3203 return NT_STATUS_ACCESS_DENIED;
3206 policy_state = policy_handle->data;
3208 if (!r->in.name.string) {
3209 return NT_STATUS_INVALID_PARAMETER;
3212 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3213 NT_STATUS_HAVE_NO_MEMORY(secret_state);
3214 secret_state->policy = policy_state;
3216 msg = ldb_msg_new(mem_ctx);
3217 if (msg == NULL) {
3218 return NT_STATUS_NO_MEMORY;
3221 if (strncmp("G$", r->in.name.string, 2) == 0) {
3222 const char *name2;
3224 secret_state->global = true;
3226 name = &r->in.name.string[2];
3227 if (strlen(name) == 0) {
3228 return NT_STATUS_INVALID_PARAMETER;
3231 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3232 ldb_binary_encode_string(mem_ctx, name));
3233 NT_STATUS_HAVE_NO_MEMORY(name2);
3235 /* We need to connect to the database as system, as this is one
3236 * of the rare RPC calls that must read the secrets (and this
3237 * is denied otherwise) */
3238 secret_state->sam_ldb = talloc_reference(secret_state,
3239 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));
3240 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3242 /* search for the secret record */
3243 ret = gendb_search(secret_state->sam_ldb,
3244 mem_ctx, policy_state->system_dn, &msgs, attrs,
3245 "(&(cn=%s)(objectclass=secret))",
3246 name2);
3247 if (ret > 0) {
3248 return NT_STATUS_OBJECT_NAME_COLLISION;
3251 if (ret < 0) {
3252 DEBUG(0,("Failure searching for CN=%s: %s\n",
3253 name2, ldb_errstring(secret_state->sam_ldb)));
3254 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3257 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3258 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3259 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3260 return NT_STATUS_NO_MEMORY;
3263 ret = ldb_msg_add_string(msg, "cn", name2);
3264 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3265 } else {
3266 secret_state->global = false;
3268 name = r->in.name.string;
3269 if (strlen(name) == 0) {
3270 return NT_STATUS_INVALID_PARAMETER;
3273 secret_state->sam_ldb = talloc_reference(secret_state,
3274 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3275 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3277 /* search for the secret record */
3278 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3279 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3280 &msgs, attrs,
3281 "(&(cn=%s)(objectclass=secret))",
3282 ldb_binary_encode_string(mem_ctx, name));
3283 if (ret > 0) {
3284 return NT_STATUS_OBJECT_NAME_COLLISION;
3287 if (ret < 0) {
3288 DEBUG(0,("Failure searching for CN=%s: %s\n",
3289 name, ldb_errstring(secret_state->sam_ldb)));
3290 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3293 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3294 "cn=%s,cn=LSA Secrets", name);
3295 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3296 ret = ldb_msg_add_string(msg, "cn", name);
3297 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3300 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3301 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3303 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3304 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3306 /* create the secret */
3307 ret = ldb_add(secret_state->sam_ldb, msg);
3308 if (ret != LDB_SUCCESS) {
3309 DEBUG(0,("Failed to create secret record %s: %s\n",
3310 ldb_dn_get_linearized(msg->dn),
3311 ldb_errstring(secret_state->sam_ldb)));
3312 return NT_STATUS_ACCESS_DENIED;
3315 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3316 NT_STATUS_HAVE_NO_MEMORY(handle);
3318 handle->data = talloc_steal(handle, secret_state);
3320 secret_state->access_mask = r->in.access_mask;
3321 secret_state->policy = talloc_reference(secret_state, policy_state);
3322 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3324 *r->out.sec_handle = handle->wire_handle;
3326 return NT_STATUS_OK;
3331 lsa_OpenSecret
3333 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3334 struct lsa_OpenSecret *r)
3336 struct dcesrv_handle *policy_handle;
3338 struct lsa_policy_state *policy_state;
3339 struct lsa_secret_state *secret_state;
3340 struct dcesrv_handle *handle;
3341 struct ldb_message **msgs;
3342 const char *attrs[] = {
3343 NULL
3346 const char *name;
3348 int ret;
3350 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3351 ZERO_STRUCTP(r->out.sec_handle);
3352 policy_state = policy_handle->data;
3354 if (!r->in.name.string) {
3355 return NT_STATUS_INVALID_PARAMETER;
3358 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3360 case SECURITY_SYSTEM:
3361 case SECURITY_ADMINISTRATOR:
3362 break;
3363 default:
3364 /* Users and annonymous are not allowed to access secrets */
3365 return NT_STATUS_ACCESS_DENIED;
3368 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3369 if (!secret_state) {
3370 return NT_STATUS_NO_MEMORY;
3372 secret_state->policy = policy_state;
3374 if (strncmp("G$", r->in.name.string, 2) == 0) {
3375 name = &r->in.name.string[2];
3376 /* 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) */
3377 secret_state->sam_ldb = talloc_reference(secret_state,
3378 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));
3379 secret_state->global = true;
3381 if (strlen(name) < 1) {
3382 return NT_STATUS_INVALID_PARAMETER;
3385 /* search for the secret record */
3386 ret = gendb_search(secret_state->sam_ldb,
3387 mem_ctx, policy_state->system_dn, &msgs, attrs,
3388 "(&(cn=%s Secret)(objectclass=secret))",
3389 ldb_binary_encode_string(mem_ctx, name));
3390 if (ret == 0) {
3391 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3394 if (ret != 1) {
3395 DEBUG(0,("Found %d records matching DN %s\n", ret,
3396 ldb_dn_get_linearized(policy_state->system_dn)));
3397 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3399 } else {
3400 secret_state->global = false;
3401 secret_state->sam_ldb = talloc_reference(secret_state,
3402 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3404 name = r->in.name.string;
3405 if (strlen(name) < 1) {
3406 return NT_STATUS_INVALID_PARAMETER;
3409 /* search for the secret record */
3410 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3411 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3412 &msgs, attrs,
3413 "(&(cn=%s)(objectclass=secret))",
3414 ldb_binary_encode_string(mem_ctx, name));
3415 if (ret == 0) {
3416 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3419 if (ret != 1) {
3420 DEBUG(0,("Found %d records matching CN=%s\n",
3421 ret, ldb_binary_encode_string(mem_ctx, name)));
3422 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3426 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3428 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3429 if (!handle) {
3430 return NT_STATUS_NO_MEMORY;
3433 handle->data = talloc_steal(handle, secret_state);
3435 secret_state->access_mask = r->in.access_mask;
3436 secret_state->policy = talloc_reference(secret_state, policy_state);
3438 *r->out.sec_handle = handle->wire_handle;
3440 return NT_STATUS_OK;
3445 lsa_SetSecret
3447 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3448 struct lsa_SetSecret *r)
3451 struct dcesrv_handle *h;
3452 struct lsa_secret_state *secret_state;
3453 struct ldb_message *msg;
3454 DATA_BLOB session_key;
3455 DATA_BLOB crypt_secret, secret;
3456 struct ldb_val val;
3457 int ret;
3458 NTSTATUS status = NT_STATUS_OK;
3460 struct timeval now = timeval_current();
3461 NTTIME nt_now = timeval_to_nttime(&now);
3463 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3465 secret_state = h->data;
3467 msg = ldb_msg_new(mem_ctx);
3468 if (msg == NULL) {
3469 return NT_STATUS_NO_MEMORY;
3472 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3473 if (!msg->dn) {
3474 return NT_STATUS_NO_MEMORY;
3476 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3477 if (!NT_STATUS_IS_OK(status)) {
3478 return status;
3481 if (r->in.old_val) {
3482 /* Decrypt */
3483 crypt_secret.data = r->in.old_val->data;
3484 crypt_secret.length = r->in.old_val->size;
3486 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3487 if (!NT_STATUS_IS_OK(status)) {
3488 return status;
3491 val.data = secret.data;
3492 val.length = secret.length;
3494 /* set value */
3495 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3496 return NT_STATUS_NO_MEMORY;
3499 /* set old value mtime */
3500 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3501 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3502 return NT_STATUS_NO_MEMORY;
3505 } else {
3506 /* If the old value is not set, then migrate the
3507 * current value to the old value */
3508 const struct ldb_val *old_val;
3509 NTTIME last_set_time;
3510 struct ldb_message **res;
3511 const char *attrs[] = {
3512 "currentValue",
3513 "lastSetTime",
3514 NULL
3517 /* search for the secret record */
3518 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3519 secret_state->secret_dn, &res, attrs);
3520 if (ret == 0) {
3521 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3524 if (ret != 1) {
3525 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3526 ldb_dn_get_linearized(secret_state->secret_dn)));
3527 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3530 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3531 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3533 if (old_val) {
3534 /* set old value */
3535 if (ldb_msg_add_value(msg, "priorValue",
3536 old_val, NULL) != LDB_SUCCESS) {
3537 return NT_STATUS_NO_MEMORY;
3539 } else {
3540 if (samdb_msg_add_delete(secret_state->sam_ldb,
3541 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3542 return NT_STATUS_NO_MEMORY;
3546 /* set old value mtime */
3547 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3548 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3549 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3550 return NT_STATUS_NO_MEMORY;
3552 } else {
3553 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3554 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3555 return NT_STATUS_NO_MEMORY;
3560 if (r->in.new_val) {
3561 /* Decrypt */
3562 crypt_secret.data = r->in.new_val->data;
3563 crypt_secret.length = r->in.new_val->size;
3565 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3566 if (!NT_STATUS_IS_OK(status)) {
3567 return status;
3570 val.data = secret.data;
3571 val.length = secret.length;
3573 /* set value */
3574 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3575 return NT_STATUS_NO_MEMORY;
3578 /* set new value mtime */
3579 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3580 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3581 return NT_STATUS_NO_MEMORY;
3583 } else {
3584 /* NULL out the NEW value */
3585 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3586 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3587 return NT_STATUS_NO_MEMORY;
3589 if (samdb_msg_add_delete(secret_state->sam_ldb,
3590 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3591 return NT_STATUS_NO_MEMORY;
3595 /* modify the samdb record */
3596 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3597 if (ret != LDB_SUCCESS) {
3598 return dsdb_ldb_err_to_ntstatus(ret);
3601 return NT_STATUS_OK;
3606 lsa_QuerySecret
3608 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3609 struct lsa_QuerySecret *r)
3611 struct dcesrv_handle *h;
3612 struct lsa_secret_state *secret_state;
3613 struct ldb_message *msg;
3614 DATA_BLOB session_key;
3615 DATA_BLOB crypt_secret, secret;
3616 int ret;
3617 struct ldb_message **res;
3618 const char *attrs[] = {
3619 "currentValue",
3620 "priorValue",
3621 "lastSetTime",
3622 "priorSetTime",
3623 NULL
3626 NTSTATUS nt_status;
3628 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3630 /* Ensure user is permitted to read this... */
3631 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3633 case SECURITY_SYSTEM:
3634 case SECURITY_ADMINISTRATOR:
3635 break;
3636 default:
3637 /* Users and annonymous are not allowed to read secrets */
3638 return NT_STATUS_ACCESS_DENIED;
3641 secret_state = h->data;
3643 /* pull all the user attributes */
3644 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3645 secret_state->secret_dn, &res, attrs);
3646 if (ret != 1) {
3647 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3649 msg = res[0];
3651 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3652 if (!NT_STATUS_IS_OK(nt_status)) {
3653 return nt_status;
3656 if (r->in.old_val) {
3657 const struct ldb_val *prior_val;
3658 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3659 if (!r->out.old_val) {
3660 return NT_STATUS_NO_MEMORY;
3662 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3664 if (prior_val && prior_val->length) {
3665 secret.data = prior_val->data;
3666 secret.length = prior_val->length;
3668 /* Encrypt */
3669 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3670 if (!crypt_secret.length) {
3671 return NT_STATUS_NO_MEMORY;
3673 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3674 if (!r->out.old_val->buf) {
3675 return NT_STATUS_NO_MEMORY;
3677 r->out.old_val->buf->size = crypt_secret.length;
3678 r->out.old_val->buf->length = crypt_secret.length;
3679 r->out.old_val->buf->data = crypt_secret.data;
3683 if (r->in.old_mtime) {
3684 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3685 if (!r->out.old_mtime) {
3686 return NT_STATUS_NO_MEMORY;
3688 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3691 if (r->in.new_val) {
3692 const struct ldb_val *new_val;
3693 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3694 if (!r->out.new_val) {
3695 return NT_STATUS_NO_MEMORY;
3698 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3700 if (new_val && new_val->length) {
3701 secret.data = new_val->data;
3702 secret.length = new_val->length;
3704 /* Encrypt */
3705 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3706 if (!crypt_secret.length) {
3707 return NT_STATUS_NO_MEMORY;
3709 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3710 if (!r->out.new_val->buf) {
3711 return NT_STATUS_NO_MEMORY;
3713 r->out.new_val->buf->length = crypt_secret.length;
3714 r->out.new_val->buf->size = crypt_secret.length;
3715 r->out.new_val->buf->data = crypt_secret.data;
3719 if (r->in.new_mtime) {
3720 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3721 if (!r->out.new_mtime) {
3722 return NT_STATUS_NO_MEMORY;
3724 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3727 return NT_STATUS_OK;
3732 lsa_LookupPrivValue
3734 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3735 TALLOC_CTX *mem_ctx,
3736 struct lsa_LookupPrivValue *r)
3738 struct dcesrv_handle *h;
3739 int id;
3741 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3743 id = sec_privilege_id(r->in.name->string);
3744 if (id == SEC_PRIV_INVALID) {
3745 return NT_STATUS_NO_SUCH_PRIVILEGE;
3748 r->out.luid->low = id;
3749 r->out.luid->high = 0;
3751 return NT_STATUS_OK;
3756 lsa_LookupPrivName
3758 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3759 TALLOC_CTX *mem_ctx,
3760 struct lsa_LookupPrivName *r)
3762 struct dcesrv_handle *h;
3763 struct lsa_StringLarge *name;
3764 const char *privname;
3766 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3768 if (r->in.luid->high != 0) {
3769 return NT_STATUS_NO_SUCH_PRIVILEGE;
3772 privname = sec_privilege_name(r->in.luid->low);
3773 if (privname == NULL) {
3774 return NT_STATUS_NO_SUCH_PRIVILEGE;
3777 name = talloc(mem_ctx, struct lsa_StringLarge);
3778 if (name == NULL) {
3779 return NT_STATUS_NO_MEMORY;
3782 name->string = privname;
3784 *r->out.name = name;
3786 return NT_STATUS_OK;
3791 lsa_LookupPrivDisplayName
3793 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3794 TALLOC_CTX *mem_ctx,
3795 struct lsa_LookupPrivDisplayName *r)
3797 struct dcesrv_handle *h;
3798 struct lsa_StringLarge *disp_name = NULL;
3799 enum sec_privilege id;
3801 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3803 id = sec_privilege_id(r->in.name->string);
3804 if (id == SEC_PRIV_INVALID) {
3805 return NT_STATUS_NO_SUCH_PRIVILEGE;
3808 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3809 if (disp_name == NULL) {
3810 return NT_STATUS_NO_MEMORY;
3813 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3814 if (disp_name->string == NULL) {
3815 return NT_STATUS_INTERNAL_ERROR;
3818 *r->out.disp_name = disp_name;
3819 *r->out.returned_language_id = 0;
3821 return NT_STATUS_OK;
3826 lsa_EnumAccountsWithUserRight
3828 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3829 TALLOC_CTX *mem_ctx,
3830 struct lsa_EnumAccountsWithUserRight *r)
3832 struct dcesrv_handle *h;
3833 struct lsa_policy_state *state;
3834 int ret, i;
3835 struct ldb_message **res;
3836 const char * const attrs[] = { "objectSid", NULL};
3837 const char *privname;
3839 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3841 state = h->data;
3843 if (r->in.name == NULL) {
3844 return NT_STATUS_NO_SUCH_PRIVILEGE;
3847 privname = r->in.name->string;
3848 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3849 return NT_STATUS_NO_SUCH_PRIVILEGE;
3852 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3853 "privilege=%s", privname);
3854 if (ret < 0) {
3855 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3857 if (ret == 0) {
3858 return NT_STATUS_NO_MORE_ENTRIES;
3861 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3862 if (r->out.sids->sids == NULL) {
3863 return NT_STATUS_NO_MEMORY;
3865 for (i=0;i<ret;i++) {
3866 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3867 res[i], "objectSid");
3868 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3870 r->out.sids->num_sids = ret;
3872 return NT_STATUS_OK;
3877 lsa_AddAccountRights
3879 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3880 TALLOC_CTX *mem_ctx,
3881 struct lsa_AddAccountRights *r)
3883 struct dcesrv_handle *h;
3884 struct lsa_policy_state *state;
3886 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3888 state = h->data;
3890 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3891 LDB_FLAG_MOD_ADD,
3892 r->in.sid, r->in.rights);
3897 lsa_RemoveAccountRights
3899 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3900 TALLOC_CTX *mem_ctx,
3901 struct lsa_RemoveAccountRights *r)
3903 struct dcesrv_handle *h;
3904 struct lsa_policy_state *state;
3906 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3908 state = h->data;
3910 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3911 LDB_FLAG_MOD_DELETE,
3912 r->in.sid, r->in.rights);
3917 lsa_StorePrivateData
3919 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3920 struct lsa_StorePrivateData *r)
3922 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3927 lsa_RetrievePrivateData
3929 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3930 struct lsa_RetrievePrivateData *r)
3932 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3937 lsa_GetUserName
3939 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3940 struct lsa_GetUserName *r)
3942 enum dcerpc_transport_t transport =
3943 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3944 NTSTATUS status = NT_STATUS_OK;
3945 const char *account_name;
3946 const char *authority_name;
3947 struct lsa_String *_account_name;
3948 struct lsa_String *_authority_name = NULL;
3950 if (transport != NCACN_NP && transport != NCALRPC) {
3951 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3954 /* this is what w2k3 does */
3955 r->out.account_name = r->in.account_name;
3956 r->out.authority_name = r->in.authority_name;
3958 if (r->in.account_name
3959 && *r->in.account_name
3960 /* && *(*r->in.account_name)->string */
3962 return NT_STATUS_INVALID_PARAMETER;
3965 if (r->in.authority_name
3966 && *r->in.authority_name
3967 /* && *(*r->in.authority_name)->string */
3969 return NT_STATUS_INVALID_PARAMETER;
3972 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3973 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3975 _account_name = talloc(mem_ctx, struct lsa_String);
3976 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3977 _account_name->string = account_name;
3979 if (r->in.authority_name) {
3980 _authority_name = talloc(mem_ctx, struct lsa_String);
3981 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3982 _authority_name->string = authority_name;
3985 *r->out.account_name = _account_name;
3986 if (r->out.authority_name) {
3987 *r->out.authority_name = _authority_name;
3990 return status;
3994 lsa_SetInfoPolicy2
3996 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3997 TALLOC_CTX *mem_ctx,
3998 struct lsa_SetInfoPolicy2 *r)
4000 /* need to support these */
4001 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4004 static void kdc_get_policy(struct loadparm_context *lp_ctx,
4005 struct smb_krb5_context *smb_krb5_context,
4006 struct lsa_DomainInfoKerberos *k)
4008 time_t svc_tkt_lifetime;
4009 time_t usr_tkt_lifetime;
4010 time_t renewal_lifetime;
4012 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
4014 /* Our KDC always re-validates the client */
4015 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
4017 lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
4018 &usr_tkt_lifetime, &renewal_lifetime);
4020 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
4021 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
4022 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
4023 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
4024 However in the parent function we basically just did a full
4025 krb5_context init with the only purpose of getting a global
4026 config option (the max skew), it would probably make more sense
4027 to have a lp_ or ldb global option as the samba default */
4028 if (smb_krb5_context) {
4029 unix_to_nt_time(&k->clock_skew,
4030 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
4032 #endif
4033 k->reserved = 0;
4036 lsa_QueryDomainInformationPolicy
4038 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4039 TALLOC_CTX *mem_ctx,
4040 struct lsa_QueryDomainInformationPolicy *r)
4042 union lsa_DomainInformationPolicy *info;
4044 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
4045 if (!info) {
4046 return NT_STATUS_NO_MEMORY;
4049 switch (r->in.level) {
4050 case LSA_DOMAIN_INFO_POLICY_EFS:
4051 talloc_free(info);
4052 *r->out.info = NULL;
4053 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4054 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
4056 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
4057 struct smb_krb5_context *smb_krb5_context;
4058 int ret = smb_krb5_init_context(mem_ctx,
4059 dce_call->conn->dce_ctx->lp_ctx,
4060 &smb_krb5_context);
4061 if (ret != 0) {
4062 talloc_free(info);
4063 *r->out.info = NULL;
4064 return NT_STATUS_INTERNAL_ERROR;
4066 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
4067 smb_krb5_context,
4069 talloc_free(smb_krb5_context);
4070 *r->out.info = info;
4071 return NT_STATUS_OK;
4073 default:
4074 talloc_free(info);
4075 *r->out.info = NULL;
4076 return NT_STATUS_INVALID_INFO_CLASS;
4081 lsa_SetDomInfoPolicy
4083 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4084 TALLOC_CTX *mem_ctx,
4085 struct lsa_SetDomainInformationPolicy *r)
4087 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4091 lsa_TestCall
4093 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
4094 TALLOC_CTX *mem_ctx,
4095 struct lsa_TestCall *r)
4097 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4101 lsa_CREDRWRITE
4103 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4104 struct lsa_CREDRWRITE *r)
4106 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4111 lsa_CREDRREAD
4113 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4114 struct lsa_CREDRREAD *r)
4116 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4121 lsa_CREDRENUMERATE
4123 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4124 struct lsa_CREDRENUMERATE *r)
4126 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4131 lsa_CREDRWRITEDOMAINCREDENTIALS
4133 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4134 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
4136 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4141 lsa_CREDRREADDOMAINCREDENTIALS
4143 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4144 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
4146 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4151 lsa_CREDRDELETE
4153 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4154 struct lsa_CREDRDELETE *r)
4156 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4161 lsa_CREDRGETTARGETINFO
4163 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4164 struct lsa_CREDRGETTARGETINFO *r)
4166 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4171 lsa_CREDRPROFILELOADED
4173 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4174 struct lsa_CREDRPROFILELOADED *r)
4176 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4181 lsa_CREDRGETSESSIONTYPES
4183 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4184 struct lsa_CREDRGETSESSIONTYPES *r)
4186 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4191 lsa_LSARREGISTERAUDITEVENT
4193 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4194 struct lsa_LSARREGISTERAUDITEVENT *r)
4196 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4201 lsa_LSARGENAUDITEVENT
4203 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4204 struct lsa_LSARGENAUDITEVENT *r)
4206 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4211 lsa_LSARUNREGISTERAUDITEVENT
4213 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4214 struct lsa_LSARUNREGISTERAUDITEVENT *r)
4216 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4221 lsa_lsaRQueryForestTrustInformation
4223 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4224 struct lsa_lsaRQueryForestTrustInformation *r)
4226 struct dcesrv_handle *h = NULL;
4227 struct lsa_policy_state *p_state = NULL;
4228 int forest_level = DS_DOMAIN_FUNCTION_2000;
4229 const char * const trust_attrs[] = {
4230 "securityIdentifier",
4231 "flatName",
4232 "trustPartner",
4233 "trustAttributes",
4234 "trustDirection",
4235 "trustType",
4236 "msDS-TrustForestTrustInfo",
4237 NULL
4239 struct ldb_message *trust_tdo_msg = NULL;
4240 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4241 struct ForestTrustInfo *trust_fti = NULL;
4242 struct lsa_ForestTrustInformation *trust_lfti = NULL;
4243 NTSTATUS status;
4245 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4247 p_state = h->data;
4249 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4250 return NT_STATUS_INVALID_DOMAIN_STATE;
4253 forest_level = dsdb_forest_functional_level(p_state->sam_ldb);
4254 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4255 return NT_STATUS_INVALID_DOMAIN_STATE;
4258 if (r->in.trusted_domain_name->string == NULL) {
4259 return NT_STATUS_NO_SUCH_DOMAIN;
4262 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4263 r->in.trusted_domain_name->string,
4264 r->in.trusted_domain_name->string,
4265 trust_attrs, mem_ctx, &trust_tdo_msg);
4266 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4267 return NT_STATUS_NO_SUCH_DOMAIN;
4269 if (!NT_STATUS_IS_OK(status)) {
4270 return status;
4273 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4274 if (!NT_STATUS_IS_OK(status)) {
4275 return status;
4278 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4279 return NT_STATUS_INVALID_PARAMETER;
4282 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4283 return NT_STATUS_INVALID_PARAMETER;
4286 status = dsdb_trust_parse_forest_info(mem_ctx,
4287 trust_tdo_msg,
4288 &trust_fti);
4289 if (!NT_STATUS_IS_OK(status)) {
4290 return status;
4293 status = dsdb_trust_forest_info_to_lsa(mem_ctx, trust_fti,
4294 &trust_lfti);
4295 if (!NT_STATUS_IS_OK(status)) {
4296 return status;
4299 *r->out.forest_trust_info = trust_lfti;
4300 return NT_STATUS_OK;
4304 lsa_lsaRSetForestTrustInformation
4306 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4307 TALLOC_CTX *mem_ctx,
4308 struct lsa_lsaRSetForestTrustInformation *r)
4310 struct dcesrv_handle *h;
4311 struct lsa_policy_state *p_state;
4312 const char * const trust_attrs[] = {
4313 "securityIdentifier",
4314 "flatName",
4315 "trustPartner",
4316 "trustAttributes",
4317 "trustDirection",
4318 "trustType",
4319 "msDS-TrustForestTrustInfo",
4320 NULL
4322 struct ldb_message *trust_tdo_msg = NULL;
4323 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4324 struct lsa_ForestTrustInformation *step1_lfti = NULL;
4325 struct lsa_ForestTrustInformation *step2_lfti = NULL;
4326 struct ForestTrustInfo *trust_fti = NULL;
4327 struct ldb_result *trusts_res = NULL;
4328 unsigned int i;
4329 struct lsa_TrustDomainInfoInfoEx *xref_tdo = NULL;
4330 struct lsa_ForestTrustInformation *xref_lfti = NULL;
4331 struct lsa_ForestTrustCollisionInfo *c_info = NULL;
4332 DATA_BLOB ft_blob = {};
4333 struct ldb_message *msg = NULL;
4334 NTSTATUS status;
4335 enum ndr_err_code ndr_err;
4336 int ret;
4337 bool in_transaction = false;
4339 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4341 p_state = h->data;
4343 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4344 return NT_STATUS_INVALID_DOMAIN_STATE;
4347 if (r->in.check_only == 0) {
4348 ret = ldb_transaction_start(p_state->sam_ldb);
4349 if (ret != LDB_SUCCESS) {
4350 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4352 in_transaction = true;
4356 * abort if we are not a PDC
4358 * In future we should use a function like IsEffectiveRoleOwner()
4360 if (!samdb_is_pdc(p_state->sam_ldb)) {
4361 status = NT_STATUS_INVALID_DOMAIN_ROLE;
4362 goto done;
4365 if (r->in.trusted_domain_name->string == NULL) {
4366 status = NT_STATUS_NO_SUCH_DOMAIN;
4367 goto done;
4370 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4371 r->in.trusted_domain_name->string,
4372 r->in.trusted_domain_name->string,
4373 trust_attrs, mem_ctx, &trust_tdo_msg);
4374 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4375 status = NT_STATUS_NO_SUCH_DOMAIN;
4376 goto done;
4378 if (!NT_STATUS_IS_OK(status)) {
4379 goto done;
4382 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4383 if (!NT_STATUS_IS_OK(status)) {
4384 goto done;
4387 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4388 status = NT_STATUS_INVALID_PARAMETER;
4389 goto done;
4392 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4393 status = NT_STATUS_INVALID_PARAMETER;
4394 goto done;
4398 * verify and normalize the given forest trust info.
4400 * Step1: doesn't reorder yet, so step1_lfti might contain
4401 * NULL entries. This means dsdb_trust_verify_forest_info()
4402 * can generate collision entries with the callers index.
4404 status = dsdb_trust_normalize_forest_info_step1(mem_ctx,
4405 r->in.forest_trust_info,
4406 &step1_lfti);
4407 if (!NT_STATUS_IS_OK(status)) {
4408 goto done;
4411 c_info = talloc_zero(r->out.collision_info,
4412 struct lsa_ForestTrustCollisionInfo);
4413 if (c_info == NULL) {
4414 status = NT_STATUS_NO_MEMORY;
4415 goto done;
4419 * First check our own forest, then other domains/forests
4422 status = dsdb_trust_xref_tdo_info(mem_ctx, p_state->sam_ldb,
4423 &xref_tdo);
4424 if (!NT_STATUS_IS_OK(status)) {
4425 goto done;
4427 status = dsdb_trust_xref_forest_info(mem_ctx, p_state->sam_ldb,
4428 &xref_lfti);
4429 if (!NT_STATUS_IS_OK(status)) {
4430 goto done;
4434 * The documentation proposed to generate
4435 * LSA_FOREST_TRUST_COLLISION_XREF collisions.
4436 * But Windows always uses LSA_FOREST_TRUST_COLLISION_TDO.
4438 status = dsdb_trust_verify_forest_info(xref_tdo, xref_lfti,
4439 LSA_FOREST_TRUST_COLLISION_TDO,
4440 c_info, step1_lfti);
4441 if (!NT_STATUS_IS_OK(status)) {
4442 goto done;
4445 /* fetch all other trusted domain objects */
4446 status = dsdb_trust_search_tdos(p_state->sam_ldb,
4447 trust_tdo->domain_name.string,
4448 trust_attrs,
4449 mem_ctx, &trusts_res);
4450 if (!NT_STATUS_IS_OK(status)) {
4451 goto done;
4455 * now check against the other domains.
4456 * and generate LSA_FOREST_TRUST_COLLISION_TDO collisions.
4458 for (i = 0; i < trusts_res->count; i++) {
4459 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
4460 struct ForestTrustInfo *fti = NULL;
4461 struct lsa_ForestTrustInformation *lfti = NULL;
4463 status = dsdb_trust_parse_tdo_info(mem_ctx,
4464 trusts_res->msgs[i],
4465 &tdo);
4466 if (!NT_STATUS_IS_OK(status)) {
4467 goto done;
4470 status = dsdb_trust_parse_forest_info(tdo,
4471 trusts_res->msgs[i],
4472 &fti);
4473 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
4474 continue;
4476 if (!NT_STATUS_IS_OK(status)) {
4477 goto done;
4480 status = dsdb_trust_forest_info_to_lsa(tdo, fti, &lfti);
4481 if (!NT_STATUS_IS_OK(status)) {
4482 goto done;
4485 status = dsdb_trust_verify_forest_info(tdo, lfti,
4486 LSA_FOREST_TRUST_COLLISION_TDO,
4487 c_info, step1_lfti);
4488 if (!NT_STATUS_IS_OK(status)) {
4489 goto done;
4492 TALLOC_FREE(tdo);
4495 if (r->in.check_only != 0) {
4496 status = NT_STATUS_OK;
4497 goto done;
4501 * not just a check, write info back
4505 * normalize the given forest trust info.
4507 * Step2: adds TOP_LEVEL_NAME[_EX] in reverse order,
4508 * followed by DOMAIN_INFO in reverse order. It also removes
4509 * possible NULL entries from Step1.
4511 status = dsdb_trust_normalize_forest_info_step2(mem_ctx, step1_lfti,
4512 &step2_lfti);
4513 if (!NT_STATUS_IS_OK(status)) {
4514 goto done;
4517 status = dsdb_trust_forest_info_from_lsa(mem_ctx, step2_lfti,
4518 &trust_fti);
4519 if (!NT_STATUS_IS_OK(status)) {
4520 goto done;
4523 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, trust_fti,
4524 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4525 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4526 status = NT_STATUS_INVALID_PARAMETER;
4527 goto done;
4530 msg = ldb_msg_new(mem_ctx);
4531 if (msg == NULL) {
4532 status = NT_STATUS_NO_MEMORY;
4533 goto done;
4536 msg->dn = ldb_dn_copy(mem_ctx, trust_tdo_msg->dn);
4537 if (!msg->dn) {
4538 status = NT_STATUS_NO_MEMORY;
4539 goto done;
4542 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4543 LDB_FLAG_MOD_REPLACE, NULL);
4544 if (ret != LDB_SUCCESS) {
4545 status = NT_STATUS_NO_MEMORY;
4546 goto done;
4548 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4549 &ft_blob, NULL);
4550 if (ret != LDB_SUCCESS) {
4551 status = NT_STATUS_NO_MEMORY;
4552 goto done;
4555 ret = ldb_modify(p_state->sam_ldb, msg);
4556 if (ret != LDB_SUCCESS) {
4557 status = dsdb_ldb_err_to_ntstatus(ret);
4559 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4560 ldb_errstring(p_state->sam_ldb)));
4562 goto done;
4565 /* ok, all fine, commit transaction and return */
4566 in_transaction = false;
4567 ret = ldb_transaction_commit(p_state->sam_ldb);
4568 if (ret != LDB_SUCCESS) {
4569 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4570 goto done;
4573 status = NT_STATUS_OK;
4575 done:
4576 if (NT_STATUS_IS_OK(status) && c_info->count != 0) {
4577 *r->out.collision_info = c_info;
4580 if (in_transaction) {
4581 ldb_transaction_cancel(p_state->sam_ldb);
4584 return status;
4588 lsa_CREDRRENAME
4590 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4591 struct lsa_CREDRRENAME *r)
4593 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4599 lsa_LSAROPENPOLICYSCE
4601 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4602 struct lsa_LSAROPENPOLICYSCE *r)
4604 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4609 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4611 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4612 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4614 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4619 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4621 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4622 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4624 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4629 lsa_LSARADTREPORTSECURITYEVENT
4631 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4632 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4634 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4638 /* include the generated boilerplate */
4639 #include "librpc/gen_ndr/ndr_lsa_s.c"
4643 /*****************************************
4644 NOTE! The remaining calls below were
4645 removed in w2k3, so the DCESRV_FAULT()
4646 replies are the correct implementation. Do
4647 not try and fill these in with anything else
4648 ******************************************/
4651 dssetup_DsRoleDnsNameToFlatName
4653 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4654 struct dssetup_DsRoleDnsNameToFlatName *r)
4656 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4661 dssetup_DsRoleDcAsDc
4663 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4664 struct dssetup_DsRoleDcAsDc *r)
4666 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4671 dssetup_DsRoleDcAsReplica
4673 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4674 struct dssetup_DsRoleDcAsReplica *r)
4676 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4681 dssetup_DsRoleDemoteDc
4683 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4684 struct dssetup_DsRoleDemoteDc *r)
4686 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4691 dssetup_DsRoleGetDcOperationProgress
4693 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4694 struct dssetup_DsRoleGetDcOperationProgress *r)
4696 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4701 dssetup_DsRoleGetDcOperationResults
4703 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4704 struct dssetup_DsRoleGetDcOperationResults *r)
4706 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4711 dssetup_DsRoleCancel
4713 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4714 struct dssetup_DsRoleCancel *r)
4716 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4721 dssetup_DsRoleServerSaveStateForUpgrade
4723 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4724 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4726 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4731 dssetup_DsRoleUpgradeDownlevelServer
4733 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4734 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4736 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4741 dssetup_DsRoleAbortDownlevelServerUpgrade
4743 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4744 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4746 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4750 /* include the generated boilerplate */
4751 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4753 NTSTATUS dcerpc_server_lsa_init(void)
4755 NTSTATUS ret;
4757 ret = dcerpc_server_dssetup_init();
4758 if (!NT_STATUS_IS_OK(ret)) {
4759 return ret;
4761 ret = dcerpc_server_lsarpc_init();
4762 if (!NT_STATUS_IS_OK(ret)) {
4763 return ret;
4765 return ret;