s4:rpc_server: make it possible to specify ncacn_np_secondary_endpoint
[Samba.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
blobc1bc78aa9d057e717534bcdd0c58e6d0f75c5af3
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(context, iface) \
39 dcesrv_interface_lsarpc_bind(context, iface)
40 static NTSTATUS dcesrv_interface_lsarpc_bind(struct dcesrv_connection_context *context,
41 const struct dcesrv_interface *iface)
43 return dcesrv_interface_bind_reject_connect(context, iface);
46 static NTSTATUS lsarpc__op_init_server(struct dcesrv_context *dce_ctx,
47 const struct dcesrv_endpoint_server *ep_server);
48 static const struct dcesrv_interface dcesrv_lsarpc_interface;
50 #define DCESRV_INTERFACE_LSARPC_INIT_SERVER \
51 dcesrv_interface_lsarpc_init_server
52 static NTSTATUS dcesrv_interface_lsarpc_init_server(struct dcesrv_context *dce_ctx,
53 const struct dcesrv_endpoint_server *ep_server)
55 if (lpcfg_lsa_over_netlogon(dce_ctx->lp_ctx)) {
56 NTSTATUS ret = dcesrv_interface_register(dce_ctx,
57 "ncacn_np:[\\pipe\\netlogon]",
58 NULL,
59 &dcesrv_lsarpc_interface, NULL);
60 if (!NT_STATUS_IS_OK(ret)) {
61 DEBUG(1,("lsarpc_op_init_server: failed to register endpoint '\\pipe\\netlogon'\n"));
62 return ret;
65 return lsarpc__op_init_server(dce_ctx, ep_server);
69 this type allows us to distinguish handle types
73 state associated with a lsa_OpenAccount() operation
75 struct lsa_account_state {
76 struct lsa_policy_state *policy;
77 uint32_t access_mask;
78 struct dom_sid *account_sid;
83 state associated with a lsa_OpenSecret() operation
85 struct lsa_secret_state {
86 struct lsa_policy_state *policy;
87 uint32_t access_mask;
88 struct ldb_dn *secret_dn;
89 struct ldb_context *sam_ldb;
90 bool global;
94 state associated with a lsa_OpenTrustedDomain() operation
96 struct lsa_trusted_domain_state {
97 struct lsa_policy_state *policy;
98 uint32_t access_mask;
99 struct ldb_dn *trusted_domain_dn;
100 struct ldb_dn *trusted_domain_user_dn;
103 static bool dcesrc_lsa_valid_AccountRight(const char *right)
105 enum sec_privilege priv_id;
106 uint32_t right_bit;
108 priv_id = sec_privilege_id(right);
109 if (priv_id != SEC_PRIV_INVALID) {
110 return true;
113 right_bit = sec_right_bit(right);
114 if (right_bit != 0) {
115 return true;
118 return false;
122 this is based on the samba3 function make_lsa_object_sd()
123 It uses the same logic, but with samba4 helper functions
125 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
126 struct security_descriptor **sd,
127 struct dom_sid *sid,
128 uint32_t sid_access)
130 NTSTATUS status;
131 uint32_t rid;
132 struct dom_sid *domain_sid, *domain_admins_sid;
133 const char *domain_admins_sid_str, *sidstr;
134 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
136 status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
137 if (!NT_STATUS_IS_OK(status)) {
138 TALLOC_FREE(tmp_ctx);
139 return status;
142 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
143 if (domain_admins_sid == NULL) {
144 TALLOC_FREE(tmp_ctx);
145 return NT_STATUS_NO_MEMORY;
148 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
149 if (domain_admins_sid_str == NULL) {
150 TALLOC_FREE(tmp_ctx);
151 return NT_STATUS_NO_MEMORY;
154 sidstr = dom_sid_string(tmp_ctx, sid);
155 if (sidstr == NULL) {
156 TALLOC_FREE(tmp_ctx);
157 return NT_STATUS_NO_MEMORY;
160 *sd = security_descriptor_dacl_create(mem_ctx,
161 0, sidstr, NULL,
163 SID_WORLD,
164 SEC_ACE_TYPE_ACCESS_ALLOWED,
165 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
167 SID_BUILTIN_ADMINISTRATORS,
168 SEC_ACE_TYPE_ACCESS_ALLOWED,
169 SEC_GENERIC_ALL, 0,
171 SID_BUILTIN_ACCOUNT_OPERATORS,
172 SEC_ACE_TYPE_ACCESS_ALLOWED,
173 SEC_GENERIC_ALL, 0,
175 domain_admins_sid_str,
176 SEC_ACE_TYPE_ACCESS_ALLOWED,
177 SEC_GENERIC_ALL, 0,
179 sidstr,
180 SEC_ACE_TYPE_ACCESS_ALLOWED,
181 sid_access, 0,
183 NULL);
184 talloc_free(tmp_ctx);
186 NT_STATUS_HAVE_NO_MEMORY(*sd);
188 return NT_STATUS_OK;
192 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
193 TALLOC_CTX *mem_ctx,
194 struct lsa_EnumAccountRights *r);
196 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
197 TALLOC_CTX *mem_ctx,
198 struct lsa_policy_state *state,
199 int ldb_flag,
200 struct dom_sid *sid,
201 const struct lsa_RightSet *rights);
204 lsa_Close
206 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
207 struct lsa_Close *r)
209 enum dcerpc_transport_t transport =
210 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
211 struct dcesrv_handle *h;
213 if (transport != NCACN_NP && transport != NCALRPC) {
214 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
217 *r->out.handle = *r->in.handle;
219 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
221 talloc_free(h);
223 ZERO_STRUCTP(r->out.handle);
225 return NT_STATUS_OK;
230 lsa_Delete
232 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
233 struct lsa_Delete *r)
235 return NT_STATUS_NOT_SUPPORTED;
240 lsa_DeleteObject
242 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
243 struct lsa_DeleteObject *r)
245 struct auth_session_info *session_info =
246 dcesrv_call_session_info(dce_call);
247 struct dcesrv_handle *h;
248 int ret;
250 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
252 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
253 struct lsa_secret_state *secret_state = h->data;
255 /* Ensure user is permitted to delete this... */
256 switch (security_session_user_level(session_info, NULL))
258 case SECURITY_SYSTEM:
259 case SECURITY_ADMINISTRATOR:
260 break;
261 default:
262 /* Users and anonymous are not allowed to delete things */
263 return NT_STATUS_ACCESS_DENIED;
266 ret = ldb_delete(secret_state->sam_ldb,
267 secret_state->secret_dn);
268 if (ret != LDB_SUCCESS) {
269 return NT_STATUS_INVALID_HANDLE;
272 ZERO_STRUCTP(r->out.handle);
274 return NT_STATUS_OK;
276 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
277 struct lsa_trusted_domain_state *trusted_domain_state =
278 talloc_get_type(h->data, struct lsa_trusted_domain_state);
279 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
280 if (ret != LDB_SUCCESS) {
281 return NT_STATUS_INTERNAL_DB_CORRUPTION;
284 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
285 trusted_domain_state->trusted_domain_dn);
286 if (ret != LDB_SUCCESS) {
287 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
288 return NT_STATUS_INVALID_HANDLE;
291 if (trusted_domain_state->trusted_domain_user_dn) {
292 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
293 trusted_domain_state->trusted_domain_user_dn);
294 if (ret != LDB_SUCCESS) {
295 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
296 return NT_STATUS_INVALID_HANDLE;
300 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
301 if (ret != LDB_SUCCESS) {
302 return NT_STATUS_INTERNAL_DB_CORRUPTION;
305 ZERO_STRUCTP(r->out.handle);
307 return NT_STATUS_OK;
309 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
310 struct lsa_RightSet *rights;
311 struct lsa_account_state *astate;
312 struct lsa_EnumAccountRights r2;
313 NTSTATUS status;
315 rights = talloc(mem_ctx, struct lsa_RightSet);
317 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
319 astate = h->data;
321 r2.in.handle = &astate->policy->handle->wire_handle;
322 r2.in.sid = astate->account_sid;
323 r2.out.rights = rights;
325 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
326 but we have a LSA_HANDLE_ACCOUNT here, so this call
327 will always fail */
328 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
329 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
330 return NT_STATUS_OK;
333 if (!NT_STATUS_IS_OK(status)) {
334 return status;
337 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
338 LDB_FLAG_MOD_DELETE, astate->account_sid,
339 r2.out.rights);
340 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
341 return NT_STATUS_OK;
344 if (!NT_STATUS_IS_OK(status)) {
345 return status;
348 ZERO_STRUCTP(r->out.handle);
350 return NT_STATUS_OK;
353 return NT_STATUS_INVALID_HANDLE;
358 lsa_EnumPrivs
360 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
361 struct lsa_EnumPrivs *r)
363 struct dcesrv_handle *h;
364 uint32_t i;
365 enum sec_privilege priv;
366 const char *privname;
368 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
370 i = *r->in.resume_handle;
372 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
373 r->out.privs->count < r->in.max_count) {
374 struct lsa_PrivEntry *e;
375 privname = sec_privilege_name(priv);
376 r->out.privs->privs = talloc_realloc(r->out.privs,
377 r->out.privs->privs,
378 struct lsa_PrivEntry,
379 r->out.privs->count+1);
380 if (r->out.privs->privs == NULL) {
381 return NT_STATUS_NO_MEMORY;
383 e = &r->out.privs->privs[r->out.privs->count];
384 e->luid.low = priv;
385 e->luid.high = 0;
386 e->name.string = privname;
387 r->out.privs->count++;
388 i++;
391 *r->out.resume_handle = i;
393 return NT_STATUS_OK;
398 lsa_QuerySecObj
400 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
401 struct lsa_QuerySecurity *r)
403 struct auth_session_info *session_info =
404 dcesrv_call_session_info(dce_call);
405 struct dcesrv_handle *h;
406 const struct security_descriptor *sd = NULL;
407 uint32_t access_granted = 0;
408 struct sec_desc_buf *sdbuf = NULL;
409 NTSTATUS status;
410 struct dom_sid *sid;
412 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
414 sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
416 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
417 struct lsa_policy_state *pstate = h->data;
419 sd = pstate->sd;
420 access_granted = pstate->access_mask;
422 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
423 struct lsa_account_state *astate = h->data;
424 struct security_descriptor *_sd = NULL;
426 status = dcesrv_build_lsa_sd(mem_ctx, &_sd, sid,
427 LSA_ACCOUNT_ALL_ACCESS);
428 if (!NT_STATUS_IS_OK(status)) {
429 return status;
431 sd = _sd;
432 access_granted = astate->access_mask;
433 } else {
434 return NT_STATUS_INVALID_HANDLE;
437 sdbuf = talloc_zero(mem_ctx, struct sec_desc_buf);
438 if (sdbuf == NULL) {
439 return NT_STATUS_NO_MEMORY;
442 status = security_descriptor_for_client(sdbuf, sd, r->in.sec_info,
443 access_granted, &sdbuf->sd);
444 if (!NT_STATUS_IS_OK(status)) {
445 return status;
448 *r->out.sdbuf = sdbuf;
450 return NT_STATUS_OK;
455 lsa_SetSecObj
457 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
458 struct lsa_SetSecObj *r)
460 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
465 lsa_ChangePassword
467 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
468 struct lsa_ChangePassword *r)
470 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
474 dssetup_DsRoleGetPrimaryDomainInformation
476 This is not an LSA call, but is the only call left on the DSSETUP
477 pipe (after the pipe was truncated), and needs lsa_get_policy_state
479 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
480 TALLOC_CTX *mem_ctx,
481 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
483 union dssetup_DsRoleInfo *info;
485 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
486 W_ERROR_HAVE_NO_MEMORY(info);
488 switch (r->in.level) {
489 case DS_ROLE_BASIC_INFORMATION:
491 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
492 uint32_t flags = 0;
493 const char *domain = NULL;
494 const char *dns_domain = NULL;
495 const char *forest = NULL;
496 struct GUID domain_guid;
497 struct lsa_policy_state *state;
499 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
500 0, /* we skip access checks */
501 &state);
502 if (!NT_STATUS_IS_OK(status)) {
503 return ntstatus_to_werror(status);
506 ZERO_STRUCT(domain_guid);
508 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
509 case ROLE_STANDALONE:
510 role = DS_ROLE_STANDALONE_SERVER;
511 break;
512 case ROLE_DOMAIN_MEMBER:
513 role = DS_ROLE_MEMBER_SERVER;
514 break;
515 case ROLE_ACTIVE_DIRECTORY_DC:
516 if (samdb_is_pdc(state->sam_ldb)) {
517 role = DS_ROLE_PRIMARY_DC;
518 } else {
519 role = DS_ROLE_BACKUP_DC;
521 break;
524 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
525 case ROLE_STANDALONE:
526 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
527 W_ERROR_HAVE_NO_MEMORY(domain);
528 break;
529 case ROLE_DOMAIN_MEMBER:
530 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
531 W_ERROR_HAVE_NO_MEMORY(domain);
532 /* TODO: what is with dns_domain and forest and guid? */
533 break;
534 case ROLE_ACTIVE_DIRECTORY_DC:
535 flags = DS_ROLE_PRIMARY_DS_RUNNING;
537 if (state->mixed_domain == 1) {
538 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
541 domain = state->domain_name;
542 dns_domain = state->domain_dns;
543 forest = state->forest_dns;
545 domain_guid = state->domain_guid;
546 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
547 break;
550 info->basic.role = role;
551 info->basic.flags = flags;
552 info->basic.domain = domain;
553 info->basic.dns_domain = dns_domain;
554 info->basic.forest = forest;
555 info->basic.domain_guid = domain_guid;
557 r->out.info = info;
558 return WERR_OK;
560 case DS_ROLE_UPGRADE_STATUS:
562 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
563 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
565 r->out.info = info;
566 return WERR_OK;
568 case DS_ROLE_OP_STATUS:
570 info->opstatus.status = DS_ROLE_OP_IDLE;
572 r->out.info = info;
573 return WERR_OK;
575 default:
576 return WERR_INVALID_PARAMETER;
581 fill in the AccountDomain info
583 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
584 struct lsa_DomainInfo *info)
586 info->name.string = state->domain_name;
587 info->sid = state->domain_sid;
589 return NT_STATUS_OK;
593 fill in the DNS domain info
595 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
596 struct lsa_DnsDomainInfo *info)
598 info->name.string = state->domain_name;
599 info->sid = state->domain_sid;
600 info->dns_domain.string = state->domain_dns;
601 info->dns_forest.string = state->forest_dns;
602 info->domain_guid = state->domain_guid;
604 return NT_STATUS_OK;
608 lsa_QueryInfoPolicy2
610 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
611 struct lsa_QueryInfoPolicy2 *r)
613 struct lsa_policy_state *state;
614 struct dcesrv_handle *h;
615 union lsa_PolicyInformation *info;
617 *r->out.info = NULL;
619 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
621 state = h->data;
623 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
624 if (!info) {
625 return NT_STATUS_NO_MEMORY;
627 *r->out.info = info;
629 switch (r->in.level) {
630 case LSA_POLICY_INFO_AUDIT_LOG:
631 /* we don't need to fill in any of this */
632 ZERO_STRUCT(info->audit_log);
633 return NT_STATUS_OK;
634 case LSA_POLICY_INFO_AUDIT_EVENTS:
635 /* we don't need to fill in any of this */
636 ZERO_STRUCT(info->audit_events);
637 return NT_STATUS_OK;
638 case LSA_POLICY_INFO_PD:
639 /* we don't need to fill in any of this */
640 ZERO_STRUCT(info->pd);
641 return NT_STATUS_OK;
643 case LSA_POLICY_INFO_DOMAIN:
644 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
645 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
646 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
647 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
648 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
650 case LSA_POLICY_INFO_ROLE:
651 info->role.role = LSA_ROLE_PRIMARY;
652 return NT_STATUS_OK;
654 case LSA_POLICY_INFO_DNS:
655 case LSA_POLICY_INFO_DNS_INT:
656 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
658 case LSA_POLICY_INFO_REPLICA:
659 ZERO_STRUCT(info->replica);
660 return NT_STATUS_OK;
662 case LSA_POLICY_INFO_QUOTA:
663 ZERO_STRUCT(info->quota);
664 return NT_STATUS_OK;
666 case LSA_POLICY_INFO_MOD:
667 case LSA_POLICY_INFO_AUDIT_FULL_SET:
668 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
669 /* windows gives INVALID_PARAMETER */
670 *r->out.info = NULL;
671 return NT_STATUS_INVALID_PARAMETER;
674 *r->out.info = NULL;
675 return NT_STATUS_INVALID_INFO_CLASS;
679 lsa_QueryInfoPolicy
681 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
682 struct lsa_QueryInfoPolicy *r)
684 struct lsa_QueryInfoPolicy2 r2;
685 NTSTATUS status;
687 ZERO_STRUCT(r2);
689 r2.in.handle = r->in.handle;
690 r2.in.level = r->in.level;
691 r2.out.info = r->out.info;
693 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
695 return status;
699 lsa_SetInfoPolicy
701 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
702 struct lsa_SetInfoPolicy *r)
704 /* need to support this */
705 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
710 lsa_ClearAuditLog
712 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
713 struct lsa_ClearAuditLog *r)
715 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
719 static const struct generic_mapping dcesrv_lsa_account_mapping = {
720 LSA_ACCOUNT_READ,
721 LSA_ACCOUNT_WRITE,
722 LSA_ACCOUNT_EXECUTE,
723 LSA_ACCOUNT_ALL_ACCESS
727 lsa_CreateAccount
729 This call does not seem to have any long-term effects, hence no database operations
731 we need to talk to the MS product group to find out what this account database means!
733 answer is that the lsa database is totally separate from the SAM and
734 ldap databases. We are going to need a separate ldb to store these
735 accounts. The SIDs on this account bear no relation to the SIDs in
738 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
739 struct lsa_CreateAccount *r)
741 struct lsa_account_state *astate;
743 struct lsa_policy_state *state;
744 struct dcesrv_handle *h, *ah;
746 ZERO_STRUCTP(r->out.acct_handle);
748 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
750 state = h->data;
752 astate = talloc(dce_call->conn, struct lsa_account_state);
753 if (astate == NULL) {
754 return NT_STATUS_NO_MEMORY;
757 astate->account_sid = dom_sid_dup(astate, r->in.sid);
758 if (astate->account_sid == NULL) {
759 talloc_free(astate);
760 return NT_STATUS_NO_MEMORY;
763 astate->policy = talloc_reference(astate, state);
764 astate->access_mask = r->in.access_mask;
767 * For now we grant all requested access.
769 * We will fail at the ldb layer later.
771 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
772 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
773 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
775 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
777 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X].\n",
778 __func__, dom_sid_string(mem_ctx, astate->account_sid),
779 (unsigned)r->in.access_mask,
780 (unsigned)astate->access_mask));
782 ah = dcesrv_handle_create(dce_call, LSA_HANDLE_ACCOUNT);
783 if (!ah) {
784 talloc_free(astate);
785 return NT_STATUS_NO_MEMORY;
788 ah->data = talloc_steal(ah, astate);
790 *r->out.acct_handle = ah->wire_handle;
792 return NT_STATUS_OK;
797 lsa_EnumAccounts
799 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
800 struct lsa_EnumAccounts *r)
802 struct dcesrv_handle *h;
803 struct lsa_policy_state *state;
804 int ret;
805 struct ldb_message **res;
806 const char * const attrs[] = { "objectSid", NULL};
807 uint32_t count, i;
809 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
811 state = h->data;
813 /* NOTE: This call must only return accounts that have at least
814 one privilege set
816 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
817 "(&(objectSid=*)(privilege=*))");
818 if (ret < 0) {
819 return NT_STATUS_INTERNAL_DB_CORRUPTION;
822 if (*r->in.resume_handle >= ret) {
823 return NT_STATUS_NO_MORE_ENTRIES;
826 count = ret - *r->in.resume_handle;
827 if (count > r->in.num_entries) {
828 count = r->in.num_entries;
831 if (count == 0) {
832 return NT_STATUS_NO_MORE_ENTRIES;
835 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
836 if (r->out.sids->sids == NULL) {
837 return NT_STATUS_NO_MEMORY;
840 for (i=0;i<count;i++) {
841 r->out.sids->sids[i].sid =
842 samdb_result_dom_sid(r->out.sids->sids,
843 res[i + *r->in.resume_handle],
844 "objectSid");
845 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
848 r->out.sids->num_sids = count;
849 *r->out.resume_handle = count + *r->in.resume_handle;
851 return NT_STATUS_OK;
854 /* This decrypts and returns Trusted Domain Auth Information Internal data */
855 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
856 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
857 struct trustDomainPasswords *auth_struct)
859 DATA_BLOB session_key = data_blob(NULL, 0);
860 enum ndr_err_code ndr_err;
861 NTSTATUS nt_status;
863 nt_status = dcesrv_transport_session_key(dce_call, &session_key);
864 if (!NT_STATUS_IS_OK(nt_status)) {
865 return nt_status;
868 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
869 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
870 auth_struct,
871 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
872 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
873 return NT_STATUS_INVALID_PARAMETER;
876 return NT_STATUS_OK;
879 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
880 TALLOC_CTX *mem_ctx,
881 struct trustAuthInOutBlob *iopw,
882 DATA_BLOB *trustauth_blob)
884 enum ndr_err_code ndr_err;
886 if (iopw->current.count != iopw->count) {
887 return NT_STATUS_INVALID_PARAMETER;
890 if (iopw->previous.count > iopw->current.count) {
891 return NT_STATUS_INVALID_PARAMETER;
894 if (iopw->previous.count == 0) {
896 * If the previous credentials are not present
897 * we need to make a copy.
899 iopw->previous = iopw->current;
902 if (iopw->previous.count < iopw->current.count) {
903 struct AuthenticationInformationArray *c = &iopw->current;
904 struct AuthenticationInformationArray *p = &iopw->previous;
907 * The previous array needs to have the same size
908 * as the current one.
910 * We may have to fill with TRUST_AUTH_TYPE_NONE
911 * elements.
913 p->array = talloc_realloc(mem_ctx, p->array,
914 struct AuthenticationInformation,
915 c->count);
916 if (p->array == NULL) {
917 return NT_STATUS_NO_MEMORY;
920 while (p->count < c->count) {
921 struct AuthenticationInformation *a =
922 &p->array[p->count++];
924 *a = (struct AuthenticationInformation) {
925 .LastUpdateTime = p->array[0].LastUpdateTime,
926 .AuthType = TRUST_AUTH_TYPE_NONE,
931 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
932 iopw,
933 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
934 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
935 return NT_STATUS_INVALID_PARAMETER;
938 return NT_STATUS_OK;
941 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
942 struct ldb_context *sam_ldb,
943 struct ldb_dn *base_dn,
944 const char *netbios_name,
945 struct trustAuthInOutBlob *in,
946 struct ldb_dn **user_dn)
948 struct ldb_request *req;
949 struct ldb_message *msg;
950 struct ldb_dn *dn;
951 uint32_t i;
952 int ret;
954 dn = ldb_dn_copy(mem_ctx, base_dn);
955 if (!dn) {
956 return NT_STATUS_NO_MEMORY;
958 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
959 return NT_STATUS_NO_MEMORY;
962 msg = ldb_msg_new(mem_ctx);
963 if (!msg) {
964 return NT_STATUS_NO_MEMORY;
966 msg->dn = dn;
968 ret = ldb_msg_add_string(msg, "objectClass", "user");
969 if (ret != LDB_SUCCESS) {
970 return NT_STATUS_NO_MEMORY;
973 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
974 if (ret != LDB_SUCCESS) {
975 return NT_STATUS_NO_MEMORY;
978 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
979 UF_INTERDOMAIN_TRUST_ACCOUNT);
980 if (ret != LDB_SUCCESS) {
981 return NT_STATUS_NO_MEMORY;
984 for (i = 0; i < in->count; i++) {
985 const char *attribute;
986 struct ldb_val v;
987 switch (in->current.array[i].AuthType) {
988 case TRUST_AUTH_TYPE_NT4OWF:
989 attribute = "unicodePwd";
990 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
991 v.length = 16;
992 break;
993 case TRUST_AUTH_TYPE_CLEAR:
994 attribute = "clearTextPassword";
995 v.data = in->current.array[i].AuthInfo.clear.password;
996 v.length = in->current.array[i].AuthInfo.clear.size;
997 break;
998 default:
999 continue;
1002 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1003 if (ret != LDB_SUCCESS) {
1004 return NT_STATUS_NO_MEMORY;
1008 /* create the trusted_domain user account */
1009 ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
1010 ldb_op_default_callback, NULL);
1011 if (ret != LDB_SUCCESS) {
1012 return NT_STATUS_NO_MEMORY;
1015 ret = ldb_request_add_control(req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
1016 false, NULL);
1017 if (ret != LDB_SUCCESS) {
1018 return NT_STATUS_NO_MEMORY;
1021 ret = dsdb_autotransaction_request(sam_ldb, req);
1022 if (ret != LDB_SUCCESS) {
1023 DEBUG(0,("Failed to create user record %s: %s\n",
1024 ldb_dn_get_linearized(msg->dn),
1025 ldb_errstring(sam_ldb)));
1027 switch (ret) {
1028 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1029 return NT_STATUS_DOMAIN_EXISTS;
1030 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1031 return NT_STATUS_ACCESS_DENIED;
1032 default:
1033 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1037 if (user_dn) {
1038 *user_dn = dn;
1040 return NT_STATUS_OK;
1044 lsa_CreateTrustedDomainEx2
1046 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
1047 TALLOC_CTX *mem_ctx,
1048 struct lsa_CreateTrustedDomainEx2 *r,
1049 int op,
1050 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
1052 struct dcesrv_handle *policy_handle;
1053 struct lsa_policy_state *policy_state;
1054 struct lsa_trusted_domain_state *trusted_domain_state;
1055 struct dcesrv_handle *handle;
1056 struct ldb_message **msgs, *msg;
1057 const char *attrs[] = {
1058 NULL
1060 const char *netbios_name;
1061 const char *dns_name;
1062 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1063 struct trustDomainPasswords auth_struct;
1064 int ret;
1065 NTSTATUS nt_status;
1066 struct ldb_context *sam_ldb;
1067 struct server_id *server_ids = NULL;
1068 uint32_t num_server_ids = 0;
1069 NTSTATUS status;
1070 bool ok;
1071 char *dns_encoded = NULL;
1072 char *netbios_encoded = NULL;
1073 char *sid_encoded = NULL;
1075 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
1076 ZERO_STRUCTP(r->out.trustdom_handle);
1078 policy_state = policy_handle->data;
1079 sam_ldb = policy_state->sam_ldb;
1081 netbios_name = r->in.info->netbios_name.string;
1082 if (!netbios_name) {
1083 return NT_STATUS_INVALID_PARAMETER;
1086 dns_name = r->in.info->domain_name.string;
1087 if (dns_name == NULL) {
1088 return NT_STATUS_INVALID_PARAMETER;
1091 if (r->in.info->sid == NULL) {
1092 return NT_STATUS_INVALID_SID;
1096 * We expect S-1-5-21-A-B-C, but we don't
1097 * allow S-1-5-21-0-0-0 as this is used
1098 * for claims and compound identities.
1100 ok = dom_sid_is_valid_account_domain(r->in.info->sid);
1101 if (!ok) {
1102 return NT_STATUS_INVALID_PARAMETER;
1105 dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1106 if (dns_encoded == NULL) {
1107 return NT_STATUS_NO_MEMORY;
1109 netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1110 if (netbios_encoded == NULL) {
1111 return NT_STATUS_NO_MEMORY;
1113 sid_encoded = ldap_encode_ndr_dom_sid(mem_ctx, r->in.info->sid);
1114 if (sid_encoded == NULL) {
1115 return NT_STATUS_NO_MEMORY;
1118 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1119 if (!trusted_domain_state) {
1120 return NT_STATUS_NO_MEMORY;
1122 trusted_domain_state->policy = policy_state;
1124 if (strcasecmp(netbios_name, "BUILTIN") == 0
1125 || (strcasecmp(dns_name, "BUILTIN") == 0)
1126 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
1127 return NT_STATUS_INVALID_PARAMETER;
1130 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
1131 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
1132 || strcasecmp(dns_name, policy_state->domain_dns) == 0
1133 || strcasecmp(dns_name, policy_state->domain_name) == 0
1134 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
1135 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
1138 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
1139 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
1140 /* No secrets are created at this time, for this function */
1141 auth_struct.outgoing.count = 0;
1142 auth_struct.incoming.count = 0;
1143 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
1144 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
1145 r->in.auth_info_internal->auth_blob.size);
1146 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1147 &auth_blob, &auth_struct);
1148 if (!NT_STATUS_IS_OK(nt_status)) {
1149 return nt_status;
1151 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
1153 if (unencrypted_auth_info->incoming_count > 1) {
1154 return NT_STATUS_INVALID_PARAMETER;
1157 /* more investigation required here, do not create secrets for
1158 * now */
1159 auth_struct.outgoing.count = 0;
1160 auth_struct.incoming.count = 0;
1161 } else {
1162 return NT_STATUS_INVALID_PARAMETER;
1165 if (auth_struct.incoming.count) {
1166 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1167 &auth_struct.incoming,
1168 &trustAuthIncoming);
1169 if (!NT_STATUS_IS_OK(nt_status)) {
1170 return nt_status;
1172 } else {
1173 trustAuthIncoming = data_blob(NULL, 0);
1176 if (auth_struct.outgoing.count) {
1177 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1178 &auth_struct.outgoing,
1179 &trustAuthOutgoing);
1180 if (!NT_STATUS_IS_OK(nt_status)) {
1181 return nt_status;
1183 } else {
1184 trustAuthOutgoing = data_blob(NULL, 0);
1187 ret = ldb_transaction_start(sam_ldb);
1188 if (ret != LDB_SUCCESS) {
1189 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1192 /* search for the trusted_domain record */
1193 ret = gendb_search(sam_ldb,
1194 mem_ctx, policy_state->system_dn, &msgs, attrs,
1195 "(&(objectClass=trustedDomain)(|"
1196 "(flatname=%s)(trustPartner=%s)"
1197 "(flatname=%s)(trustPartner=%s)"
1198 "(securityIdentifier=%s)))",
1199 dns_encoded, dns_encoded,
1200 netbios_encoded, netbios_encoded,
1201 sid_encoded);
1202 if (ret > 0) {
1203 ldb_transaction_cancel(sam_ldb);
1204 return NT_STATUS_OBJECT_NAME_COLLISION;
1206 if (ret < 0) {
1207 ldb_transaction_cancel(sam_ldb);
1208 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1211 msg = ldb_msg_new(mem_ctx);
1212 if (msg == NULL) {
1213 return NT_STATUS_NO_MEMORY;
1216 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1217 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", dns_name)) {
1218 ldb_transaction_cancel(sam_ldb);
1219 return NT_STATUS_NO_MEMORY;
1222 ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1223 if (ret != LDB_SUCCESS) {
1224 ldb_transaction_cancel(sam_ldb);
1225 return NT_STATUS_NO_MEMORY;;
1228 ret = ldb_msg_add_string(msg, "flatname", netbios_name);
1229 if (ret != LDB_SUCCESS) {
1230 ldb_transaction_cancel(sam_ldb);
1231 return NT_STATUS_NO_MEMORY;
1234 ret = ldb_msg_add_string(msg, "trustPartner", dns_name);
1235 if (ret != LDB_SUCCESS) {
1236 ldb_transaction_cancel(sam_ldb);
1237 return NT_STATUS_NO_MEMORY;;
1240 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier",
1241 r->in.info->sid);
1242 if (ret != LDB_SUCCESS) {
1243 ldb_transaction_cancel(sam_ldb);
1244 return NT_STATUS_NO_MEMORY;;
1247 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1248 if (ret != LDB_SUCCESS) {
1249 ldb_transaction_cancel(sam_ldb);
1250 return NT_STATUS_NO_MEMORY;;
1253 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1254 if (ret != LDB_SUCCESS) {
1255 ldb_transaction_cancel(sam_ldb);
1256 return NT_STATUS_NO_MEMORY;;
1259 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1260 if (ret != LDB_SUCCESS) {
1261 ldb_transaction_cancel(sam_ldb);
1262 return NT_STATUS_NO_MEMORY;;
1265 if (trustAuthIncoming.data) {
1266 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1267 if (ret != LDB_SUCCESS) {
1268 ldb_transaction_cancel(sam_ldb);
1269 return NT_STATUS_NO_MEMORY;
1272 if (trustAuthOutgoing.data) {
1273 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1274 if (ret != LDB_SUCCESS) {
1275 ldb_transaction_cancel(sam_ldb);
1276 return NT_STATUS_NO_MEMORY;
1280 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1282 /* create the trusted_domain */
1283 ret = ldb_add(sam_ldb, msg);
1284 switch (ret) {
1285 case LDB_SUCCESS:
1286 break;
1287 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1288 ldb_transaction_cancel(sam_ldb);
1289 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1290 ldb_dn_get_linearized(msg->dn),
1291 ldb_errstring(sam_ldb)));
1292 return NT_STATUS_DOMAIN_EXISTS;
1293 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1294 ldb_transaction_cancel(sam_ldb);
1295 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1296 ldb_dn_get_linearized(msg->dn),
1297 ldb_errstring(sam_ldb)));
1298 return NT_STATUS_ACCESS_DENIED;
1299 default:
1300 ldb_transaction_cancel(sam_ldb);
1301 DEBUG(0,("Failed to create user record %s: %s\n",
1302 ldb_dn_get_linearized(msg->dn),
1303 ldb_errstring(sam_ldb)));
1304 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1307 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1308 struct ldb_dn *user_dn;
1309 /* Inbound trusts must also create a cn=users object to match */
1310 nt_status = add_trust_user(mem_ctx, sam_ldb,
1311 policy_state->domain_dn,
1312 netbios_name,
1313 &auth_struct.incoming,
1314 &user_dn);
1315 if (!NT_STATUS_IS_OK(nt_status)) {
1316 ldb_transaction_cancel(sam_ldb);
1317 return nt_status;
1320 /* save the trust user dn */
1321 trusted_domain_state->trusted_domain_user_dn
1322 = talloc_steal(trusted_domain_state, user_dn);
1325 ret = ldb_transaction_commit(sam_ldb);
1326 if (ret != LDB_SUCCESS) {
1327 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1331 * Notify winbindd that we have a new trust
1333 status = irpc_servers_byname(dce_call->msg_ctx,
1334 mem_ctx,
1335 "winbind_server",
1336 &num_server_ids, &server_ids);
1337 if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
1338 imessaging_send(dce_call->msg_ctx, server_ids[0],
1339 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS, NULL);
1341 TALLOC_FREE(server_ids);
1343 handle = dcesrv_handle_create(dce_call, LSA_HANDLE_TRUSTED_DOMAIN);
1344 if (!handle) {
1345 return NT_STATUS_NO_MEMORY;
1348 handle->data = talloc_steal(handle, trusted_domain_state);
1350 trusted_domain_state->access_mask = r->in.access_mask;
1351 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1353 *r->out.trustdom_handle = handle->wire_handle;
1355 return NT_STATUS_OK;
1359 lsa_CreateTrustedDomainEx2
1361 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1362 TALLOC_CTX *mem_ctx,
1363 struct lsa_CreateTrustedDomainEx2 *r)
1365 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1368 lsa_CreateTrustedDomainEx
1370 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1371 TALLOC_CTX *mem_ctx,
1372 struct lsa_CreateTrustedDomainEx *r)
1374 struct lsa_CreateTrustedDomainEx2 r2;
1376 r2.in.policy_handle = r->in.policy_handle;
1377 r2.in.info = r->in.info;
1378 r2.out.trustdom_handle = r->out.trustdom_handle;
1379 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1383 lsa_CreateTrustedDomain
1385 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1386 struct lsa_CreateTrustedDomain *r)
1388 struct lsa_CreateTrustedDomainEx2 r2;
1390 r2.in.policy_handle = r->in.policy_handle;
1391 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1392 if (!r2.in.info) {
1393 return NT_STATUS_NO_MEMORY;
1396 r2.in.info->domain_name = r->in.info->name;
1397 r2.in.info->netbios_name = r->in.info->name;
1398 r2.in.info->sid = r->in.info->sid;
1399 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1400 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1401 r2.in.info->trust_attributes = 0;
1403 r2.in.access_mask = r->in.access_mask;
1404 r2.out.trustdom_handle = r->out.trustdom_handle;
1406 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1409 static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
1410 struct dcesrv_call_state *dce_call,
1411 TALLOC_CTX *tmp_mem,
1412 struct lsa_policy_state *policy_state,
1413 const char *filter,
1414 uint32_t access_mask,
1415 struct dcesrv_handle **_handle)
1417 struct lsa_trusted_domain_state *trusted_domain_state;
1418 struct dcesrv_handle *handle;
1419 struct ldb_message **msgs;
1420 const char *attrs[] = {
1421 "trustDirection",
1422 "flatname",
1423 NULL
1425 uint32_t direction;
1426 int ret;
1428 /* TODO: perform access checks */
1430 /* search for the trusted_domain record */
1431 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1432 policy_state->system_dn,
1433 &msgs, attrs, "%s", filter);
1434 if (ret == 0) {
1435 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1438 if (ret != 1) {
1439 DEBUG(0,("Found %d records matching %s under %s\n", ret,
1440 filter,
1441 ldb_dn_get_linearized(policy_state->system_dn)));
1442 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1445 trusted_domain_state = talloc_zero(tmp_mem,
1446 struct lsa_trusted_domain_state);
1447 if (!trusted_domain_state) {
1448 return NT_STATUS_NO_MEMORY;
1450 trusted_domain_state->policy = policy_state;
1452 trusted_domain_state->trusted_domain_dn =
1453 talloc_steal(trusted_domain_state, msgs[0]->dn);
1455 direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1456 if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1457 const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1458 "flatname", NULL);
1460 /* search for the trusted_domain account */
1461 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1462 policy_state->domain_dn,
1463 &msgs, attrs,
1464 "(&(samaccountname=%s$)(objectclass=user)"
1465 "(userAccountControl:%s:=%u))",
1466 flatname,
1467 LDB_OID_COMPARATOR_AND,
1468 UF_INTERDOMAIN_TRUST_ACCOUNT);
1469 if (ret == 1) {
1470 trusted_domain_state->trusted_domain_user_dn =
1471 talloc_steal(trusted_domain_state, msgs[0]->dn);
1475 handle = dcesrv_handle_create(dce_call, LSA_HANDLE_TRUSTED_DOMAIN);
1476 if (!handle) {
1477 return NT_STATUS_NO_MEMORY;
1480 handle->data = talloc_steal(handle, trusted_domain_state);
1482 trusted_domain_state->access_mask = access_mask;
1483 trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1484 policy_state);
1486 *_handle = handle;
1488 return NT_STATUS_OK;
1492 lsa_OpenTrustedDomain
1494 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1495 struct lsa_OpenTrustedDomain *r)
1497 struct dcesrv_handle *policy_handle;
1498 struct lsa_policy_state *policy_state;
1499 struct dcesrv_handle *handle;
1500 const char *sid_string;
1501 char *filter;
1502 NTSTATUS status;
1504 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1505 ZERO_STRUCTP(r->out.trustdom_handle);
1506 policy_state = policy_handle->data;
1508 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1509 if (!sid_string) {
1510 return NT_STATUS_NO_MEMORY;
1513 filter = talloc_asprintf(mem_ctx,
1514 "(&(securityIdentifier=%s)"
1515 "(objectclass=trustedDomain))",
1516 sid_string);
1517 if (filter == NULL) {
1518 return NT_STATUS_NO_MEMORY;
1521 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1522 policy_state,
1523 filter,
1524 r->in.access_mask,
1525 &handle);
1526 if (!NT_STATUS_IS_OK(status)) {
1527 return status;
1530 *r->out.trustdom_handle = handle->wire_handle;
1532 return NT_STATUS_OK;
1537 lsa_OpenTrustedDomainByName
1539 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1540 TALLOC_CTX *mem_ctx,
1541 struct lsa_OpenTrustedDomainByName *r)
1543 struct dcesrv_handle *policy_handle;
1544 struct lsa_policy_state *policy_state;
1545 struct dcesrv_handle *handle;
1546 char *td_name;
1547 char *filter;
1548 NTSTATUS status;
1550 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1551 ZERO_STRUCTP(r->out.trustdom_handle);
1552 policy_state = policy_handle->data;
1554 if (!r->in.name.string) {
1555 return NT_STATUS_INVALID_PARAMETER;
1558 /* search for the trusted_domain record */
1559 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1560 if (td_name == NULL) {
1561 return NT_STATUS_NO_MEMORY;
1564 filter = talloc_asprintf(mem_ctx,
1565 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1566 "(objectclass=trustedDomain))",
1567 td_name, td_name, td_name);
1568 if (filter == NULL) {
1569 return NT_STATUS_NO_MEMORY;
1572 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1573 policy_state,
1574 filter,
1575 r->in.access_mask,
1576 &handle);
1577 if (!NT_STATUS_IS_OK(status)) {
1578 return status;
1581 *r->out.trustdom_handle = handle->wire_handle;
1583 return NT_STATUS_OK;
1589 lsa_SetTrustedDomainInfo
1591 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1592 struct lsa_SetTrustedDomainInfo *r)
1594 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1599 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1600 * otherwise at least one must be provided */
1601 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1602 struct ldb_dn *basedn, const char *dns_domain,
1603 const char *netbios, struct dom_sid2 *sid,
1604 struct ldb_message ***msgs)
1606 const char *attrs[] = { "flatname", "trustPartner",
1607 "securityIdentifier", "trustDirection",
1608 "trustType", "trustAttributes",
1609 "trustPosixOffset",
1610 "msDs-supportedEncryptionTypes",
1611 "msDS-TrustForestTrustInfo",
1612 NULL
1614 char *dns = NULL;
1615 char *nbn = NULL;
1616 char *sidstr = NULL;
1617 char *filter;
1618 int ret;
1621 if (dns_domain || netbios || sid) {
1622 filter = talloc_strdup(mem_ctx,
1623 "(&(objectclass=trustedDomain)(|");
1624 } else {
1625 filter = talloc_strdup(mem_ctx,
1626 "(objectclass=trustedDomain)");
1628 if (!filter) {
1629 return NT_STATUS_NO_MEMORY;
1632 if (dns_domain) {
1633 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1634 if (!dns) {
1635 return NT_STATUS_NO_MEMORY;
1637 filter = talloc_asprintf_append(filter,
1638 "(trustPartner=%s)", dns);
1639 if (!filter) {
1640 return NT_STATUS_NO_MEMORY;
1643 if (netbios) {
1644 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1645 if (!nbn) {
1646 return NT_STATUS_NO_MEMORY;
1648 filter = talloc_asprintf_append(filter,
1649 "(flatname=%s)", nbn);
1650 if (!filter) {
1651 return NT_STATUS_NO_MEMORY;
1654 if (sid) {
1655 sidstr = dom_sid_string(mem_ctx, sid);
1656 if (!sidstr) {
1657 return NT_STATUS_INVALID_PARAMETER;
1659 filter = talloc_asprintf_append(filter,
1660 "(securityIdentifier=%s)",
1661 sidstr);
1662 if (!filter) {
1663 return NT_STATUS_NO_MEMORY;
1666 if (dns_domain || netbios || sid) {
1667 filter = talloc_asprintf_append(filter, "))");
1668 if (!filter) {
1669 return NT_STATUS_NO_MEMORY;
1673 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1674 if (ret == 0) {
1675 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1678 if (ret != 1) {
1679 return NT_STATUS_OBJECT_NAME_COLLISION;
1682 return NT_STATUS_OK;
1685 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1686 struct ldb_context *sam_ldb,
1687 struct ldb_message *orig,
1688 struct ldb_message *dest,
1689 const char *attribute,
1690 uint32_t value,
1691 uint32_t *orig_value)
1693 const struct ldb_val *orig_val;
1694 uint32_t orig_uint = 0;
1695 unsigned int flags = 0;
1696 int ret;
1698 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1699 if (!orig_val || !orig_val->data) {
1700 /* add new attribute */
1701 flags = LDB_FLAG_MOD_ADD;
1703 } else {
1704 errno = 0;
1705 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1706 if (errno != 0 || orig_uint != value) {
1707 /* replace also if can't get value */
1708 flags = LDB_FLAG_MOD_REPLACE;
1712 if (flags == 0) {
1713 /* stored value is identical, nothing to change */
1714 goto done;
1717 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1718 if (ret != LDB_SUCCESS) {
1719 return NT_STATUS_NO_MEMORY;
1722 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1723 if (ret != LDB_SUCCESS) {
1724 return NT_STATUS_NO_MEMORY;
1727 done:
1728 if (orig_value) {
1729 *orig_value = orig_uint;
1731 return NT_STATUS_OK;
1734 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1735 struct ldb_context *sam_ldb,
1736 struct ldb_dn *base_dn,
1737 bool delete_user,
1738 const char *netbios_name,
1739 struct trustAuthInOutBlob *in)
1741 const char *attrs[] = { "userAccountControl", NULL };
1742 struct ldb_message **msgs;
1743 struct ldb_message *msg;
1744 uint32_t uac;
1745 uint32_t i;
1746 int ret;
1748 ret = gendb_search(sam_ldb, mem_ctx,
1749 base_dn, &msgs, attrs,
1750 "samAccountName=%s$", netbios_name);
1751 if (ret > 1) {
1752 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1755 if (ret == 0) {
1756 if (delete_user) {
1757 return NT_STATUS_OK;
1760 /* ok no existing user, add it from scratch */
1761 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1762 netbios_name, in, NULL);
1765 /* check user is what we are looking for */
1766 uac = ldb_msg_find_attr_as_uint(msgs[0],
1767 "userAccountControl", 0);
1768 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1769 return NT_STATUS_OBJECT_NAME_COLLISION;
1772 if (delete_user) {
1773 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1774 switch (ret) {
1775 case LDB_SUCCESS:
1776 return NT_STATUS_OK;
1777 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1778 return NT_STATUS_ACCESS_DENIED;
1779 default:
1780 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1784 /* entry exists, just modify secret if any */
1785 if (in == NULL || in->count == 0) {
1786 return NT_STATUS_OK;
1789 msg = ldb_msg_new(mem_ctx);
1790 if (!msg) {
1791 return NT_STATUS_NO_MEMORY;
1793 msg->dn = msgs[0]->dn;
1795 for (i = 0; i < in->count; i++) {
1796 const char *attribute;
1797 struct ldb_val v;
1798 switch (in->current.array[i].AuthType) {
1799 case TRUST_AUTH_TYPE_NT4OWF:
1800 attribute = "unicodePwd";
1801 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1802 v.length = 16;
1803 break;
1804 case TRUST_AUTH_TYPE_CLEAR:
1805 attribute = "clearTextPassword";
1806 v.data = in->current.array[i].AuthInfo.clear.password;
1807 v.length = in->current.array[i].AuthInfo.clear.size;
1808 break;
1809 default:
1810 continue;
1813 ret = ldb_msg_add_empty(msg, attribute,
1814 LDB_FLAG_MOD_REPLACE, NULL);
1815 if (ret != LDB_SUCCESS) {
1816 return NT_STATUS_NO_MEMORY;
1819 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1820 if (ret != LDB_SUCCESS) {
1821 return NT_STATUS_NO_MEMORY;
1825 /* create the trusted_domain user account */
1826 ret = ldb_modify(sam_ldb, msg);
1827 if (ret != LDB_SUCCESS) {
1828 DEBUG(0,("Failed to create user record %s: %s\n",
1829 ldb_dn_get_linearized(msg->dn),
1830 ldb_errstring(sam_ldb)));
1832 switch (ret) {
1833 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1834 return NT_STATUS_DOMAIN_EXISTS;
1835 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1836 return NT_STATUS_ACCESS_DENIED;
1837 default:
1838 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1842 return NT_STATUS_OK;
1846 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1847 struct lsa_policy_state *p_state,
1848 TALLOC_CTX *mem_ctx,
1849 struct ldb_message *dom_msg,
1850 enum lsa_TrustDomInfoEnum level,
1851 union lsa_TrustedDomainInfo *info)
1853 uint32_t *posix_offset = NULL;
1854 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1855 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1856 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1857 uint32_t *enc_types = NULL;
1858 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1859 struct trustDomainPasswords auth_struct;
1860 struct trustAuthInOutBlob *current_passwords = NULL;
1861 NTSTATUS nt_status;
1862 struct ldb_message **msgs;
1863 struct ldb_message *msg;
1864 bool add_outgoing = false;
1865 bool add_incoming = false;
1866 bool del_outgoing = false;
1867 bool del_incoming = false;
1868 bool del_forest_info = false;
1869 bool in_transaction = false;
1870 int ret;
1871 bool am_rodc;
1873 switch (level) {
1874 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1875 posix_offset = &info->posix_offset.posix_offset;
1876 break;
1877 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1878 info_ex = &info->info_ex;
1879 break;
1880 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1881 auth_info = &info->auth_info;
1882 break;
1883 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1884 posix_offset = &info->full_info.posix_offset.posix_offset;
1885 info_ex = &info->full_info.info_ex;
1886 auth_info = &info->full_info.auth_info;
1887 break;
1888 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1889 auth_info_int = &info->auth_info_internal;
1890 break;
1891 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1892 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1893 info_ex = &info->full_info_internal.info_ex;
1894 auth_info_int = &info->full_info_internal.auth_info;
1895 break;
1896 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1897 enc_types = &info->enc_types.enc_types;
1898 break;
1899 default:
1900 return NT_STATUS_INVALID_PARAMETER;
1903 if (auth_info) {
1904 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1905 &trustAuthIncoming,
1906 &trustAuthOutgoing);
1907 if (!NT_STATUS_IS_OK(nt_status)) {
1908 return nt_status;
1910 if (trustAuthIncoming.data) {
1911 /* This does the decode of some of this twice, but it is easier that way */
1912 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1913 auth_info->incoming_count,
1914 auth_info->incoming_current_auth_info,
1915 NULL,
1916 &current_passwords);
1917 if (!NT_STATUS_IS_OK(nt_status)) {
1918 return nt_status;
1923 /* decode auth_info_int if set */
1924 if (auth_info_int) {
1926 /* now decrypt blob */
1927 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1928 auth_info_int->auth_blob.size);
1930 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1931 &auth_blob, &auth_struct);
1932 if (!NT_STATUS_IS_OK(nt_status)) {
1933 return nt_status;
1937 if (info_ex) {
1938 /* verify data matches */
1939 if (info_ex->trust_attributes &
1940 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1941 /* TODO: check what behavior level we have */
1942 if (strcasecmp_m(p_state->domain_dns,
1943 p_state->forest_dns) != 0) {
1944 return NT_STATUS_INVALID_DOMAIN_STATE;
1948 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1949 if (ret == LDB_SUCCESS && am_rodc) {
1950 return NT_STATUS_NO_SUCH_DOMAIN;
1953 /* verify only one object matches the dns/netbios/sid
1954 * triplet and that this is the one we already have */
1955 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1956 p_state->system_dn,
1957 info_ex->domain_name.string,
1958 info_ex->netbios_name.string,
1959 info_ex->sid, &msgs);
1960 if (!NT_STATUS_IS_OK(nt_status)) {
1961 return nt_status;
1963 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1964 return NT_STATUS_OBJECT_NAME_COLLISION;
1966 talloc_free(msgs);
1969 /* TODO: should we fetch previous values from the existing entry
1970 * and append them ? */
1971 if (auth_info_int && auth_struct.incoming.count) {
1972 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1973 &auth_struct.incoming,
1974 &trustAuthIncoming);
1975 if (!NT_STATUS_IS_OK(nt_status)) {
1976 return nt_status;
1979 current_passwords = &auth_struct.incoming;
1981 } else {
1982 trustAuthIncoming = data_blob(NULL, 0);
1985 if (auth_info_int && auth_struct.outgoing.count) {
1986 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1987 &auth_struct.outgoing,
1988 &trustAuthOutgoing);
1989 if (!NT_STATUS_IS_OK(nt_status)) {
1990 return nt_status;
1992 } else {
1993 trustAuthOutgoing = data_blob(NULL, 0);
1996 msg = ldb_msg_new(mem_ctx);
1997 if (msg == NULL) {
1998 return NT_STATUS_NO_MEMORY;
2000 msg->dn = dom_msg->dn;
2002 if (posix_offset) {
2003 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2004 dom_msg, msg,
2005 "trustPosixOffset",
2006 *posix_offset, NULL);
2007 if (!NT_STATUS_IS_OK(nt_status)) {
2008 return nt_status;
2012 if (info_ex) {
2013 uint32_t origattrs;
2014 uint32_t changed_attrs;
2015 uint32_t origdir;
2016 int origtype;
2018 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2019 dom_msg, msg,
2020 "trustDirection",
2021 info_ex->trust_direction,
2022 &origdir);
2023 if (!NT_STATUS_IS_OK(nt_status)) {
2024 return nt_status;
2027 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2028 if (auth_info != NULL && trustAuthIncoming.length > 0) {
2029 add_incoming = true;
2032 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2033 if (auth_info != NULL && trustAuthOutgoing.length > 0) {
2034 add_outgoing = true;
2038 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
2039 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
2040 del_incoming = true;
2042 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
2043 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2044 del_outgoing = true;
2047 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
2048 if (origtype == -1 || origtype != info_ex->trust_type) {
2049 DEBUG(1, ("Attempted to change trust type! "
2050 "Operation not handled\n"));
2051 return NT_STATUS_INVALID_PARAMETER;
2054 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2055 dom_msg, msg,
2056 "trustAttributes",
2057 info_ex->trust_attributes,
2058 &origattrs);
2059 if (!NT_STATUS_IS_OK(nt_status)) {
2060 return nt_status;
2062 /* TODO: check forestFunctionality from ldb opaque */
2063 /* TODO: check what is set makes sense */
2065 changed_attrs = origattrs ^ info_ex->trust_attributes;
2066 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2068 * For now we only allow
2069 * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
2071 * TODO: we may need to support more attribute changes
2073 DEBUG(1, ("Attempted to change trust attributes "
2074 "(0x%08x != 0x%08x)! "
2075 "Operation not handled yet...\n",
2076 (unsigned)origattrs,
2077 (unsigned)info_ex->trust_attributes));
2078 return NT_STATUS_INVALID_PARAMETER;
2081 if (!(info_ex->trust_attributes &
2082 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
2084 struct ldb_message_element *orig_forest_el = NULL;
2086 orig_forest_el = ldb_msg_find_element(dom_msg,
2087 "msDS-TrustForestTrustInfo");
2088 if (orig_forest_el != NULL) {
2089 del_forest_info = true;
2094 if (enc_types) {
2095 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2096 dom_msg, msg,
2097 "msDS-SupportedEncryptionTypes",
2098 *enc_types, NULL);
2099 if (!NT_STATUS_IS_OK(nt_status)) {
2100 return nt_status;
2104 if (add_incoming || del_incoming) {
2105 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
2106 LDB_FLAG_MOD_REPLACE, NULL);
2107 if (ret != LDB_SUCCESS) {
2108 return NT_STATUS_NO_MEMORY;
2110 if (add_incoming) {
2111 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
2112 &trustAuthIncoming, NULL);
2113 if (ret != LDB_SUCCESS) {
2114 return NT_STATUS_NO_MEMORY;
2118 if (add_outgoing || del_outgoing) {
2119 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2120 LDB_FLAG_MOD_REPLACE, NULL);
2121 if (ret != LDB_SUCCESS) {
2122 return NT_STATUS_NO_MEMORY;
2124 if (add_outgoing) {
2125 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
2126 &trustAuthOutgoing, NULL);
2127 if (ret != LDB_SUCCESS) {
2128 return NT_STATUS_NO_MEMORY;
2132 if (del_forest_info) {
2133 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
2134 LDB_FLAG_MOD_REPLACE, NULL);
2135 if (ret != LDB_SUCCESS) {
2136 return NT_STATUS_NO_MEMORY;
2140 /* start transaction */
2141 ret = ldb_transaction_start(p_state->sam_ldb);
2142 if (ret != LDB_SUCCESS) {
2143 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2145 in_transaction = true;
2147 if (msg->num_elements) {
2148 ret = ldb_modify(p_state->sam_ldb, msg);
2149 if (ret != LDB_SUCCESS) {
2150 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
2151 ldb_dn_get_linearized(msg->dn),
2152 ldb_errstring(p_state->sam_ldb)));
2153 nt_status = dsdb_ldb_err_to_ntstatus(ret);
2154 goto done;
2158 if (add_incoming || del_incoming) {
2159 const char *netbios_name;
2161 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
2162 "flatname", NULL);
2163 if (!netbios_name) {
2164 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
2165 goto done;
2168 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
2169 nt_status = update_trust_user(mem_ctx,
2170 p_state->sam_ldb,
2171 p_state->domain_dn,
2172 del_incoming,
2173 netbios_name,
2174 current_passwords);
2175 if (!NT_STATUS_IS_OK(nt_status)) {
2176 goto done;
2180 /* ok, all fine, commit transaction and return */
2181 ret = ldb_transaction_commit(p_state->sam_ldb);
2182 if (ret != LDB_SUCCESS) {
2183 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2185 in_transaction = false;
2187 nt_status = NT_STATUS_OK;
2189 done:
2190 if (in_transaction) {
2191 ldb_transaction_cancel(p_state->sam_ldb);
2193 return nt_status;
2197 lsa_SetInfomrationTrustedDomain
2199 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
2200 struct dcesrv_call_state *dce_call,
2201 TALLOC_CTX *mem_ctx,
2202 struct lsa_SetInformationTrustedDomain *r)
2204 struct dcesrv_handle *h;
2205 struct lsa_trusted_domain_state *td_state;
2206 struct ldb_message **msgs;
2207 NTSTATUS nt_status;
2209 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
2210 LSA_HANDLE_TRUSTED_DOMAIN);
2212 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2214 /* get the trusted domain object */
2215 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
2216 td_state->trusted_domain_dn,
2217 NULL, NULL, NULL, &msgs);
2218 if (!NT_STATUS_IS_OK(nt_status)) {
2219 if (NT_STATUS_EQUAL(nt_status,
2220 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2221 return nt_status;
2223 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2226 return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
2227 msgs[0], r->in.level, r->in.info);
2232 lsa_DeleteTrustedDomain
2234 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2235 struct lsa_DeleteTrustedDomain *r)
2237 NTSTATUS status;
2238 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2239 struct lsa_DeleteObject del;
2240 struct dcesrv_handle *h;
2242 opn.in.handle = r->in.handle;
2243 opn.in.sid = r->in.dom_sid;
2244 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2245 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2246 if (!opn.out.trustdom_handle) {
2247 return NT_STATUS_NO_MEMORY;
2249 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2250 if (!NT_STATUS_IS_OK(status)) {
2251 return status;
2254 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2255 talloc_steal(mem_ctx, h);
2257 del.in.handle = opn.out.trustdom_handle;
2258 del.out.handle = opn.out.trustdom_handle;
2259 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2260 if (!NT_STATUS_IS_OK(status)) {
2261 return status;
2263 return NT_STATUS_OK;
2266 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2267 struct ldb_message *msg,
2268 struct lsa_TrustDomainInfoInfoEx *info_ex)
2270 info_ex->domain_name.string
2271 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2272 info_ex->netbios_name.string
2273 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2274 info_ex->sid
2275 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2276 info_ex->trust_direction
2277 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2278 info_ex->trust_type
2279 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2280 info_ex->trust_attributes
2281 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2282 return NT_STATUS_OK;
2286 lsa_QueryTrustedDomainInfo
2288 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2289 struct lsa_QueryTrustedDomainInfo *r)
2291 union lsa_TrustedDomainInfo *info = NULL;
2292 struct dcesrv_handle *h;
2293 struct lsa_trusted_domain_state *trusted_domain_state;
2294 struct ldb_message *msg;
2295 int ret;
2296 struct ldb_message **res;
2297 const char *attrs[] = {
2298 "flatname",
2299 "trustPartner",
2300 "securityIdentifier",
2301 "trustDirection",
2302 "trustType",
2303 "trustAttributes",
2304 "msDs-supportedEncryptionTypes",
2305 NULL
2308 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2310 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2312 /* pull all the user attributes */
2313 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2314 trusted_domain_state->trusted_domain_dn, &res, attrs);
2315 if (ret != 1) {
2316 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2318 msg = res[0];
2320 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2321 if (!info) {
2322 return NT_STATUS_NO_MEMORY;
2324 *r->out.info = info;
2326 switch (r->in.level) {
2327 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2328 info->name.netbios_name.string
2329 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2330 break;
2331 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2332 info->posix_offset.posix_offset
2333 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2334 break;
2335 #if 0 /* Win2k3 doesn't implement this */
2336 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2337 r->out.info->info_basic.netbios_name.string
2338 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2339 r->out.info->info_basic.sid
2340 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2341 break;
2342 #endif
2343 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2344 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2346 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2347 ZERO_STRUCT(info->full_info);
2348 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2349 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2350 ZERO_STRUCT(info->full_info2_internal);
2351 info->full_info2_internal.posix_offset.posix_offset
2352 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2353 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2355 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2356 info->enc_types.enc_types
2357 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2358 break;
2360 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2361 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2362 /* oops, we don't want to return the info after all */
2363 talloc_free(info);
2364 *r->out.info = NULL;
2365 return NT_STATUS_INVALID_PARAMETER;
2366 default:
2367 /* oops, we don't want to return the info after all */
2368 talloc_free(info);
2369 *r->out.info = NULL;
2370 return NT_STATUS_INVALID_INFO_CLASS;
2373 return NT_STATUS_OK;
2378 lsa_QueryTrustedDomainInfoBySid
2380 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2381 struct lsa_QueryTrustedDomainInfoBySid *r)
2383 NTSTATUS status;
2384 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2385 struct lsa_QueryTrustedDomainInfo query;
2386 struct dcesrv_handle *h;
2388 opn.in.handle = r->in.handle;
2389 opn.in.sid = r->in.dom_sid;
2390 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2391 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2392 if (!opn.out.trustdom_handle) {
2393 return NT_STATUS_NO_MEMORY;
2395 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2396 if (!NT_STATUS_IS_OK(status)) {
2397 return status;
2400 /* Ensure this handle goes away at the end of this call */
2401 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2402 talloc_steal(mem_ctx, h);
2404 query.in.trustdom_handle = opn.out.trustdom_handle;
2405 query.in.level = r->in.level;
2406 query.out.info = r->out.info;
2407 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2408 if (!NT_STATUS_IS_OK(status)) {
2409 return status;
2412 return NT_STATUS_OK;
2416 lsa_SetTrustedDomainInfoByName
2418 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2419 TALLOC_CTX *mem_ctx,
2420 struct lsa_SetTrustedDomainInfoByName *r)
2422 struct dcesrv_handle *policy_handle;
2423 struct lsa_policy_state *policy_state;
2424 struct ldb_message **msgs;
2425 NTSTATUS nt_status;
2427 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2428 policy_state = policy_handle->data;
2430 /* get the trusted domain object */
2431 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2432 policy_state->domain_dn,
2433 r->in.trusted_domain->string,
2434 r->in.trusted_domain->string,
2435 NULL, &msgs);
2436 if (!NT_STATUS_IS_OK(nt_status)) {
2437 if (NT_STATUS_EQUAL(nt_status,
2438 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2439 return nt_status;
2441 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2444 return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2445 msgs[0], r->in.level, r->in.info);
2449 lsa_QueryTrustedDomainInfoByName
2451 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2452 TALLOC_CTX *mem_ctx,
2453 struct lsa_QueryTrustedDomainInfoByName *r)
2455 NTSTATUS status;
2456 struct lsa_OpenTrustedDomainByName opn = {{0},{0}};
2457 struct lsa_QueryTrustedDomainInfo query;
2458 struct dcesrv_handle *h;
2460 opn.in.handle = r->in.handle;
2461 opn.in.name = *r->in.trusted_domain;
2462 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2463 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2464 if (!opn.out.trustdom_handle) {
2465 return NT_STATUS_NO_MEMORY;
2467 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2468 if (!NT_STATUS_IS_OK(status)) {
2469 return status;
2472 /* Ensure this handle goes away at the end of this call */
2473 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2474 talloc_steal(mem_ctx, h);
2476 query.in.trustdom_handle = opn.out.trustdom_handle;
2477 query.in.level = r->in.level;
2478 query.out.info = r->out.info;
2479 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2480 if (!NT_STATUS_IS_OK(status)) {
2481 return status;
2484 return NT_STATUS_OK;
2488 lsa_CloseTrustedDomainEx
2490 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2491 TALLOC_CTX *mem_ctx,
2492 struct lsa_CloseTrustedDomainEx *r)
2494 /* The result of a bad hair day from an IDL programmer? Not
2495 * implmented in Win2k3. You should always just lsa_Close
2496 * anyway. */
2497 return NT_STATUS_NOT_IMPLEMENTED;
2502 comparison function for sorting lsa_DomainInformation array
2504 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2506 return strcasecmp_m(e1->name.string, e2->name.string);
2510 lsa_EnumTrustDom
2512 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2513 struct lsa_EnumTrustDom *r)
2515 struct dcesrv_handle *policy_handle;
2516 struct lsa_DomainInfo *entries;
2517 struct lsa_policy_state *policy_state;
2518 struct ldb_message **domains;
2519 const char *attrs[] = {
2520 "flatname",
2521 "securityIdentifier",
2522 NULL
2526 int count, i;
2528 *r->out.resume_handle = 0;
2530 r->out.domains->domains = NULL;
2531 r->out.domains->count = 0;
2533 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2535 policy_state = policy_handle->data;
2537 /* search for all users in this domain. This could possibly be cached and
2538 resumed based on resume_key */
2539 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2540 "objectclass=trustedDomain");
2541 if (count < 0) {
2542 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2545 /* convert to lsa_TrustInformation format */
2546 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2547 if (!entries) {
2548 return NT_STATUS_NO_MEMORY;
2550 for (i=0;i<count;i++) {
2551 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2552 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2555 /* sort the results by name */
2556 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2558 if (*r->in.resume_handle >= count) {
2559 *r->out.resume_handle = -1;
2561 return NT_STATUS_NO_MORE_ENTRIES;
2564 /* return the rest, limit by max_size. Note that we
2565 use the w2k3 element size value of 60 */
2566 r->out.domains->count = count - *r->in.resume_handle;
2567 r->out.domains->count = MIN(r->out.domains->count,
2568 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2570 r->out.domains->domains = entries + *r->in.resume_handle;
2572 if (r->out.domains->count < count - *r->in.resume_handle) {
2573 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2574 return STATUS_MORE_ENTRIES;
2577 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2578 * always be larger than the previous input resume handle, in
2579 * particular when hitting the last query it is vital to set the
2580 * resume handle correctly to avoid infinite client loops, as
2581 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2582 * status is NT_STATUS_OK - gd */
2584 *r->out.resume_handle = (uint32_t)-1;
2586 return NT_STATUS_OK;
2590 comparison function for sorting lsa_DomainInformation array
2592 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2594 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2598 lsa_EnumTrustedDomainsEx
2600 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2601 struct lsa_EnumTrustedDomainsEx *r)
2603 struct dcesrv_handle *policy_handle;
2604 struct lsa_TrustDomainInfoInfoEx *entries;
2605 struct lsa_policy_state *policy_state;
2606 struct ldb_message **domains;
2607 const char *attrs[] = {
2608 "flatname",
2609 "trustPartner",
2610 "securityIdentifier",
2611 "trustDirection",
2612 "trustType",
2613 "trustAttributes",
2614 NULL
2616 NTSTATUS nt_status;
2618 int count, i;
2620 *r->out.resume_handle = 0;
2622 r->out.domains->domains = NULL;
2623 r->out.domains->count = 0;
2625 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2627 policy_state = policy_handle->data;
2629 /* search for all users in this domain. This could possibly be cached and
2630 resumed based on resume_key */
2631 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2632 "objectclass=trustedDomain");
2633 if (count < 0) {
2634 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2637 /* convert to lsa_DomainInformation format */
2638 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2639 if (!entries) {
2640 return NT_STATUS_NO_MEMORY;
2642 for (i=0;i<count;i++) {
2643 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2644 if (!NT_STATUS_IS_OK(nt_status)) {
2645 return nt_status;
2649 /* sort the results by name */
2650 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2652 if (*r->in.resume_handle >= count) {
2653 *r->out.resume_handle = -1;
2655 return NT_STATUS_NO_MORE_ENTRIES;
2658 /* return the rest, limit by max_size. Note that we
2659 use the w2k3 element size value of 60 */
2660 r->out.domains->count = count - *r->in.resume_handle;
2661 r->out.domains->count = MIN(r->out.domains->count,
2662 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2664 r->out.domains->domains = entries + *r->in.resume_handle;
2666 if (r->out.domains->count < count - *r->in.resume_handle) {
2667 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2668 return STATUS_MORE_ENTRIES;
2671 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2673 return NT_STATUS_OK;
2678 lsa_OpenAccount
2680 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2681 struct lsa_OpenAccount *r)
2683 struct dcesrv_handle *h, *ah;
2684 struct lsa_policy_state *state;
2685 struct lsa_account_state *astate;
2687 ZERO_STRUCTP(r->out.acct_handle);
2689 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2691 state = h->data;
2693 astate = talloc(dce_call->conn, struct lsa_account_state);
2694 if (astate == NULL) {
2695 return NT_STATUS_NO_MEMORY;
2698 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2699 if (astate->account_sid == NULL) {
2700 talloc_free(astate);
2701 return NT_STATUS_NO_MEMORY;
2704 astate->policy = talloc_reference(astate, state);
2705 astate->access_mask = r->in.access_mask;
2708 * For now we grant all requested access.
2710 * We will fail at the ldb layer later.
2712 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2713 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2714 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2716 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2718 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2719 __func__, dom_sid_string(mem_ctx, astate->account_sid),
2720 (unsigned)r->in.access_mask,
2721 (unsigned)astate->access_mask));
2723 ah = dcesrv_handle_create(dce_call, LSA_HANDLE_ACCOUNT);
2724 if (!ah) {
2725 talloc_free(astate);
2726 return NT_STATUS_NO_MEMORY;
2729 ah->data = talloc_steal(ah, astate);
2731 *r->out.acct_handle = ah->wire_handle;
2733 return NT_STATUS_OK;
2738 lsa_EnumPrivsAccount
2740 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2741 TALLOC_CTX *mem_ctx,
2742 struct lsa_EnumPrivsAccount *r)
2744 struct dcesrv_handle *h;
2745 struct lsa_account_state *astate;
2746 int ret;
2747 unsigned int i, j;
2748 struct ldb_message **res;
2749 const char * const attrs[] = { "privilege", NULL};
2750 struct ldb_message_element *el;
2751 const char *sidstr;
2752 struct lsa_PrivilegeSet *privs;
2754 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2756 astate = h->data;
2758 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2759 if (privs == NULL) {
2760 return NT_STATUS_NO_MEMORY;
2762 privs->count = 0;
2763 privs->unknown = 0;
2764 privs->set = NULL;
2766 *r->out.privs = privs;
2768 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2769 if (sidstr == NULL) {
2770 return NT_STATUS_NO_MEMORY;
2773 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2774 "objectSid=%s", sidstr);
2775 if (ret < 0) {
2776 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2778 if (ret != 1) {
2779 return NT_STATUS_OK;
2782 el = ldb_msg_find_element(res[0], "privilege");
2783 if (el == NULL || el->num_values == 0) {
2784 return NT_STATUS_OK;
2787 privs->set = talloc_array(privs,
2788 struct lsa_LUIDAttribute, el->num_values);
2789 if (privs->set == NULL) {
2790 return NT_STATUS_NO_MEMORY;
2793 j = 0;
2794 for (i=0;i<el->num_values;i++) {
2795 int id = sec_privilege_id((const char *)el->values[i].data);
2796 if (id == SEC_PRIV_INVALID) {
2797 /* Perhaps an account right, not a privilege */
2798 continue;
2800 privs->set[j].attribute = 0;
2801 privs->set[j].luid.low = id;
2802 privs->set[j].luid.high = 0;
2803 j++;
2806 privs->count = j;
2808 return NT_STATUS_OK;
2812 lsa_EnumAccountRights
2814 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2815 TALLOC_CTX *mem_ctx,
2816 struct lsa_EnumAccountRights *r)
2818 struct dcesrv_handle *h;
2819 struct lsa_policy_state *state;
2820 int ret;
2821 unsigned int i;
2822 struct ldb_message **res;
2823 const char * const attrs[] = { "privilege", NULL};
2824 const char *sidstr;
2825 struct ldb_message_element *el;
2827 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2829 state = h->data;
2831 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2832 if (sidstr == NULL) {
2833 return NT_STATUS_NO_MEMORY;
2836 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2837 "(&(objectSid=%s)(privilege=*))", sidstr);
2838 if (ret == 0) {
2839 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2841 if (ret != 1) {
2842 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2843 dom_sid_string(mem_ctx, r->in.sid),
2844 ldb_errstring(state->pdb)));
2845 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2848 el = ldb_msg_find_element(res[0], "privilege");
2849 if (el == NULL || el->num_values == 0) {
2850 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2853 r->out.rights->count = el->num_values;
2854 r->out.rights->names = talloc_array(r->out.rights,
2855 struct lsa_StringLarge, r->out.rights->count);
2856 if (r->out.rights->names == NULL) {
2857 return NT_STATUS_NO_MEMORY;
2860 for (i=0;i<el->num_values;i++) {
2861 r->out.rights->names[i].string = (const char *)el->values[i].data;
2864 return NT_STATUS_OK;
2870 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2872 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2873 TALLOC_CTX *mem_ctx,
2874 struct lsa_policy_state *state,
2875 int ldb_flag,
2876 struct dom_sid *sid,
2877 const struct lsa_RightSet *rights)
2879 struct auth_session_info *session_info =
2880 dcesrv_call_session_info(dce_call);
2881 const char *sidstr, *sidndrstr;
2882 struct ldb_message *msg;
2883 struct ldb_message_element *el;
2884 int ret;
2885 uint32_t i;
2886 struct lsa_EnumAccountRights r2;
2887 char *dnstr;
2889 if (security_session_user_level(session_info, NULL) <
2890 SECURITY_ADMINISTRATOR) {
2891 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2892 return NT_STATUS_ACCESS_DENIED;
2895 msg = ldb_msg_new(mem_ctx);
2896 if (msg == NULL) {
2897 return NT_STATUS_NO_MEMORY;
2900 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2901 if (sidndrstr == NULL) {
2902 TALLOC_FREE(msg);
2903 return NT_STATUS_NO_MEMORY;
2906 sidstr = dom_sid_string(msg, sid);
2907 if (sidstr == NULL) {
2908 TALLOC_FREE(msg);
2909 return NT_STATUS_NO_MEMORY;
2912 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2913 if (dnstr == NULL) {
2914 TALLOC_FREE(msg);
2915 return NT_STATUS_NO_MEMORY;
2918 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2919 if (msg->dn == NULL) {
2920 TALLOC_FREE(msg);
2921 return NT_STATUS_NO_MEMORY;
2924 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2925 NTSTATUS status;
2927 r2.in.handle = &state->handle->wire_handle;
2928 r2.in.sid = sid;
2929 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2931 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2932 if (!NT_STATUS_IS_OK(status)) {
2933 ZERO_STRUCTP(r2.out.rights);
2937 for (i=0;i<rights->count;i++) {
2938 bool ok;
2940 ok = dcesrc_lsa_valid_AccountRight(rights->names[i].string);
2941 if (!ok) {
2942 talloc_free(msg);
2943 return NT_STATUS_NO_SUCH_PRIVILEGE;
2946 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2947 uint32_t j;
2948 for (j=0;j<r2.out.rights->count;j++) {
2949 if (strcasecmp_m(r2.out.rights->names[j].string,
2950 rights->names[i].string) == 0) {
2951 break;
2954 if (j != r2.out.rights->count) continue;
2957 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2958 if (ret != LDB_SUCCESS) {
2959 talloc_free(msg);
2960 return NT_STATUS_NO_MEMORY;
2964 el = ldb_msg_find_element(msg, "privilege");
2965 if (!el) {
2966 talloc_free(msg);
2967 return NT_STATUS_OK;
2970 el->flags = ldb_flag;
2972 ret = ldb_modify(state->pdb, msg);
2973 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2974 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2975 talloc_free(msg);
2976 return NT_STATUS_NO_MEMORY;
2978 ldb_msg_add_string(msg, "comment", "added via LSA");
2979 ret = ldb_add(state->pdb, msg);
2981 if (ret != LDB_SUCCESS) {
2982 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2983 talloc_free(msg);
2984 return NT_STATUS_OK;
2986 DEBUG(3, ("Could not %s attributes from %s: %s",
2987 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2988 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2989 talloc_free(msg);
2990 return NT_STATUS_UNEXPECTED_IO_ERROR;
2993 talloc_free(msg);
2994 return NT_STATUS_OK;
2998 lsa_AddPrivilegesToAccount
3000 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3001 struct lsa_AddPrivilegesToAccount *r)
3003 struct lsa_RightSet rights;
3004 struct dcesrv_handle *h;
3005 struct lsa_account_state *astate;
3006 uint32_t i;
3008 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3010 astate = h->data;
3012 rights.count = r->in.privs->count;
3013 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
3014 if (rights.names == NULL) {
3015 return NT_STATUS_NO_MEMORY;
3017 for (i=0;i<rights.count;i++) {
3018 int id = r->in.privs->set[i].luid.low;
3019 if (r->in.privs->set[i].luid.high) {
3020 return NT_STATUS_NO_SUCH_PRIVILEGE;
3022 rights.names[i].string = sec_privilege_name(id);
3023 if (rights.names[i].string == NULL) {
3024 return NT_STATUS_NO_SUCH_PRIVILEGE;
3028 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3029 LDB_FLAG_MOD_ADD, astate->account_sid,
3030 &rights);
3035 lsa_RemovePrivilegesFromAccount
3037 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3038 struct lsa_RemovePrivilegesFromAccount *r)
3040 struct lsa_RightSet *rights;
3041 struct dcesrv_handle *h;
3042 struct lsa_account_state *astate;
3043 uint32_t i;
3045 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3047 astate = h->data;
3049 rights = talloc(mem_ctx, struct lsa_RightSet);
3051 if (r->in.remove_all == 1 &&
3052 r->in.privs == NULL) {
3053 struct lsa_EnumAccountRights r2;
3054 NTSTATUS status;
3056 r2.in.handle = &astate->policy->handle->wire_handle;
3057 r2.in.sid = astate->account_sid;
3058 r2.out.rights = rights;
3060 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
3061 if (!NT_STATUS_IS_OK(status)) {
3062 return status;
3065 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3066 LDB_FLAG_MOD_DELETE, astate->account_sid,
3067 r2.out.rights);
3070 if (r->in.remove_all != 0) {
3071 return NT_STATUS_INVALID_PARAMETER;
3074 rights->count = r->in.privs->count;
3075 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
3076 if (rights->names == NULL) {
3077 return NT_STATUS_NO_MEMORY;
3079 for (i=0;i<rights->count;i++) {
3080 int id = r->in.privs->set[i].luid.low;
3081 if (r->in.privs->set[i].luid.high) {
3082 return NT_STATUS_NO_SUCH_PRIVILEGE;
3084 rights->names[i].string = sec_privilege_name(id);
3085 if (rights->names[i].string == NULL) {
3086 return NT_STATUS_NO_SUCH_PRIVILEGE;
3090 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3091 LDB_FLAG_MOD_DELETE, astate->account_sid,
3092 rights);
3097 lsa_GetQuotasForAccount
3099 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3100 struct lsa_GetQuotasForAccount *r)
3102 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3107 lsa_SetQuotasForAccount
3109 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3110 struct lsa_SetQuotasForAccount *r)
3112 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3117 lsa_GetSystemAccessAccount
3119 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3120 struct lsa_GetSystemAccessAccount *r)
3122 struct dcesrv_handle *h;
3123 struct lsa_account_state *astate;
3124 int ret;
3125 unsigned int i;
3126 struct ldb_message **res;
3127 const char * const attrs[] = { "privilege", NULL};
3128 struct ldb_message_element *el;
3129 const char *sidstr;
3131 *(r->out.access_mask) = 0x00000000;
3133 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3135 astate = h->data;
3137 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
3138 if (sidstr == NULL) {
3139 return NT_STATUS_NO_MEMORY;
3142 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
3143 "objectSid=%s", sidstr);
3144 if (ret < 0) {
3145 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3147 if (ret != 1) {
3148 return NT_STATUS_OK;
3151 el = ldb_msg_find_element(res[0], "privilege");
3152 if (el == NULL || el->num_values == 0) {
3153 return NT_STATUS_OK;
3156 for (i=0;i<el->num_values;i++) {
3157 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
3158 if (right_bit == 0) {
3159 /* Perhaps an privilege, not a right */
3160 continue;
3162 *(r->out.access_mask) |= right_bit;
3165 return NT_STATUS_OK;
3170 lsa_SetSystemAccessAccount
3172 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3173 struct lsa_SetSystemAccessAccount *r)
3175 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3178 lsa_CreateSecret
3180 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3181 struct lsa_CreateSecret *r)
3183 struct auth_session_info *session_info =
3184 dcesrv_call_session_info(dce_call);
3185 struct dcesrv_handle *policy_handle;
3186 struct lsa_policy_state *policy_state;
3187 struct lsa_secret_state *secret_state;
3188 struct dcesrv_handle *handle;
3189 struct ldb_message **msgs, *msg;
3190 struct ldb_context *samdb = NULL;
3191 const char *attrs[] = {
3192 NULL
3195 const char *name;
3197 int ret;
3199 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3200 ZERO_STRUCTP(r->out.sec_handle);
3202 switch (security_session_user_level(session_info, NULL))
3204 case SECURITY_SYSTEM:
3205 case SECURITY_ADMINISTRATOR:
3206 break;
3207 default:
3208 /* Users and annonymous are not allowed create secrets */
3209 return NT_STATUS_ACCESS_DENIED;
3212 policy_state = policy_handle->data;
3214 if (!r->in.name.string) {
3215 return NT_STATUS_INVALID_PARAMETER;
3218 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3219 NT_STATUS_HAVE_NO_MEMORY(secret_state);
3220 secret_state->policy = policy_state;
3222 msg = ldb_msg_new(mem_ctx);
3223 if (msg == NULL) {
3224 return NT_STATUS_NO_MEMORY;
3227 if (strncmp("G$", r->in.name.string, 2) == 0) {
3228 const char *name2;
3230 secret_state->global = true;
3232 name = &r->in.name.string[2];
3233 if (strlen(name) == 0) {
3234 return NT_STATUS_INVALID_PARAMETER;
3237 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3238 ldb_binary_encode_string(mem_ctx, name));
3239 NT_STATUS_HAVE_NO_MEMORY(name2);
3242 * We need to connect to the database as system, as this is
3243 * one of the rare RPC calls that must read the secrets
3244 * (and this is denied otherwise)
3246 * We also save the current remote session details so they can
3247 * used by the audit logging module. This allows the audit
3248 * logging to report the remote users details, rather than the
3249 * system users details.
3251 samdb = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
3252 secret_state->sam_ldb = talloc_reference(secret_state, samdb);
3253 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3255 /* search for the secret record */
3256 ret = gendb_search(secret_state->sam_ldb,
3257 mem_ctx, policy_state->system_dn, &msgs, attrs,
3258 "(&(cn=%s)(objectclass=secret))",
3259 name2);
3260 if (ret > 0) {
3261 return NT_STATUS_OBJECT_NAME_COLLISION;
3264 if (ret < 0) {
3265 DEBUG(0,("Failure searching for CN=%s: %s\n",
3266 name2, ldb_errstring(secret_state->sam_ldb)));
3267 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3270 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3271 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3272 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3273 return NT_STATUS_NO_MEMORY;
3276 ret = ldb_msg_add_string(msg, "cn", name2);
3277 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3278 } else {
3279 secret_state->global = false;
3281 name = r->in.name.string;
3282 if (strlen(name) == 0) {
3283 return NT_STATUS_INVALID_PARAMETER;
3286 secret_state->sam_ldb = talloc_reference(secret_state,
3287 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3288 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3290 /* search for the secret record */
3291 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3292 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3293 &msgs, attrs,
3294 "(&(cn=%s)(objectclass=secret))",
3295 ldb_binary_encode_string(mem_ctx, name));
3296 if (ret > 0) {
3297 return NT_STATUS_OBJECT_NAME_COLLISION;
3300 if (ret < 0) {
3301 DEBUG(0,("Failure searching for CN=%s: %s\n",
3302 name, ldb_errstring(secret_state->sam_ldb)));
3303 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3306 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3307 "cn=%s,cn=LSA Secrets", name);
3308 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3309 ret = ldb_msg_add_string(msg, "cn", name);
3310 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3313 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3314 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3316 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3317 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3319 /* create the secret */
3320 ret = ldb_add(secret_state->sam_ldb, msg);
3321 if (ret != LDB_SUCCESS) {
3322 DEBUG(0,("Failed to create secret record %s: %s\n",
3323 ldb_dn_get_linearized(msg->dn),
3324 ldb_errstring(secret_state->sam_ldb)));
3325 return NT_STATUS_ACCESS_DENIED;
3328 handle = dcesrv_handle_create(dce_call, LSA_HANDLE_SECRET);
3329 NT_STATUS_HAVE_NO_MEMORY(handle);
3331 handle->data = talloc_steal(handle, secret_state);
3333 secret_state->access_mask = r->in.access_mask;
3334 secret_state->policy = talloc_reference(secret_state, policy_state);
3335 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3337 *r->out.sec_handle = handle->wire_handle;
3339 return NT_STATUS_OK;
3344 lsa_OpenSecret
3346 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3347 struct lsa_OpenSecret *r)
3349 struct auth_session_info *session_info =
3350 dcesrv_call_session_info(dce_call);
3351 struct dcesrv_handle *policy_handle;
3352 struct lsa_policy_state *policy_state;
3353 struct lsa_secret_state *secret_state;
3354 struct dcesrv_handle *handle;
3355 struct ldb_message **msgs;
3356 struct ldb_context *samdb = NULL;
3357 const char *attrs[] = {
3358 NULL
3360 const char *name;
3361 int ret;
3363 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3364 ZERO_STRUCTP(r->out.sec_handle);
3365 policy_state = policy_handle->data;
3367 if (!r->in.name.string) {
3368 return NT_STATUS_INVALID_PARAMETER;
3371 switch (security_session_user_level(session_info, NULL))
3373 case SECURITY_SYSTEM:
3374 case SECURITY_ADMINISTRATOR:
3375 break;
3376 default:
3377 /* Users and annonymous are not allowed to access secrets */
3378 return NT_STATUS_ACCESS_DENIED;
3381 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3382 if (!secret_state) {
3383 return NT_STATUS_NO_MEMORY;
3385 secret_state->policy = policy_state;
3387 if (strncmp("G$", r->in.name.string, 2) == 0) {
3388 name = &r->in.name.string[2];
3390 * We need to connect to the database as system, as this is
3391 * one of the rare RPC calls that must read the secrets
3392 * (and this is denied otherwise)
3394 * We also save the current remote session details so they can
3395 * used by the audit logging module. This allows the audit
3396 * logging to report the remote users details, rather than the
3397 * system users details.
3399 samdb = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
3400 secret_state->sam_ldb = talloc_reference(secret_state, samdb);
3401 secret_state->global = true;
3403 if (strlen(name) < 1) {
3404 return NT_STATUS_INVALID_PARAMETER;
3407 /* search for the secret record */
3408 ret = gendb_search(secret_state->sam_ldb,
3409 mem_ctx, policy_state->system_dn, &msgs, attrs,
3410 "(&(cn=%s Secret)(objectclass=secret))",
3411 ldb_binary_encode_string(mem_ctx, name));
3412 if (ret == 0) {
3413 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3416 if (ret != 1) {
3417 DEBUG(0,("Found %d records matching DN %s\n", ret,
3418 ldb_dn_get_linearized(policy_state->system_dn)));
3419 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3421 } else {
3422 secret_state->global = false;
3423 secret_state->sam_ldb = talloc_reference(secret_state,
3424 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3426 name = r->in.name.string;
3427 if (strlen(name) < 1) {
3428 return NT_STATUS_INVALID_PARAMETER;
3431 /* search for the secret record */
3432 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3433 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3434 &msgs, attrs,
3435 "(&(cn=%s)(objectclass=secret))",
3436 ldb_binary_encode_string(mem_ctx, name));
3437 if (ret == 0) {
3438 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3441 if (ret != 1) {
3442 DEBUG(0,("Found %d records matching CN=%s\n",
3443 ret, ldb_binary_encode_string(mem_ctx, name)));
3444 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3448 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3450 handle = dcesrv_handle_create(dce_call, LSA_HANDLE_SECRET);
3451 if (!handle) {
3452 return NT_STATUS_NO_MEMORY;
3455 handle->data = talloc_steal(handle, secret_state);
3457 secret_state->access_mask = r->in.access_mask;
3458 secret_state->policy = talloc_reference(secret_state, policy_state);
3460 *r->out.sec_handle = handle->wire_handle;
3462 return NT_STATUS_OK;
3467 lsa_SetSecret
3469 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3470 struct lsa_SetSecret *r)
3473 struct dcesrv_handle *h;
3474 struct lsa_secret_state *secret_state;
3475 struct ldb_message *msg;
3476 DATA_BLOB session_key;
3477 DATA_BLOB crypt_secret, secret;
3478 struct ldb_val val;
3479 int ret;
3480 NTSTATUS status = NT_STATUS_OK;
3482 struct timeval now = timeval_current();
3483 NTTIME nt_now = timeval_to_nttime(&now);
3485 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3487 secret_state = h->data;
3489 msg = ldb_msg_new(mem_ctx);
3490 if (msg == NULL) {
3491 return NT_STATUS_NO_MEMORY;
3494 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3495 if (!msg->dn) {
3496 return NT_STATUS_NO_MEMORY;
3498 status = dcesrv_transport_session_key(dce_call, &session_key);
3499 if (!NT_STATUS_IS_OK(status)) {
3500 return status;
3503 if (r->in.old_val) {
3504 /* Decrypt */
3505 crypt_secret.data = r->in.old_val->data;
3506 crypt_secret.length = r->in.old_val->size;
3508 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3509 if (!NT_STATUS_IS_OK(status)) {
3510 return status;
3513 val.data = secret.data;
3514 val.length = secret.length;
3516 /* set value */
3517 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3518 return NT_STATUS_NO_MEMORY;
3521 /* set old value mtime */
3522 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3523 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3524 return NT_STATUS_NO_MEMORY;
3527 } else {
3528 /* If the old value is not set, then migrate the
3529 * current value to the old value */
3530 const struct ldb_val *old_val;
3531 NTTIME last_set_time;
3532 struct ldb_message **res;
3533 const char *attrs[] = {
3534 "currentValue",
3535 "lastSetTime",
3536 NULL
3539 /* search for the secret record */
3540 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3541 secret_state->secret_dn, &res, attrs);
3542 if (ret == 0) {
3543 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3546 if (ret != 1) {
3547 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3548 ldb_dn_get_linearized(secret_state->secret_dn)));
3549 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3552 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3553 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3555 if (old_val) {
3556 /* set old value */
3557 if (ldb_msg_add_value(msg, "priorValue",
3558 old_val, NULL) != LDB_SUCCESS) {
3559 return NT_STATUS_NO_MEMORY;
3561 } else {
3562 if (samdb_msg_add_delete(secret_state->sam_ldb,
3563 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3564 return NT_STATUS_NO_MEMORY;
3568 /* set old value mtime */
3569 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3570 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3571 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3572 return NT_STATUS_NO_MEMORY;
3574 } else {
3575 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3576 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3577 return NT_STATUS_NO_MEMORY;
3582 if (r->in.new_val) {
3583 /* Decrypt */
3584 crypt_secret.data = r->in.new_val->data;
3585 crypt_secret.length = r->in.new_val->size;
3587 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3588 if (!NT_STATUS_IS_OK(status)) {
3589 return status;
3592 val.data = secret.data;
3593 val.length = secret.length;
3595 /* set value */
3596 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3597 return NT_STATUS_NO_MEMORY;
3600 /* set new value mtime */
3601 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3602 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3603 return NT_STATUS_NO_MEMORY;
3605 } else {
3606 /* NULL out the NEW value */
3607 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3608 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3609 return NT_STATUS_NO_MEMORY;
3611 if (samdb_msg_add_delete(secret_state->sam_ldb,
3612 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3613 return NT_STATUS_NO_MEMORY;
3617 /* modify the samdb record */
3618 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3619 if (ret != LDB_SUCCESS) {
3620 return dsdb_ldb_err_to_ntstatus(ret);
3623 return NT_STATUS_OK;
3628 lsa_QuerySecret
3630 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3631 struct lsa_QuerySecret *r)
3633 struct auth_session_info *session_info =
3634 dcesrv_call_session_info(dce_call);
3635 struct dcesrv_handle *h;
3636 struct lsa_secret_state *secret_state;
3637 struct ldb_message *msg;
3638 DATA_BLOB session_key;
3639 DATA_BLOB crypt_secret, secret;
3640 int ret;
3641 struct ldb_message **res;
3642 const char *attrs[] = {
3643 "currentValue",
3644 "priorValue",
3645 "lastSetTime",
3646 "priorSetTime",
3647 NULL
3650 NTSTATUS nt_status;
3652 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3654 /* Ensure user is permitted to read this... */
3655 switch (security_session_user_level(session_info, NULL))
3657 case SECURITY_SYSTEM:
3658 case SECURITY_ADMINISTRATOR:
3659 break;
3660 default:
3661 /* Users and annonymous are not allowed to read secrets */
3662 return NT_STATUS_ACCESS_DENIED;
3665 secret_state = h->data;
3667 /* pull all the user attributes */
3668 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3669 secret_state->secret_dn, &res, attrs);
3670 if (ret != 1) {
3671 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3673 msg = res[0];
3675 nt_status = dcesrv_transport_session_key(dce_call, &session_key);
3676 if (!NT_STATUS_IS_OK(nt_status)) {
3677 return nt_status;
3680 if (r->in.old_val) {
3681 const struct ldb_val *prior_val;
3682 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3683 if (!r->out.old_val) {
3684 return NT_STATUS_NO_MEMORY;
3686 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3688 if (prior_val && prior_val->length) {
3689 secret.data = prior_val->data;
3690 secret.length = prior_val->length;
3692 /* Encrypt */
3693 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3694 if (!crypt_secret.length) {
3695 return NT_STATUS_NO_MEMORY;
3697 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3698 if (!r->out.old_val->buf) {
3699 return NT_STATUS_NO_MEMORY;
3701 r->out.old_val->buf->size = crypt_secret.length;
3702 r->out.old_val->buf->length = crypt_secret.length;
3703 r->out.old_val->buf->data = crypt_secret.data;
3707 if (r->in.old_mtime) {
3708 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3709 if (!r->out.old_mtime) {
3710 return NT_STATUS_NO_MEMORY;
3712 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3715 if (r->in.new_val) {
3716 const struct ldb_val *new_val;
3717 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3718 if (!r->out.new_val) {
3719 return NT_STATUS_NO_MEMORY;
3722 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3724 if (new_val && new_val->length) {
3725 secret.data = new_val->data;
3726 secret.length = new_val->length;
3728 /* Encrypt */
3729 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3730 if (!crypt_secret.length) {
3731 return NT_STATUS_NO_MEMORY;
3733 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3734 if (!r->out.new_val->buf) {
3735 return NT_STATUS_NO_MEMORY;
3737 r->out.new_val->buf->length = crypt_secret.length;
3738 r->out.new_val->buf->size = crypt_secret.length;
3739 r->out.new_val->buf->data = crypt_secret.data;
3743 if (r->in.new_mtime) {
3744 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3745 if (!r->out.new_mtime) {
3746 return NT_STATUS_NO_MEMORY;
3748 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3751 return NT_STATUS_OK;
3756 lsa_LookupPrivValue
3758 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3759 TALLOC_CTX *mem_ctx,
3760 struct lsa_LookupPrivValue *r)
3762 struct dcesrv_handle *h;
3763 int id;
3765 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3767 id = sec_privilege_id(r->in.name->string);
3768 if (id == SEC_PRIV_INVALID) {
3769 return NT_STATUS_NO_SUCH_PRIVILEGE;
3772 r->out.luid->low = id;
3773 r->out.luid->high = 0;
3775 return NT_STATUS_OK;
3780 lsa_LookupPrivName
3782 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3783 TALLOC_CTX *mem_ctx,
3784 struct lsa_LookupPrivName *r)
3786 struct dcesrv_handle *h;
3787 struct lsa_StringLarge *name;
3788 const char *privname;
3790 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3792 if (r->in.luid->high != 0) {
3793 return NT_STATUS_NO_SUCH_PRIVILEGE;
3796 privname = sec_privilege_name(r->in.luid->low);
3797 if (privname == NULL) {
3798 return NT_STATUS_NO_SUCH_PRIVILEGE;
3801 name = talloc(mem_ctx, struct lsa_StringLarge);
3802 if (name == NULL) {
3803 return NT_STATUS_NO_MEMORY;
3806 name->string = privname;
3808 *r->out.name = name;
3810 return NT_STATUS_OK;
3815 lsa_LookupPrivDisplayName
3817 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3818 TALLOC_CTX *mem_ctx,
3819 struct lsa_LookupPrivDisplayName *r)
3821 struct dcesrv_handle *h;
3822 struct lsa_StringLarge *disp_name = NULL;
3823 enum sec_privilege id;
3825 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3827 id = sec_privilege_id(r->in.name->string);
3828 if (id == SEC_PRIV_INVALID) {
3829 return NT_STATUS_NO_SUCH_PRIVILEGE;
3832 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3833 if (disp_name == NULL) {
3834 return NT_STATUS_NO_MEMORY;
3837 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3838 if (disp_name->string == NULL) {
3839 return NT_STATUS_INTERNAL_ERROR;
3842 *r->out.disp_name = disp_name;
3843 *r->out.returned_language_id = 0;
3845 return NT_STATUS_OK;
3850 lsa_EnumAccountsWithUserRight
3852 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3853 TALLOC_CTX *mem_ctx,
3854 struct lsa_EnumAccountsWithUserRight *r)
3856 struct dcesrv_handle *h;
3857 struct lsa_policy_state *state;
3858 int ret, i;
3859 struct ldb_message **res;
3860 const char * const attrs[] = { "objectSid", NULL};
3861 const char *privname;
3862 bool ok;
3864 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3866 state = h->data;
3868 if (r->in.name == NULL) {
3869 return NT_STATUS_NO_SUCH_PRIVILEGE;
3872 privname = r->in.name->string;
3874 ok = dcesrc_lsa_valid_AccountRight(privname);
3875 if (!ok) {
3876 return NT_STATUS_NO_SUCH_PRIVILEGE;
3879 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3880 "privilege=%s", privname);
3881 if (ret < 0) {
3882 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3884 if (ret == 0) {
3885 return NT_STATUS_NO_MORE_ENTRIES;
3888 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3889 if (r->out.sids->sids == NULL) {
3890 return NT_STATUS_NO_MEMORY;
3892 for (i=0;i<ret;i++) {
3893 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3894 res[i], "objectSid");
3895 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3897 r->out.sids->num_sids = ret;
3899 return NT_STATUS_OK;
3904 lsa_AddAccountRights
3906 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3907 TALLOC_CTX *mem_ctx,
3908 struct lsa_AddAccountRights *r)
3910 struct dcesrv_handle *h;
3911 struct lsa_policy_state *state;
3913 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3915 state = h->data;
3917 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3918 LDB_FLAG_MOD_ADD,
3919 r->in.sid, r->in.rights);
3924 lsa_RemoveAccountRights
3926 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3927 TALLOC_CTX *mem_ctx,
3928 struct lsa_RemoveAccountRights *r)
3930 struct dcesrv_handle *h;
3931 struct lsa_policy_state *state;
3933 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3935 state = h->data;
3937 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3938 LDB_FLAG_MOD_DELETE,
3939 r->in.sid, r->in.rights);
3944 lsa_StorePrivateData
3946 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3947 struct lsa_StorePrivateData *r)
3949 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3954 lsa_RetrievePrivateData
3956 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3957 struct lsa_RetrievePrivateData *r)
3959 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3964 lsa_GetUserName
3966 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3967 struct lsa_GetUserName *r)
3969 enum dcerpc_transport_t transport =
3970 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3971 struct auth_session_info *session_info =
3972 dcesrv_call_session_info(dce_call);
3973 NTSTATUS status = NT_STATUS_OK;
3974 const char *account_name;
3975 const char *authority_name;
3976 struct lsa_String *_account_name;
3977 struct lsa_String *_authority_name = NULL;
3979 if (transport != NCACN_NP && transport != NCALRPC) {
3980 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3983 /* this is what w2k3 does */
3984 r->out.account_name = r->in.account_name;
3985 r->out.authority_name = r->in.authority_name;
3987 if (r->in.account_name
3988 && *r->in.account_name
3989 /* && *(*r->in.account_name)->string */
3991 return NT_STATUS_INVALID_PARAMETER;
3994 if (r->in.authority_name
3995 && *r->in.authority_name
3996 /* && *(*r->in.authority_name)->string */
3998 return NT_STATUS_INVALID_PARAMETER;
4001 account_name = talloc_reference(mem_ctx, session_info->info->account_name);
4002 authority_name = talloc_reference(mem_ctx, session_info->info->domain_name);
4004 _account_name = talloc(mem_ctx, struct lsa_String);
4005 NT_STATUS_HAVE_NO_MEMORY(_account_name);
4006 _account_name->string = account_name;
4008 if (r->in.authority_name) {
4009 _authority_name = talloc(mem_ctx, struct lsa_String);
4010 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
4011 _authority_name->string = authority_name;
4014 *r->out.account_name = _account_name;
4015 if (r->out.authority_name) {
4016 *r->out.authority_name = _authority_name;
4019 return status;
4023 lsa_SetInfoPolicy2
4025 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
4026 TALLOC_CTX *mem_ctx,
4027 struct lsa_SetInfoPolicy2 *r)
4029 /* need to support these */
4030 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4033 static void kdc_get_policy(TALLOC_CTX *mem_ctx,
4034 struct loadparm_context *lp_ctx,
4035 struct smb_krb5_context *smb_krb5_context,
4036 struct lsa_DomainInfoKerberos *k)
4038 time_t svc_tkt_lifetime;
4039 time_t usr_tkt_lifetime;
4040 time_t renewal_lifetime;
4042 /* Our KDC always re-validates the client */
4043 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
4045 lpcfg_default_kdc_policy(mem_ctx, lp_ctx, &svc_tkt_lifetime,
4046 &usr_tkt_lifetime, &renewal_lifetime);
4048 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
4049 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
4050 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
4051 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
4052 However in the parent function we basically just did a full
4053 krb5_context init with the only purpose of getting a global
4054 config option (the max skew), it would probably make more sense
4055 to have a lp_ or ldb global option as the samba default */
4056 if (smb_krb5_context) {
4057 unix_to_nt_time(&k->clock_skew,
4058 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
4060 #endif
4061 k->reserved = 0;
4064 lsa_QueryDomainInformationPolicy
4066 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4067 TALLOC_CTX *mem_ctx,
4068 struct lsa_QueryDomainInformationPolicy *r)
4070 union lsa_DomainInformationPolicy *info;
4072 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
4073 if (!info) {
4074 return NT_STATUS_NO_MEMORY;
4077 switch (r->in.level) {
4078 case LSA_DOMAIN_INFO_POLICY_EFS:
4079 talloc_free(info);
4080 *r->out.info = NULL;
4081 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4082 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
4084 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
4085 struct smb_krb5_context *smb_krb5_context;
4086 int ret = smb_krb5_init_context(mem_ctx,
4087 dce_call->conn->dce_ctx->lp_ctx,
4088 &smb_krb5_context);
4089 if (ret != 0) {
4090 talloc_free(info);
4091 *r->out.info = NULL;
4092 return NT_STATUS_INTERNAL_ERROR;
4094 kdc_get_policy(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
4095 smb_krb5_context,
4097 talloc_free(smb_krb5_context);
4098 *r->out.info = info;
4099 return NT_STATUS_OK;
4101 default:
4102 talloc_free(info);
4103 *r->out.info = NULL;
4104 return NT_STATUS_INVALID_INFO_CLASS;
4109 lsa_SetDomInfoPolicy
4111 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4112 TALLOC_CTX *mem_ctx,
4113 struct lsa_SetDomainInformationPolicy *r)
4115 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4119 lsa_TestCall
4121 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
4122 TALLOC_CTX *mem_ctx,
4123 struct lsa_TestCall *r)
4125 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4129 lsa_CREDRWRITE
4131 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4132 struct lsa_CREDRWRITE *r)
4134 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4139 lsa_CREDRREAD
4141 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4142 struct lsa_CREDRREAD *r)
4144 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4149 lsa_CREDRENUMERATE
4151 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4152 struct lsa_CREDRENUMERATE *r)
4154 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4159 lsa_CREDRWRITEDOMAINCREDENTIALS
4161 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4162 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
4164 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4169 lsa_CREDRREADDOMAINCREDENTIALS
4171 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4172 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
4174 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4179 lsa_CREDRDELETE
4181 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4182 struct lsa_CREDRDELETE *r)
4184 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4189 lsa_CREDRGETTARGETINFO
4191 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4192 struct lsa_CREDRGETTARGETINFO *r)
4194 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4199 lsa_CREDRPROFILELOADED
4201 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4202 struct lsa_CREDRPROFILELOADED *r)
4204 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4209 lsa_CREDRGETSESSIONTYPES
4211 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4212 struct lsa_CREDRGETSESSIONTYPES *r)
4214 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4219 lsa_LSARREGISTERAUDITEVENT
4221 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4222 struct lsa_LSARREGISTERAUDITEVENT *r)
4224 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4229 lsa_LSARGENAUDITEVENT
4231 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4232 struct lsa_LSARGENAUDITEVENT *r)
4234 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4239 lsa_LSARUNREGISTERAUDITEVENT
4241 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4242 struct lsa_LSARUNREGISTERAUDITEVENT *r)
4244 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4249 lsa_lsaRQueryForestTrustInformation
4251 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4252 struct lsa_lsaRQueryForestTrustInformation *r)
4254 struct dcesrv_handle *h = NULL;
4255 struct lsa_policy_state *p_state = NULL;
4256 int forest_level = DS_DOMAIN_FUNCTION_2000;
4257 const char * const trust_attrs[] = {
4258 "securityIdentifier",
4259 "flatName",
4260 "trustPartner",
4261 "trustAttributes",
4262 "trustDirection",
4263 "trustType",
4264 "msDS-TrustForestTrustInfo",
4265 NULL
4267 struct ldb_message *trust_tdo_msg = NULL;
4268 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4269 struct ForestTrustInfo *trust_fti = NULL;
4270 struct lsa_ForestTrustInformation *trust_lfti = NULL;
4271 NTSTATUS status;
4273 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4275 p_state = h->data;
4277 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4278 return NT_STATUS_INVALID_DOMAIN_STATE;
4281 forest_level = dsdb_forest_functional_level(p_state->sam_ldb);
4282 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4283 return NT_STATUS_INVALID_DOMAIN_STATE;
4286 if (r->in.trusted_domain_name->string == NULL) {
4287 return NT_STATUS_NO_SUCH_DOMAIN;
4290 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4291 r->in.trusted_domain_name->string,
4292 r->in.trusted_domain_name->string,
4293 trust_attrs, mem_ctx, &trust_tdo_msg);
4294 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4295 return NT_STATUS_NO_SUCH_DOMAIN;
4297 if (!NT_STATUS_IS_OK(status)) {
4298 return status;
4301 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4302 if (!NT_STATUS_IS_OK(status)) {
4303 return status;
4306 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4307 return NT_STATUS_INVALID_PARAMETER;
4310 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4311 return NT_STATUS_INVALID_PARAMETER;
4314 status = dsdb_trust_parse_forest_info(mem_ctx,
4315 trust_tdo_msg,
4316 &trust_fti);
4317 if (!NT_STATUS_IS_OK(status)) {
4318 return status;
4321 status = dsdb_trust_forest_info_to_lsa(mem_ctx, trust_fti,
4322 &trust_lfti);
4323 if (!NT_STATUS_IS_OK(status)) {
4324 return status;
4327 *r->out.forest_trust_info = trust_lfti;
4328 return NT_STATUS_OK;
4332 lsa_lsaRSetForestTrustInformation
4334 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4335 TALLOC_CTX *mem_ctx,
4336 struct lsa_lsaRSetForestTrustInformation *r)
4338 struct dcesrv_handle *h;
4339 struct lsa_policy_state *p_state;
4340 const char * const trust_attrs[] = {
4341 "securityIdentifier",
4342 "flatName",
4343 "trustPartner",
4344 "trustAttributes",
4345 "trustDirection",
4346 "trustType",
4347 "msDS-TrustForestTrustInfo",
4348 NULL
4350 struct ldb_message *trust_tdo_msg = NULL;
4351 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4352 struct lsa_ForestTrustInformation *step1_lfti = NULL;
4353 struct lsa_ForestTrustInformation *step2_lfti = NULL;
4354 struct ForestTrustInfo *trust_fti = NULL;
4355 struct ldb_result *trusts_res = NULL;
4356 unsigned int i;
4357 struct lsa_TrustDomainInfoInfoEx *xref_tdo = NULL;
4358 struct lsa_ForestTrustInformation *xref_lfti = NULL;
4359 struct lsa_ForestTrustCollisionInfo *c_info = NULL;
4360 DATA_BLOB ft_blob = {};
4361 struct ldb_message *msg = NULL;
4362 struct server_id *server_ids = NULL;
4363 uint32_t num_server_ids = 0;
4364 NTSTATUS status;
4365 enum ndr_err_code ndr_err;
4366 int ret;
4367 bool in_transaction = false;
4369 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4371 p_state = h->data;
4373 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4374 return NT_STATUS_INVALID_DOMAIN_STATE;
4377 if (r->in.check_only == 0) {
4378 ret = ldb_transaction_start(p_state->sam_ldb);
4379 if (ret != LDB_SUCCESS) {
4380 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4382 in_transaction = true;
4386 * abort if we are not a PDC
4388 * In future we should use a function like IsEffectiveRoleOwner()
4390 if (!samdb_is_pdc(p_state->sam_ldb)) {
4391 status = NT_STATUS_INVALID_DOMAIN_ROLE;
4392 goto done;
4395 if (r->in.trusted_domain_name->string == NULL) {
4396 status = NT_STATUS_NO_SUCH_DOMAIN;
4397 goto done;
4400 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4401 r->in.trusted_domain_name->string,
4402 r->in.trusted_domain_name->string,
4403 trust_attrs, mem_ctx, &trust_tdo_msg);
4404 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4405 status = NT_STATUS_NO_SUCH_DOMAIN;
4406 goto done;
4408 if (!NT_STATUS_IS_OK(status)) {
4409 goto done;
4412 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4413 if (!NT_STATUS_IS_OK(status)) {
4414 goto done;
4417 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4418 status = NT_STATUS_INVALID_PARAMETER;
4419 goto done;
4422 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4423 status = NT_STATUS_INVALID_PARAMETER;
4424 goto done;
4428 * verify and normalize the given forest trust info.
4430 * Step1: doesn't reorder yet, so step1_lfti might contain
4431 * NULL entries. This means dsdb_trust_verify_forest_info()
4432 * can generate collision entries with the callers index.
4434 status = dsdb_trust_normalize_forest_info_step1(mem_ctx,
4435 r->in.forest_trust_info,
4436 &step1_lfti);
4437 if (!NT_STATUS_IS_OK(status)) {
4438 goto done;
4441 c_info = talloc_zero(r->out.collision_info,
4442 struct lsa_ForestTrustCollisionInfo);
4443 if (c_info == NULL) {
4444 status = NT_STATUS_NO_MEMORY;
4445 goto done;
4449 * First check our own forest, then other domains/forests
4452 status = dsdb_trust_xref_tdo_info(mem_ctx, p_state->sam_ldb,
4453 &xref_tdo);
4454 if (!NT_STATUS_IS_OK(status)) {
4455 goto done;
4457 status = dsdb_trust_xref_forest_info(mem_ctx, p_state->sam_ldb,
4458 &xref_lfti);
4459 if (!NT_STATUS_IS_OK(status)) {
4460 goto done;
4464 * The documentation proposed to generate
4465 * LSA_FOREST_TRUST_COLLISION_XREF collisions.
4466 * But Windows always uses LSA_FOREST_TRUST_COLLISION_TDO.
4468 status = dsdb_trust_verify_forest_info(xref_tdo, xref_lfti,
4469 LSA_FOREST_TRUST_COLLISION_TDO,
4470 c_info, step1_lfti);
4471 if (!NT_STATUS_IS_OK(status)) {
4472 goto done;
4475 /* fetch all other trusted domain objects */
4476 status = dsdb_trust_search_tdos(p_state->sam_ldb,
4477 trust_tdo->domain_name.string,
4478 trust_attrs,
4479 mem_ctx, &trusts_res);
4480 if (!NT_STATUS_IS_OK(status)) {
4481 goto done;
4485 * now check against the other domains.
4486 * and generate LSA_FOREST_TRUST_COLLISION_TDO collisions.
4488 for (i = 0; i < trusts_res->count; i++) {
4489 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
4490 struct ForestTrustInfo *fti = NULL;
4491 struct lsa_ForestTrustInformation *lfti = NULL;
4493 status = dsdb_trust_parse_tdo_info(mem_ctx,
4494 trusts_res->msgs[i],
4495 &tdo);
4496 if (!NT_STATUS_IS_OK(status)) {
4497 goto done;
4500 status = dsdb_trust_parse_forest_info(tdo,
4501 trusts_res->msgs[i],
4502 &fti);
4503 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
4504 continue;
4506 if (!NT_STATUS_IS_OK(status)) {
4507 goto done;
4510 status = dsdb_trust_forest_info_to_lsa(tdo, fti, &lfti);
4511 if (!NT_STATUS_IS_OK(status)) {
4512 goto done;
4515 status = dsdb_trust_verify_forest_info(tdo, lfti,
4516 LSA_FOREST_TRUST_COLLISION_TDO,
4517 c_info, step1_lfti);
4518 if (!NT_STATUS_IS_OK(status)) {
4519 goto done;
4522 TALLOC_FREE(tdo);
4525 if (r->in.check_only != 0) {
4526 status = NT_STATUS_OK;
4527 goto done;
4531 * not just a check, write info back
4535 * normalize the given forest trust info.
4537 * Step2: adds TOP_LEVEL_NAME[_EX] in reverse order,
4538 * followed by DOMAIN_INFO in reverse order. It also removes
4539 * possible NULL entries from Step1.
4541 status = dsdb_trust_normalize_forest_info_step2(mem_ctx, step1_lfti,
4542 &step2_lfti);
4543 if (!NT_STATUS_IS_OK(status)) {
4544 goto done;
4547 status = dsdb_trust_forest_info_from_lsa(mem_ctx, step2_lfti,
4548 &trust_fti);
4549 if (!NT_STATUS_IS_OK(status)) {
4550 goto done;
4553 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, trust_fti,
4554 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4555 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4556 status = NT_STATUS_INVALID_PARAMETER;
4557 goto done;
4560 msg = ldb_msg_new(mem_ctx);
4561 if (msg == NULL) {
4562 status = NT_STATUS_NO_MEMORY;
4563 goto done;
4566 msg->dn = ldb_dn_copy(mem_ctx, trust_tdo_msg->dn);
4567 if (!msg->dn) {
4568 status = NT_STATUS_NO_MEMORY;
4569 goto done;
4572 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4573 LDB_FLAG_MOD_REPLACE, NULL);
4574 if (ret != LDB_SUCCESS) {
4575 status = NT_STATUS_NO_MEMORY;
4576 goto done;
4578 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4579 &ft_blob, NULL);
4580 if (ret != LDB_SUCCESS) {
4581 status = NT_STATUS_NO_MEMORY;
4582 goto done;
4585 ret = ldb_modify(p_state->sam_ldb, msg);
4586 if (ret != LDB_SUCCESS) {
4587 status = dsdb_ldb_err_to_ntstatus(ret);
4589 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4590 ldb_errstring(p_state->sam_ldb)));
4592 goto done;
4595 /* ok, all fine, commit transaction and return */
4596 in_transaction = false;
4597 ret = ldb_transaction_commit(p_state->sam_ldb);
4598 if (ret != LDB_SUCCESS) {
4599 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4600 goto done;
4604 * Notify winbindd that we have a acquired forest trust info
4606 status = irpc_servers_byname(dce_call->msg_ctx,
4607 mem_ctx,
4608 "winbind_server",
4609 &num_server_ids, &server_ids);
4610 if (!NT_STATUS_IS_OK(status)) {
4611 DBG_ERR("irpc_servers_byname failed\n");
4612 goto done;
4615 imessaging_send(dce_call->msg_ctx, server_ids[0],
4616 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS, NULL);
4618 status = NT_STATUS_OK;
4620 done:
4621 if (NT_STATUS_IS_OK(status) && c_info->count != 0) {
4622 *r->out.collision_info = c_info;
4625 if (in_transaction) {
4626 ldb_transaction_cancel(p_state->sam_ldb);
4629 return status;
4633 lsa_CREDRRENAME
4635 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4636 struct lsa_CREDRRENAME *r)
4638 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4644 lsa_LSAROPENPOLICYSCE
4646 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4647 struct lsa_LSAROPENPOLICYSCE *r)
4649 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4654 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4656 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4657 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4659 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4664 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4666 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4667 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4669 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4674 lsa_LSARADTREPORTSECURITYEVENT
4676 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4677 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4679 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4683 /* include the generated boilerplate */
4684 #include "librpc/gen_ndr/ndr_lsa_s.c"
4688 /*****************************************
4689 NOTE! The remaining calls below were
4690 removed in w2k3, so the DCESRV_FAULT()
4691 replies are the correct implementation. Do
4692 not try and fill these in with anything else
4693 ******************************************/
4696 dssetup_DsRoleDnsNameToFlatName
4698 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4699 struct dssetup_DsRoleDnsNameToFlatName *r)
4701 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4706 dssetup_DsRoleDcAsDc
4708 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4709 struct dssetup_DsRoleDcAsDc *r)
4711 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4716 dssetup_DsRoleDcAsReplica
4718 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4719 struct dssetup_DsRoleDcAsReplica *r)
4721 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4726 dssetup_DsRoleDemoteDc
4728 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4729 struct dssetup_DsRoleDemoteDc *r)
4731 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4736 dssetup_DsRoleGetDcOperationProgress
4738 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4739 struct dssetup_DsRoleGetDcOperationProgress *r)
4741 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4746 dssetup_DsRoleGetDcOperationResults
4748 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4749 struct dssetup_DsRoleGetDcOperationResults *r)
4751 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4756 dssetup_DsRoleCancel
4758 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4759 struct dssetup_DsRoleCancel *r)
4761 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4766 dssetup_DsRoleServerSaveStateForUpgrade
4768 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4769 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4771 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4776 dssetup_DsRoleUpgradeDownlevelServer
4778 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4779 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4781 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4786 dssetup_DsRoleAbortDownlevelServerUpgrade
4788 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4789 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4791 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4795 /* include the generated boilerplate */
4796 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4798 NTSTATUS dcerpc_server_lsa_init(TALLOC_CTX *ctx)
4800 NTSTATUS ret;
4802 ret = dcerpc_server_dssetup_init(ctx);
4803 if (!NT_STATUS_IS_OK(ret)) {
4804 return ret;
4806 ret = dcerpc_server_lsarpc_init(ctx);
4807 if (!NT_STATUS_IS_OK(ret)) {
4808 return ret;
4810 return ret;