s4:rpc_server/lsa: normalize the access_mask for lsa account objects
[Samba.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
blob2a465d4d8123e7c7f224595074990205ed57fec5
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"
37 this type allows us to distinguish handle types
41 state associated with a lsa_OpenAccount() operation
43 struct lsa_account_state {
44 struct lsa_policy_state *policy;
45 uint32_t access_mask;
46 struct dom_sid *account_sid;
51 state associated with a lsa_OpenSecret() operation
53 struct lsa_secret_state {
54 struct lsa_policy_state *policy;
55 uint32_t access_mask;
56 struct ldb_dn *secret_dn;
57 struct ldb_context *sam_ldb;
58 bool global;
62 state associated with a lsa_OpenTrustedDomain() operation
64 struct lsa_trusted_domain_state {
65 struct lsa_policy_state *policy;
66 uint32_t access_mask;
67 struct ldb_dn *trusted_domain_dn;
68 struct ldb_dn *trusted_domain_user_dn;
72 this is based on the samba3 function make_lsa_object_sd()
73 It uses the same logic, but with samba4 helper functions
75 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
76 struct security_descriptor **sd,
77 struct dom_sid *sid,
78 uint32_t sid_access)
80 NTSTATUS status;
81 uint32_t rid;
82 struct dom_sid *domain_sid, *domain_admins_sid;
83 const char *domain_admins_sid_str, *sidstr;
84 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
86 status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
87 if (!NT_STATUS_IS_OK(status)) {
88 TALLOC_FREE(tmp_ctx);
89 return status;
92 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
93 if (domain_admins_sid == NULL) {
94 TALLOC_FREE(tmp_ctx);
95 return NT_STATUS_NO_MEMORY;
98 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
99 if (domain_admins_sid_str == NULL) {
100 TALLOC_FREE(tmp_ctx);
101 return NT_STATUS_NO_MEMORY;
104 sidstr = dom_sid_string(tmp_ctx, sid);
105 if (sidstr == NULL) {
106 TALLOC_FREE(tmp_ctx);
107 return NT_STATUS_NO_MEMORY;
110 *sd = security_descriptor_dacl_create(mem_ctx,
111 0, sidstr, NULL,
113 SID_WORLD,
114 SEC_ACE_TYPE_ACCESS_ALLOWED,
115 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
117 SID_BUILTIN_ADMINISTRATORS,
118 SEC_ACE_TYPE_ACCESS_ALLOWED,
119 SEC_GENERIC_ALL, 0,
121 SID_BUILTIN_ACCOUNT_OPERATORS,
122 SEC_ACE_TYPE_ACCESS_ALLOWED,
123 SEC_GENERIC_ALL, 0,
125 domain_admins_sid_str,
126 SEC_ACE_TYPE_ACCESS_ALLOWED,
127 SEC_GENERIC_ALL, 0,
129 sidstr,
130 SEC_ACE_TYPE_ACCESS_ALLOWED,
131 sid_access, 0,
133 NULL);
134 talloc_free(tmp_ctx);
136 NT_STATUS_HAVE_NO_MEMORY(*sd);
138 return NT_STATUS_OK;
142 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
143 TALLOC_CTX *mem_ctx,
144 struct lsa_EnumAccountRights *r);
146 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
147 TALLOC_CTX *mem_ctx,
148 struct lsa_policy_state *state,
149 int ldb_flag,
150 struct dom_sid *sid,
151 const struct lsa_RightSet *rights);
154 lsa_Close
156 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
157 struct lsa_Close *r)
159 enum dcerpc_transport_t transport =
160 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
161 struct dcesrv_handle *h;
163 if (transport != NCACN_NP && transport != NCALRPC) {
164 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
167 *r->out.handle = *r->in.handle;
169 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
171 talloc_free(h);
173 ZERO_STRUCTP(r->out.handle);
175 return NT_STATUS_OK;
180 lsa_Delete
182 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
183 struct lsa_Delete *r)
185 return NT_STATUS_NOT_SUPPORTED;
190 lsa_DeleteObject
192 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
193 struct lsa_DeleteObject *r)
195 struct dcesrv_handle *h;
196 int ret;
198 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
200 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
201 struct lsa_secret_state *secret_state = h->data;
203 /* Ensure user is permitted to delete this... */
204 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
206 case SECURITY_SYSTEM:
207 case SECURITY_ADMINISTRATOR:
208 break;
209 default:
210 /* Users and anonymous are not allowed to delete things */
211 return NT_STATUS_ACCESS_DENIED;
214 ret = ldb_delete(secret_state->sam_ldb,
215 secret_state->secret_dn);
216 if (ret != LDB_SUCCESS) {
217 return NT_STATUS_INVALID_HANDLE;
220 ZERO_STRUCTP(r->out.handle);
222 return NT_STATUS_OK;
224 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
225 struct lsa_trusted_domain_state *trusted_domain_state =
226 talloc_get_type(h->data, struct lsa_trusted_domain_state);
227 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
228 if (ret != LDB_SUCCESS) {
229 return NT_STATUS_INTERNAL_DB_CORRUPTION;
232 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
233 trusted_domain_state->trusted_domain_dn);
234 if (ret != LDB_SUCCESS) {
235 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
236 return NT_STATUS_INVALID_HANDLE;
239 if (trusted_domain_state->trusted_domain_user_dn) {
240 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
241 trusted_domain_state->trusted_domain_user_dn);
242 if (ret != LDB_SUCCESS) {
243 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
244 return NT_STATUS_INVALID_HANDLE;
248 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
249 if (ret != LDB_SUCCESS) {
250 return NT_STATUS_INTERNAL_DB_CORRUPTION;
253 ZERO_STRUCTP(r->out.handle);
255 return NT_STATUS_OK;
257 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
258 struct lsa_RightSet *rights;
259 struct lsa_account_state *astate;
260 struct lsa_EnumAccountRights r2;
261 NTSTATUS status;
263 rights = talloc(mem_ctx, struct lsa_RightSet);
265 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
267 astate = h->data;
269 r2.in.handle = &astate->policy->handle->wire_handle;
270 r2.in.sid = astate->account_sid;
271 r2.out.rights = rights;
273 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
274 but we have a LSA_HANDLE_ACCOUNT here, so this call
275 will always fail */
276 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
277 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
278 return NT_STATUS_OK;
281 if (!NT_STATUS_IS_OK(status)) {
282 return status;
285 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
286 LDB_FLAG_MOD_DELETE, astate->account_sid,
287 r2.out.rights);
288 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
289 return NT_STATUS_OK;
292 if (!NT_STATUS_IS_OK(status)) {
293 return status;
296 ZERO_STRUCTP(r->out.handle);
298 return NT_STATUS_OK;
301 return NT_STATUS_INVALID_HANDLE;
306 lsa_EnumPrivs
308 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
309 struct lsa_EnumPrivs *r)
311 struct dcesrv_handle *h;
312 uint32_t i;
313 enum sec_privilege priv;
314 const char *privname;
316 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
318 i = *r->in.resume_handle;
320 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
321 r->out.privs->count < r->in.max_count) {
322 struct lsa_PrivEntry *e;
323 privname = sec_privilege_name(priv);
324 r->out.privs->privs = talloc_realloc(r->out.privs,
325 r->out.privs->privs,
326 struct lsa_PrivEntry,
327 r->out.privs->count+1);
328 if (r->out.privs->privs == NULL) {
329 return NT_STATUS_NO_MEMORY;
331 e = &r->out.privs->privs[r->out.privs->count];
332 e->luid.low = priv;
333 e->luid.high = 0;
334 e->name.string = privname;
335 r->out.privs->count++;
336 i++;
339 *r->out.resume_handle = i;
341 return NT_STATUS_OK;
346 lsa_QuerySecObj
348 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
349 struct lsa_QuerySecurity *r)
351 struct dcesrv_handle *h;
352 struct security_descriptor *sd;
353 NTSTATUS status;
354 struct dom_sid *sid;
356 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
358 sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
360 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
361 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
362 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
363 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid,
364 LSA_ACCOUNT_ALL_ACCESS);
365 } else {
366 return NT_STATUS_INVALID_HANDLE;
368 NT_STATUS_NOT_OK_RETURN(status);
370 (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
371 NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
373 (*r->out.sdbuf)->sd = sd;
375 return NT_STATUS_OK;
380 lsa_SetSecObj
382 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
383 struct lsa_SetSecObj *r)
385 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
390 lsa_ChangePassword
392 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
393 struct lsa_ChangePassword *r)
395 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
399 dssetup_DsRoleGetPrimaryDomainInformation
401 This is not an LSA call, but is the only call left on the DSSETUP
402 pipe (after the pipe was truncated), and needs lsa_get_policy_state
404 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
405 TALLOC_CTX *mem_ctx,
406 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
408 union dssetup_DsRoleInfo *info;
410 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
411 W_ERROR_HAVE_NO_MEMORY(info);
413 switch (r->in.level) {
414 case DS_ROLE_BASIC_INFORMATION:
416 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
417 uint32_t flags = 0;
418 const char *domain = NULL;
419 const char *dns_domain = NULL;
420 const char *forest = NULL;
421 struct GUID domain_guid;
422 struct lsa_policy_state *state;
424 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
425 if (!NT_STATUS_IS_OK(status)) {
426 return ntstatus_to_werror(status);
429 ZERO_STRUCT(domain_guid);
431 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
432 case ROLE_STANDALONE:
433 role = DS_ROLE_STANDALONE_SERVER;
434 break;
435 case ROLE_DOMAIN_MEMBER:
436 role = DS_ROLE_MEMBER_SERVER;
437 break;
438 case ROLE_ACTIVE_DIRECTORY_DC:
439 if (samdb_is_pdc(state->sam_ldb)) {
440 role = DS_ROLE_PRIMARY_DC;
441 } else {
442 role = DS_ROLE_BACKUP_DC;
444 break;
447 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
448 case ROLE_STANDALONE:
449 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
450 W_ERROR_HAVE_NO_MEMORY(domain);
451 break;
452 case ROLE_DOMAIN_MEMBER:
453 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
454 W_ERROR_HAVE_NO_MEMORY(domain);
455 /* TODO: what is with dns_domain and forest and guid? */
456 break;
457 case ROLE_ACTIVE_DIRECTORY_DC:
458 flags = DS_ROLE_PRIMARY_DS_RUNNING;
460 if (state->mixed_domain == 1) {
461 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
464 domain = state->domain_name;
465 dns_domain = state->domain_dns;
466 forest = state->forest_dns;
468 domain_guid = state->domain_guid;
469 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
470 break;
473 info->basic.role = role;
474 info->basic.flags = flags;
475 info->basic.domain = domain;
476 info->basic.dns_domain = dns_domain;
477 info->basic.forest = forest;
478 info->basic.domain_guid = domain_guid;
480 r->out.info = info;
481 return WERR_OK;
483 case DS_ROLE_UPGRADE_STATUS:
485 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
486 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
488 r->out.info = info;
489 return WERR_OK;
491 case DS_ROLE_OP_STATUS:
493 info->opstatus.status = DS_ROLE_OP_IDLE;
495 r->out.info = info;
496 return WERR_OK;
498 default:
499 return WERR_INVALID_PARAM;
504 fill in the AccountDomain info
506 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
507 struct lsa_DomainInfo *info)
509 info->name.string = state->domain_name;
510 info->sid = state->domain_sid;
512 return NT_STATUS_OK;
516 fill in the DNS domain info
518 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
519 struct lsa_DnsDomainInfo *info)
521 info->name.string = state->domain_name;
522 info->sid = state->domain_sid;
523 info->dns_domain.string = state->domain_dns;
524 info->dns_forest.string = state->forest_dns;
525 info->domain_guid = state->domain_guid;
527 return NT_STATUS_OK;
531 lsa_QueryInfoPolicy2
533 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
534 struct lsa_QueryInfoPolicy2 *r)
536 struct lsa_policy_state *state;
537 struct dcesrv_handle *h;
538 union lsa_PolicyInformation *info;
540 *r->out.info = NULL;
542 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
544 state = h->data;
546 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
547 if (!info) {
548 return NT_STATUS_NO_MEMORY;
550 *r->out.info = info;
552 switch (r->in.level) {
553 case LSA_POLICY_INFO_AUDIT_LOG:
554 /* we don't need to fill in any of this */
555 ZERO_STRUCT(info->audit_log);
556 return NT_STATUS_OK;
557 case LSA_POLICY_INFO_AUDIT_EVENTS:
558 /* we don't need to fill in any of this */
559 ZERO_STRUCT(info->audit_events);
560 return NT_STATUS_OK;
561 case LSA_POLICY_INFO_PD:
562 /* we don't need to fill in any of this */
563 ZERO_STRUCT(info->pd);
564 return NT_STATUS_OK;
566 case LSA_POLICY_INFO_DOMAIN:
567 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
568 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
569 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
570 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
571 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
573 case LSA_POLICY_INFO_ROLE:
574 info->role.role = LSA_ROLE_PRIMARY;
575 return NT_STATUS_OK;
577 case LSA_POLICY_INFO_DNS:
578 case LSA_POLICY_INFO_DNS_INT:
579 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
581 case LSA_POLICY_INFO_REPLICA:
582 ZERO_STRUCT(info->replica);
583 return NT_STATUS_OK;
585 case LSA_POLICY_INFO_QUOTA:
586 ZERO_STRUCT(info->quota);
587 return NT_STATUS_OK;
589 case LSA_POLICY_INFO_MOD:
590 case LSA_POLICY_INFO_AUDIT_FULL_SET:
591 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
592 /* windows gives INVALID_PARAMETER */
593 *r->out.info = NULL;
594 return NT_STATUS_INVALID_PARAMETER;
597 *r->out.info = NULL;
598 return NT_STATUS_INVALID_INFO_CLASS;
602 lsa_QueryInfoPolicy
604 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
605 struct lsa_QueryInfoPolicy *r)
607 struct lsa_QueryInfoPolicy2 r2;
608 NTSTATUS status;
610 ZERO_STRUCT(r2);
612 r2.in.handle = r->in.handle;
613 r2.in.level = r->in.level;
614 r2.out.info = r->out.info;
616 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
618 return status;
622 lsa_SetInfoPolicy
624 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
625 struct lsa_SetInfoPolicy *r)
627 /* need to support this */
628 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
633 lsa_ClearAuditLog
635 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
636 struct lsa_ClearAuditLog *r)
638 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
642 static const struct generic_mapping dcesrv_lsa_account_mapping = {
643 LSA_ACCOUNT_READ,
644 LSA_ACCOUNT_WRITE,
645 LSA_ACCOUNT_EXECUTE,
646 LSA_ACCOUNT_ALL_ACCESS
650 lsa_CreateAccount
652 This call does not seem to have any long-term effects, hence no database operations
654 we need to talk to the MS product group to find out what this account database means!
656 answer is that the lsa database is totally separate from the SAM and
657 ldap databases. We are going to need a separate ldb to store these
658 accounts. The SIDs on this account bear no relation to the SIDs in
661 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
662 struct lsa_CreateAccount *r)
664 struct lsa_account_state *astate;
666 struct lsa_policy_state *state;
667 struct dcesrv_handle *h, *ah;
669 ZERO_STRUCTP(r->out.acct_handle);
671 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
673 state = h->data;
675 astate = talloc(dce_call->conn, struct lsa_account_state);
676 if (astate == NULL) {
677 return NT_STATUS_NO_MEMORY;
680 astate->account_sid = dom_sid_dup(astate, r->in.sid);
681 if (astate->account_sid == NULL) {
682 talloc_free(astate);
683 return NT_STATUS_NO_MEMORY;
686 astate->policy = talloc_reference(astate, state);
687 astate->access_mask = r->in.access_mask;
690 * For now we grant all requested access.
692 * We will fail at the ldb layer later.
694 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
695 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
696 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
698 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
700 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X].\n",
701 __func__, dom_sid_string(mem_ctx, astate->account_sid),
702 (unsigned)r->in.access_mask,
703 (unsigned)astate->access_mask));
705 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
706 if (!ah) {
707 talloc_free(astate);
708 return NT_STATUS_NO_MEMORY;
711 ah->data = talloc_steal(ah, astate);
713 *r->out.acct_handle = ah->wire_handle;
715 return NT_STATUS_OK;
720 lsa_EnumAccounts
722 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
723 struct lsa_EnumAccounts *r)
725 struct dcesrv_handle *h;
726 struct lsa_policy_state *state;
727 int ret;
728 struct ldb_message **res;
729 const char * const attrs[] = { "objectSid", NULL};
730 uint32_t count, i;
732 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
734 state = h->data;
736 /* NOTE: This call must only return accounts that have at least
737 one privilege set
739 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
740 "(&(objectSid=*)(privilege=*))");
741 if (ret < 0) {
742 return NT_STATUS_INTERNAL_DB_CORRUPTION;
745 if (*r->in.resume_handle >= ret) {
746 return NT_STATUS_NO_MORE_ENTRIES;
749 count = ret - *r->in.resume_handle;
750 if (count > r->in.num_entries) {
751 count = r->in.num_entries;
754 if (count == 0) {
755 return NT_STATUS_NO_MORE_ENTRIES;
758 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
759 if (r->out.sids->sids == NULL) {
760 return NT_STATUS_NO_MEMORY;
763 for (i=0;i<count;i++) {
764 r->out.sids->sids[i].sid =
765 samdb_result_dom_sid(r->out.sids->sids,
766 res[i + *r->in.resume_handle],
767 "objectSid");
768 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
771 r->out.sids->num_sids = count;
772 *r->out.resume_handle = count + *r->in.resume_handle;
774 return NT_STATUS_OK;
777 /* This decrypts and returns Trusted Domain Auth Information Internal data */
778 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
779 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
780 struct trustDomainPasswords *auth_struct)
782 DATA_BLOB session_key = data_blob(NULL, 0);
783 enum ndr_err_code ndr_err;
784 NTSTATUS nt_status;
786 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
787 if (!NT_STATUS_IS_OK(nt_status)) {
788 return nt_status;
791 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
792 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
793 auth_struct,
794 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
795 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
796 return NT_STATUS_INVALID_PARAMETER;
799 return NT_STATUS_OK;
802 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
803 TALLOC_CTX *mem_ctx,
804 struct trustAuthInOutBlob *iopw,
805 DATA_BLOB *trustauth_blob)
807 enum ndr_err_code ndr_err;
809 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
810 iopw,
811 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
812 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
813 return NT_STATUS_INVALID_PARAMETER;
816 return NT_STATUS_OK;
819 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
820 struct ldb_context *sam_ldb,
821 struct ldb_dn *base_dn,
822 const char *netbios_name,
823 struct trustAuthInOutBlob *in,
824 struct ldb_dn **user_dn)
826 struct ldb_request *req;
827 struct ldb_message *msg;
828 struct ldb_dn *dn;
829 uint32_t i;
830 int ret;
832 dn = ldb_dn_copy(mem_ctx, base_dn);
833 if (!dn) {
834 return NT_STATUS_NO_MEMORY;
836 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
837 return NT_STATUS_NO_MEMORY;
840 msg = ldb_msg_new(mem_ctx);
841 if (!msg) {
842 return NT_STATUS_NO_MEMORY;
844 msg->dn = dn;
846 ret = ldb_msg_add_string(msg, "objectClass", "user");
847 if (ret != LDB_SUCCESS) {
848 return NT_STATUS_NO_MEMORY;
851 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
852 if (ret != LDB_SUCCESS) {
853 return NT_STATUS_NO_MEMORY;
856 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
857 UF_INTERDOMAIN_TRUST_ACCOUNT);
858 if (ret != LDB_SUCCESS) {
859 return NT_STATUS_NO_MEMORY;
862 for (i = 0; i < in->count; i++) {
863 const char *attribute;
864 struct ldb_val v;
865 switch (in->current.array[i].AuthType) {
866 case TRUST_AUTH_TYPE_NT4OWF:
867 attribute = "unicodePwd";
868 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
869 v.length = 16;
870 break;
871 case TRUST_AUTH_TYPE_CLEAR:
872 attribute = "clearTextPassword";
873 v.data = in->current.array[i].AuthInfo.clear.password;
874 v.length = in->current.array[i].AuthInfo.clear.size;
875 break;
876 default:
877 continue;
880 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
881 if (ret != LDB_SUCCESS) {
882 return NT_STATUS_NO_MEMORY;
886 /* create the trusted_domain user account */
887 ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
888 ldb_op_default_callback, NULL);
889 if (ret != LDB_SUCCESS) {
890 return NT_STATUS_NO_MEMORY;
893 ret = ldb_request_add_control(req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
894 false, NULL);
895 if (ret != LDB_SUCCESS) {
896 return NT_STATUS_NO_MEMORY;
899 ret = dsdb_autotransaction_request(sam_ldb, req);
900 if (ret != LDB_SUCCESS) {
901 DEBUG(0,("Failed to create user record %s: %s\n",
902 ldb_dn_get_linearized(msg->dn),
903 ldb_errstring(sam_ldb)));
905 switch (ret) {
906 case LDB_ERR_ENTRY_ALREADY_EXISTS:
907 return NT_STATUS_DOMAIN_EXISTS;
908 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
909 return NT_STATUS_ACCESS_DENIED;
910 default:
911 return NT_STATUS_INTERNAL_DB_CORRUPTION;
915 if (user_dn) {
916 *user_dn = dn;
918 return NT_STATUS_OK;
922 lsa_CreateTrustedDomainEx2
924 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
925 TALLOC_CTX *mem_ctx,
926 struct lsa_CreateTrustedDomainEx2 *r,
927 int op,
928 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
930 struct dcesrv_handle *policy_handle;
931 struct lsa_policy_state *policy_state;
932 struct lsa_trusted_domain_state *trusted_domain_state;
933 struct dcesrv_handle *handle;
934 struct ldb_message **msgs, *msg;
935 const char *attrs[] = {
936 NULL
938 const char *netbios_name;
939 const char *dns_name;
940 const char *name;
941 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
942 struct trustDomainPasswords auth_struct;
943 int ret;
944 NTSTATUS nt_status;
945 struct ldb_context *sam_ldb;
947 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
948 ZERO_STRUCTP(r->out.trustdom_handle);
950 policy_state = policy_handle->data;
951 sam_ldb = policy_state->sam_ldb;
953 netbios_name = r->in.info->netbios_name.string;
954 if (!netbios_name) {
955 return NT_STATUS_INVALID_PARAMETER;
958 dns_name = r->in.info->domain_name.string;
960 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
961 if (!trusted_domain_state) {
962 return NT_STATUS_NO_MEMORY;
964 trusted_domain_state->policy = policy_state;
966 if (strcasecmp(netbios_name, "BUILTIN") == 0
967 || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
968 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
969 return NT_STATUS_INVALID_PARAMETER;
972 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
973 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
974 || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
975 || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
976 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
977 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
980 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
981 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
982 /* No secrets are created at this time, for this function */
983 auth_struct.outgoing.count = 0;
984 auth_struct.incoming.count = 0;
985 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
986 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
987 r->in.auth_info_internal->auth_blob.size);
988 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
989 &auth_blob, &auth_struct);
990 if (!NT_STATUS_IS_OK(nt_status)) {
991 return nt_status;
993 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
995 if (unencrypted_auth_info->incoming_count > 1) {
996 return NT_STATUS_INVALID_PARAMETER;
999 /* more investigation required here, do not create secrets for
1000 * now */
1001 auth_struct.outgoing.count = 0;
1002 auth_struct.incoming.count = 0;
1003 } else {
1004 return NT_STATUS_INVALID_PARAMETER;
1007 if (auth_struct.incoming.count) {
1008 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1009 &auth_struct.incoming,
1010 &trustAuthIncoming);
1011 if (!NT_STATUS_IS_OK(nt_status)) {
1012 return nt_status;
1014 } else {
1015 trustAuthIncoming = data_blob(NULL, 0);
1018 if (auth_struct.outgoing.count) {
1019 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1020 &auth_struct.outgoing,
1021 &trustAuthOutgoing);
1022 if (!NT_STATUS_IS_OK(nt_status)) {
1023 return nt_status;
1025 } else {
1026 trustAuthOutgoing = data_blob(NULL, 0);
1029 ret = ldb_transaction_start(sam_ldb);
1030 if (ret != LDB_SUCCESS) {
1031 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1034 if (dns_name) {
1035 char *dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1036 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1037 /* search for the trusted_domain record */
1038 ret = gendb_search(sam_ldb,
1039 mem_ctx, policy_state->system_dn, &msgs, attrs,
1040 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1041 dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
1042 if (ret > 0) {
1043 ldb_transaction_cancel(sam_ldb);
1044 return NT_STATUS_OBJECT_NAME_COLLISION;
1046 } else {
1047 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1048 /* search for the trusted_domain record */
1049 ret = gendb_search(sam_ldb,
1050 mem_ctx, policy_state->system_dn, &msgs, attrs,
1051 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1052 netbios_encoded, netbios_encoded, netbios_encoded);
1053 if (ret > 0) {
1054 ldb_transaction_cancel(sam_ldb);
1055 return NT_STATUS_OBJECT_NAME_COLLISION;
1059 if (ret < 0 ) {
1060 ldb_transaction_cancel(sam_ldb);
1061 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1064 name = dns_name ? dns_name : netbios_name;
1066 msg = ldb_msg_new(mem_ctx);
1067 if (msg == NULL) {
1068 return NT_STATUS_NO_MEMORY;
1071 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1072 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1073 ldb_transaction_cancel(sam_ldb);
1074 return NT_STATUS_NO_MEMORY;
1077 ldb_msg_add_string(msg, "flatname", netbios_name);
1079 if (r->in.info->sid) {
1080 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1081 if (ret != LDB_SUCCESS) {
1082 ldb_transaction_cancel(sam_ldb);
1083 return NT_STATUS_INVALID_PARAMETER;
1087 ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1089 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1091 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1093 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1095 if (dns_name) {
1096 ldb_msg_add_string(msg, "trustPartner", dns_name);
1099 if (trustAuthIncoming.data) {
1100 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1101 if (ret != LDB_SUCCESS) {
1102 ldb_transaction_cancel(sam_ldb);
1103 return NT_STATUS_NO_MEMORY;
1106 if (trustAuthOutgoing.data) {
1107 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1108 if (ret != LDB_SUCCESS) {
1109 ldb_transaction_cancel(sam_ldb);
1110 return NT_STATUS_NO_MEMORY;
1114 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1116 /* create the trusted_domain */
1117 ret = ldb_add(sam_ldb, msg);
1118 switch (ret) {
1119 case LDB_SUCCESS:
1120 break;
1121 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1122 ldb_transaction_cancel(sam_ldb);
1123 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1124 ldb_dn_get_linearized(msg->dn),
1125 ldb_errstring(sam_ldb)));
1126 return NT_STATUS_DOMAIN_EXISTS;
1127 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1128 ldb_transaction_cancel(sam_ldb);
1129 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1130 ldb_dn_get_linearized(msg->dn),
1131 ldb_errstring(sam_ldb)));
1132 return NT_STATUS_ACCESS_DENIED;
1133 default:
1134 ldb_transaction_cancel(sam_ldb);
1135 DEBUG(0,("Failed to create user record %s: %s\n",
1136 ldb_dn_get_linearized(msg->dn),
1137 ldb_errstring(sam_ldb)));
1138 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1141 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1142 struct ldb_dn *user_dn;
1143 /* Inbound trusts must also create a cn=users object to match */
1144 nt_status = add_trust_user(mem_ctx, sam_ldb,
1145 policy_state->domain_dn,
1146 netbios_name,
1147 &auth_struct.incoming,
1148 &user_dn);
1149 if (!NT_STATUS_IS_OK(nt_status)) {
1150 ldb_transaction_cancel(sam_ldb);
1151 return nt_status;
1154 /* save the trust user dn */
1155 trusted_domain_state->trusted_domain_user_dn
1156 = talloc_steal(trusted_domain_state, user_dn);
1159 ret = ldb_transaction_commit(sam_ldb);
1160 if (ret != LDB_SUCCESS) {
1161 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1164 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1165 if (!handle) {
1166 return NT_STATUS_NO_MEMORY;
1169 handle->data = talloc_steal(handle, trusted_domain_state);
1171 trusted_domain_state->access_mask = r->in.access_mask;
1172 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1174 *r->out.trustdom_handle = handle->wire_handle;
1176 return NT_STATUS_OK;
1180 lsa_CreateTrustedDomainEx2
1182 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1183 TALLOC_CTX *mem_ctx,
1184 struct lsa_CreateTrustedDomainEx2 *r)
1186 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1189 lsa_CreateTrustedDomainEx
1191 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1192 TALLOC_CTX *mem_ctx,
1193 struct lsa_CreateTrustedDomainEx *r)
1195 struct lsa_CreateTrustedDomainEx2 r2;
1197 r2.in.policy_handle = r->in.policy_handle;
1198 r2.in.info = r->in.info;
1199 r2.out.trustdom_handle = r->out.trustdom_handle;
1200 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1204 lsa_CreateTrustedDomain
1206 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1207 struct lsa_CreateTrustedDomain *r)
1209 struct lsa_CreateTrustedDomainEx2 r2;
1211 r2.in.policy_handle = r->in.policy_handle;
1212 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1213 if (!r2.in.info) {
1214 return NT_STATUS_NO_MEMORY;
1217 r2.in.info->domain_name.string = NULL;
1218 r2.in.info->netbios_name = r->in.info->name;
1219 r2.in.info->sid = r->in.info->sid;
1220 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1221 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1222 r2.in.info->trust_attributes = 0;
1224 r2.in.access_mask = r->in.access_mask;
1225 r2.out.trustdom_handle = r->out.trustdom_handle;
1227 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1230 static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
1231 struct dcesrv_call_state *dce_call,
1232 TALLOC_CTX *tmp_mem,
1233 struct lsa_policy_state *policy_state,
1234 const char *filter,
1235 uint32_t access_mask,
1236 struct dcesrv_handle **_handle)
1238 struct lsa_trusted_domain_state *trusted_domain_state;
1239 struct dcesrv_handle *handle;
1240 struct ldb_message **msgs;
1241 const char *attrs[] = {
1242 "trustDirection",
1243 "flatname",
1244 NULL
1246 uint32_t direction;
1247 int ret;
1249 /* TODO: perform access checks */
1251 /* search for the trusted_domain record */
1252 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1253 policy_state->system_dn,
1254 &msgs, attrs, "%s", filter);
1255 if (ret == 0) {
1256 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1259 if (ret != 1) {
1260 DEBUG(0,("Found %d records matching %s under %s\n", ret,
1261 filter,
1262 ldb_dn_get_linearized(policy_state->system_dn)));
1263 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1266 trusted_domain_state = talloc_zero(tmp_mem,
1267 struct lsa_trusted_domain_state);
1268 if (!trusted_domain_state) {
1269 return NT_STATUS_NO_MEMORY;
1271 trusted_domain_state->policy = policy_state;
1273 trusted_domain_state->trusted_domain_dn =
1274 talloc_steal(trusted_domain_state, msgs[0]->dn);
1276 direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1277 if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1278 const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1279 "flatname", NULL);
1281 /* search for the trusted_domain account */
1282 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1283 policy_state->domain_dn,
1284 &msgs, attrs,
1285 "(&(samaccountname=%s$)(objectclass=user)"
1286 "(userAccountControl:%s:=%u))",
1287 flatname,
1288 LDB_OID_COMPARATOR_AND,
1289 UF_INTERDOMAIN_TRUST_ACCOUNT);
1290 if (ret == 1) {
1291 trusted_domain_state->trusted_domain_user_dn =
1292 talloc_steal(trusted_domain_state, msgs[0]->dn);
1296 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1297 if (!handle) {
1298 return NT_STATUS_NO_MEMORY;
1301 handle->data = talloc_steal(handle, trusted_domain_state);
1303 trusted_domain_state->access_mask = access_mask;
1304 trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1305 policy_state);
1307 *_handle = handle;
1309 return NT_STATUS_OK;
1313 lsa_OpenTrustedDomain
1315 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1316 struct lsa_OpenTrustedDomain *r)
1318 struct dcesrv_handle *policy_handle;
1319 struct lsa_policy_state *policy_state;
1320 struct dcesrv_handle *handle;
1321 const char *sid_string;
1322 char *filter;
1323 NTSTATUS status;
1325 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1326 ZERO_STRUCTP(r->out.trustdom_handle);
1327 policy_state = policy_handle->data;
1329 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1330 if (!sid_string) {
1331 return NT_STATUS_NO_MEMORY;
1334 filter = talloc_asprintf(mem_ctx,
1335 "(&(securityIdentifier=%s)"
1336 "(objectclass=trustedDomain))",
1337 sid_string);
1338 if (filter == NULL) {
1339 return NT_STATUS_NO_MEMORY;
1342 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1343 policy_state,
1344 filter,
1345 r->in.access_mask,
1346 &handle);
1347 if (!NT_STATUS_IS_OK(status)) {
1348 return status;
1351 *r->out.trustdom_handle = handle->wire_handle;
1353 return NT_STATUS_OK;
1358 lsa_OpenTrustedDomainByName
1360 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1361 TALLOC_CTX *mem_ctx,
1362 struct lsa_OpenTrustedDomainByName *r)
1364 struct dcesrv_handle *policy_handle;
1365 struct lsa_policy_state *policy_state;
1366 struct dcesrv_handle *handle;
1367 char *td_name;
1368 char *filter;
1369 NTSTATUS status;
1371 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1372 ZERO_STRUCTP(r->out.trustdom_handle);
1373 policy_state = policy_handle->data;
1375 if (!r->in.name.string) {
1376 return NT_STATUS_INVALID_PARAMETER;
1379 /* search for the trusted_domain record */
1380 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1381 if (td_name == NULL) {
1382 return NT_STATUS_NO_MEMORY;
1385 filter = talloc_asprintf(mem_ctx,
1386 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1387 "(objectclass=trustedDomain))",
1388 td_name, td_name, td_name);
1389 if (filter == NULL) {
1390 return NT_STATUS_NO_MEMORY;
1393 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1394 policy_state,
1395 filter,
1396 r->in.access_mask,
1397 &handle);
1398 if (!NT_STATUS_IS_OK(status)) {
1399 return status;
1402 *r->out.trustdom_handle = handle->wire_handle;
1404 return NT_STATUS_OK;
1410 lsa_SetTrustedDomainInfo
1412 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1413 struct lsa_SetTrustedDomainInfo *r)
1415 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1420 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1421 * otherwise at least one must be provided */
1422 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1423 struct ldb_dn *basedn, const char *dns_domain,
1424 const char *netbios, struct dom_sid2 *sid,
1425 struct ldb_message ***msgs)
1427 const char *attrs[] = { "flatname", "trustPartner",
1428 "securityIdentifier", "trustDirection",
1429 "trustType", "trustAttributes",
1430 "trustPosixOffset",
1431 "msDs-supportedEncryptionTypes",
1432 "msDS-TrustForestTrustInfo",
1433 NULL
1435 char *dns = NULL;
1436 char *nbn = NULL;
1437 char *sidstr = NULL;
1438 char *filter;
1439 int ret;
1442 if (dns_domain || netbios || sid) {
1443 filter = talloc_strdup(mem_ctx,
1444 "(&(objectclass=trustedDomain)(|");
1445 } else {
1446 filter = talloc_strdup(mem_ctx,
1447 "(objectclass=trustedDomain)");
1449 if (!filter) {
1450 return NT_STATUS_NO_MEMORY;
1453 if (dns_domain) {
1454 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1455 if (!dns) {
1456 return NT_STATUS_NO_MEMORY;
1458 filter = talloc_asprintf_append(filter,
1459 "(trustPartner=%s)", dns);
1460 if (!filter) {
1461 return NT_STATUS_NO_MEMORY;
1464 if (netbios) {
1465 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1466 if (!nbn) {
1467 return NT_STATUS_NO_MEMORY;
1469 filter = talloc_asprintf_append(filter,
1470 "(flatname=%s)", nbn);
1471 if (!filter) {
1472 return NT_STATUS_NO_MEMORY;
1475 if (sid) {
1476 sidstr = dom_sid_string(mem_ctx, sid);
1477 if (!sidstr) {
1478 return NT_STATUS_INVALID_PARAMETER;
1480 filter = talloc_asprintf_append(filter,
1481 "(securityIdentifier=%s)",
1482 sidstr);
1483 if (!filter) {
1484 return NT_STATUS_NO_MEMORY;
1487 if (dns_domain || netbios || sid) {
1488 filter = talloc_asprintf_append(filter, "))");
1489 if (!filter) {
1490 return NT_STATUS_NO_MEMORY;
1494 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1495 if (ret == 0) {
1496 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1499 if (ret != 1) {
1500 return NT_STATUS_OBJECT_NAME_COLLISION;
1503 return NT_STATUS_OK;
1506 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1507 struct ldb_context *sam_ldb,
1508 struct ldb_message *orig,
1509 struct ldb_message *dest,
1510 const char *attribute,
1511 uint32_t value,
1512 uint32_t *orig_value)
1514 const struct ldb_val *orig_val;
1515 uint32_t orig_uint = 0;
1516 unsigned int flags = 0;
1517 int ret;
1519 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1520 if (!orig_val || !orig_val->data) {
1521 /* add new attribute */
1522 flags = LDB_FLAG_MOD_ADD;
1524 } else {
1525 errno = 0;
1526 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1527 if (errno != 0 || orig_uint != value) {
1528 /* replace also if can't get value */
1529 flags = LDB_FLAG_MOD_REPLACE;
1533 if (flags == 0) {
1534 /* stored value is identical, nothing to change */
1535 goto done;
1538 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1539 if (ret != LDB_SUCCESS) {
1540 return NT_STATUS_NO_MEMORY;
1543 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1544 if (ret != LDB_SUCCESS) {
1545 return NT_STATUS_NO_MEMORY;
1548 done:
1549 if (orig_value) {
1550 *orig_value = orig_uint;
1552 return NT_STATUS_OK;
1555 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1556 struct ldb_context *sam_ldb,
1557 struct ldb_dn *base_dn,
1558 bool delete_user,
1559 const char *netbios_name,
1560 struct trustAuthInOutBlob *in)
1562 const char *attrs[] = { "userAccountControl", NULL };
1563 struct ldb_message **msgs;
1564 struct ldb_message *msg;
1565 uint32_t uac;
1566 uint32_t i;
1567 int ret;
1569 ret = gendb_search(sam_ldb, mem_ctx,
1570 base_dn, &msgs, attrs,
1571 "samAccountName=%s$", netbios_name);
1572 if (ret > 1) {
1573 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1576 if (ret == 0) {
1577 if (delete_user) {
1578 return NT_STATUS_OK;
1581 /* ok no existing user, add it from scratch */
1582 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1583 netbios_name, in, NULL);
1586 /* check user is what we are looking for */
1587 uac = ldb_msg_find_attr_as_uint(msgs[0],
1588 "userAccountControl", 0);
1589 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1590 return NT_STATUS_OBJECT_NAME_COLLISION;
1593 if (delete_user) {
1594 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1595 switch (ret) {
1596 case LDB_SUCCESS:
1597 return NT_STATUS_OK;
1598 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1599 return NT_STATUS_ACCESS_DENIED;
1600 default:
1601 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1605 /* entry exists, just modify secret if any */
1606 if (in == NULL || in->count == 0) {
1607 return NT_STATUS_OK;
1610 msg = ldb_msg_new(mem_ctx);
1611 if (!msg) {
1612 return NT_STATUS_NO_MEMORY;
1614 msg->dn = msgs[0]->dn;
1616 for (i = 0; i < in->count; i++) {
1617 const char *attribute;
1618 struct ldb_val v;
1619 switch (in->current.array[i].AuthType) {
1620 case TRUST_AUTH_TYPE_NT4OWF:
1621 attribute = "unicodePwd";
1622 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1623 v.length = 16;
1624 break;
1625 case TRUST_AUTH_TYPE_CLEAR:
1626 attribute = "clearTextPassword";
1627 v.data = in->current.array[i].AuthInfo.clear.password;
1628 v.length = in->current.array[i].AuthInfo.clear.size;
1629 break;
1630 default:
1631 continue;
1634 ret = ldb_msg_add_empty(msg, attribute,
1635 LDB_FLAG_MOD_REPLACE, NULL);
1636 if (ret != LDB_SUCCESS) {
1637 return NT_STATUS_NO_MEMORY;
1640 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1641 if (ret != LDB_SUCCESS) {
1642 return NT_STATUS_NO_MEMORY;
1646 /* create the trusted_domain user account */
1647 ret = ldb_modify(sam_ldb, msg);
1648 if (ret != LDB_SUCCESS) {
1649 DEBUG(0,("Failed to create user record %s: %s\n",
1650 ldb_dn_get_linearized(msg->dn),
1651 ldb_errstring(sam_ldb)));
1653 switch (ret) {
1654 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1655 return NT_STATUS_DOMAIN_EXISTS;
1656 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1657 return NT_STATUS_ACCESS_DENIED;
1658 default:
1659 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1663 return NT_STATUS_OK;
1667 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1668 struct lsa_policy_state *p_state,
1669 TALLOC_CTX *mem_ctx,
1670 struct ldb_message *dom_msg,
1671 enum lsa_TrustDomInfoEnum level,
1672 union lsa_TrustedDomainInfo *info)
1674 uint32_t *posix_offset = NULL;
1675 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1676 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1677 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1678 uint32_t *enc_types = NULL;
1679 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1680 struct trustDomainPasswords auth_struct;
1681 struct trustAuthInOutBlob *current_passwords = NULL;
1682 NTSTATUS nt_status;
1683 struct ldb_message **msgs;
1684 struct ldb_message *msg;
1685 bool add_outgoing = false;
1686 bool add_incoming = false;
1687 bool del_outgoing = false;
1688 bool del_incoming = false;
1689 bool del_forest_info = false;
1690 bool in_transaction = false;
1691 int ret;
1692 bool am_rodc;
1694 switch (level) {
1695 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1696 posix_offset = &info->posix_offset.posix_offset;
1697 break;
1698 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1699 info_ex = &info->info_ex;
1700 break;
1701 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1702 auth_info = &info->auth_info;
1703 break;
1704 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1705 posix_offset = &info->full_info.posix_offset.posix_offset;
1706 info_ex = &info->full_info.info_ex;
1707 auth_info = &info->full_info.auth_info;
1708 break;
1709 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1710 auth_info_int = &info->auth_info_internal;
1711 break;
1712 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1713 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1714 info_ex = &info->full_info_internal.info_ex;
1715 auth_info_int = &info->full_info_internal.auth_info;
1716 break;
1717 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1718 enc_types = &info->enc_types.enc_types;
1719 break;
1720 default:
1721 return NT_STATUS_INVALID_PARAMETER;
1724 if (auth_info) {
1725 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1726 &trustAuthIncoming,
1727 &trustAuthOutgoing);
1728 if (!NT_STATUS_IS_OK(nt_status)) {
1729 return nt_status;
1731 if (trustAuthIncoming.data) {
1732 /* This does the decode of some of this twice, but it is easier that way */
1733 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1734 auth_info->incoming_count,
1735 auth_info->incoming_current_auth_info,
1736 NULL,
1737 &current_passwords);
1738 if (!NT_STATUS_IS_OK(nt_status)) {
1739 return nt_status;
1744 /* decode auth_info_int if set */
1745 if (auth_info_int) {
1747 /* now decrypt blob */
1748 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1749 auth_info_int->auth_blob.size);
1751 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1752 &auth_blob, &auth_struct);
1753 if (!NT_STATUS_IS_OK(nt_status)) {
1754 return nt_status;
1758 if (info_ex) {
1759 /* verify data matches */
1760 if (info_ex->trust_attributes &
1761 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1762 /* TODO: check what behavior level we have */
1763 if (strcasecmp_m(p_state->domain_dns,
1764 p_state->forest_dns) != 0) {
1765 return NT_STATUS_INVALID_DOMAIN_STATE;
1769 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1770 if (ret == LDB_SUCCESS && am_rodc) {
1771 return NT_STATUS_NO_SUCH_DOMAIN;
1774 /* verify only one object matches the dns/netbios/sid
1775 * triplet and that this is the one we already have */
1776 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1777 p_state->system_dn,
1778 info_ex->domain_name.string,
1779 info_ex->netbios_name.string,
1780 info_ex->sid, &msgs);
1781 if (!NT_STATUS_IS_OK(nt_status)) {
1782 return nt_status;
1784 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1785 return NT_STATUS_OBJECT_NAME_COLLISION;
1787 talloc_free(msgs);
1790 /* TODO: should we fetch previous values from the existing entry
1791 * and append them ? */
1792 if (auth_info_int && auth_struct.incoming.count) {
1793 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1794 &auth_struct.incoming,
1795 &trustAuthIncoming);
1796 if (!NT_STATUS_IS_OK(nt_status)) {
1797 return nt_status;
1800 current_passwords = &auth_struct.incoming;
1802 } else {
1803 trustAuthIncoming = data_blob(NULL, 0);
1806 if (auth_info_int && auth_struct.outgoing.count) {
1807 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1808 &auth_struct.outgoing,
1809 &trustAuthOutgoing);
1810 if (!NT_STATUS_IS_OK(nt_status)) {
1811 return nt_status;
1813 } else {
1814 trustAuthOutgoing = data_blob(NULL, 0);
1817 msg = ldb_msg_new(mem_ctx);
1818 if (msg == NULL) {
1819 return NT_STATUS_NO_MEMORY;
1821 msg->dn = dom_msg->dn;
1823 if (posix_offset) {
1824 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1825 dom_msg, msg,
1826 "trustPosixOffset",
1827 *posix_offset, NULL);
1828 if (!NT_STATUS_IS_OK(nt_status)) {
1829 return nt_status;
1833 if (info_ex) {
1834 uint32_t origattrs;
1835 uint32_t changed_attrs;
1836 uint32_t origdir;
1837 int origtype;
1839 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1840 dom_msg, msg,
1841 "trustDirection",
1842 info_ex->trust_direction,
1843 &origdir);
1844 if (!NT_STATUS_IS_OK(nt_status)) {
1845 return nt_status;
1848 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1849 if (auth_info != NULL && trustAuthIncoming.length > 0) {
1850 add_incoming = true;
1853 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1854 if (auth_info != NULL && trustAuthOutgoing.length > 0) {
1855 add_outgoing = true;
1859 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1860 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1861 del_incoming = true;
1863 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1864 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1865 del_outgoing = true;
1868 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1869 if (origtype == -1 || origtype != info_ex->trust_type) {
1870 DEBUG(1, ("Attempted to change trust type! "
1871 "Operation not handled\n"));
1872 return NT_STATUS_INVALID_PARAMETER;
1875 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1876 dom_msg, msg,
1877 "trustAttributes",
1878 info_ex->trust_attributes,
1879 &origattrs);
1880 if (!NT_STATUS_IS_OK(nt_status)) {
1881 return nt_status;
1883 /* TODO: check forestFunctionality from ldb opaque */
1884 /* TODO: check what is set makes sense */
1886 changed_attrs = origattrs ^ info_ex->trust_attributes;
1887 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1889 * For now we only allow
1890 * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
1892 * TODO: we may need to support more attribute changes
1894 DEBUG(1, ("Attempted to change trust attributes "
1895 "(0x%08x != 0x%08x)! "
1896 "Operation not handled yet...\n",
1897 (unsigned)origattrs,
1898 (unsigned)info_ex->trust_attributes));
1899 return NT_STATUS_INVALID_PARAMETER;
1902 if (!(info_ex->trust_attributes &
1903 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
1905 struct ldb_message_element *orig_forest_el = NULL;
1907 orig_forest_el = ldb_msg_find_element(dom_msg,
1908 "msDS-TrustForestTrustInfo");
1909 if (orig_forest_el != NULL) {
1910 del_forest_info = true;
1915 if (enc_types) {
1916 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1917 dom_msg, msg,
1918 "msDS-SupportedEncryptionTypes",
1919 *enc_types, NULL);
1920 if (!NT_STATUS_IS_OK(nt_status)) {
1921 return nt_status;
1925 if (add_incoming || del_incoming) {
1926 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1927 LDB_FLAG_MOD_REPLACE, NULL);
1928 if (ret != LDB_SUCCESS) {
1929 return NT_STATUS_NO_MEMORY;
1931 if (add_incoming) {
1932 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1933 &trustAuthIncoming, NULL);
1934 if (ret != LDB_SUCCESS) {
1935 return NT_STATUS_NO_MEMORY;
1939 if (add_outgoing || del_outgoing) {
1940 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1941 LDB_FLAG_MOD_REPLACE, NULL);
1942 if (ret != LDB_SUCCESS) {
1943 return NT_STATUS_NO_MEMORY;
1945 if (add_outgoing) {
1946 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1947 &trustAuthOutgoing, NULL);
1948 if (ret != LDB_SUCCESS) {
1949 return NT_STATUS_NO_MEMORY;
1953 if (del_forest_info) {
1954 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
1955 LDB_FLAG_MOD_REPLACE, NULL);
1956 if (ret != LDB_SUCCESS) {
1957 return NT_STATUS_NO_MEMORY;
1961 /* start transaction */
1962 ret = ldb_transaction_start(p_state->sam_ldb);
1963 if (ret != LDB_SUCCESS) {
1964 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1966 in_transaction = true;
1968 if (msg->num_elements) {
1969 ret = ldb_modify(p_state->sam_ldb, msg);
1970 if (ret != LDB_SUCCESS) {
1971 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1972 ldb_dn_get_linearized(msg->dn),
1973 ldb_errstring(p_state->sam_ldb)));
1974 nt_status = dsdb_ldb_err_to_ntstatus(ret);
1975 goto done;
1979 if (add_incoming || del_incoming) {
1980 const char *netbios_name;
1982 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1983 "flatname", NULL);
1984 if (!netbios_name) {
1985 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1986 goto done;
1989 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
1990 nt_status = update_trust_user(mem_ctx,
1991 p_state->sam_ldb,
1992 p_state->domain_dn,
1993 del_incoming,
1994 netbios_name,
1995 current_passwords);
1996 if (!NT_STATUS_IS_OK(nt_status)) {
1997 goto done;
2001 /* ok, all fine, commit transaction and return */
2002 ret = ldb_transaction_commit(p_state->sam_ldb);
2003 if (ret != LDB_SUCCESS) {
2004 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2006 in_transaction = false;
2008 nt_status = NT_STATUS_OK;
2010 done:
2011 if (in_transaction) {
2012 ldb_transaction_cancel(p_state->sam_ldb);
2014 return nt_status;
2018 lsa_SetInfomrationTrustedDomain
2020 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
2021 struct dcesrv_call_state *dce_call,
2022 TALLOC_CTX *mem_ctx,
2023 struct lsa_SetInformationTrustedDomain *r)
2025 struct dcesrv_handle *h;
2026 struct lsa_trusted_domain_state *td_state;
2027 struct ldb_message **msgs;
2028 NTSTATUS nt_status;
2030 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
2031 LSA_HANDLE_TRUSTED_DOMAIN);
2033 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2035 /* get the trusted domain object */
2036 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
2037 td_state->trusted_domain_dn,
2038 NULL, NULL, NULL, &msgs);
2039 if (!NT_STATUS_IS_OK(nt_status)) {
2040 if (NT_STATUS_EQUAL(nt_status,
2041 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2042 return nt_status;
2044 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2047 return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
2048 msgs[0], r->in.level, r->in.info);
2053 lsa_DeleteTrustedDomain
2055 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2056 struct lsa_DeleteTrustedDomain *r)
2058 NTSTATUS status;
2059 struct lsa_OpenTrustedDomain opn;
2060 struct lsa_DeleteObject del;
2061 struct dcesrv_handle *h;
2063 opn.in.handle = r->in.handle;
2064 opn.in.sid = r->in.dom_sid;
2065 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2066 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2067 if (!opn.out.trustdom_handle) {
2068 return NT_STATUS_NO_MEMORY;
2070 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2071 if (!NT_STATUS_IS_OK(status)) {
2072 return status;
2075 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2076 talloc_steal(mem_ctx, h);
2078 del.in.handle = opn.out.trustdom_handle;
2079 del.out.handle = opn.out.trustdom_handle;
2080 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2081 if (!NT_STATUS_IS_OK(status)) {
2082 return status;
2084 return NT_STATUS_OK;
2087 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2088 struct ldb_message *msg,
2089 struct lsa_TrustDomainInfoInfoEx *info_ex)
2091 info_ex->domain_name.string
2092 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2093 info_ex->netbios_name.string
2094 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2095 info_ex->sid
2096 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2097 info_ex->trust_direction
2098 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2099 info_ex->trust_type
2100 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2101 info_ex->trust_attributes
2102 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2103 return NT_STATUS_OK;
2107 lsa_QueryTrustedDomainInfo
2109 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2110 struct lsa_QueryTrustedDomainInfo *r)
2112 union lsa_TrustedDomainInfo *info = NULL;
2113 struct dcesrv_handle *h;
2114 struct lsa_trusted_domain_state *trusted_domain_state;
2115 struct ldb_message *msg;
2116 int ret;
2117 struct ldb_message **res;
2118 const char *attrs[] = {
2119 "flatname",
2120 "trustPartner",
2121 "securityIdentifier",
2122 "trustDirection",
2123 "trustType",
2124 "trustAttributes",
2125 "msDs-supportedEncryptionTypes",
2126 NULL
2129 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2131 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2133 /* pull all the user attributes */
2134 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2135 trusted_domain_state->trusted_domain_dn, &res, attrs);
2136 if (ret != 1) {
2137 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2139 msg = res[0];
2141 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2142 if (!info) {
2143 return NT_STATUS_NO_MEMORY;
2145 *r->out.info = info;
2147 switch (r->in.level) {
2148 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2149 info->name.netbios_name.string
2150 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2151 break;
2152 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2153 info->posix_offset.posix_offset
2154 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2155 break;
2156 #if 0 /* Win2k3 doesn't implement this */
2157 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2158 r->out.info->info_basic.netbios_name.string
2159 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2160 r->out.info->info_basic.sid
2161 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2162 break;
2163 #endif
2164 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2165 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2167 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2168 ZERO_STRUCT(info->full_info);
2169 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2170 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2171 ZERO_STRUCT(info->full_info2_internal);
2172 info->full_info2_internal.posix_offset.posix_offset
2173 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2174 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2176 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2177 info->enc_types.enc_types
2178 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2179 break;
2181 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2182 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2183 /* oops, we don't want to return the info after all */
2184 talloc_free(info);
2185 *r->out.info = NULL;
2186 return NT_STATUS_INVALID_PARAMETER;
2187 default:
2188 /* oops, we don't want to return the info after all */
2189 talloc_free(info);
2190 *r->out.info = NULL;
2191 return NT_STATUS_INVALID_INFO_CLASS;
2194 return NT_STATUS_OK;
2199 lsa_QueryTrustedDomainInfoBySid
2201 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2202 struct lsa_QueryTrustedDomainInfoBySid *r)
2204 NTSTATUS status;
2205 struct lsa_OpenTrustedDomain opn;
2206 struct lsa_QueryTrustedDomainInfo query;
2207 struct dcesrv_handle *h;
2209 opn.in.handle = r->in.handle;
2210 opn.in.sid = r->in.dom_sid;
2211 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2212 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2213 if (!opn.out.trustdom_handle) {
2214 return NT_STATUS_NO_MEMORY;
2216 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2217 if (!NT_STATUS_IS_OK(status)) {
2218 return status;
2221 /* Ensure this handle goes away at the end of this call */
2222 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2223 talloc_steal(mem_ctx, h);
2225 query.in.trustdom_handle = opn.out.trustdom_handle;
2226 query.in.level = r->in.level;
2227 query.out.info = r->out.info;
2228 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2229 if (!NT_STATUS_IS_OK(status)) {
2230 return status;
2233 return NT_STATUS_OK;
2237 lsa_SetTrustedDomainInfoByName
2239 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2240 TALLOC_CTX *mem_ctx,
2241 struct lsa_SetTrustedDomainInfoByName *r)
2243 struct dcesrv_handle *policy_handle;
2244 struct lsa_policy_state *policy_state;
2245 struct ldb_message **msgs;
2246 NTSTATUS nt_status;
2248 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2249 policy_state = policy_handle->data;
2251 /* get the trusted domain object */
2252 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2253 policy_state->domain_dn,
2254 r->in.trusted_domain->string,
2255 r->in.trusted_domain->string,
2256 NULL, &msgs);
2257 if (!NT_STATUS_IS_OK(nt_status)) {
2258 if (NT_STATUS_EQUAL(nt_status,
2259 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2260 return nt_status;
2262 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2265 return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2266 msgs[0], r->in.level, r->in.info);
2270 lsa_QueryTrustedDomainInfoByName
2272 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2273 TALLOC_CTX *mem_ctx,
2274 struct lsa_QueryTrustedDomainInfoByName *r)
2276 NTSTATUS status;
2277 struct lsa_OpenTrustedDomainByName opn;
2278 struct lsa_QueryTrustedDomainInfo query;
2279 struct dcesrv_handle *h;
2281 opn.in.handle = r->in.handle;
2282 opn.in.name = *r->in.trusted_domain;
2283 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2284 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2285 if (!opn.out.trustdom_handle) {
2286 return NT_STATUS_NO_MEMORY;
2288 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2289 if (!NT_STATUS_IS_OK(status)) {
2290 return status;
2293 /* Ensure this handle goes away at the end of this call */
2294 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2295 talloc_steal(mem_ctx, h);
2297 query.in.trustdom_handle = opn.out.trustdom_handle;
2298 query.in.level = r->in.level;
2299 query.out.info = r->out.info;
2300 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2301 if (!NT_STATUS_IS_OK(status)) {
2302 return status;
2305 return NT_STATUS_OK;
2309 lsa_CloseTrustedDomainEx
2311 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2312 TALLOC_CTX *mem_ctx,
2313 struct lsa_CloseTrustedDomainEx *r)
2315 /* The result of a bad hair day from an IDL programmer? Not
2316 * implmented in Win2k3. You should always just lsa_Close
2317 * anyway. */
2318 return NT_STATUS_NOT_IMPLEMENTED;
2323 comparison function for sorting lsa_DomainInformation array
2325 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2327 return strcasecmp_m(e1->name.string, e2->name.string);
2331 lsa_EnumTrustDom
2333 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2334 struct lsa_EnumTrustDom *r)
2336 struct dcesrv_handle *policy_handle;
2337 struct lsa_DomainInfo *entries;
2338 struct lsa_policy_state *policy_state;
2339 struct ldb_message **domains;
2340 const char *attrs[] = {
2341 "flatname",
2342 "securityIdentifier",
2343 NULL
2347 int count, i;
2349 *r->out.resume_handle = 0;
2351 r->out.domains->domains = NULL;
2352 r->out.domains->count = 0;
2354 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2356 policy_state = policy_handle->data;
2358 /* search for all users in this domain. This could possibly be cached and
2359 resumed based on resume_key */
2360 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2361 "objectclass=trustedDomain");
2362 if (count < 0) {
2363 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2366 /* convert to lsa_TrustInformation format */
2367 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2368 if (!entries) {
2369 return NT_STATUS_NO_MEMORY;
2371 for (i=0;i<count;i++) {
2372 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2373 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2376 /* sort the results by name */
2377 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2379 if (*r->in.resume_handle >= count) {
2380 *r->out.resume_handle = -1;
2382 return NT_STATUS_NO_MORE_ENTRIES;
2385 /* return the rest, limit by max_size. Note that we
2386 use the w2k3 element size value of 60 */
2387 r->out.domains->count = count - *r->in.resume_handle;
2388 r->out.domains->count = MIN(r->out.domains->count,
2389 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2391 r->out.domains->domains = entries + *r->in.resume_handle;
2392 r->out.domains->count = r->out.domains->count;
2394 if (r->out.domains->count < count - *r->in.resume_handle) {
2395 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2396 return STATUS_MORE_ENTRIES;
2399 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2400 * always be larger than the previous input resume handle, in
2401 * particular when hitting the last query it is vital to set the
2402 * resume handle correctly to avoid infinite client loops, as
2403 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2404 * status is NT_STATUS_OK - gd */
2406 *r->out.resume_handle = (uint32_t)-1;
2408 return NT_STATUS_OK;
2412 comparison function for sorting lsa_DomainInformation array
2414 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2416 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2420 lsa_EnumTrustedDomainsEx
2422 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2423 struct lsa_EnumTrustedDomainsEx *r)
2425 struct dcesrv_handle *policy_handle;
2426 struct lsa_TrustDomainInfoInfoEx *entries;
2427 struct lsa_policy_state *policy_state;
2428 struct ldb_message **domains;
2429 const char *attrs[] = {
2430 "flatname",
2431 "trustPartner",
2432 "securityIdentifier",
2433 "trustDirection",
2434 "trustType",
2435 "trustAttributes",
2436 NULL
2438 NTSTATUS nt_status;
2440 int count, i;
2442 *r->out.resume_handle = 0;
2444 r->out.domains->domains = NULL;
2445 r->out.domains->count = 0;
2447 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2449 policy_state = policy_handle->data;
2451 /* search for all users in this domain. This could possibly be cached and
2452 resumed based on resume_key */
2453 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2454 "objectclass=trustedDomain");
2455 if (count < 0) {
2456 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2459 /* convert to lsa_DomainInformation format */
2460 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2461 if (!entries) {
2462 return NT_STATUS_NO_MEMORY;
2464 for (i=0;i<count;i++) {
2465 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2466 if (!NT_STATUS_IS_OK(nt_status)) {
2467 return nt_status;
2471 /* sort the results by name */
2472 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2474 if (*r->in.resume_handle >= count) {
2475 *r->out.resume_handle = -1;
2477 return NT_STATUS_NO_MORE_ENTRIES;
2480 /* return the rest, limit by max_size. Note that we
2481 use the w2k3 element size value of 60 */
2482 r->out.domains->count = count - *r->in.resume_handle;
2483 r->out.domains->count = MIN(r->out.domains->count,
2484 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2486 r->out.domains->domains = entries + *r->in.resume_handle;
2487 r->out.domains->count = r->out.domains->count;
2489 if (r->out.domains->count < count - *r->in.resume_handle) {
2490 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2491 return STATUS_MORE_ENTRIES;
2494 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2496 return NT_STATUS_OK;
2501 lsa_OpenAccount
2503 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2504 struct lsa_OpenAccount *r)
2506 struct dcesrv_handle *h, *ah;
2507 struct lsa_policy_state *state;
2508 struct lsa_account_state *astate;
2510 ZERO_STRUCTP(r->out.acct_handle);
2512 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2514 state = h->data;
2516 astate = talloc(dce_call->conn, struct lsa_account_state);
2517 if (astate == NULL) {
2518 return NT_STATUS_NO_MEMORY;
2521 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2522 if (astate->account_sid == NULL) {
2523 talloc_free(astate);
2524 return NT_STATUS_NO_MEMORY;
2527 astate->policy = talloc_reference(astate, state);
2528 astate->access_mask = r->in.access_mask;
2531 * For now we grant all requested access.
2533 * We will fail at the ldb layer later.
2535 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2536 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2537 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2539 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2541 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2542 __func__, dom_sid_string(mem_ctx, astate->account_sid),
2543 (unsigned)r->in.access_mask,
2544 (unsigned)astate->access_mask));
2546 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2547 if (!ah) {
2548 talloc_free(astate);
2549 return NT_STATUS_NO_MEMORY;
2552 ah->data = talloc_steal(ah, astate);
2554 *r->out.acct_handle = ah->wire_handle;
2556 return NT_STATUS_OK;
2561 lsa_EnumPrivsAccount
2563 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2564 TALLOC_CTX *mem_ctx,
2565 struct lsa_EnumPrivsAccount *r)
2567 struct dcesrv_handle *h;
2568 struct lsa_account_state *astate;
2569 int ret;
2570 unsigned int i, j;
2571 struct ldb_message **res;
2572 const char * const attrs[] = { "privilege", NULL};
2573 struct ldb_message_element *el;
2574 const char *sidstr;
2575 struct lsa_PrivilegeSet *privs;
2577 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2579 astate = h->data;
2581 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2582 if (privs == NULL) {
2583 return NT_STATUS_NO_MEMORY;
2585 privs->count = 0;
2586 privs->unknown = 0;
2587 privs->set = NULL;
2589 *r->out.privs = privs;
2591 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2592 if (sidstr == NULL) {
2593 return NT_STATUS_NO_MEMORY;
2596 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2597 "objectSid=%s", sidstr);
2598 if (ret < 0) {
2599 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2601 if (ret != 1) {
2602 return NT_STATUS_OK;
2605 el = ldb_msg_find_element(res[0], "privilege");
2606 if (el == NULL || el->num_values == 0) {
2607 return NT_STATUS_OK;
2610 privs->set = talloc_array(privs,
2611 struct lsa_LUIDAttribute, el->num_values);
2612 if (privs->set == NULL) {
2613 return NT_STATUS_NO_MEMORY;
2616 j = 0;
2617 for (i=0;i<el->num_values;i++) {
2618 int id = sec_privilege_id((const char *)el->values[i].data);
2619 if (id == SEC_PRIV_INVALID) {
2620 /* Perhaps an account right, not a privilege */
2621 continue;
2623 privs->set[j].attribute = 0;
2624 privs->set[j].luid.low = id;
2625 privs->set[j].luid.high = 0;
2626 j++;
2629 privs->count = j;
2631 return NT_STATUS_OK;
2635 lsa_EnumAccountRights
2637 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2638 TALLOC_CTX *mem_ctx,
2639 struct lsa_EnumAccountRights *r)
2641 struct dcesrv_handle *h;
2642 struct lsa_policy_state *state;
2643 int ret;
2644 unsigned int i;
2645 struct ldb_message **res;
2646 const char * const attrs[] = { "privilege", NULL};
2647 const char *sidstr;
2648 struct ldb_message_element *el;
2650 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2652 state = h->data;
2654 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2655 if (sidstr == NULL) {
2656 return NT_STATUS_NO_MEMORY;
2659 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2660 "(&(objectSid=%s)(privilege=*))", sidstr);
2661 if (ret == 0) {
2662 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2664 if (ret != 1) {
2665 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2666 dom_sid_string(mem_ctx, r->in.sid),
2667 ldb_errstring(state->pdb)));
2668 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2671 el = ldb_msg_find_element(res[0], "privilege");
2672 if (el == NULL || el->num_values == 0) {
2673 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2676 r->out.rights->count = el->num_values;
2677 r->out.rights->names = talloc_array(r->out.rights,
2678 struct lsa_StringLarge, r->out.rights->count);
2679 if (r->out.rights->names == NULL) {
2680 return NT_STATUS_NO_MEMORY;
2683 for (i=0;i<el->num_values;i++) {
2684 r->out.rights->names[i].string = (const char *)el->values[i].data;
2687 return NT_STATUS_OK;
2693 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2695 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2696 TALLOC_CTX *mem_ctx,
2697 struct lsa_policy_state *state,
2698 int ldb_flag,
2699 struct dom_sid *sid,
2700 const struct lsa_RightSet *rights)
2702 const char *sidstr, *sidndrstr;
2703 struct ldb_message *msg;
2704 struct ldb_message_element *el;
2705 int ret;
2706 uint32_t i;
2707 struct lsa_EnumAccountRights r2;
2708 char *dnstr;
2710 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2711 SECURITY_ADMINISTRATOR) {
2712 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2713 return NT_STATUS_ACCESS_DENIED;
2716 msg = ldb_msg_new(mem_ctx);
2717 if (msg == NULL) {
2718 return NT_STATUS_NO_MEMORY;
2721 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2722 if (sidndrstr == NULL) {
2723 TALLOC_FREE(msg);
2724 return NT_STATUS_NO_MEMORY;
2727 sidstr = dom_sid_string(msg, sid);
2728 if (sidstr == NULL) {
2729 TALLOC_FREE(msg);
2730 return NT_STATUS_NO_MEMORY;
2733 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2734 if (dnstr == NULL) {
2735 TALLOC_FREE(msg);
2736 return NT_STATUS_NO_MEMORY;
2739 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2740 if (msg->dn == NULL) {
2741 TALLOC_FREE(msg);
2742 return NT_STATUS_NO_MEMORY;
2745 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2746 NTSTATUS status;
2748 r2.in.handle = &state->handle->wire_handle;
2749 r2.in.sid = sid;
2750 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2752 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2753 if (!NT_STATUS_IS_OK(status)) {
2754 ZERO_STRUCTP(r2.out.rights);
2758 for (i=0;i<rights->count;i++) {
2759 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2760 if (sec_right_bit(rights->names[i].string) == 0) {
2761 talloc_free(msg);
2762 return NT_STATUS_NO_SUCH_PRIVILEGE;
2765 talloc_free(msg);
2766 return NT_STATUS_NO_SUCH_PRIVILEGE;
2769 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2770 uint32_t j;
2771 for (j=0;j<r2.out.rights->count;j++) {
2772 if (strcasecmp_m(r2.out.rights->names[j].string,
2773 rights->names[i].string) == 0) {
2774 break;
2777 if (j != r2.out.rights->count) continue;
2780 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2781 if (ret != LDB_SUCCESS) {
2782 talloc_free(msg);
2783 return NT_STATUS_NO_MEMORY;
2787 el = ldb_msg_find_element(msg, "privilege");
2788 if (!el) {
2789 talloc_free(msg);
2790 return NT_STATUS_OK;
2793 el->flags = ldb_flag;
2795 ret = ldb_modify(state->pdb, msg);
2796 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2797 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2798 talloc_free(msg);
2799 return NT_STATUS_NO_MEMORY;
2801 ldb_msg_add_string(msg, "comment", "added via LSA");
2802 ret = ldb_add(state->pdb, msg);
2804 if (ret != LDB_SUCCESS) {
2805 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2806 talloc_free(msg);
2807 return NT_STATUS_OK;
2809 DEBUG(3, ("Could not %s attributes from %s: %s",
2810 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2811 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2812 talloc_free(msg);
2813 return NT_STATUS_UNEXPECTED_IO_ERROR;
2816 talloc_free(msg);
2817 return NT_STATUS_OK;
2821 lsa_AddPrivilegesToAccount
2823 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2824 struct lsa_AddPrivilegesToAccount *r)
2826 struct lsa_RightSet rights;
2827 struct dcesrv_handle *h;
2828 struct lsa_account_state *astate;
2829 uint32_t i;
2831 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2833 astate = h->data;
2835 rights.count = r->in.privs->count;
2836 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2837 if (rights.names == NULL) {
2838 return NT_STATUS_NO_MEMORY;
2840 for (i=0;i<rights.count;i++) {
2841 int id = r->in.privs->set[i].luid.low;
2842 if (r->in.privs->set[i].luid.high) {
2843 return NT_STATUS_NO_SUCH_PRIVILEGE;
2845 rights.names[i].string = sec_privilege_name(id);
2846 if (rights.names[i].string == NULL) {
2847 return NT_STATUS_NO_SUCH_PRIVILEGE;
2851 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2852 LDB_FLAG_MOD_ADD, astate->account_sid,
2853 &rights);
2858 lsa_RemovePrivilegesFromAccount
2860 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2861 struct lsa_RemovePrivilegesFromAccount *r)
2863 struct lsa_RightSet *rights;
2864 struct dcesrv_handle *h;
2865 struct lsa_account_state *astate;
2866 uint32_t i;
2868 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2870 astate = h->data;
2872 rights = talloc(mem_ctx, struct lsa_RightSet);
2874 if (r->in.remove_all == 1 &&
2875 r->in.privs == NULL) {
2876 struct lsa_EnumAccountRights r2;
2877 NTSTATUS status;
2879 r2.in.handle = &astate->policy->handle->wire_handle;
2880 r2.in.sid = astate->account_sid;
2881 r2.out.rights = rights;
2883 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2884 if (!NT_STATUS_IS_OK(status)) {
2885 return status;
2888 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2889 LDB_FLAG_MOD_DELETE, astate->account_sid,
2890 r2.out.rights);
2893 if (r->in.remove_all != 0) {
2894 return NT_STATUS_INVALID_PARAMETER;
2897 rights->count = r->in.privs->count;
2898 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2899 if (rights->names == NULL) {
2900 return NT_STATUS_NO_MEMORY;
2902 for (i=0;i<rights->count;i++) {
2903 int id = r->in.privs->set[i].luid.low;
2904 if (r->in.privs->set[i].luid.high) {
2905 return NT_STATUS_NO_SUCH_PRIVILEGE;
2907 rights->names[i].string = sec_privilege_name(id);
2908 if (rights->names[i].string == NULL) {
2909 return NT_STATUS_NO_SUCH_PRIVILEGE;
2913 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2914 LDB_FLAG_MOD_DELETE, astate->account_sid,
2915 rights);
2920 lsa_GetQuotasForAccount
2922 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2923 struct lsa_GetQuotasForAccount *r)
2925 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2930 lsa_SetQuotasForAccount
2932 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2933 struct lsa_SetQuotasForAccount *r)
2935 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2940 lsa_GetSystemAccessAccount
2942 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2943 struct lsa_GetSystemAccessAccount *r)
2945 struct dcesrv_handle *h;
2946 struct lsa_account_state *astate;
2947 int ret;
2948 unsigned int i;
2949 struct ldb_message **res;
2950 const char * const attrs[] = { "privilege", NULL};
2951 struct ldb_message_element *el;
2952 const char *sidstr;
2954 *(r->out.access_mask) = 0x00000000;
2956 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2958 astate = h->data;
2960 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2961 if (sidstr == NULL) {
2962 return NT_STATUS_NO_MEMORY;
2965 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2966 "objectSid=%s", sidstr);
2967 if (ret < 0) {
2968 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2970 if (ret != 1) {
2971 return NT_STATUS_OK;
2974 el = ldb_msg_find_element(res[0], "privilege");
2975 if (el == NULL || el->num_values == 0) {
2976 return NT_STATUS_OK;
2979 for (i=0;i<el->num_values;i++) {
2980 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2981 if (right_bit == 0) {
2982 /* Perhaps an privilege, not a right */
2983 continue;
2985 *(r->out.access_mask) |= right_bit;
2988 return NT_STATUS_OK;
2993 lsa_SetSystemAccessAccount
2995 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2996 struct lsa_SetSystemAccessAccount *r)
2998 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3003 lsa_CreateSecret
3005 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3006 struct lsa_CreateSecret *r)
3008 struct dcesrv_handle *policy_handle;
3009 struct lsa_policy_state *policy_state;
3010 struct lsa_secret_state *secret_state;
3011 struct dcesrv_handle *handle;
3012 struct ldb_message **msgs, *msg;
3013 const char *attrs[] = {
3014 NULL
3017 const char *name;
3019 int ret;
3021 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3022 ZERO_STRUCTP(r->out.sec_handle);
3024 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3026 case SECURITY_SYSTEM:
3027 case SECURITY_ADMINISTRATOR:
3028 break;
3029 default:
3030 /* Users and annonymous are not allowed create secrets */
3031 return NT_STATUS_ACCESS_DENIED;
3034 policy_state = policy_handle->data;
3036 if (!r->in.name.string) {
3037 return NT_STATUS_INVALID_PARAMETER;
3040 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3041 NT_STATUS_HAVE_NO_MEMORY(secret_state);
3042 secret_state->policy = policy_state;
3044 msg = ldb_msg_new(mem_ctx);
3045 if (msg == NULL) {
3046 return NT_STATUS_NO_MEMORY;
3049 if (strncmp("G$", r->in.name.string, 2) == 0) {
3050 const char *name2;
3052 secret_state->global = true;
3054 name = &r->in.name.string[2];
3055 if (strlen(name) == 0) {
3056 return NT_STATUS_INVALID_PARAMETER;
3059 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3060 ldb_binary_encode_string(mem_ctx, name));
3061 NT_STATUS_HAVE_NO_MEMORY(name2);
3063 /* We need to connect to the database as system, as this is one
3064 * of the rare RPC calls that must read the secrets (and this
3065 * is denied otherwise) */
3066 secret_state->sam_ldb = talloc_reference(secret_state,
3067 samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
3068 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3070 /* search for the secret record */
3071 ret = gendb_search(secret_state->sam_ldb,
3072 mem_ctx, policy_state->system_dn, &msgs, attrs,
3073 "(&(cn=%s)(objectclass=secret))",
3074 name2);
3075 if (ret > 0) {
3076 return NT_STATUS_OBJECT_NAME_COLLISION;
3079 if (ret < 0) {
3080 DEBUG(0,("Failure searching for CN=%s: %s\n",
3081 name2, ldb_errstring(secret_state->sam_ldb)));
3082 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3085 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3086 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3087 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3088 return NT_STATUS_NO_MEMORY;
3091 ret = ldb_msg_add_string(msg, "cn", name2);
3092 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3093 } else {
3094 secret_state->global = false;
3096 name = r->in.name.string;
3097 if (strlen(name) == 0) {
3098 return NT_STATUS_INVALID_PARAMETER;
3101 secret_state->sam_ldb = talloc_reference(secret_state,
3102 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3103 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3105 /* search for the secret record */
3106 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3107 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3108 &msgs, attrs,
3109 "(&(cn=%s)(objectclass=secret))",
3110 ldb_binary_encode_string(mem_ctx, name));
3111 if (ret > 0) {
3112 return NT_STATUS_OBJECT_NAME_COLLISION;
3115 if (ret < 0) {
3116 DEBUG(0,("Failure searching for CN=%s: %s\n",
3117 name, ldb_errstring(secret_state->sam_ldb)));
3118 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3121 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3122 "cn=%s,cn=LSA Secrets", name);
3123 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3124 ret = ldb_msg_add_string(msg, "cn", name);
3125 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3128 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3129 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3131 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3132 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3134 /* create the secret */
3135 ret = ldb_add(secret_state->sam_ldb, msg);
3136 if (ret != LDB_SUCCESS) {
3137 DEBUG(0,("Failed to create secret record %s: %s\n",
3138 ldb_dn_get_linearized(msg->dn),
3139 ldb_errstring(secret_state->sam_ldb)));
3140 return NT_STATUS_ACCESS_DENIED;
3143 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3144 NT_STATUS_HAVE_NO_MEMORY(handle);
3146 handle->data = talloc_steal(handle, secret_state);
3148 secret_state->access_mask = r->in.access_mask;
3149 secret_state->policy = talloc_reference(secret_state, policy_state);
3150 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3152 *r->out.sec_handle = handle->wire_handle;
3154 return NT_STATUS_OK;
3159 lsa_OpenSecret
3161 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3162 struct lsa_OpenSecret *r)
3164 struct dcesrv_handle *policy_handle;
3166 struct lsa_policy_state *policy_state;
3167 struct lsa_secret_state *secret_state;
3168 struct dcesrv_handle *handle;
3169 struct ldb_message **msgs;
3170 const char *attrs[] = {
3171 NULL
3174 const char *name;
3176 int ret;
3178 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3179 ZERO_STRUCTP(r->out.sec_handle);
3180 policy_state = policy_handle->data;
3182 if (!r->in.name.string) {
3183 return NT_STATUS_INVALID_PARAMETER;
3186 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3188 case SECURITY_SYSTEM:
3189 case SECURITY_ADMINISTRATOR:
3190 break;
3191 default:
3192 /* Users and annonymous are not allowed to access secrets */
3193 return NT_STATUS_ACCESS_DENIED;
3196 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3197 if (!secret_state) {
3198 return NT_STATUS_NO_MEMORY;
3200 secret_state->policy = policy_state;
3202 if (strncmp("G$", r->in.name.string, 2) == 0) {
3203 name = &r->in.name.string[2];
3204 /* We need to connect to the database as system, as this is one of the rare RPC calls that must read the secrets (and this is denied otherwise) */
3205 secret_state->sam_ldb = talloc_reference(secret_state,
3206 samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
3207 secret_state->global = true;
3209 if (strlen(name) < 1) {
3210 return NT_STATUS_INVALID_PARAMETER;
3213 /* search for the secret record */
3214 ret = gendb_search(secret_state->sam_ldb,
3215 mem_ctx, policy_state->system_dn, &msgs, attrs,
3216 "(&(cn=%s Secret)(objectclass=secret))",
3217 ldb_binary_encode_string(mem_ctx, name));
3218 if (ret == 0) {
3219 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3222 if (ret != 1) {
3223 DEBUG(0,("Found %d records matching DN %s\n", ret,
3224 ldb_dn_get_linearized(policy_state->system_dn)));
3225 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3227 } else {
3228 secret_state->global = false;
3229 secret_state->sam_ldb = talloc_reference(secret_state,
3230 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3232 name = r->in.name.string;
3233 if (strlen(name) < 1) {
3234 return NT_STATUS_INVALID_PARAMETER;
3237 /* search for the secret record */
3238 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3239 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3240 &msgs, attrs,
3241 "(&(cn=%s)(objectclass=secret))",
3242 ldb_binary_encode_string(mem_ctx, name));
3243 if (ret == 0) {
3244 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3247 if (ret != 1) {
3248 DEBUG(0,("Found %d records matching CN=%s\n",
3249 ret, ldb_binary_encode_string(mem_ctx, name)));
3250 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3254 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3256 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3257 if (!handle) {
3258 return NT_STATUS_NO_MEMORY;
3261 handle->data = talloc_steal(handle, secret_state);
3263 secret_state->access_mask = r->in.access_mask;
3264 secret_state->policy = talloc_reference(secret_state, policy_state);
3266 *r->out.sec_handle = handle->wire_handle;
3268 return NT_STATUS_OK;
3273 lsa_SetSecret
3275 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3276 struct lsa_SetSecret *r)
3279 struct dcesrv_handle *h;
3280 struct lsa_secret_state *secret_state;
3281 struct ldb_message *msg;
3282 DATA_BLOB session_key;
3283 DATA_BLOB crypt_secret, secret;
3284 struct ldb_val val;
3285 int ret;
3286 NTSTATUS status = NT_STATUS_OK;
3288 struct timeval now = timeval_current();
3289 NTTIME nt_now = timeval_to_nttime(&now);
3291 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3293 secret_state = h->data;
3295 msg = ldb_msg_new(mem_ctx);
3296 if (msg == NULL) {
3297 return NT_STATUS_NO_MEMORY;
3300 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3301 if (!msg->dn) {
3302 return NT_STATUS_NO_MEMORY;
3304 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3305 if (!NT_STATUS_IS_OK(status)) {
3306 return status;
3309 if (r->in.old_val) {
3310 /* Decrypt */
3311 crypt_secret.data = r->in.old_val->data;
3312 crypt_secret.length = r->in.old_val->size;
3314 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3315 if (!NT_STATUS_IS_OK(status)) {
3316 return status;
3319 val.data = secret.data;
3320 val.length = secret.length;
3322 /* set value */
3323 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3324 return NT_STATUS_NO_MEMORY;
3327 /* set old value mtime */
3328 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3329 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3330 return NT_STATUS_NO_MEMORY;
3333 } else {
3334 /* If the old value is not set, then migrate the
3335 * current value to the old value */
3336 const struct ldb_val *old_val;
3337 NTTIME last_set_time;
3338 struct ldb_message **res;
3339 const char *attrs[] = {
3340 "currentValue",
3341 "lastSetTime",
3342 NULL
3345 /* search for the secret record */
3346 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3347 secret_state->secret_dn, &res, attrs);
3348 if (ret == 0) {
3349 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3352 if (ret != 1) {
3353 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3354 ldb_dn_get_linearized(secret_state->secret_dn)));
3355 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3358 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3359 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3361 if (old_val) {
3362 /* set old value */
3363 if (ldb_msg_add_value(msg, "priorValue",
3364 old_val, NULL) != LDB_SUCCESS) {
3365 return NT_STATUS_NO_MEMORY;
3367 } else {
3368 if (samdb_msg_add_delete(secret_state->sam_ldb,
3369 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3370 return NT_STATUS_NO_MEMORY;
3374 /* set old value mtime */
3375 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3376 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3377 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3378 return NT_STATUS_NO_MEMORY;
3380 } else {
3381 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3382 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3383 return NT_STATUS_NO_MEMORY;
3388 if (r->in.new_val) {
3389 /* Decrypt */
3390 crypt_secret.data = r->in.new_val->data;
3391 crypt_secret.length = r->in.new_val->size;
3393 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3394 if (!NT_STATUS_IS_OK(status)) {
3395 return status;
3398 val.data = secret.data;
3399 val.length = secret.length;
3401 /* set value */
3402 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3403 return NT_STATUS_NO_MEMORY;
3406 /* set new value mtime */
3407 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3408 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3409 return NT_STATUS_NO_MEMORY;
3411 } else {
3412 /* NULL out the NEW value */
3413 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3414 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3415 return NT_STATUS_NO_MEMORY;
3417 if (samdb_msg_add_delete(secret_state->sam_ldb,
3418 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3419 return NT_STATUS_NO_MEMORY;
3423 /* modify the samdb record */
3424 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3425 if (ret != LDB_SUCCESS) {
3426 return dsdb_ldb_err_to_ntstatus(ret);
3429 return NT_STATUS_OK;
3434 lsa_QuerySecret
3436 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3437 struct lsa_QuerySecret *r)
3439 struct dcesrv_handle *h;
3440 struct lsa_secret_state *secret_state;
3441 struct ldb_message *msg;
3442 DATA_BLOB session_key;
3443 DATA_BLOB crypt_secret, secret;
3444 int ret;
3445 struct ldb_message **res;
3446 const char *attrs[] = {
3447 "currentValue",
3448 "priorValue",
3449 "lastSetTime",
3450 "priorSetTime",
3451 NULL
3454 NTSTATUS nt_status;
3456 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3458 /* Ensure user is permitted to read this... */
3459 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3461 case SECURITY_SYSTEM:
3462 case SECURITY_ADMINISTRATOR:
3463 break;
3464 default:
3465 /* Users and annonymous are not allowed to read secrets */
3466 return NT_STATUS_ACCESS_DENIED;
3469 secret_state = h->data;
3471 /* pull all the user attributes */
3472 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3473 secret_state->secret_dn, &res, attrs);
3474 if (ret != 1) {
3475 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3477 msg = res[0];
3479 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3480 if (!NT_STATUS_IS_OK(nt_status)) {
3481 return nt_status;
3484 if (r->in.old_val) {
3485 const struct ldb_val *prior_val;
3486 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3487 if (!r->out.old_val) {
3488 return NT_STATUS_NO_MEMORY;
3490 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3492 if (prior_val && prior_val->length) {
3493 secret.data = prior_val->data;
3494 secret.length = prior_val->length;
3496 /* Encrypt */
3497 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3498 if (!crypt_secret.length) {
3499 return NT_STATUS_NO_MEMORY;
3501 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3502 if (!r->out.old_val->buf) {
3503 return NT_STATUS_NO_MEMORY;
3505 r->out.old_val->buf->size = crypt_secret.length;
3506 r->out.old_val->buf->length = crypt_secret.length;
3507 r->out.old_val->buf->data = crypt_secret.data;
3511 if (r->in.old_mtime) {
3512 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3513 if (!r->out.old_mtime) {
3514 return NT_STATUS_NO_MEMORY;
3516 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3519 if (r->in.new_val) {
3520 const struct ldb_val *new_val;
3521 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3522 if (!r->out.new_val) {
3523 return NT_STATUS_NO_MEMORY;
3526 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3528 if (new_val && new_val->length) {
3529 secret.data = new_val->data;
3530 secret.length = new_val->length;
3532 /* Encrypt */
3533 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3534 if (!crypt_secret.length) {
3535 return NT_STATUS_NO_MEMORY;
3537 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3538 if (!r->out.new_val->buf) {
3539 return NT_STATUS_NO_MEMORY;
3541 r->out.new_val->buf->length = crypt_secret.length;
3542 r->out.new_val->buf->size = crypt_secret.length;
3543 r->out.new_val->buf->data = crypt_secret.data;
3547 if (r->in.new_mtime) {
3548 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3549 if (!r->out.new_mtime) {
3550 return NT_STATUS_NO_MEMORY;
3552 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3555 return NT_STATUS_OK;
3560 lsa_LookupPrivValue
3562 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3563 TALLOC_CTX *mem_ctx,
3564 struct lsa_LookupPrivValue *r)
3566 struct dcesrv_handle *h;
3567 int id;
3569 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3571 id = sec_privilege_id(r->in.name->string);
3572 if (id == SEC_PRIV_INVALID) {
3573 return NT_STATUS_NO_SUCH_PRIVILEGE;
3576 r->out.luid->low = id;
3577 r->out.luid->high = 0;
3579 return NT_STATUS_OK;
3584 lsa_LookupPrivName
3586 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3587 TALLOC_CTX *mem_ctx,
3588 struct lsa_LookupPrivName *r)
3590 struct dcesrv_handle *h;
3591 struct lsa_StringLarge *name;
3592 const char *privname;
3594 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3596 if (r->in.luid->high != 0) {
3597 return NT_STATUS_NO_SUCH_PRIVILEGE;
3600 privname = sec_privilege_name(r->in.luid->low);
3601 if (privname == NULL) {
3602 return NT_STATUS_NO_SUCH_PRIVILEGE;
3605 name = talloc(mem_ctx, struct lsa_StringLarge);
3606 if (name == NULL) {
3607 return NT_STATUS_NO_MEMORY;
3610 name->string = privname;
3612 *r->out.name = name;
3614 return NT_STATUS_OK;
3619 lsa_LookupPrivDisplayName
3621 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3622 TALLOC_CTX *mem_ctx,
3623 struct lsa_LookupPrivDisplayName *r)
3625 struct dcesrv_handle *h;
3626 struct lsa_StringLarge *disp_name = NULL;
3627 enum sec_privilege id;
3629 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3631 id = sec_privilege_id(r->in.name->string);
3632 if (id == SEC_PRIV_INVALID) {
3633 return NT_STATUS_NO_SUCH_PRIVILEGE;
3636 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3637 if (disp_name == NULL) {
3638 return NT_STATUS_NO_MEMORY;
3641 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3642 if (disp_name->string == NULL) {
3643 return NT_STATUS_INTERNAL_ERROR;
3646 *r->out.disp_name = disp_name;
3647 *r->out.returned_language_id = 0;
3649 return NT_STATUS_OK;
3654 lsa_EnumAccountsWithUserRight
3656 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3657 TALLOC_CTX *mem_ctx,
3658 struct lsa_EnumAccountsWithUserRight *r)
3660 struct dcesrv_handle *h;
3661 struct lsa_policy_state *state;
3662 int ret, i;
3663 struct ldb_message **res;
3664 const char * const attrs[] = { "objectSid", NULL};
3665 const char *privname;
3667 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3669 state = h->data;
3671 if (r->in.name == NULL) {
3672 return NT_STATUS_NO_SUCH_PRIVILEGE;
3675 privname = r->in.name->string;
3676 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3677 return NT_STATUS_NO_SUCH_PRIVILEGE;
3680 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3681 "privilege=%s", privname);
3682 if (ret < 0) {
3683 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3685 if (ret == 0) {
3686 return NT_STATUS_NO_MORE_ENTRIES;
3689 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3690 if (r->out.sids->sids == NULL) {
3691 return NT_STATUS_NO_MEMORY;
3693 for (i=0;i<ret;i++) {
3694 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3695 res[i], "objectSid");
3696 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3698 r->out.sids->num_sids = ret;
3700 return NT_STATUS_OK;
3705 lsa_AddAccountRights
3707 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3708 TALLOC_CTX *mem_ctx,
3709 struct lsa_AddAccountRights *r)
3711 struct dcesrv_handle *h;
3712 struct lsa_policy_state *state;
3714 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3716 state = h->data;
3718 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3719 LDB_FLAG_MOD_ADD,
3720 r->in.sid, r->in.rights);
3725 lsa_RemoveAccountRights
3727 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3728 TALLOC_CTX *mem_ctx,
3729 struct lsa_RemoveAccountRights *r)
3731 struct dcesrv_handle *h;
3732 struct lsa_policy_state *state;
3734 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3736 state = h->data;
3738 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3739 LDB_FLAG_MOD_DELETE,
3740 r->in.sid, r->in.rights);
3745 lsa_StorePrivateData
3747 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3748 struct lsa_StorePrivateData *r)
3750 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3755 lsa_RetrievePrivateData
3757 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3758 struct lsa_RetrievePrivateData *r)
3760 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3765 lsa_GetUserName
3767 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3768 struct lsa_GetUserName *r)
3770 enum dcerpc_transport_t transport =
3771 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3772 NTSTATUS status = NT_STATUS_OK;
3773 const char *account_name;
3774 const char *authority_name;
3775 struct lsa_String *_account_name;
3776 struct lsa_String *_authority_name = NULL;
3778 if (transport != NCACN_NP && transport != NCALRPC) {
3779 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3782 /* this is what w2k3 does */
3783 r->out.account_name = r->in.account_name;
3784 r->out.authority_name = r->in.authority_name;
3786 if (r->in.account_name
3787 && *r->in.account_name
3788 /* && *(*r->in.account_name)->string */
3790 return NT_STATUS_INVALID_PARAMETER;
3793 if (r->in.authority_name
3794 && *r->in.authority_name
3795 /* && *(*r->in.authority_name)->string */
3797 return NT_STATUS_INVALID_PARAMETER;
3800 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3801 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3803 _account_name = talloc(mem_ctx, struct lsa_String);
3804 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3805 _account_name->string = account_name;
3807 if (r->in.authority_name) {
3808 _authority_name = talloc(mem_ctx, struct lsa_String);
3809 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3810 _authority_name->string = authority_name;
3813 *r->out.account_name = _account_name;
3814 if (r->out.authority_name) {
3815 *r->out.authority_name = _authority_name;
3818 return status;
3822 lsa_SetInfoPolicy2
3824 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3825 TALLOC_CTX *mem_ctx,
3826 struct lsa_SetInfoPolicy2 *r)
3828 /* need to support these */
3829 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3832 static void kdc_get_policy(struct loadparm_context *lp_ctx,
3833 struct smb_krb5_context *smb_krb5_context,
3834 struct lsa_DomainInfoKerberos *k)
3836 time_t svc_tkt_lifetime;
3837 time_t usr_tkt_lifetime;
3838 time_t renewal_lifetime;
3840 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
3842 /* Our KDC always re-validates the client */
3843 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
3845 lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
3846 &usr_tkt_lifetime, &renewal_lifetime);
3848 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
3849 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
3850 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
3851 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
3852 However in the parent function we basically just did a full
3853 krb5_context init with the only purpose of getting a global
3854 config option (the max skew), it would probably make more sense
3855 to have a lp_ or ldb global option as the samba default */
3856 if (smb_krb5_context) {
3857 unix_to_nt_time(&k->clock_skew,
3858 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
3860 #endif
3861 k->reserved = 0;
3864 lsa_QueryDomainInformationPolicy
3866 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3867 TALLOC_CTX *mem_ctx,
3868 struct lsa_QueryDomainInformationPolicy *r)
3870 union lsa_DomainInformationPolicy *info;
3872 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3873 if (!info) {
3874 return NT_STATUS_NO_MEMORY;
3877 switch (r->in.level) {
3878 case LSA_DOMAIN_INFO_POLICY_EFS:
3879 talloc_free(info);
3880 *r->out.info = NULL;
3881 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3882 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3884 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3885 struct smb_krb5_context *smb_krb5_context;
3886 int ret = smb_krb5_init_context(mem_ctx,
3887 dce_call->conn->dce_ctx->lp_ctx,
3888 &smb_krb5_context);
3889 if (ret != 0) {
3890 talloc_free(info);
3891 *r->out.info = NULL;
3892 return NT_STATUS_INTERNAL_ERROR;
3894 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3895 smb_krb5_context,
3897 talloc_free(smb_krb5_context);
3898 *r->out.info = info;
3899 return NT_STATUS_OK;
3901 default:
3902 talloc_free(info);
3903 *r->out.info = NULL;
3904 return NT_STATUS_INVALID_INFO_CLASS;
3909 lsa_SetDomInfoPolicy
3911 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3912 TALLOC_CTX *mem_ctx,
3913 struct lsa_SetDomainInformationPolicy *r)
3915 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3919 lsa_TestCall
3921 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3922 TALLOC_CTX *mem_ctx,
3923 struct lsa_TestCall *r)
3925 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3929 lsa_CREDRWRITE
3931 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3932 struct lsa_CREDRWRITE *r)
3934 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3939 lsa_CREDRREAD
3941 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3942 struct lsa_CREDRREAD *r)
3944 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3949 lsa_CREDRENUMERATE
3951 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3952 struct lsa_CREDRENUMERATE *r)
3954 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3959 lsa_CREDRWRITEDOMAINCREDENTIALS
3961 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3962 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3964 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3969 lsa_CREDRREADDOMAINCREDENTIALS
3971 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3972 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3974 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3979 lsa_CREDRDELETE
3981 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3982 struct lsa_CREDRDELETE *r)
3984 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3989 lsa_CREDRGETTARGETINFO
3991 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3992 struct lsa_CREDRGETTARGETINFO *r)
3994 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3999 lsa_CREDRPROFILELOADED
4001 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4002 struct lsa_CREDRPROFILELOADED *r)
4004 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4009 lsa_CREDRGETSESSIONTYPES
4011 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4012 struct lsa_CREDRGETSESSIONTYPES *r)
4014 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4019 lsa_LSARREGISTERAUDITEVENT
4021 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4022 struct lsa_LSARREGISTERAUDITEVENT *r)
4024 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4029 lsa_LSARGENAUDITEVENT
4031 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4032 struct lsa_LSARGENAUDITEVENT *r)
4034 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4039 lsa_LSARUNREGISTERAUDITEVENT
4041 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4042 struct lsa_LSARUNREGISTERAUDITEVENT *r)
4044 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4049 lsa_lsaRQueryForestTrustInformation
4051 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4052 struct lsa_lsaRQueryForestTrustInformation *r)
4054 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4057 #define DNS_CMP_MATCH 0
4058 #define DNS_CMP_FIRST_IS_CHILD 1
4059 #define DNS_CMP_SECOND_IS_CHILD 2
4060 #define DNS_CMP_NO_MATCH 3
4062 /* this function assumes names are well formed DNS names.
4063 * it doesn't validate them */
4064 static int dns_cmp(const char *s1, size_t l1,
4065 const char *s2, size_t l2)
4067 const char *p1, *p2;
4068 size_t t1, t2;
4069 int cret;
4071 if (l1 == l2) {
4072 if (strcasecmp_m(s1, s2) == 0) {
4073 return DNS_CMP_MATCH;
4075 return DNS_CMP_NO_MATCH;
4078 if (l1 > l2) {
4079 p1 = s1;
4080 p2 = s2;
4081 t1 = l1;
4082 t2 = l2;
4083 cret = DNS_CMP_FIRST_IS_CHILD;
4084 } else {
4085 p1 = s2;
4086 p2 = s1;
4087 t1 = l2;
4088 t2 = l1;
4089 cret = DNS_CMP_SECOND_IS_CHILD;
4092 if (p1[t1 - t2 - 1] != '.') {
4093 return DNS_CMP_NO_MATCH;
4096 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
4097 return cret;
4100 return DNS_CMP_NO_MATCH;
4103 /* decode all TDOs forest trust info blobs */
4104 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
4105 struct ldb_message *msg,
4106 struct ForestTrustInfo *info)
4108 const struct ldb_val *ft_blob;
4109 enum ndr_err_code ndr_err;
4111 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
4112 if (!ft_blob || !ft_blob->data) {
4113 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4115 /* ldb_val is equivalent to DATA_BLOB */
4116 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
4117 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
4118 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4119 return NT_STATUS_INVALID_DOMAIN_STATE;
4122 return NT_STATUS_OK;
4125 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
4126 struct ForestTrustInfo *fti)
4128 struct ForestTrustDataDomainInfo *info;
4129 struct ForestTrustInfoRecord *rec;
4131 fti->version = 1;
4132 fti->count = 2;
4133 fti->records = talloc_array(fti,
4134 struct ForestTrustInfoRecordArmor, 2);
4135 if (!fti->records) {
4136 return NT_STATUS_NO_MEMORY;
4139 /* TLN info */
4140 rec = &fti->records[0].record;
4142 rec->flags = 0;
4143 rec->timestamp = 0;
4144 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
4146 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
4147 if (!rec->data.name.string) {
4148 return NT_STATUS_NO_MEMORY;
4150 rec->data.name.size = strlen(rec->data.name.string);
4152 /* DOMAIN info */
4153 rec = &fti->records[1].record;
4155 rec->flags = 0;
4156 rec->timestamp = 0;
4157 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
4159 info = &rec->data.info;
4161 info->sid = *ps->domain_sid;
4162 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
4163 if (!info->dns_name.string) {
4164 return NT_STATUS_NO_MEMORY;
4166 info->dns_name.size = strlen(info->dns_name.string);
4167 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
4168 if (!info->netbios_name.string) {
4169 return NT_STATUS_NO_MEMORY;
4171 info->netbios_name.size = strlen(info->netbios_name.string);
4173 return NT_STATUS_OK;
4176 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
4177 struct lsa_ForestTrustInformation *lfti,
4178 struct ForestTrustInfo *fti)
4180 struct lsa_ForestTrustRecord *lrec;
4181 struct ForestTrustInfoRecord *rec;
4182 struct lsa_StringLarge *tln;
4183 struct lsa_ForestTrustDomainInfo *info;
4184 uint32_t i;
4186 fti->version = 1;
4187 fti->count = lfti->count;
4188 fti->records = talloc_array(mem_ctx,
4189 struct ForestTrustInfoRecordArmor,
4190 fti->count);
4191 if (!fti->records) {
4192 return NT_STATUS_NO_MEMORY;
4194 for (i = 0; i < fti->count; i++) {
4195 lrec = lfti->entries[i];
4196 rec = &fti->records[i].record;
4198 rec->flags = lrec->flags;
4199 rec->timestamp = lrec->time;
4200 rec->type = lrec->type;
4202 switch (lrec->type) {
4203 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4204 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4205 tln = &lrec->forest_trust_data.top_level_name;
4206 rec->data.name.string =
4207 talloc_strdup(mem_ctx, tln->string);
4208 if (!rec->data.name.string) {
4209 return NT_STATUS_NO_MEMORY;
4211 rec->data.name.size = strlen(rec->data.name.string);
4212 break;
4213 case LSA_FOREST_TRUST_DOMAIN_INFO:
4214 info = &lrec->forest_trust_data.domain_info;
4215 rec->data.info.sid = *info->domain_sid;
4216 rec->data.info.dns_name.string =
4217 talloc_strdup(mem_ctx,
4218 info->dns_domain_name.string);
4219 if (!rec->data.info.dns_name.string) {
4220 return NT_STATUS_NO_MEMORY;
4222 rec->data.info.dns_name.size =
4223 strlen(rec->data.info.dns_name.string);
4224 rec->data.info.netbios_name.string =
4225 talloc_strdup(mem_ctx,
4226 info->netbios_domain_name.string);
4227 if (!rec->data.info.netbios_name.string) {
4228 return NT_STATUS_NO_MEMORY;
4230 rec->data.info.netbios_name.size =
4231 strlen(rec->data.info.netbios_name.string);
4232 break;
4233 default:
4234 return NT_STATUS_INVALID_DOMAIN_STATE;
4238 return NT_STATUS_OK;
4241 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4242 uint32_t idx, uint32_t collision_type,
4243 uint32_t conflict_type, const char *tdo_name);
4245 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4246 const char *tdo_name,
4247 struct ForestTrustInfo *tdo_fti,
4248 struct ForestTrustInfo *new_fti,
4249 struct lsa_ForestTrustCollisionInfo *c_info)
4251 struct ForestTrustInfoRecord *nrec;
4252 struct ForestTrustInfoRecord *trec;
4253 const char *dns_name;
4254 const char *nb_name;
4255 struct dom_sid *sid = NULL;
4256 const char *tname = NULL;
4257 size_t dns_len;
4258 size_t tlen = 0;
4259 NTSTATUS nt_status = NT_STATUS_OK;
4260 uint32_t new_fti_idx;
4261 uint32_t i;
4262 /* use always TDO type, until we understand when Xref can be used */
4263 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4264 bool tln_conflict;
4265 bool sid_conflict;
4266 bool nb_conflict;
4267 bool exclusion;
4268 bool ex_rule = false;
4269 int ret;
4271 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4273 nrec = &new_fti->records[new_fti_idx].record;
4274 dns_name = NULL;
4275 nb_name = NULL;
4276 tln_conflict = false;
4277 sid_conflict = false;
4278 nb_conflict = false;
4279 exclusion = false;
4281 switch (nrec->type) {
4282 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4283 /* exclusions do not conflict by definition */
4284 break;
4286 case FOREST_TRUST_TOP_LEVEL_NAME:
4287 dns_name = nrec->data.name.string;
4288 dns_len = nrec->data.name.size;
4289 break;
4291 case LSA_FOREST_TRUST_DOMAIN_INFO:
4292 dns_name = nrec->data.info.dns_name.string;
4293 dns_len = nrec->data.info.dns_name.size;
4294 nb_name = nrec->data.info.netbios_name.string;
4295 sid = &nrec->data.info.sid;
4296 break;
4299 if (!dns_name) continue;
4301 /* check if this is already taken and not excluded */
4302 for (i = 0; i < tdo_fti->count; i++) {
4303 trec = &tdo_fti->records[i].record;
4305 switch (trec->type) {
4306 case FOREST_TRUST_TOP_LEVEL_NAME:
4307 ex_rule = false;
4308 tname = trec->data.name.string;
4309 tlen = trec->data.name.size;
4310 break;
4311 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4312 ex_rule = true;
4313 tname = trec->data.name.string;
4314 tlen = trec->data.name.size;
4315 break;
4316 case FOREST_TRUST_DOMAIN_INFO:
4317 ex_rule = false;
4318 tname = trec->data.info.dns_name.string;
4319 tlen = trec->data.info.dns_name.size;
4321 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4322 switch (ret) {
4323 case DNS_CMP_MATCH:
4324 /* if it matches exclusion,
4325 * it doesn't conflict */
4326 if (ex_rule) {
4327 exclusion = true;
4328 break;
4330 /* fall through */
4331 case DNS_CMP_FIRST_IS_CHILD:
4332 case DNS_CMP_SECOND_IS_CHILD:
4333 tln_conflict = true;
4334 /* fall through */
4335 default:
4336 break;
4339 /* explicit exclusion, no dns name conflict here */
4340 if (exclusion) {
4341 tln_conflict = false;
4344 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4345 continue;
4348 /* also test for domain info */
4349 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4350 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4351 sid_conflict = true;
4353 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4354 (nb_name != NULL) &&
4355 strcasecmp_m(trec->data.info.netbios_name.string,
4356 nb_name) == 0) {
4357 nb_conflict = true;
4361 if (tln_conflict) {
4362 nt_status = add_collision(c_info, new_fti_idx,
4363 collision_type,
4364 LSA_TLN_DISABLED_CONFLICT,
4365 tdo_name);
4366 if (!NT_STATUS_IS_OK(nt_status)) {
4367 goto done;
4370 if (sid_conflict) {
4371 nt_status = add_collision(c_info, new_fti_idx,
4372 collision_type,
4373 LSA_SID_DISABLED_CONFLICT,
4374 tdo_name);
4375 if (!NT_STATUS_IS_OK(nt_status)) {
4376 goto done;
4379 if (nb_conflict) {
4380 nt_status = add_collision(c_info, new_fti_idx,
4381 collision_type,
4382 LSA_NB_DISABLED_CONFLICT,
4383 tdo_name);
4384 if (!NT_STATUS_IS_OK(nt_status)) {
4385 goto done;
4390 done:
4391 return nt_status;
4394 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4395 uint32_t idx, uint32_t collision_type,
4396 uint32_t conflict_type, const char *tdo_name)
4398 struct lsa_ForestTrustCollisionRecord **es;
4399 uint32_t i = c_info->count;
4401 es = talloc_realloc(c_info, c_info->entries,
4402 struct lsa_ForestTrustCollisionRecord *, i + 1);
4403 if (!es) {
4404 return NT_STATUS_NO_MEMORY;
4406 c_info->entries = es;
4407 c_info->count = i + 1;
4409 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4410 if (!es[i]) {
4411 return NT_STATUS_NO_MEMORY;
4414 es[i]->index = idx;
4415 es[i]->type = collision_type;
4416 es[i]->flags = conflict_type;
4417 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4418 if (!es[i]->name.string) {
4419 return NT_STATUS_NO_MEMORY;
4421 es[i]->name.size = strlen(es[i]->name.string);
4423 return NT_STATUS_OK;
4427 lsa_lsaRSetForestTrustInformation
4429 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4430 TALLOC_CTX *mem_ctx,
4431 struct lsa_lsaRSetForestTrustInformation *r)
4433 struct dcesrv_handle *h;
4434 struct lsa_policy_state *p_state;
4435 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4436 "msDS-TrustForestTrustInfo", NULL };
4437 struct ldb_message **dom_res = NULL;
4438 struct ldb_dn *tdo_dn;
4439 struct ldb_message *msg;
4440 int num_res, i;
4441 const char *td_name;
4442 uint32_t trust_attributes;
4443 struct lsa_ForestTrustCollisionInfo *c_info;
4444 struct ForestTrustInfo *nfti;
4445 struct ForestTrustInfo *fti;
4446 DATA_BLOB ft_blob;
4447 enum ndr_err_code ndr_err;
4448 NTSTATUS nt_status;
4449 bool am_rodc;
4450 int ret;
4452 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4454 p_state = h->data;
4456 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4457 return NT_STATUS_INVALID_DOMAIN_STATE;
4460 /* abort if we are not a PDC */
4461 if (!samdb_is_pdc(p_state->sam_ldb)) {
4462 return NT_STATUS_INVALID_DOMAIN_ROLE;
4465 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4466 if (ret == LDB_SUCCESS && am_rodc) {
4467 return NT_STATUS_NO_SUCH_DOMAIN;
4470 /* check caller has TRUSTED_SET_AUTH */
4472 /* fetch all trusted domain objects */
4473 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4474 p_state->system_dn,
4475 &dom_res, trust_attrs,
4476 "(objectclass=trustedDomain)");
4477 if (num_res == 0) {
4478 return NT_STATUS_NO_SUCH_DOMAIN;
4481 for (i = 0; i < num_res; i++) {
4482 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4483 "trustPartner", NULL);
4484 if (!td_name) {
4485 return NT_STATUS_INVALID_DOMAIN_STATE;
4487 if (strcasecmp_m(td_name,
4488 r->in.trusted_domain_name->string) == 0) {
4489 break;
4492 if (i >= num_res) {
4493 return NT_STATUS_NO_SUCH_DOMAIN;
4496 tdo_dn = dom_res[i]->dn;
4498 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4499 "trustAttributes", 0);
4500 if (!(trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4501 return NT_STATUS_INVALID_PARAMETER;
4504 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4505 return NT_STATUS_INVALID_PARAMETER;
4508 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4509 if (!nfti) {
4510 return NT_STATUS_NO_MEMORY;
4513 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4514 if (!NT_STATUS_IS_OK(nt_status)) {
4515 return nt_status;
4518 c_info = talloc_zero(r->out.collision_info,
4519 struct lsa_ForestTrustCollisionInfo);
4520 if (!c_info) {
4521 return NT_STATUS_NO_MEMORY;
4524 /* first check own info, then other domains */
4525 fti = talloc(mem_ctx, struct ForestTrustInfo);
4526 if (!fti) {
4527 return NT_STATUS_NO_MEMORY;
4530 nt_status = own_ft_info(p_state, fti);
4531 if (!NT_STATUS_IS_OK(nt_status)) {
4532 return nt_status;
4535 nt_status = check_ft_info(c_info, p_state->domain_dns,
4536 fti, nfti, c_info);
4537 if (!NT_STATUS_IS_OK(nt_status)) {
4538 return nt_status;
4541 for (i = 0; i < num_res; i++) {
4542 fti = talloc(mem_ctx, struct ForestTrustInfo);
4543 if (!fti) {
4544 return NT_STATUS_NO_MEMORY;
4547 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4548 if (!NT_STATUS_IS_OK(nt_status)) {
4549 if (NT_STATUS_EQUAL(nt_status,
4550 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4551 continue;
4553 return nt_status;
4556 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4557 "trustPartner", NULL);
4558 if (!td_name) {
4559 return NT_STATUS_INVALID_DOMAIN_STATE;
4562 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4563 if (!NT_STATUS_IS_OK(nt_status)) {
4564 return nt_status;
4568 if (c_info->count != 0) {
4569 *r->out.collision_info = c_info;
4572 if (r->in.check_only != 0) {
4573 return NT_STATUS_OK;
4576 /* not just a check, write info back */
4578 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4579 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4580 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4581 return NT_STATUS_INVALID_PARAMETER;
4584 msg = ldb_msg_new(mem_ctx);
4585 if (msg == NULL) {
4586 return NT_STATUS_NO_MEMORY;
4589 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4590 if (!msg->dn) {
4591 return NT_STATUS_NO_MEMORY;
4594 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4595 LDB_FLAG_MOD_REPLACE, NULL);
4596 if (ret != LDB_SUCCESS) {
4597 return NT_STATUS_NO_MEMORY;
4599 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4600 &ft_blob, NULL);
4601 if (ret != LDB_SUCCESS) {
4602 return NT_STATUS_NO_MEMORY;
4605 ret = ldb_modify(p_state->sam_ldb, msg);
4606 if (ret != LDB_SUCCESS) {
4607 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4608 ldb_errstring(p_state->sam_ldb)));
4610 switch (ret) {
4611 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4612 return NT_STATUS_ACCESS_DENIED;
4613 default:
4614 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4618 return NT_STATUS_OK;
4622 lsa_CREDRRENAME
4624 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4625 struct lsa_CREDRRENAME *r)
4627 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4633 lsa_LSAROPENPOLICYSCE
4635 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4636 struct lsa_LSAROPENPOLICYSCE *r)
4638 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4643 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4645 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4646 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4648 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4653 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4655 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4656 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4658 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4663 lsa_LSARADTREPORTSECURITYEVENT
4665 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4666 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4668 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4672 /* include the generated boilerplate */
4673 #include "librpc/gen_ndr/ndr_lsa_s.c"
4677 /*****************************************
4678 NOTE! The remaining calls below were
4679 removed in w2k3, so the DCESRV_FAULT()
4680 replies are the correct implementation. Do
4681 not try and fill these in with anything else
4682 ******************************************/
4685 dssetup_DsRoleDnsNameToFlatName
4687 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4688 struct dssetup_DsRoleDnsNameToFlatName *r)
4690 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4695 dssetup_DsRoleDcAsDc
4697 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4698 struct dssetup_DsRoleDcAsDc *r)
4700 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4705 dssetup_DsRoleDcAsReplica
4707 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4708 struct dssetup_DsRoleDcAsReplica *r)
4710 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4715 dssetup_DsRoleDemoteDc
4717 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4718 struct dssetup_DsRoleDemoteDc *r)
4720 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4725 dssetup_DsRoleGetDcOperationProgress
4727 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4728 struct dssetup_DsRoleGetDcOperationProgress *r)
4730 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4735 dssetup_DsRoleGetDcOperationResults
4737 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4738 struct dssetup_DsRoleGetDcOperationResults *r)
4740 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4745 dssetup_DsRoleCancel
4747 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4748 struct dssetup_DsRoleCancel *r)
4750 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4755 dssetup_DsRoleServerSaveStateForUpgrade
4757 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4758 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4760 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4765 dssetup_DsRoleUpgradeDownlevelServer
4767 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4768 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4770 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4775 dssetup_DsRoleAbortDownlevelServerUpgrade
4777 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4778 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4780 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4784 /* include the generated boilerplate */
4785 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4787 NTSTATUS dcerpc_server_lsa_init(void)
4789 NTSTATUS ret;
4791 ret = dcerpc_server_dssetup_init();
4792 if (!NT_STATUS_IS_OK(ret)) {
4793 return ret;
4795 ret = dcerpc_server_lsarpc_init();
4796 if (!NT_STATUS_IS_OK(ret)) {
4797 return ret;
4799 return ret;