s4:rpc_server: make use of dcerpc_binding_get_transport()
[Samba.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
bloba7fc1862c53323168486928d9a1a315539aa4dc5
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 NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
89 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
90 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid, tmp_ctx);
92 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
93 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid_str, tmp_ctx);
95 sidstr = dom_sid_string(tmp_ctx, sid);
96 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, tmp_ctx);
98 *sd = security_descriptor_dacl_create(mem_ctx,
99 0, sidstr, NULL,
101 SID_WORLD,
102 SEC_ACE_TYPE_ACCESS_ALLOWED,
103 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
105 SID_BUILTIN_ADMINISTRATORS,
106 SEC_ACE_TYPE_ACCESS_ALLOWED,
107 SEC_GENERIC_ALL, 0,
109 SID_BUILTIN_ACCOUNT_OPERATORS,
110 SEC_ACE_TYPE_ACCESS_ALLOWED,
111 SEC_GENERIC_ALL, 0,
113 domain_admins_sid_str,
114 SEC_ACE_TYPE_ACCESS_ALLOWED,
115 SEC_GENERIC_ALL, 0,
117 sidstr,
118 SEC_ACE_TYPE_ACCESS_ALLOWED,
119 sid_access, 0,
121 NULL);
122 talloc_free(tmp_ctx);
124 NT_STATUS_HAVE_NO_MEMORY(*sd);
126 return NT_STATUS_OK;
130 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
131 TALLOC_CTX *mem_ctx,
132 struct lsa_EnumAccountRights *r);
134 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
135 TALLOC_CTX *mem_ctx,
136 struct lsa_policy_state *state,
137 int ldb_flag,
138 struct dom_sid *sid,
139 const struct lsa_RightSet *rights);
142 lsa_Close
144 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
145 struct lsa_Close *r)
147 enum dcerpc_transport_t transport =
148 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
149 struct dcesrv_handle *h;
151 if (transport != NCACN_NP && transport != NCALRPC) {
152 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
155 *r->out.handle = *r->in.handle;
157 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
159 talloc_free(h);
161 ZERO_STRUCTP(r->out.handle);
163 return NT_STATUS_OK;
168 lsa_Delete
170 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
171 struct lsa_Delete *r)
173 return NT_STATUS_NOT_SUPPORTED;
178 lsa_DeleteObject
180 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
181 struct lsa_DeleteObject *r)
183 struct dcesrv_handle *h;
184 int ret;
186 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
188 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
189 struct lsa_secret_state *secret_state = h->data;
191 /* Ensure user is permitted to delete this... */
192 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
194 case SECURITY_SYSTEM:
195 case SECURITY_ADMINISTRATOR:
196 break;
197 default:
198 /* Users and anonymous are not allowed to delete things */
199 return NT_STATUS_ACCESS_DENIED;
202 ret = ldb_delete(secret_state->sam_ldb,
203 secret_state->secret_dn);
204 if (ret != LDB_SUCCESS) {
205 return NT_STATUS_INVALID_HANDLE;
208 ZERO_STRUCTP(r->out.handle);
210 return NT_STATUS_OK;
212 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
213 struct lsa_trusted_domain_state *trusted_domain_state =
214 talloc_get_type(h->data, struct lsa_trusted_domain_state);
215 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
216 if (ret != LDB_SUCCESS) {
217 return NT_STATUS_INTERNAL_DB_CORRUPTION;
220 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
221 trusted_domain_state->trusted_domain_dn);
222 if (ret != LDB_SUCCESS) {
223 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
224 return NT_STATUS_INVALID_HANDLE;
227 if (trusted_domain_state->trusted_domain_user_dn) {
228 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
229 trusted_domain_state->trusted_domain_user_dn);
230 if (ret != LDB_SUCCESS) {
231 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
232 return NT_STATUS_INVALID_HANDLE;
236 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
237 if (ret != LDB_SUCCESS) {
238 return NT_STATUS_INTERNAL_DB_CORRUPTION;
241 ZERO_STRUCTP(r->out.handle);
243 return NT_STATUS_OK;
245 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
246 struct lsa_RightSet *rights;
247 struct lsa_account_state *astate;
248 struct lsa_EnumAccountRights r2;
249 NTSTATUS status;
251 rights = talloc(mem_ctx, struct lsa_RightSet);
253 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
255 astate = h->data;
257 r2.in.handle = &astate->policy->handle->wire_handle;
258 r2.in.sid = astate->account_sid;
259 r2.out.rights = rights;
261 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
262 but we have a LSA_HANDLE_ACCOUNT here, so this call
263 will always fail */
264 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
265 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
266 return NT_STATUS_OK;
269 if (!NT_STATUS_IS_OK(status)) {
270 return status;
273 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
274 LDB_FLAG_MOD_DELETE, astate->account_sid,
275 r2.out.rights);
276 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
277 return NT_STATUS_OK;
280 if (!NT_STATUS_IS_OK(status)) {
281 return status;
284 ZERO_STRUCTP(r->out.handle);
286 return NT_STATUS_OK;
289 return NT_STATUS_INVALID_HANDLE;
294 lsa_EnumPrivs
296 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
297 struct lsa_EnumPrivs *r)
299 struct dcesrv_handle *h;
300 uint32_t i;
301 enum sec_privilege priv;
302 const char *privname;
304 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
306 i = *r->in.resume_handle;
308 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
309 r->out.privs->count < r->in.max_count) {
310 struct lsa_PrivEntry *e;
311 privname = sec_privilege_name(priv);
312 r->out.privs->privs = talloc_realloc(r->out.privs,
313 r->out.privs->privs,
314 struct lsa_PrivEntry,
315 r->out.privs->count+1);
316 if (r->out.privs->privs == NULL) {
317 return NT_STATUS_NO_MEMORY;
319 e = &r->out.privs->privs[r->out.privs->count];
320 e->luid.low = priv;
321 e->luid.high = 0;
322 e->name.string = privname;
323 r->out.privs->count++;
324 i++;
327 *r->out.resume_handle = i;
329 return NT_STATUS_OK;
334 lsa_QuerySecObj
336 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
337 struct lsa_QuerySecurity *r)
339 struct dcesrv_handle *h;
340 struct security_descriptor *sd;
341 NTSTATUS status;
342 struct dom_sid *sid;
344 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
346 sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
348 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
349 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
350 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
351 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid,
352 LSA_ACCOUNT_ALL_ACCESS);
353 } else {
354 return NT_STATUS_INVALID_HANDLE;
356 NT_STATUS_NOT_OK_RETURN(status);
358 (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
359 NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
361 (*r->out.sdbuf)->sd = sd;
363 return NT_STATUS_OK;
368 lsa_SetSecObj
370 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
371 struct lsa_SetSecObj *r)
373 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
378 lsa_ChangePassword
380 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
381 struct lsa_ChangePassword *r)
383 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
387 dssetup_DsRoleGetPrimaryDomainInformation
389 This is not an LSA call, but is the only call left on the DSSETUP
390 pipe (after the pipe was truncated), and needs lsa_get_policy_state
392 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
393 TALLOC_CTX *mem_ctx,
394 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
396 union dssetup_DsRoleInfo *info;
398 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
399 W_ERROR_HAVE_NO_MEMORY(info);
401 switch (r->in.level) {
402 case DS_ROLE_BASIC_INFORMATION:
404 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
405 uint32_t flags = 0;
406 const char *domain = NULL;
407 const char *dns_domain = NULL;
408 const char *forest = NULL;
409 struct GUID domain_guid;
410 struct lsa_policy_state *state;
412 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
413 if (!NT_STATUS_IS_OK(status)) {
414 return ntstatus_to_werror(status);
417 ZERO_STRUCT(domain_guid);
419 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
420 case ROLE_STANDALONE:
421 role = DS_ROLE_STANDALONE_SERVER;
422 break;
423 case ROLE_DOMAIN_MEMBER:
424 role = DS_ROLE_MEMBER_SERVER;
425 break;
426 case ROLE_ACTIVE_DIRECTORY_DC:
427 if (samdb_is_pdc(state->sam_ldb)) {
428 role = DS_ROLE_PRIMARY_DC;
429 } else {
430 role = DS_ROLE_BACKUP_DC;
432 break;
435 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
436 case ROLE_STANDALONE:
437 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
438 W_ERROR_HAVE_NO_MEMORY(domain);
439 break;
440 case ROLE_DOMAIN_MEMBER:
441 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
442 W_ERROR_HAVE_NO_MEMORY(domain);
443 /* TODO: what is with dns_domain and forest and guid? */
444 break;
445 case ROLE_ACTIVE_DIRECTORY_DC:
446 flags = DS_ROLE_PRIMARY_DS_RUNNING;
448 if (state->mixed_domain == 1) {
449 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
452 domain = state->domain_name;
453 dns_domain = state->domain_dns;
454 forest = state->forest_dns;
456 domain_guid = state->domain_guid;
457 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
458 break;
461 info->basic.role = role;
462 info->basic.flags = flags;
463 info->basic.domain = domain;
464 info->basic.dns_domain = dns_domain;
465 info->basic.forest = forest;
466 info->basic.domain_guid = domain_guid;
468 r->out.info = info;
469 return WERR_OK;
471 case DS_ROLE_UPGRADE_STATUS:
473 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
474 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
476 r->out.info = info;
477 return WERR_OK;
479 case DS_ROLE_OP_STATUS:
481 info->opstatus.status = DS_ROLE_OP_IDLE;
483 r->out.info = info;
484 return WERR_OK;
486 default:
487 return WERR_INVALID_PARAM;
492 fill in the AccountDomain info
494 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
495 struct lsa_DomainInfo *info)
497 info->name.string = state->domain_name;
498 info->sid = state->domain_sid;
500 return NT_STATUS_OK;
504 fill in the DNS domain info
506 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
507 struct lsa_DnsDomainInfo *info)
509 info->name.string = state->domain_name;
510 info->sid = state->domain_sid;
511 info->dns_domain.string = state->domain_dns;
512 info->dns_forest.string = state->forest_dns;
513 info->domain_guid = state->domain_guid;
515 return NT_STATUS_OK;
519 lsa_QueryInfoPolicy2
521 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
522 struct lsa_QueryInfoPolicy2 *r)
524 struct lsa_policy_state *state;
525 struct dcesrv_handle *h;
526 union lsa_PolicyInformation *info;
528 *r->out.info = NULL;
530 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
532 state = h->data;
534 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
535 if (!info) {
536 return NT_STATUS_NO_MEMORY;
538 *r->out.info = info;
540 switch (r->in.level) {
541 case LSA_POLICY_INFO_AUDIT_LOG:
542 /* we don't need to fill in any of this */
543 ZERO_STRUCT(info->audit_log);
544 return NT_STATUS_OK;
545 case LSA_POLICY_INFO_AUDIT_EVENTS:
546 /* we don't need to fill in any of this */
547 ZERO_STRUCT(info->audit_events);
548 return NT_STATUS_OK;
549 case LSA_POLICY_INFO_PD:
550 /* we don't need to fill in any of this */
551 ZERO_STRUCT(info->pd);
552 return NT_STATUS_OK;
554 case LSA_POLICY_INFO_DOMAIN:
555 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
556 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
557 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
558 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
559 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
561 case LSA_POLICY_INFO_ROLE:
562 info->role.role = LSA_ROLE_PRIMARY;
563 return NT_STATUS_OK;
565 case LSA_POLICY_INFO_DNS:
566 case LSA_POLICY_INFO_DNS_INT:
567 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
569 case LSA_POLICY_INFO_REPLICA:
570 ZERO_STRUCT(info->replica);
571 return NT_STATUS_OK;
573 case LSA_POLICY_INFO_QUOTA:
574 ZERO_STRUCT(info->quota);
575 return NT_STATUS_OK;
577 case LSA_POLICY_INFO_MOD:
578 case LSA_POLICY_INFO_AUDIT_FULL_SET:
579 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
580 /* windows gives INVALID_PARAMETER */
581 *r->out.info = NULL;
582 return NT_STATUS_INVALID_PARAMETER;
585 *r->out.info = NULL;
586 return NT_STATUS_INVALID_INFO_CLASS;
590 lsa_QueryInfoPolicy
592 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
593 struct lsa_QueryInfoPolicy *r)
595 struct lsa_QueryInfoPolicy2 r2;
596 NTSTATUS status;
598 ZERO_STRUCT(r2);
600 r2.in.handle = r->in.handle;
601 r2.in.level = r->in.level;
602 r2.out.info = r->out.info;
604 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
606 return status;
610 lsa_SetInfoPolicy
612 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
613 struct lsa_SetInfoPolicy *r)
615 /* need to support this */
616 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
621 lsa_ClearAuditLog
623 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
624 struct lsa_ClearAuditLog *r)
626 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
631 lsa_CreateAccount
633 This call does not seem to have any long-term effects, hence no database operations
635 we need to talk to the MS product group to find out what this account database means!
637 answer is that the lsa database is totally separate from the SAM and
638 ldap databases. We are going to need a separate ldb to store these
639 accounts. The SIDs on this account bear no relation to the SIDs in
642 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
643 struct lsa_CreateAccount *r)
645 struct lsa_account_state *astate;
647 struct lsa_policy_state *state;
648 struct dcesrv_handle *h, *ah;
650 ZERO_STRUCTP(r->out.acct_handle);
652 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
654 state = h->data;
656 astate = talloc(dce_call->conn, struct lsa_account_state);
657 if (astate == NULL) {
658 return NT_STATUS_NO_MEMORY;
661 astate->account_sid = dom_sid_dup(astate, r->in.sid);
662 if (astate->account_sid == NULL) {
663 talloc_free(astate);
664 return NT_STATUS_NO_MEMORY;
667 astate->policy = talloc_reference(astate, state);
668 astate->access_mask = r->in.access_mask;
670 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
671 if (!ah) {
672 talloc_free(astate);
673 return NT_STATUS_NO_MEMORY;
676 ah->data = talloc_steal(ah, astate);
678 *r->out.acct_handle = ah->wire_handle;
680 return NT_STATUS_OK;
685 lsa_EnumAccounts
687 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
688 struct lsa_EnumAccounts *r)
690 struct dcesrv_handle *h;
691 struct lsa_policy_state *state;
692 int ret;
693 struct ldb_message **res;
694 const char * const attrs[] = { "objectSid", NULL};
695 uint32_t count, i;
697 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
699 state = h->data;
701 /* NOTE: This call must only return accounts that have at least
702 one privilege set
704 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
705 "(&(objectSid=*)(privilege=*))");
706 if (ret < 0) {
707 return NT_STATUS_INTERNAL_DB_CORRUPTION;
710 if (*r->in.resume_handle >= ret) {
711 return NT_STATUS_NO_MORE_ENTRIES;
714 count = ret - *r->in.resume_handle;
715 if (count > r->in.num_entries) {
716 count = r->in.num_entries;
719 if (count == 0) {
720 return NT_STATUS_NO_MORE_ENTRIES;
723 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
724 if (r->out.sids->sids == NULL) {
725 return NT_STATUS_NO_MEMORY;
728 for (i=0;i<count;i++) {
729 r->out.sids->sids[i].sid =
730 samdb_result_dom_sid(r->out.sids->sids,
731 res[i + *r->in.resume_handle],
732 "objectSid");
733 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
736 r->out.sids->num_sids = count;
737 *r->out.resume_handle = count + *r->in.resume_handle;
739 return NT_STATUS_OK;
742 /* This decrypts and returns Trusted Domain Auth Information Internal data */
743 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
744 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
745 struct trustDomainPasswords *auth_struct)
747 DATA_BLOB session_key = data_blob(NULL, 0);
748 enum ndr_err_code ndr_err;
749 NTSTATUS nt_status;
751 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
752 if (!NT_STATUS_IS_OK(nt_status)) {
753 return nt_status;
756 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
757 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
758 auth_struct,
759 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
760 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
761 return NT_STATUS_INVALID_PARAMETER;
764 return NT_STATUS_OK;
767 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
768 TALLOC_CTX *mem_ctx,
769 struct trustAuthInOutBlob *iopw,
770 DATA_BLOB *trustauth_blob)
772 enum ndr_err_code ndr_err;
774 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
775 iopw,
776 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
777 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
778 return NT_STATUS_INVALID_PARAMETER;
781 return NT_STATUS_OK;
784 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
785 struct ldb_context *sam_ldb,
786 struct ldb_dn *base_dn,
787 const char *netbios_name,
788 struct trustAuthInOutBlob *in,
789 struct ldb_dn **user_dn)
791 struct ldb_message *msg;
792 struct ldb_dn *dn;
793 uint32_t i;
794 int ret;
796 dn = ldb_dn_copy(mem_ctx, base_dn);
797 if (!dn) {
798 return NT_STATUS_NO_MEMORY;
800 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
801 return NT_STATUS_NO_MEMORY;
804 msg = ldb_msg_new(mem_ctx);
805 if (!msg) {
806 return NT_STATUS_NO_MEMORY;
808 msg->dn = dn;
810 ret = ldb_msg_add_string(msg, "objectClass", "user");
811 if (ret != LDB_SUCCESS) {
812 return NT_STATUS_NO_MEMORY;
815 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
816 if (ret != LDB_SUCCESS) {
817 return NT_STATUS_NO_MEMORY;
820 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
821 UF_INTERDOMAIN_TRUST_ACCOUNT);
822 if (ret != LDB_SUCCESS) {
823 return NT_STATUS_NO_MEMORY;
826 for (i = 0; i < in->count; i++) {
827 const char *attribute;
828 struct ldb_val v;
829 switch (in->current.array[i].AuthType) {
830 case TRUST_AUTH_TYPE_NT4OWF:
831 attribute = "unicodePwd";
832 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
833 v.length = 16;
834 break;
835 case TRUST_AUTH_TYPE_CLEAR:
836 attribute = "clearTextPassword";
837 v.data = in->current.array[i].AuthInfo.clear.password;
838 v.length = in->current.array[i].AuthInfo.clear.size;
839 break;
840 default:
841 continue;
844 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
845 if (ret != LDB_SUCCESS) {
846 return NT_STATUS_NO_MEMORY;
850 /* create the trusted_domain user account */
851 ret = ldb_add(sam_ldb, msg);
852 if (ret != LDB_SUCCESS) {
853 DEBUG(0,("Failed to create user record %s: %s\n",
854 ldb_dn_get_linearized(msg->dn),
855 ldb_errstring(sam_ldb)));
857 switch (ret) {
858 case LDB_ERR_ENTRY_ALREADY_EXISTS:
859 return NT_STATUS_DOMAIN_EXISTS;
860 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
861 return NT_STATUS_ACCESS_DENIED;
862 default:
863 return NT_STATUS_INTERNAL_DB_CORRUPTION;
867 if (user_dn) {
868 *user_dn = dn;
870 return NT_STATUS_OK;
874 lsa_CreateTrustedDomainEx2
876 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
877 TALLOC_CTX *mem_ctx,
878 struct lsa_CreateTrustedDomainEx2 *r,
879 int op,
880 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
882 struct dcesrv_handle *policy_handle;
883 struct lsa_policy_state *policy_state;
884 struct lsa_trusted_domain_state *trusted_domain_state;
885 struct dcesrv_handle *handle;
886 struct ldb_message **msgs, *msg;
887 const char *attrs[] = {
888 NULL
890 const char *netbios_name;
891 const char *dns_name;
892 const char *name;
893 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
894 struct trustDomainPasswords auth_struct;
895 int ret;
896 NTSTATUS nt_status;
897 struct ldb_context *sam_ldb;
899 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
900 ZERO_STRUCTP(r->out.trustdom_handle);
902 policy_state = policy_handle->data;
903 sam_ldb = policy_state->sam_ldb;
905 netbios_name = r->in.info->netbios_name.string;
906 if (!netbios_name) {
907 return NT_STATUS_INVALID_PARAMETER;
910 dns_name = r->in.info->domain_name.string;
912 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
913 if (!trusted_domain_state) {
914 return NT_STATUS_NO_MEMORY;
916 trusted_domain_state->policy = policy_state;
918 if (strcasecmp(netbios_name, "BUILTIN") == 0
919 || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
920 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
921 return NT_STATUS_INVALID_PARAMETER;
924 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
925 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
926 || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
927 || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
928 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
929 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
932 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
933 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
934 /* No secrets are created at this time, for this function */
935 auth_struct.outgoing.count = 0;
936 auth_struct.incoming.count = 0;
937 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
938 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
939 r->in.auth_info_internal->auth_blob.size);
940 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
941 &auth_blob, &auth_struct);
942 if (!NT_STATUS_IS_OK(nt_status)) {
943 return nt_status;
945 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
947 if (unencrypted_auth_info->incoming_count > 1) {
948 return NT_STATUS_INVALID_PARAMETER;
951 /* more investigation required here, do not create secrets for
952 * now */
953 auth_struct.outgoing.count = 0;
954 auth_struct.incoming.count = 0;
955 } else {
956 return NT_STATUS_INVALID_PARAMETER;
959 if (auth_struct.incoming.count) {
960 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
961 &auth_struct.incoming,
962 &trustAuthIncoming);
963 if (!NT_STATUS_IS_OK(nt_status)) {
964 return nt_status;
966 } else {
967 trustAuthIncoming = data_blob(NULL, 0);
970 if (auth_struct.outgoing.count) {
971 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
972 &auth_struct.outgoing,
973 &trustAuthOutgoing);
974 if (!NT_STATUS_IS_OK(nt_status)) {
975 return nt_status;
977 } else {
978 trustAuthOutgoing = data_blob(NULL, 0);
981 ret = ldb_transaction_start(sam_ldb);
982 if (ret != LDB_SUCCESS) {
983 return NT_STATUS_INTERNAL_DB_CORRUPTION;
986 if (dns_name) {
987 char *dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
988 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
989 /* search for the trusted_domain record */
990 ret = gendb_search(sam_ldb,
991 mem_ctx, policy_state->system_dn, &msgs, attrs,
992 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
993 dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
994 if (ret > 0) {
995 ldb_transaction_cancel(sam_ldb);
996 return NT_STATUS_OBJECT_NAME_COLLISION;
998 } else {
999 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1000 /* search for the trusted_domain record */
1001 ret = gendb_search(sam_ldb,
1002 mem_ctx, policy_state->system_dn, &msgs, attrs,
1003 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1004 netbios_encoded, netbios_encoded, netbios_encoded);
1005 if (ret > 0) {
1006 ldb_transaction_cancel(sam_ldb);
1007 return NT_STATUS_OBJECT_NAME_COLLISION;
1011 if (ret < 0 ) {
1012 ldb_transaction_cancel(sam_ldb);
1013 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1016 name = dns_name ? dns_name : netbios_name;
1018 msg = ldb_msg_new(mem_ctx);
1019 if (msg == NULL) {
1020 return NT_STATUS_NO_MEMORY;
1023 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1024 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1025 ldb_transaction_cancel(sam_ldb);
1026 return NT_STATUS_NO_MEMORY;
1029 ldb_msg_add_string(msg, "flatname", netbios_name);
1031 if (r->in.info->sid) {
1032 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1033 if (ret != LDB_SUCCESS) {
1034 ldb_transaction_cancel(sam_ldb);
1035 return NT_STATUS_INVALID_PARAMETER;
1039 ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1041 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1043 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1045 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1047 if (dns_name) {
1048 ldb_msg_add_string(msg, "trustPartner", dns_name);
1051 if (trustAuthIncoming.data) {
1052 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1053 if (ret != LDB_SUCCESS) {
1054 ldb_transaction_cancel(sam_ldb);
1055 return NT_STATUS_NO_MEMORY;
1058 if (trustAuthOutgoing.data) {
1059 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1060 if (ret != LDB_SUCCESS) {
1061 ldb_transaction_cancel(sam_ldb);
1062 return NT_STATUS_NO_MEMORY;
1066 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1068 /* create the trusted_domain */
1069 ret = ldb_add(sam_ldb, msg);
1070 switch (ret) {
1071 case LDB_SUCCESS:
1072 break;
1073 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1074 ldb_transaction_cancel(sam_ldb);
1075 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1076 ldb_dn_get_linearized(msg->dn),
1077 ldb_errstring(sam_ldb)));
1078 return NT_STATUS_DOMAIN_EXISTS;
1079 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1080 ldb_transaction_cancel(sam_ldb);
1081 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1082 ldb_dn_get_linearized(msg->dn),
1083 ldb_errstring(sam_ldb)));
1084 return NT_STATUS_ACCESS_DENIED;
1085 default:
1086 ldb_transaction_cancel(sam_ldb);
1087 DEBUG(0,("Failed to create user record %s: %s\n",
1088 ldb_dn_get_linearized(msg->dn),
1089 ldb_errstring(sam_ldb)));
1090 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1093 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1094 struct ldb_dn *user_dn;
1095 /* Inbound trusts must also create a cn=users object to match */
1096 nt_status = add_trust_user(mem_ctx, sam_ldb,
1097 policy_state->domain_dn,
1098 netbios_name,
1099 &auth_struct.incoming,
1100 &user_dn);
1101 if (!NT_STATUS_IS_OK(nt_status)) {
1102 ldb_transaction_cancel(sam_ldb);
1103 return nt_status;
1106 /* save the trust user dn */
1107 trusted_domain_state->trusted_domain_user_dn
1108 = talloc_steal(trusted_domain_state, user_dn);
1111 ret = ldb_transaction_commit(sam_ldb);
1112 if (ret != LDB_SUCCESS) {
1113 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1116 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1117 if (!handle) {
1118 return NT_STATUS_NO_MEMORY;
1121 handle->data = talloc_steal(handle, trusted_domain_state);
1123 trusted_domain_state->access_mask = r->in.access_mask;
1124 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1126 *r->out.trustdom_handle = handle->wire_handle;
1128 return NT_STATUS_OK;
1132 lsa_CreateTrustedDomainEx2
1134 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1135 TALLOC_CTX *mem_ctx,
1136 struct lsa_CreateTrustedDomainEx2 *r)
1138 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1141 lsa_CreateTrustedDomainEx
1143 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1144 TALLOC_CTX *mem_ctx,
1145 struct lsa_CreateTrustedDomainEx *r)
1147 struct lsa_CreateTrustedDomainEx2 r2;
1149 r2.in.policy_handle = r->in.policy_handle;
1150 r2.in.info = r->in.info;
1151 r2.out.trustdom_handle = r->out.trustdom_handle;
1152 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1156 lsa_CreateTrustedDomain
1158 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1159 struct lsa_CreateTrustedDomain *r)
1161 struct lsa_CreateTrustedDomainEx2 r2;
1163 r2.in.policy_handle = r->in.policy_handle;
1164 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1165 if (!r2.in.info) {
1166 return NT_STATUS_NO_MEMORY;
1169 r2.in.info->domain_name.string = NULL;
1170 r2.in.info->netbios_name = r->in.info->name;
1171 r2.in.info->sid = r->in.info->sid;
1172 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1173 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1174 r2.in.info->trust_attributes = 0;
1176 r2.in.access_mask = r->in.access_mask;
1177 r2.out.trustdom_handle = r->out.trustdom_handle;
1179 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1183 lsa_OpenTrustedDomain
1185 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1186 struct lsa_OpenTrustedDomain *r)
1188 struct dcesrv_handle *policy_handle;
1190 struct lsa_policy_state *policy_state;
1191 struct lsa_trusted_domain_state *trusted_domain_state;
1192 struct dcesrv_handle *handle;
1193 struct ldb_message **msgs;
1194 const char *attrs[] = {
1195 "trustDirection",
1196 "flatname",
1197 NULL
1200 const char *sid_string;
1201 int ret;
1203 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1204 ZERO_STRUCTP(r->out.trustdom_handle);
1205 policy_state = policy_handle->data;
1207 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1208 if (!trusted_domain_state) {
1209 return NT_STATUS_NO_MEMORY;
1211 trusted_domain_state->policy = policy_state;
1213 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1214 if (!sid_string) {
1215 return NT_STATUS_NO_MEMORY;
1218 /* search for the trusted_domain record */
1219 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1220 mem_ctx, policy_state->system_dn, &msgs, attrs,
1221 "(&(securityIdentifier=%s)(objectclass=trustedDomain))",
1222 sid_string);
1223 if (ret == 0) {
1224 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1227 if (ret != 1) {
1228 DEBUG(0,("Found %d records matching DN %s\n", ret,
1229 ldb_dn_get_linearized(policy_state->system_dn)));
1230 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1233 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1235 trusted_domain_state->trusted_domain_user_dn = NULL;
1237 if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1238 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1239 /* search for the trusted_domain record */
1240 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1241 mem_ctx, policy_state->domain_dn, &msgs, attrs,
1242 "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%u))",
1243 flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1244 if (ret == 1) {
1245 trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1248 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1249 if (!handle) {
1250 return NT_STATUS_NO_MEMORY;
1253 handle->data = talloc_steal(handle, trusted_domain_state);
1255 trusted_domain_state->access_mask = r->in.access_mask;
1256 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1258 *r->out.trustdom_handle = handle->wire_handle;
1260 return NT_STATUS_OK;
1265 lsa_OpenTrustedDomainByName
1267 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1268 TALLOC_CTX *mem_ctx,
1269 struct lsa_OpenTrustedDomainByName *r)
1271 struct dcesrv_handle *policy_handle;
1273 struct lsa_policy_state *policy_state;
1274 struct lsa_trusted_domain_state *trusted_domain_state;
1275 struct dcesrv_handle *handle;
1276 struct ldb_message **msgs;
1277 const char *attrs[] = {
1278 NULL
1280 char *td_name;
1281 int ret;
1283 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1284 ZERO_STRUCTP(r->out.trustdom_handle);
1285 policy_state = policy_handle->data;
1287 if (!r->in.name.string) {
1288 return NT_STATUS_INVALID_PARAMETER;
1291 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1292 if (!trusted_domain_state) {
1293 return NT_STATUS_NO_MEMORY;
1295 trusted_domain_state->policy = policy_state;
1297 /* search for the trusted_domain record */
1298 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1299 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1300 mem_ctx, policy_state->system_dn, &msgs, attrs,
1301 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1302 "(objectclass=trustedDomain))",
1303 td_name, td_name, td_name);
1304 if (ret == 0) {
1305 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1308 if (ret != 1) {
1309 DEBUG(0,("Found %d records matching DN %s\n", ret,
1310 ldb_dn_get_linearized(policy_state->system_dn)));
1311 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1314 /* TODO: perform access checks */
1316 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1318 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1319 if (!handle) {
1320 return NT_STATUS_NO_MEMORY;
1323 handle->data = talloc_steal(handle, trusted_domain_state);
1325 trusted_domain_state->access_mask = r->in.access_mask;
1326 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1328 *r->out.trustdom_handle = handle->wire_handle;
1330 return NT_STATUS_OK;
1336 lsa_SetTrustedDomainInfo
1338 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1339 struct lsa_SetTrustedDomainInfo *r)
1341 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1346 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1347 * otherwise at least one must be provided */
1348 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1349 struct ldb_dn *basedn, const char *dns_domain,
1350 const char *netbios, struct dom_sid2 *sid,
1351 struct ldb_message ***msgs)
1353 const char *attrs[] = { "flatname", "trustPartner",
1354 "securityIdentifier", "trustDirection",
1355 "trustType", "trustAttributes",
1356 "trustPosixOffset",
1357 "msDs-supportedEncryptionTypes", NULL };
1358 char *dns = NULL;
1359 char *nbn = NULL;
1360 char *sidstr = NULL;
1361 char *filter;
1362 int ret;
1365 if (dns_domain || netbios || sid) {
1366 filter = talloc_strdup(mem_ctx,
1367 "(&(objectclass=trustedDomain)(|");
1368 } else {
1369 filter = talloc_strdup(mem_ctx,
1370 "(objectclass=trustedDomain)");
1372 if (!filter) {
1373 return NT_STATUS_NO_MEMORY;
1376 if (dns_domain) {
1377 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1378 if (!dns) {
1379 return NT_STATUS_NO_MEMORY;
1381 filter = talloc_asprintf_append(filter,
1382 "(trustPartner=%s)", dns);
1383 if (!filter) {
1384 return NT_STATUS_NO_MEMORY;
1387 if (netbios) {
1388 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1389 if (!nbn) {
1390 return NT_STATUS_NO_MEMORY;
1392 filter = talloc_asprintf_append(filter,
1393 "(flatname=%s)", nbn);
1394 if (!filter) {
1395 return NT_STATUS_NO_MEMORY;
1398 if (sid) {
1399 sidstr = dom_sid_string(mem_ctx, sid);
1400 if (!sidstr) {
1401 return NT_STATUS_INVALID_PARAMETER;
1403 filter = talloc_asprintf_append(filter,
1404 "(securityIdentifier=%s)",
1405 sidstr);
1406 if (!filter) {
1407 return NT_STATUS_NO_MEMORY;
1410 if (dns_domain || netbios || sid) {
1411 filter = talloc_asprintf_append(filter, "))");
1412 if (!filter) {
1413 return NT_STATUS_NO_MEMORY;
1417 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1418 if (ret == 0) {
1419 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1422 if (ret != 1) {
1423 return NT_STATUS_OBJECT_NAME_COLLISION;
1426 return NT_STATUS_OK;
1429 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1430 struct ldb_context *sam_ldb,
1431 struct ldb_message *orig,
1432 struct ldb_message *dest,
1433 const char *attribute,
1434 uint32_t value,
1435 uint32_t *orig_value)
1437 const struct ldb_val *orig_val;
1438 uint32_t orig_uint = 0;
1439 unsigned int flags = 0;
1440 int ret;
1442 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1443 if (!orig_val || !orig_val->data) {
1444 /* add new attribute */
1445 flags = LDB_FLAG_MOD_ADD;
1447 } else {
1448 errno = 0;
1449 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1450 if (errno != 0 || orig_uint != value) {
1451 /* replace also if can't get value */
1452 flags = LDB_FLAG_MOD_REPLACE;
1456 if (flags == 0) {
1457 /* stored value is identical, nothing to change */
1458 goto done;
1461 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1462 if (ret != LDB_SUCCESS) {
1463 return NT_STATUS_NO_MEMORY;
1466 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1467 if (ret != LDB_SUCCESS) {
1468 return NT_STATUS_NO_MEMORY;
1471 done:
1472 if (orig_value) {
1473 *orig_value = orig_uint;
1475 return NT_STATUS_OK;
1478 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1479 struct ldb_context *sam_ldb,
1480 struct ldb_dn *base_dn,
1481 bool delete_user,
1482 const char *netbios_name,
1483 struct trustAuthInOutBlob *in)
1485 const char *attrs[] = { "userAccountControl", NULL };
1486 struct ldb_message **msgs;
1487 struct ldb_message *msg;
1488 uint32_t uac;
1489 uint32_t i;
1490 int ret;
1492 ret = gendb_search(sam_ldb, mem_ctx,
1493 base_dn, &msgs, attrs,
1494 "samAccountName=%s$", netbios_name);
1495 if (ret > 1) {
1496 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1499 if (ret == 0) {
1500 if (delete_user) {
1501 return NT_STATUS_OK;
1504 /* ok no existing user, add it from scratch */
1505 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1506 netbios_name, in, NULL);
1509 /* check user is what we are looking for */
1510 uac = ldb_msg_find_attr_as_uint(msgs[0],
1511 "userAccountControl", 0);
1512 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1513 return NT_STATUS_OBJECT_NAME_COLLISION;
1516 if (delete_user) {
1517 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1518 switch (ret) {
1519 case LDB_SUCCESS:
1520 return NT_STATUS_OK;
1521 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1522 return NT_STATUS_ACCESS_DENIED;
1523 default:
1524 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1528 /* entry exists, just modify secret if any */
1529 if (in == NULL || in->count == 0) {
1530 return NT_STATUS_OK;
1533 msg = ldb_msg_new(mem_ctx);
1534 if (!msg) {
1535 return NT_STATUS_NO_MEMORY;
1537 msg->dn = msgs[0]->dn;
1539 for (i = 0; i < in->count; i++) {
1540 const char *attribute;
1541 struct ldb_val v;
1542 switch (in->current.array[i].AuthType) {
1543 case TRUST_AUTH_TYPE_NT4OWF:
1544 attribute = "unicodePwd";
1545 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1546 v.length = 16;
1547 break;
1548 case TRUST_AUTH_TYPE_CLEAR:
1549 attribute = "clearTextPassword";
1550 v.data = in->current.array[i].AuthInfo.clear.password;
1551 v.length = in->current.array[i].AuthInfo.clear.size;
1552 break;
1553 default:
1554 continue;
1557 ret = ldb_msg_add_empty(msg, attribute,
1558 LDB_FLAG_MOD_REPLACE, NULL);
1559 if (ret != LDB_SUCCESS) {
1560 return NT_STATUS_NO_MEMORY;
1563 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1564 if (ret != LDB_SUCCESS) {
1565 return NT_STATUS_NO_MEMORY;
1569 /* create the trusted_domain user account */
1570 ret = ldb_modify(sam_ldb, msg);
1571 if (ret != LDB_SUCCESS) {
1572 DEBUG(0,("Failed to create user record %s: %s\n",
1573 ldb_dn_get_linearized(msg->dn),
1574 ldb_errstring(sam_ldb)));
1576 switch (ret) {
1577 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1578 return NT_STATUS_DOMAIN_EXISTS;
1579 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1580 return NT_STATUS_ACCESS_DENIED;
1581 default:
1582 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1586 return NT_STATUS_OK;
1590 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1591 struct dcesrv_handle *p_handle,
1592 TALLOC_CTX *mem_ctx,
1593 struct ldb_message *dom_msg,
1594 enum lsa_TrustDomInfoEnum level,
1595 union lsa_TrustedDomainInfo *info)
1597 struct lsa_policy_state *p_state = p_handle->data;
1598 uint32_t *posix_offset = NULL;
1599 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1600 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1601 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1602 uint32_t *enc_types = NULL;
1603 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1604 struct trustDomainPasswords auth_struct;
1605 struct trustAuthInOutBlob *current_passwords = NULL;
1606 NTSTATUS nt_status;
1607 struct ldb_message **msgs;
1608 struct ldb_message *msg;
1609 bool add_outgoing = false;
1610 bool add_incoming = false;
1611 bool del_outgoing = false;
1612 bool del_incoming = false;
1613 bool in_transaction = false;
1614 int ret;
1615 bool am_rodc;
1617 switch (level) {
1618 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1619 posix_offset = &info->posix_offset.posix_offset;
1620 break;
1621 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1622 info_ex = &info->info_ex;
1623 break;
1624 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1625 auth_info = &info->auth_info;
1626 break;
1627 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1628 posix_offset = &info->full_info.posix_offset.posix_offset;
1629 info_ex = &info->full_info.info_ex;
1630 auth_info = &info->full_info.auth_info;
1631 break;
1632 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1633 auth_info_int = &info->auth_info_internal;
1634 break;
1635 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1636 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1637 info_ex = &info->full_info_internal.info_ex;
1638 auth_info_int = &info->full_info_internal.auth_info;
1639 break;
1640 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1641 enc_types = &info->enc_types.enc_types;
1642 break;
1643 default:
1644 return NT_STATUS_INVALID_PARAMETER;
1647 if (auth_info) {
1648 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1649 &trustAuthIncoming,
1650 &trustAuthOutgoing);
1651 if (!NT_STATUS_IS_OK(nt_status)) {
1652 return nt_status;
1654 if (trustAuthIncoming.data) {
1655 /* This does the decode of some of this twice, but it is easier that way */
1656 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1657 auth_info->incoming_count,
1658 auth_info->incoming_current_auth_info,
1659 NULL,
1660 &current_passwords);
1661 if (!NT_STATUS_IS_OK(nt_status)) {
1662 return nt_status;
1667 /* decode auth_info_int if set */
1668 if (auth_info_int) {
1670 /* now decrypt blob */
1671 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1672 auth_info_int->auth_blob.size);
1674 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1675 &auth_blob, &auth_struct);
1676 if (!NT_STATUS_IS_OK(nt_status)) {
1677 return nt_status;
1681 if (info_ex) {
1682 /* verify data matches */
1683 if (info_ex->trust_attributes &
1684 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1685 /* TODO: check what behavior level we have */
1686 if (strcasecmp_m(p_state->domain_dns,
1687 p_state->forest_dns) != 0) {
1688 return NT_STATUS_INVALID_DOMAIN_STATE;
1692 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1693 if (ret == LDB_SUCCESS && am_rodc) {
1694 return NT_STATUS_NO_SUCH_DOMAIN;
1697 /* verify only one object matches the dns/netbios/sid
1698 * triplet and that this is the one we already have */
1699 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1700 p_state->system_dn,
1701 info_ex->domain_name.string,
1702 info_ex->netbios_name.string,
1703 info_ex->sid, &msgs);
1704 if (!NT_STATUS_IS_OK(nt_status)) {
1705 return nt_status;
1707 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1708 return NT_STATUS_OBJECT_NAME_COLLISION;
1710 talloc_free(msgs);
1713 /* TODO: should we fetch previous values from the existing entry
1714 * and append them ? */
1715 if (auth_info_int && auth_struct.incoming.count) {
1716 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1717 &auth_struct.incoming,
1718 &trustAuthIncoming);
1719 if (!NT_STATUS_IS_OK(nt_status)) {
1720 return nt_status;
1723 current_passwords = &auth_struct.incoming;
1725 } else {
1726 trustAuthIncoming = data_blob(NULL, 0);
1729 if (auth_info_int && auth_struct.outgoing.count) {
1730 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1731 &auth_struct.outgoing,
1732 &trustAuthOutgoing);
1733 if (!NT_STATUS_IS_OK(nt_status)) {
1734 return nt_status;
1736 } else {
1737 trustAuthOutgoing = data_blob(NULL, 0);
1740 msg = ldb_msg_new(mem_ctx);
1741 if (msg == NULL) {
1742 return NT_STATUS_NO_MEMORY;
1744 msg->dn = dom_msg->dn;
1746 if (posix_offset) {
1747 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1748 dom_msg, msg,
1749 "trustPosixOffset",
1750 *posix_offset, NULL);
1751 if (!NT_STATUS_IS_OK(nt_status)) {
1752 return nt_status;
1756 if (info_ex) {
1757 uint32_t origattrs;
1758 uint32_t origdir;
1759 int origtype;
1761 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1762 dom_msg, msg,
1763 "trustDirection",
1764 info_ex->trust_direction,
1765 &origdir);
1766 if (!NT_STATUS_IS_OK(nt_status)) {
1767 return nt_status;
1770 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1771 add_incoming = true;
1773 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1774 add_outgoing = true;
1777 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1778 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1779 del_incoming = true;
1781 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1782 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1783 del_outgoing = true;
1786 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1787 if (origtype == -1 || origtype != info_ex->trust_type) {
1788 DEBUG(1, ("Attempted to change trust type! "
1789 "Operation not handled\n"));
1790 return NT_STATUS_INVALID_PARAMETER;
1793 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1794 dom_msg, msg,
1795 "trustAttributes",
1796 info_ex->trust_attributes,
1797 &origattrs);
1798 if (!NT_STATUS_IS_OK(nt_status)) {
1799 return nt_status;
1801 /* TODO: check forestFunctionality from ldb opaque */
1802 /* TODO: check what is set makes sense */
1803 /* for now refuse changes */
1804 if (origattrs == -1 ||
1805 origattrs != info_ex->trust_attributes) {
1806 DEBUG(1, ("Attempted to change trust attributes! "
1807 "Operation not handled\n"));
1808 return NT_STATUS_INVALID_PARAMETER;
1812 if (enc_types) {
1813 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1814 dom_msg, msg,
1815 "msDS-SupportedEncryptionTypes",
1816 *enc_types, NULL);
1817 if (!NT_STATUS_IS_OK(nt_status)) {
1818 return nt_status;
1822 if (add_incoming && trustAuthIncoming.data) {
1823 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1824 LDB_FLAG_MOD_REPLACE, NULL);
1825 if (ret != LDB_SUCCESS) {
1826 return NT_STATUS_NO_MEMORY;
1828 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1829 &trustAuthIncoming, NULL);
1830 if (ret != LDB_SUCCESS) {
1831 return NT_STATUS_NO_MEMORY;
1834 if (add_outgoing && trustAuthOutgoing.data) {
1835 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1836 LDB_FLAG_MOD_REPLACE, NULL);
1837 if (ret != LDB_SUCCESS) {
1838 return NT_STATUS_NO_MEMORY;
1840 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1841 &trustAuthOutgoing, NULL);
1842 if (ret != LDB_SUCCESS) {
1843 return NT_STATUS_NO_MEMORY;
1847 /* start transaction */
1848 ret = ldb_transaction_start(p_state->sam_ldb);
1849 if (ret != LDB_SUCCESS) {
1850 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1852 in_transaction = true;
1854 if (msg->num_elements) {
1855 ret = ldb_modify(p_state->sam_ldb, msg);
1856 if (ret != LDB_SUCCESS) {
1857 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1858 ldb_dn_get_linearized(msg->dn),
1859 ldb_errstring(p_state->sam_ldb)));
1860 nt_status = dsdb_ldb_err_to_ntstatus(ret);
1861 goto done;
1865 if (add_incoming || del_incoming) {
1866 const char *netbios_name;
1868 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1869 "flatname", NULL);
1870 if (!netbios_name) {
1871 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1872 goto done;
1875 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
1876 nt_status = update_trust_user(mem_ctx,
1877 p_state->sam_ldb,
1878 p_state->domain_dn,
1879 del_incoming,
1880 netbios_name,
1881 current_passwords);
1882 if (!NT_STATUS_IS_OK(nt_status)) {
1883 goto done;
1887 /* ok, all fine, commit transaction and return */
1888 ret = ldb_transaction_commit(p_state->sam_ldb);
1889 if (ret != LDB_SUCCESS) {
1890 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1892 in_transaction = false;
1894 nt_status = NT_STATUS_OK;
1896 done:
1897 if (in_transaction) {
1898 ldb_transaction_cancel(p_state->sam_ldb);
1900 return nt_status;
1904 lsa_SetInfomrationTrustedDomain
1906 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1907 struct dcesrv_call_state *dce_call,
1908 TALLOC_CTX *mem_ctx,
1909 struct lsa_SetInformationTrustedDomain *r)
1911 struct dcesrv_handle *h;
1912 struct lsa_trusted_domain_state *td_state;
1913 struct ldb_message **msgs;
1914 NTSTATUS nt_status;
1916 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1917 LSA_HANDLE_TRUSTED_DOMAIN);
1919 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1921 /* get the trusted domain object */
1922 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1923 td_state->trusted_domain_dn,
1924 NULL, NULL, NULL, &msgs);
1925 if (!NT_STATUS_IS_OK(nt_status)) {
1926 if (NT_STATUS_EQUAL(nt_status,
1927 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1928 return nt_status;
1930 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1933 return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1934 msgs[0], r->in.level, r->in.info);
1939 lsa_DeleteTrustedDomain
1941 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1942 struct lsa_DeleteTrustedDomain *r)
1944 NTSTATUS status;
1945 struct lsa_OpenTrustedDomain opn;
1946 struct lsa_DeleteObject del;
1947 struct dcesrv_handle *h;
1949 opn.in.handle = r->in.handle;
1950 opn.in.sid = r->in.dom_sid;
1951 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1952 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1953 if (!opn.out.trustdom_handle) {
1954 return NT_STATUS_NO_MEMORY;
1956 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1957 if (!NT_STATUS_IS_OK(status)) {
1958 return status;
1961 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1962 talloc_steal(mem_ctx, h);
1964 del.in.handle = opn.out.trustdom_handle;
1965 del.out.handle = opn.out.trustdom_handle;
1966 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1967 if (!NT_STATUS_IS_OK(status)) {
1968 return status;
1970 return NT_STATUS_OK;
1973 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
1974 struct ldb_message *msg,
1975 struct lsa_TrustDomainInfoInfoEx *info_ex)
1977 info_ex->domain_name.string
1978 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1979 info_ex->netbios_name.string
1980 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1981 info_ex->sid
1982 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1983 info_ex->trust_direction
1984 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1985 info_ex->trust_type
1986 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1987 info_ex->trust_attributes
1988 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
1989 return NT_STATUS_OK;
1993 lsa_QueryTrustedDomainInfo
1995 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1996 struct lsa_QueryTrustedDomainInfo *r)
1998 union lsa_TrustedDomainInfo *info = NULL;
1999 struct dcesrv_handle *h;
2000 struct lsa_trusted_domain_state *trusted_domain_state;
2001 struct ldb_message *msg;
2002 int ret;
2003 struct ldb_message **res;
2004 const char *attrs[] = {
2005 "flatname",
2006 "trustPartner",
2007 "securityIdentifier",
2008 "trustDirection",
2009 "trustType",
2010 "trustAttributes",
2011 "msDs-supportedEncryptionTypes",
2012 NULL
2015 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2017 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2019 /* pull all the user attributes */
2020 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2021 trusted_domain_state->trusted_domain_dn, &res, attrs);
2022 if (ret != 1) {
2023 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2025 msg = res[0];
2027 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2028 if (!info) {
2029 return NT_STATUS_NO_MEMORY;
2031 *r->out.info = info;
2033 switch (r->in.level) {
2034 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2035 info->name.netbios_name.string
2036 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2037 break;
2038 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2039 info->posix_offset.posix_offset
2040 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2041 break;
2042 #if 0 /* Win2k3 doesn't implement this */
2043 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2044 r->out.info->info_basic.netbios_name.string
2045 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2046 r->out.info->info_basic.sid
2047 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2048 break;
2049 #endif
2050 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2051 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2053 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2054 ZERO_STRUCT(info->full_info);
2055 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2056 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2057 ZERO_STRUCT(info->full_info2_internal);
2058 info->full_info2_internal.posix_offset.posix_offset
2059 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2060 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2062 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2063 info->enc_types.enc_types
2064 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2065 break;
2067 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2068 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2069 /* oops, we don't want to return the info after all */
2070 talloc_free(info);
2071 *r->out.info = NULL;
2072 return NT_STATUS_INVALID_PARAMETER;
2073 default:
2074 /* oops, we don't want to return the info after all */
2075 talloc_free(info);
2076 *r->out.info = NULL;
2077 return NT_STATUS_INVALID_INFO_CLASS;
2080 return NT_STATUS_OK;
2085 lsa_QueryTrustedDomainInfoBySid
2087 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2088 struct lsa_QueryTrustedDomainInfoBySid *r)
2090 NTSTATUS status;
2091 struct lsa_OpenTrustedDomain opn;
2092 struct lsa_QueryTrustedDomainInfo query;
2093 struct dcesrv_handle *h;
2095 opn.in.handle = r->in.handle;
2096 opn.in.sid = r->in.dom_sid;
2097 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2098 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2099 if (!opn.out.trustdom_handle) {
2100 return NT_STATUS_NO_MEMORY;
2102 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2103 if (!NT_STATUS_IS_OK(status)) {
2104 return status;
2107 /* Ensure this handle goes away at the end of this call */
2108 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2109 talloc_steal(mem_ctx, h);
2111 query.in.trustdom_handle = opn.out.trustdom_handle;
2112 query.in.level = r->in.level;
2113 query.out.info = r->out.info;
2114 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2115 if (!NT_STATUS_IS_OK(status)) {
2116 return status;
2119 return NT_STATUS_OK;
2123 lsa_SetTrustedDomainInfoByName
2125 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2126 TALLOC_CTX *mem_ctx,
2127 struct lsa_SetTrustedDomainInfoByName *r)
2129 struct dcesrv_handle *policy_handle;
2130 struct lsa_policy_state *policy_state;
2131 struct ldb_message **msgs;
2132 NTSTATUS nt_status;
2134 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2135 policy_state = policy_handle->data;
2137 /* get the trusted domain object */
2138 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2139 policy_state->domain_dn,
2140 r->in.trusted_domain->string,
2141 r->in.trusted_domain->string,
2142 NULL, &msgs);
2143 if (!NT_STATUS_IS_OK(nt_status)) {
2144 if (NT_STATUS_EQUAL(nt_status,
2145 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2146 return nt_status;
2148 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2151 return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2152 msgs[0], r->in.level, r->in.info);
2156 lsa_QueryTrustedDomainInfoByName
2158 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2159 TALLOC_CTX *mem_ctx,
2160 struct lsa_QueryTrustedDomainInfoByName *r)
2162 NTSTATUS status;
2163 struct lsa_OpenTrustedDomainByName opn;
2164 struct lsa_QueryTrustedDomainInfo query;
2165 struct dcesrv_handle *h;
2167 opn.in.handle = r->in.handle;
2168 opn.in.name = *r->in.trusted_domain;
2169 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2170 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2171 if (!opn.out.trustdom_handle) {
2172 return NT_STATUS_NO_MEMORY;
2174 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2175 if (!NT_STATUS_IS_OK(status)) {
2176 return status;
2179 /* Ensure this handle goes away at the end of this call */
2180 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2181 talloc_steal(mem_ctx, h);
2183 query.in.trustdom_handle = opn.out.trustdom_handle;
2184 query.in.level = r->in.level;
2185 query.out.info = r->out.info;
2186 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2187 if (!NT_STATUS_IS_OK(status)) {
2188 return status;
2191 return NT_STATUS_OK;
2195 lsa_CloseTrustedDomainEx
2197 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2198 TALLOC_CTX *mem_ctx,
2199 struct lsa_CloseTrustedDomainEx *r)
2201 /* The result of a bad hair day from an IDL programmer? Not
2202 * implmented in Win2k3. You should always just lsa_Close
2203 * anyway. */
2204 return NT_STATUS_NOT_IMPLEMENTED;
2209 comparison function for sorting lsa_DomainInformation array
2211 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2213 return strcasecmp_m(e1->name.string, e2->name.string);
2217 lsa_EnumTrustDom
2219 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2220 struct lsa_EnumTrustDom *r)
2222 struct dcesrv_handle *policy_handle;
2223 struct lsa_DomainInfo *entries;
2224 struct lsa_policy_state *policy_state;
2225 struct ldb_message **domains;
2226 const char *attrs[] = {
2227 "flatname",
2228 "securityIdentifier",
2229 NULL
2233 int count, i;
2235 *r->out.resume_handle = 0;
2237 r->out.domains->domains = NULL;
2238 r->out.domains->count = 0;
2240 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2242 policy_state = policy_handle->data;
2244 /* search for all users in this domain. This could possibly be cached and
2245 resumed based on resume_key */
2246 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2247 "objectclass=trustedDomain");
2248 if (count < 0) {
2249 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2252 /* convert to lsa_TrustInformation format */
2253 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2254 if (!entries) {
2255 return NT_STATUS_NO_MEMORY;
2257 for (i=0;i<count;i++) {
2258 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2259 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2262 /* sort the results by name */
2263 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2265 if (*r->in.resume_handle >= count) {
2266 *r->out.resume_handle = -1;
2268 return NT_STATUS_NO_MORE_ENTRIES;
2271 /* return the rest, limit by max_size. Note that we
2272 use the w2k3 element size value of 60 */
2273 r->out.domains->count = count - *r->in.resume_handle;
2274 r->out.domains->count = MIN(r->out.domains->count,
2275 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2277 r->out.domains->domains = entries + *r->in.resume_handle;
2278 r->out.domains->count = r->out.domains->count;
2280 if (r->out.domains->count < count - *r->in.resume_handle) {
2281 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2282 return STATUS_MORE_ENTRIES;
2285 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2286 * always be larger than the previous input resume handle, in
2287 * particular when hitting the last query it is vital to set the
2288 * resume handle correctly to avoid infinite client loops, as
2289 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2290 * status is NT_STATUS_OK - gd */
2292 *r->out.resume_handle = (uint32_t)-1;
2294 return NT_STATUS_OK;
2298 comparison function for sorting lsa_DomainInformation array
2300 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2302 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2306 lsa_EnumTrustedDomainsEx
2308 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2309 struct lsa_EnumTrustedDomainsEx *r)
2311 struct dcesrv_handle *policy_handle;
2312 struct lsa_TrustDomainInfoInfoEx *entries;
2313 struct lsa_policy_state *policy_state;
2314 struct ldb_message **domains;
2315 const char *attrs[] = {
2316 "flatname",
2317 "trustPartner",
2318 "securityIdentifier",
2319 "trustDirection",
2320 "trustType",
2321 "trustAttributes",
2322 NULL
2324 NTSTATUS nt_status;
2326 int count, i;
2328 *r->out.resume_handle = 0;
2330 r->out.domains->domains = NULL;
2331 r->out.domains->count = 0;
2333 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2335 policy_state = policy_handle->data;
2337 /* search for all users in this domain. This could possibly be cached and
2338 resumed based on resume_key */
2339 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2340 "objectclass=trustedDomain");
2341 if (count < 0) {
2342 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2345 /* convert to lsa_DomainInformation format */
2346 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2347 if (!entries) {
2348 return NT_STATUS_NO_MEMORY;
2350 for (i=0;i<count;i++) {
2351 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2352 if (!NT_STATUS_IS_OK(nt_status)) {
2353 return nt_status;
2357 /* sort the results by name */
2358 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2360 if (*r->in.resume_handle >= count) {
2361 *r->out.resume_handle = -1;
2363 return NT_STATUS_NO_MORE_ENTRIES;
2366 /* return the rest, limit by max_size. Note that we
2367 use the w2k3 element size value of 60 */
2368 r->out.domains->count = count - *r->in.resume_handle;
2369 r->out.domains->count = MIN(r->out.domains->count,
2370 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2372 r->out.domains->domains = entries + *r->in.resume_handle;
2373 r->out.domains->count = r->out.domains->count;
2375 if (r->out.domains->count < count - *r->in.resume_handle) {
2376 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2377 return STATUS_MORE_ENTRIES;
2380 return NT_STATUS_OK;
2385 lsa_OpenAccount
2387 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2388 struct lsa_OpenAccount *r)
2390 struct dcesrv_handle *h, *ah;
2391 struct lsa_policy_state *state;
2392 struct lsa_account_state *astate;
2394 ZERO_STRUCTP(r->out.acct_handle);
2396 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2398 state = h->data;
2400 astate = talloc(dce_call->conn, struct lsa_account_state);
2401 if (astate == NULL) {
2402 return NT_STATUS_NO_MEMORY;
2405 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2406 if (astate->account_sid == NULL) {
2407 talloc_free(astate);
2408 return NT_STATUS_NO_MEMORY;
2411 astate->policy = talloc_reference(astate, state);
2412 astate->access_mask = r->in.access_mask;
2414 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2415 if (!ah) {
2416 talloc_free(astate);
2417 return NT_STATUS_NO_MEMORY;
2420 ah->data = talloc_steal(ah, astate);
2422 *r->out.acct_handle = ah->wire_handle;
2424 return NT_STATUS_OK;
2429 lsa_EnumPrivsAccount
2431 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2432 TALLOC_CTX *mem_ctx,
2433 struct lsa_EnumPrivsAccount *r)
2435 struct dcesrv_handle *h;
2436 struct lsa_account_state *astate;
2437 int ret;
2438 unsigned int i, j;
2439 struct ldb_message **res;
2440 const char * const attrs[] = { "privilege", NULL};
2441 struct ldb_message_element *el;
2442 const char *sidstr;
2443 struct lsa_PrivilegeSet *privs;
2445 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2447 astate = h->data;
2449 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2450 if (privs == NULL) {
2451 return NT_STATUS_NO_MEMORY;
2453 privs->count = 0;
2454 privs->unknown = 0;
2455 privs->set = NULL;
2457 *r->out.privs = privs;
2459 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2460 if (sidstr == NULL) {
2461 return NT_STATUS_NO_MEMORY;
2464 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2465 "objectSid=%s", sidstr);
2466 if (ret < 0) {
2467 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2469 if (ret != 1) {
2470 return NT_STATUS_OK;
2473 el = ldb_msg_find_element(res[0], "privilege");
2474 if (el == NULL || el->num_values == 0) {
2475 return NT_STATUS_OK;
2478 privs->set = talloc_array(privs,
2479 struct lsa_LUIDAttribute, el->num_values);
2480 if (privs->set == NULL) {
2481 return NT_STATUS_NO_MEMORY;
2484 j = 0;
2485 for (i=0;i<el->num_values;i++) {
2486 int id = sec_privilege_id((const char *)el->values[i].data);
2487 if (id == SEC_PRIV_INVALID) {
2488 /* Perhaps an account right, not a privilege */
2489 continue;
2491 privs->set[j].attribute = 0;
2492 privs->set[j].luid.low = id;
2493 privs->set[j].luid.high = 0;
2494 j++;
2497 privs->count = j;
2499 return NT_STATUS_OK;
2503 lsa_EnumAccountRights
2505 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2506 TALLOC_CTX *mem_ctx,
2507 struct lsa_EnumAccountRights *r)
2509 struct dcesrv_handle *h;
2510 struct lsa_policy_state *state;
2511 int ret;
2512 unsigned int i;
2513 struct ldb_message **res;
2514 const char * const attrs[] = { "privilege", NULL};
2515 const char *sidstr;
2516 struct ldb_message_element *el;
2518 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2520 state = h->data;
2522 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2523 if (sidstr == NULL) {
2524 return NT_STATUS_NO_MEMORY;
2527 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2528 "(&(objectSid=%s)(privilege=*))", sidstr);
2529 if (ret == 0) {
2530 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2532 if (ret != 1) {
2533 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2534 dom_sid_string(mem_ctx, r->in.sid),
2535 ldb_errstring(state->pdb)));
2536 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2539 el = ldb_msg_find_element(res[0], "privilege");
2540 if (el == NULL || el->num_values == 0) {
2541 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2544 r->out.rights->count = el->num_values;
2545 r->out.rights->names = talloc_array(r->out.rights,
2546 struct lsa_StringLarge, r->out.rights->count);
2547 if (r->out.rights->names == NULL) {
2548 return NT_STATUS_NO_MEMORY;
2551 for (i=0;i<el->num_values;i++) {
2552 r->out.rights->names[i].string = (const char *)el->values[i].data;
2555 return NT_STATUS_OK;
2561 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2563 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2564 TALLOC_CTX *mem_ctx,
2565 struct lsa_policy_state *state,
2566 int ldb_flag,
2567 struct dom_sid *sid,
2568 const struct lsa_RightSet *rights)
2570 const char *sidstr, *sidndrstr;
2571 struct ldb_message *msg;
2572 struct ldb_message_element *el;
2573 int ret;
2574 uint32_t i;
2575 struct lsa_EnumAccountRights r2;
2576 char *dnstr;
2578 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2579 SECURITY_ADMINISTRATOR) {
2580 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2581 return NT_STATUS_ACCESS_DENIED;
2584 msg = ldb_msg_new(mem_ctx);
2585 if (msg == NULL) {
2586 return NT_STATUS_NO_MEMORY;
2589 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2590 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
2592 sidstr = dom_sid_string(msg, sid);
2593 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
2595 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2596 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
2598 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2599 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
2601 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2602 NTSTATUS status;
2604 r2.in.handle = &state->handle->wire_handle;
2605 r2.in.sid = sid;
2606 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2608 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2609 if (!NT_STATUS_IS_OK(status)) {
2610 ZERO_STRUCTP(r2.out.rights);
2614 for (i=0;i<rights->count;i++) {
2615 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2616 if (sec_right_bit(rights->names[i].string) == 0) {
2617 talloc_free(msg);
2618 return NT_STATUS_NO_SUCH_PRIVILEGE;
2621 talloc_free(msg);
2622 return NT_STATUS_NO_SUCH_PRIVILEGE;
2625 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2626 uint32_t j;
2627 for (j=0;j<r2.out.rights->count;j++) {
2628 if (strcasecmp_m(r2.out.rights->names[j].string,
2629 rights->names[i].string) == 0) {
2630 break;
2633 if (j != r2.out.rights->count) continue;
2636 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2637 if (ret != LDB_SUCCESS) {
2638 talloc_free(msg);
2639 return NT_STATUS_NO_MEMORY;
2643 el = ldb_msg_find_element(msg, "privilege");
2644 if (!el) {
2645 talloc_free(msg);
2646 return NT_STATUS_OK;
2649 el->flags = ldb_flag;
2651 ret = ldb_modify(state->pdb, msg);
2652 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2653 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2654 talloc_free(msg);
2655 return NT_STATUS_NO_MEMORY;
2657 ldb_msg_add_string(msg, "comment", "added via LSA");
2658 ret = ldb_add(state->pdb, msg);
2660 if (ret != LDB_SUCCESS) {
2661 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2662 talloc_free(msg);
2663 return NT_STATUS_OK;
2665 DEBUG(3, ("Could not %s attributes from %s: %s",
2666 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2667 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2668 talloc_free(msg);
2669 return NT_STATUS_UNEXPECTED_IO_ERROR;
2672 talloc_free(msg);
2673 return NT_STATUS_OK;
2677 lsa_AddPrivilegesToAccount
2679 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2680 struct lsa_AddPrivilegesToAccount *r)
2682 struct lsa_RightSet rights;
2683 struct dcesrv_handle *h;
2684 struct lsa_account_state *astate;
2685 uint32_t i;
2687 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2689 astate = h->data;
2691 rights.count = r->in.privs->count;
2692 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2693 if (rights.names == NULL) {
2694 return NT_STATUS_NO_MEMORY;
2696 for (i=0;i<rights.count;i++) {
2697 int id = r->in.privs->set[i].luid.low;
2698 if (r->in.privs->set[i].luid.high) {
2699 return NT_STATUS_NO_SUCH_PRIVILEGE;
2701 rights.names[i].string = sec_privilege_name(id);
2702 if (rights.names[i].string == NULL) {
2703 return NT_STATUS_NO_SUCH_PRIVILEGE;
2707 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2708 LDB_FLAG_MOD_ADD, astate->account_sid,
2709 &rights);
2714 lsa_RemovePrivilegesFromAccount
2716 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2717 struct lsa_RemovePrivilegesFromAccount *r)
2719 struct lsa_RightSet *rights;
2720 struct dcesrv_handle *h;
2721 struct lsa_account_state *astate;
2722 uint32_t i;
2724 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2726 astate = h->data;
2728 rights = talloc(mem_ctx, struct lsa_RightSet);
2730 if (r->in.remove_all == 1 &&
2731 r->in.privs == NULL) {
2732 struct lsa_EnumAccountRights r2;
2733 NTSTATUS status;
2735 r2.in.handle = &astate->policy->handle->wire_handle;
2736 r2.in.sid = astate->account_sid;
2737 r2.out.rights = rights;
2739 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2740 if (!NT_STATUS_IS_OK(status)) {
2741 return status;
2744 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2745 LDB_FLAG_MOD_DELETE, astate->account_sid,
2746 r2.out.rights);
2749 if (r->in.remove_all != 0) {
2750 return NT_STATUS_INVALID_PARAMETER;
2753 rights->count = r->in.privs->count;
2754 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2755 if (rights->names == NULL) {
2756 return NT_STATUS_NO_MEMORY;
2758 for (i=0;i<rights->count;i++) {
2759 int id = r->in.privs->set[i].luid.low;
2760 if (r->in.privs->set[i].luid.high) {
2761 return NT_STATUS_NO_SUCH_PRIVILEGE;
2763 rights->names[i].string = sec_privilege_name(id);
2764 if (rights->names[i].string == NULL) {
2765 return NT_STATUS_NO_SUCH_PRIVILEGE;
2769 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2770 LDB_FLAG_MOD_DELETE, astate->account_sid,
2771 rights);
2776 lsa_GetQuotasForAccount
2778 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2779 struct lsa_GetQuotasForAccount *r)
2781 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2786 lsa_SetQuotasForAccount
2788 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2789 struct lsa_SetQuotasForAccount *r)
2791 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2796 lsa_GetSystemAccessAccount
2798 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2799 struct lsa_GetSystemAccessAccount *r)
2801 struct dcesrv_handle *h;
2802 struct lsa_account_state *astate;
2803 int ret;
2804 unsigned int i;
2805 struct ldb_message **res;
2806 const char * const attrs[] = { "privilege", NULL};
2807 struct ldb_message_element *el;
2808 const char *sidstr;
2810 *(r->out.access_mask) = 0x00000000;
2812 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2814 astate = h->data;
2816 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2817 if (sidstr == NULL) {
2818 return NT_STATUS_NO_MEMORY;
2821 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2822 "objectSid=%s", sidstr);
2823 if (ret < 0) {
2824 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2826 if (ret != 1) {
2827 return NT_STATUS_OK;
2830 el = ldb_msg_find_element(res[0], "privilege");
2831 if (el == NULL || el->num_values == 0) {
2832 return NT_STATUS_OK;
2835 for (i=0;i<el->num_values;i++) {
2836 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2837 if (right_bit == 0) {
2838 /* Perhaps an privilege, not a right */
2839 continue;
2841 *(r->out.access_mask) |= right_bit;
2844 return NT_STATUS_OK;
2849 lsa_SetSystemAccessAccount
2851 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2852 struct lsa_SetSystemAccessAccount *r)
2854 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2859 lsa_CreateSecret
2861 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2862 struct lsa_CreateSecret *r)
2864 struct dcesrv_handle *policy_handle;
2865 struct lsa_policy_state *policy_state;
2866 struct lsa_secret_state *secret_state;
2867 struct dcesrv_handle *handle;
2868 struct ldb_message **msgs, *msg;
2869 const char *attrs[] = {
2870 NULL
2873 const char *name;
2875 int ret;
2877 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2878 ZERO_STRUCTP(r->out.sec_handle);
2880 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2882 case SECURITY_SYSTEM:
2883 case SECURITY_ADMINISTRATOR:
2884 break;
2885 default:
2886 /* Users and annonymous are not allowed create secrets */
2887 return NT_STATUS_ACCESS_DENIED;
2890 policy_state = policy_handle->data;
2892 if (!r->in.name.string) {
2893 return NT_STATUS_INVALID_PARAMETER;
2896 secret_state = talloc(mem_ctx, struct lsa_secret_state);
2897 NT_STATUS_HAVE_NO_MEMORY(secret_state);
2898 secret_state->policy = policy_state;
2900 msg = ldb_msg_new(mem_ctx);
2901 if (msg == NULL) {
2902 return NT_STATUS_NO_MEMORY;
2905 if (strncmp("G$", r->in.name.string, 2) == 0) {
2906 const char *name2;
2908 secret_state->global = true;
2910 name = &r->in.name.string[2];
2911 if (strlen(name) == 0) {
2912 return NT_STATUS_INVALID_PARAMETER;
2915 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2916 ldb_binary_encode_string(mem_ctx, name));
2917 NT_STATUS_HAVE_NO_MEMORY(name2);
2919 /* We need to connect to the database as system, as this is one
2920 * of the rare RPC calls that must read the secrets (and this
2921 * is denied otherwise) */
2922 secret_state->sam_ldb = talloc_reference(secret_state,
2923 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));
2924 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2926 /* search for the secret record */
2927 ret = gendb_search(secret_state->sam_ldb,
2928 mem_ctx, policy_state->system_dn, &msgs, attrs,
2929 "(&(cn=%s)(objectclass=secret))",
2930 name2);
2931 if (ret > 0) {
2932 return NT_STATUS_OBJECT_NAME_COLLISION;
2935 if (ret < 0) {
2936 DEBUG(0,("Failure searching for CN=%s: %s\n",
2937 name2, ldb_errstring(secret_state->sam_ldb)));
2938 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2941 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2942 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2943 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2944 return NT_STATUS_NO_MEMORY;
2947 ret = ldb_msg_add_string(msg, "cn", name2);
2948 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2949 } else {
2950 secret_state->global = false;
2952 name = r->in.name.string;
2953 if (strlen(name) == 0) {
2954 return NT_STATUS_INVALID_PARAMETER;
2957 secret_state->sam_ldb = talloc_reference(secret_state,
2958 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
2959 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2961 /* search for the secret record */
2962 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2963 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2964 &msgs, attrs,
2965 "(&(cn=%s)(objectclass=secret))",
2966 ldb_binary_encode_string(mem_ctx, name));
2967 if (ret > 0) {
2968 return NT_STATUS_OBJECT_NAME_COLLISION;
2971 if (ret < 0) {
2972 DEBUG(0,("Failure searching for CN=%s: %s\n",
2973 name, ldb_errstring(secret_state->sam_ldb)));
2974 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2977 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
2978 "cn=%s,cn=LSA Secrets", name);
2979 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2980 ret = ldb_msg_add_string(msg, "cn", name);
2981 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2984 ret = ldb_msg_add_string(msg, "objectClass", "secret");
2985 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2987 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2988 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
2990 /* create the secret */
2991 ret = ldb_add(secret_state->sam_ldb, msg);
2992 if (ret != LDB_SUCCESS) {
2993 DEBUG(0,("Failed to create secret record %s: %s\n",
2994 ldb_dn_get_linearized(msg->dn),
2995 ldb_errstring(secret_state->sam_ldb)));
2996 return NT_STATUS_ACCESS_DENIED;
2999 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3000 NT_STATUS_HAVE_NO_MEMORY(handle);
3002 handle->data = talloc_steal(handle, secret_state);
3004 secret_state->access_mask = r->in.access_mask;
3005 secret_state->policy = talloc_reference(secret_state, policy_state);
3006 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3008 *r->out.sec_handle = handle->wire_handle;
3010 return NT_STATUS_OK;
3015 lsa_OpenSecret
3017 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3018 struct lsa_OpenSecret *r)
3020 struct dcesrv_handle *policy_handle;
3022 struct lsa_policy_state *policy_state;
3023 struct lsa_secret_state *secret_state;
3024 struct dcesrv_handle *handle;
3025 struct ldb_message **msgs;
3026 const char *attrs[] = {
3027 NULL
3030 const char *name;
3032 int ret;
3034 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3035 ZERO_STRUCTP(r->out.sec_handle);
3036 policy_state = policy_handle->data;
3038 if (!r->in.name.string) {
3039 return NT_STATUS_INVALID_PARAMETER;
3042 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3044 case SECURITY_SYSTEM:
3045 case SECURITY_ADMINISTRATOR:
3046 break;
3047 default:
3048 /* Users and annonymous are not allowed to access secrets */
3049 return NT_STATUS_ACCESS_DENIED;
3052 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3053 if (!secret_state) {
3054 return NT_STATUS_NO_MEMORY;
3056 secret_state->policy = policy_state;
3058 if (strncmp("G$", r->in.name.string, 2) == 0) {
3059 name = &r->in.name.string[2];
3060 /* 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) */
3061 secret_state->sam_ldb = talloc_reference(secret_state,
3062 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));
3063 secret_state->global = true;
3065 if (strlen(name) < 1) {
3066 return NT_STATUS_INVALID_PARAMETER;
3069 /* search for the secret record */
3070 ret = gendb_search(secret_state->sam_ldb,
3071 mem_ctx, policy_state->system_dn, &msgs, attrs,
3072 "(&(cn=%s Secret)(objectclass=secret))",
3073 ldb_binary_encode_string(mem_ctx, name));
3074 if (ret == 0) {
3075 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3078 if (ret != 1) {
3079 DEBUG(0,("Found %d records matching DN %s\n", ret,
3080 ldb_dn_get_linearized(policy_state->system_dn)));
3081 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3083 } else {
3084 secret_state->global = false;
3085 secret_state->sam_ldb = talloc_reference(secret_state,
3086 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3088 name = r->in.name.string;
3089 if (strlen(name) < 1) {
3090 return NT_STATUS_INVALID_PARAMETER;
3093 /* search for the secret record */
3094 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3095 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3096 &msgs, attrs,
3097 "(&(cn=%s)(objectclass=secret))",
3098 ldb_binary_encode_string(mem_ctx, name));
3099 if (ret == 0) {
3100 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3103 if (ret != 1) {
3104 DEBUG(0,("Found %d records matching CN=%s\n",
3105 ret, ldb_binary_encode_string(mem_ctx, name)));
3106 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3110 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3112 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3113 if (!handle) {
3114 return NT_STATUS_NO_MEMORY;
3117 handle->data = talloc_steal(handle, secret_state);
3119 secret_state->access_mask = r->in.access_mask;
3120 secret_state->policy = talloc_reference(secret_state, policy_state);
3122 *r->out.sec_handle = handle->wire_handle;
3124 return NT_STATUS_OK;
3129 lsa_SetSecret
3131 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3132 struct lsa_SetSecret *r)
3135 struct dcesrv_handle *h;
3136 struct lsa_secret_state *secret_state;
3137 struct ldb_message *msg;
3138 DATA_BLOB session_key;
3139 DATA_BLOB crypt_secret, secret;
3140 struct ldb_val val;
3141 int ret;
3142 NTSTATUS status = NT_STATUS_OK;
3144 struct timeval now = timeval_current();
3145 NTTIME nt_now = timeval_to_nttime(&now);
3147 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3149 secret_state = h->data;
3151 msg = ldb_msg_new(mem_ctx);
3152 if (msg == NULL) {
3153 return NT_STATUS_NO_MEMORY;
3156 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3157 if (!msg->dn) {
3158 return NT_STATUS_NO_MEMORY;
3160 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3161 if (!NT_STATUS_IS_OK(status)) {
3162 return status;
3165 if (r->in.old_val) {
3166 /* Decrypt */
3167 crypt_secret.data = r->in.old_val->data;
3168 crypt_secret.length = r->in.old_val->size;
3170 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3171 if (!NT_STATUS_IS_OK(status)) {
3172 return status;
3175 val.data = secret.data;
3176 val.length = secret.length;
3178 /* set value */
3179 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3180 return NT_STATUS_NO_MEMORY;
3183 /* set old value mtime */
3184 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3185 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3186 return NT_STATUS_NO_MEMORY;
3189 } else {
3190 /* If the old value is not set, then migrate the
3191 * current value to the old value */
3192 const struct ldb_val *old_val;
3193 NTTIME last_set_time;
3194 struct ldb_message **res;
3195 const char *attrs[] = {
3196 "currentValue",
3197 "lastSetTime",
3198 NULL
3201 /* search for the secret record */
3202 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3203 secret_state->secret_dn, &res, attrs);
3204 if (ret == 0) {
3205 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3208 if (ret != 1) {
3209 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3210 ldb_dn_get_linearized(secret_state->secret_dn)));
3211 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3214 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3215 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3217 if (old_val) {
3218 /* set old value */
3219 if (ldb_msg_add_value(msg, "priorValue",
3220 old_val, NULL) != LDB_SUCCESS) {
3221 return NT_STATUS_NO_MEMORY;
3223 } else {
3224 if (samdb_msg_add_delete(secret_state->sam_ldb,
3225 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3226 return NT_STATUS_NO_MEMORY;
3230 /* set old value mtime */
3231 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3232 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3233 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3234 return NT_STATUS_NO_MEMORY;
3236 } else {
3237 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3238 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3239 return NT_STATUS_NO_MEMORY;
3244 if (r->in.new_val) {
3245 /* Decrypt */
3246 crypt_secret.data = r->in.new_val->data;
3247 crypt_secret.length = r->in.new_val->size;
3249 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3250 if (!NT_STATUS_IS_OK(status)) {
3251 return status;
3254 val.data = secret.data;
3255 val.length = secret.length;
3257 /* set value */
3258 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3259 return NT_STATUS_NO_MEMORY;
3262 /* set new value mtime */
3263 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3264 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3265 return NT_STATUS_NO_MEMORY;
3267 } else {
3268 /* NULL out the NEW value */
3269 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3270 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3271 return NT_STATUS_NO_MEMORY;
3273 if (samdb_msg_add_delete(secret_state->sam_ldb,
3274 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3275 return NT_STATUS_NO_MEMORY;
3279 /* modify the samdb record */
3280 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3281 if (ret != LDB_SUCCESS) {
3282 return dsdb_ldb_err_to_ntstatus(ret);
3285 return NT_STATUS_OK;
3290 lsa_QuerySecret
3292 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3293 struct lsa_QuerySecret *r)
3295 struct dcesrv_handle *h;
3296 struct lsa_secret_state *secret_state;
3297 struct ldb_message *msg;
3298 DATA_BLOB session_key;
3299 DATA_BLOB crypt_secret, secret;
3300 int ret;
3301 struct ldb_message **res;
3302 const char *attrs[] = {
3303 "currentValue",
3304 "priorValue",
3305 "lastSetTime",
3306 "priorSetTime",
3307 NULL
3310 NTSTATUS nt_status;
3312 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3314 /* Ensure user is permitted to read this... */
3315 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3317 case SECURITY_SYSTEM:
3318 case SECURITY_ADMINISTRATOR:
3319 break;
3320 default:
3321 /* Users and annonymous are not allowed to read secrets */
3322 return NT_STATUS_ACCESS_DENIED;
3325 secret_state = h->data;
3327 /* pull all the user attributes */
3328 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3329 secret_state->secret_dn, &res, attrs);
3330 if (ret != 1) {
3331 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3333 msg = res[0];
3335 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3336 if (!NT_STATUS_IS_OK(nt_status)) {
3337 return nt_status;
3340 if (r->in.old_val) {
3341 const struct ldb_val *prior_val;
3342 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3343 if (!r->out.old_val) {
3344 return NT_STATUS_NO_MEMORY;
3346 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3348 if (prior_val && prior_val->length) {
3349 secret.data = prior_val->data;
3350 secret.length = prior_val->length;
3352 /* Encrypt */
3353 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3354 if (!crypt_secret.length) {
3355 return NT_STATUS_NO_MEMORY;
3357 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3358 if (!r->out.old_val->buf) {
3359 return NT_STATUS_NO_MEMORY;
3361 r->out.old_val->buf->size = crypt_secret.length;
3362 r->out.old_val->buf->length = crypt_secret.length;
3363 r->out.old_val->buf->data = crypt_secret.data;
3367 if (r->in.old_mtime) {
3368 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3369 if (!r->out.old_mtime) {
3370 return NT_STATUS_NO_MEMORY;
3372 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3375 if (r->in.new_val) {
3376 const struct ldb_val *new_val;
3377 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3378 if (!r->out.new_val) {
3379 return NT_STATUS_NO_MEMORY;
3382 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3384 if (new_val && new_val->length) {
3385 secret.data = new_val->data;
3386 secret.length = new_val->length;
3388 /* Encrypt */
3389 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3390 if (!crypt_secret.length) {
3391 return NT_STATUS_NO_MEMORY;
3393 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3394 if (!r->out.new_val->buf) {
3395 return NT_STATUS_NO_MEMORY;
3397 r->out.new_val->buf->length = crypt_secret.length;
3398 r->out.new_val->buf->size = crypt_secret.length;
3399 r->out.new_val->buf->data = crypt_secret.data;
3403 if (r->in.new_mtime) {
3404 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3405 if (!r->out.new_mtime) {
3406 return NT_STATUS_NO_MEMORY;
3408 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3411 return NT_STATUS_OK;
3416 lsa_LookupPrivValue
3418 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3419 TALLOC_CTX *mem_ctx,
3420 struct lsa_LookupPrivValue *r)
3422 struct dcesrv_handle *h;
3423 int id;
3425 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3427 id = sec_privilege_id(r->in.name->string);
3428 if (id == SEC_PRIV_INVALID) {
3429 return NT_STATUS_NO_SUCH_PRIVILEGE;
3432 r->out.luid->low = id;
3433 r->out.luid->high = 0;
3435 return NT_STATUS_OK;
3440 lsa_LookupPrivName
3442 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3443 TALLOC_CTX *mem_ctx,
3444 struct lsa_LookupPrivName *r)
3446 struct dcesrv_handle *h;
3447 struct lsa_StringLarge *name;
3448 const char *privname;
3450 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3452 if (r->in.luid->high != 0) {
3453 return NT_STATUS_NO_SUCH_PRIVILEGE;
3456 privname = sec_privilege_name(r->in.luid->low);
3457 if (privname == NULL) {
3458 return NT_STATUS_NO_SUCH_PRIVILEGE;
3461 name = talloc(mem_ctx, struct lsa_StringLarge);
3462 if (name == NULL) {
3463 return NT_STATUS_NO_MEMORY;
3466 name->string = privname;
3468 *r->out.name = name;
3470 return NT_STATUS_OK;
3475 lsa_LookupPrivDisplayName
3477 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3478 TALLOC_CTX *mem_ctx,
3479 struct lsa_LookupPrivDisplayName *r)
3481 struct dcesrv_handle *h;
3482 struct lsa_StringLarge *disp_name = NULL;
3483 enum sec_privilege id;
3485 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3487 id = sec_privilege_id(r->in.name->string);
3488 if (id == SEC_PRIV_INVALID) {
3489 return NT_STATUS_NO_SUCH_PRIVILEGE;
3492 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3493 if (disp_name == NULL) {
3494 return NT_STATUS_NO_MEMORY;
3497 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3498 if (disp_name->string == NULL) {
3499 return NT_STATUS_INTERNAL_ERROR;
3502 *r->out.disp_name = disp_name;
3503 *r->out.returned_language_id = 0;
3505 return NT_STATUS_OK;
3510 lsa_EnumAccountsWithUserRight
3512 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3513 TALLOC_CTX *mem_ctx,
3514 struct lsa_EnumAccountsWithUserRight *r)
3516 struct dcesrv_handle *h;
3517 struct lsa_policy_state *state;
3518 int ret, i;
3519 struct ldb_message **res;
3520 const char * const attrs[] = { "objectSid", NULL};
3521 const char *privname;
3523 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3525 state = h->data;
3527 if (r->in.name == NULL) {
3528 return NT_STATUS_NO_SUCH_PRIVILEGE;
3531 privname = r->in.name->string;
3532 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3533 return NT_STATUS_NO_SUCH_PRIVILEGE;
3536 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3537 "privilege=%s", privname);
3538 if (ret < 0) {
3539 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3541 if (ret == 0) {
3542 return NT_STATUS_NO_MORE_ENTRIES;
3545 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3546 if (r->out.sids->sids == NULL) {
3547 return NT_STATUS_NO_MEMORY;
3549 for (i=0;i<ret;i++) {
3550 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3551 res[i], "objectSid");
3552 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3554 r->out.sids->num_sids = ret;
3556 return NT_STATUS_OK;
3561 lsa_AddAccountRights
3563 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3564 TALLOC_CTX *mem_ctx,
3565 struct lsa_AddAccountRights *r)
3567 struct dcesrv_handle *h;
3568 struct lsa_policy_state *state;
3570 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3572 state = h->data;
3574 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3575 LDB_FLAG_MOD_ADD,
3576 r->in.sid, r->in.rights);
3581 lsa_RemoveAccountRights
3583 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3584 TALLOC_CTX *mem_ctx,
3585 struct lsa_RemoveAccountRights *r)
3587 struct dcesrv_handle *h;
3588 struct lsa_policy_state *state;
3590 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3592 state = h->data;
3594 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3595 LDB_FLAG_MOD_DELETE,
3596 r->in.sid, r->in.rights);
3601 lsa_StorePrivateData
3603 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3604 struct lsa_StorePrivateData *r)
3606 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3611 lsa_RetrievePrivateData
3613 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3614 struct lsa_RetrievePrivateData *r)
3616 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3621 lsa_GetUserName
3623 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3624 struct lsa_GetUserName *r)
3626 enum dcerpc_transport_t transport =
3627 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3628 NTSTATUS status = NT_STATUS_OK;
3629 const char *account_name;
3630 const char *authority_name;
3631 struct lsa_String *_account_name;
3632 struct lsa_String *_authority_name = NULL;
3634 if (transport != NCACN_NP && transport != NCALRPC) {
3635 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3638 /* this is what w2k3 does */
3639 r->out.account_name = r->in.account_name;
3640 r->out.authority_name = r->in.authority_name;
3642 if (r->in.account_name
3643 && *r->in.account_name
3644 /* && *(*r->in.account_name)->string */
3646 return NT_STATUS_INVALID_PARAMETER;
3649 if (r->in.authority_name
3650 && *r->in.authority_name
3651 /* && *(*r->in.authority_name)->string */
3653 return NT_STATUS_INVALID_PARAMETER;
3656 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3657 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3659 _account_name = talloc(mem_ctx, struct lsa_String);
3660 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3661 _account_name->string = account_name;
3663 if (r->in.authority_name) {
3664 _authority_name = talloc(mem_ctx, struct lsa_String);
3665 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3666 _authority_name->string = authority_name;
3669 *r->out.account_name = _account_name;
3670 if (r->out.authority_name) {
3671 *r->out.authority_name = _authority_name;
3674 return status;
3678 lsa_SetInfoPolicy2
3680 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3681 TALLOC_CTX *mem_ctx,
3682 struct lsa_SetInfoPolicy2 *r)
3684 /* need to support these */
3685 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3688 static void kdc_get_policy(struct loadparm_context *lp_ctx,
3689 struct smb_krb5_context *smb_krb5_context,
3690 struct lsa_DomainInfoKerberos *k)
3692 time_t svc_tkt_lifetime;
3693 time_t usr_tkt_lifetime;
3694 time_t renewal_lifetime;
3696 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
3698 /* Our KDC always re-validates the client */
3699 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
3701 lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
3702 &usr_tkt_lifetime, &renewal_lifetime);
3704 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
3705 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
3706 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
3707 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
3708 However in the parent function we basically just did a full
3709 krb5_context init with the only purpose of getting a global
3710 config option (the max skew), it would probably make more sense
3711 to have a lp_ or ldb global option as the samba default */
3712 if (smb_krb5_context) {
3713 unix_to_nt_time(&k->clock_skew,
3714 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
3716 #endif
3717 k->reserved = 0;
3720 lsa_QueryDomainInformationPolicy
3722 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3723 TALLOC_CTX *mem_ctx,
3724 struct lsa_QueryDomainInformationPolicy *r)
3726 union lsa_DomainInformationPolicy *info;
3728 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3729 if (!info) {
3730 return NT_STATUS_NO_MEMORY;
3733 switch (r->in.level) {
3734 case LSA_DOMAIN_INFO_POLICY_EFS:
3735 talloc_free(info);
3736 *r->out.info = NULL;
3737 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3738 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3740 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3741 struct smb_krb5_context *smb_krb5_context;
3742 int ret = smb_krb5_init_context(mem_ctx,
3743 dce_call->event_ctx,
3744 dce_call->conn->dce_ctx->lp_ctx,
3745 &smb_krb5_context);
3746 if (ret != 0) {
3747 talloc_free(info);
3748 *r->out.info = NULL;
3749 return NT_STATUS_INTERNAL_ERROR;
3751 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3752 smb_krb5_context,
3754 talloc_free(smb_krb5_context);
3755 *r->out.info = info;
3756 return NT_STATUS_OK;
3758 default:
3759 talloc_free(info);
3760 *r->out.info = NULL;
3761 return NT_STATUS_INVALID_INFO_CLASS;
3766 lsa_SetDomInfoPolicy
3768 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3769 TALLOC_CTX *mem_ctx,
3770 struct lsa_SetDomainInformationPolicy *r)
3772 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3776 lsa_TestCall
3778 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3779 TALLOC_CTX *mem_ctx,
3780 struct lsa_TestCall *r)
3782 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3786 lsa_CREDRWRITE
3788 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3789 struct lsa_CREDRWRITE *r)
3791 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3796 lsa_CREDRREAD
3798 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3799 struct lsa_CREDRREAD *r)
3801 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3806 lsa_CREDRENUMERATE
3808 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3809 struct lsa_CREDRENUMERATE *r)
3811 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3816 lsa_CREDRWRITEDOMAINCREDENTIALS
3818 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3819 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3821 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3826 lsa_CREDRREADDOMAINCREDENTIALS
3828 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3829 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3831 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3836 lsa_CREDRDELETE
3838 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3839 struct lsa_CREDRDELETE *r)
3841 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3846 lsa_CREDRGETTARGETINFO
3848 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3849 struct lsa_CREDRGETTARGETINFO *r)
3851 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3856 lsa_CREDRPROFILELOADED
3858 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3859 struct lsa_CREDRPROFILELOADED *r)
3861 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3866 lsa_CREDRGETSESSIONTYPES
3868 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3869 struct lsa_CREDRGETSESSIONTYPES *r)
3871 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3876 lsa_LSARREGISTERAUDITEVENT
3878 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3879 struct lsa_LSARREGISTERAUDITEVENT *r)
3881 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3886 lsa_LSARGENAUDITEVENT
3888 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3889 struct lsa_LSARGENAUDITEVENT *r)
3891 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3896 lsa_LSARUNREGISTERAUDITEVENT
3898 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3899 struct lsa_LSARUNREGISTERAUDITEVENT *r)
3901 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3906 lsa_lsaRQueryForestTrustInformation
3908 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3909 struct lsa_lsaRQueryForestTrustInformation *r)
3911 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3914 #define DNS_CMP_MATCH 0
3915 #define DNS_CMP_FIRST_IS_CHILD 1
3916 #define DNS_CMP_SECOND_IS_CHILD 2
3917 #define DNS_CMP_NO_MATCH 3
3919 /* this function assumes names are well formed DNS names.
3920 * it doesn't validate them */
3921 static int dns_cmp(const char *s1, size_t l1,
3922 const char *s2, size_t l2)
3924 const char *p1, *p2;
3925 size_t t1, t2;
3926 int cret;
3928 if (l1 == l2) {
3929 if (strcasecmp_m(s1, s2) == 0) {
3930 return DNS_CMP_MATCH;
3932 return DNS_CMP_NO_MATCH;
3935 if (l1 > l2) {
3936 p1 = s1;
3937 p2 = s2;
3938 t1 = l1;
3939 t2 = l2;
3940 cret = DNS_CMP_FIRST_IS_CHILD;
3941 } else {
3942 p1 = s2;
3943 p2 = s1;
3944 t1 = l2;
3945 t2 = l1;
3946 cret = DNS_CMP_SECOND_IS_CHILD;
3949 if (p1[t1 - t2 - 1] != '.') {
3950 return DNS_CMP_NO_MATCH;
3953 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3954 return cret;
3957 return DNS_CMP_NO_MATCH;
3960 /* decode all TDOs forest trust info blobs */
3961 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3962 struct ldb_message *msg,
3963 struct ForestTrustInfo *info)
3965 const struct ldb_val *ft_blob;
3966 enum ndr_err_code ndr_err;
3968 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3969 if (!ft_blob || !ft_blob->data) {
3970 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3972 /* ldb_val is equivalent to DATA_BLOB */
3973 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3974 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3975 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3976 return NT_STATUS_INVALID_DOMAIN_STATE;
3979 return NT_STATUS_OK;
3982 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
3983 struct ForestTrustInfo *fti)
3985 struct ForestTrustDataDomainInfo *info;
3986 struct ForestTrustInfoRecord *rec;
3988 fti->version = 1;
3989 fti->count = 2;
3990 fti->records = talloc_array(fti,
3991 struct ForestTrustInfoRecordArmor, 2);
3992 if (!fti->records) {
3993 return NT_STATUS_NO_MEMORY;
3996 /* TLN info */
3997 rec = &fti->records[0].record;
3999 rec->flags = 0;
4000 rec->timestamp = 0;
4001 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
4003 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
4004 if (!rec->data.name.string) {
4005 return NT_STATUS_NO_MEMORY;
4007 rec->data.name.size = strlen(rec->data.name.string);
4009 /* DOMAIN info */
4010 rec = &fti->records[1].record;
4012 rec->flags = 0;
4013 rec->timestamp = 0;
4014 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
4016 info = &rec->data.info;
4018 info->sid = *ps->domain_sid;
4019 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
4020 if (!info->dns_name.string) {
4021 return NT_STATUS_NO_MEMORY;
4023 info->dns_name.size = strlen(info->dns_name.string);
4024 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
4025 if (!info->netbios_name.string) {
4026 return NT_STATUS_NO_MEMORY;
4028 info->netbios_name.size = strlen(info->netbios_name.string);
4030 return NT_STATUS_OK;
4033 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
4034 struct lsa_ForestTrustInformation *lfti,
4035 struct ForestTrustInfo *fti)
4037 struct lsa_ForestTrustRecord *lrec;
4038 struct ForestTrustInfoRecord *rec;
4039 struct lsa_StringLarge *tln;
4040 struct lsa_ForestTrustDomainInfo *info;
4041 uint32_t i;
4043 fti->version = 1;
4044 fti->count = lfti->count;
4045 fti->records = talloc_array(mem_ctx,
4046 struct ForestTrustInfoRecordArmor,
4047 fti->count);
4048 if (!fti->records) {
4049 return NT_STATUS_NO_MEMORY;
4051 for (i = 0; i < fti->count; i++) {
4052 lrec = lfti->entries[i];
4053 rec = &fti->records[i].record;
4055 rec->flags = lrec->flags;
4056 rec->timestamp = lrec->time;
4057 rec->type = lrec->type;
4059 switch (lrec->type) {
4060 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4061 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4062 tln = &lrec->forest_trust_data.top_level_name;
4063 rec->data.name.string =
4064 talloc_strdup(mem_ctx, tln->string);
4065 if (!rec->data.name.string) {
4066 return NT_STATUS_NO_MEMORY;
4068 rec->data.name.size = strlen(rec->data.name.string);
4069 break;
4070 case LSA_FOREST_TRUST_DOMAIN_INFO:
4071 info = &lrec->forest_trust_data.domain_info;
4072 rec->data.info.sid = *info->domain_sid;
4073 rec->data.info.dns_name.string =
4074 talloc_strdup(mem_ctx,
4075 info->dns_domain_name.string);
4076 if (!rec->data.info.dns_name.string) {
4077 return NT_STATUS_NO_MEMORY;
4079 rec->data.info.dns_name.size =
4080 strlen(rec->data.info.dns_name.string);
4081 rec->data.info.netbios_name.string =
4082 talloc_strdup(mem_ctx,
4083 info->netbios_domain_name.string);
4084 if (!rec->data.info.netbios_name.string) {
4085 return NT_STATUS_NO_MEMORY;
4087 rec->data.info.netbios_name.size =
4088 strlen(rec->data.info.netbios_name.string);
4089 break;
4090 default:
4091 return NT_STATUS_INVALID_DOMAIN_STATE;
4095 return NT_STATUS_OK;
4098 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4099 uint32_t idx, uint32_t collision_type,
4100 uint32_t conflict_type, const char *tdo_name);
4102 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4103 const char *tdo_name,
4104 struct ForestTrustInfo *tdo_fti,
4105 struct ForestTrustInfo *new_fti,
4106 struct lsa_ForestTrustCollisionInfo *c_info)
4108 struct ForestTrustInfoRecord *nrec;
4109 struct ForestTrustInfoRecord *trec;
4110 const char *dns_name;
4111 const char *nb_name;
4112 struct dom_sid *sid;
4113 const char *tname;
4114 size_t dns_len;
4115 size_t tlen;
4116 NTSTATUS nt_status = NT_STATUS_OK;
4117 uint32_t new_fti_idx;
4118 uint32_t i;
4119 /* use always TDO type, until we understand when Xref can be used */
4120 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4121 bool tln_conflict;
4122 bool sid_conflict;
4123 bool nb_conflict;
4124 bool exclusion;
4125 bool ex_rule;
4126 int ret;
4128 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4130 nrec = &new_fti->records[new_fti_idx].record;
4131 dns_name = NULL;
4132 tln_conflict = false;
4133 sid_conflict = false;
4134 nb_conflict = false;
4135 exclusion = false;
4137 switch (nrec->type) {
4138 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4139 /* exclusions do not conflict by definition */
4140 break;
4142 case FOREST_TRUST_TOP_LEVEL_NAME:
4143 dns_name = nrec->data.name.string;
4144 dns_len = nrec->data.name.size;
4145 break;
4147 case LSA_FOREST_TRUST_DOMAIN_INFO:
4148 dns_name = nrec->data.info.dns_name.string;
4149 dns_len = nrec->data.info.dns_name.size;
4150 nb_name = nrec->data.info.netbios_name.string;
4151 sid = &nrec->data.info.sid;
4152 break;
4155 if (!dns_name) continue;
4157 /* check if this is already taken and not excluded */
4158 for (i = 0; i < tdo_fti->count; i++) {
4159 trec = &tdo_fti->records[i].record;
4161 switch (trec->type) {
4162 case FOREST_TRUST_TOP_LEVEL_NAME:
4163 ex_rule = false;
4164 tname = trec->data.name.string;
4165 tlen = trec->data.name.size;
4166 break;
4167 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4168 ex_rule = true;
4169 tname = trec->data.name.string;
4170 tlen = trec->data.name.size;
4171 break;
4172 case FOREST_TRUST_DOMAIN_INFO:
4173 ex_rule = false;
4174 tname = trec->data.info.dns_name.string;
4175 tlen = trec->data.info.dns_name.size;
4177 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4178 switch (ret) {
4179 case DNS_CMP_MATCH:
4180 /* if it matches exclusion,
4181 * it doesn't conflict */
4182 if (ex_rule) {
4183 exclusion = true;
4184 break;
4186 /* fall through */
4187 case DNS_CMP_FIRST_IS_CHILD:
4188 case DNS_CMP_SECOND_IS_CHILD:
4189 tln_conflict = true;
4190 /* fall through */
4191 default:
4192 break;
4195 /* explicit exclusion, no dns name conflict here */
4196 if (exclusion) {
4197 tln_conflict = false;
4200 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4201 continue;
4204 /* also test for domain info */
4205 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4206 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4207 sid_conflict = true;
4209 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4210 strcasecmp_m(trec->data.info.netbios_name.string,
4211 nb_name) == 0) {
4212 nb_conflict = true;
4216 if (tln_conflict) {
4217 nt_status = add_collision(c_info, new_fti_idx,
4218 collision_type,
4219 LSA_TLN_DISABLED_CONFLICT,
4220 tdo_name);
4221 if (!NT_STATUS_IS_OK(nt_status)) {
4222 goto done;
4225 if (sid_conflict) {
4226 nt_status = add_collision(c_info, new_fti_idx,
4227 collision_type,
4228 LSA_SID_DISABLED_CONFLICT,
4229 tdo_name);
4230 if (!NT_STATUS_IS_OK(nt_status)) {
4231 goto done;
4234 if (nb_conflict) {
4235 nt_status = add_collision(c_info, new_fti_idx,
4236 collision_type,
4237 LSA_NB_DISABLED_CONFLICT,
4238 tdo_name);
4239 if (!NT_STATUS_IS_OK(nt_status)) {
4240 goto done;
4245 done:
4246 return nt_status;
4249 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4250 uint32_t idx, uint32_t collision_type,
4251 uint32_t conflict_type, const char *tdo_name)
4253 struct lsa_ForestTrustCollisionRecord **es;
4254 uint32_t i = c_info->count;
4256 es = talloc_realloc(c_info, c_info->entries,
4257 struct lsa_ForestTrustCollisionRecord *, i + 1);
4258 if (!es) {
4259 return NT_STATUS_NO_MEMORY;
4261 c_info->entries = es;
4262 c_info->count = i + 1;
4264 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4265 if (!es[i]) {
4266 return NT_STATUS_NO_MEMORY;
4269 es[i]->index = idx;
4270 es[i]->type = collision_type;
4271 es[i]->flags.flags = conflict_type;
4272 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4273 if (!es[i]->name.string) {
4274 return NT_STATUS_NO_MEMORY;
4276 es[i]->name.size = strlen(es[i]->name.string);
4278 return NT_STATUS_OK;
4282 lsa_lsaRSetForestTrustInformation
4284 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4285 TALLOC_CTX *mem_ctx,
4286 struct lsa_lsaRSetForestTrustInformation *r)
4288 struct dcesrv_handle *h;
4289 struct lsa_policy_state *p_state;
4290 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4291 "msDS-TrustForestTrustInfo", NULL };
4292 struct ldb_message **dom_res = NULL;
4293 struct ldb_dn *tdo_dn;
4294 struct ldb_message *msg;
4295 int num_res, i;
4296 const char *td_name;
4297 uint32_t trust_attributes;
4298 struct lsa_ForestTrustCollisionInfo *c_info;
4299 struct ForestTrustInfo *nfti;
4300 struct ForestTrustInfo *fti;
4301 DATA_BLOB ft_blob;
4302 enum ndr_err_code ndr_err;
4303 NTSTATUS nt_status;
4304 bool am_rodc;
4305 int ret;
4307 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4309 p_state = h->data;
4311 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4312 return NT_STATUS_INVALID_DOMAIN_STATE;
4315 /* abort if we are not a PDC */
4316 if (!samdb_is_pdc(p_state->sam_ldb)) {
4317 return NT_STATUS_INVALID_DOMAIN_ROLE;
4320 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4321 if (ret == LDB_SUCCESS && am_rodc) {
4322 return NT_STATUS_NO_SUCH_DOMAIN;
4325 /* check caller has TRUSTED_SET_AUTH */
4327 /* fetch all trusted domain objects */
4328 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4329 p_state->system_dn,
4330 &dom_res, trust_attrs,
4331 "(objectclass=trustedDomain)");
4332 if (num_res == 0) {
4333 return NT_STATUS_NO_SUCH_DOMAIN;
4336 for (i = 0; i < num_res; i++) {
4337 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4338 "trustPartner", NULL);
4339 if (!td_name) {
4340 return NT_STATUS_INVALID_DOMAIN_STATE;
4342 if (strcasecmp_m(td_name,
4343 r->in.trusted_domain_name->string) == 0) {
4344 break;
4347 if (i >= num_res) {
4348 return NT_STATUS_NO_SUCH_DOMAIN;
4351 tdo_dn = dom_res[i]->dn;
4353 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4354 "trustAttributes", 0);
4355 if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4356 return NT_STATUS_INVALID_PARAMETER;
4359 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4360 return NT_STATUS_INVALID_PARAMETER;
4363 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4364 if (!nfti) {
4365 return NT_STATUS_NO_MEMORY;
4368 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4369 if (!NT_STATUS_IS_OK(nt_status)) {
4370 return nt_status;
4373 c_info = talloc_zero(r->out.collision_info,
4374 struct lsa_ForestTrustCollisionInfo);
4375 if (!c_info) {
4376 return NT_STATUS_NO_MEMORY;
4379 /* first check own info, then other domains */
4380 fti = talloc(mem_ctx, struct ForestTrustInfo);
4381 if (!fti) {
4382 return NT_STATUS_NO_MEMORY;
4385 nt_status = own_ft_info(p_state, fti);
4386 if (!NT_STATUS_IS_OK(nt_status)) {
4387 return nt_status;
4390 nt_status = check_ft_info(c_info, p_state->domain_dns,
4391 fti, nfti, c_info);
4392 if (!NT_STATUS_IS_OK(nt_status)) {
4393 return nt_status;
4396 for (i = 0; i < num_res; i++) {
4397 fti = talloc(mem_ctx, struct ForestTrustInfo);
4398 if (!fti) {
4399 return NT_STATUS_NO_MEMORY;
4402 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4403 if (!NT_STATUS_IS_OK(nt_status)) {
4404 if (NT_STATUS_EQUAL(nt_status,
4405 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4406 continue;
4408 return nt_status;
4411 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4412 "trustPartner", NULL);
4413 if (!td_name) {
4414 return NT_STATUS_INVALID_DOMAIN_STATE;
4417 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4418 if (!NT_STATUS_IS_OK(nt_status)) {
4419 return nt_status;
4423 *r->out.collision_info = c_info;
4425 if (r->in.check_only != 0) {
4426 return NT_STATUS_OK;
4429 /* not just a check, write info back */
4431 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4432 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4433 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4434 return NT_STATUS_INVALID_PARAMETER;
4437 msg = ldb_msg_new(mem_ctx);
4438 if (msg == NULL) {
4439 return NT_STATUS_NO_MEMORY;
4442 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4443 if (!msg->dn) {
4444 return NT_STATUS_NO_MEMORY;
4447 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4448 LDB_FLAG_MOD_REPLACE, NULL);
4449 if (ret != LDB_SUCCESS) {
4450 return NT_STATUS_NO_MEMORY;
4452 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4453 &ft_blob, NULL);
4454 if (ret != LDB_SUCCESS) {
4455 return NT_STATUS_NO_MEMORY;
4458 ret = ldb_modify(p_state->sam_ldb, msg);
4459 if (ret != LDB_SUCCESS) {
4460 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4461 ldb_errstring(p_state->sam_ldb)));
4463 switch (ret) {
4464 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4465 return NT_STATUS_ACCESS_DENIED;
4466 default:
4467 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4471 return NT_STATUS_OK;
4475 lsa_CREDRRENAME
4477 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4478 struct lsa_CREDRRENAME *r)
4480 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4486 lsa_LSAROPENPOLICYSCE
4488 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4489 struct lsa_LSAROPENPOLICYSCE *r)
4491 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4496 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4498 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4499 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4501 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4506 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4508 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4509 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4511 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4516 lsa_LSARADTREPORTSECURITYEVENT
4518 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4519 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4521 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4525 /* include the generated boilerplate */
4526 #include "librpc/gen_ndr/ndr_lsa_s.c"
4530 /*****************************************
4531 NOTE! The remaining calls below were
4532 removed in w2k3, so the DCESRV_FAULT()
4533 replies are the correct implementation. Do
4534 not try and fill these in with anything else
4535 ******************************************/
4538 dssetup_DsRoleDnsNameToFlatName
4540 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4541 struct dssetup_DsRoleDnsNameToFlatName *r)
4543 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4548 dssetup_DsRoleDcAsDc
4550 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4551 struct dssetup_DsRoleDcAsDc *r)
4553 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4558 dssetup_DsRoleDcAsReplica
4560 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4561 struct dssetup_DsRoleDcAsReplica *r)
4563 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4568 dssetup_DsRoleDemoteDc
4570 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4571 struct dssetup_DsRoleDemoteDc *r)
4573 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4578 dssetup_DsRoleGetDcOperationProgress
4580 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4581 struct dssetup_DsRoleGetDcOperationProgress *r)
4583 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4588 dssetup_DsRoleGetDcOperationResults
4590 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4591 struct dssetup_DsRoleGetDcOperationResults *r)
4593 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4598 dssetup_DsRoleCancel
4600 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4601 struct dssetup_DsRoleCancel *r)
4603 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4608 dssetup_DsRoleServerSaveStateForUpgrade
4610 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4611 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4613 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4618 dssetup_DsRoleUpgradeDownlevelServer
4620 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4621 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4623 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4628 dssetup_DsRoleAbortDownlevelServerUpgrade
4630 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4631 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4633 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4637 /* include the generated boilerplate */
4638 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4640 NTSTATUS dcerpc_server_lsa_init(void)
4642 NTSTATUS ret;
4644 ret = dcerpc_server_dssetup_init();
4645 if (!NT_STATUS_IS_OK(ret)) {
4646 return ret;
4648 ret = dcerpc_server_lsarpc_init();
4649 if (!NT_STATUS_IS_OK(ret)) {
4650 return ret;
4652 return ret;