s4:torture/smb2: fix compound.invalid2 against windows
[Samba/gebeck_regimport.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
blob5acdfe8046081f43617ed6d3dbf39ed3e11af82c
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 "kdc/kdc-policy.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 struct dcesrv_handle *h;
149 *r->out.handle = *r->in.handle;
151 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
153 talloc_free(h);
155 ZERO_STRUCTP(r->out.handle);
157 return NT_STATUS_OK;
162 lsa_Delete
164 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
165 struct lsa_Delete *r)
167 return NT_STATUS_NOT_SUPPORTED;
172 lsa_DeleteObject
174 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
175 struct lsa_DeleteObject *r)
177 struct dcesrv_handle *h;
178 int ret;
180 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
182 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
183 struct lsa_secret_state *secret_state = h->data;
185 /* Ensure user is permitted to delete this... */
186 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
188 case SECURITY_SYSTEM:
189 case SECURITY_ADMINISTRATOR:
190 break;
191 default:
192 /* Users and anonymous are not allowed to delete things */
193 return NT_STATUS_ACCESS_DENIED;
196 ret = ldb_delete(secret_state->sam_ldb,
197 secret_state->secret_dn);
198 if (ret != LDB_SUCCESS) {
199 return NT_STATUS_INVALID_HANDLE;
202 ZERO_STRUCTP(r->out.handle);
204 return NT_STATUS_OK;
206 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
207 struct lsa_trusted_domain_state *trusted_domain_state =
208 talloc_get_type(h->data, struct lsa_trusted_domain_state);
209 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
210 if (ret != LDB_SUCCESS) {
211 return NT_STATUS_INTERNAL_DB_CORRUPTION;
214 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
215 trusted_domain_state->trusted_domain_dn);
216 if (ret != LDB_SUCCESS) {
217 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
218 return NT_STATUS_INVALID_HANDLE;
221 if (trusted_domain_state->trusted_domain_user_dn) {
222 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
223 trusted_domain_state->trusted_domain_user_dn);
224 if (ret != LDB_SUCCESS) {
225 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
226 return NT_STATUS_INVALID_HANDLE;
230 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
231 if (ret != LDB_SUCCESS) {
232 return NT_STATUS_INTERNAL_DB_CORRUPTION;
235 ZERO_STRUCTP(r->out.handle);
237 return NT_STATUS_OK;
239 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
240 struct lsa_RightSet *rights;
241 struct lsa_account_state *astate;
242 struct lsa_EnumAccountRights r2;
243 NTSTATUS status;
245 rights = talloc(mem_ctx, struct lsa_RightSet);
247 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
249 astate = h->data;
251 r2.in.handle = &astate->policy->handle->wire_handle;
252 r2.in.sid = astate->account_sid;
253 r2.out.rights = rights;
255 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
256 but we have a LSA_HANDLE_ACCOUNT here, so this call
257 will always fail */
258 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
259 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
260 return NT_STATUS_OK;
263 if (!NT_STATUS_IS_OK(status)) {
264 return status;
267 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
268 LDB_FLAG_MOD_DELETE, astate->account_sid,
269 r2.out.rights);
270 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
271 return NT_STATUS_OK;
274 if (!NT_STATUS_IS_OK(status)) {
275 return status;
278 ZERO_STRUCTP(r->out.handle);
280 return NT_STATUS_OK;
283 return NT_STATUS_INVALID_HANDLE;
288 lsa_EnumPrivs
290 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
291 struct lsa_EnumPrivs *r)
293 struct dcesrv_handle *h;
294 struct lsa_policy_state *state;
295 uint32_t i;
296 enum sec_privilege priv;
297 const char *privname;
299 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
301 state = h->data;
303 i = *r->in.resume_handle;
305 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
306 r->out.privs->count < r->in.max_count) {
307 struct lsa_PrivEntry *e;
308 privname = sec_privilege_name(priv);
309 r->out.privs->privs = talloc_realloc(r->out.privs,
310 r->out.privs->privs,
311 struct lsa_PrivEntry,
312 r->out.privs->count+1);
313 if (r->out.privs->privs == NULL) {
314 return NT_STATUS_NO_MEMORY;
316 e = &r->out.privs->privs[r->out.privs->count];
317 e->luid.low = priv;
318 e->luid.high = 0;
319 e->name.string = privname;
320 r->out.privs->count++;
321 i++;
324 *r->out.resume_handle = i;
326 return NT_STATUS_OK;
331 lsa_QuerySecObj
333 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
334 struct lsa_QuerySecurity *r)
336 struct dcesrv_handle *h;
337 struct security_descriptor *sd;
338 NTSTATUS status;
339 struct dom_sid *sid;
341 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
343 sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
345 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
346 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
347 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
348 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid,
349 LSA_ACCOUNT_ALL_ACCESS);
350 } else {
351 return NT_STATUS_INVALID_HANDLE;
353 NT_STATUS_NOT_OK_RETURN(status);
355 (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
356 NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
358 (*r->out.sdbuf)->sd = sd;
360 return NT_STATUS_OK;
365 lsa_SetSecObj
367 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
368 struct lsa_SetSecObj *r)
370 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
375 lsa_ChangePassword
377 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
378 struct lsa_ChangePassword *r)
380 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
384 dssetup_DsRoleGetPrimaryDomainInformation
386 This is not an LSA call, but is the only call left on the DSSETUP
387 pipe (after the pipe was truncated), and needs lsa_get_policy_state
389 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
390 TALLOC_CTX *mem_ctx,
391 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
393 union dssetup_DsRoleInfo *info;
395 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
396 W_ERROR_HAVE_NO_MEMORY(info);
398 switch (r->in.level) {
399 case DS_ROLE_BASIC_INFORMATION:
401 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
402 uint32_t flags = 0;
403 const char *domain = NULL;
404 const char *dns_domain = NULL;
405 const char *forest = NULL;
406 struct GUID domain_guid;
407 struct lsa_policy_state *state;
409 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
410 if (!NT_STATUS_IS_OK(status)) {
411 return ntstatus_to_werror(status);
414 ZERO_STRUCT(domain_guid);
416 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
417 case ROLE_STANDALONE:
418 role = DS_ROLE_STANDALONE_SERVER;
419 break;
420 case ROLE_DOMAIN_MEMBER:
421 role = DS_ROLE_MEMBER_SERVER;
422 break;
423 case ROLE_DOMAIN_CONTROLLER:
424 if (samdb_is_pdc(state->sam_ldb)) {
425 role = DS_ROLE_PRIMARY_DC;
426 } else {
427 role = DS_ROLE_BACKUP_DC;
429 break;
432 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
433 case ROLE_STANDALONE:
434 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
435 W_ERROR_HAVE_NO_MEMORY(domain);
436 break;
437 case ROLE_DOMAIN_MEMBER:
438 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
439 W_ERROR_HAVE_NO_MEMORY(domain);
440 /* TODO: what is with dns_domain and forest and guid? */
441 break;
442 case ROLE_DOMAIN_CONTROLLER:
443 flags = DS_ROLE_PRIMARY_DS_RUNNING;
445 if (state->mixed_domain == 1) {
446 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
449 domain = state->domain_name;
450 dns_domain = state->domain_dns;
451 forest = state->forest_dns;
453 domain_guid = state->domain_guid;
454 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
455 break;
458 info->basic.role = role;
459 info->basic.flags = flags;
460 info->basic.domain = domain;
461 info->basic.dns_domain = dns_domain;
462 info->basic.forest = forest;
463 info->basic.domain_guid = domain_guid;
465 r->out.info = info;
466 return WERR_OK;
468 case DS_ROLE_UPGRADE_STATUS:
470 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
471 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
473 r->out.info = info;
474 return WERR_OK;
476 case DS_ROLE_OP_STATUS:
478 info->opstatus.status = DS_ROLE_OP_IDLE;
480 r->out.info = info;
481 return WERR_OK;
483 default:
484 return WERR_INVALID_PARAM;
489 fill in the AccountDomain info
491 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
492 struct lsa_DomainInfo *info)
494 info->name.string = state->domain_name;
495 info->sid = state->domain_sid;
497 return NT_STATUS_OK;
501 fill in the DNS domain info
503 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
504 struct lsa_DnsDomainInfo *info)
506 info->name.string = state->domain_name;
507 info->sid = state->domain_sid;
508 info->dns_domain.string = state->domain_dns;
509 info->dns_forest.string = state->forest_dns;
510 info->domain_guid = state->domain_guid;
512 return NT_STATUS_OK;
516 lsa_QueryInfoPolicy2
518 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
519 struct lsa_QueryInfoPolicy2 *r)
521 struct lsa_policy_state *state;
522 struct dcesrv_handle *h;
523 union lsa_PolicyInformation *info;
525 *r->out.info = NULL;
527 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
529 state = h->data;
531 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
532 if (!info) {
533 return NT_STATUS_NO_MEMORY;
535 *r->out.info = info;
537 switch (r->in.level) {
538 case LSA_POLICY_INFO_AUDIT_LOG:
539 /* we don't need to fill in any of this */
540 ZERO_STRUCT(info->audit_log);
541 return NT_STATUS_OK;
542 case LSA_POLICY_INFO_AUDIT_EVENTS:
543 /* we don't need to fill in any of this */
544 ZERO_STRUCT(info->audit_events);
545 return NT_STATUS_OK;
546 case LSA_POLICY_INFO_PD:
547 /* we don't need to fill in any of this */
548 ZERO_STRUCT(info->pd);
549 return NT_STATUS_OK;
551 case LSA_POLICY_INFO_DOMAIN:
552 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
553 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
554 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
555 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
556 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
558 case LSA_POLICY_INFO_ROLE:
559 info->role.role = LSA_ROLE_PRIMARY;
560 return NT_STATUS_OK;
562 case LSA_POLICY_INFO_DNS:
563 case LSA_POLICY_INFO_DNS_INT:
564 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
566 case LSA_POLICY_INFO_REPLICA:
567 ZERO_STRUCT(info->replica);
568 return NT_STATUS_OK;
570 case LSA_POLICY_INFO_QUOTA:
571 ZERO_STRUCT(info->quota);
572 return NT_STATUS_OK;
574 case LSA_POLICY_INFO_MOD:
575 case LSA_POLICY_INFO_AUDIT_FULL_SET:
576 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
577 /* windows gives INVALID_PARAMETER */
578 *r->out.info = NULL;
579 return NT_STATUS_INVALID_PARAMETER;
582 *r->out.info = NULL;
583 return NT_STATUS_INVALID_INFO_CLASS;
587 lsa_QueryInfoPolicy
589 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
590 struct lsa_QueryInfoPolicy *r)
592 struct lsa_QueryInfoPolicy2 r2;
593 NTSTATUS status;
595 ZERO_STRUCT(r2);
597 r2.in.handle = r->in.handle;
598 r2.in.level = r->in.level;
599 r2.out.info = r->out.info;
601 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
603 return status;
607 lsa_SetInfoPolicy
609 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
610 struct lsa_SetInfoPolicy *r)
612 /* need to support this */
613 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
618 lsa_ClearAuditLog
620 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
621 struct lsa_ClearAuditLog *r)
623 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
628 lsa_CreateAccount
630 This call does not seem to have any long-term effects, hence no database operations
632 we need to talk to the MS product group to find out what this account database means!
634 answer is that the lsa database is totally separate from the SAM and
635 ldap databases. We are going to need a separate ldb to store these
636 accounts. The SIDs on this account bear no relation to the SIDs in
639 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
640 struct lsa_CreateAccount *r)
642 struct lsa_account_state *astate;
644 struct lsa_policy_state *state;
645 struct dcesrv_handle *h, *ah;
647 ZERO_STRUCTP(r->out.acct_handle);
649 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
651 state = h->data;
653 astate = talloc(dce_call->conn, struct lsa_account_state);
654 if (astate == NULL) {
655 return NT_STATUS_NO_MEMORY;
658 astate->account_sid = dom_sid_dup(astate, r->in.sid);
659 if (astate->account_sid == NULL) {
660 talloc_free(astate);
661 return NT_STATUS_NO_MEMORY;
664 astate->policy = talloc_reference(astate, state);
665 astate->access_mask = r->in.access_mask;
667 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
668 if (!ah) {
669 talloc_free(astate);
670 return NT_STATUS_NO_MEMORY;
673 ah->data = talloc_steal(ah, astate);
675 *r->out.acct_handle = ah->wire_handle;
677 return NT_STATUS_OK;
682 lsa_EnumAccounts
684 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
685 struct lsa_EnumAccounts *r)
687 struct dcesrv_handle *h;
688 struct lsa_policy_state *state;
689 int ret;
690 struct ldb_message **res;
691 const char * const attrs[] = { "objectSid", NULL};
692 uint32_t count, i;
694 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
696 state = h->data;
698 /* NOTE: This call must only return accounts that have at least
699 one privilege set
701 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
702 "(&(objectSid=*)(privilege=*))");
703 if (ret < 0) {
704 return NT_STATUS_INTERNAL_DB_CORRUPTION;
707 if (*r->in.resume_handle >= ret) {
708 return NT_STATUS_NO_MORE_ENTRIES;
711 count = ret - *r->in.resume_handle;
712 if (count > r->in.num_entries) {
713 count = r->in.num_entries;
716 if (count == 0) {
717 return NT_STATUS_NO_MORE_ENTRIES;
720 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
721 if (r->out.sids->sids == NULL) {
722 return NT_STATUS_NO_MEMORY;
725 for (i=0;i<count;i++) {
726 r->out.sids->sids[i].sid =
727 samdb_result_dom_sid(r->out.sids->sids,
728 res[i + *r->in.resume_handle],
729 "objectSid");
730 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
733 r->out.sids->num_sids = count;
734 *r->out.resume_handle = count + *r->in.resume_handle;
736 return NT_STATUS_OK;
740 /* This decrypts and returns Trusted Domain Auth Information Internal data */
741 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
742 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
743 struct trustDomainPasswords *auth_struct)
745 DATA_BLOB session_key = data_blob(NULL, 0);
746 enum ndr_err_code ndr_err;
747 NTSTATUS nt_status;
749 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
750 if (!NT_STATUS_IS_OK(nt_status)) {
751 return nt_status;
754 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
755 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
756 auth_struct,
757 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
758 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
759 return NT_STATUS_INVALID_PARAMETER;
762 return NT_STATUS_OK;
765 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
766 TALLOC_CTX *mem_ctx,
767 struct trustAuthInOutBlob *iopw,
768 DATA_BLOB *trustauth_blob)
770 enum ndr_err_code ndr_err;
772 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
773 iopw,
774 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
775 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
776 return NT_STATUS_INVALID_PARAMETER;
779 return NT_STATUS_OK;
782 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
783 struct ldb_context *sam_ldb,
784 struct ldb_dn *base_dn,
785 const char *netbios_name,
786 struct trustAuthInOutBlob *in,
787 struct ldb_dn **user_dn)
789 struct ldb_message *msg;
790 struct ldb_dn *dn;
791 uint32_t i;
792 int ret;
794 dn = ldb_dn_copy(mem_ctx, base_dn);
795 if (!dn) {
796 return NT_STATUS_NO_MEMORY;
798 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
799 return NT_STATUS_NO_MEMORY;
802 msg = ldb_msg_new(mem_ctx);
803 if (!msg) {
804 return NT_STATUS_NO_MEMORY;
806 msg->dn = dn;
808 ret = ldb_msg_add_string(msg, "objectClass", "user");
809 if (ret != LDB_SUCCESS) {
810 return NT_STATUS_NO_MEMORY;
813 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
814 if (ret != LDB_SUCCESS) {
815 return NT_STATUS_NO_MEMORY;
818 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
819 UF_INTERDOMAIN_TRUST_ACCOUNT);
820 if (ret != LDB_SUCCESS) {
821 return NT_STATUS_NO_MEMORY;
824 for (i = 0; i < in->count; i++) {
825 const char *attribute;
826 struct ldb_val v;
827 switch (in->current.array[i].AuthType) {
828 case TRUST_AUTH_TYPE_NT4OWF:
829 attribute = "unicodePwd";
830 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
831 v.length = 16;
832 break;
833 case TRUST_AUTH_TYPE_CLEAR:
834 attribute = "clearTextPassword";
835 v.data = in->current.array[i].AuthInfo.clear.password;
836 v.length = in->current.array[i].AuthInfo.clear.size;
837 break;
838 default:
839 continue;
842 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
843 if (ret != LDB_SUCCESS) {
844 return NT_STATUS_NO_MEMORY;
848 /* create the trusted_domain user account */
849 ret = ldb_add(sam_ldb, msg);
850 if (ret != LDB_SUCCESS) {
851 DEBUG(0,("Failed to create user record %s: %s\n",
852 ldb_dn_get_linearized(msg->dn),
853 ldb_errstring(sam_ldb)));
855 switch (ret) {
856 case LDB_ERR_ENTRY_ALREADY_EXISTS:
857 return NT_STATUS_DOMAIN_EXISTS;
858 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
859 return NT_STATUS_ACCESS_DENIED;
860 default:
861 return NT_STATUS_INTERNAL_DB_CORRUPTION;
865 if (user_dn) {
866 *user_dn = dn;
868 return NT_STATUS_OK;
872 lsa_CreateTrustedDomainEx2
874 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
875 TALLOC_CTX *mem_ctx,
876 struct lsa_CreateTrustedDomainEx2 *r,
877 int op,
878 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
880 struct dcesrv_handle *policy_handle;
881 struct lsa_policy_state *policy_state;
882 struct lsa_trusted_domain_state *trusted_domain_state;
883 struct dcesrv_handle *handle;
884 struct ldb_message **msgs, *msg;
885 const char *attrs[] = {
886 NULL
888 const char *netbios_name;
889 const char *dns_name;
890 const char *name;
891 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
892 struct trustDomainPasswords auth_struct;
893 int ret;
894 NTSTATUS nt_status;
895 struct ldb_context *sam_ldb;
897 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
898 ZERO_STRUCTP(r->out.trustdom_handle);
900 policy_state = policy_handle->data;
901 sam_ldb = policy_state->sam_ldb;
903 netbios_name = r->in.info->netbios_name.string;
904 if (!netbios_name) {
905 return NT_STATUS_INVALID_PARAMETER;
908 dns_name = r->in.info->domain_name.string;
910 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
911 if (!trusted_domain_state) {
912 return NT_STATUS_NO_MEMORY;
914 trusted_domain_state->policy = policy_state;
916 if (strcasecmp(netbios_name, "BUILTIN") == 0
917 || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
918 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
919 return NT_STATUS_INVALID_PARAMETER;
922 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
923 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
924 || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
925 || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
926 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
927 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
930 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
931 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
932 /* No secrets are created at this time, for this function */
933 auth_struct.outgoing.count = 0;
934 auth_struct.incoming.count = 0;
935 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
936 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
937 r->in.auth_info_internal->auth_blob.size);
938 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
939 &auth_blob, &auth_struct);
940 if (!NT_STATUS_IS_OK(nt_status)) {
941 return nt_status;
943 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
945 if (unencrypted_auth_info->incoming_count > 1) {
946 return NT_STATUS_INVALID_PARAMETER;
949 /* more investigation required here, do not create secrets for
950 * now */
951 auth_struct.outgoing.count = 0;
952 auth_struct.incoming.count = 0;
953 } else {
954 return NT_STATUS_INVALID_PARAMETER;
957 if (auth_struct.incoming.count) {
958 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
959 &auth_struct.incoming,
960 &trustAuthIncoming);
961 if (!NT_STATUS_IS_OK(nt_status)) {
962 return nt_status;
964 } else {
965 trustAuthIncoming = data_blob(NULL, 0);
968 if (auth_struct.outgoing.count) {
969 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
970 &auth_struct.outgoing,
971 &trustAuthOutgoing);
972 if (!NT_STATUS_IS_OK(nt_status)) {
973 return nt_status;
975 } else {
976 trustAuthOutgoing = data_blob(NULL, 0);
979 ret = ldb_transaction_start(sam_ldb);
980 if (ret != LDB_SUCCESS) {
981 return NT_STATUS_INTERNAL_DB_CORRUPTION;
984 if (dns_name) {
985 char *dns_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
986 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
987 /* search for the trusted_domain record */
988 ret = gendb_search(sam_ldb,
989 mem_ctx, policy_state->system_dn, &msgs, attrs,
990 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
991 dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
992 if (ret > 0) {
993 ldb_transaction_cancel(sam_ldb);
994 return NT_STATUS_OBJECT_NAME_COLLISION;
996 } else {
997 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
998 /* search for the trusted_domain record */
999 ret = gendb_search(sam_ldb,
1000 mem_ctx, policy_state->system_dn, &msgs, attrs,
1001 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1002 netbios_encoded, netbios_encoded, netbios_encoded);
1003 if (ret > 0) {
1004 ldb_transaction_cancel(sam_ldb);
1005 return NT_STATUS_OBJECT_NAME_COLLISION;
1009 if (ret < 0 ) {
1010 ldb_transaction_cancel(sam_ldb);
1011 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1014 name = dns_name ? dns_name : netbios_name;
1016 msg = ldb_msg_new(mem_ctx);
1017 if (msg == NULL) {
1018 return NT_STATUS_NO_MEMORY;
1021 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1022 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1023 ldb_transaction_cancel(sam_ldb);
1024 return NT_STATUS_NO_MEMORY;
1027 ldb_msg_add_string(msg, "flatname", netbios_name);
1029 if (r->in.info->sid) {
1030 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1031 if (ret != LDB_SUCCESS) {
1032 ldb_transaction_cancel(sam_ldb);
1033 return NT_STATUS_INVALID_PARAMETER;
1037 ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1039 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1041 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1043 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1045 if (dns_name) {
1046 ldb_msg_add_string(msg, "trustPartner", dns_name);
1049 if (trustAuthIncoming.data) {
1050 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1051 if (ret != LDB_SUCCESS) {
1052 ldb_transaction_cancel(sam_ldb);
1053 return NT_STATUS_NO_MEMORY;
1056 if (trustAuthOutgoing.data) {
1057 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1058 if (ret != LDB_SUCCESS) {
1059 ldb_transaction_cancel(sam_ldb);
1060 return NT_STATUS_NO_MEMORY;
1064 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1066 /* create the trusted_domain */
1067 ret = ldb_add(sam_ldb, msg);
1068 switch (ret) {
1069 case LDB_SUCCESS:
1070 break;
1071 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1072 ldb_transaction_cancel(sam_ldb);
1073 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1074 ldb_dn_get_linearized(msg->dn),
1075 ldb_errstring(sam_ldb)));
1076 return NT_STATUS_DOMAIN_EXISTS;
1077 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1078 ldb_transaction_cancel(sam_ldb);
1079 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1080 ldb_dn_get_linearized(msg->dn),
1081 ldb_errstring(sam_ldb)));
1082 return NT_STATUS_ACCESS_DENIED;
1083 default:
1084 ldb_transaction_cancel(sam_ldb);
1085 DEBUG(0,("Failed to create user record %s: %s\n",
1086 ldb_dn_get_linearized(msg->dn),
1087 ldb_errstring(sam_ldb)));
1088 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1091 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1092 struct ldb_dn *user_dn;
1093 /* Inbound trusts must also create a cn=users object to match */
1094 nt_status = add_trust_user(mem_ctx, sam_ldb,
1095 policy_state->domain_dn,
1096 netbios_name,
1097 &auth_struct.incoming,
1098 &user_dn);
1099 if (!NT_STATUS_IS_OK(nt_status)) {
1100 ldb_transaction_cancel(sam_ldb);
1101 return nt_status;
1104 /* save the trust user dn */
1105 trusted_domain_state->trusted_domain_user_dn
1106 = talloc_steal(trusted_domain_state, user_dn);
1109 ret = ldb_transaction_commit(sam_ldb);
1110 if (ret != LDB_SUCCESS) {
1111 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1114 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1115 if (!handle) {
1116 return NT_STATUS_NO_MEMORY;
1119 handle->data = talloc_steal(handle, trusted_domain_state);
1121 trusted_domain_state->access_mask = r->in.access_mask;
1122 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1124 *r->out.trustdom_handle = handle->wire_handle;
1126 return NT_STATUS_OK;
1130 lsa_CreateTrustedDomainEx2
1132 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1133 TALLOC_CTX *mem_ctx,
1134 struct lsa_CreateTrustedDomainEx2 *r)
1136 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1139 lsa_CreateTrustedDomainEx
1141 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1142 TALLOC_CTX *mem_ctx,
1143 struct lsa_CreateTrustedDomainEx *r)
1145 struct lsa_CreateTrustedDomainEx2 r2;
1147 r2.in.policy_handle = r->in.policy_handle;
1148 r2.in.info = r->in.info;
1149 r2.out.trustdom_handle = r->out.trustdom_handle;
1150 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1154 lsa_CreateTrustedDomain
1156 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1157 struct lsa_CreateTrustedDomain *r)
1159 struct lsa_CreateTrustedDomainEx2 r2;
1161 r2.in.policy_handle = r->in.policy_handle;
1162 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1163 if (!r2.in.info) {
1164 return NT_STATUS_NO_MEMORY;
1167 r2.in.info->domain_name.string = NULL;
1168 r2.in.info->netbios_name = r->in.info->name;
1169 r2.in.info->sid = r->in.info->sid;
1170 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1171 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1172 r2.in.info->trust_attributes = 0;
1174 r2.in.access_mask = r->in.access_mask;
1175 r2.out.trustdom_handle = r->out.trustdom_handle;
1177 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1182 lsa_OpenTrustedDomain
1184 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1185 struct lsa_OpenTrustedDomain *r)
1187 struct dcesrv_handle *policy_handle;
1189 struct lsa_policy_state *policy_state;
1190 struct lsa_trusted_domain_state *trusted_domain_state;
1191 struct dcesrv_handle *handle;
1192 struct ldb_message **msgs;
1193 const char *attrs[] = {
1194 "trustDirection",
1195 "flatname",
1196 NULL
1199 const char *sid_string;
1200 int ret;
1202 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1203 ZERO_STRUCTP(r->out.trustdom_handle);
1204 policy_state = policy_handle->data;
1206 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1207 if (!trusted_domain_state) {
1208 return NT_STATUS_NO_MEMORY;
1210 trusted_domain_state->policy = policy_state;
1212 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1213 if (!sid_string) {
1214 return NT_STATUS_NO_MEMORY;
1217 /* search for the trusted_domain record */
1218 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1219 mem_ctx, policy_state->system_dn, &msgs, attrs,
1220 "(&(securityIdentifier=%s)(objectclass=trustedDomain))",
1221 sid_string);
1222 if (ret == 0) {
1223 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1226 if (ret != 1) {
1227 DEBUG(0,("Found %d records matching DN %s\n", ret,
1228 ldb_dn_get_linearized(policy_state->system_dn)));
1229 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1232 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1234 trusted_domain_state->trusted_domain_user_dn = NULL;
1236 if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1237 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1238 /* search for the trusted_domain record */
1239 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1240 mem_ctx, policy_state->domain_dn, &msgs, attrs,
1241 "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%u))",
1242 flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1243 if (ret == 1) {
1244 trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1247 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1248 if (!handle) {
1249 return NT_STATUS_NO_MEMORY;
1252 handle->data = talloc_steal(handle, trusted_domain_state);
1254 trusted_domain_state->access_mask = r->in.access_mask;
1255 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1257 *r->out.trustdom_handle = handle->wire_handle;
1259 return NT_STATUS_OK;
1264 lsa_OpenTrustedDomainByName
1266 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1267 TALLOC_CTX *mem_ctx,
1268 struct lsa_OpenTrustedDomainByName *r)
1270 struct dcesrv_handle *policy_handle;
1272 struct lsa_policy_state *policy_state;
1273 struct lsa_trusted_domain_state *trusted_domain_state;
1274 struct dcesrv_handle *handle;
1275 struct ldb_message **msgs;
1276 const char *attrs[] = {
1277 NULL
1279 char *td_name;
1280 int ret;
1282 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1283 ZERO_STRUCTP(r->out.trustdom_handle);
1284 policy_state = policy_handle->data;
1286 if (!r->in.name.string) {
1287 return NT_STATUS_INVALID_PARAMETER;
1290 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1291 if (!trusted_domain_state) {
1292 return NT_STATUS_NO_MEMORY;
1294 trusted_domain_state->policy = policy_state;
1296 /* search for the trusted_domain record */
1297 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1298 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1299 mem_ctx, policy_state->system_dn, &msgs, attrs,
1300 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1301 "(objectclass=trustedDomain))",
1302 td_name, td_name, td_name);
1303 if (ret == 0) {
1304 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1307 if (ret != 1) {
1308 DEBUG(0,("Found %d records matching DN %s\n", ret,
1309 ldb_dn_get_linearized(policy_state->system_dn)));
1310 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1313 /* TODO: perform access checks */
1315 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1317 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1318 if (!handle) {
1319 return NT_STATUS_NO_MEMORY;
1322 handle->data = talloc_steal(handle, trusted_domain_state);
1324 trusted_domain_state->access_mask = r->in.access_mask;
1325 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1327 *r->out.trustdom_handle = handle->wire_handle;
1329 return NT_STATUS_OK;
1335 lsa_SetTrustedDomainInfo
1337 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1338 struct lsa_SetTrustedDomainInfo *r)
1340 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1345 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1346 * otherwise at least one must be provided */
1347 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1348 struct ldb_dn *basedn, const char *dns_domain,
1349 const char *netbios, struct dom_sid2 *sid,
1350 struct ldb_message ***msgs)
1352 const char *attrs[] = { "flatname", "trustPartner",
1353 "securityIdentifier", "trustDirection",
1354 "trustType", "trustAttributes",
1355 "trustPosixOffset",
1356 "msDs-supportedEncryptionTypes", NULL };
1357 char *dns = NULL;
1358 char *nbn = NULL;
1359 char *sidstr = NULL;
1360 char *filter;
1361 int ret;
1364 if (dns_domain || netbios || sid) {
1365 filter = talloc_strdup(mem_ctx,
1366 "(&(objectclass=trustedDomain)(|");
1367 } else {
1368 filter = talloc_strdup(mem_ctx,
1369 "(objectclass=trustedDomain)");
1371 if (!filter) {
1372 return NT_STATUS_NO_MEMORY;
1375 if (dns_domain) {
1376 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1377 if (!dns) {
1378 return NT_STATUS_NO_MEMORY;
1380 filter = talloc_asprintf_append(filter,
1381 "(trustPartner=%s)", dns);
1382 if (!filter) {
1383 return NT_STATUS_NO_MEMORY;
1386 if (netbios) {
1387 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1388 if (!nbn) {
1389 return NT_STATUS_NO_MEMORY;
1391 filter = talloc_asprintf_append(filter,
1392 "(flatname=%s)", nbn);
1393 if (!filter) {
1394 return NT_STATUS_NO_MEMORY;
1397 if (sid) {
1398 sidstr = dom_sid_string(mem_ctx, sid);
1399 if (!sidstr) {
1400 return NT_STATUS_INVALID_PARAMETER;
1402 filter = talloc_asprintf_append(filter,
1403 "(securityIdentifier=%s)",
1404 sidstr);
1405 if (!filter) {
1406 return NT_STATUS_NO_MEMORY;
1409 if (dns_domain || netbios || sid) {
1410 filter = talloc_asprintf_append(filter, "))");
1411 if (!filter) {
1412 return NT_STATUS_NO_MEMORY;
1416 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1417 if (ret == 0) {
1418 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1421 if (ret != 1) {
1422 return NT_STATUS_OBJECT_NAME_COLLISION;
1425 return NT_STATUS_OK;
1428 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1429 struct ldb_context *sam_ldb,
1430 struct ldb_message *orig,
1431 struct ldb_message *dest,
1432 const char *attribute,
1433 uint32_t value,
1434 uint32_t *orig_value)
1436 const struct ldb_val *orig_val;
1437 uint32_t orig_uint = 0;
1438 unsigned int flags = 0;
1439 int ret;
1441 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1442 if (!orig_val || !orig_val->data) {
1443 /* add new attribute */
1444 flags = LDB_FLAG_MOD_ADD;
1446 } else {
1447 errno = 0;
1448 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1449 if (errno != 0 || orig_uint != value) {
1450 /* replace also if can't get value */
1451 flags = LDB_FLAG_MOD_REPLACE;
1455 if (flags == 0) {
1456 /* stored value is identical, nothing to change */
1457 goto done;
1460 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1461 if (ret != LDB_SUCCESS) {
1462 return NT_STATUS_NO_MEMORY;
1465 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1466 if (ret != LDB_SUCCESS) {
1467 return NT_STATUS_NO_MEMORY;
1470 done:
1471 if (orig_value) {
1472 *orig_value = orig_uint;
1474 return NT_STATUS_OK;
1477 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1478 struct ldb_context *sam_ldb,
1479 struct ldb_dn *base_dn,
1480 bool delete_user,
1481 const char *netbios_name,
1482 struct trustAuthInOutBlob *in)
1484 const char *attrs[] = { "userAccountControl", NULL };
1485 struct ldb_message **msgs;
1486 struct ldb_message *msg;
1487 uint32_t uac;
1488 uint32_t i;
1489 int ret;
1491 ret = gendb_search(sam_ldb, mem_ctx,
1492 base_dn, &msgs, attrs,
1493 "samAccountName=%s$", netbios_name);
1494 if (ret > 1) {
1495 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1498 if (ret == 0) {
1499 if (delete_user) {
1500 return NT_STATUS_OK;
1503 /* ok no existing user, add it from scratch */
1504 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1505 netbios_name, in, NULL);
1508 /* check user is what we are looking for */
1509 uac = ldb_msg_find_attr_as_uint(msgs[0],
1510 "userAccountControl", 0);
1511 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1512 return NT_STATUS_OBJECT_NAME_COLLISION;
1515 if (delete_user) {
1516 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1517 switch (ret) {
1518 case LDB_SUCCESS:
1519 return NT_STATUS_OK;
1520 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1521 return NT_STATUS_ACCESS_DENIED;
1522 default:
1523 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1527 /* entry exists, just modify secret if any */
1528 if (in->count == 0) {
1529 return NT_STATUS_OK;
1532 msg = ldb_msg_new(mem_ctx);
1533 if (!msg) {
1534 return NT_STATUS_NO_MEMORY;
1536 msg->dn = msgs[0]->dn;
1538 for (i = 0; i < in->count; i++) {
1539 const char *attribute;
1540 struct ldb_val v;
1541 switch (in->current.array[i].AuthType) {
1542 case TRUST_AUTH_TYPE_NT4OWF:
1543 attribute = "unicodePwd";
1544 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1545 v.length = 16;
1546 break;
1547 case TRUST_AUTH_TYPE_CLEAR:
1548 attribute = "clearTextPassword";
1549 v.data = in->current.array[i].AuthInfo.clear.password;
1550 v.length = in->current.array[i].AuthInfo.clear.size;
1551 break;
1552 default:
1553 continue;
1556 ret = ldb_msg_add_empty(msg, attribute,
1557 LDB_FLAG_MOD_REPLACE, NULL);
1558 if (ret != LDB_SUCCESS) {
1559 return NT_STATUS_NO_MEMORY;
1562 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1563 if (ret != LDB_SUCCESS) {
1564 return NT_STATUS_NO_MEMORY;
1568 /* create the trusted_domain user account */
1569 ret = ldb_modify(sam_ldb, msg);
1570 if (ret != LDB_SUCCESS) {
1571 DEBUG(0,("Failed to create user record %s: %s\n",
1572 ldb_dn_get_linearized(msg->dn),
1573 ldb_errstring(sam_ldb)));
1575 switch (ret) {
1576 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1577 return NT_STATUS_DOMAIN_EXISTS;
1578 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1579 return NT_STATUS_ACCESS_DENIED;
1580 default:
1581 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1585 return NT_STATUS_OK;
1589 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1590 struct dcesrv_handle *p_handle,
1591 TALLOC_CTX *mem_ctx,
1592 struct ldb_message *dom_msg,
1593 enum lsa_TrustDomInfoEnum level,
1594 union lsa_TrustedDomainInfo *info)
1596 struct lsa_policy_state *p_state = p_handle->data;
1597 uint32_t *posix_offset = NULL;
1598 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1599 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1600 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1601 uint32_t *enc_types = NULL;
1602 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1603 struct trustDomainPasswords auth_struct;
1604 NTSTATUS nt_status;
1605 struct ldb_message **msgs;
1606 struct ldb_message *msg;
1607 bool add_outgoing = false;
1608 bool add_incoming = false;
1609 bool del_outgoing = false;
1610 bool del_incoming = false;
1611 bool in_transaction = false;
1612 int ret;
1613 bool am_rodc;
1615 switch (level) {
1616 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1617 posix_offset = &info->posix_offset.posix_offset;
1618 break;
1619 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1620 info_ex = &info->info_ex;
1621 break;
1622 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1623 auth_info = &info->auth_info;
1624 break;
1625 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1626 posix_offset = &info->full_info.posix_offset.posix_offset;
1627 info_ex = &info->full_info.info_ex;
1628 auth_info = &info->full_info.auth_info;
1629 break;
1630 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1631 auth_info_int = &info->auth_info_internal;
1632 break;
1633 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1634 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1635 info_ex = &info->full_info_internal.info_ex;
1636 auth_info_int = &info->full_info_internal.auth_info;
1637 break;
1638 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1639 enc_types = &info->enc_types.enc_types;
1640 break;
1641 default:
1642 return NT_STATUS_INVALID_PARAMETER;
1645 if (auth_info) {
1646 /* FIXME: not handled yet */
1647 return NT_STATUS_INVALID_PARAMETER;
1650 /* decode auth_info_int if set */
1651 if (auth_info_int) {
1653 /* now decrypt blob */
1654 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1655 auth_info_int->auth_blob.size);
1657 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1658 &auth_blob, &auth_struct);
1659 if (!NT_STATUS_IS_OK(nt_status)) {
1660 return nt_status;
1664 if (info_ex) {
1665 /* verify data matches */
1666 if (info_ex->trust_attributes &
1667 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1668 /* TODO: check what behavior level we have */
1669 if (strcasecmp_m(p_state->domain_dns,
1670 p_state->forest_dns) != 0) {
1671 return NT_STATUS_INVALID_DOMAIN_STATE;
1675 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1676 if (ret == LDB_SUCCESS && am_rodc) {
1677 return NT_STATUS_NO_SUCH_DOMAIN;
1680 /* verify only one object matches the dns/netbios/sid
1681 * triplet and that this is the one we already have */
1682 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1683 p_state->system_dn,
1684 info_ex->domain_name.string,
1685 info_ex->netbios_name.string,
1686 info_ex->sid, &msgs);
1687 if (!NT_STATUS_IS_OK(nt_status)) {
1688 return nt_status;
1690 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1691 return NT_STATUS_OBJECT_NAME_COLLISION;
1693 talloc_free(msgs);
1696 /* TODO: should we fetch previous values from the existing entry
1697 * and append them ? */
1698 if (auth_struct.incoming.count) {
1699 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1700 &auth_struct.incoming,
1701 &trustAuthIncoming);
1702 if (!NT_STATUS_IS_OK(nt_status)) {
1703 return nt_status;
1705 } else {
1706 trustAuthIncoming = data_blob(NULL, 0);
1709 if (auth_struct.outgoing.count) {
1710 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1711 &auth_struct.outgoing,
1712 &trustAuthOutgoing);
1713 if (!NT_STATUS_IS_OK(nt_status)) {
1714 return nt_status;
1716 } else {
1717 trustAuthOutgoing = data_blob(NULL, 0);
1720 msg = ldb_msg_new(mem_ctx);
1721 if (msg == NULL) {
1722 return NT_STATUS_NO_MEMORY;
1724 msg->dn = dom_msg->dn;
1726 if (posix_offset) {
1727 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1728 dom_msg, msg,
1729 "trustPosixOffset",
1730 *posix_offset, NULL);
1731 if (!NT_STATUS_IS_OK(nt_status)) {
1732 return nt_status;
1736 if (info_ex) {
1737 uint32_t origattrs;
1738 uint32_t origdir;
1739 int origtype;
1741 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1742 dom_msg, msg,
1743 "trustDirection",
1744 info_ex->trust_direction,
1745 &origdir);
1746 if (!NT_STATUS_IS_OK(nt_status)) {
1747 return nt_status;
1750 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1751 add_incoming = true;
1753 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1754 add_outgoing = true;
1757 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1758 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1759 del_incoming = true;
1761 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1762 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1763 del_outgoing = true;
1766 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1767 if (origtype == -1 || origtype != info_ex->trust_type) {
1768 DEBUG(1, ("Attempted to change trust type! "
1769 "Operation not handled\n"));
1770 return NT_STATUS_INVALID_PARAMETER;
1773 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1774 dom_msg, msg,
1775 "trustAttributes",
1776 info_ex->trust_attributes,
1777 &origattrs);
1778 if (!NT_STATUS_IS_OK(nt_status)) {
1779 return nt_status;
1781 /* TODO: check forestFunctionality from ldb opaque */
1782 /* TODO: check what is set makes sense */
1783 /* for now refuse changes */
1784 if (origattrs == -1 ||
1785 origattrs != info_ex->trust_attributes) {
1786 DEBUG(1, ("Attempted to change trust attributes! "
1787 "Operation not handled\n"));
1788 return NT_STATUS_INVALID_PARAMETER;
1792 if (enc_types) {
1793 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1794 dom_msg, msg,
1795 "msDS-SupportedEncryptionTypes",
1796 *enc_types, NULL);
1797 if (!NT_STATUS_IS_OK(nt_status)) {
1798 return nt_status;
1802 if (add_incoming && trustAuthIncoming.data) {
1803 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1804 LDB_FLAG_MOD_REPLACE, NULL);
1805 if (ret != LDB_SUCCESS) {
1806 return NT_STATUS_NO_MEMORY;
1808 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1809 &trustAuthIncoming, NULL);
1810 if (ret != LDB_SUCCESS) {
1811 return NT_STATUS_NO_MEMORY;
1814 if (add_outgoing && trustAuthOutgoing.data) {
1815 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1816 LDB_FLAG_MOD_REPLACE, NULL);
1817 if (ret != LDB_SUCCESS) {
1818 return NT_STATUS_NO_MEMORY;
1820 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1821 &trustAuthOutgoing, NULL);
1822 if (ret != LDB_SUCCESS) {
1823 return NT_STATUS_NO_MEMORY;
1827 /* start transaction */
1828 ret = ldb_transaction_start(p_state->sam_ldb);
1829 if (ret != LDB_SUCCESS) {
1830 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1832 in_transaction = true;
1834 ret = ldb_modify(p_state->sam_ldb, msg);
1835 if (ret != LDB_SUCCESS) {
1836 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1837 ldb_dn_get_linearized(msg->dn),
1838 ldb_errstring(p_state->sam_ldb)));
1839 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
1840 nt_status = NT_STATUS_ACCESS_DENIED;
1841 } else {
1842 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1844 goto done;
1847 if (add_incoming || del_incoming) {
1848 const char *netbios_name;
1850 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1851 "flatname", NULL);
1852 if (!netbios_name) {
1853 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1854 goto done;
1857 nt_status = update_trust_user(mem_ctx,
1858 p_state->sam_ldb,
1859 p_state->domain_dn,
1860 del_incoming,
1861 netbios_name,
1862 &auth_struct.incoming);
1863 if (!NT_STATUS_IS_OK(nt_status)) {
1864 goto done;
1868 /* ok, all fine, commit transaction and return */
1869 ret = ldb_transaction_commit(p_state->sam_ldb);
1870 if (ret != LDB_SUCCESS) {
1871 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1873 in_transaction = false;
1875 nt_status = NT_STATUS_OK;
1877 done:
1878 if (in_transaction) {
1879 ldb_transaction_cancel(p_state->sam_ldb);
1881 return nt_status;
1885 lsa_SetInfomrationTrustedDomain
1887 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1888 struct dcesrv_call_state *dce_call,
1889 TALLOC_CTX *mem_ctx,
1890 struct lsa_SetInformationTrustedDomain *r)
1892 struct dcesrv_handle *h;
1893 struct lsa_trusted_domain_state *td_state;
1894 struct ldb_message **msgs;
1895 NTSTATUS nt_status;
1897 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1898 LSA_HANDLE_TRUSTED_DOMAIN);
1900 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1902 /* get the trusted domain object */
1903 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1904 td_state->trusted_domain_dn,
1905 NULL, NULL, NULL, &msgs);
1906 if (!NT_STATUS_IS_OK(nt_status)) {
1907 if (NT_STATUS_EQUAL(nt_status,
1908 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1909 return nt_status;
1911 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1914 return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1915 msgs[0], r->in.level, r->in.info);
1920 lsa_DeleteTrustedDomain
1922 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1923 struct lsa_DeleteTrustedDomain *r)
1925 NTSTATUS status;
1926 struct lsa_OpenTrustedDomain opn;
1927 struct lsa_DeleteObject del;
1928 struct dcesrv_handle *h;
1930 opn.in.handle = r->in.handle;
1931 opn.in.sid = r->in.dom_sid;
1932 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1933 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1934 if (!opn.out.trustdom_handle) {
1935 return NT_STATUS_NO_MEMORY;
1937 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1938 if (!NT_STATUS_IS_OK(status)) {
1939 return status;
1942 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1943 talloc_steal(mem_ctx, h);
1945 del.in.handle = opn.out.trustdom_handle;
1946 del.out.handle = opn.out.trustdom_handle;
1947 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1948 if (!NT_STATUS_IS_OK(status)) {
1949 return status;
1951 return NT_STATUS_OK;
1954 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
1955 struct ldb_message *msg,
1956 struct lsa_TrustDomainInfoInfoEx *info_ex)
1958 info_ex->domain_name.string
1959 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1960 info_ex->netbios_name.string
1961 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1962 info_ex->sid
1963 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1964 info_ex->trust_direction
1965 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1966 info_ex->trust_type
1967 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1968 info_ex->trust_attributes
1969 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
1970 return NT_STATUS_OK;
1974 lsa_QueryTrustedDomainInfo
1976 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1977 struct lsa_QueryTrustedDomainInfo *r)
1979 union lsa_TrustedDomainInfo *info = NULL;
1980 struct dcesrv_handle *h;
1981 struct lsa_trusted_domain_state *trusted_domain_state;
1982 struct ldb_message *msg;
1983 int ret;
1984 struct ldb_message **res;
1985 const char *attrs[] = {
1986 "flatname",
1987 "trustPartner",
1988 "securityIdentifier",
1989 "trustDirection",
1990 "trustType",
1991 "trustAttributes",
1992 "msDs-supportedEncryptionTypes",
1993 NULL
1996 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
1998 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2000 /* pull all the user attributes */
2001 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2002 trusted_domain_state->trusted_domain_dn, &res, attrs);
2003 if (ret != 1) {
2004 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2006 msg = res[0];
2008 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2009 if (!info) {
2010 return NT_STATUS_NO_MEMORY;
2012 *r->out.info = info;
2014 switch (r->in.level) {
2015 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2016 info->name.netbios_name.string
2017 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2018 break;
2019 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2020 info->posix_offset.posix_offset
2021 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2022 break;
2023 #if 0 /* Win2k3 doesn't implement this */
2024 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2025 r->out.info->info_basic.netbios_name.string
2026 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2027 r->out.info->info_basic.sid
2028 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2029 break;
2030 #endif
2031 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2032 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2034 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2035 ZERO_STRUCT(info->full_info);
2036 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2037 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2038 ZERO_STRUCT(info->full_info2_internal);
2039 info->full_info2_internal.posix_offset.posix_offset
2040 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2041 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2043 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2044 info->enc_types.enc_types
2045 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2046 break;
2048 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2049 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2050 /* oops, we don't want to return the info after all */
2051 talloc_free(info);
2052 *r->out.info = NULL;
2053 return NT_STATUS_INVALID_PARAMETER;
2054 default:
2055 /* oops, we don't want to return the info after all */
2056 talloc_free(info);
2057 *r->out.info = NULL;
2058 return NT_STATUS_INVALID_INFO_CLASS;
2061 return NT_STATUS_OK;
2066 lsa_QueryTrustedDomainInfoBySid
2068 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2069 struct lsa_QueryTrustedDomainInfoBySid *r)
2071 NTSTATUS status;
2072 struct lsa_OpenTrustedDomain opn;
2073 struct lsa_QueryTrustedDomainInfo query;
2074 struct dcesrv_handle *h;
2076 opn.in.handle = r->in.handle;
2077 opn.in.sid = r->in.dom_sid;
2078 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2079 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2080 if (!opn.out.trustdom_handle) {
2081 return NT_STATUS_NO_MEMORY;
2083 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2084 if (!NT_STATUS_IS_OK(status)) {
2085 return status;
2088 /* Ensure this handle goes away at the end of this call */
2089 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2090 talloc_steal(mem_ctx, h);
2092 query.in.trustdom_handle = opn.out.trustdom_handle;
2093 query.in.level = r->in.level;
2094 query.out.info = r->out.info;
2095 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2096 if (!NT_STATUS_IS_OK(status)) {
2097 return status;
2100 return NT_STATUS_OK;
2104 lsa_SetTrustedDomainInfoByName
2106 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2107 TALLOC_CTX *mem_ctx,
2108 struct lsa_SetTrustedDomainInfoByName *r)
2110 struct dcesrv_handle *policy_handle;
2111 struct lsa_policy_state *policy_state;
2112 struct ldb_message **msgs;
2113 NTSTATUS nt_status;
2115 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2116 policy_state = policy_handle->data;
2118 /* get the trusted domain object */
2119 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2120 policy_state->domain_dn,
2121 r->in.trusted_domain->string,
2122 r->in.trusted_domain->string,
2123 NULL, &msgs);
2124 if (!NT_STATUS_IS_OK(nt_status)) {
2125 if (NT_STATUS_EQUAL(nt_status,
2126 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2127 return nt_status;
2129 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2132 return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2133 msgs[0], r->in.level, r->in.info);
2137 lsa_QueryTrustedDomainInfoByName
2139 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2140 TALLOC_CTX *mem_ctx,
2141 struct lsa_QueryTrustedDomainInfoByName *r)
2143 NTSTATUS status;
2144 struct lsa_OpenTrustedDomainByName opn;
2145 struct lsa_QueryTrustedDomainInfo query;
2146 struct dcesrv_handle *h;
2148 opn.in.handle = r->in.handle;
2149 opn.in.name = *r->in.trusted_domain;
2150 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2151 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2152 if (!opn.out.trustdom_handle) {
2153 return NT_STATUS_NO_MEMORY;
2155 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2156 if (!NT_STATUS_IS_OK(status)) {
2157 return status;
2160 /* Ensure this handle goes away at the end of this call */
2161 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2162 talloc_steal(mem_ctx, h);
2164 query.in.trustdom_handle = opn.out.trustdom_handle;
2165 query.in.level = r->in.level;
2166 query.out.info = r->out.info;
2167 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2168 if (!NT_STATUS_IS_OK(status)) {
2169 return status;
2172 return NT_STATUS_OK;
2176 lsa_CloseTrustedDomainEx
2178 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2179 TALLOC_CTX *mem_ctx,
2180 struct lsa_CloseTrustedDomainEx *r)
2182 /* The result of a bad hair day from an IDL programmer? Not
2183 * implmented in Win2k3. You should always just lsa_Close
2184 * anyway. */
2185 return NT_STATUS_NOT_IMPLEMENTED;
2190 comparison function for sorting lsa_DomainInformation array
2192 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2194 return strcasecmp_m(e1->name.string, e2->name.string);
2198 lsa_EnumTrustDom
2200 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2201 struct lsa_EnumTrustDom *r)
2203 struct dcesrv_handle *policy_handle;
2204 struct lsa_DomainInfo *entries;
2205 struct lsa_policy_state *policy_state;
2206 struct ldb_message **domains;
2207 const char *attrs[] = {
2208 "flatname",
2209 "securityIdentifier",
2210 NULL
2214 int count, i;
2216 *r->out.resume_handle = 0;
2218 r->out.domains->domains = NULL;
2219 r->out.domains->count = 0;
2221 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2223 policy_state = policy_handle->data;
2225 /* search for all users in this domain. This could possibly be cached and
2226 resumed based on resume_key */
2227 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2228 "objectclass=trustedDomain");
2229 if (count < 0) {
2230 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2233 /* convert to lsa_TrustInformation format */
2234 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2235 if (!entries) {
2236 return NT_STATUS_NO_MEMORY;
2238 for (i=0;i<count;i++) {
2239 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2240 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2243 /* sort the results by name */
2244 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2246 if (*r->in.resume_handle >= count) {
2247 *r->out.resume_handle = -1;
2249 return NT_STATUS_NO_MORE_ENTRIES;
2252 /* return the rest, limit by max_size. Note that we
2253 use the w2k3 element size value of 60 */
2254 r->out.domains->count = count - *r->in.resume_handle;
2255 r->out.domains->count = MIN(r->out.domains->count,
2256 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2258 r->out.domains->domains = entries + *r->in.resume_handle;
2259 r->out.domains->count = r->out.domains->count;
2261 if (r->out.domains->count < count - *r->in.resume_handle) {
2262 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2263 return STATUS_MORE_ENTRIES;
2266 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2267 * always be larger than the previous input resume handle, in
2268 * particular when hitting the last query it is vital to set the
2269 * resume handle correctly to avoid infinite client loops, as
2270 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2271 * status is NT_STATUS_OK - gd */
2273 *r->out.resume_handle = (uint32_t)-1;
2275 return NT_STATUS_OK;
2279 comparison function for sorting lsa_DomainInformation array
2281 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2283 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2287 lsa_EnumTrustedDomainsEx
2289 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2290 struct lsa_EnumTrustedDomainsEx *r)
2292 struct dcesrv_handle *policy_handle;
2293 struct lsa_TrustDomainInfoInfoEx *entries;
2294 struct lsa_policy_state *policy_state;
2295 struct ldb_message **domains;
2296 const char *attrs[] = {
2297 "flatname",
2298 "trustPartner",
2299 "securityIdentifier",
2300 "trustDirection",
2301 "trustType",
2302 "trustAttributes",
2303 NULL
2305 NTSTATUS nt_status;
2307 int count, i;
2309 *r->out.resume_handle = 0;
2311 r->out.domains->domains = NULL;
2312 r->out.domains->count = 0;
2314 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2316 policy_state = policy_handle->data;
2318 /* search for all users in this domain. This could possibly be cached and
2319 resumed based on resume_key */
2320 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2321 "objectclass=trustedDomain");
2322 if (count < 0) {
2323 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2326 /* convert to lsa_DomainInformation format */
2327 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2328 if (!entries) {
2329 return NT_STATUS_NO_MEMORY;
2331 for (i=0;i<count;i++) {
2332 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2333 if (!NT_STATUS_IS_OK(nt_status)) {
2334 return nt_status;
2338 /* sort the results by name */
2339 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2341 if (*r->in.resume_handle >= count) {
2342 *r->out.resume_handle = -1;
2344 return NT_STATUS_NO_MORE_ENTRIES;
2347 /* return the rest, limit by max_size. Note that we
2348 use the w2k3 element size value of 60 */
2349 r->out.domains->count = count - *r->in.resume_handle;
2350 r->out.domains->count = MIN(r->out.domains->count,
2351 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2353 r->out.domains->domains = entries + *r->in.resume_handle;
2354 r->out.domains->count = r->out.domains->count;
2356 if (r->out.domains->count < count - *r->in.resume_handle) {
2357 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2358 return STATUS_MORE_ENTRIES;
2361 return NT_STATUS_OK;
2366 lsa_OpenAccount
2368 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2369 struct lsa_OpenAccount *r)
2371 struct dcesrv_handle *h, *ah;
2372 struct lsa_policy_state *state;
2373 struct lsa_account_state *astate;
2375 ZERO_STRUCTP(r->out.acct_handle);
2377 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2379 state = h->data;
2381 astate = talloc(dce_call->conn, struct lsa_account_state);
2382 if (astate == NULL) {
2383 return NT_STATUS_NO_MEMORY;
2386 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2387 if (astate->account_sid == NULL) {
2388 talloc_free(astate);
2389 return NT_STATUS_NO_MEMORY;
2392 astate->policy = talloc_reference(astate, state);
2393 astate->access_mask = r->in.access_mask;
2395 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2396 if (!ah) {
2397 talloc_free(astate);
2398 return NT_STATUS_NO_MEMORY;
2401 ah->data = talloc_steal(ah, astate);
2403 *r->out.acct_handle = ah->wire_handle;
2405 return NT_STATUS_OK;
2410 lsa_EnumPrivsAccount
2412 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2413 TALLOC_CTX *mem_ctx,
2414 struct lsa_EnumPrivsAccount *r)
2416 struct dcesrv_handle *h;
2417 struct lsa_account_state *astate;
2418 int ret;
2419 unsigned int i, j;
2420 struct ldb_message **res;
2421 const char * const attrs[] = { "privilege", NULL};
2422 struct ldb_message_element *el;
2423 const char *sidstr;
2424 struct lsa_PrivilegeSet *privs;
2426 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2428 astate = h->data;
2430 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2431 if (privs == NULL) {
2432 return NT_STATUS_NO_MEMORY;
2434 privs->count = 0;
2435 privs->unknown = 0;
2436 privs->set = NULL;
2438 *r->out.privs = privs;
2440 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2441 if (sidstr == NULL) {
2442 return NT_STATUS_NO_MEMORY;
2445 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2446 "objectSid=%s", sidstr);
2447 if (ret < 0) {
2448 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2450 if (ret != 1) {
2451 return NT_STATUS_OK;
2454 el = ldb_msg_find_element(res[0], "privilege");
2455 if (el == NULL || el->num_values == 0) {
2456 return NT_STATUS_OK;
2459 privs->set = talloc_array(privs,
2460 struct lsa_LUIDAttribute, el->num_values);
2461 if (privs->set == NULL) {
2462 return NT_STATUS_NO_MEMORY;
2465 j = 0;
2466 for (i=0;i<el->num_values;i++) {
2467 int id = sec_privilege_id((const char *)el->values[i].data);
2468 if (id == SEC_PRIV_INVALID) {
2469 /* Perhaps an account right, not a privilege */
2470 continue;
2472 privs->set[j].attribute = 0;
2473 privs->set[j].luid.low = id;
2474 privs->set[j].luid.high = 0;
2475 j++;
2478 privs->count = j;
2480 return NT_STATUS_OK;
2484 lsa_EnumAccountRights
2486 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2487 TALLOC_CTX *mem_ctx,
2488 struct lsa_EnumAccountRights *r)
2490 struct dcesrv_handle *h;
2491 struct lsa_policy_state *state;
2492 int ret;
2493 unsigned int i;
2494 struct ldb_message **res;
2495 const char * const attrs[] = { "privilege", NULL};
2496 const char *sidstr;
2497 struct ldb_message_element *el;
2499 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2501 state = h->data;
2503 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2504 if (sidstr == NULL) {
2505 return NT_STATUS_NO_MEMORY;
2508 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2509 "(&(objectSid=%s)(privilege=*))", sidstr);
2510 if (ret == 0) {
2511 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2513 if (ret != 1) {
2514 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2515 dom_sid_string(mem_ctx, r->in.sid),
2516 ldb_errstring(state->pdb)));
2517 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2520 el = ldb_msg_find_element(res[0], "privilege");
2521 if (el == NULL || el->num_values == 0) {
2522 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2525 r->out.rights->count = el->num_values;
2526 r->out.rights->names = talloc_array(r->out.rights,
2527 struct lsa_StringLarge, r->out.rights->count);
2528 if (r->out.rights->names == NULL) {
2529 return NT_STATUS_NO_MEMORY;
2532 for (i=0;i<el->num_values;i++) {
2533 r->out.rights->names[i].string = (const char *)el->values[i].data;
2536 return NT_STATUS_OK;
2542 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2544 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2545 TALLOC_CTX *mem_ctx,
2546 struct lsa_policy_state *state,
2547 int ldb_flag,
2548 struct dom_sid *sid,
2549 const struct lsa_RightSet *rights)
2551 const char *sidstr, *sidndrstr;
2552 struct ldb_message *msg;
2553 struct ldb_message_element *el;
2554 int ret;
2555 uint32_t i;
2556 struct lsa_EnumAccountRights r2;
2557 char *dnstr;
2559 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2560 SECURITY_ADMINISTRATOR) {
2561 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2562 return NT_STATUS_ACCESS_DENIED;
2565 msg = ldb_msg_new(mem_ctx);
2566 if (msg == NULL) {
2567 return NT_STATUS_NO_MEMORY;
2570 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2571 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
2573 sidstr = dom_sid_string(msg, sid);
2574 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
2576 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2577 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
2579 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2580 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
2582 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2583 NTSTATUS status;
2585 r2.in.handle = &state->handle->wire_handle;
2586 r2.in.sid = sid;
2587 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2589 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2590 if (!NT_STATUS_IS_OK(status)) {
2591 ZERO_STRUCTP(r2.out.rights);
2595 for (i=0;i<rights->count;i++) {
2596 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2597 if (sec_right_bit(rights->names[i].string) == 0) {
2598 talloc_free(msg);
2599 return NT_STATUS_NO_SUCH_PRIVILEGE;
2602 talloc_free(msg);
2603 return NT_STATUS_NO_SUCH_PRIVILEGE;
2606 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2607 uint32_t j;
2608 for (j=0;j<r2.out.rights->count;j++) {
2609 if (strcasecmp_m(r2.out.rights->names[j].string,
2610 rights->names[i].string) == 0) {
2611 break;
2614 if (j != r2.out.rights->count) continue;
2617 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2618 if (ret != LDB_SUCCESS) {
2619 talloc_free(msg);
2620 return NT_STATUS_NO_MEMORY;
2624 el = ldb_msg_find_element(msg, "privilege");
2625 if (!el) {
2626 talloc_free(msg);
2627 return NT_STATUS_OK;
2630 el->flags = ldb_flag;
2632 ret = ldb_modify(state->pdb, msg);
2633 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2634 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2635 talloc_free(msg);
2636 return NT_STATUS_NO_MEMORY;
2638 ldb_msg_add_string(msg, "comment", "added via LSA");
2639 ret = ldb_add(state->pdb, msg);
2641 if (ret != LDB_SUCCESS) {
2642 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2643 talloc_free(msg);
2644 return NT_STATUS_OK;
2646 DEBUG(3, ("Could not %s attributes from %s: %s",
2647 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2648 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2649 talloc_free(msg);
2650 return NT_STATUS_UNEXPECTED_IO_ERROR;
2653 talloc_free(msg);
2654 return NT_STATUS_OK;
2658 lsa_AddPrivilegesToAccount
2660 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2661 struct lsa_AddPrivilegesToAccount *r)
2663 struct lsa_RightSet rights;
2664 struct dcesrv_handle *h;
2665 struct lsa_account_state *astate;
2666 uint32_t i;
2668 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2670 astate = h->data;
2672 rights.count = r->in.privs->count;
2673 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2674 if (rights.names == NULL) {
2675 return NT_STATUS_NO_MEMORY;
2677 for (i=0;i<rights.count;i++) {
2678 int id = r->in.privs->set[i].luid.low;
2679 if (r->in.privs->set[i].luid.high) {
2680 return NT_STATUS_NO_SUCH_PRIVILEGE;
2682 rights.names[i].string = sec_privilege_name(id);
2683 if (rights.names[i].string == NULL) {
2684 return NT_STATUS_NO_SUCH_PRIVILEGE;
2688 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2689 LDB_FLAG_MOD_ADD, astate->account_sid,
2690 &rights);
2695 lsa_RemovePrivilegesFromAccount
2697 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2698 struct lsa_RemovePrivilegesFromAccount *r)
2700 struct lsa_RightSet *rights;
2701 struct dcesrv_handle *h;
2702 struct lsa_account_state *astate;
2703 uint32_t i;
2705 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2707 astate = h->data;
2709 rights = talloc(mem_ctx, struct lsa_RightSet);
2711 if (r->in.remove_all == 1 &&
2712 r->in.privs == NULL) {
2713 struct lsa_EnumAccountRights r2;
2714 NTSTATUS status;
2716 r2.in.handle = &astate->policy->handle->wire_handle;
2717 r2.in.sid = astate->account_sid;
2718 r2.out.rights = rights;
2720 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2721 if (!NT_STATUS_IS_OK(status)) {
2722 return status;
2725 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2726 LDB_FLAG_MOD_DELETE, astate->account_sid,
2727 r2.out.rights);
2730 if (r->in.remove_all != 0) {
2731 return NT_STATUS_INVALID_PARAMETER;
2734 rights->count = r->in.privs->count;
2735 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2736 if (rights->names == NULL) {
2737 return NT_STATUS_NO_MEMORY;
2739 for (i=0;i<rights->count;i++) {
2740 int id = r->in.privs->set[i].luid.low;
2741 if (r->in.privs->set[i].luid.high) {
2742 return NT_STATUS_NO_SUCH_PRIVILEGE;
2744 rights->names[i].string = sec_privilege_name(id);
2745 if (rights->names[i].string == NULL) {
2746 return NT_STATUS_NO_SUCH_PRIVILEGE;
2750 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2751 LDB_FLAG_MOD_DELETE, astate->account_sid,
2752 rights);
2757 lsa_GetQuotasForAccount
2759 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2760 struct lsa_GetQuotasForAccount *r)
2762 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2767 lsa_SetQuotasForAccount
2769 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2770 struct lsa_SetQuotasForAccount *r)
2772 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2777 lsa_GetSystemAccessAccount
2779 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2780 struct lsa_GetSystemAccessAccount *r)
2782 struct dcesrv_handle *h;
2783 struct lsa_account_state *astate;
2784 int ret;
2785 unsigned int i;
2786 struct ldb_message **res;
2787 const char * const attrs[] = { "privilege", NULL};
2788 struct ldb_message_element *el;
2789 const char *sidstr;
2791 *(r->out.access_mask) = 0x00000000;
2793 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2795 astate = h->data;
2797 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2798 if (sidstr == NULL) {
2799 return NT_STATUS_NO_MEMORY;
2802 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2803 "objectSid=%s", sidstr);
2804 if (ret < 0) {
2805 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2807 if (ret != 1) {
2808 return NT_STATUS_OK;
2811 el = ldb_msg_find_element(res[0], "privilege");
2812 if (el == NULL || el->num_values == 0) {
2813 return NT_STATUS_OK;
2816 for (i=0;i<el->num_values;i++) {
2817 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2818 if (right_bit == 0) {
2819 /* Perhaps an privilege, not a right */
2820 continue;
2822 *(r->out.access_mask) |= right_bit;
2825 return NT_STATUS_OK;
2830 lsa_SetSystemAccessAccount
2832 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2833 struct lsa_SetSystemAccessAccount *r)
2835 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2840 lsa_CreateSecret
2842 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2843 struct lsa_CreateSecret *r)
2845 struct dcesrv_handle *policy_handle;
2846 struct lsa_policy_state *policy_state;
2847 struct lsa_secret_state *secret_state;
2848 struct dcesrv_handle *handle;
2849 struct ldb_message **msgs, *msg;
2850 const char *attrs[] = {
2851 NULL
2854 const char *name;
2856 int ret;
2858 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2859 ZERO_STRUCTP(r->out.sec_handle);
2861 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2863 case SECURITY_SYSTEM:
2864 case SECURITY_ADMINISTRATOR:
2865 break;
2866 default:
2867 /* Users and annonymous are not allowed create secrets */
2868 return NT_STATUS_ACCESS_DENIED;
2871 policy_state = policy_handle->data;
2873 if (!r->in.name.string) {
2874 return NT_STATUS_INVALID_PARAMETER;
2877 secret_state = talloc(mem_ctx, struct lsa_secret_state);
2878 NT_STATUS_HAVE_NO_MEMORY(secret_state);
2879 secret_state->policy = policy_state;
2881 msg = ldb_msg_new(mem_ctx);
2882 if (msg == NULL) {
2883 return NT_STATUS_NO_MEMORY;
2886 if (strncmp("G$", r->in.name.string, 2) == 0) {
2887 const char *name2;
2889 secret_state->global = true;
2891 name = &r->in.name.string[2];
2892 if (strlen(name) == 0) {
2893 return NT_STATUS_INVALID_PARAMETER;
2896 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2897 ldb_binary_encode_string(mem_ctx, name));
2898 NT_STATUS_HAVE_NO_MEMORY(name2);
2900 /* We need to connect to the database as system, as this is one
2901 * of the rare RPC calls that must read the secrets (and this
2902 * is denied otherwise) */
2903 secret_state->sam_ldb = talloc_reference(secret_state,
2904 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));
2905 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2907 /* search for the secret record */
2908 ret = gendb_search(secret_state->sam_ldb,
2909 mem_ctx, policy_state->system_dn, &msgs, attrs,
2910 "(&(cn=%s)(objectclass=secret))",
2911 name2);
2912 if (ret > 0) {
2913 return NT_STATUS_OBJECT_NAME_COLLISION;
2916 if (ret < 0) {
2917 DEBUG(0,("Failure searching for CN=%s: %s\n",
2918 name2, ldb_errstring(secret_state->sam_ldb)));
2919 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2922 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2923 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2924 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2925 return NT_STATUS_NO_MEMORY;
2928 ret = ldb_msg_add_string(msg, "cn", name2);
2929 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2930 } else {
2931 secret_state->global = false;
2933 name = r->in.name.string;
2934 if (strlen(name) == 0) {
2935 return NT_STATUS_INVALID_PARAMETER;
2938 secret_state->sam_ldb = talloc_reference(secret_state,
2939 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
2940 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2942 /* search for the secret record */
2943 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2944 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2945 &msgs, attrs,
2946 "(&(cn=%s)(objectclass=secret))",
2947 ldb_binary_encode_string(mem_ctx, name));
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 name, ldb_errstring(secret_state->sam_ldb)));
2955 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2958 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
2959 "cn=%s,cn=LSA Secrets", name);
2960 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2961 ret = ldb_msg_add_string(msg, "cn", name);
2962 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2965 ret = ldb_msg_add_string(msg, "objectClass", "secret");
2966 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2968 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2969 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
2971 /* create the secret */
2972 ret = ldb_add(secret_state->sam_ldb, msg);
2973 if (ret != LDB_SUCCESS) {
2974 DEBUG(0,("Failed to create secret record %s: %s\n",
2975 ldb_dn_get_linearized(msg->dn),
2976 ldb_errstring(secret_state->sam_ldb)));
2977 return NT_STATUS_ACCESS_DENIED;
2980 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2981 NT_STATUS_HAVE_NO_MEMORY(handle);
2983 handle->data = talloc_steal(handle, secret_state);
2985 secret_state->access_mask = r->in.access_mask;
2986 secret_state->policy = talloc_reference(secret_state, policy_state);
2987 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
2989 *r->out.sec_handle = handle->wire_handle;
2991 return NT_STATUS_OK;
2996 lsa_OpenSecret
2998 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2999 struct lsa_OpenSecret *r)
3001 struct dcesrv_handle *policy_handle;
3003 struct lsa_policy_state *policy_state;
3004 struct lsa_secret_state *secret_state;
3005 struct dcesrv_handle *handle;
3006 struct ldb_message **msgs;
3007 const char *attrs[] = {
3008 NULL
3011 const char *name;
3013 int ret;
3015 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3016 ZERO_STRUCTP(r->out.sec_handle);
3017 policy_state = policy_handle->data;
3019 if (!r->in.name.string) {
3020 return NT_STATUS_INVALID_PARAMETER;
3023 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3025 case SECURITY_SYSTEM:
3026 case SECURITY_ADMINISTRATOR:
3027 break;
3028 default:
3029 /* Users and annonymous are not allowed to access secrets */
3030 return NT_STATUS_ACCESS_DENIED;
3033 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3034 if (!secret_state) {
3035 return NT_STATUS_NO_MEMORY;
3037 secret_state->policy = policy_state;
3039 if (strncmp("G$", r->in.name.string, 2) == 0) {
3040 name = &r->in.name.string[2];
3041 /* 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) */
3042 secret_state->sam_ldb = talloc_reference(secret_state,
3043 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));
3044 secret_state->global = true;
3046 if (strlen(name) < 1) {
3047 return NT_STATUS_INVALID_PARAMETER;
3050 /* search for the secret record */
3051 ret = gendb_search(secret_state->sam_ldb,
3052 mem_ctx, policy_state->system_dn, &msgs, attrs,
3053 "(&(cn=%s Secret)(objectclass=secret))",
3054 ldb_binary_encode_string(mem_ctx, name));
3055 if (ret == 0) {
3056 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3059 if (ret != 1) {
3060 DEBUG(0,("Found %d records matching DN %s\n", ret,
3061 ldb_dn_get_linearized(policy_state->system_dn)));
3062 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3065 } else {
3066 secret_state->global = false;
3067 secret_state->sam_ldb = talloc_reference(secret_state,
3068 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3070 name = r->in.name.string;
3071 if (strlen(name) < 1) {
3072 return NT_STATUS_INVALID_PARAMETER;
3075 /* search for the secret record */
3076 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3077 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3078 &msgs, attrs,
3079 "(&(cn=%s)(objectclass=secret))",
3080 ldb_binary_encode_string(mem_ctx, name));
3081 if (ret == 0) {
3082 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3085 if (ret != 1) {
3086 DEBUG(0,("Found %d records matching CN=%s\n",
3087 ret, ldb_binary_encode_string(mem_ctx, name)));
3088 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3092 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3094 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3095 if (!handle) {
3096 return NT_STATUS_NO_MEMORY;
3099 handle->data = talloc_steal(handle, secret_state);
3101 secret_state->access_mask = r->in.access_mask;
3102 secret_state->policy = talloc_reference(secret_state, policy_state);
3104 *r->out.sec_handle = handle->wire_handle;
3106 return NT_STATUS_OK;
3111 lsa_SetSecret
3113 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3114 struct lsa_SetSecret *r)
3117 struct dcesrv_handle *h;
3118 struct lsa_secret_state *secret_state;
3119 struct ldb_message *msg;
3120 DATA_BLOB session_key;
3121 DATA_BLOB crypt_secret, secret;
3122 struct ldb_val val;
3123 int ret;
3124 NTSTATUS status = NT_STATUS_OK;
3126 struct timeval now = timeval_current();
3127 NTTIME nt_now = timeval_to_nttime(&now);
3129 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3131 secret_state = h->data;
3133 msg = ldb_msg_new(mem_ctx);
3134 if (msg == NULL) {
3135 return NT_STATUS_NO_MEMORY;
3138 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3139 if (!msg->dn) {
3140 return NT_STATUS_NO_MEMORY;
3142 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3143 if (!NT_STATUS_IS_OK(status)) {
3144 return status;
3147 if (r->in.old_val) {
3148 /* Decrypt */
3149 crypt_secret.data = r->in.old_val->data;
3150 crypt_secret.length = r->in.old_val->size;
3152 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3153 if (!NT_STATUS_IS_OK(status)) {
3154 return status;
3157 val.data = secret.data;
3158 val.length = secret.length;
3160 /* set value */
3161 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3162 return NT_STATUS_NO_MEMORY;
3165 /* set old value mtime */
3166 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3167 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3168 return NT_STATUS_NO_MEMORY;
3171 } else {
3172 /* If the old value is not set, then migrate the
3173 * current value to the old value */
3174 const struct ldb_val *old_val;
3175 NTTIME last_set_time;
3176 struct ldb_message **res;
3177 const char *attrs[] = {
3178 "currentValue",
3179 "lastSetTime",
3180 NULL
3183 /* search for the secret record */
3184 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3185 secret_state->secret_dn, &res, attrs);
3186 if (ret == 0) {
3187 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3190 if (ret != 1) {
3191 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3192 ldb_dn_get_linearized(secret_state->secret_dn)));
3193 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3196 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3197 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3199 if (old_val) {
3200 /* set old value */
3201 if (ldb_msg_add_value(msg, "priorValue",
3202 old_val, NULL) != LDB_SUCCESS) {
3203 return NT_STATUS_NO_MEMORY;
3205 } else {
3206 if (samdb_msg_add_delete(secret_state->sam_ldb,
3207 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3208 return NT_STATUS_NO_MEMORY;
3213 /* set old value mtime */
3214 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3215 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3216 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3217 return NT_STATUS_NO_MEMORY;
3219 } else {
3220 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3221 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3222 return NT_STATUS_NO_MEMORY;
3227 if (r->in.new_val) {
3228 /* Decrypt */
3229 crypt_secret.data = r->in.new_val->data;
3230 crypt_secret.length = r->in.new_val->size;
3232 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3233 if (!NT_STATUS_IS_OK(status)) {
3234 return status;
3237 val.data = secret.data;
3238 val.length = secret.length;
3240 /* set value */
3241 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3242 return NT_STATUS_NO_MEMORY;
3245 /* set new value mtime */
3246 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3247 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3248 return NT_STATUS_NO_MEMORY;
3251 } else {
3252 /* NULL out the NEW value */
3253 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3254 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3255 return NT_STATUS_NO_MEMORY;
3257 if (samdb_msg_add_delete(secret_state->sam_ldb,
3258 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3259 return NT_STATUS_NO_MEMORY;
3263 /* modify the samdb record */
3264 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3265 if (ret != LDB_SUCCESS) {
3266 return dsdb_ldb_err_to_ntstatus(ret);
3269 return NT_STATUS_OK;
3274 lsa_QuerySecret
3276 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3277 struct lsa_QuerySecret *r)
3279 struct dcesrv_handle *h;
3280 struct lsa_secret_state *secret_state;
3281 struct ldb_message *msg;
3282 DATA_BLOB session_key;
3283 DATA_BLOB crypt_secret, secret;
3284 int ret;
3285 struct ldb_message **res;
3286 const char *attrs[] = {
3287 "currentValue",
3288 "priorValue",
3289 "lastSetTime",
3290 "priorSetTime",
3291 NULL
3294 NTSTATUS nt_status;
3296 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3298 /* Ensure user is permitted to read this... */
3299 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3301 case SECURITY_SYSTEM:
3302 case SECURITY_ADMINISTRATOR:
3303 break;
3304 default:
3305 /* Users and annonymous are not allowed to read secrets */
3306 return NT_STATUS_ACCESS_DENIED;
3309 secret_state = h->data;
3311 /* pull all the user attributes */
3312 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3313 secret_state->secret_dn, &res, attrs);
3314 if (ret != 1) {
3315 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3317 msg = res[0];
3319 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3320 if (!NT_STATUS_IS_OK(nt_status)) {
3321 return nt_status;
3324 if (r->in.old_val) {
3325 const struct ldb_val *prior_val;
3326 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3327 if (!r->out.old_val) {
3328 return NT_STATUS_NO_MEMORY;
3330 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
3332 if (prior_val && prior_val->length) {
3333 secret.data = prior_val->data;
3334 secret.length = prior_val->length;
3336 /* Encrypt */
3337 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3338 if (!crypt_secret.length) {
3339 return NT_STATUS_NO_MEMORY;
3341 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3342 if (!r->out.old_val->buf) {
3343 return NT_STATUS_NO_MEMORY;
3345 r->out.old_val->buf->size = crypt_secret.length;
3346 r->out.old_val->buf->length = crypt_secret.length;
3347 r->out.old_val->buf->data = crypt_secret.data;
3351 if (r->in.old_mtime) {
3352 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3353 if (!r->out.old_mtime) {
3354 return NT_STATUS_NO_MEMORY;
3356 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
3359 if (r->in.new_val) {
3360 const struct ldb_val *new_val;
3361 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3362 if (!r->out.new_val) {
3363 return NT_STATUS_NO_MEMORY;
3366 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3368 if (new_val && new_val->length) {
3369 secret.data = new_val->data;
3370 secret.length = new_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.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3378 if (!r->out.new_val->buf) {
3379 return NT_STATUS_NO_MEMORY;
3381 r->out.new_val->buf->length = crypt_secret.length;
3382 r->out.new_val->buf->size = crypt_secret.length;
3383 r->out.new_val->buf->data = crypt_secret.data;
3387 if (r->in.new_mtime) {
3388 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3389 if (!r->out.new_mtime) {
3390 return NT_STATUS_NO_MEMORY;
3392 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3395 return NT_STATUS_OK;
3400 lsa_LookupPrivValue
3402 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3403 TALLOC_CTX *mem_ctx,
3404 struct lsa_LookupPrivValue *r)
3406 struct dcesrv_handle *h;
3407 struct lsa_policy_state *state;
3408 int id;
3410 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3412 state = h->data;
3414 id = sec_privilege_id(r->in.name->string);
3415 if (id == SEC_PRIV_INVALID) {
3416 return NT_STATUS_NO_SUCH_PRIVILEGE;
3419 r->out.luid->low = id;
3420 r->out.luid->high = 0;
3422 return NT_STATUS_OK;
3427 lsa_LookupPrivName
3429 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3430 TALLOC_CTX *mem_ctx,
3431 struct lsa_LookupPrivName *r)
3433 struct dcesrv_handle *h;
3434 struct lsa_policy_state *state;
3435 struct lsa_StringLarge *name;
3436 const char *privname;
3438 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3440 state = h->data;
3442 if (r->in.luid->high != 0) {
3443 return NT_STATUS_NO_SUCH_PRIVILEGE;
3446 privname = sec_privilege_name(r->in.luid->low);
3447 if (privname == NULL) {
3448 return NT_STATUS_NO_SUCH_PRIVILEGE;
3451 name = talloc(mem_ctx, struct lsa_StringLarge);
3452 if (name == NULL) {
3453 return NT_STATUS_NO_MEMORY;
3456 name->string = privname;
3458 *r->out.name = name;
3460 return NT_STATUS_OK;
3465 lsa_LookupPrivDisplayName
3467 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3468 TALLOC_CTX *mem_ctx,
3469 struct lsa_LookupPrivDisplayName *r)
3471 struct dcesrv_handle *h;
3472 struct lsa_policy_state *state;
3473 struct lsa_StringLarge *disp_name = NULL;
3474 enum sec_privilege id;
3476 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3478 state = h->data;
3480 id = sec_privilege_id(r->in.name->string);
3481 if (id == SEC_PRIV_INVALID) {
3482 return NT_STATUS_NO_SUCH_PRIVILEGE;
3485 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3486 if (disp_name == NULL) {
3487 return NT_STATUS_NO_MEMORY;
3490 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3491 if (disp_name->string == NULL) {
3492 return NT_STATUS_INTERNAL_ERROR;
3495 *r->out.disp_name = disp_name;
3496 *r->out.returned_language_id = 0;
3498 return NT_STATUS_OK;
3503 lsa_EnumAccountsWithUserRight
3505 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3506 TALLOC_CTX *mem_ctx,
3507 struct lsa_EnumAccountsWithUserRight *r)
3509 struct dcesrv_handle *h;
3510 struct lsa_policy_state *state;
3511 int ret, i;
3512 struct ldb_message **res;
3513 const char * const attrs[] = { "objectSid", NULL};
3514 const char *privname;
3516 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3518 state = h->data;
3520 if (r->in.name == NULL) {
3521 return NT_STATUS_NO_SUCH_PRIVILEGE;
3524 privname = r->in.name->string;
3525 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3526 return NT_STATUS_NO_SUCH_PRIVILEGE;
3529 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3530 "privilege=%s", privname);
3531 if (ret < 0) {
3532 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3534 if (ret == 0) {
3535 return NT_STATUS_NO_MORE_ENTRIES;
3538 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3539 if (r->out.sids->sids == NULL) {
3540 return NT_STATUS_NO_MEMORY;
3542 for (i=0;i<ret;i++) {
3543 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3544 res[i], "objectSid");
3545 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3547 r->out.sids->num_sids = ret;
3549 return NT_STATUS_OK;
3554 lsa_AddAccountRights
3556 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3557 TALLOC_CTX *mem_ctx,
3558 struct lsa_AddAccountRights *r)
3560 struct dcesrv_handle *h;
3561 struct lsa_policy_state *state;
3563 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3565 state = h->data;
3567 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3568 LDB_FLAG_MOD_ADD,
3569 r->in.sid, r->in.rights);
3574 lsa_RemoveAccountRights
3576 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3577 TALLOC_CTX *mem_ctx,
3578 struct lsa_RemoveAccountRights *r)
3580 struct dcesrv_handle *h;
3581 struct lsa_policy_state *state;
3583 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3585 state = h->data;
3587 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3588 LDB_FLAG_MOD_DELETE,
3589 r->in.sid, r->in.rights);
3594 lsa_StorePrivateData
3596 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3597 struct lsa_StorePrivateData *r)
3599 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3604 lsa_RetrievePrivateData
3606 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3607 struct lsa_RetrievePrivateData *r)
3609 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3614 lsa_GetUserName
3616 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3617 struct lsa_GetUserName *r)
3619 NTSTATUS status = NT_STATUS_OK;
3620 const char *account_name;
3621 const char *authority_name;
3622 struct lsa_String *_account_name;
3623 struct lsa_String *_authority_name = NULL;
3625 /* this is what w2k3 does */
3626 r->out.account_name = r->in.account_name;
3627 r->out.authority_name = r->in.authority_name;
3629 if (r->in.account_name
3630 && *r->in.account_name
3631 /* && *(*r->in.account_name)->string */
3633 return NT_STATUS_INVALID_PARAMETER;
3636 if (r->in.authority_name
3637 && *r->in.authority_name
3638 /* && *(*r->in.authority_name)->string */
3640 return NT_STATUS_INVALID_PARAMETER;
3643 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3644 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3646 _account_name = talloc(mem_ctx, struct lsa_String);
3647 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3648 _account_name->string = account_name;
3650 if (r->in.authority_name) {
3651 _authority_name = talloc(mem_ctx, struct lsa_String);
3652 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3653 _authority_name->string = authority_name;
3656 *r->out.account_name = _account_name;
3657 if (r->out.authority_name) {
3658 *r->out.authority_name = _authority_name;
3661 return status;
3665 lsa_SetInfoPolicy2
3667 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3668 TALLOC_CTX *mem_ctx,
3669 struct lsa_SetInfoPolicy2 *r)
3671 /* need to support these */
3672 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3676 lsa_QueryDomainInformationPolicy
3678 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3679 TALLOC_CTX *mem_ctx,
3680 struct lsa_QueryDomainInformationPolicy *r)
3682 union lsa_DomainInformationPolicy *info;
3684 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3685 if (!info) {
3686 return NT_STATUS_NO_MEMORY;
3689 switch (r->in.level) {
3690 case LSA_DOMAIN_INFO_POLICY_EFS:
3691 talloc_free(info);
3692 *r->out.info = NULL;
3693 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3694 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3696 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3697 struct smb_krb5_context *smb_krb5_context;
3698 int ret = smb_krb5_init_context(mem_ctx,
3699 dce_call->event_ctx,
3700 dce_call->conn->dce_ctx->lp_ctx,
3701 &smb_krb5_context);
3702 if (ret != 0) {
3703 talloc_free(info);
3704 *r->out.info = NULL;
3705 return NT_STATUS_INTERNAL_ERROR;
3707 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3708 smb_krb5_context,
3710 talloc_free(smb_krb5_context);
3711 *r->out.info = info;
3712 return NT_STATUS_OK;
3714 default:
3715 talloc_free(info);
3716 *r->out.info = NULL;
3717 return NT_STATUS_INVALID_INFO_CLASS;
3722 lsa_SetDomInfoPolicy
3724 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3725 TALLOC_CTX *mem_ctx,
3726 struct lsa_SetDomainInformationPolicy *r)
3728 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3732 lsa_TestCall
3734 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3735 TALLOC_CTX *mem_ctx,
3736 struct lsa_TestCall *r)
3738 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3742 lsa_CREDRWRITE
3744 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3745 struct lsa_CREDRWRITE *r)
3747 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3752 lsa_CREDRREAD
3754 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3755 struct lsa_CREDRREAD *r)
3757 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3762 lsa_CREDRENUMERATE
3764 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3765 struct lsa_CREDRENUMERATE *r)
3767 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3772 lsa_CREDRWRITEDOMAINCREDENTIALS
3774 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3775 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3777 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3782 lsa_CREDRREADDOMAINCREDENTIALS
3784 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3785 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3787 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3792 lsa_CREDRDELETE
3794 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3795 struct lsa_CREDRDELETE *r)
3797 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3802 lsa_CREDRGETTARGETINFO
3804 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3805 struct lsa_CREDRGETTARGETINFO *r)
3807 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3812 lsa_CREDRPROFILELOADED
3814 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3815 struct lsa_CREDRPROFILELOADED *r)
3817 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3822 lsa_CREDRGETSESSIONTYPES
3824 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3825 struct lsa_CREDRGETSESSIONTYPES *r)
3827 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3832 lsa_LSARREGISTERAUDITEVENT
3834 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3835 struct lsa_LSARREGISTERAUDITEVENT *r)
3837 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3842 lsa_LSARGENAUDITEVENT
3844 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3845 struct lsa_LSARGENAUDITEVENT *r)
3847 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3852 lsa_LSARUNREGISTERAUDITEVENT
3854 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3855 struct lsa_LSARUNREGISTERAUDITEVENT *r)
3857 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3862 lsa_lsaRQueryForestTrustInformation
3864 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3865 struct lsa_lsaRQueryForestTrustInformation *r)
3867 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3870 #define DNS_CMP_MATCH 0
3871 #define DNS_CMP_FIRST_IS_CHILD 1
3872 #define DNS_CMP_SECOND_IS_CHILD 2
3873 #define DNS_CMP_NO_MATCH 3
3875 /* this function assumes names are well formed DNS names.
3876 * it doesn't validate them */
3877 static int dns_cmp(const char *s1, size_t l1,
3878 const char *s2, size_t l2)
3880 const char *p1, *p2;
3881 size_t t1, t2;
3882 int cret;
3884 if (l1 == l2) {
3885 if (strcasecmp_m(s1, s2) == 0) {
3886 return DNS_CMP_MATCH;
3888 return DNS_CMP_NO_MATCH;
3891 if (l1 > l2) {
3892 p1 = s1;
3893 p2 = s2;
3894 t1 = l1;
3895 t2 = l2;
3896 cret = DNS_CMP_FIRST_IS_CHILD;
3897 } else {
3898 p1 = s2;
3899 p2 = s1;
3900 t1 = l2;
3901 t2 = l1;
3902 cret = DNS_CMP_SECOND_IS_CHILD;
3905 if (p1[t1 - t2 - 1] != '.') {
3906 return DNS_CMP_NO_MATCH;
3909 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3910 return cret;
3913 return DNS_CMP_NO_MATCH;
3916 /* decode all TDOs forest trust info blobs */
3917 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3918 struct ldb_message *msg,
3919 struct ForestTrustInfo *info)
3921 const struct ldb_val *ft_blob;
3922 enum ndr_err_code ndr_err;
3924 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3925 if (!ft_blob || !ft_blob->data) {
3926 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3928 /* ldb_val is equivalent to DATA_BLOB */
3929 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3930 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3931 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3932 return NT_STATUS_INVALID_DOMAIN_STATE;
3935 return NT_STATUS_OK;
3938 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
3939 struct ForestTrustInfo *fti)
3941 struct ForestTrustDataDomainInfo *info;
3942 struct ForestTrustInfoRecord *rec;
3944 fti->version = 1;
3945 fti->count = 2;
3946 fti->records = talloc_array(fti,
3947 struct ForestTrustInfoRecordArmor, 2);
3948 if (!fti->records) {
3949 return NT_STATUS_NO_MEMORY;
3952 /* TLN info */
3953 rec = &fti->records[0].record;
3955 rec->flags = 0;
3956 rec->timestamp = 0;
3957 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
3959 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
3960 if (!rec->data.name.string) {
3961 return NT_STATUS_NO_MEMORY;
3963 rec->data.name.size = strlen(rec->data.name.string);
3965 /* DOMAIN info */
3966 rec = &fti->records[1].record;
3968 rec->flags = 0;
3969 rec->timestamp = 0;
3970 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
3972 info = &rec->data.info;
3974 info->sid = *ps->domain_sid;
3975 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
3976 if (!info->dns_name.string) {
3977 return NT_STATUS_NO_MEMORY;
3979 info->dns_name.size = strlen(info->dns_name.string);
3980 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
3981 if (!info->netbios_name.string) {
3982 return NT_STATUS_NO_MEMORY;
3984 info->netbios_name.size = strlen(info->netbios_name.string);
3986 return NT_STATUS_OK;
3989 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
3990 struct lsa_ForestTrustInformation *lfti,
3991 struct ForestTrustInfo *fti)
3993 struct lsa_ForestTrustRecord *lrec;
3994 struct ForestTrustInfoRecord *rec;
3995 struct lsa_StringLarge *tln;
3996 struct lsa_ForestTrustDomainInfo *info;
3997 uint32_t i;
3999 fti->version = 1;
4000 fti->count = lfti->count;
4001 fti->records = talloc_array(mem_ctx,
4002 struct ForestTrustInfoRecordArmor,
4003 fti->count);
4004 if (!fti->records) {
4005 return NT_STATUS_NO_MEMORY;
4007 for (i = 0; i < fti->count; i++) {
4008 lrec = lfti->entries[i];
4009 rec = &fti->records[i].record;
4011 rec->flags = lrec->flags;
4012 rec->timestamp = lrec->time;
4013 rec->type = lrec->type;
4015 switch (lrec->type) {
4016 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4017 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4018 tln = &lrec->forest_trust_data.top_level_name;
4019 rec->data.name.string =
4020 talloc_strdup(mem_ctx, tln->string);
4021 if (!rec->data.name.string) {
4022 return NT_STATUS_NO_MEMORY;
4024 rec->data.name.size = strlen(rec->data.name.string);
4025 break;
4026 case LSA_FOREST_TRUST_DOMAIN_INFO:
4027 info = &lrec->forest_trust_data.domain_info;
4028 rec->data.info.sid = *info->domain_sid;
4029 rec->data.info.dns_name.string =
4030 talloc_strdup(mem_ctx,
4031 info->dns_domain_name.string);
4032 if (!rec->data.info.dns_name.string) {
4033 return NT_STATUS_NO_MEMORY;
4035 rec->data.info.dns_name.size =
4036 strlen(rec->data.info.dns_name.string);
4037 rec->data.info.netbios_name.string =
4038 talloc_strdup(mem_ctx,
4039 info->netbios_domain_name.string);
4040 if (!rec->data.info.netbios_name.string) {
4041 return NT_STATUS_NO_MEMORY;
4043 rec->data.info.netbios_name.size =
4044 strlen(rec->data.info.netbios_name.string);
4045 break;
4046 default:
4047 return NT_STATUS_INVALID_DOMAIN_STATE;
4051 return NT_STATUS_OK;
4054 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4055 uint32_t idx, uint32_t collision_type,
4056 uint32_t conflict_type, const char *tdo_name);
4058 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4059 const char *tdo_name,
4060 struct ForestTrustInfo *tdo_fti,
4061 struct ForestTrustInfo *new_fti,
4062 struct lsa_ForestTrustCollisionInfo *c_info)
4064 struct ForestTrustInfoRecord *nrec;
4065 struct ForestTrustInfoRecord *trec;
4066 const char *dns_name;
4067 const char *nb_name;
4068 struct dom_sid *sid;
4069 const char *tname;
4070 size_t dns_len;
4071 size_t nb_len;
4072 size_t tlen;
4073 NTSTATUS nt_status;
4074 uint32_t new_fti_idx;
4075 uint32_t i;
4076 /* use always TDO type, until we understand when Xref can be used */
4077 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4078 bool tln_conflict;
4079 bool sid_conflict;
4080 bool nb_conflict;
4081 bool exclusion;
4082 bool ex_rule;
4083 int ret;
4085 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4087 nrec = &new_fti->records[new_fti_idx].record;
4088 dns_name = NULL;
4089 tln_conflict = false;
4090 sid_conflict = false;
4091 nb_conflict = false;
4092 exclusion = false;
4094 switch (nrec->type) {
4095 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4096 /* exclusions do not conflict by definition */
4097 break;
4099 case FOREST_TRUST_TOP_LEVEL_NAME:
4100 dns_name = nrec->data.name.string;
4101 dns_len = nrec->data.name.size;
4102 break;
4104 case LSA_FOREST_TRUST_DOMAIN_INFO:
4105 dns_name = nrec->data.info.dns_name.string;
4106 dns_len = nrec->data.info.dns_name.size;
4107 nb_name = nrec->data.info.netbios_name.string;
4108 nb_len = nrec->data.info.netbios_name.size;
4109 sid = &nrec->data.info.sid;
4110 break;
4113 if (!dns_name) continue;
4115 /* check if this is already taken and not excluded */
4116 for (i = 0; i < tdo_fti->count; i++) {
4117 trec = &tdo_fti->records[i].record;
4119 switch (trec->type) {
4120 case FOREST_TRUST_TOP_LEVEL_NAME:
4121 ex_rule = false;
4122 tname = trec->data.name.string;
4123 tlen = trec->data.name.size;
4124 break;
4125 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4126 ex_rule = true;
4127 tname = trec->data.name.string;
4128 tlen = trec->data.name.size;
4129 break;
4130 case FOREST_TRUST_DOMAIN_INFO:
4131 ex_rule = false;
4132 tname = trec->data.info.dns_name.string;
4133 tlen = trec->data.info.dns_name.size;
4135 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4136 switch (ret) {
4137 case DNS_CMP_MATCH:
4138 /* if it matches exclusion,
4139 * it doesn't conflict */
4140 if (ex_rule) {
4141 exclusion = true;
4142 break;
4144 /* fall through */
4145 case DNS_CMP_FIRST_IS_CHILD:
4146 case DNS_CMP_SECOND_IS_CHILD:
4147 tln_conflict = true;
4148 /* fall through */
4149 default:
4150 break;
4153 /* explicit exclusion, no dns name conflict here */
4154 if (exclusion) {
4155 tln_conflict = false;
4158 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4159 continue;
4162 /* also test for domain info */
4163 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4164 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4165 sid_conflict = true;
4167 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4168 strcasecmp_m(trec->data.info.netbios_name.string,
4169 nb_name) == 0) {
4170 nb_conflict = true;
4174 if (tln_conflict) {
4175 nt_status = add_collision(c_info, new_fti_idx,
4176 collision_type,
4177 LSA_TLN_DISABLED_CONFLICT,
4178 tdo_name);
4180 if (sid_conflict) {
4181 nt_status = add_collision(c_info, new_fti_idx,
4182 collision_type,
4183 LSA_SID_DISABLED_CONFLICT,
4184 tdo_name);
4186 if (nb_conflict) {
4187 nt_status = add_collision(c_info, new_fti_idx,
4188 collision_type,
4189 LSA_NB_DISABLED_CONFLICT,
4190 tdo_name);
4194 return NT_STATUS_OK;
4197 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4198 uint32_t idx, uint32_t collision_type,
4199 uint32_t conflict_type, const char *tdo_name)
4201 struct lsa_ForestTrustCollisionRecord **es;
4202 uint32_t i = c_info->count;
4204 es = talloc_realloc(c_info, c_info->entries,
4205 struct lsa_ForestTrustCollisionRecord *, i + 1);
4206 if (!es) {
4207 return NT_STATUS_NO_MEMORY;
4209 c_info->entries = es;
4210 c_info->count = i + 1;
4212 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4213 if (!es[i]) {
4214 return NT_STATUS_NO_MEMORY;
4217 es[i]->index = idx;
4218 es[i]->type = collision_type;
4219 es[i]->flags.flags = conflict_type;
4220 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4221 if (!es[i]->name.string) {
4222 return NT_STATUS_NO_MEMORY;
4224 es[i]->name.size = strlen(es[i]->name.string);
4226 return NT_STATUS_OK;
4230 lsa_lsaRSetForestTrustInformation
4232 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4233 TALLOC_CTX *mem_ctx,
4234 struct lsa_lsaRSetForestTrustInformation *r)
4236 struct dcesrv_handle *h;
4237 struct lsa_policy_state *p_state;
4238 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4239 "msDS-TrustForestTrustInfo", NULL };
4240 struct ldb_message **dom_res = NULL;
4241 struct ldb_dn *tdo_dn;
4242 struct ldb_message *msg;
4243 int num_res, i;
4244 const char *td_name;
4245 uint32_t trust_attributes;
4246 struct lsa_ForestTrustCollisionInfo *c_info;
4247 struct ForestTrustInfo *nfti;
4248 struct ForestTrustInfo *fti;
4249 DATA_BLOB ft_blob;
4250 enum ndr_err_code ndr_err;
4251 NTSTATUS nt_status;
4252 bool am_rodc;
4253 int ret;
4255 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4257 p_state = h->data;
4259 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4260 return NT_STATUS_INVALID_DOMAIN_STATE;
4263 /* abort if we are not a PDC */
4264 if (!samdb_is_pdc(p_state->sam_ldb)) {
4265 return NT_STATUS_INVALID_DOMAIN_ROLE;
4268 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4269 if (ret == LDB_SUCCESS && am_rodc) {
4270 return NT_STATUS_NO_SUCH_DOMAIN;
4273 /* check caller has TRUSTED_SET_AUTH */
4275 /* fetch all trusted domain objects */
4276 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4277 p_state->system_dn,
4278 &dom_res, trust_attrs,
4279 "(objectclass=trustedDomain)");
4280 if (num_res == 0) {
4281 return NT_STATUS_NO_SUCH_DOMAIN;
4284 for (i = 0; i < num_res; i++) {
4285 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4286 "trustPartner", NULL);
4287 if (!td_name) {
4288 return NT_STATUS_INVALID_DOMAIN_STATE;
4290 if (strcasecmp_m(td_name,
4291 r->in.trusted_domain_name->string) == 0) {
4292 break;
4295 if (i >= num_res) {
4296 return NT_STATUS_NO_SUCH_DOMAIN;
4299 tdo_dn = dom_res[i]->dn;
4301 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4302 "trustAttributes", 0);
4303 if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4304 return NT_STATUS_INVALID_PARAMETER;
4307 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4308 return NT_STATUS_INVALID_PARAMETER;
4311 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4312 if (!nfti) {
4313 return NT_STATUS_NO_MEMORY;
4316 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4317 if (!NT_STATUS_IS_OK(nt_status)) {
4318 return nt_status;
4321 c_info = talloc_zero(r->out.collision_info,
4322 struct lsa_ForestTrustCollisionInfo);
4323 if (!c_info) {
4324 return NT_STATUS_NO_MEMORY;
4327 /* first check own info, then other domains */
4328 fti = talloc(mem_ctx, struct ForestTrustInfo);
4329 if (!fti) {
4330 return NT_STATUS_NO_MEMORY;
4333 nt_status = own_ft_info(p_state, fti);
4334 if (!NT_STATUS_IS_OK(nt_status)) {
4335 return nt_status;
4338 nt_status = check_ft_info(c_info, p_state->domain_dns,
4339 fti, nfti, c_info);
4340 if (!NT_STATUS_IS_OK(nt_status)) {
4341 return nt_status;
4344 for (i = 0; i < num_res; i++) {
4345 fti = talloc(mem_ctx, struct ForestTrustInfo);
4346 if (!fti) {
4347 return NT_STATUS_NO_MEMORY;
4350 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4351 if (!NT_STATUS_IS_OK(nt_status)) {
4352 if (NT_STATUS_EQUAL(nt_status,
4353 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4354 continue;
4356 return nt_status;
4359 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4360 "trustPartner", NULL);
4361 if (!td_name) {
4362 return NT_STATUS_INVALID_DOMAIN_STATE;
4365 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4366 if (!NT_STATUS_IS_OK(nt_status)) {
4367 return nt_status;
4371 *r->out.collision_info = c_info;
4373 if (r->in.check_only != 0) {
4374 return NT_STATUS_OK;
4377 /* not just a check, write info back */
4379 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4380 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4381 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4382 return NT_STATUS_INVALID_PARAMETER;
4385 msg = ldb_msg_new(mem_ctx);
4386 if (msg == NULL) {
4387 return NT_STATUS_NO_MEMORY;
4390 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4391 if (!msg->dn) {
4392 return NT_STATUS_NO_MEMORY;
4395 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4396 LDB_FLAG_MOD_REPLACE, NULL);
4397 if (ret != LDB_SUCCESS) {
4398 return NT_STATUS_NO_MEMORY;
4400 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4401 &ft_blob, NULL);
4402 if (ret != LDB_SUCCESS) {
4403 return NT_STATUS_NO_MEMORY;
4406 ret = ldb_modify(p_state->sam_ldb, msg);
4407 if (ret != LDB_SUCCESS) {
4408 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4409 ldb_errstring(p_state->sam_ldb)));
4411 switch (ret) {
4412 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4413 return NT_STATUS_ACCESS_DENIED;
4414 default:
4415 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4419 return NT_STATUS_OK;
4423 lsa_CREDRRENAME
4425 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4426 struct lsa_CREDRRENAME *r)
4428 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4434 lsa_LSAROPENPOLICYSCE
4436 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4437 struct lsa_LSAROPENPOLICYSCE *r)
4439 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4444 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4446 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4447 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4449 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4454 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4456 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4457 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4459 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4464 lsa_LSARADTREPORTSECURITYEVENT
4466 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4467 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4469 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4473 /* include the generated boilerplate */
4474 #include "librpc/gen_ndr/ndr_lsa_s.c"
4478 /*****************************************
4479 NOTE! The remaining calls below were
4480 removed in w2k3, so the DCESRV_FAULT()
4481 replies are the correct implementation. Do
4482 not try and fill these in with anything else
4483 ******************************************/
4486 dssetup_DsRoleDnsNameToFlatName
4488 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4489 struct dssetup_DsRoleDnsNameToFlatName *r)
4491 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4496 dssetup_DsRoleDcAsDc
4498 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4499 struct dssetup_DsRoleDcAsDc *r)
4501 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4506 dssetup_DsRoleDcAsReplica
4508 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4509 struct dssetup_DsRoleDcAsReplica *r)
4511 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4516 dssetup_DsRoleDemoteDc
4518 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4519 struct dssetup_DsRoleDemoteDc *r)
4521 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4526 dssetup_DsRoleGetDcOperationProgress
4528 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4529 struct dssetup_DsRoleGetDcOperationProgress *r)
4531 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4536 dssetup_DsRoleGetDcOperationResults
4538 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4539 struct dssetup_DsRoleGetDcOperationResults *r)
4541 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4546 dssetup_DsRoleCancel
4548 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4549 struct dssetup_DsRoleCancel *r)
4551 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4556 dssetup_DsRoleServerSaveStateForUpgrade
4558 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4559 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4561 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4566 dssetup_DsRoleUpgradeDownlevelServer
4568 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4569 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4571 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4576 dssetup_DsRoleAbortDownlevelServerUpgrade
4578 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4579 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4581 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4585 /* include the generated boilerplate */
4586 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4588 NTSTATUS dcerpc_server_lsa_init(void)
4590 NTSTATUS ret;
4592 ret = dcerpc_server_dssetup_init();
4593 if (!NT_STATUS_IS_OK(ret)) {
4594 return ret;
4596 ret = dcerpc_server_lsarpc_init();
4597 if (!NT_STATUS_IS_OK(ret)) {
4598 return ret;
4600 return ret;