s4:librpc/rpc: don't do async requests if gensec doesn't support async replies (bug...
[Samba/gebeck_regimport.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
blobbdd0777757825f8b13ed565fc9b3c6de25982d3b
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 = dce_call->conn->endpoint->ep_description->transport;
148 struct dcesrv_handle *h;
150 if (transport != NCACN_NP && transport != NCALRPC) {
151 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
154 *r->out.handle = *r->in.handle;
156 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
158 talloc_free(h);
160 ZERO_STRUCTP(r->out.handle);
162 return NT_STATUS_OK;
167 lsa_Delete
169 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
170 struct lsa_Delete *r)
172 return NT_STATUS_NOT_SUPPORTED;
177 lsa_DeleteObject
179 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
180 struct lsa_DeleteObject *r)
182 struct dcesrv_handle *h;
183 int ret;
185 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
187 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
188 struct lsa_secret_state *secret_state = h->data;
190 /* Ensure user is permitted to delete this... */
191 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
193 case SECURITY_SYSTEM:
194 case SECURITY_ADMINISTRATOR:
195 break;
196 default:
197 /* Users and anonymous are not allowed to delete things */
198 return NT_STATUS_ACCESS_DENIED;
201 ret = ldb_delete(secret_state->sam_ldb,
202 secret_state->secret_dn);
203 if (ret != LDB_SUCCESS) {
204 return NT_STATUS_INVALID_HANDLE;
207 ZERO_STRUCTP(r->out.handle);
209 return NT_STATUS_OK;
211 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
212 struct lsa_trusted_domain_state *trusted_domain_state =
213 talloc_get_type(h->data, struct lsa_trusted_domain_state);
214 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
215 if (ret != LDB_SUCCESS) {
216 return NT_STATUS_INTERNAL_DB_CORRUPTION;
219 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
220 trusted_domain_state->trusted_domain_dn);
221 if (ret != LDB_SUCCESS) {
222 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
223 return NT_STATUS_INVALID_HANDLE;
226 if (trusted_domain_state->trusted_domain_user_dn) {
227 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
228 trusted_domain_state->trusted_domain_user_dn);
229 if (ret != LDB_SUCCESS) {
230 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
231 return NT_STATUS_INVALID_HANDLE;
235 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
236 if (ret != LDB_SUCCESS) {
237 return NT_STATUS_INTERNAL_DB_CORRUPTION;
240 ZERO_STRUCTP(r->out.handle);
242 return NT_STATUS_OK;
244 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
245 struct lsa_RightSet *rights;
246 struct lsa_account_state *astate;
247 struct lsa_EnumAccountRights r2;
248 NTSTATUS status;
250 rights = talloc(mem_ctx, struct lsa_RightSet);
252 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
254 astate = h->data;
256 r2.in.handle = &astate->policy->handle->wire_handle;
257 r2.in.sid = astate->account_sid;
258 r2.out.rights = rights;
260 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
261 but we have a LSA_HANDLE_ACCOUNT here, so this call
262 will always fail */
263 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
264 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
265 return NT_STATUS_OK;
268 if (!NT_STATUS_IS_OK(status)) {
269 return status;
272 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
273 LDB_FLAG_MOD_DELETE, astate->account_sid,
274 r2.out.rights);
275 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
276 return NT_STATUS_OK;
279 if (!NT_STATUS_IS_OK(status)) {
280 return status;
283 ZERO_STRUCTP(r->out.handle);
285 return NT_STATUS_OK;
288 return NT_STATUS_INVALID_HANDLE;
293 lsa_EnumPrivs
295 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
296 struct lsa_EnumPrivs *r)
298 struct dcesrv_handle *h;
299 struct lsa_policy_state *state;
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 state = h->data;
308 i = *r->in.resume_handle;
310 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
311 r->out.privs->count < r->in.max_count) {
312 struct lsa_PrivEntry *e;
313 privname = sec_privilege_name(priv);
314 r->out.privs->privs = talloc_realloc(r->out.privs,
315 r->out.privs->privs,
316 struct lsa_PrivEntry,
317 r->out.privs->count+1);
318 if (r->out.privs->privs == NULL) {
319 return NT_STATUS_NO_MEMORY;
321 e = &r->out.privs->privs[r->out.privs->count];
322 e->luid.low = priv;
323 e->luid.high = 0;
324 e->name.string = privname;
325 r->out.privs->count++;
326 i++;
329 *r->out.resume_handle = i;
331 return NT_STATUS_OK;
336 lsa_QuerySecObj
338 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
339 struct lsa_QuerySecurity *r)
341 struct dcesrv_handle *h;
342 struct security_descriptor *sd;
343 NTSTATUS status;
344 struct dom_sid *sid;
346 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
348 sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
350 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
351 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
352 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
353 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid,
354 LSA_ACCOUNT_ALL_ACCESS);
355 } else {
356 return NT_STATUS_INVALID_HANDLE;
358 NT_STATUS_NOT_OK_RETURN(status);
360 (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
361 NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
363 (*r->out.sdbuf)->sd = sd;
365 return NT_STATUS_OK;
370 lsa_SetSecObj
372 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
373 struct lsa_SetSecObj *r)
375 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
380 lsa_ChangePassword
382 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
383 struct lsa_ChangePassword *r)
385 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
389 dssetup_DsRoleGetPrimaryDomainInformation
391 This is not an LSA call, but is the only call left on the DSSETUP
392 pipe (after the pipe was truncated), and needs lsa_get_policy_state
394 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
395 TALLOC_CTX *mem_ctx,
396 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
398 union dssetup_DsRoleInfo *info;
400 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
401 W_ERROR_HAVE_NO_MEMORY(info);
403 switch (r->in.level) {
404 case DS_ROLE_BASIC_INFORMATION:
406 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
407 uint32_t flags = 0;
408 const char *domain = NULL;
409 const char *dns_domain = NULL;
410 const char *forest = NULL;
411 struct GUID domain_guid;
412 struct lsa_policy_state *state;
414 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
415 if (!NT_STATUS_IS_OK(status)) {
416 return ntstatus_to_werror(status);
419 ZERO_STRUCT(domain_guid);
421 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
422 case ROLE_STANDALONE:
423 role = DS_ROLE_STANDALONE_SERVER;
424 break;
425 case ROLE_DOMAIN_MEMBER:
426 role = DS_ROLE_MEMBER_SERVER;
427 break;
428 case ROLE_ACTIVE_DIRECTORY_DC:
429 if (samdb_is_pdc(state->sam_ldb)) {
430 role = DS_ROLE_PRIMARY_DC;
431 } else {
432 role = DS_ROLE_BACKUP_DC;
434 break;
437 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
438 case ROLE_STANDALONE:
439 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
440 W_ERROR_HAVE_NO_MEMORY(domain);
441 break;
442 case ROLE_DOMAIN_MEMBER:
443 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
444 W_ERROR_HAVE_NO_MEMORY(domain);
445 /* TODO: what is with dns_domain and forest and guid? */
446 break;
447 case ROLE_ACTIVE_DIRECTORY_DC:
448 flags = DS_ROLE_PRIMARY_DS_RUNNING;
450 if (state->mixed_domain == 1) {
451 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
454 domain = state->domain_name;
455 dns_domain = state->domain_dns;
456 forest = state->forest_dns;
458 domain_guid = state->domain_guid;
459 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
460 break;
463 info->basic.role = role;
464 info->basic.flags = flags;
465 info->basic.domain = domain;
466 info->basic.dns_domain = dns_domain;
467 info->basic.forest = forest;
468 info->basic.domain_guid = domain_guid;
470 r->out.info = info;
471 return WERR_OK;
473 case DS_ROLE_UPGRADE_STATUS:
475 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
476 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
478 r->out.info = info;
479 return WERR_OK;
481 case DS_ROLE_OP_STATUS:
483 info->opstatus.status = DS_ROLE_OP_IDLE;
485 r->out.info = info;
486 return WERR_OK;
488 default:
489 return WERR_INVALID_PARAM;
494 fill in the AccountDomain info
496 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
497 struct lsa_DomainInfo *info)
499 info->name.string = state->domain_name;
500 info->sid = state->domain_sid;
502 return NT_STATUS_OK;
506 fill in the DNS domain info
508 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
509 struct lsa_DnsDomainInfo *info)
511 info->name.string = state->domain_name;
512 info->sid = state->domain_sid;
513 info->dns_domain.string = state->domain_dns;
514 info->dns_forest.string = state->forest_dns;
515 info->domain_guid = state->domain_guid;
517 return NT_STATUS_OK;
521 lsa_QueryInfoPolicy2
523 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
524 struct lsa_QueryInfoPolicy2 *r)
526 struct lsa_policy_state *state;
527 struct dcesrv_handle *h;
528 union lsa_PolicyInformation *info;
530 *r->out.info = NULL;
532 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
534 state = h->data;
536 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
537 if (!info) {
538 return NT_STATUS_NO_MEMORY;
540 *r->out.info = info;
542 switch (r->in.level) {
543 case LSA_POLICY_INFO_AUDIT_LOG:
544 /* we don't need to fill in any of this */
545 ZERO_STRUCT(info->audit_log);
546 return NT_STATUS_OK;
547 case LSA_POLICY_INFO_AUDIT_EVENTS:
548 /* we don't need to fill in any of this */
549 ZERO_STRUCT(info->audit_events);
550 return NT_STATUS_OK;
551 case LSA_POLICY_INFO_PD:
552 /* we don't need to fill in any of this */
553 ZERO_STRUCT(info->pd);
554 return NT_STATUS_OK;
556 case LSA_POLICY_INFO_DOMAIN:
557 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
558 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
559 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
560 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
561 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
563 case LSA_POLICY_INFO_ROLE:
564 info->role.role = LSA_ROLE_PRIMARY;
565 return NT_STATUS_OK;
567 case LSA_POLICY_INFO_DNS:
568 case LSA_POLICY_INFO_DNS_INT:
569 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
571 case LSA_POLICY_INFO_REPLICA:
572 ZERO_STRUCT(info->replica);
573 return NT_STATUS_OK;
575 case LSA_POLICY_INFO_QUOTA:
576 ZERO_STRUCT(info->quota);
577 return NT_STATUS_OK;
579 case LSA_POLICY_INFO_MOD:
580 case LSA_POLICY_INFO_AUDIT_FULL_SET:
581 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
582 /* windows gives INVALID_PARAMETER */
583 *r->out.info = NULL;
584 return NT_STATUS_INVALID_PARAMETER;
587 *r->out.info = NULL;
588 return NT_STATUS_INVALID_INFO_CLASS;
592 lsa_QueryInfoPolicy
594 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
595 struct lsa_QueryInfoPolicy *r)
597 struct lsa_QueryInfoPolicy2 r2;
598 NTSTATUS status;
600 ZERO_STRUCT(r2);
602 r2.in.handle = r->in.handle;
603 r2.in.level = r->in.level;
604 r2.out.info = r->out.info;
606 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
608 return status;
612 lsa_SetInfoPolicy
614 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
615 struct lsa_SetInfoPolicy *r)
617 /* need to support this */
618 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
623 lsa_ClearAuditLog
625 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
626 struct lsa_ClearAuditLog *r)
628 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
633 lsa_CreateAccount
635 This call does not seem to have any long-term effects, hence no database operations
637 we need to talk to the MS product group to find out what this account database means!
639 answer is that the lsa database is totally separate from the SAM and
640 ldap databases. We are going to need a separate ldb to store these
641 accounts. The SIDs on this account bear no relation to the SIDs in
644 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
645 struct lsa_CreateAccount *r)
647 struct lsa_account_state *astate;
649 struct lsa_policy_state *state;
650 struct dcesrv_handle *h, *ah;
652 ZERO_STRUCTP(r->out.acct_handle);
654 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
656 state = h->data;
658 astate = talloc(dce_call->conn, struct lsa_account_state);
659 if (astate == NULL) {
660 return NT_STATUS_NO_MEMORY;
663 astate->account_sid = dom_sid_dup(astate, r->in.sid);
664 if (astate->account_sid == NULL) {
665 talloc_free(astate);
666 return NT_STATUS_NO_MEMORY;
669 astate->policy = talloc_reference(astate, state);
670 astate->access_mask = r->in.access_mask;
672 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
673 if (!ah) {
674 talloc_free(astate);
675 return NT_STATUS_NO_MEMORY;
678 ah->data = talloc_steal(ah, astate);
680 *r->out.acct_handle = ah->wire_handle;
682 return NT_STATUS_OK;
687 lsa_EnumAccounts
689 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
690 struct lsa_EnumAccounts *r)
692 struct dcesrv_handle *h;
693 struct lsa_policy_state *state;
694 int ret;
695 struct ldb_message **res;
696 const char * const attrs[] = { "objectSid", NULL};
697 uint32_t count, i;
699 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
701 state = h->data;
703 /* NOTE: This call must only return accounts that have at least
704 one privilege set
706 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
707 "(&(objectSid=*)(privilege=*))");
708 if (ret < 0) {
709 return NT_STATUS_INTERNAL_DB_CORRUPTION;
712 if (*r->in.resume_handle >= ret) {
713 return NT_STATUS_NO_MORE_ENTRIES;
716 count = ret - *r->in.resume_handle;
717 if (count > r->in.num_entries) {
718 count = r->in.num_entries;
721 if (count == 0) {
722 return NT_STATUS_NO_MORE_ENTRIES;
725 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
726 if (r->out.sids->sids == NULL) {
727 return NT_STATUS_NO_MEMORY;
730 for (i=0;i<count;i++) {
731 r->out.sids->sids[i].sid =
732 samdb_result_dom_sid(r->out.sids->sids,
733 res[i + *r->in.resume_handle],
734 "objectSid");
735 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
738 r->out.sids->num_sids = count;
739 *r->out.resume_handle = count + *r->in.resume_handle;
741 return NT_STATUS_OK;
745 /* This decrypts and returns Trusted Domain Auth Information Internal data */
746 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
747 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
748 struct trustDomainPasswords *auth_struct)
750 DATA_BLOB session_key = data_blob(NULL, 0);
751 enum ndr_err_code ndr_err;
752 NTSTATUS nt_status;
754 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
755 if (!NT_STATUS_IS_OK(nt_status)) {
756 return nt_status;
759 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
760 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
761 auth_struct,
762 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
763 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
764 return NT_STATUS_INVALID_PARAMETER;
767 return NT_STATUS_OK;
770 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
771 TALLOC_CTX *mem_ctx,
772 struct trustAuthInOutBlob *iopw,
773 DATA_BLOB *trustauth_blob)
775 enum ndr_err_code ndr_err;
777 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
778 iopw,
779 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
780 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
781 return NT_STATUS_INVALID_PARAMETER;
784 return NT_STATUS_OK;
787 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
788 struct ldb_context *sam_ldb,
789 struct ldb_dn *base_dn,
790 const char *netbios_name,
791 struct trustAuthInOutBlob *in,
792 struct ldb_dn **user_dn)
794 struct ldb_message *msg;
795 struct ldb_dn *dn;
796 uint32_t i;
797 int ret;
799 dn = ldb_dn_copy(mem_ctx, base_dn);
800 if (!dn) {
801 return NT_STATUS_NO_MEMORY;
803 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
804 return NT_STATUS_NO_MEMORY;
807 msg = ldb_msg_new(mem_ctx);
808 if (!msg) {
809 return NT_STATUS_NO_MEMORY;
811 msg->dn = dn;
813 ret = ldb_msg_add_string(msg, "objectClass", "user");
814 if (ret != LDB_SUCCESS) {
815 return NT_STATUS_NO_MEMORY;
818 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
819 if (ret != LDB_SUCCESS) {
820 return NT_STATUS_NO_MEMORY;
823 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
824 UF_INTERDOMAIN_TRUST_ACCOUNT);
825 if (ret != LDB_SUCCESS) {
826 return NT_STATUS_NO_MEMORY;
829 for (i = 0; i < in->count; i++) {
830 const char *attribute;
831 struct ldb_val v;
832 switch (in->current.array[i].AuthType) {
833 case TRUST_AUTH_TYPE_NT4OWF:
834 attribute = "unicodePwd";
835 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
836 v.length = 16;
837 break;
838 case TRUST_AUTH_TYPE_CLEAR:
839 attribute = "clearTextPassword";
840 v.data = in->current.array[i].AuthInfo.clear.password;
841 v.length = in->current.array[i].AuthInfo.clear.size;
842 break;
843 default:
844 continue;
847 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
848 if (ret != LDB_SUCCESS) {
849 return NT_STATUS_NO_MEMORY;
853 /* create the trusted_domain user account */
854 ret = ldb_add(sam_ldb, msg);
855 if (ret != LDB_SUCCESS) {
856 DEBUG(0,("Failed to create user record %s: %s\n",
857 ldb_dn_get_linearized(msg->dn),
858 ldb_errstring(sam_ldb)));
860 switch (ret) {
861 case LDB_ERR_ENTRY_ALREADY_EXISTS:
862 return NT_STATUS_DOMAIN_EXISTS;
863 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
864 return NT_STATUS_ACCESS_DENIED;
865 default:
866 return NT_STATUS_INTERNAL_DB_CORRUPTION;
870 if (user_dn) {
871 *user_dn = dn;
873 return NT_STATUS_OK;
877 lsa_CreateTrustedDomainEx2
879 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
880 TALLOC_CTX *mem_ctx,
881 struct lsa_CreateTrustedDomainEx2 *r,
882 int op,
883 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
885 struct dcesrv_handle *policy_handle;
886 struct lsa_policy_state *policy_state;
887 struct lsa_trusted_domain_state *trusted_domain_state;
888 struct dcesrv_handle *handle;
889 struct ldb_message **msgs, *msg;
890 const char *attrs[] = {
891 NULL
893 const char *netbios_name;
894 const char *dns_name;
895 const char *name;
896 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
897 struct trustDomainPasswords auth_struct;
898 int ret;
899 NTSTATUS nt_status;
900 struct ldb_context *sam_ldb;
902 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
903 ZERO_STRUCTP(r->out.trustdom_handle);
905 policy_state = policy_handle->data;
906 sam_ldb = policy_state->sam_ldb;
908 netbios_name = r->in.info->netbios_name.string;
909 if (!netbios_name) {
910 return NT_STATUS_INVALID_PARAMETER;
913 dns_name = r->in.info->domain_name.string;
915 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
916 if (!trusted_domain_state) {
917 return NT_STATUS_NO_MEMORY;
919 trusted_domain_state->policy = policy_state;
921 if (strcasecmp(netbios_name, "BUILTIN") == 0
922 || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
923 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
924 return NT_STATUS_INVALID_PARAMETER;
927 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
928 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
929 || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
930 || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
931 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
932 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
935 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
936 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
937 /* No secrets are created at this time, for this function */
938 auth_struct.outgoing.count = 0;
939 auth_struct.incoming.count = 0;
940 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
941 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
942 r->in.auth_info_internal->auth_blob.size);
943 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
944 &auth_blob, &auth_struct);
945 if (!NT_STATUS_IS_OK(nt_status)) {
946 return nt_status;
948 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
950 if (unencrypted_auth_info->incoming_count > 1) {
951 return NT_STATUS_INVALID_PARAMETER;
954 /* more investigation required here, do not create secrets for
955 * now */
956 auth_struct.outgoing.count = 0;
957 auth_struct.incoming.count = 0;
958 } else {
959 return NT_STATUS_INVALID_PARAMETER;
962 if (auth_struct.incoming.count) {
963 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
964 &auth_struct.incoming,
965 &trustAuthIncoming);
966 if (!NT_STATUS_IS_OK(nt_status)) {
967 return nt_status;
969 } else {
970 trustAuthIncoming = data_blob(NULL, 0);
973 if (auth_struct.outgoing.count) {
974 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
975 &auth_struct.outgoing,
976 &trustAuthOutgoing);
977 if (!NT_STATUS_IS_OK(nt_status)) {
978 return nt_status;
980 } else {
981 trustAuthOutgoing = data_blob(NULL, 0);
984 ret = ldb_transaction_start(sam_ldb);
985 if (ret != LDB_SUCCESS) {
986 return NT_STATUS_INTERNAL_DB_CORRUPTION;
989 if (dns_name) {
990 char *dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
991 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
992 /* search for the trusted_domain record */
993 ret = gendb_search(sam_ldb,
994 mem_ctx, policy_state->system_dn, &msgs, attrs,
995 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
996 dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
997 if (ret > 0) {
998 ldb_transaction_cancel(sam_ldb);
999 return NT_STATUS_OBJECT_NAME_COLLISION;
1001 } else {
1002 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1003 /* search for the trusted_domain record */
1004 ret = gendb_search(sam_ldb,
1005 mem_ctx, policy_state->system_dn, &msgs, attrs,
1006 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1007 netbios_encoded, netbios_encoded, netbios_encoded);
1008 if (ret > 0) {
1009 ldb_transaction_cancel(sam_ldb);
1010 return NT_STATUS_OBJECT_NAME_COLLISION;
1014 if (ret < 0 ) {
1015 ldb_transaction_cancel(sam_ldb);
1016 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1019 name = dns_name ? dns_name : netbios_name;
1021 msg = ldb_msg_new(mem_ctx);
1022 if (msg == NULL) {
1023 return NT_STATUS_NO_MEMORY;
1026 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1027 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1028 ldb_transaction_cancel(sam_ldb);
1029 return NT_STATUS_NO_MEMORY;
1032 ldb_msg_add_string(msg, "flatname", netbios_name);
1034 if (r->in.info->sid) {
1035 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1036 if (ret != LDB_SUCCESS) {
1037 ldb_transaction_cancel(sam_ldb);
1038 return NT_STATUS_INVALID_PARAMETER;
1042 ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1044 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1046 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1048 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1050 if (dns_name) {
1051 ldb_msg_add_string(msg, "trustPartner", dns_name);
1054 if (trustAuthIncoming.data) {
1055 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1056 if (ret != LDB_SUCCESS) {
1057 ldb_transaction_cancel(sam_ldb);
1058 return NT_STATUS_NO_MEMORY;
1061 if (trustAuthOutgoing.data) {
1062 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1063 if (ret != LDB_SUCCESS) {
1064 ldb_transaction_cancel(sam_ldb);
1065 return NT_STATUS_NO_MEMORY;
1069 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1071 /* create the trusted_domain */
1072 ret = ldb_add(sam_ldb, msg);
1073 switch (ret) {
1074 case LDB_SUCCESS:
1075 break;
1076 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1077 ldb_transaction_cancel(sam_ldb);
1078 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1079 ldb_dn_get_linearized(msg->dn),
1080 ldb_errstring(sam_ldb)));
1081 return NT_STATUS_DOMAIN_EXISTS;
1082 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1083 ldb_transaction_cancel(sam_ldb);
1084 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1085 ldb_dn_get_linearized(msg->dn),
1086 ldb_errstring(sam_ldb)));
1087 return NT_STATUS_ACCESS_DENIED;
1088 default:
1089 ldb_transaction_cancel(sam_ldb);
1090 DEBUG(0,("Failed to create user record %s: %s\n",
1091 ldb_dn_get_linearized(msg->dn),
1092 ldb_errstring(sam_ldb)));
1093 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1096 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1097 struct ldb_dn *user_dn;
1098 /* Inbound trusts must also create a cn=users object to match */
1099 nt_status = add_trust_user(mem_ctx, sam_ldb,
1100 policy_state->domain_dn,
1101 netbios_name,
1102 &auth_struct.incoming,
1103 &user_dn);
1104 if (!NT_STATUS_IS_OK(nt_status)) {
1105 ldb_transaction_cancel(sam_ldb);
1106 return nt_status;
1109 /* save the trust user dn */
1110 trusted_domain_state->trusted_domain_user_dn
1111 = talloc_steal(trusted_domain_state, user_dn);
1114 ret = ldb_transaction_commit(sam_ldb);
1115 if (ret != LDB_SUCCESS) {
1116 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1119 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1120 if (!handle) {
1121 return NT_STATUS_NO_MEMORY;
1124 handle->data = talloc_steal(handle, trusted_domain_state);
1126 trusted_domain_state->access_mask = r->in.access_mask;
1127 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1129 *r->out.trustdom_handle = handle->wire_handle;
1131 return NT_STATUS_OK;
1135 lsa_CreateTrustedDomainEx2
1137 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1138 TALLOC_CTX *mem_ctx,
1139 struct lsa_CreateTrustedDomainEx2 *r)
1141 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1144 lsa_CreateTrustedDomainEx
1146 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1147 TALLOC_CTX *mem_ctx,
1148 struct lsa_CreateTrustedDomainEx *r)
1150 struct lsa_CreateTrustedDomainEx2 r2;
1152 r2.in.policy_handle = r->in.policy_handle;
1153 r2.in.info = r->in.info;
1154 r2.out.trustdom_handle = r->out.trustdom_handle;
1155 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1159 lsa_CreateTrustedDomain
1161 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1162 struct lsa_CreateTrustedDomain *r)
1164 struct lsa_CreateTrustedDomainEx2 r2;
1166 r2.in.policy_handle = r->in.policy_handle;
1167 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1168 if (!r2.in.info) {
1169 return NT_STATUS_NO_MEMORY;
1172 r2.in.info->domain_name.string = NULL;
1173 r2.in.info->netbios_name = r->in.info->name;
1174 r2.in.info->sid = r->in.info->sid;
1175 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1176 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1177 r2.in.info->trust_attributes = 0;
1179 r2.in.access_mask = r->in.access_mask;
1180 r2.out.trustdom_handle = r->out.trustdom_handle;
1182 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1187 lsa_OpenTrustedDomain
1189 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1190 struct lsa_OpenTrustedDomain *r)
1192 struct dcesrv_handle *policy_handle;
1194 struct lsa_policy_state *policy_state;
1195 struct lsa_trusted_domain_state *trusted_domain_state;
1196 struct dcesrv_handle *handle;
1197 struct ldb_message **msgs;
1198 const char *attrs[] = {
1199 "trustDirection",
1200 "flatname",
1201 NULL
1204 const char *sid_string;
1205 int ret;
1207 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1208 ZERO_STRUCTP(r->out.trustdom_handle);
1209 policy_state = policy_handle->data;
1211 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1212 if (!trusted_domain_state) {
1213 return NT_STATUS_NO_MEMORY;
1215 trusted_domain_state->policy = policy_state;
1217 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1218 if (!sid_string) {
1219 return NT_STATUS_NO_MEMORY;
1222 /* search for the trusted_domain record */
1223 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1224 mem_ctx, policy_state->system_dn, &msgs, attrs,
1225 "(&(securityIdentifier=%s)(objectclass=trustedDomain))",
1226 sid_string);
1227 if (ret == 0) {
1228 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1231 if (ret != 1) {
1232 DEBUG(0,("Found %d records matching DN %s\n", ret,
1233 ldb_dn_get_linearized(policy_state->system_dn)));
1234 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1237 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1239 trusted_domain_state->trusted_domain_user_dn = NULL;
1241 if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1242 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1243 /* search for the trusted_domain record */
1244 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1245 mem_ctx, policy_state->domain_dn, &msgs, attrs,
1246 "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%u))",
1247 flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1248 if (ret == 1) {
1249 trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1252 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1253 if (!handle) {
1254 return NT_STATUS_NO_MEMORY;
1257 handle->data = talloc_steal(handle, trusted_domain_state);
1259 trusted_domain_state->access_mask = r->in.access_mask;
1260 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1262 *r->out.trustdom_handle = handle->wire_handle;
1264 return NT_STATUS_OK;
1269 lsa_OpenTrustedDomainByName
1271 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1272 TALLOC_CTX *mem_ctx,
1273 struct lsa_OpenTrustedDomainByName *r)
1275 struct dcesrv_handle *policy_handle;
1277 struct lsa_policy_state *policy_state;
1278 struct lsa_trusted_domain_state *trusted_domain_state;
1279 struct dcesrv_handle *handle;
1280 struct ldb_message **msgs;
1281 const char *attrs[] = {
1282 NULL
1284 char *td_name;
1285 int ret;
1287 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1288 ZERO_STRUCTP(r->out.trustdom_handle);
1289 policy_state = policy_handle->data;
1291 if (!r->in.name.string) {
1292 return NT_STATUS_INVALID_PARAMETER;
1295 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1296 if (!trusted_domain_state) {
1297 return NT_STATUS_NO_MEMORY;
1299 trusted_domain_state->policy = policy_state;
1301 /* search for the trusted_domain record */
1302 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1303 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1304 mem_ctx, policy_state->system_dn, &msgs, attrs,
1305 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1306 "(objectclass=trustedDomain))",
1307 td_name, td_name, td_name);
1308 if (ret == 0) {
1309 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1312 if (ret != 1) {
1313 DEBUG(0,("Found %d records matching DN %s\n", ret,
1314 ldb_dn_get_linearized(policy_state->system_dn)));
1315 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1318 /* TODO: perform access checks */
1320 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1322 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1323 if (!handle) {
1324 return NT_STATUS_NO_MEMORY;
1327 handle->data = talloc_steal(handle, trusted_domain_state);
1329 trusted_domain_state->access_mask = r->in.access_mask;
1330 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1332 *r->out.trustdom_handle = handle->wire_handle;
1334 return NT_STATUS_OK;
1340 lsa_SetTrustedDomainInfo
1342 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1343 struct lsa_SetTrustedDomainInfo *r)
1345 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1350 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1351 * otherwise at least one must be provided */
1352 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1353 struct ldb_dn *basedn, const char *dns_domain,
1354 const char *netbios, struct dom_sid2 *sid,
1355 struct ldb_message ***msgs)
1357 const char *attrs[] = { "flatname", "trustPartner",
1358 "securityIdentifier", "trustDirection",
1359 "trustType", "trustAttributes",
1360 "trustPosixOffset",
1361 "msDs-supportedEncryptionTypes", NULL };
1362 char *dns = NULL;
1363 char *nbn = NULL;
1364 char *sidstr = NULL;
1365 char *filter;
1366 int ret;
1369 if (dns_domain || netbios || sid) {
1370 filter = talloc_strdup(mem_ctx,
1371 "(&(objectclass=trustedDomain)(|");
1372 } else {
1373 filter = talloc_strdup(mem_ctx,
1374 "(objectclass=trustedDomain)");
1376 if (!filter) {
1377 return NT_STATUS_NO_MEMORY;
1380 if (dns_domain) {
1381 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1382 if (!dns) {
1383 return NT_STATUS_NO_MEMORY;
1385 filter = talloc_asprintf_append(filter,
1386 "(trustPartner=%s)", dns);
1387 if (!filter) {
1388 return NT_STATUS_NO_MEMORY;
1391 if (netbios) {
1392 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1393 if (!nbn) {
1394 return NT_STATUS_NO_MEMORY;
1396 filter = talloc_asprintf_append(filter,
1397 "(flatname=%s)", nbn);
1398 if (!filter) {
1399 return NT_STATUS_NO_MEMORY;
1402 if (sid) {
1403 sidstr = dom_sid_string(mem_ctx, sid);
1404 if (!sidstr) {
1405 return NT_STATUS_INVALID_PARAMETER;
1407 filter = talloc_asprintf_append(filter,
1408 "(securityIdentifier=%s)",
1409 sidstr);
1410 if (!filter) {
1411 return NT_STATUS_NO_MEMORY;
1414 if (dns_domain || netbios || sid) {
1415 filter = talloc_asprintf_append(filter, "))");
1416 if (!filter) {
1417 return NT_STATUS_NO_MEMORY;
1421 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1422 if (ret == 0) {
1423 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1426 if (ret != 1) {
1427 return NT_STATUS_OBJECT_NAME_COLLISION;
1430 return NT_STATUS_OK;
1433 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1434 struct ldb_context *sam_ldb,
1435 struct ldb_message *orig,
1436 struct ldb_message *dest,
1437 const char *attribute,
1438 uint32_t value,
1439 uint32_t *orig_value)
1441 const struct ldb_val *orig_val;
1442 uint32_t orig_uint = 0;
1443 unsigned int flags = 0;
1444 int ret;
1446 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1447 if (!orig_val || !orig_val->data) {
1448 /* add new attribute */
1449 flags = LDB_FLAG_MOD_ADD;
1451 } else {
1452 errno = 0;
1453 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1454 if (errno != 0 || orig_uint != value) {
1455 /* replace also if can't get value */
1456 flags = LDB_FLAG_MOD_REPLACE;
1460 if (flags == 0) {
1461 /* stored value is identical, nothing to change */
1462 goto done;
1465 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1466 if (ret != LDB_SUCCESS) {
1467 return NT_STATUS_NO_MEMORY;
1470 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1471 if (ret != LDB_SUCCESS) {
1472 return NT_STATUS_NO_MEMORY;
1475 done:
1476 if (orig_value) {
1477 *orig_value = orig_uint;
1479 return NT_STATUS_OK;
1482 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1483 struct ldb_context *sam_ldb,
1484 struct ldb_dn *base_dn,
1485 bool delete_user,
1486 const char *netbios_name,
1487 struct trustAuthInOutBlob *in)
1489 const char *attrs[] = { "userAccountControl", NULL };
1490 struct ldb_message **msgs;
1491 struct ldb_message *msg;
1492 uint32_t uac;
1493 uint32_t i;
1494 int ret;
1496 ret = gendb_search(sam_ldb, mem_ctx,
1497 base_dn, &msgs, attrs,
1498 "samAccountName=%s$", netbios_name);
1499 if (ret > 1) {
1500 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1503 if (ret == 0) {
1504 if (delete_user) {
1505 return NT_STATUS_OK;
1508 /* ok no existing user, add it from scratch */
1509 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1510 netbios_name, in, NULL);
1513 /* check user is what we are looking for */
1514 uac = ldb_msg_find_attr_as_uint(msgs[0],
1515 "userAccountControl", 0);
1516 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1517 return NT_STATUS_OBJECT_NAME_COLLISION;
1520 if (delete_user) {
1521 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1522 switch (ret) {
1523 case LDB_SUCCESS:
1524 return NT_STATUS_OK;
1525 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1526 return NT_STATUS_ACCESS_DENIED;
1527 default:
1528 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1532 /* entry exists, just modify secret if any */
1533 if (in == NULL || in->count == 0) {
1534 return NT_STATUS_OK;
1537 msg = ldb_msg_new(mem_ctx);
1538 if (!msg) {
1539 return NT_STATUS_NO_MEMORY;
1541 msg->dn = msgs[0]->dn;
1543 for (i = 0; i < in->count; i++) {
1544 const char *attribute;
1545 struct ldb_val v;
1546 switch (in->current.array[i].AuthType) {
1547 case TRUST_AUTH_TYPE_NT4OWF:
1548 attribute = "unicodePwd";
1549 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1550 v.length = 16;
1551 break;
1552 case TRUST_AUTH_TYPE_CLEAR:
1553 attribute = "clearTextPassword";
1554 v.data = in->current.array[i].AuthInfo.clear.password;
1555 v.length = in->current.array[i].AuthInfo.clear.size;
1556 break;
1557 default:
1558 continue;
1561 ret = ldb_msg_add_empty(msg, attribute,
1562 LDB_FLAG_MOD_REPLACE, NULL);
1563 if (ret != LDB_SUCCESS) {
1564 return NT_STATUS_NO_MEMORY;
1567 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1568 if (ret != LDB_SUCCESS) {
1569 return NT_STATUS_NO_MEMORY;
1573 /* create the trusted_domain user account */
1574 ret = ldb_modify(sam_ldb, msg);
1575 if (ret != LDB_SUCCESS) {
1576 DEBUG(0,("Failed to create user record %s: %s\n",
1577 ldb_dn_get_linearized(msg->dn),
1578 ldb_errstring(sam_ldb)));
1580 switch (ret) {
1581 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1582 return NT_STATUS_DOMAIN_EXISTS;
1583 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1584 return NT_STATUS_ACCESS_DENIED;
1585 default:
1586 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1590 return NT_STATUS_OK;
1594 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1595 struct dcesrv_handle *p_handle,
1596 TALLOC_CTX *mem_ctx,
1597 struct ldb_message *dom_msg,
1598 enum lsa_TrustDomInfoEnum level,
1599 union lsa_TrustedDomainInfo *info)
1601 struct lsa_policy_state *p_state = p_handle->data;
1602 uint32_t *posix_offset = NULL;
1603 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1604 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1605 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1606 uint32_t *enc_types = NULL;
1607 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1608 struct trustDomainPasswords auth_struct;
1609 struct trustAuthInOutBlob *current_passwords = NULL;
1610 NTSTATUS nt_status;
1611 struct ldb_message **msgs;
1612 struct ldb_message *msg;
1613 bool add_outgoing = false;
1614 bool add_incoming = false;
1615 bool del_outgoing = false;
1616 bool del_incoming = false;
1617 bool in_transaction = false;
1618 int ret;
1619 bool am_rodc;
1621 switch (level) {
1622 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1623 posix_offset = &info->posix_offset.posix_offset;
1624 break;
1625 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1626 info_ex = &info->info_ex;
1627 break;
1628 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1629 auth_info = &info->auth_info;
1630 break;
1631 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1632 posix_offset = &info->full_info.posix_offset.posix_offset;
1633 info_ex = &info->full_info.info_ex;
1634 auth_info = &info->full_info.auth_info;
1635 break;
1636 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1637 auth_info_int = &info->auth_info_internal;
1638 break;
1639 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1640 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1641 info_ex = &info->full_info_internal.info_ex;
1642 auth_info_int = &info->full_info_internal.auth_info;
1643 break;
1644 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1645 enc_types = &info->enc_types.enc_types;
1646 break;
1647 default:
1648 return NT_STATUS_INVALID_PARAMETER;
1651 if (auth_info) {
1652 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1653 &trustAuthIncoming,
1654 &trustAuthOutgoing);
1655 if (!NT_STATUS_IS_OK(nt_status)) {
1656 return nt_status;
1658 if (trustAuthIncoming.data) {
1659 /* This does the decode of some of this twice, but it is easier that way */
1660 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1661 auth_info->incoming_count,
1662 auth_info->incoming_current_auth_info,
1663 NULL,
1664 &current_passwords);
1665 if (!NT_STATUS_IS_OK(nt_status)) {
1666 return nt_status;
1671 /* decode auth_info_int if set */
1672 if (auth_info_int) {
1674 /* now decrypt blob */
1675 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1676 auth_info_int->auth_blob.size);
1678 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1679 &auth_blob, &auth_struct);
1680 if (!NT_STATUS_IS_OK(nt_status)) {
1681 return nt_status;
1685 if (info_ex) {
1686 /* verify data matches */
1687 if (info_ex->trust_attributes &
1688 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1689 /* TODO: check what behavior level we have */
1690 if (strcasecmp_m(p_state->domain_dns,
1691 p_state->forest_dns) != 0) {
1692 return NT_STATUS_INVALID_DOMAIN_STATE;
1696 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1697 if (ret == LDB_SUCCESS && am_rodc) {
1698 return NT_STATUS_NO_SUCH_DOMAIN;
1701 /* verify only one object matches the dns/netbios/sid
1702 * triplet and that this is the one we already have */
1703 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1704 p_state->system_dn,
1705 info_ex->domain_name.string,
1706 info_ex->netbios_name.string,
1707 info_ex->sid, &msgs);
1708 if (!NT_STATUS_IS_OK(nt_status)) {
1709 return nt_status;
1711 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1712 return NT_STATUS_OBJECT_NAME_COLLISION;
1714 talloc_free(msgs);
1717 /* TODO: should we fetch previous values from the existing entry
1718 * and append them ? */
1719 if (auth_info_int && auth_struct.incoming.count) {
1720 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1721 &auth_struct.incoming,
1722 &trustAuthIncoming);
1723 if (!NT_STATUS_IS_OK(nt_status)) {
1724 return nt_status;
1727 current_passwords = &auth_struct.incoming;
1729 } else {
1730 trustAuthIncoming = data_blob(NULL, 0);
1733 if (auth_info_int && auth_struct.outgoing.count) {
1734 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1735 &auth_struct.outgoing,
1736 &trustAuthOutgoing);
1737 if (!NT_STATUS_IS_OK(nt_status)) {
1738 return nt_status;
1740 } else {
1741 trustAuthOutgoing = data_blob(NULL, 0);
1744 msg = ldb_msg_new(mem_ctx);
1745 if (msg == NULL) {
1746 return NT_STATUS_NO_MEMORY;
1748 msg->dn = dom_msg->dn;
1750 if (posix_offset) {
1751 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1752 dom_msg, msg,
1753 "trustPosixOffset",
1754 *posix_offset, NULL);
1755 if (!NT_STATUS_IS_OK(nt_status)) {
1756 return nt_status;
1760 if (info_ex) {
1761 uint32_t origattrs;
1762 uint32_t origdir;
1763 int origtype;
1765 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1766 dom_msg, msg,
1767 "trustDirection",
1768 info_ex->trust_direction,
1769 &origdir);
1770 if (!NT_STATUS_IS_OK(nt_status)) {
1771 return nt_status;
1774 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1775 add_incoming = true;
1777 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1778 add_outgoing = true;
1781 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1782 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1783 del_incoming = true;
1785 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1786 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1787 del_outgoing = true;
1790 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1791 if (origtype == -1 || origtype != info_ex->trust_type) {
1792 DEBUG(1, ("Attempted to change trust type! "
1793 "Operation not handled\n"));
1794 return NT_STATUS_INVALID_PARAMETER;
1797 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1798 dom_msg, msg,
1799 "trustAttributes",
1800 info_ex->trust_attributes,
1801 &origattrs);
1802 if (!NT_STATUS_IS_OK(nt_status)) {
1803 return nt_status;
1805 /* TODO: check forestFunctionality from ldb opaque */
1806 /* TODO: check what is set makes sense */
1807 /* for now refuse changes */
1808 if (origattrs == -1 ||
1809 origattrs != info_ex->trust_attributes) {
1810 DEBUG(1, ("Attempted to change trust attributes! "
1811 "Operation not handled\n"));
1812 return NT_STATUS_INVALID_PARAMETER;
1816 if (enc_types) {
1817 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1818 dom_msg, msg,
1819 "msDS-SupportedEncryptionTypes",
1820 *enc_types, NULL);
1821 if (!NT_STATUS_IS_OK(nt_status)) {
1822 return nt_status;
1826 if (add_incoming && trustAuthIncoming.data) {
1827 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1828 LDB_FLAG_MOD_REPLACE, NULL);
1829 if (ret != LDB_SUCCESS) {
1830 return NT_STATUS_NO_MEMORY;
1832 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1833 &trustAuthIncoming, NULL);
1834 if (ret != LDB_SUCCESS) {
1835 return NT_STATUS_NO_MEMORY;
1838 if (add_outgoing && trustAuthOutgoing.data) {
1839 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1840 LDB_FLAG_MOD_REPLACE, NULL);
1841 if (ret != LDB_SUCCESS) {
1842 return NT_STATUS_NO_MEMORY;
1844 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1845 &trustAuthOutgoing, NULL);
1846 if (ret != LDB_SUCCESS) {
1847 return NT_STATUS_NO_MEMORY;
1851 /* start transaction */
1852 ret = ldb_transaction_start(p_state->sam_ldb);
1853 if (ret != LDB_SUCCESS) {
1854 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1856 in_transaction = true;
1858 if (msg->num_elements) {
1859 ret = ldb_modify(p_state->sam_ldb, msg);
1860 if (ret != LDB_SUCCESS) {
1861 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1862 ldb_dn_get_linearized(msg->dn),
1863 ldb_errstring(p_state->sam_ldb)));
1864 nt_status = dsdb_ldb_err_to_ntstatus(ret);
1865 goto done;
1869 if (add_incoming || del_incoming) {
1870 const char *netbios_name;
1872 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1873 "flatname", NULL);
1874 if (!netbios_name) {
1875 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1876 goto done;
1879 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
1880 nt_status = update_trust_user(mem_ctx,
1881 p_state->sam_ldb,
1882 p_state->domain_dn,
1883 del_incoming,
1884 netbios_name,
1885 current_passwords);
1886 if (!NT_STATUS_IS_OK(nt_status)) {
1887 goto done;
1891 /* ok, all fine, commit transaction and return */
1892 ret = ldb_transaction_commit(p_state->sam_ldb);
1893 if (ret != LDB_SUCCESS) {
1894 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1896 in_transaction = false;
1898 nt_status = NT_STATUS_OK;
1900 done:
1901 if (in_transaction) {
1902 ldb_transaction_cancel(p_state->sam_ldb);
1904 return nt_status;
1908 lsa_SetInfomrationTrustedDomain
1910 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1911 struct dcesrv_call_state *dce_call,
1912 TALLOC_CTX *mem_ctx,
1913 struct lsa_SetInformationTrustedDomain *r)
1915 struct dcesrv_handle *h;
1916 struct lsa_trusted_domain_state *td_state;
1917 struct ldb_message **msgs;
1918 NTSTATUS nt_status;
1920 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1921 LSA_HANDLE_TRUSTED_DOMAIN);
1923 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1925 /* get the trusted domain object */
1926 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1927 td_state->trusted_domain_dn,
1928 NULL, NULL, NULL, &msgs);
1929 if (!NT_STATUS_IS_OK(nt_status)) {
1930 if (NT_STATUS_EQUAL(nt_status,
1931 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1932 return nt_status;
1934 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1937 return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1938 msgs[0], r->in.level, r->in.info);
1943 lsa_DeleteTrustedDomain
1945 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1946 struct lsa_DeleteTrustedDomain *r)
1948 NTSTATUS status;
1949 struct lsa_OpenTrustedDomain opn;
1950 struct lsa_DeleteObject del;
1951 struct dcesrv_handle *h;
1953 opn.in.handle = r->in.handle;
1954 opn.in.sid = r->in.dom_sid;
1955 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1956 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1957 if (!opn.out.trustdom_handle) {
1958 return NT_STATUS_NO_MEMORY;
1960 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1961 if (!NT_STATUS_IS_OK(status)) {
1962 return status;
1965 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1966 talloc_steal(mem_ctx, h);
1968 del.in.handle = opn.out.trustdom_handle;
1969 del.out.handle = opn.out.trustdom_handle;
1970 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1971 if (!NT_STATUS_IS_OK(status)) {
1972 return status;
1974 return NT_STATUS_OK;
1977 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
1978 struct ldb_message *msg,
1979 struct lsa_TrustDomainInfoInfoEx *info_ex)
1981 info_ex->domain_name.string
1982 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1983 info_ex->netbios_name.string
1984 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1985 info_ex->sid
1986 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1987 info_ex->trust_direction
1988 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1989 info_ex->trust_type
1990 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1991 info_ex->trust_attributes
1992 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
1993 return NT_STATUS_OK;
1997 lsa_QueryTrustedDomainInfo
1999 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2000 struct lsa_QueryTrustedDomainInfo *r)
2002 union lsa_TrustedDomainInfo *info = NULL;
2003 struct dcesrv_handle *h;
2004 struct lsa_trusted_domain_state *trusted_domain_state;
2005 struct ldb_message *msg;
2006 int ret;
2007 struct ldb_message **res;
2008 const char *attrs[] = {
2009 "flatname",
2010 "trustPartner",
2011 "securityIdentifier",
2012 "trustDirection",
2013 "trustType",
2014 "trustAttributes",
2015 "msDs-supportedEncryptionTypes",
2016 NULL
2019 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2021 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2023 /* pull all the user attributes */
2024 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2025 trusted_domain_state->trusted_domain_dn, &res, attrs);
2026 if (ret != 1) {
2027 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2029 msg = res[0];
2031 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2032 if (!info) {
2033 return NT_STATUS_NO_MEMORY;
2035 *r->out.info = info;
2037 switch (r->in.level) {
2038 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2039 info->name.netbios_name.string
2040 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2041 break;
2042 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2043 info->posix_offset.posix_offset
2044 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2045 break;
2046 #if 0 /* Win2k3 doesn't implement this */
2047 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2048 r->out.info->info_basic.netbios_name.string
2049 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2050 r->out.info->info_basic.sid
2051 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2052 break;
2053 #endif
2054 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2055 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2057 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2058 ZERO_STRUCT(info->full_info);
2059 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2060 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2061 ZERO_STRUCT(info->full_info2_internal);
2062 info->full_info2_internal.posix_offset.posix_offset
2063 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2064 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2066 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2067 info->enc_types.enc_types
2068 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2069 break;
2071 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2072 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2073 /* oops, we don't want to return the info after all */
2074 talloc_free(info);
2075 *r->out.info = NULL;
2076 return NT_STATUS_INVALID_PARAMETER;
2077 default:
2078 /* oops, we don't want to return the info after all */
2079 talloc_free(info);
2080 *r->out.info = NULL;
2081 return NT_STATUS_INVALID_INFO_CLASS;
2084 return NT_STATUS_OK;
2089 lsa_QueryTrustedDomainInfoBySid
2091 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2092 struct lsa_QueryTrustedDomainInfoBySid *r)
2094 NTSTATUS status;
2095 struct lsa_OpenTrustedDomain opn;
2096 struct lsa_QueryTrustedDomainInfo query;
2097 struct dcesrv_handle *h;
2099 opn.in.handle = r->in.handle;
2100 opn.in.sid = r->in.dom_sid;
2101 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2102 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2103 if (!opn.out.trustdom_handle) {
2104 return NT_STATUS_NO_MEMORY;
2106 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2107 if (!NT_STATUS_IS_OK(status)) {
2108 return status;
2111 /* Ensure this handle goes away at the end of this call */
2112 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2113 talloc_steal(mem_ctx, h);
2115 query.in.trustdom_handle = opn.out.trustdom_handle;
2116 query.in.level = r->in.level;
2117 query.out.info = r->out.info;
2118 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2119 if (!NT_STATUS_IS_OK(status)) {
2120 return status;
2123 return NT_STATUS_OK;
2127 lsa_SetTrustedDomainInfoByName
2129 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2130 TALLOC_CTX *mem_ctx,
2131 struct lsa_SetTrustedDomainInfoByName *r)
2133 struct dcesrv_handle *policy_handle;
2134 struct lsa_policy_state *policy_state;
2135 struct ldb_message **msgs;
2136 NTSTATUS nt_status;
2138 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2139 policy_state = policy_handle->data;
2141 /* get the trusted domain object */
2142 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2143 policy_state->domain_dn,
2144 r->in.trusted_domain->string,
2145 r->in.trusted_domain->string,
2146 NULL, &msgs);
2147 if (!NT_STATUS_IS_OK(nt_status)) {
2148 if (NT_STATUS_EQUAL(nt_status,
2149 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2150 return nt_status;
2152 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2155 return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2156 msgs[0], r->in.level, r->in.info);
2160 lsa_QueryTrustedDomainInfoByName
2162 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2163 TALLOC_CTX *mem_ctx,
2164 struct lsa_QueryTrustedDomainInfoByName *r)
2166 NTSTATUS status;
2167 struct lsa_OpenTrustedDomainByName opn;
2168 struct lsa_QueryTrustedDomainInfo query;
2169 struct dcesrv_handle *h;
2171 opn.in.handle = r->in.handle;
2172 opn.in.name = *r->in.trusted_domain;
2173 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2174 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2175 if (!opn.out.trustdom_handle) {
2176 return NT_STATUS_NO_MEMORY;
2178 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2179 if (!NT_STATUS_IS_OK(status)) {
2180 return status;
2183 /* Ensure this handle goes away at the end of this call */
2184 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2185 talloc_steal(mem_ctx, h);
2187 query.in.trustdom_handle = opn.out.trustdom_handle;
2188 query.in.level = r->in.level;
2189 query.out.info = r->out.info;
2190 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2191 if (!NT_STATUS_IS_OK(status)) {
2192 return status;
2195 return NT_STATUS_OK;
2199 lsa_CloseTrustedDomainEx
2201 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2202 TALLOC_CTX *mem_ctx,
2203 struct lsa_CloseTrustedDomainEx *r)
2205 /* The result of a bad hair day from an IDL programmer? Not
2206 * implmented in Win2k3. You should always just lsa_Close
2207 * anyway. */
2208 return NT_STATUS_NOT_IMPLEMENTED;
2213 comparison function for sorting lsa_DomainInformation array
2215 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2217 return strcasecmp_m(e1->name.string, e2->name.string);
2221 lsa_EnumTrustDom
2223 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2224 struct lsa_EnumTrustDom *r)
2226 struct dcesrv_handle *policy_handle;
2227 struct lsa_DomainInfo *entries;
2228 struct lsa_policy_state *policy_state;
2229 struct ldb_message **domains;
2230 const char *attrs[] = {
2231 "flatname",
2232 "securityIdentifier",
2233 NULL
2237 int count, i;
2239 *r->out.resume_handle = 0;
2241 r->out.domains->domains = NULL;
2242 r->out.domains->count = 0;
2244 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2246 policy_state = policy_handle->data;
2248 /* search for all users in this domain. This could possibly be cached and
2249 resumed based on resume_key */
2250 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2251 "objectclass=trustedDomain");
2252 if (count < 0) {
2253 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2256 /* convert to lsa_TrustInformation format */
2257 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2258 if (!entries) {
2259 return NT_STATUS_NO_MEMORY;
2261 for (i=0;i<count;i++) {
2262 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2263 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2266 /* sort the results by name */
2267 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2269 if (*r->in.resume_handle >= count) {
2270 *r->out.resume_handle = -1;
2272 return NT_STATUS_NO_MORE_ENTRIES;
2275 /* return the rest, limit by max_size. Note that we
2276 use the w2k3 element size value of 60 */
2277 r->out.domains->count = count - *r->in.resume_handle;
2278 r->out.domains->count = MIN(r->out.domains->count,
2279 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2281 r->out.domains->domains = entries + *r->in.resume_handle;
2282 r->out.domains->count = r->out.domains->count;
2284 if (r->out.domains->count < count - *r->in.resume_handle) {
2285 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2286 return STATUS_MORE_ENTRIES;
2289 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2290 * always be larger than the previous input resume handle, in
2291 * particular when hitting the last query it is vital to set the
2292 * resume handle correctly to avoid infinite client loops, as
2293 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2294 * status is NT_STATUS_OK - gd */
2296 *r->out.resume_handle = (uint32_t)-1;
2298 return NT_STATUS_OK;
2302 comparison function for sorting lsa_DomainInformation array
2304 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2306 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2310 lsa_EnumTrustedDomainsEx
2312 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2313 struct lsa_EnumTrustedDomainsEx *r)
2315 struct dcesrv_handle *policy_handle;
2316 struct lsa_TrustDomainInfoInfoEx *entries;
2317 struct lsa_policy_state *policy_state;
2318 struct ldb_message **domains;
2319 const char *attrs[] = {
2320 "flatname",
2321 "trustPartner",
2322 "securityIdentifier",
2323 "trustDirection",
2324 "trustType",
2325 "trustAttributes",
2326 NULL
2328 NTSTATUS nt_status;
2330 int count, i;
2332 *r->out.resume_handle = 0;
2334 r->out.domains->domains = NULL;
2335 r->out.domains->count = 0;
2337 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2339 policy_state = policy_handle->data;
2341 /* search for all users in this domain. This could possibly be cached and
2342 resumed based on resume_key */
2343 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2344 "objectclass=trustedDomain");
2345 if (count < 0) {
2346 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2349 /* convert to lsa_DomainInformation format */
2350 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2351 if (!entries) {
2352 return NT_STATUS_NO_MEMORY;
2354 for (i=0;i<count;i++) {
2355 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2356 if (!NT_STATUS_IS_OK(nt_status)) {
2357 return nt_status;
2361 /* sort the results by name */
2362 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2364 if (*r->in.resume_handle >= count) {
2365 *r->out.resume_handle = -1;
2367 return NT_STATUS_NO_MORE_ENTRIES;
2370 /* return the rest, limit by max_size. Note that we
2371 use the w2k3 element size value of 60 */
2372 r->out.domains->count = count - *r->in.resume_handle;
2373 r->out.domains->count = MIN(r->out.domains->count,
2374 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2376 r->out.domains->domains = entries + *r->in.resume_handle;
2377 r->out.domains->count = r->out.domains->count;
2379 if (r->out.domains->count < count - *r->in.resume_handle) {
2380 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2381 return STATUS_MORE_ENTRIES;
2384 return NT_STATUS_OK;
2389 lsa_OpenAccount
2391 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2392 struct lsa_OpenAccount *r)
2394 struct dcesrv_handle *h, *ah;
2395 struct lsa_policy_state *state;
2396 struct lsa_account_state *astate;
2398 ZERO_STRUCTP(r->out.acct_handle);
2400 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2402 state = h->data;
2404 astate = talloc(dce_call->conn, struct lsa_account_state);
2405 if (astate == NULL) {
2406 return NT_STATUS_NO_MEMORY;
2409 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2410 if (astate->account_sid == NULL) {
2411 talloc_free(astate);
2412 return NT_STATUS_NO_MEMORY;
2415 astate->policy = talloc_reference(astate, state);
2416 astate->access_mask = r->in.access_mask;
2418 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2419 if (!ah) {
2420 talloc_free(astate);
2421 return NT_STATUS_NO_MEMORY;
2424 ah->data = talloc_steal(ah, astate);
2426 *r->out.acct_handle = ah->wire_handle;
2428 return NT_STATUS_OK;
2433 lsa_EnumPrivsAccount
2435 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2436 TALLOC_CTX *mem_ctx,
2437 struct lsa_EnumPrivsAccount *r)
2439 struct dcesrv_handle *h;
2440 struct lsa_account_state *astate;
2441 int ret;
2442 unsigned int i, j;
2443 struct ldb_message **res;
2444 const char * const attrs[] = { "privilege", NULL};
2445 struct ldb_message_element *el;
2446 const char *sidstr;
2447 struct lsa_PrivilegeSet *privs;
2449 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2451 astate = h->data;
2453 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2454 if (privs == NULL) {
2455 return NT_STATUS_NO_MEMORY;
2457 privs->count = 0;
2458 privs->unknown = 0;
2459 privs->set = NULL;
2461 *r->out.privs = privs;
2463 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2464 if (sidstr == NULL) {
2465 return NT_STATUS_NO_MEMORY;
2468 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2469 "objectSid=%s", sidstr);
2470 if (ret < 0) {
2471 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2473 if (ret != 1) {
2474 return NT_STATUS_OK;
2477 el = ldb_msg_find_element(res[0], "privilege");
2478 if (el == NULL || el->num_values == 0) {
2479 return NT_STATUS_OK;
2482 privs->set = talloc_array(privs,
2483 struct lsa_LUIDAttribute, el->num_values);
2484 if (privs->set == NULL) {
2485 return NT_STATUS_NO_MEMORY;
2488 j = 0;
2489 for (i=0;i<el->num_values;i++) {
2490 int id = sec_privilege_id((const char *)el->values[i].data);
2491 if (id == SEC_PRIV_INVALID) {
2492 /* Perhaps an account right, not a privilege */
2493 continue;
2495 privs->set[j].attribute = 0;
2496 privs->set[j].luid.low = id;
2497 privs->set[j].luid.high = 0;
2498 j++;
2501 privs->count = j;
2503 return NT_STATUS_OK;
2507 lsa_EnumAccountRights
2509 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2510 TALLOC_CTX *mem_ctx,
2511 struct lsa_EnumAccountRights *r)
2513 struct dcesrv_handle *h;
2514 struct lsa_policy_state *state;
2515 int ret;
2516 unsigned int i;
2517 struct ldb_message **res;
2518 const char * const attrs[] = { "privilege", NULL};
2519 const char *sidstr;
2520 struct ldb_message_element *el;
2522 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2524 state = h->data;
2526 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2527 if (sidstr == NULL) {
2528 return NT_STATUS_NO_MEMORY;
2531 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2532 "(&(objectSid=%s)(privilege=*))", sidstr);
2533 if (ret == 0) {
2534 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2536 if (ret != 1) {
2537 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2538 dom_sid_string(mem_ctx, r->in.sid),
2539 ldb_errstring(state->pdb)));
2540 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2543 el = ldb_msg_find_element(res[0], "privilege");
2544 if (el == NULL || el->num_values == 0) {
2545 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2548 r->out.rights->count = el->num_values;
2549 r->out.rights->names = talloc_array(r->out.rights,
2550 struct lsa_StringLarge, r->out.rights->count);
2551 if (r->out.rights->names == NULL) {
2552 return NT_STATUS_NO_MEMORY;
2555 for (i=0;i<el->num_values;i++) {
2556 r->out.rights->names[i].string = (const char *)el->values[i].data;
2559 return NT_STATUS_OK;
2565 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2567 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2568 TALLOC_CTX *mem_ctx,
2569 struct lsa_policy_state *state,
2570 int ldb_flag,
2571 struct dom_sid *sid,
2572 const struct lsa_RightSet *rights)
2574 const char *sidstr, *sidndrstr;
2575 struct ldb_message *msg;
2576 struct ldb_message_element *el;
2577 int ret;
2578 uint32_t i;
2579 struct lsa_EnumAccountRights r2;
2580 char *dnstr;
2582 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2583 SECURITY_ADMINISTRATOR) {
2584 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2585 return NT_STATUS_ACCESS_DENIED;
2588 msg = ldb_msg_new(mem_ctx);
2589 if (msg == NULL) {
2590 return NT_STATUS_NO_MEMORY;
2593 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2594 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
2596 sidstr = dom_sid_string(msg, sid);
2597 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
2599 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2600 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
2602 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2603 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
2605 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2606 NTSTATUS status;
2608 r2.in.handle = &state->handle->wire_handle;
2609 r2.in.sid = sid;
2610 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2612 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2613 if (!NT_STATUS_IS_OK(status)) {
2614 ZERO_STRUCTP(r2.out.rights);
2618 for (i=0;i<rights->count;i++) {
2619 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2620 if (sec_right_bit(rights->names[i].string) == 0) {
2621 talloc_free(msg);
2622 return NT_STATUS_NO_SUCH_PRIVILEGE;
2625 talloc_free(msg);
2626 return NT_STATUS_NO_SUCH_PRIVILEGE;
2629 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2630 uint32_t j;
2631 for (j=0;j<r2.out.rights->count;j++) {
2632 if (strcasecmp_m(r2.out.rights->names[j].string,
2633 rights->names[i].string) == 0) {
2634 break;
2637 if (j != r2.out.rights->count) continue;
2640 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2641 if (ret != LDB_SUCCESS) {
2642 talloc_free(msg);
2643 return NT_STATUS_NO_MEMORY;
2647 el = ldb_msg_find_element(msg, "privilege");
2648 if (!el) {
2649 talloc_free(msg);
2650 return NT_STATUS_OK;
2653 el->flags = ldb_flag;
2655 ret = ldb_modify(state->pdb, msg);
2656 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2657 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2658 talloc_free(msg);
2659 return NT_STATUS_NO_MEMORY;
2661 ldb_msg_add_string(msg, "comment", "added via LSA");
2662 ret = ldb_add(state->pdb, msg);
2664 if (ret != LDB_SUCCESS) {
2665 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2666 talloc_free(msg);
2667 return NT_STATUS_OK;
2669 DEBUG(3, ("Could not %s attributes from %s: %s",
2670 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2671 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2672 talloc_free(msg);
2673 return NT_STATUS_UNEXPECTED_IO_ERROR;
2676 talloc_free(msg);
2677 return NT_STATUS_OK;
2681 lsa_AddPrivilegesToAccount
2683 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2684 struct lsa_AddPrivilegesToAccount *r)
2686 struct lsa_RightSet rights;
2687 struct dcesrv_handle *h;
2688 struct lsa_account_state *astate;
2689 uint32_t i;
2691 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2693 astate = h->data;
2695 rights.count = r->in.privs->count;
2696 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2697 if (rights.names == NULL) {
2698 return NT_STATUS_NO_MEMORY;
2700 for (i=0;i<rights.count;i++) {
2701 int id = r->in.privs->set[i].luid.low;
2702 if (r->in.privs->set[i].luid.high) {
2703 return NT_STATUS_NO_SUCH_PRIVILEGE;
2705 rights.names[i].string = sec_privilege_name(id);
2706 if (rights.names[i].string == NULL) {
2707 return NT_STATUS_NO_SUCH_PRIVILEGE;
2711 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2712 LDB_FLAG_MOD_ADD, astate->account_sid,
2713 &rights);
2718 lsa_RemovePrivilegesFromAccount
2720 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2721 struct lsa_RemovePrivilegesFromAccount *r)
2723 struct lsa_RightSet *rights;
2724 struct dcesrv_handle *h;
2725 struct lsa_account_state *astate;
2726 uint32_t i;
2728 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2730 astate = h->data;
2732 rights = talloc(mem_ctx, struct lsa_RightSet);
2734 if (r->in.remove_all == 1 &&
2735 r->in.privs == NULL) {
2736 struct lsa_EnumAccountRights r2;
2737 NTSTATUS status;
2739 r2.in.handle = &astate->policy->handle->wire_handle;
2740 r2.in.sid = astate->account_sid;
2741 r2.out.rights = rights;
2743 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2744 if (!NT_STATUS_IS_OK(status)) {
2745 return status;
2748 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2749 LDB_FLAG_MOD_DELETE, astate->account_sid,
2750 r2.out.rights);
2753 if (r->in.remove_all != 0) {
2754 return NT_STATUS_INVALID_PARAMETER;
2757 rights->count = r->in.privs->count;
2758 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2759 if (rights->names == NULL) {
2760 return NT_STATUS_NO_MEMORY;
2762 for (i=0;i<rights->count;i++) {
2763 int id = r->in.privs->set[i].luid.low;
2764 if (r->in.privs->set[i].luid.high) {
2765 return NT_STATUS_NO_SUCH_PRIVILEGE;
2767 rights->names[i].string = sec_privilege_name(id);
2768 if (rights->names[i].string == NULL) {
2769 return NT_STATUS_NO_SUCH_PRIVILEGE;
2773 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2774 LDB_FLAG_MOD_DELETE, astate->account_sid,
2775 rights);
2780 lsa_GetQuotasForAccount
2782 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2783 struct lsa_GetQuotasForAccount *r)
2785 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2790 lsa_SetQuotasForAccount
2792 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2793 struct lsa_SetQuotasForAccount *r)
2795 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2800 lsa_GetSystemAccessAccount
2802 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2803 struct lsa_GetSystemAccessAccount *r)
2805 struct dcesrv_handle *h;
2806 struct lsa_account_state *astate;
2807 int ret;
2808 unsigned int i;
2809 struct ldb_message **res;
2810 const char * const attrs[] = { "privilege", NULL};
2811 struct ldb_message_element *el;
2812 const char *sidstr;
2814 *(r->out.access_mask) = 0x00000000;
2816 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2818 astate = h->data;
2820 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2821 if (sidstr == NULL) {
2822 return NT_STATUS_NO_MEMORY;
2825 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2826 "objectSid=%s", sidstr);
2827 if (ret < 0) {
2828 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2830 if (ret != 1) {
2831 return NT_STATUS_OK;
2834 el = ldb_msg_find_element(res[0], "privilege");
2835 if (el == NULL || el->num_values == 0) {
2836 return NT_STATUS_OK;
2839 for (i=0;i<el->num_values;i++) {
2840 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2841 if (right_bit == 0) {
2842 /* Perhaps an privilege, not a right */
2843 continue;
2845 *(r->out.access_mask) |= right_bit;
2848 return NT_STATUS_OK;
2853 lsa_SetSystemAccessAccount
2855 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2856 struct lsa_SetSystemAccessAccount *r)
2858 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2863 lsa_CreateSecret
2865 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2866 struct lsa_CreateSecret *r)
2868 struct dcesrv_handle *policy_handle;
2869 struct lsa_policy_state *policy_state;
2870 struct lsa_secret_state *secret_state;
2871 struct dcesrv_handle *handle;
2872 struct ldb_message **msgs, *msg;
2873 const char *attrs[] = {
2874 NULL
2877 const char *name;
2879 int ret;
2881 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2882 ZERO_STRUCTP(r->out.sec_handle);
2884 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2886 case SECURITY_SYSTEM:
2887 case SECURITY_ADMINISTRATOR:
2888 break;
2889 default:
2890 /* Users and annonymous are not allowed create secrets */
2891 return NT_STATUS_ACCESS_DENIED;
2894 policy_state = policy_handle->data;
2896 if (!r->in.name.string) {
2897 return NT_STATUS_INVALID_PARAMETER;
2900 secret_state = talloc(mem_ctx, struct lsa_secret_state);
2901 NT_STATUS_HAVE_NO_MEMORY(secret_state);
2902 secret_state->policy = policy_state;
2904 msg = ldb_msg_new(mem_ctx);
2905 if (msg == NULL) {
2906 return NT_STATUS_NO_MEMORY;
2909 if (strncmp("G$", r->in.name.string, 2) == 0) {
2910 const char *name2;
2912 secret_state->global = true;
2914 name = &r->in.name.string[2];
2915 if (strlen(name) == 0) {
2916 return NT_STATUS_INVALID_PARAMETER;
2919 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2920 ldb_binary_encode_string(mem_ctx, name));
2921 NT_STATUS_HAVE_NO_MEMORY(name2);
2923 /* We need to connect to the database as system, as this is one
2924 * of the rare RPC calls that must read the secrets (and this
2925 * is denied otherwise) */
2926 secret_state->sam_ldb = talloc_reference(secret_state,
2927 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));
2928 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2930 /* search for the secret record */
2931 ret = gendb_search(secret_state->sam_ldb,
2932 mem_ctx, policy_state->system_dn, &msgs, attrs,
2933 "(&(cn=%s)(objectclass=secret))",
2934 name2);
2935 if (ret > 0) {
2936 return NT_STATUS_OBJECT_NAME_COLLISION;
2939 if (ret < 0) {
2940 DEBUG(0,("Failure searching for CN=%s: %s\n",
2941 name2, ldb_errstring(secret_state->sam_ldb)));
2942 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2945 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2946 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2947 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2948 return NT_STATUS_NO_MEMORY;
2951 ret = ldb_msg_add_string(msg, "cn", name2);
2952 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2953 } else {
2954 secret_state->global = false;
2956 name = r->in.name.string;
2957 if (strlen(name) == 0) {
2958 return NT_STATUS_INVALID_PARAMETER;
2961 secret_state->sam_ldb = talloc_reference(secret_state,
2962 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
2963 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2965 /* search for the secret record */
2966 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2967 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2968 &msgs, attrs,
2969 "(&(cn=%s)(objectclass=secret))",
2970 ldb_binary_encode_string(mem_ctx, name));
2971 if (ret > 0) {
2972 return NT_STATUS_OBJECT_NAME_COLLISION;
2975 if (ret < 0) {
2976 DEBUG(0,("Failure searching for CN=%s: %s\n",
2977 name, ldb_errstring(secret_state->sam_ldb)));
2978 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2981 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
2982 "cn=%s,cn=LSA Secrets", name);
2983 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2984 ret = ldb_msg_add_string(msg, "cn", name);
2985 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2988 ret = ldb_msg_add_string(msg, "objectClass", "secret");
2989 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2991 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2992 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
2994 /* create the secret */
2995 ret = ldb_add(secret_state->sam_ldb, msg);
2996 if (ret != LDB_SUCCESS) {
2997 DEBUG(0,("Failed to create secret record %s: %s\n",
2998 ldb_dn_get_linearized(msg->dn),
2999 ldb_errstring(secret_state->sam_ldb)));
3000 return NT_STATUS_ACCESS_DENIED;
3003 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3004 NT_STATUS_HAVE_NO_MEMORY(handle);
3006 handle->data = talloc_steal(handle, secret_state);
3008 secret_state->access_mask = r->in.access_mask;
3009 secret_state->policy = talloc_reference(secret_state, policy_state);
3010 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3012 *r->out.sec_handle = handle->wire_handle;
3014 return NT_STATUS_OK;
3019 lsa_OpenSecret
3021 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3022 struct lsa_OpenSecret *r)
3024 struct dcesrv_handle *policy_handle;
3026 struct lsa_policy_state *policy_state;
3027 struct lsa_secret_state *secret_state;
3028 struct dcesrv_handle *handle;
3029 struct ldb_message **msgs;
3030 const char *attrs[] = {
3031 NULL
3034 const char *name;
3036 int ret;
3038 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3039 ZERO_STRUCTP(r->out.sec_handle);
3040 policy_state = policy_handle->data;
3042 if (!r->in.name.string) {
3043 return NT_STATUS_INVALID_PARAMETER;
3046 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3048 case SECURITY_SYSTEM:
3049 case SECURITY_ADMINISTRATOR:
3050 break;
3051 default:
3052 /* Users and annonymous are not allowed to access secrets */
3053 return NT_STATUS_ACCESS_DENIED;
3056 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3057 if (!secret_state) {
3058 return NT_STATUS_NO_MEMORY;
3060 secret_state->policy = policy_state;
3062 if (strncmp("G$", r->in.name.string, 2) == 0) {
3063 name = &r->in.name.string[2];
3064 /* 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) */
3065 secret_state->sam_ldb = talloc_reference(secret_state,
3066 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));
3067 secret_state->global = true;
3069 if (strlen(name) < 1) {
3070 return NT_STATUS_INVALID_PARAMETER;
3073 /* search for the secret record */
3074 ret = gendb_search(secret_state->sam_ldb,
3075 mem_ctx, policy_state->system_dn, &msgs, attrs,
3076 "(&(cn=%s Secret)(objectclass=secret))",
3077 ldb_binary_encode_string(mem_ctx, name));
3078 if (ret == 0) {
3079 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3082 if (ret != 1) {
3083 DEBUG(0,("Found %d records matching DN %s\n", ret,
3084 ldb_dn_get_linearized(policy_state->system_dn)));
3085 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3088 } else {
3089 secret_state->global = false;
3090 secret_state->sam_ldb = talloc_reference(secret_state,
3091 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3093 name = r->in.name.string;
3094 if (strlen(name) < 1) {
3095 return NT_STATUS_INVALID_PARAMETER;
3098 /* search for the secret record */
3099 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3100 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3101 &msgs, attrs,
3102 "(&(cn=%s)(objectclass=secret))",
3103 ldb_binary_encode_string(mem_ctx, name));
3104 if (ret == 0) {
3105 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3108 if (ret != 1) {
3109 DEBUG(0,("Found %d records matching CN=%s\n",
3110 ret, ldb_binary_encode_string(mem_ctx, name)));
3111 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3115 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3117 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3118 if (!handle) {
3119 return NT_STATUS_NO_MEMORY;
3122 handle->data = talloc_steal(handle, secret_state);
3124 secret_state->access_mask = r->in.access_mask;
3125 secret_state->policy = talloc_reference(secret_state, policy_state);
3127 *r->out.sec_handle = handle->wire_handle;
3129 return NT_STATUS_OK;
3134 lsa_SetSecret
3136 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3137 struct lsa_SetSecret *r)
3140 struct dcesrv_handle *h;
3141 struct lsa_secret_state *secret_state;
3142 struct ldb_message *msg;
3143 DATA_BLOB session_key;
3144 DATA_BLOB crypt_secret, secret;
3145 struct ldb_val val;
3146 int ret;
3147 NTSTATUS status = NT_STATUS_OK;
3149 struct timeval now = timeval_current();
3150 NTTIME nt_now = timeval_to_nttime(&now);
3152 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3154 secret_state = h->data;
3156 msg = ldb_msg_new(mem_ctx);
3157 if (msg == NULL) {
3158 return NT_STATUS_NO_MEMORY;
3161 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3162 if (!msg->dn) {
3163 return NT_STATUS_NO_MEMORY;
3165 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3166 if (!NT_STATUS_IS_OK(status)) {
3167 return status;
3170 if (r->in.old_val) {
3171 /* Decrypt */
3172 crypt_secret.data = r->in.old_val->data;
3173 crypt_secret.length = r->in.old_val->size;
3175 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3176 if (!NT_STATUS_IS_OK(status)) {
3177 return status;
3180 val.data = secret.data;
3181 val.length = secret.length;
3183 /* set value */
3184 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3185 return NT_STATUS_NO_MEMORY;
3188 /* set old value mtime */
3189 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3190 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3191 return NT_STATUS_NO_MEMORY;
3194 } else {
3195 /* If the old value is not set, then migrate the
3196 * current value to the old value */
3197 const struct ldb_val *old_val;
3198 NTTIME last_set_time;
3199 struct ldb_message **res;
3200 const char *attrs[] = {
3201 "currentValue",
3202 "lastSetTime",
3203 NULL
3206 /* search for the secret record */
3207 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3208 secret_state->secret_dn, &res, attrs);
3209 if (ret == 0) {
3210 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3213 if (ret != 1) {
3214 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3215 ldb_dn_get_linearized(secret_state->secret_dn)));
3216 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3219 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3220 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3222 if (old_val) {
3223 /* set old value */
3224 if (ldb_msg_add_value(msg, "priorValue",
3225 old_val, NULL) != LDB_SUCCESS) {
3226 return NT_STATUS_NO_MEMORY;
3228 } else {
3229 if (samdb_msg_add_delete(secret_state->sam_ldb,
3230 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3231 return NT_STATUS_NO_MEMORY;
3236 /* set old value mtime */
3237 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3238 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3239 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3240 return NT_STATUS_NO_MEMORY;
3242 } else {
3243 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3244 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3245 return NT_STATUS_NO_MEMORY;
3250 if (r->in.new_val) {
3251 /* Decrypt */
3252 crypt_secret.data = r->in.new_val->data;
3253 crypt_secret.length = r->in.new_val->size;
3255 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3256 if (!NT_STATUS_IS_OK(status)) {
3257 return status;
3260 val.data = secret.data;
3261 val.length = secret.length;
3263 /* set value */
3264 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3265 return NT_STATUS_NO_MEMORY;
3268 /* set new value mtime */
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;
3274 } else {
3275 /* NULL out the NEW value */
3276 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3277 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3278 return NT_STATUS_NO_MEMORY;
3280 if (samdb_msg_add_delete(secret_state->sam_ldb,
3281 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3282 return NT_STATUS_NO_MEMORY;
3286 /* modify the samdb record */
3287 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3288 if (ret != LDB_SUCCESS) {
3289 return dsdb_ldb_err_to_ntstatus(ret);
3292 return NT_STATUS_OK;
3297 lsa_QuerySecret
3299 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3300 struct lsa_QuerySecret *r)
3302 struct dcesrv_handle *h;
3303 struct lsa_secret_state *secret_state;
3304 struct ldb_message *msg;
3305 DATA_BLOB session_key;
3306 DATA_BLOB crypt_secret, secret;
3307 int ret;
3308 struct ldb_message **res;
3309 const char *attrs[] = {
3310 "currentValue",
3311 "priorValue",
3312 "lastSetTime",
3313 "priorSetTime",
3314 NULL
3317 NTSTATUS nt_status;
3319 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3321 /* Ensure user is permitted to read this... */
3322 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3324 case SECURITY_SYSTEM:
3325 case SECURITY_ADMINISTRATOR:
3326 break;
3327 default:
3328 /* Users and annonymous are not allowed to read secrets */
3329 return NT_STATUS_ACCESS_DENIED;
3332 secret_state = h->data;
3334 /* pull all the user attributes */
3335 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3336 secret_state->secret_dn, &res, attrs);
3337 if (ret != 1) {
3338 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3340 msg = res[0];
3342 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3343 if (!NT_STATUS_IS_OK(nt_status)) {
3344 return nt_status;
3347 if (r->in.old_val) {
3348 const struct ldb_val *prior_val;
3349 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3350 if (!r->out.old_val) {
3351 return NT_STATUS_NO_MEMORY;
3353 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
3355 if (prior_val && prior_val->length) {
3356 secret.data = prior_val->data;
3357 secret.length = prior_val->length;
3359 /* Encrypt */
3360 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3361 if (!crypt_secret.length) {
3362 return NT_STATUS_NO_MEMORY;
3364 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3365 if (!r->out.old_val->buf) {
3366 return NT_STATUS_NO_MEMORY;
3368 r->out.old_val->buf->size = crypt_secret.length;
3369 r->out.old_val->buf->length = crypt_secret.length;
3370 r->out.old_val->buf->data = crypt_secret.data;
3374 if (r->in.old_mtime) {
3375 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3376 if (!r->out.old_mtime) {
3377 return NT_STATUS_NO_MEMORY;
3379 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
3382 if (r->in.new_val) {
3383 const struct ldb_val *new_val;
3384 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3385 if (!r->out.new_val) {
3386 return NT_STATUS_NO_MEMORY;
3389 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3391 if (new_val && new_val->length) {
3392 secret.data = new_val->data;
3393 secret.length = new_val->length;
3395 /* Encrypt */
3396 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3397 if (!crypt_secret.length) {
3398 return NT_STATUS_NO_MEMORY;
3400 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3401 if (!r->out.new_val->buf) {
3402 return NT_STATUS_NO_MEMORY;
3404 r->out.new_val->buf->length = crypt_secret.length;
3405 r->out.new_val->buf->size = crypt_secret.length;
3406 r->out.new_val->buf->data = crypt_secret.data;
3410 if (r->in.new_mtime) {
3411 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3412 if (!r->out.new_mtime) {
3413 return NT_STATUS_NO_MEMORY;
3415 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3418 return NT_STATUS_OK;
3423 lsa_LookupPrivValue
3425 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3426 TALLOC_CTX *mem_ctx,
3427 struct lsa_LookupPrivValue *r)
3429 struct dcesrv_handle *h;
3430 struct lsa_policy_state *state;
3431 int id;
3433 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3435 state = h->data;
3437 id = sec_privilege_id(r->in.name->string);
3438 if (id == SEC_PRIV_INVALID) {
3439 return NT_STATUS_NO_SUCH_PRIVILEGE;
3442 r->out.luid->low = id;
3443 r->out.luid->high = 0;
3445 return NT_STATUS_OK;
3450 lsa_LookupPrivName
3452 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3453 TALLOC_CTX *mem_ctx,
3454 struct lsa_LookupPrivName *r)
3456 struct dcesrv_handle *h;
3457 struct lsa_policy_state *state;
3458 struct lsa_StringLarge *name;
3459 const char *privname;
3461 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3463 state = h->data;
3465 if (r->in.luid->high != 0) {
3466 return NT_STATUS_NO_SUCH_PRIVILEGE;
3469 privname = sec_privilege_name(r->in.luid->low);
3470 if (privname == NULL) {
3471 return NT_STATUS_NO_SUCH_PRIVILEGE;
3474 name = talloc(mem_ctx, struct lsa_StringLarge);
3475 if (name == NULL) {
3476 return NT_STATUS_NO_MEMORY;
3479 name->string = privname;
3481 *r->out.name = name;
3483 return NT_STATUS_OK;
3488 lsa_LookupPrivDisplayName
3490 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3491 TALLOC_CTX *mem_ctx,
3492 struct lsa_LookupPrivDisplayName *r)
3494 struct dcesrv_handle *h;
3495 struct lsa_policy_state *state;
3496 struct lsa_StringLarge *disp_name = NULL;
3497 enum sec_privilege id;
3499 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3501 state = h->data;
3503 id = sec_privilege_id(r->in.name->string);
3504 if (id == SEC_PRIV_INVALID) {
3505 return NT_STATUS_NO_SUCH_PRIVILEGE;
3508 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3509 if (disp_name == NULL) {
3510 return NT_STATUS_NO_MEMORY;
3513 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3514 if (disp_name->string == NULL) {
3515 return NT_STATUS_INTERNAL_ERROR;
3518 *r->out.disp_name = disp_name;
3519 *r->out.returned_language_id = 0;
3521 return NT_STATUS_OK;
3526 lsa_EnumAccountsWithUserRight
3528 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3529 TALLOC_CTX *mem_ctx,
3530 struct lsa_EnumAccountsWithUserRight *r)
3532 struct dcesrv_handle *h;
3533 struct lsa_policy_state *state;
3534 int ret, i;
3535 struct ldb_message **res;
3536 const char * const attrs[] = { "objectSid", NULL};
3537 const char *privname;
3539 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3541 state = h->data;
3543 if (r->in.name == NULL) {
3544 return NT_STATUS_NO_SUCH_PRIVILEGE;
3547 privname = r->in.name->string;
3548 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3549 return NT_STATUS_NO_SUCH_PRIVILEGE;
3552 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3553 "privilege=%s", privname);
3554 if (ret < 0) {
3555 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3557 if (ret == 0) {
3558 return NT_STATUS_NO_MORE_ENTRIES;
3561 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3562 if (r->out.sids->sids == NULL) {
3563 return NT_STATUS_NO_MEMORY;
3565 for (i=0;i<ret;i++) {
3566 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3567 res[i], "objectSid");
3568 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3570 r->out.sids->num_sids = ret;
3572 return NT_STATUS_OK;
3577 lsa_AddAccountRights
3579 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3580 TALLOC_CTX *mem_ctx,
3581 struct lsa_AddAccountRights *r)
3583 struct dcesrv_handle *h;
3584 struct lsa_policy_state *state;
3586 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3588 state = h->data;
3590 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3591 LDB_FLAG_MOD_ADD,
3592 r->in.sid, r->in.rights);
3597 lsa_RemoveAccountRights
3599 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3600 TALLOC_CTX *mem_ctx,
3601 struct lsa_RemoveAccountRights *r)
3603 struct dcesrv_handle *h;
3604 struct lsa_policy_state *state;
3606 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3608 state = h->data;
3610 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3611 LDB_FLAG_MOD_DELETE,
3612 r->in.sid, r->in.rights);
3617 lsa_StorePrivateData
3619 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3620 struct lsa_StorePrivateData *r)
3622 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3627 lsa_RetrievePrivateData
3629 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3630 struct lsa_RetrievePrivateData *r)
3632 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3637 lsa_GetUserName
3639 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3640 struct lsa_GetUserName *r)
3642 enum dcerpc_transport_t transport = dce_call->conn->endpoint->ep_description->transport;
3643 NTSTATUS status = NT_STATUS_OK;
3644 const char *account_name;
3645 const char *authority_name;
3646 struct lsa_String *_account_name;
3647 struct lsa_String *_authority_name = NULL;
3649 if (transport != NCACN_NP && transport != NCALRPC) {
3650 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3653 /* this is what w2k3 does */
3654 r->out.account_name = r->in.account_name;
3655 r->out.authority_name = r->in.authority_name;
3657 if (r->in.account_name
3658 && *r->in.account_name
3659 /* && *(*r->in.account_name)->string */
3661 return NT_STATUS_INVALID_PARAMETER;
3664 if (r->in.authority_name
3665 && *r->in.authority_name
3666 /* && *(*r->in.authority_name)->string */
3668 return NT_STATUS_INVALID_PARAMETER;
3671 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3672 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3674 _account_name = talloc(mem_ctx, struct lsa_String);
3675 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3676 _account_name->string = account_name;
3678 if (r->in.authority_name) {
3679 _authority_name = talloc(mem_ctx, struct lsa_String);
3680 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3681 _authority_name->string = authority_name;
3684 *r->out.account_name = _account_name;
3685 if (r->out.authority_name) {
3686 *r->out.authority_name = _authority_name;
3689 return status;
3693 lsa_SetInfoPolicy2
3695 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3696 TALLOC_CTX *mem_ctx,
3697 struct lsa_SetInfoPolicy2 *r)
3699 /* need to support these */
3700 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3703 static void kdc_get_policy(struct loadparm_context *lp_ctx,
3704 struct smb_krb5_context *smb_krb5_context,
3705 struct lsa_DomainInfoKerberos *k)
3707 time_t svc_tkt_lifetime;
3708 time_t usr_tkt_lifetime;
3709 time_t renewal_lifetime;
3711 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
3713 /* Our KDC always re-validates the client */
3714 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
3716 lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
3717 &usr_tkt_lifetime, &renewal_lifetime);
3719 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
3720 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
3721 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
3722 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
3723 However in the parent function we basically just did a full
3724 krb5_context init with the only purpose of getting a global
3725 config option (the max skew), it would probably make more sense
3726 to have a lp_ or ldb global option as the samba default */
3727 if (smb_krb5_context) {
3728 unix_to_nt_time(&k->clock_skew,
3729 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
3731 #endif
3732 k->reserved = 0;
3735 lsa_QueryDomainInformationPolicy
3737 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3738 TALLOC_CTX *mem_ctx,
3739 struct lsa_QueryDomainInformationPolicy *r)
3741 union lsa_DomainInformationPolicy *info;
3743 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3744 if (!info) {
3745 return NT_STATUS_NO_MEMORY;
3748 switch (r->in.level) {
3749 case LSA_DOMAIN_INFO_POLICY_EFS:
3750 talloc_free(info);
3751 *r->out.info = NULL;
3752 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3753 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3755 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3756 struct smb_krb5_context *smb_krb5_context;
3757 int ret = smb_krb5_init_context(mem_ctx,
3758 dce_call->event_ctx,
3759 dce_call->conn->dce_ctx->lp_ctx,
3760 &smb_krb5_context);
3761 if (ret != 0) {
3762 talloc_free(info);
3763 *r->out.info = NULL;
3764 return NT_STATUS_INTERNAL_ERROR;
3766 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3767 smb_krb5_context,
3769 talloc_free(smb_krb5_context);
3770 *r->out.info = info;
3771 return NT_STATUS_OK;
3773 default:
3774 talloc_free(info);
3775 *r->out.info = NULL;
3776 return NT_STATUS_INVALID_INFO_CLASS;
3781 lsa_SetDomInfoPolicy
3783 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3784 TALLOC_CTX *mem_ctx,
3785 struct lsa_SetDomainInformationPolicy *r)
3787 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3791 lsa_TestCall
3793 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3794 TALLOC_CTX *mem_ctx,
3795 struct lsa_TestCall *r)
3797 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3801 lsa_CREDRWRITE
3803 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3804 struct lsa_CREDRWRITE *r)
3806 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3811 lsa_CREDRREAD
3813 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3814 struct lsa_CREDRREAD *r)
3816 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3821 lsa_CREDRENUMERATE
3823 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3824 struct lsa_CREDRENUMERATE *r)
3826 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3831 lsa_CREDRWRITEDOMAINCREDENTIALS
3833 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3834 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3836 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3841 lsa_CREDRREADDOMAINCREDENTIALS
3843 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3844 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3846 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3851 lsa_CREDRDELETE
3853 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3854 struct lsa_CREDRDELETE *r)
3856 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3861 lsa_CREDRGETTARGETINFO
3863 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3864 struct lsa_CREDRGETTARGETINFO *r)
3866 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3871 lsa_CREDRPROFILELOADED
3873 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3874 struct lsa_CREDRPROFILELOADED *r)
3876 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3881 lsa_CREDRGETSESSIONTYPES
3883 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3884 struct lsa_CREDRGETSESSIONTYPES *r)
3886 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3891 lsa_LSARREGISTERAUDITEVENT
3893 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3894 struct lsa_LSARREGISTERAUDITEVENT *r)
3896 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3901 lsa_LSARGENAUDITEVENT
3903 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3904 struct lsa_LSARGENAUDITEVENT *r)
3906 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3911 lsa_LSARUNREGISTERAUDITEVENT
3913 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3914 struct lsa_LSARUNREGISTERAUDITEVENT *r)
3916 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3921 lsa_lsaRQueryForestTrustInformation
3923 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3924 struct lsa_lsaRQueryForestTrustInformation *r)
3926 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3929 #define DNS_CMP_MATCH 0
3930 #define DNS_CMP_FIRST_IS_CHILD 1
3931 #define DNS_CMP_SECOND_IS_CHILD 2
3932 #define DNS_CMP_NO_MATCH 3
3934 /* this function assumes names are well formed DNS names.
3935 * it doesn't validate them */
3936 static int dns_cmp(const char *s1, size_t l1,
3937 const char *s2, size_t l2)
3939 const char *p1, *p2;
3940 size_t t1, t2;
3941 int cret;
3943 if (l1 == l2) {
3944 if (strcasecmp_m(s1, s2) == 0) {
3945 return DNS_CMP_MATCH;
3947 return DNS_CMP_NO_MATCH;
3950 if (l1 > l2) {
3951 p1 = s1;
3952 p2 = s2;
3953 t1 = l1;
3954 t2 = l2;
3955 cret = DNS_CMP_FIRST_IS_CHILD;
3956 } else {
3957 p1 = s2;
3958 p2 = s1;
3959 t1 = l2;
3960 t2 = l1;
3961 cret = DNS_CMP_SECOND_IS_CHILD;
3964 if (p1[t1 - t2 - 1] != '.') {
3965 return DNS_CMP_NO_MATCH;
3968 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3969 return cret;
3972 return DNS_CMP_NO_MATCH;
3975 /* decode all TDOs forest trust info blobs */
3976 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3977 struct ldb_message *msg,
3978 struct ForestTrustInfo *info)
3980 const struct ldb_val *ft_blob;
3981 enum ndr_err_code ndr_err;
3983 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3984 if (!ft_blob || !ft_blob->data) {
3985 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3987 /* ldb_val is equivalent to DATA_BLOB */
3988 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3989 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3990 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3991 return NT_STATUS_INVALID_DOMAIN_STATE;
3994 return NT_STATUS_OK;
3997 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
3998 struct ForestTrustInfo *fti)
4000 struct ForestTrustDataDomainInfo *info;
4001 struct ForestTrustInfoRecord *rec;
4003 fti->version = 1;
4004 fti->count = 2;
4005 fti->records = talloc_array(fti,
4006 struct ForestTrustInfoRecordArmor, 2);
4007 if (!fti->records) {
4008 return NT_STATUS_NO_MEMORY;
4011 /* TLN info */
4012 rec = &fti->records[0].record;
4014 rec->flags = 0;
4015 rec->timestamp = 0;
4016 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
4018 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
4019 if (!rec->data.name.string) {
4020 return NT_STATUS_NO_MEMORY;
4022 rec->data.name.size = strlen(rec->data.name.string);
4024 /* DOMAIN info */
4025 rec = &fti->records[1].record;
4027 rec->flags = 0;
4028 rec->timestamp = 0;
4029 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
4031 info = &rec->data.info;
4033 info->sid = *ps->domain_sid;
4034 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
4035 if (!info->dns_name.string) {
4036 return NT_STATUS_NO_MEMORY;
4038 info->dns_name.size = strlen(info->dns_name.string);
4039 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
4040 if (!info->netbios_name.string) {
4041 return NT_STATUS_NO_MEMORY;
4043 info->netbios_name.size = strlen(info->netbios_name.string);
4045 return NT_STATUS_OK;
4048 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
4049 struct lsa_ForestTrustInformation *lfti,
4050 struct ForestTrustInfo *fti)
4052 struct lsa_ForestTrustRecord *lrec;
4053 struct ForestTrustInfoRecord *rec;
4054 struct lsa_StringLarge *tln;
4055 struct lsa_ForestTrustDomainInfo *info;
4056 uint32_t i;
4058 fti->version = 1;
4059 fti->count = lfti->count;
4060 fti->records = talloc_array(mem_ctx,
4061 struct ForestTrustInfoRecordArmor,
4062 fti->count);
4063 if (!fti->records) {
4064 return NT_STATUS_NO_MEMORY;
4066 for (i = 0; i < fti->count; i++) {
4067 lrec = lfti->entries[i];
4068 rec = &fti->records[i].record;
4070 rec->flags = lrec->flags;
4071 rec->timestamp = lrec->time;
4072 rec->type = lrec->type;
4074 switch (lrec->type) {
4075 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4076 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4077 tln = &lrec->forest_trust_data.top_level_name;
4078 rec->data.name.string =
4079 talloc_strdup(mem_ctx, tln->string);
4080 if (!rec->data.name.string) {
4081 return NT_STATUS_NO_MEMORY;
4083 rec->data.name.size = strlen(rec->data.name.string);
4084 break;
4085 case LSA_FOREST_TRUST_DOMAIN_INFO:
4086 info = &lrec->forest_trust_data.domain_info;
4087 rec->data.info.sid = *info->domain_sid;
4088 rec->data.info.dns_name.string =
4089 talloc_strdup(mem_ctx,
4090 info->dns_domain_name.string);
4091 if (!rec->data.info.dns_name.string) {
4092 return NT_STATUS_NO_MEMORY;
4094 rec->data.info.dns_name.size =
4095 strlen(rec->data.info.dns_name.string);
4096 rec->data.info.netbios_name.string =
4097 talloc_strdup(mem_ctx,
4098 info->netbios_domain_name.string);
4099 if (!rec->data.info.netbios_name.string) {
4100 return NT_STATUS_NO_MEMORY;
4102 rec->data.info.netbios_name.size =
4103 strlen(rec->data.info.netbios_name.string);
4104 break;
4105 default:
4106 return NT_STATUS_INVALID_DOMAIN_STATE;
4110 return NT_STATUS_OK;
4113 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4114 uint32_t idx, uint32_t collision_type,
4115 uint32_t conflict_type, const char *tdo_name);
4117 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4118 const char *tdo_name,
4119 struct ForestTrustInfo *tdo_fti,
4120 struct ForestTrustInfo *new_fti,
4121 struct lsa_ForestTrustCollisionInfo *c_info)
4123 struct ForestTrustInfoRecord *nrec;
4124 struct ForestTrustInfoRecord *trec;
4125 const char *dns_name;
4126 const char *nb_name;
4127 struct dom_sid *sid;
4128 const char *tname;
4129 size_t dns_len;
4130 size_t nb_len;
4131 size_t tlen;
4132 NTSTATUS nt_status;
4133 uint32_t new_fti_idx;
4134 uint32_t i;
4135 /* use always TDO type, until we understand when Xref can be used */
4136 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4137 bool tln_conflict;
4138 bool sid_conflict;
4139 bool nb_conflict;
4140 bool exclusion;
4141 bool ex_rule;
4142 int ret;
4144 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4146 nrec = &new_fti->records[new_fti_idx].record;
4147 dns_name = NULL;
4148 tln_conflict = false;
4149 sid_conflict = false;
4150 nb_conflict = false;
4151 exclusion = false;
4153 switch (nrec->type) {
4154 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4155 /* exclusions do not conflict by definition */
4156 break;
4158 case FOREST_TRUST_TOP_LEVEL_NAME:
4159 dns_name = nrec->data.name.string;
4160 dns_len = nrec->data.name.size;
4161 break;
4163 case LSA_FOREST_TRUST_DOMAIN_INFO:
4164 dns_name = nrec->data.info.dns_name.string;
4165 dns_len = nrec->data.info.dns_name.size;
4166 nb_name = nrec->data.info.netbios_name.string;
4167 nb_len = nrec->data.info.netbios_name.size;
4168 sid = &nrec->data.info.sid;
4169 break;
4172 if (!dns_name) continue;
4174 /* check if this is already taken and not excluded */
4175 for (i = 0; i < tdo_fti->count; i++) {
4176 trec = &tdo_fti->records[i].record;
4178 switch (trec->type) {
4179 case FOREST_TRUST_TOP_LEVEL_NAME:
4180 ex_rule = false;
4181 tname = trec->data.name.string;
4182 tlen = trec->data.name.size;
4183 break;
4184 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4185 ex_rule = true;
4186 tname = trec->data.name.string;
4187 tlen = trec->data.name.size;
4188 break;
4189 case FOREST_TRUST_DOMAIN_INFO:
4190 ex_rule = false;
4191 tname = trec->data.info.dns_name.string;
4192 tlen = trec->data.info.dns_name.size;
4194 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4195 switch (ret) {
4196 case DNS_CMP_MATCH:
4197 /* if it matches exclusion,
4198 * it doesn't conflict */
4199 if (ex_rule) {
4200 exclusion = true;
4201 break;
4203 /* fall through */
4204 case DNS_CMP_FIRST_IS_CHILD:
4205 case DNS_CMP_SECOND_IS_CHILD:
4206 tln_conflict = true;
4207 /* fall through */
4208 default:
4209 break;
4212 /* explicit exclusion, no dns name conflict here */
4213 if (exclusion) {
4214 tln_conflict = false;
4217 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4218 continue;
4221 /* also test for domain info */
4222 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4223 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4224 sid_conflict = true;
4226 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4227 strcasecmp_m(trec->data.info.netbios_name.string,
4228 nb_name) == 0) {
4229 nb_conflict = true;
4233 if (tln_conflict) {
4234 nt_status = add_collision(c_info, new_fti_idx,
4235 collision_type,
4236 LSA_TLN_DISABLED_CONFLICT,
4237 tdo_name);
4239 if (sid_conflict) {
4240 nt_status = add_collision(c_info, new_fti_idx,
4241 collision_type,
4242 LSA_SID_DISABLED_CONFLICT,
4243 tdo_name);
4245 if (nb_conflict) {
4246 nt_status = add_collision(c_info, new_fti_idx,
4247 collision_type,
4248 LSA_NB_DISABLED_CONFLICT,
4249 tdo_name);
4253 return NT_STATUS_OK;
4256 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4257 uint32_t idx, uint32_t collision_type,
4258 uint32_t conflict_type, const char *tdo_name)
4260 struct lsa_ForestTrustCollisionRecord **es;
4261 uint32_t i = c_info->count;
4263 es = talloc_realloc(c_info, c_info->entries,
4264 struct lsa_ForestTrustCollisionRecord *, i + 1);
4265 if (!es) {
4266 return NT_STATUS_NO_MEMORY;
4268 c_info->entries = es;
4269 c_info->count = i + 1;
4271 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4272 if (!es[i]) {
4273 return NT_STATUS_NO_MEMORY;
4276 es[i]->index = idx;
4277 es[i]->type = collision_type;
4278 es[i]->flags.flags = conflict_type;
4279 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4280 if (!es[i]->name.string) {
4281 return NT_STATUS_NO_MEMORY;
4283 es[i]->name.size = strlen(es[i]->name.string);
4285 return NT_STATUS_OK;
4289 lsa_lsaRSetForestTrustInformation
4291 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4292 TALLOC_CTX *mem_ctx,
4293 struct lsa_lsaRSetForestTrustInformation *r)
4295 struct dcesrv_handle *h;
4296 struct lsa_policy_state *p_state;
4297 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4298 "msDS-TrustForestTrustInfo", NULL };
4299 struct ldb_message **dom_res = NULL;
4300 struct ldb_dn *tdo_dn;
4301 struct ldb_message *msg;
4302 int num_res, i;
4303 const char *td_name;
4304 uint32_t trust_attributes;
4305 struct lsa_ForestTrustCollisionInfo *c_info;
4306 struct ForestTrustInfo *nfti;
4307 struct ForestTrustInfo *fti;
4308 DATA_BLOB ft_blob;
4309 enum ndr_err_code ndr_err;
4310 NTSTATUS nt_status;
4311 bool am_rodc;
4312 int ret;
4314 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4316 p_state = h->data;
4318 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4319 return NT_STATUS_INVALID_DOMAIN_STATE;
4322 /* abort if we are not a PDC */
4323 if (!samdb_is_pdc(p_state->sam_ldb)) {
4324 return NT_STATUS_INVALID_DOMAIN_ROLE;
4327 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4328 if (ret == LDB_SUCCESS && am_rodc) {
4329 return NT_STATUS_NO_SUCH_DOMAIN;
4332 /* check caller has TRUSTED_SET_AUTH */
4334 /* fetch all trusted domain objects */
4335 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4336 p_state->system_dn,
4337 &dom_res, trust_attrs,
4338 "(objectclass=trustedDomain)");
4339 if (num_res == 0) {
4340 return NT_STATUS_NO_SUCH_DOMAIN;
4343 for (i = 0; i < num_res; i++) {
4344 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4345 "trustPartner", NULL);
4346 if (!td_name) {
4347 return NT_STATUS_INVALID_DOMAIN_STATE;
4349 if (strcasecmp_m(td_name,
4350 r->in.trusted_domain_name->string) == 0) {
4351 break;
4354 if (i >= num_res) {
4355 return NT_STATUS_NO_SUCH_DOMAIN;
4358 tdo_dn = dom_res[i]->dn;
4360 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4361 "trustAttributes", 0);
4362 if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4363 return NT_STATUS_INVALID_PARAMETER;
4366 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4367 return NT_STATUS_INVALID_PARAMETER;
4370 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4371 if (!nfti) {
4372 return NT_STATUS_NO_MEMORY;
4375 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4376 if (!NT_STATUS_IS_OK(nt_status)) {
4377 return nt_status;
4380 c_info = talloc_zero(r->out.collision_info,
4381 struct lsa_ForestTrustCollisionInfo);
4382 if (!c_info) {
4383 return NT_STATUS_NO_MEMORY;
4386 /* first check own info, then other domains */
4387 fti = talloc(mem_ctx, struct ForestTrustInfo);
4388 if (!fti) {
4389 return NT_STATUS_NO_MEMORY;
4392 nt_status = own_ft_info(p_state, fti);
4393 if (!NT_STATUS_IS_OK(nt_status)) {
4394 return nt_status;
4397 nt_status = check_ft_info(c_info, p_state->domain_dns,
4398 fti, nfti, c_info);
4399 if (!NT_STATUS_IS_OK(nt_status)) {
4400 return nt_status;
4403 for (i = 0; i < num_res; i++) {
4404 fti = talloc(mem_ctx, struct ForestTrustInfo);
4405 if (!fti) {
4406 return NT_STATUS_NO_MEMORY;
4409 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4410 if (!NT_STATUS_IS_OK(nt_status)) {
4411 if (NT_STATUS_EQUAL(nt_status,
4412 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4413 continue;
4415 return nt_status;
4418 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4419 "trustPartner", NULL);
4420 if (!td_name) {
4421 return NT_STATUS_INVALID_DOMAIN_STATE;
4424 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4425 if (!NT_STATUS_IS_OK(nt_status)) {
4426 return nt_status;
4430 *r->out.collision_info = c_info;
4432 if (r->in.check_only != 0) {
4433 return NT_STATUS_OK;
4436 /* not just a check, write info back */
4438 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4439 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4440 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4441 return NT_STATUS_INVALID_PARAMETER;
4444 msg = ldb_msg_new(mem_ctx);
4445 if (msg == NULL) {
4446 return NT_STATUS_NO_MEMORY;
4449 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4450 if (!msg->dn) {
4451 return NT_STATUS_NO_MEMORY;
4454 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4455 LDB_FLAG_MOD_REPLACE, NULL);
4456 if (ret != LDB_SUCCESS) {
4457 return NT_STATUS_NO_MEMORY;
4459 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4460 &ft_blob, NULL);
4461 if (ret != LDB_SUCCESS) {
4462 return NT_STATUS_NO_MEMORY;
4465 ret = ldb_modify(p_state->sam_ldb, msg);
4466 if (ret != LDB_SUCCESS) {
4467 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4468 ldb_errstring(p_state->sam_ldb)));
4470 switch (ret) {
4471 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4472 return NT_STATUS_ACCESS_DENIED;
4473 default:
4474 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4478 return NT_STATUS_OK;
4482 lsa_CREDRRENAME
4484 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4485 struct lsa_CREDRRENAME *r)
4487 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4493 lsa_LSAROPENPOLICYSCE
4495 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4496 struct lsa_LSAROPENPOLICYSCE *r)
4498 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4503 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4505 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4506 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4508 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4513 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4515 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4516 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4518 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4523 lsa_LSARADTREPORTSECURITYEVENT
4525 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4526 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4528 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4532 /* include the generated boilerplate */
4533 #include "librpc/gen_ndr/ndr_lsa_s.c"
4537 /*****************************************
4538 NOTE! The remaining calls below were
4539 removed in w2k3, so the DCESRV_FAULT()
4540 replies are the correct implementation. Do
4541 not try and fill these in with anything else
4542 ******************************************/
4545 dssetup_DsRoleDnsNameToFlatName
4547 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4548 struct dssetup_DsRoleDnsNameToFlatName *r)
4550 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4555 dssetup_DsRoleDcAsDc
4557 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4558 struct dssetup_DsRoleDcAsDc *r)
4560 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4565 dssetup_DsRoleDcAsReplica
4567 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4568 struct dssetup_DsRoleDcAsReplica *r)
4570 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4575 dssetup_DsRoleDemoteDc
4577 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4578 struct dssetup_DsRoleDemoteDc *r)
4580 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4585 dssetup_DsRoleGetDcOperationProgress
4587 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4588 struct dssetup_DsRoleGetDcOperationProgress *r)
4590 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4595 dssetup_DsRoleGetDcOperationResults
4597 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4598 struct dssetup_DsRoleGetDcOperationResults *r)
4600 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4605 dssetup_DsRoleCancel
4607 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4608 struct dssetup_DsRoleCancel *r)
4610 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4615 dssetup_DsRoleServerSaveStateForUpgrade
4617 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4618 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4620 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4625 dssetup_DsRoleUpgradeDownlevelServer
4627 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4628 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4630 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4635 dssetup_DsRoleAbortDownlevelServerUpgrade
4637 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4638 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4640 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4644 /* include the generated boilerplate */
4645 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4647 NTSTATUS dcerpc_server_lsa_init(void)
4649 NTSTATUS ret;
4651 ret = dcerpc_server_dssetup_init();
4652 if (!NT_STATUS_IS_OK(ret)) {
4653 return ret;
4655 ret = dcerpc_server_lsarpc_init();
4656 if (!NT_STATUS_IS_OK(ret)) {
4657 return ret;
4659 return ret;