CVE-2014-8143:dsdb-samldb: Check for extended access rights before we allow changes...
[Samba.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
blob648e31dbde6d7bd4cdeb3211007491b8a6177392
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_request *req;
795 struct ldb_message *msg;
796 struct ldb_dn *dn;
797 uint32_t i;
798 int ret;
800 dn = ldb_dn_copy(mem_ctx, base_dn);
801 if (!dn) {
802 return NT_STATUS_NO_MEMORY;
804 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
805 return NT_STATUS_NO_MEMORY;
808 msg = ldb_msg_new(mem_ctx);
809 if (!msg) {
810 return NT_STATUS_NO_MEMORY;
812 msg->dn = dn;
814 ret = ldb_msg_add_string(msg, "objectClass", "user");
815 if (ret != LDB_SUCCESS) {
816 return NT_STATUS_NO_MEMORY;
819 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
820 if (ret != LDB_SUCCESS) {
821 return NT_STATUS_NO_MEMORY;
824 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
825 UF_INTERDOMAIN_TRUST_ACCOUNT);
826 if (ret != LDB_SUCCESS) {
827 return NT_STATUS_NO_MEMORY;
830 for (i = 0; i < in->count; i++) {
831 const char *attribute;
832 struct ldb_val v;
833 switch (in->current.array[i].AuthType) {
834 case TRUST_AUTH_TYPE_NT4OWF:
835 attribute = "unicodePwd";
836 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
837 v.length = 16;
838 break;
839 case TRUST_AUTH_TYPE_CLEAR:
840 attribute = "clearTextPassword";
841 v.data = in->current.array[i].AuthInfo.clear.password;
842 v.length = in->current.array[i].AuthInfo.clear.size;
843 break;
844 default:
845 continue;
848 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
849 if (ret != LDB_SUCCESS) {
850 return NT_STATUS_NO_MEMORY;
854 /* create the trusted_domain user account */
855 ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
856 ldb_op_default_callback, NULL);
857 if (ret != LDB_SUCCESS) {
858 return NT_STATUS_NO_MEMORY;
861 ret = ldb_request_add_control(req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
862 false, NULL);
863 if (ret != LDB_SUCCESS) {
864 return NT_STATUS_NO_MEMORY;
867 ret = dsdb_autotransaction_request(sam_ldb, req);
868 if (ret != LDB_SUCCESS) {
869 DEBUG(0,("Failed to create user record %s: %s\n",
870 ldb_dn_get_linearized(msg->dn),
871 ldb_errstring(sam_ldb)));
873 switch (ret) {
874 case LDB_ERR_ENTRY_ALREADY_EXISTS:
875 return NT_STATUS_DOMAIN_EXISTS;
876 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
877 return NT_STATUS_ACCESS_DENIED;
878 default:
879 return NT_STATUS_INTERNAL_DB_CORRUPTION;
883 if (user_dn) {
884 *user_dn = dn;
886 return NT_STATUS_OK;
890 lsa_CreateTrustedDomainEx2
892 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
893 TALLOC_CTX *mem_ctx,
894 struct lsa_CreateTrustedDomainEx2 *r,
895 int op,
896 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
898 struct dcesrv_handle *policy_handle;
899 struct lsa_policy_state *policy_state;
900 struct lsa_trusted_domain_state *trusted_domain_state;
901 struct dcesrv_handle *handle;
902 struct ldb_message **msgs, *msg;
903 const char *attrs[] = {
904 NULL
906 const char *netbios_name;
907 const char *dns_name;
908 const char *name;
909 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
910 struct trustDomainPasswords auth_struct;
911 int ret;
912 NTSTATUS nt_status;
913 struct ldb_context *sam_ldb;
915 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
916 ZERO_STRUCTP(r->out.trustdom_handle);
918 policy_state = policy_handle->data;
919 sam_ldb = policy_state->sam_ldb;
921 netbios_name = r->in.info->netbios_name.string;
922 if (!netbios_name) {
923 return NT_STATUS_INVALID_PARAMETER;
926 dns_name = r->in.info->domain_name.string;
928 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
929 if (!trusted_domain_state) {
930 return NT_STATUS_NO_MEMORY;
932 trusted_domain_state->policy = policy_state;
934 if (strcasecmp(netbios_name, "BUILTIN") == 0
935 || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
936 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
937 return NT_STATUS_INVALID_PARAMETER;
940 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
941 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
942 || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
943 || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
944 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
945 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
948 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
949 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
950 /* No secrets are created at this time, for this function */
951 auth_struct.outgoing.count = 0;
952 auth_struct.incoming.count = 0;
953 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
954 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
955 r->in.auth_info_internal->auth_blob.size);
956 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
957 &auth_blob, &auth_struct);
958 if (!NT_STATUS_IS_OK(nt_status)) {
959 return nt_status;
961 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
963 if (unencrypted_auth_info->incoming_count > 1) {
964 return NT_STATUS_INVALID_PARAMETER;
967 /* more investigation required here, do not create secrets for
968 * now */
969 auth_struct.outgoing.count = 0;
970 auth_struct.incoming.count = 0;
971 } else {
972 return NT_STATUS_INVALID_PARAMETER;
975 if (auth_struct.incoming.count) {
976 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
977 &auth_struct.incoming,
978 &trustAuthIncoming);
979 if (!NT_STATUS_IS_OK(nt_status)) {
980 return nt_status;
982 } else {
983 trustAuthIncoming = data_blob(NULL, 0);
986 if (auth_struct.outgoing.count) {
987 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
988 &auth_struct.outgoing,
989 &trustAuthOutgoing);
990 if (!NT_STATUS_IS_OK(nt_status)) {
991 return nt_status;
993 } else {
994 trustAuthOutgoing = data_blob(NULL, 0);
997 ret = ldb_transaction_start(sam_ldb);
998 if (ret != LDB_SUCCESS) {
999 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1002 if (dns_name) {
1003 char *dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1004 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1005 /* search for the trusted_domain record */
1006 ret = gendb_search(sam_ldb,
1007 mem_ctx, policy_state->system_dn, &msgs, attrs,
1008 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1009 dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
1010 if (ret > 0) {
1011 ldb_transaction_cancel(sam_ldb);
1012 return NT_STATUS_OBJECT_NAME_COLLISION;
1014 } else {
1015 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1016 /* search for the trusted_domain record */
1017 ret = gendb_search(sam_ldb,
1018 mem_ctx, policy_state->system_dn, &msgs, attrs,
1019 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1020 netbios_encoded, netbios_encoded, netbios_encoded);
1021 if (ret > 0) {
1022 ldb_transaction_cancel(sam_ldb);
1023 return NT_STATUS_OBJECT_NAME_COLLISION;
1027 if (ret < 0 ) {
1028 ldb_transaction_cancel(sam_ldb);
1029 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1032 name = dns_name ? dns_name : netbios_name;
1034 msg = ldb_msg_new(mem_ctx);
1035 if (msg == NULL) {
1036 return NT_STATUS_NO_MEMORY;
1039 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1040 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1041 ldb_transaction_cancel(sam_ldb);
1042 return NT_STATUS_NO_MEMORY;
1045 ldb_msg_add_string(msg, "flatname", netbios_name);
1047 if (r->in.info->sid) {
1048 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1049 if (ret != LDB_SUCCESS) {
1050 ldb_transaction_cancel(sam_ldb);
1051 return NT_STATUS_INVALID_PARAMETER;
1055 ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1057 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1059 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1061 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1063 if (dns_name) {
1064 ldb_msg_add_string(msg, "trustPartner", dns_name);
1067 if (trustAuthIncoming.data) {
1068 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1069 if (ret != LDB_SUCCESS) {
1070 ldb_transaction_cancel(sam_ldb);
1071 return NT_STATUS_NO_MEMORY;
1074 if (trustAuthOutgoing.data) {
1075 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1076 if (ret != LDB_SUCCESS) {
1077 ldb_transaction_cancel(sam_ldb);
1078 return NT_STATUS_NO_MEMORY;
1082 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1084 /* create the trusted_domain */
1085 ret = ldb_add(sam_ldb, msg);
1086 switch (ret) {
1087 case LDB_SUCCESS:
1088 break;
1089 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1090 ldb_transaction_cancel(sam_ldb);
1091 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1092 ldb_dn_get_linearized(msg->dn),
1093 ldb_errstring(sam_ldb)));
1094 return NT_STATUS_DOMAIN_EXISTS;
1095 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1096 ldb_transaction_cancel(sam_ldb);
1097 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1098 ldb_dn_get_linearized(msg->dn),
1099 ldb_errstring(sam_ldb)));
1100 return NT_STATUS_ACCESS_DENIED;
1101 default:
1102 ldb_transaction_cancel(sam_ldb);
1103 DEBUG(0,("Failed to create user record %s: %s\n",
1104 ldb_dn_get_linearized(msg->dn),
1105 ldb_errstring(sam_ldb)));
1106 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1109 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1110 struct ldb_dn *user_dn;
1111 /* Inbound trusts must also create a cn=users object to match */
1112 nt_status = add_trust_user(mem_ctx, sam_ldb,
1113 policy_state->domain_dn,
1114 netbios_name,
1115 &auth_struct.incoming,
1116 &user_dn);
1117 if (!NT_STATUS_IS_OK(nt_status)) {
1118 ldb_transaction_cancel(sam_ldb);
1119 return nt_status;
1122 /* save the trust user dn */
1123 trusted_domain_state->trusted_domain_user_dn
1124 = talloc_steal(trusted_domain_state, user_dn);
1127 ret = ldb_transaction_commit(sam_ldb);
1128 if (ret != LDB_SUCCESS) {
1129 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1132 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1133 if (!handle) {
1134 return NT_STATUS_NO_MEMORY;
1137 handle->data = talloc_steal(handle, trusted_domain_state);
1139 trusted_domain_state->access_mask = r->in.access_mask;
1140 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1142 *r->out.trustdom_handle = handle->wire_handle;
1144 return NT_STATUS_OK;
1148 lsa_CreateTrustedDomainEx2
1150 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1151 TALLOC_CTX *mem_ctx,
1152 struct lsa_CreateTrustedDomainEx2 *r)
1154 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1157 lsa_CreateTrustedDomainEx
1159 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1160 TALLOC_CTX *mem_ctx,
1161 struct lsa_CreateTrustedDomainEx *r)
1163 struct lsa_CreateTrustedDomainEx2 r2;
1165 r2.in.policy_handle = r->in.policy_handle;
1166 r2.in.info = r->in.info;
1167 r2.out.trustdom_handle = r->out.trustdom_handle;
1168 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1172 lsa_CreateTrustedDomain
1174 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1175 struct lsa_CreateTrustedDomain *r)
1177 struct lsa_CreateTrustedDomainEx2 r2;
1179 r2.in.policy_handle = r->in.policy_handle;
1180 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1181 if (!r2.in.info) {
1182 return NT_STATUS_NO_MEMORY;
1185 r2.in.info->domain_name.string = NULL;
1186 r2.in.info->netbios_name = r->in.info->name;
1187 r2.in.info->sid = r->in.info->sid;
1188 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1189 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1190 r2.in.info->trust_attributes = 0;
1192 r2.in.access_mask = r->in.access_mask;
1193 r2.out.trustdom_handle = r->out.trustdom_handle;
1195 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1200 lsa_OpenTrustedDomain
1202 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1203 struct lsa_OpenTrustedDomain *r)
1205 struct dcesrv_handle *policy_handle;
1207 struct lsa_policy_state *policy_state;
1208 struct lsa_trusted_domain_state *trusted_domain_state;
1209 struct dcesrv_handle *handle;
1210 struct ldb_message **msgs;
1211 const char *attrs[] = {
1212 "trustDirection",
1213 "flatname",
1214 NULL
1217 const char *sid_string;
1218 int ret;
1220 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1221 ZERO_STRUCTP(r->out.trustdom_handle);
1222 policy_state = policy_handle->data;
1224 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1225 if (!trusted_domain_state) {
1226 return NT_STATUS_NO_MEMORY;
1228 trusted_domain_state->policy = policy_state;
1230 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1231 if (!sid_string) {
1232 return NT_STATUS_NO_MEMORY;
1235 /* search for the trusted_domain record */
1236 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1237 mem_ctx, policy_state->system_dn, &msgs, attrs,
1238 "(&(securityIdentifier=%s)(objectclass=trustedDomain))",
1239 sid_string);
1240 if (ret == 0) {
1241 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1244 if (ret != 1) {
1245 DEBUG(0,("Found %d records matching DN %s\n", ret,
1246 ldb_dn_get_linearized(policy_state->system_dn)));
1247 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1250 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1252 trusted_domain_state->trusted_domain_user_dn = NULL;
1254 if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1255 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1256 /* search for the trusted_domain record */
1257 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1258 mem_ctx, policy_state->domain_dn, &msgs, attrs,
1259 "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%u))",
1260 flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1261 if (ret == 1) {
1262 trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1265 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1266 if (!handle) {
1267 return NT_STATUS_NO_MEMORY;
1270 handle->data = talloc_steal(handle, trusted_domain_state);
1272 trusted_domain_state->access_mask = r->in.access_mask;
1273 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1275 *r->out.trustdom_handle = handle->wire_handle;
1277 return NT_STATUS_OK;
1282 lsa_OpenTrustedDomainByName
1284 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1285 TALLOC_CTX *mem_ctx,
1286 struct lsa_OpenTrustedDomainByName *r)
1288 struct dcesrv_handle *policy_handle;
1290 struct lsa_policy_state *policy_state;
1291 struct lsa_trusted_domain_state *trusted_domain_state;
1292 struct dcesrv_handle *handle;
1293 struct ldb_message **msgs;
1294 const char *attrs[] = {
1295 NULL
1297 char *td_name;
1298 int ret;
1300 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1301 ZERO_STRUCTP(r->out.trustdom_handle);
1302 policy_state = policy_handle->data;
1304 if (!r->in.name.string) {
1305 return NT_STATUS_INVALID_PARAMETER;
1308 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1309 if (!trusted_domain_state) {
1310 return NT_STATUS_NO_MEMORY;
1312 trusted_domain_state->policy = policy_state;
1314 /* search for the trusted_domain record */
1315 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1316 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1317 mem_ctx, policy_state->system_dn, &msgs, attrs,
1318 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1319 "(objectclass=trustedDomain))",
1320 td_name, td_name, td_name);
1321 if (ret == 0) {
1322 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1325 if (ret != 1) {
1326 DEBUG(0,("Found %d records matching DN %s\n", ret,
1327 ldb_dn_get_linearized(policy_state->system_dn)));
1328 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1331 /* TODO: perform access checks */
1333 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1335 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1336 if (!handle) {
1337 return NT_STATUS_NO_MEMORY;
1340 handle->data = talloc_steal(handle, trusted_domain_state);
1342 trusted_domain_state->access_mask = r->in.access_mask;
1343 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1345 *r->out.trustdom_handle = handle->wire_handle;
1347 return NT_STATUS_OK;
1353 lsa_SetTrustedDomainInfo
1355 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1356 struct lsa_SetTrustedDomainInfo *r)
1358 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1363 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1364 * otherwise at least one must be provided */
1365 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1366 struct ldb_dn *basedn, const char *dns_domain,
1367 const char *netbios, struct dom_sid2 *sid,
1368 struct ldb_message ***msgs)
1370 const char *attrs[] = { "flatname", "trustPartner",
1371 "securityIdentifier", "trustDirection",
1372 "trustType", "trustAttributes",
1373 "trustPosixOffset",
1374 "msDs-supportedEncryptionTypes", NULL };
1375 char *dns = NULL;
1376 char *nbn = NULL;
1377 char *sidstr = NULL;
1378 char *filter;
1379 int ret;
1382 if (dns_domain || netbios || sid) {
1383 filter = talloc_strdup(mem_ctx,
1384 "(&(objectclass=trustedDomain)(|");
1385 } else {
1386 filter = talloc_strdup(mem_ctx,
1387 "(objectclass=trustedDomain)");
1389 if (!filter) {
1390 return NT_STATUS_NO_MEMORY;
1393 if (dns_domain) {
1394 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1395 if (!dns) {
1396 return NT_STATUS_NO_MEMORY;
1398 filter = talloc_asprintf_append(filter,
1399 "(trustPartner=%s)", dns);
1400 if (!filter) {
1401 return NT_STATUS_NO_MEMORY;
1404 if (netbios) {
1405 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1406 if (!nbn) {
1407 return NT_STATUS_NO_MEMORY;
1409 filter = talloc_asprintf_append(filter,
1410 "(flatname=%s)", nbn);
1411 if (!filter) {
1412 return NT_STATUS_NO_MEMORY;
1415 if (sid) {
1416 sidstr = dom_sid_string(mem_ctx, sid);
1417 if (!sidstr) {
1418 return NT_STATUS_INVALID_PARAMETER;
1420 filter = talloc_asprintf_append(filter,
1421 "(securityIdentifier=%s)",
1422 sidstr);
1423 if (!filter) {
1424 return NT_STATUS_NO_MEMORY;
1427 if (dns_domain || netbios || sid) {
1428 filter = talloc_asprintf_append(filter, "))");
1429 if (!filter) {
1430 return NT_STATUS_NO_MEMORY;
1434 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1435 if (ret == 0) {
1436 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1439 if (ret != 1) {
1440 return NT_STATUS_OBJECT_NAME_COLLISION;
1443 return NT_STATUS_OK;
1446 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1447 struct ldb_context *sam_ldb,
1448 struct ldb_message *orig,
1449 struct ldb_message *dest,
1450 const char *attribute,
1451 uint32_t value,
1452 uint32_t *orig_value)
1454 const struct ldb_val *orig_val;
1455 uint32_t orig_uint = 0;
1456 unsigned int flags = 0;
1457 int ret;
1459 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1460 if (!orig_val || !orig_val->data) {
1461 /* add new attribute */
1462 flags = LDB_FLAG_MOD_ADD;
1464 } else {
1465 errno = 0;
1466 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1467 if (errno != 0 || orig_uint != value) {
1468 /* replace also if can't get value */
1469 flags = LDB_FLAG_MOD_REPLACE;
1473 if (flags == 0) {
1474 /* stored value is identical, nothing to change */
1475 goto done;
1478 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1479 if (ret != LDB_SUCCESS) {
1480 return NT_STATUS_NO_MEMORY;
1483 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1484 if (ret != LDB_SUCCESS) {
1485 return NT_STATUS_NO_MEMORY;
1488 done:
1489 if (orig_value) {
1490 *orig_value = orig_uint;
1492 return NT_STATUS_OK;
1495 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1496 struct ldb_context *sam_ldb,
1497 struct ldb_dn *base_dn,
1498 bool delete_user,
1499 const char *netbios_name,
1500 struct trustAuthInOutBlob *in)
1502 const char *attrs[] = { "userAccountControl", NULL };
1503 struct ldb_message **msgs;
1504 struct ldb_message *msg;
1505 uint32_t uac;
1506 uint32_t i;
1507 int ret;
1509 ret = gendb_search(sam_ldb, mem_ctx,
1510 base_dn, &msgs, attrs,
1511 "samAccountName=%s$", netbios_name);
1512 if (ret > 1) {
1513 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1516 if (ret == 0) {
1517 if (delete_user) {
1518 return NT_STATUS_OK;
1521 /* ok no existing user, add it from scratch */
1522 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1523 netbios_name, in, NULL);
1526 /* check user is what we are looking for */
1527 uac = ldb_msg_find_attr_as_uint(msgs[0],
1528 "userAccountControl", 0);
1529 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1530 return NT_STATUS_OBJECT_NAME_COLLISION;
1533 if (delete_user) {
1534 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1535 switch (ret) {
1536 case LDB_SUCCESS:
1537 return NT_STATUS_OK;
1538 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1539 return NT_STATUS_ACCESS_DENIED;
1540 default:
1541 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1545 /* entry exists, just modify secret if any */
1546 if (in == NULL || in->count == 0) {
1547 return NT_STATUS_OK;
1550 msg = ldb_msg_new(mem_ctx);
1551 if (!msg) {
1552 return NT_STATUS_NO_MEMORY;
1554 msg->dn = msgs[0]->dn;
1556 for (i = 0; i < in->count; i++) {
1557 const char *attribute;
1558 struct ldb_val v;
1559 switch (in->current.array[i].AuthType) {
1560 case TRUST_AUTH_TYPE_NT4OWF:
1561 attribute = "unicodePwd";
1562 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1563 v.length = 16;
1564 break;
1565 case TRUST_AUTH_TYPE_CLEAR:
1566 attribute = "clearTextPassword";
1567 v.data = in->current.array[i].AuthInfo.clear.password;
1568 v.length = in->current.array[i].AuthInfo.clear.size;
1569 break;
1570 default:
1571 continue;
1574 ret = ldb_msg_add_empty(msg, attribute,
1575 LDB_FLAG_MOD_REPLACE, NULL);
1576 if (ret != LDB_SUCCESS) {
1577 return NT_STATUS_NO_MEMORY;
1580 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1581 if (ret != LDB_SUCCESS) {
1582 return NT_STATUS_NO_MEMORY;
1586 /* create the trusted_domain user account */
1587 ret = ldb_modify(sam_ldb, msg);
1588 if (ret != LDB_SUCCESS) {
1589 DEBUG(0,("Failed to create user record %s: %s\n",
1590 ldb_dn_get_linearized(msg->dn),
1591 ldb_errstring(sam_ldb)));
1593 switch (ret) {
1594 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1595 return NT_STATUS_DOMAIN_EXISTS;
1596 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1597 return NT_STATUS_ACCESS_DENIED;
1598 default:
1599 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1603 return NT_STATUS_OK;
1607 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1608 struct dcesrv_handle *p_handle,
1609 TALLOC_CTX *mem_ctx,
1610 struct ldb_message *dom_msg,
1611 enum lsa_TrustDomInfoEnum level,
1612 union lsa_TrustedDomainInfo *info)
1614 struct lsa_policy_state *p_state = p_handle->data;
1615 uint32_t *posix_offset = NULL;
1616 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1617 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1618 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1619 uint32_t *enc_types = NULL;
1620 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1621 struct trustDomainPasswords auth_struct;
1622 struct trustAuthInOutBlob *current_passwords = NULL;
1623 NTSTATUS nt_status;
1624 struct ldb_message **msgs;
1625 struct ldb_message *msg;
1626 bool add_outgoing = false;
1627 bool add_incoming = false;
1628 bool del_outgoing = false;
1629 bool del_incoming = false;
1630 bool in_transaction = false;
1631 int ret;
1632 bool am_rodc;
1634 switch (level) {
1635 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1636 posix_offset = &info->posix_offset.posix_offset;
1637 break;
1638 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1639 info_ex = &info->info_ex;
1640 break;
1641 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1642 auth_info = &info->auth_info;
1643 break;
1644 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1645 posix_offset = &info->full_info.posix_offset.posix_offset;
1646 info_ex = &info->full_info.info_ex;
1647 auth_info = &info->full_info.auth_info;
1648 break;
1649 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1650 auth_info_int = &info->auth_info_internal;
1651 break;
1652 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1653 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1654 info_ex = &info->full_info_internal.info_ex;
1655 auth_info_int = &info->full_info_internal.auth_info;
1656 break;
1657 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1658 enc_types = &info->enc_types.enc_types;
1659 break;
1660 default:
1661 return NT_STATUS_INVALID_PARAMETER;
1664 if (auth_info) {
1665 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1666 &trustAuthIncoming,
1667 &trustAuthOutgoing);
1668 if (!NT_STATUS_IS_OK(nt_status)) {
1669 return nt_status;
1671 if (trustAuthIncoming.data) {
1672 /* This does the decode of some of this twice, but it is easier that way */
1673 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1674 auth_info->incoming_count,
1675 auth_info->incoming_current_auth_info,
1676 NULL,
1677 &current_passwords);
1678 if (!NT_STATUS_IS_OK(nt_status)) {
1679 return nt_status;
1684 /* decode auth_info_int if set */
1685 if (auth_info_int) {
1687 /* now decrypt blob */
1688 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1689 auth_info_int->auth_blob.size);
1691 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1692 &auth_blob, &auth_struct);
1693 if (!NT_STATUS_IS_OK(nt_status)) {
1694 return nt_status;
1698 if (info_ex) {
1699 /* verify data matches */
1700 if (info_ex->trust_attributes &
1701 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1702 /* TODO: check what behavior level we have */
1703 if (strcasecmp_m(p_state->domain_dns,
1704 p_state->forest_dns) != 0) {
1705 return NT_STATUS_INVALID_DOMAIN_STATE;
1709 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1710 if (ret == LDB_SUCCESS && am_rodc) {
1711 return NT_STATUS_NO_SUCH_DOMAIN;
1714 /* verify only one object matches the dns/netbios/sid
1715 * triplet and that this is the one we already have */
1716 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1717 p_state->system_dn,
1718 info_ex->domain_name.string,
1719 info_ex->netbios_name.string,
1720 info_ex->sid, &msgs);
1721 if (!NT_STATUS_IS_OK(nt_status)) {
1722 return nt_status;
1724 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1725 return NT_STATUS_OBJECT_NAME_COLLISION;
1727 talloc_free(msgs);
1730 /* TODO: should we fetch previous values from the existing entry
1731 * and append them ? */
1732 if (auth_info_int && auth_struct.incoming.count) {
1733 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1734 &auth_struct.incoming,
1735 &trustAuthIncoming);
1736 if (!NT_STATUS_IS_OK(nt_status)) {
1737 return nt_status;
1740 current_passwords = &auth_struct.incoming;
1742 } else {
1743 trustAuthIncoming = data_blob(NULL, 0);
1746 if (auth_info_int && auth_struct.outgoing.count) {
1747 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1748 &auth_struct.outgoing,
1749 &trustAuthOutgoing);
1750 if (!NT_STATUS_IS_OK(nt_status)) {
1751 return nt_status;
1753 } else {
1754 trustAuthOutgoing = data_blob(NULL, 0);
1757 msg = ldb_msg_new(mem_ctx);
1758 if (msg == NULL) {
1759 return NT_STATUS_NO_MEMORY;
1761 msg->dn = dom_msg->dn;
1763 if (posix_offset) {
1764 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1765 dom_msg, msg,
1766 "trustPosixOffset",
1767 *posix_offset, NULL);
1768 if (!NT_STATUS_IS_OK(nt_status)) {
1769 return nt_status;
1773 if (info_ex) {
1774 uint32_t origattrs;
1775 uint32_t origdir;
1776 int origtype;
1778 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1779 dom_msg, msg,
1780 "trustDirection",
1781 info_ex->trust_direction,
1782 &origdir);
1783 if (!NT_STATUS_IS_OK(nt_status)) {
1784 return nt_status;
1787 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1788 add_incoming = true;
1790 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1791 add_outgoing = true;
1794 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1795 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1796 del_incoming = true;
1798 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1799 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1800 del_outgoing = true;
1803 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1804 if (origtype == -1 || origtype != info_ex->trust_type) {
1805 DEBUG(1, ("Attempted to change trust type! "
1806 "Operation not handled\n"));
1807 return NT_STATUS_INVALID_PARAMETER;
1810 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1811 dom_msg, msg,
1812 "trustAttributes",
1813 info_ex->trust_attributes,
1814 &origattrs);
1815 if (!NT_STATUS_IS_OK(nt_status)) {
1816 return nt_status;
1818 /* TODO: check forestFunctionality from ldb opaque */
1819 /* TODO: check what is set makes sense */
1820 /* for now refuse changes */
1821 if (origattrs == -1 ||
1822 origattrs != info_ex->trust_attributes) {
1823 DEBUG(1, ("Attempted to change trust attributes! "
1824 "Operation not handled\n"));
1825 return NT_STATUS_INVALID_PARAMETER;
1829 if (enc_types) {
1830 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1831 dom_msg, msg,
1832 "msDS-SupportedEncryptionTypes",
1833 *enc_types, NULL);
1834 if (!NT_STATUS_IS_OK(nt_status)) {
1835 return nt_status;
1839 if (add_incoming && trustAuthIncoming.data) {
1840 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1841 LDB_FLAG_MOD_REPLACE, NULL);
1842 if (ret != LDB_SUCCESS) {
1843 return NT_STATUS_NO_MEMORY;
1845 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1846 &trustAuthIncoming, NULL);
1847 if (ret != LDB_SUCCESS) {
1848 return NT_STATUS_NO_MEMORY;
1851 if (add_outgoing && trustAuthOutgoing.data) {
1852 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1853 LDB_FLAG_MOD_REPLACE, NULL);
1854 if (ret != LDB_SUCCESS) {
1855 return NT_STATUS_NO_MEMORY;
1857 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1858 &trustAuthOutgoing, NULL);
1859 if (ret != LDB_SUCCESS) {
1860 return NT_STATUS_NO_MEMORY;
1864 /* start transaction */
1865 ret = ldb_transaction_start(p_state->sam_ldb);
1866 if (ret != LDB_SUCCESS) {
1867 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1869 in_transaction = true;
1871 if (msg->num_elements) {
1872 ret = ldb_modify(p_state->sam_ldb, msg);
1873 if (ret != LDB_SUCCESS) {
1874 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1875 ldb_dn_get_linearized(msg->dn),
1876 ldb_errstring(p_state->sam_ldb)));
1877 nt_status = dsdb_ldb_err_to_ntstatus(ret);
1878 goto done;
1882 if (add_incoming || del_incoming) {
1883 const char *netbios_name;
1885 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1886 "flatname", NULL);
1887 if (!netbios_name) {
1888 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1889 goto done;
1892 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
1893 nt_status = update_trust_user(mem_ctx,
1894 p_state->sam_ldb,
1895 p_state->domain_dn,
1896 del_incoming,
1897 netbios_name,
1898 current_passwords);
1899 if (!NT_STATUS_IS_OK(nt_status)) {
1900 goto done;
1904 /* ok, all fine, commit transaction and return */
1905 ret = ldb_transaction_commit(p_state->sam_ldb);
1906 if (ret != LDB_SUCCESS) {
1907 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1909 in_transaction = false;
1911 nt_status = NT_STATUS_OK;
1913 done:
1914 if (in_transaction) {
1915 ldb_transaction_cancel(p_state->sam_ldb);
1917 return nt_status;
1921 lsa_SetInfomrationTrustedDomain
1923 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1924 struct dcesrv_call_state *dce_call,
1925 TALLOC_CTX *mem_ctx,
1926 struct lsa_SetInformationTrustedDomain *r)
1928 struct dcesrv_handle *h;
1929 struct lsa_trusted_domain_state *td_state;
1930 struct ldb_message **msgs;
1931 NTSTATUS nt_status;
1933 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1934 LSA_HANDLE_TRUSTED_DOMAIN);
1936 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1938 /* get the trusted domain object */
1939 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1940 td_state->trusted_domain_dn,
1941 NULL, NULL, NULL, &msgs);
1942 if (!NT_STATUS_IS_OK(nt_status)) {
1943 if (NT_STATUS_EQUAL(nt_status,
1944 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1945 return nt_status;
1947 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1950 return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1951 msgs[0], r->in.level, r->in.info);
1956 lsa_DeleteTrustedDomain
1958 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1959 struct lsa_DeleteTrustedDomain *r)
1961 NTSTATUS status;
1962 struct lsa_OpenTrustedDomain opn;
1963 struct lsa_DeleteObject del;
1964 struct dcesrv_handle *h;
1966 opn.in.handle = r->in.handle;
1967 opn.in.sid = r->in.dom_sid;
1968 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1969 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1970 if (!opn.out.trustdom_handle) {
1971 return NT_STATUS_NO_MEMORY;
1973 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1974 if (!NT_STATUS_IS_OK(status)) {
1975 return status;
1978 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1979 talloc_steal(mem_ctx, h);
1981 del.in.handle = opn.out.trustdom_handle;
1982 del.out.handle = opn.out.trustdom_handle;
1983 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1984 if (!NT_STATUS_IS_OK(status)) {
1985 return status;
1987 return NT_STATUS_OK;
1990 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
1991 struct ldb_message *msg,
1992 struct lsa_TrustDomainInfoInfoEx *info_ex)
1994 info_ex->domain_name.string
1995 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1996 info_ex->netbios_name.string
1997 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1998 info_ex->sid
1999 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2000 info_ex->trust_direction
2001 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2002 info_ex->trust_type
2003 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2004 info_ex->trust_attributes
2005 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2006 return NT_STATUS_OK;
2010 lsa_QueryTrustedDomainInfo
2012 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2013 struct lsa_QueryTrustedDomainInfo *r)
2015 union lsa_TrustedDomainInfo *info = NULL;
2016 struct dcesrv_handle *h;
2017 struct lsa_trusted_domain_state *trusted_domain_state;
2018 struct ldb_message *msg;
2019 int ret;
2020 struct ldb_message **res;
2021 const char *attrs[] = {
2022 "flatname",
2023 "trustPartner",
2024 "securityIdentifier",
2025 "trustDirection",
2026 "trustType",
2027 "trustAttributes",
2028 "msDs-supportedEncryptionTypes",
2029 NULL
2032 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2034 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2036 /* pull all the user attributes */
2037 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2038 trusted_domain_state->trusted_domain_dn, &res, attrs);
2039 if (ret != 1) {
2040 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2042 msg = res[0];
2044 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2045 if (!info) {
2046 return NT_STATUS_NO_MEMORY;
2048 *r->out.info = info;
2050 switch (r->in.level) {
2051 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2052 info->name.netbios_name.string
2053 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2054 break;
2055 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2056 info->posix_offset.posix_offset
2057 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2058 break;
2059 #if 0 /* Win2k3 doesn't implement this */
2060 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2061 r->out.info->info_basic.netbios_name.string
2062 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2063 r->out.info->info_basic.sid
2064 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2065 break;
2066 #endif
2067 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2068 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2070 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2071 ZERO_STRUCT(info->full_info);
2072 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2073 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2074 ZERO_STRUCT(info->full_info2_internal);
2075 info->full_info2_internal.posix_offset.posix_offset
2076 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2077 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2079 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2080 info->enc_types.enc_types
2081 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2082 break;
2084 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2085 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2086 /* oops, we don't want to return the info after all */
2087 talloc_free(info);
2088 *r->out.info = NULL;
2089 return NT_STATUS_INVALID_PARAMETER;
2090 default:
2091 /* oops, we don't want to return the info after all */
2092 talloc_free(info);
2093 *r->out.info = NULL;
2094 return NT_STATUS_INVALID_INFO_CLASS;
2097 return NT_STATUS_OK;
2102 lsa_QueryTrustedDomainInfoBySid
2104 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2105 struct lsa_QueryTrustedDomainInfoBySid *r)
2107 NTSTATUS status;
2108 struct lsa_OpenTrustedDomain opn;
2109 struct lsa_QueryTrustedDomainInfo query;
2110 struct dcesrv_handle *h;
2112 opn.in.handle = r->in.handle;
2113 opn.in.sid = r->in.dom_sid;
2114 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2115 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2116 if (!opn.out.trustdom_handle) {
2117 return NT_STATUS_NO_MEMORY;
2119 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2120 if (!NT_STATUS_IS_OK(status)) {
2121 return status;
2124 /* Ensure this handle goes away at the end of this call */
2125 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2126 talloc_steal(mem_ctx, h);
2128 query.in.trustdom_handle = opn.out.trustdom_handle;
2129 query.in.level = r->in.level;
2130 query.out.info = r->out.info;
2131 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2132 if (!NT_STATUS_IS_OK(status)) {
2133 return status;
2136 return NT_STATUS_OK;
2140 lsa_SetTrustedDomainInfoByName
2142 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2143 TALLOC_CTX *mem_ctx,
2144 struct lsa_SetTrustedDomainInfoByName *r)
2146 struct dcesrv_handle *policy_handle;
2147 struct lsa_policy_state *policy_state;
2148 struct ldb_message **msgs;
2149 NTSTATUS nt_status;
2151 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2152 policy_state = policy_handle->data;
2154 /* get the trusted domain object */
2155 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2156 policy_state->domain_dn,
2157 r->in.trusted_domain->string,
2158 r->in.trusted_domain->string,
2159 NULL, &msgs);
2160 if (!NT_STATUS_IS_OK(nt_status)) {
2161 if (NT_STATUS_EQUAL(nt_status,
2162 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2163 return nt_status;
2165 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2168 return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2169 msgs[0], r->in.level, r->in.info);
2173 lsa_QueryTrustedDomainInfoByName
2175 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2176 TALLOC_CTX *mem_ctx,
2177 struct lsa_QueryTrustedDomainInfoByName *r)
2179 NTSTATUS status;
2180 struct lsa_OpenTrustedDomainByName opn;
2181 struct lsa_QueryTrustedDomainInfo query;
2182 struct dcesrv_handle *h;
2184 opn.in.handle = r->in.handle;
2185 opn.in.name = *r->in.trusted_domain;
2186 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2187 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2188 if (!opn.out.trustdom_handle) {
2189 return NT_STATUS_NO_MEMORY;
2191 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2192 if (!NT_STATUS_IS_OK(status)) {
2193 return status;
2196 /* Ensure this handle goes away at the end of this call */
2197 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2198 talloc_steal(mem_ctx, h);
2200 query.in.trustdom_handle = opn.out.trustdom_handle;
2201 query.in.level = r->in.level;
2202 query.out.info = r->out.info;
2203 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2204 if (!NT_STATUS_IS_OK(status)) {
2205 return status;
2208 return NT_STATUS_OK;
2212 lsa_CloseTrustedDomainEx
2214 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2215 TALLOC_CTX *mem_ctx,
2216 struct lsa_CloseTrustedDomainEx *r)
2218 /* The result of a bad hair day from an IDL programmer? Not
2219 * implmented in Win2k3. You should always just lsa_Close
2220 * anyway. */
2221 return NT_STATUS_NOT_IMPLEMENTED;
2226 comparison function for sorting lsa_DomainInformation array
2228 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2230 return strcasecmp_m(e1->name.string, e2->name.string);
2234 lsa_EnumTrustDom
2236 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2237 struct lsa_EnumTrustDom *r)
2239 struct dcesrv_handle *policy_handle;
2240 struct lsa_DomainInfo *entries;
2241 struct lsa_policy_state *policy_state;
2242 struct ldb_message **domains;
2243 const char *attrs[] = {
2244 "flatname",
2245 "securityIdentifier",
2246 NULL
2250 int count, i;
2252 *r->out.resume_handle = 0;
2254 r->out.domains->domains = NULL;
2255 r->out.domains->count = 0;
2257 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2259 policy_state = policy_handle->data;
2261 /* search for all users in this domain. This could possibly be cached and
2262 resumed based on resume_key */
2263 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2264 "objectclass=trustedDomain");
2265 if (count < 0) {
2266 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2269 /* convert to lsa_TrustInformation format */
2270 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2271 if (!entries) {
2272 return NT_STATUS_NO_MEMORY;
2274 for (i=0;i<count;i++) {
2275 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2276 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2279 /* sort the results by name */
2280 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2282 if (*r->in.resume_handle >= count) {
2283 *r->out.resume_handle = -1;
2285 return NT_STATUS_NO_MORE_ENTRIES;
2288 /* return the rest, limit by max_size. Note that we
2289 use the w2k3 element size value of 60 */
2290 r->out.domains->count = count - *r->in.resume_handle;
2291 r->out.domains->count = MIN(r->out.domains->count,
2292 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2294 r->out.domains->domains = entries + *r->in.resume_handle;
2295 r->out.domains->count = r->out.domains->count;
2297 if (r->out.domains->count < count - *r->in.resume_handle) {
2298 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2299 return STATUS_MORE_ENTRIES;
2302 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2303 * always be larger than the previous input resume handle, in
2304 * particular when hitting the last query it is vital to set the
2305 * resume handle correctly to avoid infinite client loops, as
2306 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2307 * status is NT_STATUS_OK - gd */
2309 *r->out.resume_handle = (uint32_t)-1;
2311 return NT_STATUS_OK;
2315 comparison function for sorting lsa_DomainInformation array
2317 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2319 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2323 lsa_EnumTrustedDomainsEx
2325 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2326 struct lsa_EnumTrustedDomainsEx *r)
2328 struct dcesrv_handle *policy_handle;
2329 struct lsa_TrustDomainInfoInfoEx *entries;
2330 struct lsa_policy_state *policy_state;
2331 struct ldb_message **domains;
2332 const char *attrs[] = {
2333 "flatname",
2334 "trustPartner",
2335 "securityIdentifier",
2336 "trustDirection",
2337 "trustType",
2338 "trustAttributes",
2339 NULL
2341 NTSTATUS nt_status;
2343 int count, i;
2345 *r->out.resume_handle = 0;
2347 r->out.domains->domains = NULL;
2348 r->out.domains->count = 0;
2350 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2352 policy_state = policy_handle->data;
2354 /* search for all users in this domain. This could possibly be cached and
2355 resumed based on resume_key */
2356 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2357 "objectclass=trustedDomain");
2358 if (count < 0) {
2359 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2362 /* convert to lsa_DomainInformation format */
2363 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2364 if (!entries) {
2365 return NT_STATUS_NO_MEMORY;
2367 for (i=0;i<count;i++) {
2368 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2369 if (!NT_STATUS_IS_OK(nt_status)) {
2370 return nt_status;
2374 /* sort the results by name */
2375 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2377 if (*r->in.resume_handle >= count) {
2378 *r->out.resume_handle = -1;
2380 return NT_STATUS_NO_MORE_ENTRIES;
2383 /* return the rest, limit by max_size. Note that we
2384 use the w2k3 element size value of 60 */
2385 r->out.domains->count = count - *r->in.resume_handle;
2386 r->out.domains->count = MIN(r->out.domains->count,
2387 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2389 r->out.domains->domains = entries + *r->in.resume_handle;
2390 r->out.domains->count = r->out.domains->count;
2392 if (r->out.domains->count < count - *r->in.resume_handle) {
2393 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2394 return STATUS_MORE_ENTRIES;
2397 return NT_STATUS_OK;
2402 lsa_OpenAccount
2404 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2405 struct lsa_OpenAccount *r)
2407 struct dcesrv_handle *h, *ah;
2408 struct lsa_policy_state *state;
2409 struct lsa_account_state *astate;
2411 ZERO_STRUCTP(r->out.acct_handle);
2413 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2415 state = h->data;
2417 astate = talloc(dce_call->conn, struct lsa_account_state);
2418 if (astate == NULL) {
2419 return NT_STATUS_NO_MEMORY;
2422 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2423 if (astate->account_sid == NULL) {
2424 talloc_free(astate);
2425 return NT_STATUS_NO_MEMORY;
2428 astate->policy = talloc_reference(astate, state);
2429 astate->access_mask = r->in.access_mask;
2431 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2432 if (!ah) {
2433 talloc_free(astate);
2434 return NT_STATUS_NO_MEMORY;
2437 ah->data = talloc_steal(ah, astate);
2439 *r->out.acct_handle = ah->wire_handle;
2441 return NT_STATUS_OK;
2446 lsa_EnumPrivsAccount
2448 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2449 TALLOC_CTX *mem_ctx,
2450 struct lsa_EnumPrivsAccount *r)
2452 struct dcesrv_handle *h;
2453 struct lsa_account_state *astate;
2454 int ret;
2455 unsigned int i, j;
2456 struct ldb_message **res;
2457 const char * const attrs[] = { "privilege", NULL};
2458 struct ldb_message_element *el;
2459 const char *sidstr;
2460 struct lsa_PrivilegeSet *privs;
2462 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2464 astate = h->data;
2466 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2467 if (privs == NULL) {
2468 return NT_STATUS_NO_MEMORY;
2470 privs->count = 0;
2471 privs->unknown = 0;
2472 privs->set = NULL;
2474 *r->out.privs = privs;
2476 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2477 if (sidstr == NULL) {
2478 return NT_STATUS_NO_MEMORY;
2481 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2482 "objectSid=%s", sidstr);
2483 if (ret < 0) {
2484 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2486 if (ret != 1) {
2487 return NT_STATUS_OK;
2490 el = ldb_msg_find_element(res[0], "privilege");
2491 if (el == NULL || el->num_values == 0) {
2492 return NT_STATUS_OK;
2495 privs->set = talloc_array(privs,
2496 struct lsa_LUIDAttribute, el->num_values);
2497 if (privs->set == NULL) {
2498 return NT_STATUS_NO_MEMORY;
2501 j = 0;
2502 for (i=0;i<el->num_values;i++) {
2503 int id = sec_privilege_id((const char *)el->values[i].data);
2504 if (id == SEC_PRIV_INVALID) {
2505 /* Perhaps an account right, not a privilege */
2506 continue;
2508 privs->set[j].attribute = 0;
2509 privs->set[j].luid.low = id;
2510 privs->set[j].luid.high = 0;
2511 j++;
2514 privs->count = j;
2516 return NT_STATUS_OK;
2520 lsa_EnumAccountRights
2522 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2523 TALLOC_CTX *mem_ctx,
2524 struct lsa_EnumAccountRights *r)
2526 struct dcesrv_handle *h;
2527 struct lsa_policy_state *state;
2528 int ret;
2529 unsigned int i;
2530 struct ldb_message **res;
2531 const char * const attrs[] = { "privilege", NULL};
2532 const char *sidstr;
2533 struct ldb_message_element *el;
2535 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2537 state = h->data;
2539 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2540 if (sidstr == NULL) {
2541 return NT_STATUS_NO_MEMORY;
2544 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2545 "(&(objectSid=%s)(privilege=*))", sidstr);
2546 if (ret == 0) {
2547 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2549 if (ret != 1) {
2550 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2551 dom_sid_string(mem_ctx, r->in.sid),
2552 ldb_errstring(state->pdb)));
2553 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2556 el = ldb_msg_find_element(res[0], "privilege");
2557 if (el == NULL || el->num_values == 0) {
2558 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2561 r->out.rights->count = el->num_values;
2562 r->out.rights->names = talloc_array(r->out.rights,
2563 struct lsa_StringLarge, r->out.rights->count);
2564 if (r->out.rights->names == NULL) {
2565 return NT_STATUS_NO_MEMORY;
2568 for (i=0;i<el->num_values;i++) {
2569 r->out.rights->names[i].string = (const char *)el->values[i].data;
2572 return NT_STATUS_OK;
2578 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2580 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2581 TALLOC_CTX *mem_ctx,
2582 struct lsa_policy_state *state,
2583 int ldb_flag,
2584 struct dom_sid *sid,
2585 const struct lsa_RightSet *rights)
2587 const char *sidstr, *sidndrstr;
2588 struct ldb_message *msg;
2589 struct ldb_message_element *el;
2590 int ret;
2591 uint32_t i;
2592 struct lsa_EnumAccountRights r2;
2593 char *dnstr;
2595 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2596 SECURITY_ADMINISTRATOR) {
2597 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2598 return NT_STATUS_ACCESS_DENIED;
2601 msg = ldb_msg_new(mem_ctx);
2602 if (msg == NULL) {
2603 return NT_STATUS_NO_MEMORY;
2606 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2607 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
2609 sidstr = dom_sid_string(msg, sid);
2610 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
2612 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2613 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
2615 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2616 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
2618 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2619 NTSTATUS status;
2621 r2.in.handle = &state->handle->wire_handle;
2622 r2.in.sid = sid;
2623 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2625 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2626 if (!NT_STATUS_IS_OK(status)) {
2627 ZERO_STRUCTP(r2.out.rights);
2631 for (i=0;i<rights->count;i++) {
2632 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2633 if (sec_right_bit(rights->names[i].string) == 0) {
2634 talloc_free(msg);
2635 return NT_STATUS_NO_SUCH_PRIVILEGE;
2638 talloc_free(msg);
2639 return NT_STATUS_NO_SUCH_PRIVILEGE;
2642 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2643 uint32_t j;
2644 for (j=0;j<r2.out.rights->count;j++) {
2645 if (strcasecmp_m(r2.out.rights->names[j].string,
2646 rights->names[i].string) == 0) {
2647 break;
2650 if (j != r2.out.rights->count) continue;
2653 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2654 if (ret != LDB_SUCCESS) {
2655 talloc_free(msg);
2656 return NT_STATUS_NO_MEMORY;
2660 el = ldb_msg_find_element(msg, "privilege");
2661 if (!el) {
2662 talloc_free(msg);
2663 return NT_STATUS_OK;
2666 el->flags = ldb_flag;
2668 ret = ldb_modify(state->pdb, msg);
2669 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2670 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2671 talloc_free(msg);
2672 return NT_STATUS_NO_MEMORY;
2674 ldb_msg_add_string(msg, "comment", "added via LSA");
2675 ret = ldb_add(state->pdb, msg);
2677 if (ret != LDB_SUCCESS) {
2678 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2679 talloc_free(msg);
2680 return NT_STATUS_OK;
2682 DEBUG(3, ("Could not %s attributes from %s: %s",
2683 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2684 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2685 talloc_free(msg);
2686 return NT_STATUS_UNEXPECTED_IO_ERROR;
2689 talloc_free(msg);
2690 return NT_STATUS_OK;
2694 lsa_AddPrivilegesToAccount
2696 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2697 struct lsa_AddPrivilegesToAccount *r)
2699 struct lsa_RightSet rights;
2700 struct dcesrv_handle *h;
2701 struct lsa_account_state *astate;
2702 uint32_t i;
2704 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2706 astate = h->data;
2708 rights.count = r->in.privs->count;
2709 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2710 if (rights.names == NULL) {
2711 return NT_STATUS_NO_MEMORY;
2713 for (i=0;i<rights.count;i++) {
2714 int id = r->in.privs->set[i].luid.low;
2715 if (r->in.privs->set[i].luid.high) {
2716 return NT_STATUS_NO_SUCH_PRIVILEGE;
2718 rights.names[i].string = sec_privilege_name(id);
2719 if (rights.names[i].string == NULL) {
2720 return NT_STATUS_NO_SUCH_PRIVILEGE;
2724 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2725 LDB_FLAG_MOD_ADD, astate->account_sid,
2726 &rights);
2731 lsa_RemovePrivilegesFromAccount
2733 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2734 struct lsa_RemovePrivilegesFromAccount *r)
2736 struct lsa_RightSet *rights;
2737 struct dcesrv_handle *h;
2738 struct lsa_account_state *astate;
2739 uint32_t i;
2741 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2743 astate = h->data;
2745 rights = talloc(mem_ctx, struct lsa_RightSet);
2747 if (r->in.remove_all == 1 &&
2748 r->in.privs == NULL) {
2749 struct lsa_EnumAccountRights r2;
2750 NTSTATUS status;
2752 r2.in.handle = &astate->policy->handle->wire_handle;
2753 r2.in.sid = astate->account_sid;
2754 r2.out.rights = rights;
2756 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2757 if (!NT_STATUS_IS_OK(status)) {
2758 return status;
2761 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2762 LDB_FLAG_MOD_DELETE, astate->account_sid,
2763 r2.out.rights);
2766 if (r->in.remove_all != 0) {
2767 return NT_STATUS_INVALID_PARAMETER;
2770 rights->count = r->in.privs->count;
2771 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2772 if (rights->names == NULL) {
2773 return NT_STATUS_NO_MEMORY;
2775 for (i=0;i<rights->count;i++) {
2776 int id = r->in.privs->set[i].luid.low;
2777 if (r->in.privs->set[i].luid.high) {
2778 return NT_STATUS_NO_SUCH_PRIVILEGE;
2780 rights->names[i].string = sec_privilege_name(id);
2781 if (rights->names[i].string == NULL) {
2782 return NT_STATUS_NO_SUCH_PRIVILEGE;
2786 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2787 LDB_FLAG_MOD_DELETE, astate->account_sid,
2788 rights);
2793 lsa_GetQuotasForAccount
2795 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2796 struct lsa_GetQuotasForAccount *r)
2798 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2803 lsa_SetQuotasForAccount
2805 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2806 struct lsa_SetQuotasForAccount *r)
2808 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2813 lsa_GetSystemAccessAccount
2815 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2816 struct lsa_GetSystemAccessAccount *r)
2818 struct dcesrv_handle *h;
2819 struct lsa_account_state *astate;
2820 int ret;
2821 unsigned int i;
2822 struct ldb_message **res;
2823 const char * const attrs[] = { "privilege", NULL};
2824 struct ldb_message_element *el;
2825 const char *sidstr;
2827 *(r->out.access_mask) = 0x00000000;
2829 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2831 astate = h->data;
2833 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2834 if (sidstr == NULL) {
2835 return NT_STATUS_NO_MEMORY;
2838 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2839 "objectSid=%s", sidstr);
2840 if (ret < 0) {
2841 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2843 if (ret != 1) {
2844 return NT_STATUS_OK;
2847 el = ldb_msg_find_element(res[0], "privilege");
2848 if (el == NULL || el->num_values == 0) {
2849 return NT_STATUS_OK;
2852 for (i=0;i<el->num_values;i++) {
2853 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2854 if (right_bit == 0) {
2855 /* Perhaps an privilege, not a right */
2856 continue;
2858 *(r->out.access_mask) |= right_bit;
2861 return NT_STATUS_OK;
2866 lsa_SetSystemAccessAccount
2868 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2869 struct lsa_SetSystemAccessAccount *r)
2871 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2876 lsa_CreateSecret
2878 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2879 struct lsa_CreateSecret *r)
2881 struct dcesrv_handle *policy_handle;
2882 struct lsa_policy_state *policy_state;
2883 struct lsa_secret_state *secret_state;
2884 struct dcesrv_handle *handle;
2885 struct ldb_message **msgs, *msg;
2886 const char *attrs[] = {
2887 NULL
2890 const char *name;
2892 int ret;
2894 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2895 ZERO_STRUCTP(r->out.sec_handle);
2897 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2899 case SECURITY_SYSTEM:
2900 case SECURITY_ADMINISTRATOR:
2901 break;
2902 default:
2903 /* Users and annonymous are not allowed create secrets */
2904 return NT_STATUS_ACCESS_DENIED;
2907 policy_state = policy_handle->data;
2909 if (!r->in.name.string) {
2910 return NT_STATUS_INVALID_PARAMETER;
2913 secret_state = talloc(mem_ctx, struct lsa_secret_state);
2914 NT_STATUS_HAVE_NO_MEMORY(secret_state);
2915 secret_state->policy = policy_state;
2917 msg = ldb_msg_new(mem_ctx);
2918 if (msg == NULL) {
2919 return NT_STATUS_NO_MEMORY;
2922 if (strncmp("G$", r->in.name.string, 2) == 0) {
2923 const char *name2;
2925 secret_state->global = true;
2927 name = &r->in.name.string[2];
2928 if (strlen(name) == 0) {
2929 return NT_STATUS_INVALID_PARAMETER;
2932 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2933 ldb_binary_encode_string(mem_ctx, name));
2934 NT_STATUS_HAVE_NO_MEMORY(name2);
2936 /* We need to connect to the database as system, as this is one
2937 * of the rare RPC calls that must read the secrets (and this
2938 * is denied otherwise) */
2939 secret_state->sam_ldb = talloc_reference(secret_state,
2940 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));
2941 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2943 /* search for the secret record */
2944 ret = gendb_search(secret_state->sam_ldb,
2945 mem_ctx, policy_state->system_dn, &msgs, attrs,
2946 "(&(cn=%s)(objectclass=secret))",
2947 name2);
2948 if (ret > 0) {
2949 return NT_STATUS_OBJECT_NAME_COLLISION;
2952 if (ret < 0) {
2953 DEBUG(0,("Failure searching for CN=%s: %s\n",
2954 name2, ldb_errstring(secret_state->sam_ldb)));
2955 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2958 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2959 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2960 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2961 return NT_STATUS_NO_MEMORY;
2964 ret = ldb_msg_add_string(msg, "cn", name2);
2965 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2966 } else {
2967 secret_state->global = false;
2969 name = r->in.name.string;
2970 if (strlen(name) == 0) {
2971 return NT_STATUS_INVALID_PARAMETER;
2974 secret_state->sam_ldb = talloc_reference(secret_state,
2975 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
2976 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2978 /* search for the secret record */
2979 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2980 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2981 &msgs, attrs,
2982 "(&(cn=%s)(objectclass=secret))",
2983 ldb_binary_encode_string(mem_ctx, name));
2984 if (ret > 0) {
2985 return NT_STATUS_OBJECT_NAME_COLLISION;
2988 if (ret < 0) {
2989 DEBUG(0,("Failure searching for CN=%s: %s\n",
2990 name, ldb_errstring(secret_state->sam_ldb)));
2991 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2994 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
2995 "cn=%s,cn=LSA Secrets", name);
2996 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2997 ret = ldb_msg_add_string(msg, "cn", name);
2998 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3001 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3002 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3004 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3005 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3007 /* create the secret */
3008 ret = ldb_add(secret_state->sam_ldb, msg);
3009 if (ret != LDB_SUCCESS) {
3010 DEBUG(0,("Failed to create secret record %s: %s\n",
3011 ldb_dn_get_linearized(msg->dn),
3012 ldb_errstring(secret_state->sam_ldb)));
3013 return NT_STATUS_ACCESS_DENIED;
3016 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3017 NT_STATUS_HAVE_NO_MEMORY(handle);
3019 handle->data = talloc_steal(handle, secret_state);
3021 secret_state->access_mask = r->in.access_mask;
3022 secret_state->policy = talloc_reference(secret_state, policy_state);
3023 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3025 *r->out.sec_handle = handle->wire_handle;
3027 return NT_STATUS_OK;
3032 lsa_OpenSecret
3034 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3035 struct lsa_OpenSecret *r)
3037 struct dcesrv_handle *policy_handle;
3039 struct lsa_policy_state *policy_state;
3040 struct lsa_secret_state *secret_state;
3041 struct dcesrv_handle *handle;
3042 struct ldb_message **msgs;
3043 const char *attrs[] = {
3044 NULL
3047 const char *name;
3049 int ret;
3051 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3052 ZERO_STRUCTP(r->out.sec_handle);
3053 policy_state = policy_handle->data;
3055 if (!r->in.name.string) {
3056 return NT_STATUS_INVALID_PARAMETER;
3059 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3061 case SECURITY_SYSTEM:
3062 case SECURITY_ADMINISTRATOR:
3063 break;
3064 default:
3065 /* Users and annonymous are not allowed to access secrets */
3066 return NT_STATUS_ACCESS_DENIED;
3069 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3070 if (!secret_state) {
3071 return NT_STATUS_NO_MEMORY;
3073 secret_state->policy = policy_state;
3075 if (strncmp("G$", r->in.name.string, 2) == 0) {
3076 name = &r->in.name.string[2];
3077 /* 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) */
3078 secret_state->sam_ldb = talloc_reference(secret_state,
3079 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));
3080 secret_state->global = true;
3082 if (strlen(name) < 1) {
3083 return NT_STATUS_INVALID_PARAMETER;
3086 /* search for the secret record */
3087 ret = gendb_search(secret_state->sam_ldb,
3088 mem_ctx, policy_state->system_dn, &msgs, attrs,
3089 "(&(cn=%s Secret)(objectclass=secret))",
3090 ldb_binary_encode_string(mem_ctx, name));
3091 if (ret == 0) {
3092 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3095 if (ret != 1) {
3096 DEBUG(0,("Found %d records matching DN %s\n", ret,
3097 ldb_dn_get_linearized(policy_state->system_dn)));
3098 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3101 } else {
3102 secret_state->global = false;
3103 secret_state->sam_ldb = talloc_reference(secret_state,
3104 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3106 name = r->in.name.string;
3107 if (strlen(name) < 1) {
3108 return NT_STATUS_INVALID_PARAMETER;
3111 /* search for the secret record */
3112 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3113 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3114 &msgs, attrs,
3115 "(&(cn=%s)(objectclass=secret))",
3116 ldb_binary_encode_string(mem_ctx, name));
3117 if (ret == 0) {
3118 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3121 if (ret != 1) {
3122 DEBUG(0,("Found %d records matching CN=%s\n",
3123 ret, ldb_binary_encode_string(mem_ctx, name)));
3124 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3128 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3130 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3131 if (!handle) {
3132 return NT_STATUS_NO_MEMORY;
3135 handle->data = talloc_steal(handle, secret_state);
3137 secret_state->access_mask = r->in.access_mask;
3138 secret_state->policy = talloc_reference(secret_state, policy_state);
3140 *r->out.sec_handle = handle->wire_handle;
3142 return NT_STATUS_OK;
3147 lsa_SetSecret
3149 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3150 struct lsa_SetSecret *r)
3153 struct dcesrv_handle *h;
3154 struct lsa_secret_state *secret_state;
3155 struct ldb_message *msg;
3156 DATA_BLOB session_key;
3157 DATA_BLOB crypt_secret, secret;
3158 struct ldb_val val;
3159 int ret;
3160 NTSTATUS status = NT_STATUS_OK;
3162 struct timeval now = timeval_current();
3163 NTTIME nt_now = timeval_to_nttime(&now);
3165 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3167 secret_state = h->data;
3169 msg = ldb_msg_new(mem_ctx);
3170 if (msg == NULL) {
3171 return NT_STATUS_NO_MEMORY;
3174 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3175 if (!msg->dn) {
3176 return NT_STATUS_NO_MEMORY;
3178 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3179 if (!NT_STATUS_IS_OK(status)) {
3180 return status;
3183 if (r->in.old_val) {
3184 /* Decrypt */
3185 crypt_secret.data = r->in.old_val->data;
3186 crypt_secret.length = r->in.old_val->size;
3188 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3189 if (!NT_STATUS_IS_OK(status)) {
3190 return status;
3193 val.data = secret.data;
3194 val.length = secret.length;
3196 /* set value */
3197 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3198 return NT_STATUS_NO_MEMORY;
3201 /* set old value mtime */
3202 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3203 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3204 return NT_STATUS_NO_MEMORY;
3207 } else {
3208 /* If the old value is not set, then migrate the
3209 * current value to the old value */
3210 const struct ldb_val *old_val;
3211 NTTIME last_set_time;
3212 struct ldb_message **res;
3213 const char *attrs[] = {
3214 "currentValue",
3215 "lastSetTime",
3216 NULL
3219 /* search for the secret record */
3220 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3221 secret_state->secret_dn, &res, attrs);
3222 if (ret == 0) {
3223 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3226 if (ret != 1) {
3227 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3228 ldb_dn_get_linearized(secret_state->secret_dn)));
3229 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3232 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3233 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3235 if (old_val) {
3236 /* set old value */
3237 if (ldb_msg_add_value(msg, "priorValue",
3238 old_val, NULL) != LDB_SUCCESS) {
3239 return NT_STATUS_NO_MEMORY;
3241 } else {
3242 if (samdb_msg_add_delete(secret_state->sam_ldb,
3243 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3244 return NT_STATUS_NO_MEMORY;
3249 /* set old value mtime */
3250 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3251 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3252 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3253 return NT_STATUS_NO_MEMORY;
3255 } else {
3256 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3257 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3258 return NT_STATUS_NO_MEMORY;
3263 if (r->in.new_val) {
3264 /* Decrypt */
3265 crypt_secret.data = r->in.new_val->data;
3266 crypt_secret.length = r->in.new_val->size;
3268 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3269 if (!NT_STATUS_IS_OK(status)) {
3270 return status;
3273 val.data = secret.data;
3274 val.length = secret.length;
3276 /* set value */
3277 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3278 return NT_STATUS_NO_MEMORY;
3281 /* set new value mtime */
3282 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3283 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3284 return NT_STATUS_NO_MEMORY;
3287 } else {
3288 /* NULL out the NEW value */
3289 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3290 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3291 return NT_STATUS_NO_MEMORY;
3293 if (samdb_msg_add_delete(secret_state->sam_ldb,
3294 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3295 return NT_STATUS_NO_MEMORY;
3299 /* modify the samdb record */
3300 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3301 if (ret != LDB_SUCCESS) {
3302 return dsdb_ldb_err_to_ntstatus(ret);
3305 return NT_STATUS_OK;
3310 lsa_QuerySecret
3312 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3313 struct lsa_QuerySecret *r)
3315 struct dcesrv_handle *h;
3316 struct lsa_secret_state *secret_state;
3317 struct ldb_message *msg;
3318 DATA_BLOB session_key;
3319 DATA_BLOB crypt_secret, secret;
3320 int ret;
3321 struct ldb_message **res;
3322 const char *attrs[] = {
3323 "currentValue",
3324 "priorValue",
3325 "lastSetTime",
3326 "priorSetTime",
3327 NULL
3330 NTSTATUS nt_status;
3332 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3334 /* Ensure user is permitted to read this... */
3335 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3337 case SECURITY_SYSTEM:
3338 case SECURITY_ADMINISTRATOR:
3339 break;
3340 default:
3341 /* Users and annonymous are not allowed to read secrets */
3342 return NT_STATUS_ACCESS_DENIED;
3345 secret_state = h->data;
3347 /* pull all the user attributes */
3348 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3349 secret_state->secret_dn, &res, attrs);
3350 if (ret != 1) {
3351 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3353 msg = res[0];
3355 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3356 if (!NT_STATUS_IS_OK(nt_status)) {
3357 return nt_status;
3360 if (r->in.old_val) {
3361 const struct ldb_val *prior_val;
3362 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3363 if (!r->out.old_val) {
3364 return NT_STATUS_NO_MEMORY;
3366 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
3368 if (prior_val && prior_val->length) {
3369 secret.data = prior_val->data;
3370 secret.length = prior_val->length;
3372 /* Encrypt */
3373 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3374 if (!crypt_secret.length) {
3375 return NT_STATUS_NO_MEMORY;
3377 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3378 if (!r->out.old_val->buf) {
3379 return NT_STATUS_NO_MEMORY;
3381 r->out.old_val->buf->size = crypt_secret.length;
3382 r->out.old_val->buf->length = crypt_secret.length;
3383 r->out.old_val->buf->data = crypt_secret.data;
3387 if (r->in.old_mtime) {
3388 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3389 if (!r->out.old_mtime) {
3390 return NT_STATUS_NO_MEMORY;
3392 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
3395 if (r->in.new_val) {
3396 const struct ldb_val *new_val;
3397 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3398 if (!r->out.new_val) {
3399 return NT_STATUS_NO_MEMORY;
3402 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3404 if (new_val && new_val->length) {
3405 secret.data = new_val->data;
3406 secret.length = new_val->length;
3408 /* Encrypt */
3409 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3410 if (!crypt_secret.length) {
3411 return NT_STATUS_NO_MEMORY;
3413 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3414 if (!r->out.new_val->buf) {
3415 return NT_STATUS_NO_MEMORY;
3417 r->out.new_val->buf->length = crypt_secret.length;
3418 r->out.new_val->buf->size = crypt_secret.length;
3419 r->out.new_val->buf->data = crypt_secret.data;
3423 if (r->in.new_mtime) {
3424 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3425 if (!r->out.new_mtime) {
3426 return NT_STATUS_NO_MEMORY;
3428 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3431 return NT_STATUS_OK;
3436 lsa_LookupPrivValue
3438 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3439 TALLOC_CTX *mem_ctx,
3440 struct lsa_LookupPrivValue *r)
3442 struct dcesrv_handle *h;
3443 struct lsa_policy_state *state;
3444 int id;
3446 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3448 state = h->data;
3450 id = sec_privilege_id(r->in.name->string);
3451 if (id == SEC_PRIV_INVALID) {
3452 return NT_STATUS_NO_SUCH_PRIVILEGE;
3455 r->out.luid->low = id;
3456 r->out.luid->high = 0;
3458 return NT_STATUS_OK;
3463 lsa_LookupPrivName
3465 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3466 TALLOC_CTX *mem_ctx,
3467 struct lsa_LookupPrivName *r)
3469 struct dcesrv_handle *h;
3470 struct lsa_policy_state *state;
3471 struct lsa_StringLarge *name;
3472 const char *privname;
3474 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3476 state = h->data;
3478 if (r->in.luid->high != 0) {
3479 return NT_STATUS_NO_SUCH_PRIVILEGE;
3482 privname = sec_privilege_name(r->in.luid->low);
3483 if (privname == NULL) {
3484 return NT_STATUS_NO_SUCH_PRIVILEGE;
3487 name = talloc(mem_ctx, struct lsa_StringLarge);
3488 if (name == NULL) {
3489 return NT_STATUS_NO_MEMORY;
3492 name->string = privname;
3494 *r->out.name = name;
3496 return NT_STATUS_OK;
3501 lsa_LookupPrivDisplayName
3503 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3504 TALLOC_CTX *mem_ctx,
3505 struct lsa_LookupPrivDisplayName *r)
3507 struct dcesrv_handle *h;
3508 struct lsa_policy_state *state;
3509 struct lsa_StringLarge *disp_name = NULL;
3510 enum sec_privilege id;
3512 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3514 state = h->data;
3516 id = sec_privilege_id(r->in.name->string);
3517 if (id == SEC_PRIV_INVALID) {
3518 return NT_STATUS_NO_SUCH_PRIVILEGE;
3521 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3522 if (disp_name == NULL) {
3523 return NT_STATUS_NO_MEMORY;
3526 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3527 if (disp_name->string == NULL) {
3528 return NT_STATUS_INTERNAL_ERROR;
3531 *r->out.disp_name = disp_name;
3532 *r->out.returned_language_id = 0;
3534 return NT_STATUS_OK;
3539 lsa_EnumAccountsWithUserRight
3541 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3542 TALLOC_CTX *mem_ctx,
3543 struct lsa_EnumAccountsWithUserRight *r)
3545 struct dcesrv_handle *h;
3546 struct lsa_policy_state *state;
3547 int ret, i;
3548 struct ldb_message **res;
3549 const char * const attrs[] = { "objectSid", NULL};
3550 const char *privname;
3552 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3554 state = h->data;
3556 if (r->in.name == NULL) {
3557 return NT_STATUS_NO_SUCH_PRIVILEGE;
3560 privname = r->in.name->string;
3561 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3562 return NT_STATUS_NO_SUCH_PRIVILEGE;
3565 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3566 "privilege=%s", privname);
3567 if (ret < 0) {
3568 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3570 if (ret == 0) {
3571 return NT_STATUS_NO_MORE_ENTRIES;
3574 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3575 if (r->out.sids->sids == NULL) {
3576 return NT_STATUS_NO_MEMORY;
3578 for (i=0;i<ret;i++) {
3579 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3580 res[i], "objectSid");
3581 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3583 r->out.sids->num_sids = ret;
3585 return NT_STATUS_OK;
3590 lsa_AddAccountRights
3592 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3593 TALLOC_CTX *mem_ctx,
3594 struct lsa_AddAccountRights *r)
3596 struct dcesrv_handle *h;
3597 struct lsa_policy_state *state;
3599 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3601 state = h->data;
3603 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3604 LDB_FLAG_MOD_ADD,
3605 r->in.sid, r->in.rights);
3610 lsa_RemoveAccountRights
3612 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3613 TALLOC_CTX *mem_ctx,
3614 struct lsa_RemoveAccountRights *r)
3616 struct dcesrv_handle *h;
3617 struct lsa_policy_state *state;
3619 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3621 state = h->data;
3623 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3624 LDB_FLAG_MOD_DELETE,
3625 r->in.sid, r->in.rights);
3630 lsa_StorePrivateData
3632 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3633 struct lsa_StorePrivateData *r)
3635 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3640 lsa_RetrievePrivateData
3642 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3643 struct lsa_RetrievePrivateData *r)
3645 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3650 lsa_GetUserName
3652 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3653 struct lsa_GetUserName *r)
3655 enum dcerpc_transport_t transport = dce_call->conn->endpoint->ep_description->transport;
3656 NTSTATUS status = NT_STATUS_OK;
3657 const char *account_name;
3658 const char *authority_name;
3659 struct lsa_String *_account_name;
3660 struct lsa_String *_authority_name = NULL;
3662 if (transport != NCACN_NP && transport != NCALRPC) {
3663 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3666 /* this is what w2k3 does */
3667 r->out.account_name = r->in.account_name;
3668 r->out.authority_name = r->in.authority_name;
3670 if (r->in.account_name
3671 && *r->in.account_name
3672 /* && *(*r->in.account_name)->string */
3674 return NT_STATUS_INVALID_PARAMETER;
3677 if (r->in.authority_name
3678 && *r->in.authority_name
3679 /* && *(*r->in.authority_name)->string */
3681 return NT_STATUS_INVALID_PARAMETER;
3684 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3685 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3687 _account_name = talloc(mem_ctx, struct lsa_String);
3688 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3689 _account_name->string = account_name;
3691 if (r->in.authority_name) {
3692 _authority_name = talloc(mem_ctx, struct lsa_String);
3693 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3694 _authority_name->string = authority_name;
3697 *r->out.account_name = _account_name;
3698 if (r->out.authority_name) {
3699 *r->out.authority_name = _authority_name;
3702 return status;
3706 lsa_SetInfoPolicy2
3708 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3709 TALLOC_CTX *mem_ctx,
3710 struct lsa_SetInfoPolicy2 *r)
3712 /* need to support these */
3713 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3716 static void kdc_get_policy(struct loadparm_context *lp_ctx,
3717 struct smb_krb5_context *smb_krb5_context,
3718 struct lsa_DomainInfoKerberos *k)
3720 time_t svc_tkt_lifetime;
3721 time_t usr_tkt_lifetime;
3722 time_t renewal_lifetime;
3724 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
3726 /* Our KDC always re-validates the client */
3727 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
3729 lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
3730 &usr_tkt_lifetime, &renewal_lifetime);
3732 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
3733 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
3734 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
3735 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
3736 However in the parent function we basically just did a full
3737 krb5_context init with the only purpose of getting a global
3738 config option (the max skew), it would probably make more sense
3739 to have a lp_ or ldb global option as the samba default */
3740 if (smb_krb5_context) {
3741 unix_to_nt_time(&k->clock_skew,
3742 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
3744 #endif
3745 k->reserved = 0;
3748 lsa_QueryDomainInformationPolicy
3750 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3751 TALLOC_CTX *mem_ctx,
3752 struct lsa_QueryDomainInformationPolicy *r)
3754 union lsa_DomainInformationPolicy *info;
3756 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3757 if (!info) {
3758 return NT_STATUS_NO_MEMORY;
3761 switch (r->in.level) {
3762 case LSA_DOMAIN_INFO_POLICY_EFS:
3763 talloc_free(info);
3764 *r->out.info = NULL;
3765 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3766 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3768 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3769 struct smb_krb5_context *smb_krb5_context;
3770 int ret = smb_krb5_init_context(mem_ctx,
3771 dce_call->event_ctx,
3772 dce_call->conn->dce_ctx->lp_ctx,
3773 &smb_krb5_context);
3774 if (ret != 0) {
3775 talloc_free(info);
3776 *r->out.info = NULL;
3777 return NT_STATUS_INTERNAL_ERROR;
3779 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3780 smb_krb5_context,
3782 talloc_free(smb_krb5_context);
3783 *r->out.info = info;
3784 return NT_STATUS_OK;
3786 default:
3787 talloc_free(info);
3788 *r->out.info = NULL;
3789 return NT_STATUS_INVALID_INFO_CLASS;
3794 lsa_SetDomInfoPolicy
3796 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3797 TALLOC_CTX *mem_ctx,
3798 struct lsa_SetDomainInformationPolicy *r)
3800 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3804 lsa_TestCall
3806 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3807 TALLOC_CTX *mem_ctx,
3808 struct lsa_TestCall *r)
3810 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3814 lsa_CREDRWRITE
3816 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3817 struct lsa_CREDRWRITE *r)
3819 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3824 lsa_CREDRREAD
3826 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3827 struct lsa_CREDRREAD *r)
3829 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3834 lsa_CREDRENUMERATE
3836 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3837 struct lsa_CREDRENUMERATE *r)
3839 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3844 lsa_CREDRWRITEDOMAINCREDENTIALS
3846 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3847 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3849 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3854 lsa_CREDRREADDOMAINCREDENTIALS
3856 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3857 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3859 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3864 lsa_CREDRDELETE
3866 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3867 struct lsa_CREDRDELETE *r)
3869 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3874 lsa_CREDRGETTARGETINFO
3876 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3877 struct lsa_CREDRGETTARGETINFO *r)
3879 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3884 lsa_CREDRPROFILELOADED
3886 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3887 struct lsa_CREDRPROFILELOADED *r)
3889 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3894 lsa_CREDRGETSESSIONTYPES
3896 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3897 struct lsa_CREDRGETSESSIONTYPES *r)
3899 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3904 lsa_LSARREGISTERAUDITEVENT
3906 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3907 struct lsa_LSARREGISTERAUDITEVENT *r)
3909 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3914 lsa_LSARGENAUDITEVENT
3916 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3917 struct lsa_LSARGENAUDITEVENT *r)
3919 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3924 lsa_LSARUNREGISTERAUDITEVENT
3926 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3927 struct lsa_LSARUNREGISTERAUDITEVENT *r)
3929 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3934 lsa_lsaRQueryForestTrustInformation
3936 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3937 struct lsa_lsaRQueryForestTrustInformation *r)
3939 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3942 #define DNS_CMP_MATCH 0
3943 #define DNS_CMP_FIRST_IS_CHILD 1
3944 #define DNS_CMP_SECOND_IS_CHILD 2
3945 #define DNS_CMP_NO_MATCH 3
3947 /* this function assumes names are well formed DNS names.
3948 * it doesn't validate them */
3949 static int dns_cmp(const char *s1, size_t l1,
3950 const char *s2, size_t l2)
3952 const char *p1, *p2;
3953 size_t t1, t2;
3954 int cret;
3956 if (l1 == l2) {
3957 if (strcasecmp_m(s1, s2) == 0) {
3958 return DNS_CMP_MATCH;
3960 return DNS_CMP_NO_MATCH;
3963 if (l1 > l2) {
3964 p1 = s1;
3965 p2 = s2;
3966 t1 = l1;
3967 t2 = l2;
3968 cret = DNS_CMP_FIRST_IS_CHILD;
3969 } else {
3970 p1 = s2;
3971 p2 = s1;
3972 t1 = l2;
3973 t2 = l1;
3974 cret = DNS_CMP_SECOND_IS_CHILD;
3977 if (p1[t1 - t2 - 1] != '.') {
3978 return DNS_CMP_NO_MATCH;
3981 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3982 return cret;
3985 return DNS_CMP_NO_MATCH;
3988 /* decode all TDOs forest trust info blobs */
3989 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3990 struct ldb_message *msg,
3991 struct ForestTrustInfo *info)
3993 const struct ldb_val *ft_blob;
3994 enum ndr_err_code ndr_err;
3996 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3997 if (!ft_blob || !ft_blob->data) {
3998 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4000 /* ldb_val is equivalent to DATA_BLOB */
4001 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
4002 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
4003 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4004 return NT_STATUS_INVALID_DOMAIN_STATE;
4007 return NT_STATUS_OK;
4010 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
4011 struct ForestTrustInfo *fti)
4013 struct ForestTrustDataDomainInfo *info;
4014 struct ForestTrustInfoRecord *rec;
4016 fti->version = 1;
4017 fti->count = 2;
4018 fti->records = talloc_array(fti,
4019 struct ForestTrustInfoRecordArmor, 2);
4020 if (!fti->records) {
4021 return NT_STATUS_NO_MEMORY;
4024 /* TLN info */
4025 rec = &fti->records[0].record;
4027 rec->flags = 0;
4028 rec->timestamp = 0;
4029 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
4031 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
4032 if (!rec->data.name.string) {
4033 return NT_STATUS_NO_MEMORY;
4035 rec->data.name.size = strlen(rec->data.name.string);
4037 /* DOMAIN info */
4038 rec = &fti->records[1].record;
4040 rec->flags = 0;
4041 rec->timestamp = 0;
4042 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
4044 info = &rec->data.info;
4046 info->sid = *ps->domain_sid;
4047 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
4048 if (!info->dns_name.string) {
4049 return NT_STATUS_NO_MEMORY;
4051 info->dns_name.size = strlen(info->dns_name.string);
4052 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
4053 if (!info->netbios_name.string) {
4054 return NT_STATUS_NO_MEMORY;
4056 info->netbios_name.size = strlen(info->netbios_name.string);
4058 return NT_STATUS_OK;
4061 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
4062 struct lsa_ForestTrustInformation *lfti,
4063 struct ForestTrustInfo *fti)
4065 struct lsa_ForestTrustRecord *lrec;
4066 struct ForestTrustInfoRecord *rec;
4067 struct lsa_StringLarge *tln;
4068 struct lsa_ForestTrustDomainInfo *info;
4069 uint32_t i;
4071 fti->version = 1;
4072 fti->count = lfti->count;
4073 fti->records = talloc_array(mem_ctx,
4074 struct ForestTrustInfoRecordArmor,
4075 fti->count);
4076 if (!fti->records) {
4077 return NT_STATUS_NO_MEMORY;
4079 for (i = 0; i < fti->count; i++) {
4080 lrec = lfti->entries[i];
4081 rec = &fti->records[i].record;
4083 rec->flags = lrec->flags;
4084 rec->timestamp = lrec->time;
4085 rec->type = lrec->type;
4087 switch (lrec->type) {
4088 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4089 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4090 tln = &lrec->forest_trust_data.top_level_name;
4091 rec->data.name.string =
4092 talloc_strdup(mem_ctx, tln->string);
4093 if (!rec->data.name.string) {
4094 return NT_STATUS_NO_MEMORY;
4096 rec->data.name.size = strlen(rec->data.name.string);
4097 break;
4098 case LSA_FOREST_TRUST_DOMAIN_INFO:
4099 info = &lrec->forest_trust_data.domain_info;
4100 rec->data.info.sid = *info->domain_sid;
4101 rec->data.info.dns_name.string =
4102 talloc_strdup(mem_ctx,
4103 info->dns_domain_name.string);
4104 if (!rec->data.info.dns_name.string) {
4105 return NT_STATUS_NO_MEMORY;
4107 rec->data.info.dns_name.size =
4108 strlen(rec->data.info.dns_name.string);
4109 rec->data.info.netbios_name.string =
4110 talloc_strdup(mem_ctx,
4111 info->netbios_domain_name.string);
4112 if (!rec->data.info.netbios_name.string) {
4113 return NT_STATUS_NO_MEMORY;
4115 rec->data.info.netbios_name.size =
4116 strlen(rec->data.info.netbios_name.string);
4117 break;
4118 default:
4119 return NT_STATUS_INVALID_DOMAIN_STATE;
4123 return NT_STATUS_OK;
4126 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4127 uint32_t idx, uint32_t collision_type,
4128 uint32_t conflict_type, const char *tdo_name);
4130 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4131 const char *tdo_name,
4132 struct ForestTrustInfo *tdo_fti,
4133 struct ForestTrustInfo *new_fti,
4134 struct lsa_ForestTrustCollisionInfo *c_info)
4136 struct ForestTrustInfoRecord *nrec;
4137 struct ForestTrustInfoRecord *trec;
4138 const char *dns_name;
4139 const char *nb_name;
4140 struct dom_sid *sid;
4141 const char *tname;
4142 size_t dns_len;
4143 size_t nb_len;
4144 size_t tlen;
4145 NTSTATUS nt_status;
4146 uint32_t new_fti_idx;
4147 uint32_t i;
4148 /* use always TDO type, until we understand when Xref can be used */
4149 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4150 bool tln_conflict;
4151 bool sid_conflict;
4152 bool nb_conflict;
4153 bool exclusion;
4154 bool ex_rule;
4155 int ret;
4157 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4159 nrec = &new_fti->records[new_fti_idx].record;
4160 dns_name = NULL;
4161 tln_conflict = false;
4162 sid_conflict = false;
4163 nb_conflict = false;
4164 exclusion = false;
4166 switch (nrec->type) {
4167 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4168 /* exclusions do not conflict by definition */
4169 break;
4171 case FOREST_TRUST_TOP_LEVEL_NAME:
4172 dns_name = nrec->data.name.string;
4173 dns_len = nrec->data.name.size;
4174 break;
4176 case LSA_FOREST_TRUST_DOMAIN_INFO:
4177 dns_name = nrec->data.info.dns_name.string;
4178 dns_len = nrec->data.info.dns_name.size;
4179 nb_name = nrec->data.info.netbios_name.string;
4180 nb_len = nrec->data.info.netbios_name.size;
4181 sid = &nrec->data.info.sid;
4182 break;
4185 if (!dns_name) continue;
4187 /* check if this is already taken and not excluded */
4188 for (i = 0; i < tdo_fti->count; i++) {
4189 trec = &tdo_fti->records[i].record;
4191 switch (trec->type) {
4192 case FOREST_TRUST_TOP_LEVEL_NAME:
4193 ex_rule = false;
4194 tname = trec->data.name.string;
4195 tlen = trec->data.name.size;
4196 break;
4197 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4198 ex_rule = true;
4199 tname = trec->data.name.string;
4200 tlen = trec->data.name.size;
4201 break;
4202 case FOREST_TRUST_DOMAIN_INFO:
4203 ex_rule = false;
4204 tname = trec->data.info.dns_name.string;
4205 tlen = trec->data.info.dns_name.size;
4207 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4208 switch (ret) {
4209 case DNS_CMP_MATCH:
4210 /* if it matches exclusion,
4211 * it doesn't conflict */
4212 if (ex_rule) {
4213 exclusion = true;
4214 break;
4216 /* fall through */
4217 case DNS_CMP_FIRST_IS_CHILD:
4218 case DNS_CMP_SECOND_IS_CHILD:
4219 tln_conflict = true;
4220 /* fall through */
4221 default:
4222 break;
4225 /* explicit exclusion, no dns name conflict here */
4226 if (exclusion) {
4227 tln_conflict = false;
4230 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4231 continue;
4234 /* also test for domain info */
4235 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4236 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4237 sid_conflict = true;
4239 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4240 strcasecmp_m(trec->data.info.netbios_name.string,
4241 nb_name) == 0) {
4242 nb_conflict = true;
4246 if (tln_conflict) {
4247 nt_status = add_collision(c_info, new_fti_idx,
4248 collision_type,
4249 LSA_TLN_DISABLED_CONFLICT,
4250 tdo_name);
4252 if (sid_conflict) {
4253 nt_status = add_collision(c_info, new_fti_idx,
4254 collision_type,
4255 LSA_SID_DISABLED_CONFLICT,
4256 tdo_name);
4258 if (nb_conflict) {
4259 nt_status = add_collision(c_info, new_fti_idx,
4260 collision_type,
4261 LSA_NB_DISABLED_CONFLICT,
4262 tdo_name);
4266 return NT_STATUS_OK;
4269 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4270 uint32_t idx, uint32_t collision_type,
4271 uint32_t conflict_type, const char *tdo_name)
4273 struct lsa_ForestTrustCollisionRecord **es;
4274 uint32_t i = c_info->count;
4276 es = talloc_realloc(c_info, c_info->entries,
4277 struct lsa_ForestTrustCollisionRecord *, i + 1);
4278 if (!es) {
4279 return NT_STATUS_NO_MEMORY;
4281 c_info->entries = es;
4282 c_info->count = i + 1;
4284 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4285 if (!es[i]) {
4286 return NT_STATUS_NO_MEMORY;
4289 es[i]->index = idx;
4290 es[i]->type = collision_type;
4291 es[i]->flags.flags = conflict_type;
4292 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4293 if (!es[i]->name.string) {
4294 return NT_STATUS_NO_MEMORY;
4296 es[i]->name.size = strlen(es[i]->name.string);
4298 return NT_STATUS_OK;
4302 lsa_lsaRSetForestTrustInformation
4304 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4305 TALLOC_CTX *mem_ctx,
4306 struct lsa_lsaRSetForestTrustInformation *r)
4308 struct dcesrv_handle *h;
4309 struct lsa_policy_state *p_state;
4310 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4311 "msDS-TrustForestTrustInfo", NULL };
4312 struct ldb_message **dom_res = NULL;
4313 struct ldb_dn *tdo_dn;
4314 struct ldb_message *msg;
4315 int num_res, i;
4316 const char *td_name;
4317 uint32_t trust_attributes;
4318 struct lsa_ForestTrustCollisionInfo *c_info;
4319 struct ForestTrustInfo *nfti;
4320 struct ForestTrustInfo *fti;
4321 DATA_BLOB ft_blob;
4322 enum ndr_err_code ndr_err;
4323 NTSTATUS nt_status;
4324 bool am_rodc;
4325 int ret;
4327 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4329 p_state = h->data;
4331 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4332 return NT_STATUS_INVALID_DOMAIN_STATE;
4335 /* abort if we are not a PDC */
4336 if (!samdb_is_pdc(p_state->sam_ldb)) {
4337 return NT_STATUS_INVALID_DOMAIN_ROLE;
4340 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4341 if (ret == LDB_SUCCESS && am_rodc) {
4342 return NT_STATUS_NO_SUCH_DOMAIN;
4345 /* check caller has TRUSTED_SET_AUTH */
4347 /* fetch all trusted domain objects */
4348 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4349 p_state->system_dn,
4350 &dom_res, trust_attrs,
4351 "(objectclass=trustedDomain)");
4352 if (num_res == 0) {
4353 return NT_STATUS_NO_SUCH_DOMAIN;
4356 for (i = 0; i < num_res; i++) {
4357 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4358 "trustPartner", NULL);
4359 if (!td_name) {
4360 return NT_STATUS_INVALID_DOMAIN_STATE;
4362 if (strcasecmp_m(td_name,
4363 r->in.trusted_domain_name->string) == 0) {
4364 break;
4367 if (i >= num_res) {
4368 return NT_STATUS_NO_SUCH_DOMAIN;
4371 tdo_dn = dom_res[i]->dn;
4373 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4374 "trustAttributes", 0);
4375 if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4376 return NT_STATUS_INVALID_PARAMETER;
4379 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4380 return NT_STATUS_INVALID_PARAMETER;
4383 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4384 if (!nfti) {
4385 return NT_STATUS_NO_MEMORY;
4388 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4389 if (!NT_STATUS_IS_OK(nt_status)) {
4390 return nt_status;
4393 c_info = talloc_zero(r->out.collision_info,
4394 struct lsa_ForestTrustCollisionInfo);
4395 if (!c_info) {
4396 return NT_STATUS_NO_MEMORY;
4399 /* first check own info, then other domains */
4400 fti = talloc(mem_ctx, struct ForestTrustInfo);
4401 if (!fti) {
4402 return NT_STATUS_NO_MEMORY;
4405 nt_status = own_ft_info(p_state, fti);
4406 if (!NT_STATUS_IS_OK(nt_status)) {
4407 return nt_status;
4410 nt_status = check_ft_info(c_info, p_state->domain_dns,
4411 fti, nfti, c_info);
4412 if (!NT_STATUS_IS_OK(nt_status)) {
4413 return nt_status;
4416 for (i = 0; i < num_res; i++) {
4417 fti = talloc(mem_ctx, struct ForestTrustInfo);
4418 if (!fti) {
4419 return NT_STATUS_NO_MEMORY;
4422 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4423 if (!NT_STATUS_IS_OK(nt_status)) {
4424 if (NT_STATUS_EQUAL(nt_status,
4425 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4426 continue;
4428 return nt_status;
4431 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4432 "trustPartner", NULL);
4433 if (!td_name) {
4434 return NT_STATUS_INVALID_DOMAIN_STATE;
4437 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4438 if (!NT_STATUS_IS_OK(nt_status)) {
4439 return nt_status;
4443 *r->out.collision_info = c_info;
4445 if (r->in.check_only != 0) {
4446 return NT_STATUS_OK;
4449 /* not just a check, write info back */
4451 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4452 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4453 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4454 return NT_STATUS_INVALID_PARAMETER;
4457 msg = ldb_msg_new(mem_ctx);
4458 if (msg == NULL) {
4459 return NT_STATUS_NO_MEMORY;
4462 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4463 if (!msg->dn) {
4464 return NT_STATUS_NO_MEMORY;
4467 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4468 LDB_FLAG_MOD_REPLACE, NULL);
4469 if (ret != LDB_SUCCESS) {
4470 return NT_STATUS_NO_MEMORY;
4472 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4473 &ft_blob, NULL);
4474 if (ret != LDB_SUCCESS) {
4475 return NT_STATUS_NO_MEMORY;
4478 ret = ldb_modify(p_state->sam_ldb, msg);
4479 if (ret != LDB_SUCCESS) {
4480 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4481 ldb_errstring(p_state->sam_ldb)));
4483 switch (ret) {
4484 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4485 return NT_STATUS_ACCESS_DENIED;
4486 default:
4487 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4491 return NT_STATUS_OK;
4495 lsa_CREDRRENAME
4497 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4498 struct lsa_CREDRRENAME *r)
4500 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4506 lsa_LSAROPENPOLICYSCE
4508 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4509 struct lsa_LSAROPENPOLICYSCE *r)
4511 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4516 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4518 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4519 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4521 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4526 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4528 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4529 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4531 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4536 lsa_LSARADTREPORTSECURITYEVENT
4538 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4539 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4541 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4545 /* include the generated boilerplate */
4546 #include "librpc/gen_ndr/ndr_lsa_s.c"
4550 /*****************************************
4551 NOTE! The remaining calls below were
4552 removed in w2k3, so the DCESRV_FAULT()
4553 replies are the correct implementation. Do
4554 not try and fill these in with anything else
4555 ******************************************/
4558 dssetup_DsRoleDnsNameToFlatName
4560 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4561 struct dssetup_DsRoleDnsNameToFlatName *r)
4563 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4568 dssetup_DsRoleDcAsDc
4570 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4571 struct dssetup_DsRoleDcAsDc *r)
4573 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4578 dssetup_DsRoleDcAsReplica
4580 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4581 struct dssetup_DsRoleDcAsReplica *r)
4583 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4588 dssetup_DsRoleDemoteDc
4590 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4591 struct dssetup_DsRoleDemoteDc *r)
4593 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4598 dssetup_DsRoleGetDcOperationProgress
4600 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4601 struct dssetup_DsRoleGetDcOperationProgress *r)
4603 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4608 dssetup_DsRoleGetDcOperationResults
4610 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4611 struct dssetup_DsRoleGetDcOperationResults *r)
4613 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4618 dssetup_DsRoleCancel
4620 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4621 struct dssetup_DsRoleCancel *r)
4623 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4628 dssetup_DsRoleServerSaveStateForUpgrade
4630 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4631 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4633 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4638 dssetup_DsRoleUpgradeDownlevelServer
4640 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4641 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4643 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4648 dssetup_DsRoleAbortDownlevelServerUpgrade
4650 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4651 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4653 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4657 /* include the generated boilerplate */
4658 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4660 NTSTATUS dcerpc_server_lsa_init(void)
4662 NTSTATUS ret;
4664 ret = dcerpc_server_dssetup_init();
4665 if (!NT_STATUS_IS_OK(ret)) {
4666 return ret;
4668 ret = dcerpc_server_lsarpc_init();
4669 if (!NT_STATUS_IS_OK(ret)) {
4670 return ret;
4672 return ret;