s4:rpc_server/lsa/dcesrv_lsa.c - fix typo
[Samba.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
blob3f5c9ff87059b166828dcd0364dad1723d40cca9
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"
34 this type allows us to distinguish handle types
38 state associated with a lsa_OpenAccount() operation
40 struct lsa_account_state {
41 struct lsa_policy_state *policy;
42 uint32_t access_mask;
43 struct dom_sid *account_sid;
48 state associated with a lsa_OpenSecret() operation
50 struct lsa_secret_state {
51 struct lsa_policy_state *policy;
52 uint32_t access_mask;
53 struct ldb_dn *secret_dn;
54 struct ldb_context *sam_ldb;
55 bool global;
59 state associated with a lsa_OpenTrustedDomain() operation
61 struct lsa_trusted_domain_state {
62 struct lsa_policy_state *policy;
63 uint32_t access_mask;
64 struct ldb_dn *trusted_domain_dn;
65 struct ldb_dn *trusted_domain_user_dn;
69 this is based on the samba3 function make_lsa_object_sd()
70 It uses the same logic, but with samba4 helper functions
72 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
73 struct security_descriptor **sd,
74 struct dom_sid *sid,
75 uint32_t sid_access)
77 NTSTATUS status;
78 uint32_t rid;
79 struct dom_sid *domain_sid, *domain_admins_sid;
80 const char *domain_admins_sid_str, *sidstr;
81 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
83 status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
84 NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
86 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
87 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid, tmp_ctx);
89 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
90 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid_str, tmp_ctx);
92 sidstr = dom_sid_string(tmp_ctx, sid);
93 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, tmp_ctx);
95 *sd = security_descriptor_dacl_create(mem_ctx,
96 0, sidstr, NULL,
98 SID_WORLD,
99 SEC_ACE_TYPE_ACCESS_ALLOWED,
100 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
102 SID_BUILTIN_ADMINISTRATORS,
103 SEC_ACE_TYPE_ACCESS_ALLOWED,
104 SEC_GENERIC_ALL, 0,
106 SID_BUILTIN_ACCOUNT_OPERATORS,
107 SEC_ACE_TYPE_ACCESS_ALLOWED,
108 SEC_GENERIC_ALL, 0,
110 domain_admins_sid_str,
111 SEC_ACE_TYPE_ACCESS_ALLOWED,
112 SEC_GENERIC_ALL, 0,
114 sidstr,
115 SEC_ACE_TYPE_ACCESS_ALLOWED,
116 sid_access, 0,
118 NULL);
119 talloc_free(tmp_ctx);
121 NT_STATUS_HAVE_NO_MEMORY(*sd);
123 return NT_STATUS_OK;
127 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
128 TALLOC_CTX *mem_ctx,
129 struct lsa_EnumAccountRights *r);
131 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
132 TALLOC_CTX *mem_ctx,
133 struct lsa_policy_state *state,
134 int ldb_flag,
135 struct dom_sid *sid,
136 const struct lsa_RightSet *rights);
139 lsa_Close
141 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
142 struct lsa_Close *r)
144 struct dcesrv_handle *h;
146 *r->out.handle = *r->in.handle;
148 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
150 talloc_free(h);
152 ZERO_STRUCTP(r->out.handle);
154 return NT_STATUS_OK;
159 lsa_Delete
161 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
162 struct lsa_Delete *r)
164 return NT_STATUS_NOT_SUPPORTED;
169 lsa_DeleteObject
171 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
172 struct lsa_DeleteObject *r)
174 struct dcesrv_handle *h;
175 int ret;
177 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
179 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
180 struct lsa_secret_state *secret_state = h->data;
182 /* Ensure user is permitted to delete this... */
183 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
185 case SECURITY_SYSTEM:
186 case SECURITY_ADMINISTRATOR:
187 break;
188 default:
189 /* Users and anonymous are not allowed to delete things */
190 return NT_STATUS_ACCESS_DENIED;
193 ret = ldb_delete(secret_state->sam_ldb,
194 secret_state->secret_dn);
195 if (ret != LDB_SUCCESS) {
196 return NT_STATUS_INVALID_HANDLE;
199 ZERO_STRUCTP(r->out.handle);
201 return NT_STATUS_OK;
203 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
204 struct lsa_trusted_domain_state *trusted_domain_state =
205 talloc_get_type(h->data, struct lsa_trusted_domain_state);
206 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
207 if (ret != LDB_SUCCESS) {
208 return NT_STATUS_INTERNAL_DB_CORRUPTION;
211 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
212 trusted_domain_state->trusted_domain_dn);
213 if (ret != LDB_SUCCESS) {
214 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
215 return NT_STATUS_INVALID_HANDLE;
218 if (trusted_domain_state->trusted_domain_user_dn) {
219 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
220 trusted_domain_state->trusted_domain_user_dn);
221 if (ret != LDB_SUCCESS) {
222 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
223 return NT_STATUS_INVALID_HANDLE;
227 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
228 if (ret != LDB_SUCCESS) {
229 return NT_STATUS_INTERNAL_DB_CORRUPTION;
232 ZERO_STRUCTP(r->out.handle);
234 return NT_STATUS_OK;
236 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
237 struct lsa_RightSet *rights;
238 struct lsa_account_state *astate;
239 struct lsa_EnumAccountRights r2;
240 NTSTATUS status;
242 rights = talloc(mem_ctx, struct lsa_RightSet);
244 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
246 astate = h->data;
248 r2.in.handle = &astate->policy->handle->wire_handle;
249 r2.in.sid = astate->account_sid;
250 r2.out.rights = rights;
252 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
253 but we have a LSA_HANDLE_ACCOUNT here, so this call
254 will always fail */
255 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
256 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
257 return NT_STATUS_OK;
260 if (!NT_STATUS_IS_OK(status)) {
261 return status;
264 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
265 LDB_FLAG_MOD_DELETE, astate->account_sid,
266 r2.out.rights);
267 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
268 return NT_STATUS_OK;
271 if (!NT_STATUS_IS_OK(status)) {
272 return status;
275 ZERO_STRUCTP(r->out.handle);
277 return NT_STATUS_OK;
280 return NT_STATUS_INVALID_HANDLE;
285 lsa_EnumPrivs
287 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
288 struct lsa_EnumPrivs *r)
290 struct dcesrv_handle *h;
291 struct lsa_policy_state *state;
292 uint32_t i;
293 const char *privname;
295 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
297 state = h->data;
299 i = *r->in.resume_handle;
300 if (i == 0) i = 1;
302 while ((privname = sec_privilege_name(i)) &&
303 r->out.privs->count < r->in.max_count) {
304 struct lsa_PrivEntry *e;
306 r->out.privs->privs = talloc_realloc(r->out.privs,
307 r->out.privs->privs,
308 struct lsa_PrivEntry,
309 r->out.privs->count+1);
310 if (r->out.privs->privs == NULL) {
311 return NT_STATUS_NO_MEMORY;
313 e = &r->out.privs->privs[r->out.privs->count];
314 e->luid.low = i;
315 e->luid.high = 0;
316 e->name.string = privname;
317 r->out.privs->count++;
318 i++;
321 *r->out.resume_handle = i;
323 return NT_STATUS_OK;
328 lsa_QuerySecObj
330 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
331 struct lsa_QuerySecurity *r)
333 struct dcesrv_handle *h;
334 struct security_descriptor *sd;
335 NTSTATUS status;
336 struct dom_sid *sid;
338 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
340 sid = dce_call->conn->auth_state.session_info->security_token->user_sid;
342 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
343 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
344 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
345 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid,
346 LSA_ACCOUNT_ALL_ACCESS);
347 } else {
348 return NT_STATUS_INVALID_HANDLE;
350 NT_STATUS_NOT_OK_RETURN(status);
352 (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
353 NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
355 (*r->out.sdbuf)->sd = sd;
357 return NT_STATUS_OK;
362 lsa_SetSecObj
364 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
365 struct lsa_SetSecObj *r)
367 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
372 lsa_ChangePassword
374 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
375 struct lsa_ChangePassword *r)
377 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
381 dssetup_DsRoleGetPrimaryDomainInformation
383 This is not an LSA call, but is the only call left on the DSSETUP
384 pipe (after the pipe was truncated), and needs lsa_get_policy_state
386 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
387 TALLOC_CTX *mem_ctx,
388 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
390 union dssetup_DsRoleInfo *info;
392 info = talloc(mem_ctx, union dssetup_DsRoleInfo);
393 W_ERROR_HAVE_NO_MEMORY(info);
395 switch (r->in.level) {
396 case DS_ROLE_BASIC_INFORMATION:
398 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
399 uint32_t flags = 0;
400 const char *domain = NULL;
401 const char *dns_domain = NULL;
402 const char *forest = NULL;
403 struct GUID domain_guid;
404 struct lsa_policy_state *state;
406 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
407 if (!NT_STATUS_IS_OK(status)) {
408 return ntstatus_to_werror(status);
411 ZERO_STRUCT(domain_guid);
413 switch (lp_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
414 case ROLE_STANDALONE:
415 role = DS_ROLE_STANDALONE_SERVER;
416 break;
417 case ROLE_DOMAIN_MEMBER:
418 role = DS_ROLE_MEMBER_SERVER;
419 break;
420 case ROLE_DOMAIN_CONTROLLER:
421 if (samdb_is_pdc(state->sam_ldb)) {
422 role = DS_ROLE_PRIMARY_DC;
423 } else {
424 role = DS_ROLE_BACKUP_DC;
426 break;
429 switch (lp_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
430 case ROLE_STANDALONE:
431 domain = talloc_strdup(mem_ctx, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));
432 W_ERROR_HAVE_NO_MEMORY(domain);
433 break;
434 case ROLE_DOMAIN_MEMBER:
435 domain = talloc_strdup(mem_ctx, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));
436 W_ERROR_HAVE_NO_MEMORY(domain);
437 /* TODO: what is with dns_domain and forest and guid? */
438 break;
439 case ROLE_DOMAIN_CONTROLLER:
440 flags = DS_ROLE_PRIMARY_DS_RUNNING;
442 if (state->mixed_domain == 1) {
443 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
446 domain = state->domain_name;
447 dns_domain = state->domain_dns;
448 forest = state->forest_dns;
450 domain_guid = state->domain_guid;
451 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
452 break;
455 info->basic.role = role;
456 info->basic.flags = flags;
457 info->basic.domain = domain;
458 info->basic.dns_domain = dns_domain;
459 info->basic.forest = forest;
460 info->basic.domain_guid = domain_guid;
462 r->out.info = info;
463 return WERR_OK;
465 case DS_ROLE_UPGRADE_STATUS:
467 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
468 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
470 r->out.info = info;
471 return WERR_OK;
473 case DS_ROLE_OP_STATUS:
475 info->opstatus.status = DS_ROLE_OP_IDLE;
477 r->out.info = info;
478 return WERR_OK;
480 default:
481 return WERR_INVALID_PARAM;
486 fill in the AccountDomain info
488 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
489 struct lsa_DomainInfo *info)
491 info->name.string = state->domain_name;
492 info->sid = state->domain_sid;
494 return NT_STATUS_OK;
498 fill in the DNS domain info
500 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
501 struct lsa_DnsDomainInfo *info)
503 info->name.string = state->domain_name;
504 info->sid = state->domain_sid;
505 info->dns_domain.string = state->domain_dns;
506 info->dns_forest.string = state->forest_dns;
507 info->domain_guid = state->domain_guid;
509 return NT_STATUS_OK;
513 lsa_QueryInfoPolicy2
515 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
516 struct lsa_QueryInfoPolicy2 *r)
518 struct lsa_policy_state *state;
519 struct dcesrv_handle *h;
520 union lsa_PolicyInformation *info;
522 *r->out.info = NULL;
524 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
526 state = h->data;
528 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
529 if (!info) {
530 return NT_STATUS_NO_MEMORY;
532 *r->out.info = info;
534 switch (r->in.level) {
535 case LSA_POLICY_INFO_AUDIT_LOG:
536 /* we don't need to fill in any of this */
537 ZERO_STRUCT(info->audit_log);
538 return NT_STATUS_OK;
539 case LSA_POLICY_INFO_AUDIT_EVENTS:
540 /* we don't need to fill in any of this */
541 ZERO_STRUCT(info->audit_events);
542 return NT_STATUS_OK;
543 case LSA_POLICY_INFO_PD:
544 /* we don't need to fill in any of this */
545 ZERO_STRUCT(info->pd);
546 return NT_STATUS_OK;
548 case LSA_POLICY_INFO_DOMAIN:
549 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
550 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
551 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
552 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
553 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
555 case LSA_POLICY_INFO_ROLE:
556 info->role.role = LSA_ROLE_PRIMARY;
557 return NT_STATUS_OK;
559 case LSA_POLICY_INFO_DNS:
560 case LSA_POLICY_INFO_DNS_INT:
561 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
563 case LSA_POLICY_INFO_REPLICA:
564 ZERO_STRUCT(info->replica);
565 return NT_STATUS_OK;
567 case LSA_POLICY_INFO_QUOTA:
568 ZERO_STRUCT(info->quota);
569 return NT_STATUS_OK;
571 case LSA_POLICY_INFO_MOD:
572 case LSA_POLICY_INFO_AUDIT_FULL_SET:
573 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
574 /* windows gives INVALID_PARAMETER */
575 *r->out.info = NULL;
576 return NT_STATUS_INVALID_PARAMETER;
579 *r->out.info = NULL;
580 return NT_STATUS_INVALID_INFO_CLASS;
584 lsa_QueryInfoPolicy
586 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
587 struct lsa_QueryInfoPolicy *r)
589 struct lsa_QueryInfoPolicy2 r2;
590 NTSTATUS status;
592 ZERO_STRUCT(r2);
594 r2.in.handle = r->in.handle;
595 r2.in.level = r->in.level;
596 r2.out.info = r->out.info;
598 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
600 return status;
604 lsa_SetInfoPolicy
606 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
607 struct lsa_SetInfoPolicy *r)
609 /* need to support this */
610 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
615 lsa_ClearAuditLog
617 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
618 struct lsa_ClearAuditLog *r)
620 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
625 lsa_CreateAccount
627 This call does not seem to have any long-term effects, hence no database operations
629 we need to talk to the MS product group to find out what this account database means!
631 answer is that the lsa database is totally separate from the SAM and
632 ldap databases. We are going to need a separate ldb to store these
633 accounts. The SIDs on this account bear no relation to the SIDs in
636 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
637 struct lsa_CreateAccount *r)
639 struct lsa_account_state *astate;
641 struct lsa_policy_state *state;
642 struct dcesrv_handle *h, *ah;
644 ZERO_STRUCTP(r->out.acct_handle);
646 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
648 state = h->data;
650 astate = talloc(dce_call->conn, struct lsa_account_state);
651 if (astate == NULL) {
652 return NT_STATUS_NO_MEMORY;
655 astate->account_sid = dom_sid_dup(astate, r->in.sid);
656 if (astate->account_sid == NULL) {
657 talloc_free(astate);
658 return NT_STATUS_NO_MEMORY;
661 astate->policy = talloc_reference(astate, state);
662 astate->access_mask = r->in.access_mask;
664 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
665 if (!ah) {
666 talloc_free(astate);
667 return NT_STATUS_NO_MEMORY;
670 ah->data = talloc_steal(ah, astate);
672 *r->out.acct_handle = ah->wire_handle;
674 return NT_STATUS_OK;
679 lsa_EnumAccounts
681 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
682 struct lsa_EnumAccounts *r)
684 struct dcesrv_handle *h;
685 struct lsa_policy_state *state;
686 int ret;
687 struct ldb_message **res;
688 const char * const attrs[] = { "objectSid", NULL};
689 uint32_t count, i;
691 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
693 state = h->data;
695 /* NOTE: This call must only return accounts that have at least
696 one privilege set
698 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
699 "(&(objectSid=*)(privilege=*))");
700 if (ret < 0) {
701 return NT_STATUS_INTERNAL_DB_CORRUPTION;
704 if (*r->in.resume_handle >= ret) {
705 return NT_STATUS_NO_MORE_ENTRIES;
708 count = ret - *r->in.resume_handle;
709 if (count > r->in.num_entries) {
710 count = r->in.num_entries;
713 if (count == 0) {
714 return NT_STATUS_NO_MORE_ENTRIES;
717 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
718 if (r->out.sids->sids == NULL) {
719 return NT_STATUS_NO_MEMORY;
722 for (i=0;i<count;i++) {
723 r->out.sids->sids[i].sid =
724 samdb_result_dom_sid(r->out.sids->sids,
725 res[i + *r->in.resume_handle],
726 "objectSid");
727 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
730 r->out.sids->num_sids = count;
731 *r->out.resume_handle = count + *r->in.resume_handle;
733 return NT_STATUS_OK;
737 /* This decrypts and returns Trusted Domain Auth Information Internal data */
738 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
739 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
740 struct trustDomainPasswords *auth_struct)
742 DATA_BLOB session_key = data_blob(NULL, 0);
743 enum ndr_err_code ndr_err;
744 NTSTATUS nt_status;
746 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
747 if (!NT_STATUS_IS_OK(nt_status)) {
748 return nt_status;
751 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
752 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
753 auth_struct,
754 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
755 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
756 return NT_STATUS_INVALID_PARAMETER;
759 return NT_STATUS_OK;
762 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
763 TALLOC_CTX *mem_ctx,
764 struct trustCurrentPasswords *iopw,
765 DATA_BLOB *trustauth_blob)
767 uint32_t i;
768 struct trustAuthInOutBlob ioblob;
769 enum ndr_err_code ndr_err;
771 ioblob.count = iopw->count;
772 ioblob.current = talloc(mem_ctx,
773 struct AuthenticationInformationArray);
774 if (!ioblob.current) {
775 return NT_STATUS_NO_MEMORY;
778 ioblob.current->array = *iopw->current;
779 if (!ioblob.current->array) {
780 return NT_STATUS_NO_MEMORY;
783 ioblob.previous = talloc(mem_ctx,
784 struct AuthenticationInformationArray);
785 if (!ioblob.previous) {
786 return NT_STATUS_NO_MEMORY;
788 ioblob.previous->array = talloc_array(mem_ctx,
789 struct AuthenticationInformation,
790 ioblob.count);
791 if (!ioblob.previous->array) {
792 return NT_STATUS_NO_MEMORY;
795 for (i = 0; i < ioblob.count; i++) {
796 ioblob.previous->array[i].LastUpdateTime = 0;
797 ioblob.previous->array[i].AuthType = 0;
799 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
800 &ioblob,
801 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
802 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
803 return NT_STATUS_INVALID_PARAMETER;
806 return NT_STATUS_OK;
809 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
810 struct ldb_context *sam_ldb,
811 struct ldb_dn *base_dn,
812 const char *netbios_name,
813 struct trustCurrentPasswords *in,
814 struct ldb_dn **user_dn)
816 struct ldb_message *msg;
817 struct ldb_dn *dn;
818 uint32_t i;
819 int ret;
821 dn = ldb_dn_copy(mem_ctx, base_dn);
822 if (!dn) {
823 return NT_STATUS_NO_MEMORY;
825 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
826 return NT_STATUS_NO_MEMORY;
829 msg = ldb_msg_new(mem_ctx);
830 if (!msg) {
831 return NT_STATUS_NO_MEMORY;
833 msg->dn = dn;
835 ret = ldb_msg_add_string(msg, "objectClass", "user");
836 if (ret != LDB_SUCCESS) {
837 return NT_STATUS_NO_MEMORY;
840 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
841 if (ret != LDB_SUCCESS) {
842 return NT_STATUS_NO_MEMORY;
845 ret = ldb_msg_add_fmt(msg, "userAccountControl", "%u",
846 UF_INTERDOMAIN_TRUST_ACCOUNT);
847 if (ret != LDB_SUCCESS) {
848 return NT_STATUS_NO_MEMORY;
851 for (i = 0; i < in->count; i++) {
852 const char *attribute;
853 struct ldb_val v;
854 switch (in->current[i]->AuthType) {
855 case TRUST_AUTH_TYPE_NT4OWF:
856 attribute = "unicodePwd";
857 v.data = (uint8_t *)&in->current[i]->AuthInfo.nt4owf.password;
858 v.length = 16;
859 break;
860 case TRUST_AUTH_TYPE_CLEAR:
861 attribute = "clearTextPassword";
862 v.data = in->current[i]->AuthInfo.clear.password;
863 v.length = in->current[i]->AuthInfo.clear.size;
864 break;
865 default:
866 continue;
869 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
870 if (ret != LDB_SUCCESS) {
871 return NT_STATUS_NO_MEMORY;
875 /* create the trusted_domain user account */
876 ret = ldb_add(sam_ldb, msg);
877 if (ret != LDB_SUCCESS) {
878 DEBUG(0,("Failed to create user record %s: %s\n",
879 ldb_dn_get_linearized(msg->dn),
880 ldb_errstring(sam_ldb)));
882 switch (ret) {
883 case LDB_ERR_ENTRY_ALREADY_EXISTS:
884 return NT_STATUS_DOMAIN_EXISTS;
885 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
886 return NT_STATUS_ACCESS_DENIED;
887 default:
888 return NT_STATUS_INTERNAL_DB_CORRUPTION;
892 if (user_dn) {
893 *user_dn = dn;
895 return NT_STATUS_OK;
899 lsa_CreateTrustedDomainEx2
901 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
902 TALLOC_CTX *mem_ctx,
903 struct lsa_CreateTrustedDomainEx2 *r,
904 int op)
906 struct dcesrv_handle *policy_handle;
907 struct lsa_policy_state *policy_state;
908 struct lsa_trusted_domain_state *trusted_domain_state;
909 struct dcesrv_handle *handle;
910 struct ldb_message **msgs, *msg;
911 const char *attrs[] = {
912 NULL
914 const char *netbios_name;
915 const char *dns_name;
916 const char *name;
917 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
918 struct trustDomainPasswords auth_struct;
919 int ret;
920 NTSTATUS nt_status;
921 struct ldb_context *sam_ldb;
923 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
924 ZERO_STRUCTP(r->out.trustdom_handle);
926 policy_state = policy_handle->data;
927 sam_ldb = policy_state->sam_ldb;
929 netbios_name = r->in.info->netbios_name.string;
930 if (!netbios_name) {
931 return NT_STATUS_INVALID_PARAMETER;
934 dns_name = r->in.info->domain_name.string;
936 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
937 if (!trusted_domain_state) {
938 return NT_STATUS_NO_MEMORY;
940 trusted_domain_state->policy = policy_state;
942 if (strcasecmp(netbios_name, "BUILTIN") == 0
943 || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
944 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
945 return NT_STATUS_INVALID_PARAMETER;
948 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
949 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
950 || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
951 || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
952 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
953 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
956 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
957 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
958 /* No secrets are created at this time, for this function */
959 auth_struct.outgoing.count = 0;
960 auth_struct.incoming.count = 0;
961 } else {
962 auth_blob = data_blob_const(r->in.auth_info->auth_blob.data,
963 r->in.auth_info->auth_blob.size);
964 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
965 &auth_blob, &auth_struct);
966 if (!NT_STATUS_IS_OK(nt_status)) {
967 return nt_status;
970 if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
971 if (auth_struct.incoming.count > 1) {
972 return NT_STATUS_INVALID_PARAMETER;
977 if (auth_struct.incoming.count) {
978 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
979 &auth_struct.incoming,
980 &trustAuthIncoming);
981 if (!NT_STATUS_IS_OK(nt_status)) {
982 return nt_status;
984 } else {
985 trustAuthIncoming = data_blob(NULL, 0);
988 if (auth_struct.outgoing.count) {
989 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
990 &auth_struct.outgoing,
991 &trustAuthOutgoing);
992 if (!NT_STATUS_IS_OK(nt_status)) {
993 return nt_status;
995 } else {
996 trustAuthOutgoing = data_blob(NULL, 0);
999 ret = ldb_transaction_start(sam_ldb);
1000 if (ret != LDB_SUCCESS) {
1001 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1004 if (dns_name) {
1005 char *dns_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1006 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1007 /* search for the trusted_domain record */
1008 ret = gendb_search(sam_ldb,
1009 mem_ctx, policy_state->system_dn, &msgs, attrs,
1010 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1011 dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
1012 if (ret > 0) {
1013 ldb_transaction_cancel(sam_ldb);
1014 return NT_STATUS_OBJECT_NAME_COLLISION;
1016 } else {
1017 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1018 /* search for the trusted_domain record */
1019 ret = gendb_search(sam_ldb,
1020 mem_ctx, policy_state->system_dn, &msgs, attrs,
1021 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1022 netbios_encoded, netbios_encoded, netbios_encoded);
1023 if (ret > 0) {
1024 ldb_transaction_cancel(sam_ldb);
1025 return NT_STATUS_OBJECT_NAME_COLLISION;
1029 if (ret < 0 ) {
1030 ldb_transaction_cancel(sam_ldb);
1031 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1034 name = dns_name ? dns_name : netbios_name;
1036 msg = ldb_msg_new(mem_ctx);
1037 if (msg == NULL) {
1038 return NT_STATUS_NO_MEMORY;
1041 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1042 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1043 ldb_transaction_cancel(sam_ldb);
1044 return NT_STATUS_NO_MEMORY;
1047 samdb_msg_add_string(sam_ldb, mem_ctx, msg, "flatname", netbios_name);
1049 if (r->in.info->sid) {
1050 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1051 if (ret != LDB_SUCCESS) {
1052 ldb_transaction_cancel(sam_ldb);
1053 return NT_STATUS_INVALID_PARAMETER;
1057 samdb_msg_add_string(sam_ldb, mem_ctx, msg, "objectClass", "trustedDomain");
1059 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1061 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1063 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1065 if (dns_name) {
1066 samdb_msg_add_string(sam_ldb, mem_ctx, msg, "trustPartner", dns_name);
1069 if (trustAuthIncoming.data) {
1070 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1071 if (ret != LDB_SUCCESS) {
1072 ldb_transaction_cancel(sam_ldb);
1073 return NT_STATUS_NO_MEMORY;
1076 if (trustAuthOutgoing.data) {
1077 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1078 if (ret != LDB_SUCCESS) {
1079 ldb_transaction_cancel(sam_ldb);
1080 return NT_STATUS_NO_MEMORY;
1084 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1086 /* create the trusted_domain */
1087 ret = ldb_add(sam_ldb, msg);
1088 switch (ret) {
1089 case LDB_SUCCESS:
1090 break;
1091 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1092 ldb_transaction_cancel(sam_ldb);
1093 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1094 ldb_dn_get_linearized(msg->dn),
1095 ldb_errstring(sam_ldb)));
1096 return NT_STATUS_DOMAIN_EXISTS;
1097 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1098 ldb_transaction_cancel(sam_ldb);
1099 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1100 ldb_dn_get_linearized(msg->dn),
1101 ldb_errstring(sam_ldb)));
1102 return NT_STATUS_ACCESS_DENIED;
1103 default:
1104 ldb_transaction_cancel(sam_ldb);
1105 DEBUG(0,("Failed to create user record %s: %s\n",
1106 ldb_dn_get_linearized(msg->dn),
1107 ldb_errstring(sam_ldb)));
1108 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1111 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1112 struct ldb_dn *user_dn;
1113 /* Inbound trusts must also create a cn=users object to match */
1114 nt_status = add_trust_user(mem_ctx, sam_ldb,
1115 policy_state->domain_dn,
1116 netbios_name,
1117 &auth_struct.incoming,
1118 &user_dn);
1119 if (!NT_STATUS_IS_OK(nt_status)) {
1120 ldb_transaction_cancel(sam_ldb);
1121 return nt_status;
1124 /* save the trust user dn */
1125 trusted_domain_state->trusted_domain_user_dn
1126 = talloc_steal(trusted_domain_state, user_dn);
1129 ret = ldb_transaction_commit(sam_ldb);
1130 if (ret != LDB_SUCCESS) {
1131 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1134 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1135 if (!handle) {
1136 return NT_STATUS_NO_MEMORY;
1139 handle->data = talloc_steal(handle, trusted_domain_state);
1141 trusted_domain_state->access_mask = r->in.access_mask;
1142 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1144 *r->out.trustdom_handle = handle->wire_handle;
1146 return NT_STATUS_OK;
1150 lsa_CreateTrustedDomainEx2
1152 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1153 TALLOC_CTX *mem_ctx,
1154 struct lsa_CreateTrustedDomainEx2 *r)
1156 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2);
1159 lsa_CreateTrustedDomainEx
1161 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1162 TALLOC_CTX *mem_ctx,
1163 struct lsa_CreateTrustedDomainEx *r)
1165 struct lsa_CreateTrustedDomainEx2 r2;
1167 r2.in.policy_handle = r->in.policy_handle;
1168 r2.in.info = r->in.info;
1169 r2.in.auth_info = r->in.auth_info;
1170 r2.out.trustdom_handle = r->out.trustdom_handle;
1171 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX);
1175 lsa_CreateTrustedDomain
1177 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1178 struct lsa_CreateTrustedDomain *r)
1180 struct lsa_CreateTrustedDomainEx2 r2;
1182 r2.in.policy_handle = r->in.policy_handle;
1183 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1184 if (!r2.in.info) {
1185 return NT_STATUS_NO_MEMORY;
1188 r2.in.info->domain_name.string = NULL;
1189 r2.in.info->netbios_name = r->in.info->name;
1190 r2.in.info->sid = r->in.info->sid;
1191 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1192 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1193 r2.in.info->trust_attributes = 0;
1195 r2.in.access_mask = r->in.access_mask;
1196 r2.out.trustdom_handle = r->out.trustdom_handle;
1198 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN);
1203 lsa_OpenTrustedDomain
1205 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1206 struct lsa_OpenTrustedDomain *r)
1208 struct dcesrv_handle *policy_handle;
1210 struct lsa_policy_state *policy_state;
1211 struct lsa_trusted_domain_state *trusted_domain_state;
1212 struct dcesrv_handle *handle;
1213 struct ldb_message **msgs;
1214 const char *attrs[] = {
1215 "trustDirection",
1216 "flatname",
1217 NULL
1220 const char *sid_string;
1221 int ret;
1223 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1224 ZERO_STRUCTP(r->out.trustdom_handle);
1225 policy_state = policy_handle->data;
1227 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1228 if (!trusted_domain_state) {
1229 return NT_STATUS_NO_MEMORY;
1231 trusted_domain_state->policy = policy_state;
1233 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1234 if (!sid_string) {
1235 return NT_STATUS_NO_MEMORY;
1238 /* search for the trusted_domain record */
1239 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1240 mem_ctx, policy_state->system_dn, &msgs, attrs,
1241 "(&(securityIdentifier=%s)(objectclass=trustedDomain))",
1242 sid_string);
1243 if (ret == 0) {
1244 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1247 if (ret != 1) {
1248 DEBUG(0,("Found %d records matching DN %s\n", ret,
1249 ldb_dn_get_linearized(policy_state->system_dn)));
1250 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1253 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1255 trusted_domain_state->trusted_domain_user_dn = NULL;
1257 if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1258 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1259 /* search for the trusted_domain record */
1260 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1261 mem_ctx, policy_state->domain_dn, &msgs, attrs,
1262 "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%d))",
1263 flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1264 if (ret == 1) {
1265 trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1268 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1269 if (!handle) {
1270 return NT_STATUS_NO_MEMORY;
1273 handle->data = talloc_steal(handle, trusted_domain_state);
1275 trusted_domain_state->access_mask = r->in.access_mask;
1276 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1278 *r->out.trustdom_handle = handle->wire_handle;
1280 return NT_STATUS_OK;
1285 lsa_OpenTrustedDomainByName
1287 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1288 TALLOC_CTX *mem_ctx,
1289 struct lsa_OpenTrustedDomainByName *r)
1291 struct dcesrv_handle *policy_handle;
1293 struct lsa_policy_state *policy_state;
1294 struct lsa_trusted_domain_state *trusted_domain_state;
1295 struct dcesrv_handle *handle;
1296 struct ldb_message **msgs;
1297 const char *attrs[] = {
1298 NULL
1300 char *td_name;
1301 int ret;
1303 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1304 ZERO_STRUCTP(r->out.trustdom_handle);
1305 policy_state = policy_handle->data;
1307 if (!r->in.name.string) {
1308 return NT_STATUS_INVALID_PARAMETER;
1311 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1312 if (!trusted_domain_state) {
1313 return NT_STATUS_NO_MEMORY;
1315 trusted_domain_state->policy = policy_state;
1317 /* search for the trusted_domain record */
1318 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1319 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1320 mem_ctx, policy_state->system_dn, &msgs, attrs,
1321 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1322 "(objectclass=trustedDomain))",
1323 td_name, td_name, td_name);
1324 if (ret == 0) {
1325 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1328 if (ret != 1) {
1329 DEBUG(0,("Found %d records matching DN %s\n", ret,
1330 ldb_dn_get_linearized(policy_state->system_dn)));
1331 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1334 /* TODO: perform access checks */
1336 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1338 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1339 if (!handle) {
1340 return NT_STATUS_NO_MEMORY;
1343 handle->data = talloc_steal(handle, trusted_domain_state);
1345 trusted_domain_state->access_mask = r->in.access_mask;
1346 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1348 *r->out.trustdom_handle = handle->wire_handle;
1350 return NT_STATUS_OK;
1356 lsa_SetTrustedDomainInfo
1358 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1359 struct lsa_SetTrustedDomainInfo *r)
1361 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1366 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1367 * otherwise at least one must be provided */
1368 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1369 struct ldb_dn *basedn, const char *dns_domain,
1370 const char *netbios, struct dom_sid2 *sid,
1371 struct ldb_message ***msgs)
1373 const char *attrs[] = { "flatname", "trustPartner",
1374 "securityIdentifier", "trustDirection",
1375 "trustType", "trustAttributes",
1376 "trustPosixOffset",
1377 "msDs-supportedEncryptionTypes", NULL };
1378 char *dns = NULL;
1379 char *nbn = NULL;
1380 char *sidstr = NULL;
1381 char *filter;
1382 int ret;
1385 if (dns_domain || netbios || sid) {
1386 filter = talloc_strdup(mem_ctx,
1387 "(&(objectclass=trustedDomain)(|");
1388 } else {
1389 filter = talloc_strdup(mem_ctx,
1390 "(objectclass=trustedDomain)");
1392 if (!filter) {
1393 return NT_STATUS_NO_MEMORY;
1396 if (dns_domain) {
1397 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1398 if (!dns) {
1399 return NT_STATUS_NO_MEMORY;
1401 filter = talloc_asprintf_append(filter,
1402 "(trustPartner=%s)", dns);
1403 if (!filter) {
1404 return NT_STATUS_NO_MEMORY;
1407 if (netbios) {
1408 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1409 if (!nbn) {
1410 return NT_STATUS_NO_MEMORY;
1412 filter = talloc_asprintf_append(filter,
1413 "(flatname=%s)", nbn);
1414 if (!filter) {
1415 return NT_STATUS_NO_MEMORY;
1418 if (sid) {
1419 sidstr = dom_sid_string(mem_ctx, sid);
1420 if (!sidstr) {
1421 return NT_STATUS_INVALID_PARAMETER;
1423 filter = talloc_asprintf_append(filter,
1424 "(securityIdentifier=%s)",
1425 sidstr);
1426 if (!filter) {
1427 return NT_STATUS_NO_MEMORY;
1430 if (dns_domain || netbios || sid) {
1431 filter = talloc_asprintf_append(filter, "))");
1432 if (!filter) {
1433 return NT_STATUS_NO_MEMORY;
1437 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1438 if (ret == 0) {
1439 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1442 if (ret != 1) {
1443 return NT_STATUS_OBJECT_NAME_COLLISION;
1446 return NT_STATUS_OK;
1449 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1450 struct ldb_message *orig,
1451 struct ldb_message *dest,
1452 const char *attribute,
1453 uint32_t value,
1454 uint32_t *orig_value)
1456 const struct ldb_val *orig_val;
1457 uint32_t orig_uint = 0;
1458 char *str_val;
1459 int flags = 0;
1460 int ret;
1462 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1463 if (!orig_val || !orig_val->data) {
1464 /* add new attribute */
1465 flags = LDB_FLAG_MOD_ADD;
1467 } else {
1468 errno = 0;
1469 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1470 if (errno != 0 || orig_uint != value) {
1471 /* replace also if can't get value */
1472 flags = LDB_FLAG_MOD_REPLACE;
1476 if (flags == 0) {
1477 /* stored value is identical, nothing to change */
1478 goto done;
1481 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1482 if (ret != LDB_SUCCESS) {
1483 return NT_STATUS_NO_MEMORY;
1486 str_val = talloc_asprintf(mem_ctx, "%u", value);
1487 if (!str_val) {
1488 return NT_STATUS_NO_MEMORY;
1490 ret = ldb_msg_add_steal_string(dest, attribute, str_val);
1491 if (ret != LDB_SUCCESS) {
1492 return NT_STATUS_NO_MEMORY;
1495 done:
1496 if (orig_value) {
1497 *orig_value = orig_uint;
1499 return NT_STATUS_OK;
1502 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1503 struct ldb_context *sam_ldb,
1504 struct ldb_dn *base_dn,
1505 bool delete_user,
1506 const char *netbios_name,
1507 struct trustCurrentPasswords *in)
1509 const char *attrs[] = { "userAccountControl", NULL };
1510 struct ldb_message **msgs;
1511 struct ldb_message *msg;
1512 uint32_t uac;
1513 uint32_t i;
1514 int ret;
1516 ret = gendb_search(sam_ldb, mem_ctx,
1517 base_dn, &msgs, attrs,
1518 "samAccountName=%s$", netbios_name);
1519 if (ret > 1) {
1520 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1523 if (ret == 0) {
1524 if (delete_user) {
1525 return NT_STATUS_OK;
1528 /* ok no existing user, add it from scratch */
1529 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1530 netbios_name, in, NULL);
1533 /* check user is what we are looking for */
1534 uac = ldb_msg_find_attr_as_uint(msgs[0],
1535 "userAccountControl", 0);
1536 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1537 return NT_STATUS_OBJECT_NAME_COLLISION;
1540 if (delete_user) {
1541 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1542 switch (ret) {
1543 case LDB_SUCCESS:
1544 return NT_STATUS_OK;
1545 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1546 return NT_STATUS_ACCESS_DENIED;
1547 default:
1548 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1552 /* entry exists, just modify secret if any */
1553 if (in->count == 0) {
1554 return NT_STATUS_OK;
1557 msg = ldb_msg_new(mem_ctx);
1558 if (!msg) {
1559 return NT_STATUS_NO_MEMORY;
1561 msg->dn = msgs[0]->dn;
1563 for (i = 0; i < in->count; i++) {
1564 const char *attribute;
1565 struct ldb_val v;
1566 switch (in->current[i]->AuthType) {
1567 case TRUST_AUTH_TYPE_NT4OWF:
1568 attribute = "unicodePwd";
1569 v.data = (uint8_t *)&in->current[i]->AuthInfo.nt4owf.password;
1570 v.length = 16;
1571 break;
1572 case TRUST_AUTH_TYPE_CLEAR:
1573 attribute = "clearTextPassword";
1574 v.data = in->current[i]->AuthInfo.clear.password;
1575 v.length = in->current[i]->AuthInfo.clear.size;
1576 break;
1577 default:
1578 continue;
1581 ret = ldb_msg_add_empty(msg, attribute,
1582 LDB_FLAG_MOD_REPLACE, NULL);
1583 if (ret != LDB_SUCCESS) {
1584 return NT_STATUS_NO_MEMORY;
1587 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1588 if (ret != LDB_SUCCESS) {
1589 return NT_STATUS_NO_MEMORY;
1593 /* create the trusted_domain user account */
1594 ret = ldb_modify(sam_ldb, msg);
1595 if (ret != LDB_SUCCESS) {
1596 DEBUG(0,("Failed to create user record %s: %s\n",
1597 ldb_dn_get_linearized(msg->dn),
1598 ldb_errstring(sam_ldb)));
1600 switch (ret) {
1601 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1602 return NT_STATUS_DOMAIN_EXISTS;
1603 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1604 return NT_STATUS_ACCESS_DENIED;
1605 default:
1606 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1610 return NT_STATUS_OK;
1614 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1615 struct dcesrv_handle *p_handle,
1616 TALLOC_CTX *mem_ctx,
1617 struct ldb_message *dom_msg,
1618 enum lsa_TrustDomInfoEnum level,
1619 union lsa_TrustedDomainInfo *info)
1621 struct lsa_policy_state *p_state = p_handle->data;
1622 uint32_t *posix_offset = NULL;
1623 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1624 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1625 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1626 uint32_t *enc_types = NULL;
1627 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1628 struct trustDomainPasswords auth_struct;
1629 NTSTATUS nt_status;
1630 struct ldb_message **msgs;
1631 struct ldb_message *msg;
1632 bool add_outgoing = false;
1633 bool add_incoming = false;
1634 bool del_outgoing = false;
1635 bool del_incoming = false;
1636 bool in_transaction = false;
1637 int ret;
1638 bool am_rodc;
1640 switch (level) {
1641 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1642 posix_offset = &info->posix_offset.posix_offset;
1643 break;
1644 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1645 info_ex = &info->info_ex;
1646 break;
1647 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1648 auth_info = &info->auth_info;
1649 break;
1650 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1651 posix_offset = &info->full_info.posix_offset.posix_offset;
1652 info_ex = &info->full_info.info_ex;
1653 auth_info = &info->full_info.auth_info;
1654 break;
1655 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1656 auth_info_int = &info->auth_info_internal;
1657 break;
1658 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1659 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1660 info_ex = &info->full_info_internal.info_ex;
1661 auth_info_int = &info->full_info_internal.auth_info;
1662 break;
1663 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1664 enc_types = &info->enc_types.enc_types;
1665 break;
1666 default:
1667 return NT_STATUS_INVALID_PARAMETER;
1670 if (auth_info) {
1671 /* FIXME: not handled yet */
1672 return NT_STATUS_INVALID_PARAMETER;
1675 /* decode auth_info_int if set */
1676 if (auth_info_int) {
1678 /* now decrypt blob */
1679 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1680 auth_info_int->auth_blob.size);
1682 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1683 &auth_blob, &auth_struct);
1684 if (!NT_STATUS_IS_OK(nt_status)) {
1685 return nt_status;
1689 if (info_ex) {
1690 /* verify data matches */
1691 if (info_ex->trust_attributes &
1692 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1693 /* TODO: check what behavior level we have */
1694 if (strcasecmp_m(p_state->domain_dns,
1695 p_state->forest_dns) != 0) {
1696 return NT_STATUS_INVALID_DOMAIN_STATE;
1700 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1701 if (ret == LDB_SUCCESS && am_rodc) {
1702 return NT_STATUS_NO_SUCH_DOMAIN;
1705 /* verify only one object matches the dns/netbios/sid
1706 * triplet and that this is the one we already have */
1707 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1708 p_state->system_dn,
1709 info_ex->domain_name.string,
1710 info_ex->netbios_name.string,
1711 info_ex->sid, &msgs);
1712 if (!NT_STATUS_IS_OK(nt_status)) {
1713 return nt_status;
1715 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1716 return NT_STATUS_OBJECT_NAME_COLLISION;
1718 talloc_free(msgs);
1721 /* TODO: should we fetch previous values from the existing entry
1722 * and append them ? */
1723 if (auth_struct.incoming.count) {
1724 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1725 &auth_struct.incoming,
1726 &trustAuthIncoming);
1727 if (!NT_STATUS_IS_OK(nt_status)) {
1728 return nt_status;
1730 } else {
1731 trustAuthIncoming = data_blob(NULL, 0);
1734 if (auth_struct.outgoing.count) {
1735 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1736 &auth_struct.outgoing,
1737 &trustAuthOutgoing);
1738 if (!NT_STATUS_IS_OK(nt_status)) {
1739 return nt_status;
1741 } else {
1742 trustAuthOutgoing = data_blob(NULL, 0);
1745 msg = ldb_msg_new(mem_ctx);
1746 if (msg == NULL) {
1747 return NT_STATUS_NO_MEMORY;
1749 msg->dn = dom_msg->dn;
1751 if (posix_offset) {
1752 nt_status = update_uint32_t_value(mem_ctx, dom_msg, msg,
1753 "trustPosixOffset",
1754 *posix_offset, NULL);
1755 if (!NT_STATUS_IS_OK(nt_status)) {
1756 return nt_status;
1760 if (info_ex) {
1761 uint32_t origattrs;
1762 uint32_t origdir;
1763 uint32_t tmp;
1764 int origtype;
1766 nt_status = update_uint32_t_value(mem_ctx, dom_msg, msg,
1767 "trustDirection",
1768 info_ex->trust_direction,
1769 &origdir);
1770 if (!NT_STATUS_IS_OK(nt_status)) {
1771 return nt_status;
1774 tmp = info_ex->trust_direction ^ origdir;
1775 if (tmp & LSA_TRUST_DIRECTION_INBOUND) {
1776 if (origdir & LSA_TRUST_DIRECTION_INBOUND) {
1777 del_incoming = true;
1778 } else {
1779 add_incoming = true;
1782 if (tmp & LSA_TRUST_DIRECTION_OUTBOUND) {
1783 if (origdir & LSA_TRUST_DIRECTION_OUTBOUND) {
1784 del_outgoing = true;
1785 } else {
1786 add_outgoing = true;
1790 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1791 if (origtype == -1 || origtype != info_ex->trust_type) {
1792 DEBUG(1, ("Attempted to change trust type! "
1793 "Operation not handled\n"));
1794 return NT_STATUS_INVALID_PARAMETER;
1797 nt_status = update_uint32_t_value(mem_ctx, dom_msg, msg,
1798 "trustAttributes",
1799 info_ex->trust_attributes,
1800 &origattrs);
1801 if (!NT_STATUS_IS_OK(nt_status)) {
1802 return nt_status;
1804 /* TODO: check forestFunctionality from ldb opaque */
1805 /* TODO: check what is set makes sense */
1806 /* for now refuse changes */
1807 if (origattrs == -1 ||
1808 origattrs != info_ex->trust_attributes) {
1809 DEBUG(1, ("Attempted to change trust attributes! "
1810 "Operation not handled\n"));
1811 return NT_STATUS_INVALID_PARAMETER;
1815 if (enc_types) {
1816 nt_status = update_uint32_t_value(mem_ctx, dom_msg, msg,
1817 "msDS-SupportedEncryptionTypes",
1818 *enc_types, NULL);
1819 if (!NT_STATUS_IS_OK(nt_status)) {
1820 return nt_status;
1824 if (add_incoming && trustAuthIncoming.data) {
1825 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1826 LDB_FLAG_MOD_REPLACE, NULL);
1827 if (ret != LDB_SUCCESS) {
1828 return NT_STATUS_NO_MEMORY;
1830 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1831 &trustAuthIncoming, NULL);
1832 if (ret != LDB_SUCCESS) {
1833 return NT_STATUS_NO_MEMORY;
1836 if (add_outgoing && trustAuthOutgoing.data) {
1837 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1838 LDB_FLAG_MOD_REPLACE, NULL);
1839 if (ret != LDB_SUCCESS) {
1840 return NT_STATUS_NO_MEMORY;
1842 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1843 &trustAuthOutgoing, NULL);
1844 if (ret != LDB_SUCCESS) {
1845 return NT_STATUS_NO_MEMORY;
1849 /* start transaction */
1850 ret = ldb_transaction_start(p_state->sam_ldb);
1851 if (ret != LDB_SUCCESS) {
1852 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1854 in_transaction = true;
1856 ret = ldb_modify(p_state->sam_ldb, msg);
1857 if (ret != LDB_SUCCESS) {
1858 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1859 ldb_dn_get_linearized(msg->dn),
1860 ldb_errstring(p_state->sam_ldb)));
1861 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
1862 nt_status = NT_STATUS_ACCESS_DENIED;
1863 } else {
1864 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1866 goto done;
1869 if (add_incoming || del_incoming) {
1870 const char *netbios_name;
1872 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1873 "flatname", NULL);
1874 if (!netbios_name) {
1875 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1876 goto done;
1879 nt_status = update_trust_user(mem_ctx,
1880 p_state->sam_ldb,
1881 p_state->domain_dn,
1882 del_incoming,
1883 netbios_name,
1884 &auth_struct.incoming);
1885 if (!NT_STATUS_IS_OK(nt_status)) {
1886 goto done;
1890 /* ok, all fine, commit transaction and return */
1891 ret = ldb_transaction_commit(p_state->sam_ldb);
1892 if (ret != LDB_SUCCESS) {
1893 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1895 in_transaction = false;
1897 nt_status = NT_STATUS_OK;
1899 done:
1900 if (in_transaction) {
1901 ldb_transaction_cancel(p_state->sam_ldb);
1903 return nt_status;
1907 lsa_SetInfomrationTrustedDomain
1909 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1910 struct dcesrv_call_state *dce_call,
1911 TALLOC_CTX *mem_ctx,
1912 struct lsa_SetInformationTrustedDomain *r)
1914 struct dcesrv_handle *h;
1915 struct lsa_trusted_domain_state *td_state;
1916 struct ldb_message **msgs;
1917 NTSTATUS nt_status;
1919 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1920 LSA_HANDLE_TRUSTED_DOMAIN);
1922 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1924 /* get the trusted domain object */
1925 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1926 td_state->trusted_domain_dn,
1927 NULL, NULL, NULL, &msgs);
1928 if (!NT_STATUS_IS_OK(nt_status)) {
1929 if (NT_STATUS_EQUAL(nt_status,
1930 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1931 return nt_status;
1933 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1936 return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1937 msgs[0], r->in.level, r->in.info);
1942 lsa_DeleteTrustedDomain
1944 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1945 struct lsa_DeleteTrustedDomain *r)
1947 NTSTATUS status;
1948 struct lsa_OpenTrustedDomain opn;
1949 struct lsa_DeleteObject del;
1950 struct dcesrv_handle *h;
1952 opn.in.handle = r->in.handle;
1953 opn.in.sid = r->in.dom_sid;
1954 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1955 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1956 if (!opn.out.trustdom_handle) {
1957 return NT_STATUS_NO_MEMORY;
1959 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1960 if (!NT_STATUS_IS_OK(status)) {
1961 return status;
1964 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1965 talloc_steal(mem_ctx, h);
1967 del.in.handle = opn.out.trustdom_handle;
1968 del.out.handle = opn.out.trustdom_handle;
1969 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1970 if (!NT_STATUS_IS_OK(status)) {
1971 return status;
1973 return NT_STATUS_OK;
1976 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
1977 struct ldb_message *msg,
1978 struct lsa_TrustDomainInfoInfoEx *info_ex)
1980 info_ex->domain_name.string
1981 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1982 info_ex->netbios_name.string
1983 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1984 info_ex->sid
1985 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1986 info_ex->trust_direction
1987 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1988 info_ex->trust_type
1989 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1990 info_ex->trust_attributes
1991 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
1992 return NT_STATUS_OK;
1996 lsa_QueryTrustedDomainInfo
1998 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1999 struct lsa_QueryTrustedDomainInfo *r)
2001 union lsa_TrustedDomainInfo *info = NULL;
2002 struct dcesrv_handle *h;
2003 struct lsa_trusted_domain_state *trusted_domain_state;
2004 struct ldb_message *msg;
2005 int ret;
2006 struct ldb_message **res;
2007 const char *attrs[] = {
2008 "flatname",
2009 "trustPartner",
2010 "securityIdentifier",
2011 "trustDirection",
2012 "trustType",
2013 "trustAttributes",
2014 "msDs-supportedEncryptionTypes",
2015 NULL
2018 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2020 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2022 /* pull all the user attributes */
2023 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2024 trusted_domain_state->trusted_domain_dn, &res, attrs);
2025 if (ret != 1) {
2026 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2028 msg = res[0];
2030 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2031 if (!info) {
2032 return NT_STATUS_NO_MEMORY;
2034 *r->out.info = info;
2036 switch (r->in.level) {
2037 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2038 info->name.netbios_name.string
2039 = samdb_result_string(msg, "flatname", NULL);
2040 break;
2041 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2042 info->posix_offset.posix_offset
2043 = samdb_result_uint(msg, "posixOffset", 0);
2044 break;
2045 #if 0 /* Win2k3 doesn't implement this */
2046 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2047 r->out.info->info_basic.netbios_name.string
2048 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2049 r->out.info->info_basic.sid
2050 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2051 break;
2052 #endif
2053 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2054 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2056 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2057 ZERO_STRUCT(info->full_info);
2058 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2060 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2061 ZERO_STRUCT(info->full_info2_internal);
2062 info->full_info2_internal.posix_offset.posix_offset
2063 = samdb_result_uint(msg, "posixOffset", 0);
2064 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2066 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2067 info->enc_types.enc_types
2068 = samdb_result_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2069 break;
2071 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2072 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2073 /* oops, we don't want to return the info after all */
2074 talloc_free(info);
2075 *r->out.info = NULL;
2076 return NT_STATUS_INVALID_PARAMETER;
2077 default:
2078 /* oops, we don't want to return the info after all */
2079 talloc_free(info);
2080 *r->out.info = NULL;
2081 return NT_STATUS_INVALID_INFO_CLASS;
2084 return NT_STATUS_OK;
2089 lsa_QueryTrustedDomainInfoBySid
2091 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2092 struct lsa_QueryTrustedDomainInfoBySid *r)
2094 NTSTATUS status;
2095 struct lsa_OpenTrustedDomain opn;
2096 struct lsa_QueryTrustedDomainInfo query;
2097 struct dcesrv_handle *h;
2099 opn.in.handle = r->in.handle;
2100 opn.in.sid = r->in.dom_sid;
2101 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2102 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2103 if (!opn.out.trustdom_handle) {
2104 return NT_STATUS_NO_MEMORY;
2106 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2107 if (!NT_STATUS_IS_OK(status)) {
2108 return status;
2111 /* Ensure this handle goes away at the end of this call */
2112 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2113 talloc_steal(mem_ctx, h);
2115 query.in.trustdom_handle = opn.out.trustdom_handle;
2116 query.in.level = r->in.level;
2117 query.out.info = r->out.info;
2118 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2119 if (!NT_STATUS_IS_OK(status)) {
2120 return status;
2123 return NT_STATUS_OK;
2127 lsa_SetTrustedDomainInfoByName
2129 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2130 TALLOC_CTX *mem_ctx,
2131 struct lsa_SetTrustedDomainInfoByName *r)
2133 struct dcesrv_handle *policy_handle;
2134 struct lsa_policy_state *policy_state;
2135 struct ldb_message **msgs;
2136 NTSTATUS nt_status;
2138 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2139 policy_state = policy_handle->data;
2141 /* get the trusted domain object */
2142 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2143 policy_state->domain_dn,
2144 r->in.trusted_domain->string,
2145 r->in.trusted_domain->string,
2146 NULL, &msgs);
2147 if (!NT_STATUS_IS_OK(nt_status)) {
2148 if (NT_STATUS_EQUAL(nt_status,
2149 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2150 return nt_status;
2152 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2155 return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2156 msgs[0], r->in.level, r->in.info);
2160 lsa_QueryTrustedDomainInfoByName
2162 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2163 TALLOC_CTX *mem_ctx,
2164 struct lsa_QueryTrustedDomainInfoByName *r)
2166 NTSTATUS status;
2167 struct lsa_OpenTrustedDomainByName opn;
2168 struct lsa_QueryTrustedDomainInfo query;
2169 struct dcesrv_handle *h;
2171 opn.in.handle = r->in.handle;
2172 opn.in.name = *r->in.trusted_domain;
2173 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2174 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2175 if (!opn.out.trustdom_handle) {
2176 return NT_STATUS_NO_MEMORY;
2178 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2179 if (!NT_STATUS_IS_OK(status)) {
2180 return status;
2183 /* Ensure this handle goes away at the end of this call */
2184 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2185 talloc_steal(mem_ctx, h);
2187 query.in.trustdom_handle = opn.out.trustdom_handle;
2188 query.in.level = r->in.level;
2189 query.out.info = r->out.info;
2190 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2191 if (!NT_STATUS_IS_OK(status)) {
2192 return status;
2195 return NT_STATUS_OK;
2199 lsa_CloseTrustedDomainEx
2201 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2202 TALLOC_CTX *mem_ctx,
2203 struct lsa_CloseTrustedDomainEx *r)
2205 /* The result of a bad hair day from an IDL programmer? Not
2206 * implmented in Win2k3. You should always just lsa_Close
2207 * anyway. */
2208 return NT_STATUS_NOT_IMPLEMENTED;
2213 comparison function for sorting lsa_DomainInformation array
2215 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2217 return strcasecmp_m(e1->name.string, e2->name.string);
2221 lsa_EnumTrustDom
2223 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2224 struct lsa_EnumTrustDom *r)
2226 struct dcesrv_handle *policy_handle;
2227 struct lsa_DomainInfo *entries;
2228 struct lsa_policy_state *policy_state;
2229 struct ldb_message **domains;
2230 const char *attrs[] = {
2231 "flatname",
2232 "securityIdentifier",
2233 NULL
2237 int count, i;
2239 *r->out.resume_handle = 0;
2241 r->out.domains->domains = NULL;
2242 r->out.domains->count = 0;
2244 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2246 policy_state = policy_handle->data;
2248 /* search for all users in this domain. This could possibly be cached and
2249 resumed based on resume_key */
2250 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2251 "objectclass=trustedDomain");
2252 if (count < 0) {
2253 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2256 /* convert to lsa_TrustInformation format */
2257 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2258 if (!entries) {
2259 return NT_STATUS_NO_MEMORY;
2261 for (i=0;i<count;i++) {
2262 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2263 entries[i].name.string = samdb_result_string(domains[i], "flatname", NULL);
2266 /* sort the results by name */
2267 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2269 if (*r->in.resume_handle >= count) {
2270 *r->out.resume_handle = -1;
2272 return NT_STATUS_NO_MORE_ENTRIES;
2275 /* return the rest, limit by max_size. Note that we
2276 use the w2k3 element size value of 60 */
2277 r->out.domains->count = count - *r->in.resume_handle;
2278 r->out.domains->count = MIN(r->out.domains->count,
2279 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2281 r->out.domains->domains = entries + *r->in.resume_handle;
2282 r->out.domains->count = r->out.domains->count;
2284 if (r->out.domains->count < count - *r->in.resume_handle) {
2285 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2286 return STATUS_MORE_ENTRIES;
2289 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2290 * always be larger than the previous input resume handle, in
2291 * particular when hitting the last query it is vital to set the
2292 * resume handle correctly to avoid infinite client loops, as
2293 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2294 * status is NT_STATUS_OK - gd */
2296 *r->out.resume_handle = (uint32_t)-1;
2298 return NT_STATUS_OK;
2302 comparison function for sorting lsa_DomainInformation array
2304 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2306 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2310 lsa_EnumTrustedDomainsEx
2312 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2313 struct lsa_EnumTrustedDomainsEx *r)
2315 struct dcesrv_handle *policy_handle;
2316 struct lsa_TrustDomainInfoInfoEx *entries;
2317 struct lsa_policy_state *policy_state;
2318 struct ldb_message **domains;
2319 const char *attrs[] = {
2320 "flatname",
2321 "trustPartner",
2322 "securityIdentifier",
2323 "trustDirection",
2324 "trustType",
2325 "trustAttributes",
2326 NULL
2328 NTSTATUS nt_status;
2330 int count, i;
2332 *r->out.resume_handle = 0;
2334 r->out.domains->domains = NULL;
2335 r->out.domains->count = 0;
2337 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2339 policy_state = policy_handle->data;
2341 /* search for all users in this domain. This could possibly be cached and
2342 resumed based on resume_key */
2343 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2344 "objectclass=trustedDomain");
2345 if (count < 0) {
2346 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2349 /* convert to lsa_DomainInformation format */
2350 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2351 if (!entries) {
2352 return NT_STATUS_NO_MEMORY;
2354 for (i=0;i<count;i++) {
2355 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2356 if (!NT_STATUS_IS_OK(nt_status)) {
2357 return nt_status;
2361 /* sort the results by name */
2362 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2364 if (*r->in.resume_handle >= count) {
2365 *r->out.resume_handle = -1;
2367 return NT_STATUS_NO_MORE_ENTRIES;
2370 /* return the rest, limit by max_size. Note that we
2371 use the w2k3 element size value of 60 */
2372 r->out.domains->count = count - *r->in.resume_handle;
2373 r->out.domains->count = MIN(r->out.domains->count,
2374 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2376 r->out.domains->domains = entries + *r->in.resume_handle;
2377 r->out.domains->count = r->out.domains->count;
2379 if (r->out.domains->count < count - *r->in.resume_handle) {
2380 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2381 return STATUS_MORE_ENTRIES;
2384 return NT_STATUS_OK;
2389 lsa_OpenAccount
2391 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2392 struct lsa_OpenAccount *r)
2394 struct dcesrv_handle *h, *ah;
2395 struct lsa_policy_state *state;
2396 struct lsa_account_state *astate;
2398 ZERO_STRUCTP(r->out.acct_handle);
2400 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2402 state = h->data;
2404 astate = talloc(dce_call->conn, struct lsa_account_state);
2405 if (astate == NULL) {
2406 return NT_STATUS_NO_MEMORY;
2409 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2410 if (astate->account_sid == NULL) {
2411 talloc_free(astate);
2412 return NT_STATUS_NO_MEMORY;
2415 astate->policy = talloc_reference(astate, state);
2416 astate->access_mask = r->in.access_mask;
2418 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2419 if (!ah) {
2420 talloc_free(astate);
2421 return NT_STATUS_NO_MEMORY;
2424 ah->data = talloc_steal(ah, astate);
2426 *r->out.acct_handle = ah->wire_handle;
2428 return NT_STATUS_OK;
2433 lsa_EnumPrivsAccount
2435 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2436 TALLOC_CTX *mem_ctx,
2437 struct lsa_EnumPrivsAccount *r)
2439 struct dcesrv_handle *h;
2440 struct lsa_account_state *astate;
2441 int ret;
2442 unsigned int i;
2443 struct ldb_message **res;
2444 const char * const attrs[] = { "privilege", NULL};
2445 struct ldb_message_element *el;
2446 const char *sidstr;
2447 struct lsa_PrivilegeSet *privs;
2449 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2451 astate = h->data;
2453 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2454 if (privs == NULL) {
2455 return NT_STATUS_NO_MEMORY;
2457 privs->count = 0;
2458 privs->unknown = 0;
2459 privs->set = NULL;
2461 *r->out.privs = privs;
2463 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2464 if (sidstr == NULL) {
2465 return NT_STATUS_NO_MEMORY;
2468 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2469 "objectSid=%s", sidstr);
2470 if (ret < 0) {
2471 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2473 if (ret != 1) {
2474 return NT_STATUS_OK;
2477 el = ldb_msg_find_element(res[0], "privilege");
2478 if (el == NULL || el->num_values == 0) {
2479 return NT_STATUS_OK;
2482 privs->set = talloc_array(privs,
2483 struct lsa_LUIDAttribute, el->num_values);
2484 if (privs->set == NULL) {
2485 return NT_STATUS_NO_MEMORY;
2488 for (i=0;i<el->num_values;i++) {
2489 int id = sec_privilege_id((const char *)el->values[i].data);
2490 if (id == -1) {
2491 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2493 privs->set[i].attribute = 0;
2494 privs->set[i].luid.low = id;
2495 privs->set[i].luid.high = 0;
2498 privs->count = el->num_values;
2500 return NT_STATUS_OK;
2504 lsa_EnumAccountRights
2506 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2507 TALLOC_CTX *mem_ctx,
2508 struct lsa_EnumAccountRights *r)
2510 struct dcesrv_handle *h;
2511 struct lsa_policy_state *state;
2512 int ret;
2513 unsigned int i;
2514 struct ldb_message **res;
2515 const char * const attrs[] = { "privilege", NULL};
2516 const char *sidstr;
2517 struct ldb_message_element *el;
2519 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2521 state = h->data;
2523 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2524 if (sidstr == NULL) {
2525 return NT_STATUS_NO_MEMORY;
2528 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2529 "(&(objectSid=%s)(privilege=*))", sidstr);
2530 if (ret == 0) {
2531 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2533 if (ret != 1) {
2534 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2535 dom_sid_string(mem_ctx, r->in.sid),
2536 ldb_errstring(state->pdb)));
2537 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2540 el = ldb_msg_find_element(res[0], "privilege");
2541 if (el == NULL || el->num_values == 0) {
2542 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2545 r->out.rights->count = el->num_values;
2546 r->out.rights->names = talloc_array(r->out.rights,
2547 struct lsa_StringLarge, r->out.rights->count);
2548 if (r->out.rights->names == NULL) {
2549 return NT_STATUS_NO_MEMORY;
2552 for (i=0;i<el->num_values;i++) {
2553 r->out.rights->names[i].string = (const char *)el->values[i].data;
2556 return NT_STATUS_OK;
2562 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2564 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2565 TALLOC_CTX *mem_ctx,
2566 struct lsa_policy_state *state,
2567 int ldb_flag,
2568 struct dom_sid *sid,
2569 const struct lsa_RightSet *rights)
2571 const char *sidstr, *sidndrstr;
2572 struct ldb_message *msg;
2573 struct ldb_message_element *el;
2574 int ret;
2575 uint32_t i;
2576 struct lsa_EnumAccountRights r2;
2577 char *dnstr;
2579 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2580 SECURITY_ADMINISTRATOR) {
2581 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2582 return NT_STATUS_ACCESS_DENIED;
2585 msg = ldb_msg_new(mem_ctx);
2586 if (msg == NULL) {
2587 return NT_STATUS_NO_MEMORY;
2590 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2591 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
2593 sidstr = dom_sid_string(msg, sid);
2594 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
2596 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2597 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
2599 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2600 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
2602 if (ldb_flag == LDB_FLAG_MOD_ADD) {
2603 NTSTATUS status;
2605 r2.in.handle = &state->handle->wire_handle;
2606 r2.in.sid = sid;
2607 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2609 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2610 if (!NT_STATUS_IS_OK(status)) {
2611 ZERO_STRUCTP(r2.out.rights);
2615 for (i=0;i<rights->count;i++) {
2616 if (sec_privilege_id(rights->names[i].string) == -1) {
2617 talloc_free(msg);
2618 return NT_STATUS_NO_SUCH_PRIVILEGE;
2621 if (ldb_flag == LDB_FLAG_MOD_ADD) {
2622 uint32_t j;
2623 for (j=0;j<r2.out.rights->count;j++) {
2624 if (strcasecmp_m(r2.out.rights->names[j].string,
2625 rights->names[i].string) == 0) {
2626 break;
2629 if (j != r2.out.rights->count) continue;
2632 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2633 if (ret != LDB_SUCCESS) {
2634 talloc_free(msg);
2635 return NT_STATUS_NO_MEMORY;
2639 el = ldb_msg_find_element(msg, "privilege");
2640 if (!el) {
2641 talloc_free(msg);
2642 return NT_STATUS_OK;
2645 el->flags = ldb_flag;
2647 ret = ldb_modify(state->pdb, msg);
2648 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2649 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2650 talloc_free(msg);
2651 return NT_STATUS_NO_MEMORY;
2653 samdb_msg_add_string(state->pdb, msg, msg, "comment", "added via LSA");
2654 ret = ldb_add(state->pdb, msg);
2656 if (ret != LDB_SUCCESS) {
2657 if (ldb_flag == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2658 talloc_free(msg);
2659 return NT_STATUS_OK;
2661 DEBUG(3, ("Could not %s attributes from %s: %s",
2662 ldb_flag == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2663 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2664 talloc_free(msg);
2665 return NT_STATUS_UNEXPECTED_IO_ERROR;
2668 talloc_free(msg);
2669 return NT_STATUS_OK;
2673 lsa_AddPrivilegesToAccount
2675 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2676 struct lsa_AddPrivilegesToAccount *r)
2678 struct lsa_RightSet rights;
2679 struct dcesrv_handle *h;
2680 struct lsa_account_state *astate;
2681 uint32_t i;
2683 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2685 astate = h->data;
2687 rights.count = r->in.privs->count;
2688 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2689 if (rights.names == NULL) {
2690 return NT_STATUS_NO_MEMORY;
2692 for (i=0;i<rights.count;i++) {
2693 int id = r->in.privs->set[i].luid.low;
2694 if (r->in.privs->set[i].luid.high) {
2695 return NT_STATUS_NO_SUCH_PRIVILEGE;
2697 rights.names[i].string = sec_privilege_name(id);
2698 if (rights.names[i].string == NULL) {
2699 return NT_STATUS_NO_SUCH_PRIVILEGE;
2703 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2704 LDB_FLAG_MOD_ADD, astate->account_sid,
2705 &rights);
2710 lsa_RemovePrivilegesFromAccount
2712 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2713 struct lsa_RemovePrivilegesFromAccount *r)
2715 struct lsa_RightSet *rights;
2716 struct dcesrv_handle *h;
2717 struct lsa_account_state *astate;
2718 uint32_t i;
2720 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2722 astate = h->data;
2724 rights = talloc(mem_ctx, struct lsa_RightSet);
2726 if (r->in.remove_all == 1 &&
2727 r->in.privs == NULL) {
2728 struct lsa_EnumAccountRights r2;
2729 NTSTATUS status;
2731 r2.in.handle = &astate->policy->handle->wire_handle;
2732 r2.in.sid = astate->account_sid;
2733 r2.out.rights = rights;
2735 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2736 if (!NT_STATUS_IS_OK(status)) {
2737 return status;
2740 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2741 LDB_FLAG_MOD_DELETE, astate->account_sid,
2742 r2.out.rights);
2745 if (r->in.remove_all != 0) {
2746 return NT_STATUS_INVALID_PARAMETER;
2749 rights->count = r->in.privs->count;
2750 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2751 if (rights->names == NULL) {
2752 return NT_STATUS_NO_MEMORY;
2754 for (i=0;i<rights->count;i++) {
2755 int id = r->in.privs->set[i].luid.low;
2756 if (r->in.privs->set[i].luid.high) {
2757 return NT_STATUS_NO_SUCH_PRIVILEGE;
2759 rights->names[i].string = sec_privilege_name(id);
2760 if (rights->names[i].string == NULL) {
2761 return NT_STATUS_NO_SUCH_PRIVILEGE;
2765 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2766 LDB_FLAG_MOD_DELETE, astate->account_sid,
2767 rights);
2772 lsa_GetQuotasForAccount
2774 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2775 struct lsa_GetQuotasForAccount *r)
2777 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2782 lsa_SetQuotasForAccount
2784 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2785 struct lsa_SetQuotasForAccount *r)
2787 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2792 lsa_GetSystemAccessAccount
2794 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2795 struct lsa_GetSystemAccessAccount *r)
2797 uint32_t i;
2798 NTSTATUS status;
2799 struct lsa_EnumPrivsAccount enumPrivs;
2800 struct lsa_PrivilegeSet *privs;
2802 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2803 if (!privs) {
2804 return NT_STATUS_NO_MEMORY;
2806 privs->count = 0;
2807 privs->unknown = 0;
2808 privs->set = NULL;
2810 enumPrivs.in.handle = r->in.handle;
2811 enumPrivs.out.privs = &privs;
2813 status = dcesrv_lsa_EnumPrivsAccount(dce_call, mem_ctx, &enumPrivs);
2814 if (!NT_STATUS_IS_OK(status)) {
2815 return status;
2818 *(r->out.access_mask) = 0x00000000;
2820 for (i = 0; i < privs->count; i++) {
2821 int priv = privs->set[i].luid.low;
2823 switch (priv) {
2824 case SEC_PRIV_INTERACTIVE_LOGON:
2825 *(r->out.access_mask) |= LSA_POLICY_MODE_INTERACTIVE;
2826 break;
2827 case SEC_PRIV_NETWORK_LOGON:
2828 *(r->out.access_mask) |= LSA_POLICY_MODE_NETWORK;
2829 break;
2830 case SEC_PRIV_REMOTE_INTERACTIVE_LOGON:
2831 *(r->out.access_mask) |= LSA_POLICY_MODE_REMOTE_INTERACTIVE;
2832 break;
2836 return NT_STATUS_OK;
2841 lsa_SetSystemAccessAccount
2843 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2844 struct lsa_SetSystemAccessAccount *r)
2846 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2851 lsa_CreateSecret
2853 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2854 struct lsa_CreateSecret *r)
2856 struct dcesrv_handle *policy_handle;
2857 struct lsa_policy_state *policy_state;
2858 struct lsa_secret_state *secret_state;
2859 struct dcesrv_handle *handle;
2860 struct ldb_message **msgs, *msg;
2861 const char *attrs[] = {
2862 NULL
2865 const char *name;
2867 int ret;
2869 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2870 ZERO_STRUCTP(r->out.sec_handle);
2872 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2874 case SECURITY_SYSTEM:
2875 case SECURITY_ADMINISTRATOR:
2876 break;
2877 default:
2878 /* Users and annonymous are not allowed create secrets */
2879 return NT_STATUS_ACCESS_DENIED;
2882 policy_state = policy_handle->data;
2884 if (!r->in.name.string) {
2885 return NT_STATUS_INVALID_PARAMETER;
2888 secret_state = talloc(mem_ctx, struct lsa_secret_state);
2889 if (!secret_state) {
2890 return NT_STATUS_NO_MEMORY;
2892 secret_state->policy = policy_state;
2894 msg = ldb_msg_new(mem_ctx);
2895 if (msg == NULL) {
2896 return NT_STATUS_NO_MEMORY;
2899 if (strncmp("G$", r->in.name.string, 2) == 0) {
2900 const char *name2;
2901 name = &r->in.name.string[2];
2902 /* 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) */
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)));
2905 secret_state->global = true;
2907 if (strlen(name) < 1) {
2908 return NT_STATUS_INVALID_PARAMETER;
2911 name2 = talloc_asprintf(mem_ctx, "%s Secret", ldb_binary_encode_string(mem_ctx, name));
2912 /* search for the secret record */
2913 ret = gendb_search(secret_state->sam_ldb,
2914 mem_ctx, policy_state->system_dn, &msgs, attrs,
2915 "(&(cn=%s)(objectclass=secret))",
2916 name2);
2917 if (ret > 0) {
2918 return NT_STATUS_OBJECT_NAME_COLLISION;
2921 if (ret < 0) {
2922 DEBUG(0,("Failure searching for CN=%s: %s\n",
2923 name2, ldb_errstring(secret_state->sam_ldb)));
2924 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2927 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2928 if (!name2 || ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2929 return NT_STATUS_NO_MEMORY;
2932 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name2);
2934 } else {
2935 secret_state->global = false;
2937 name = r->in.name.string;
2938 if (strlen(name) < 1) {
2939 return NT_STATUS_INVALID_PARAMETER;
2942 secret_state->sam_ldb = talloc_reference(secret_state,
2943 secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
2944 /* search for the secret record */
2945 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2946 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2947 &msgs, attrs,
2948 "(&(cn=%s)(objectclass=secret))",
2949 ldb_binary_encode_string(mem_ctx, name));
2950 if (ret > 0) {
2951 return NT_STATUS_OBJECT_NAME_COLLISION;
2954 if (ret < 0) {
2955 DEBUG(0,("Failure searching for CN=%s: %s\n",
2956 name, ldb_errstring(secret_state->sam_ldb)));
2957 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2960 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb, "cn=%s,cn=LSA Secrets", name);
2961 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name);
2964 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "objectClass", "secret");
2966 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2968 /* create the secret */
2969 ret = ldb_add(secret_state->sam_ldb, msg);
2970 if (ret != LDB_SUCCESS) {
2971 DEBUG(0,("Failed to create secret record %s: %s\n",
2972 ldb_dn_get_linearized(msg->dn),
2973 ldb_errstring(secret_state->sam_ldb)));
2974 return NT_STATUS_ACCESS_DENIED;
2977 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2978 if (!handle) {
2979 return NT_STATUS_NO_MEMORY;
2982 handle->data = talloc_steal(handle, secret_state);
2984 secret_state->access_mask = r->in.access_mask;
2985 secret_state->policy = talloc_reference(secret_state, policy_state);
2987 *r->out.sec_handle = handle->wire_handle;
2989 return NT_STATUS_OK;
2994 lsa_OpenSecret
2996 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2997 struct lsa_OpenSecret *r)
2999 struct dcesrv_handle *policy_handle;
3001 struct lsa_policy_state *policy_state;
3002 struct lsa_secret_state *secret_state;
3003 struct dcesrv_handle *handle;
3004 struct ldb_message **msgs;
3005 const char *attrs[] = {
3006 NULL
3009 const char *name;
3011 int ret;
3013 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3014 ZERO_STRUCTP(r->out.sec_handle);
3015 policy_state = policy_handle->data;
3017 if (!r->in.name.string) {
3018 return NT_STATUS_INVALID_PARAMETER;
3021 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3023 case SECURITY_SYSTEM:
3024 case SECURITY_ADMINISTRATOR:
3025 break;
3026 default:
3027 /* Users and annonymous are not allowed to access secrets */
3028 return NT_STATUS_ACCESS_DENIED;
3031 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3032 if (!secret_state) {
3033 return NT_STATUS_NO_MEMORY;
3035 secret_state->policy = policy_state;
3037 if (strncmp("G$", r->in.name.string, 2) == 0) {
3038 name = &r->in.name.string[2];
3039 /* 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) */
3040 secret_state->sam_ldb = talloc_reference(secret_state,
3041 samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx)));
3042 secret_state->global = true;
3044 if (strlen(name) < 1) {
3045 return NT_STATUS_INVALID_PARAMETER;
3048 /* search for the secret record */
3049 ret = gendb_search(secret_state->sam_ldb,
3050 mem_ctx, policy_state->system_dn, &msgs, attrs,
3051 "(&(cn=%s Secret)(objectclass=secret))",
3052 ldb_binary_encode_string(mem_ctx, name));
3053 if (ret == 0) {
3054 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3057 if (ret != 1) {
3058 DEBUG(0,("Found %d records matching DN %s\n", ret,
3059 ldb_dn_get_linearized(policy_state->system_dn)));
3060 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3063 } else {
3064 secret_state->global = false;
3065 secret_state->sam_ldb = talloc_reference(secret_state,
3066 secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
3068 name = r->in.name.string;
3069 if (strlen(name) < 1) {
3070 return NT_STATUS_INVALID_PARAMETER;
3073 /* search for the secret record */
3074 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3075 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3076 &msgs, attrs,
3077 "(&(cn=%s)(objectclass=secret))",
3078 ldb_binary_encode_string(mem_ctx, name));
3079 if (ret == 0) {
3080 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3083 if (ret != 1) {
3084 DEBUG(0,("Found %d records matching CN=%s\n",
3085 ret, ldb_binary_encode_string(mem_ctx, name)));
3086 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3090 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3092 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3093 if (!handle) {
3094 return NT_STATUS_NO_MEMORY;
3097 handle->data = talloc_steal(handle, secret_state);
3099 secret_state->access_mask = r->in.access_mask;
3100 secret_state->policy = talloc_reference(secret_state, policy_state);
3102 *r->out.sec_handle = handle->wire_handle;
3104 return NT_STATUS_OK;
3109 lsa_SetSecret
3111 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3112 struct lsa_SetSecret *r)
3115 struct dcesrv_handle *h;
3116 struct lsa_secret_state *secret_state;
3117 struct ldb_message *msg;
3118 DATA_BLOB session_key;
3119 DATA_BLOB crypt_secret, secret;
3120 struct ldb_val val;
3121 int ret;
3122 NTSTATUS status = NT_STATUS_OK;
3124 struct timeval now = timeval_current();
3125 NTTIME nt_now = timeval_to_nttime(&now);
3127 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3129 secret_state = h->data;
3131 msg = ldb_msg_new(mem_ctx);
3132 if (msg == NULL) {
3133 return NT_STATUS_NO_MEMORY;
3136 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3137 if (!msg->dn) {
3138 return NT_STATUS_NO_MEMORY;
3140 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3141 if (!NT_STATUS_IS_OK(status)) {
3142 return status;
3145 if (r->in.old_val) {
3146 /* Decrypt */
3147 crypt_secret.data = r->in.old_val->data;
3148 crypt_secret.length = r->in.old_val->size;
3150 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3151 if (!NT_STATUS_IS_OK(status)) {
3152 return status;
3155 val.data = secret.data;
3156 val.length = secret.length;
3158 /* set value */
3159 if (samdb_msg_add_value(secret_state->sam_ldb,
3160 mem_ctx, msg, "priorValue", &val) != LDB_SUCCESS) {
3161 return NT_STATUS_NO_MEMORY;
3164 /* set old value mtime */
3165 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3166 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3167 return NT_STATUS_NO_MEMORY;
3170 } else {
3171 /* If the old value is not set, then migrate the
3172 * current value to the old value */
3173 const struct ldb_val *old_val;
3174 NTTIME last_set_time;
3175 struct ldb_message **res;
3176 const char *attrs[] = {
3177 "currentValue",
3178 "lastSetTime",
3179 NULL
3182 /* search for the secret record */
3183 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3184 secret_state->secret_dn, &res, attrs);
3185 if (ret == 0) {
3186 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3189 if (ret != 1) {
3190 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3191 ldb_dn_get_linearized(secret_state->secret_dn)));
3192 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3195 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3196 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3198 if (old_val) {
3199 /* set old value */
3200 if (samdb_msg_add_value(secret_state->sam_ldb,
3201 mem_ctx, msg, "priorValue",
3202 old_val) != 0) {
3203 return NT_STATUS_NO_MEMORY;
3205 } else {
3206 if (samdb_msg_add_delete(secret_state->sam_ldb,
3207 mem_ctx, msg, "priorValue")) {
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 (samdb_msg_add_value(secret_state->sam_ldb,
3242 mem_ctx, msg, "currentValue", &val) != LDB_SUCCESS) {
3243 return NT_STATUS_NO_MEMORY;
3246 /* set new value mtime */
3247 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3248 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3249 return NT_STATUS_NO_MEMORY;
3252 } else {
3253 /* NULL out the NEW value */
3254 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3255 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3256 return NT_STATUS_NO_MEMORY;
3258 if (samdb_msg_add_delete(secret_state->sam_ldb,
3259 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3260 return NT_STATUS_NO_MEMORY;
3264 /* modify the samdb record */
3265 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3266 if (ret != LDB_SUCCESS) {
3267 /* we really need samdb.c to return NTSTATUS */
3268 return NT_STATUS_UNSUCCESSFUL;
3271 return NT_STATUS_OK;
3276 lsa_QuerySecret
3278 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3279 struct lsa_QuerySecret *r)
3281 struct dcesrv_handle *h;
3282 struct lsa_secret_state *secret_state;
3283 struct ldb_message *msg;
3284 DATA_BLOB session_key;
3285 DATA_BLOB crypt_secret, secret;
3286 int ret;
3287 struct ldb_message **res;
3288 const char *attrs[] = {
3289 "currentValue",
3290 "priorValue",
3291 "lastSetTime",
3292 "priorSetTime",
3293 NULL
3296 NTSTATUS nt_status;
3298 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3300 /* Ensure user is permitted to read this... */
3301 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3303 case SECURITY_SYSTEM:
3304 case SECURITY_ADMINISTRATOR:
3305 break;
3306 default:
3307 /* Users and annonymous are not allowed to read secrets */
3308 return NT_STATUS_ACCESS_DENIED;
3311 secret_state = h->data;
3313 /* pull all the user attributes */
3314 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3315 secret_state->secret_dn, &res, attrs);
3316 if (ret != 1) {
3317 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3319 msg = res[0];
3321 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3322 if (!NT_STATUS_IS_OK(nt_status)) {
3323 return nt_status;
3326 if (r->in.old_val) {
3327 const struct ldb_val *prior_val;
3328 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3329 if (!r->out.old_val) {
3330 return NT_STATUS_NO_MEMORY;
3332 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
3334 if (prior_val && prior_val->length) {
3335 secret.data = prior_val->data;
3336 secret.length = prior_val->length;
3338 /* Encrypt */
3339 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3340 if (!crypt_secret.length) {
3341 return NT_STATUS_NO_MEMORY;
3343 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3344 if (!r->out.old_val->buf) {
3345 return NT_STATUS_NO_MEMORY;
3347 r->out.old_val->buf->size = crypt_secret.length;
3348 r->out.old_val->buf->length = crypt_secret.length;
3349 r->out.old_val->buf->data = crypt_secret.data;
3353 if (r->in.old_mtime) {
3354 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3355 if (!r->out.old_mtime) {
3356 return NT_STATUS_NO_MEMORY;
3358 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
3361 if (r->in.new_val) {
3362 const struct ldb_val *new_val;
3363 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3364 if (!r->out.new_val) {
3365 return NT_STATUS_NO_MEMORY;
3368 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3370 if (new_val && new_val->length) {
3371 secret.data = new_val->data;
3372 secret.length = new_val->length;
3374 /* Encrypt */
3375 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3376 if (!crypt_secret.length) {
3377 return NT_STATUS_NO_MEMORY;
3379 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3380 if (!r->out.new_val->buf) {
3381 return NT_STATUS_NO_MEMORY;
3383 r->out.new_val->buf->length = crypt_secret.length;
3384 r->out.new_val->buf->size = crypt_secret.length;
3385 r->out.new_val->buf->data = crypt_secret.data;
3389 if (r->in.new_mtime) {
3390 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3391 if (!r->out.new_mtime) {
3392 return NT_STATUS_NO_MEMORY;
3394 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3397 return NT_STATUS_OK;
3402 lsa_LookupPrivValue
3404 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3405 TALLOC_CTX *mem_ctx,
3406 struct lsa_LookupPrivValue *r)
3408 struct dcesrv_handle *h;
3409 struct lsa_policy_state *state;
3410 int id;
3412 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3414 state = h->data;
3416 id = sec_privilege_id(r->in.name->string);
3417 if (id == -1) {
3418 return NT_STATUS_NO_SUCH_PRIVILEGE;
3421 r->out.luid->low = id;
3422 r->out.luid->high = 0;
3424 return NT_STATUS_OK;
3429 lsa_LookupPrivName
3431 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3432 TALLOC_CTX *mem_ctx,
3433 struct lsa_LookupPrivName *r)
3435 struct dcesrv_handle *h;
3436 struct lsa_policy_state *state;
3437 struct lsa_StringLarge *name;
3438 const char *privname;
3440 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3442 state = h->data;
3444 if (r->in.luid->high != 0) {
3445 return NT_STATUS_NO_SUCH_PRIVILEGE;
3448 privname = sec_privilege_name(r->in.luid->low);
3449 if (privname == NULL) {
3450 return NT_STATUS_NO_SUCH_PRIVILEGE;
3453 name = talloc(mem_ctx, struct lsa_StringLarge);
3454 if (name == NULL) {
3455 return NT_STATUS_NO_MEMORY;
3458 name->string = privname;
3460 *r->out.name = name;
3462 return NT_STATUS_OK;
3467 lsa_LookupPrivDisplayName
3469 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3470 TALLOC_CTX *mem_ctx,
3471 struct lsa_LookupPrivDisplayName *r)
3473 struct dcesrv_handle *h;
3474 struct lsa_policy_state *state;
3475 struct lsa_StringLarge *disp_name = NULL;
3476 int id;
3478 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3480 state = h->data;
3482 id = sec_privilege_id(r->in.name->string);
3483 if (id == -1) {
3484 return NT_STATUS_NO_SUCH_PRIVILEGE;
3487 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3488 if (disp_name == NULL) {
3489 return NT_STATUS_NO_MEMORY;
3492 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3493 if (disp_name->string == NULL) {
3494 return NT_STATUS_INTERNAL_ERROR;
3497 *r->out.disp_name = disp_name;
3498 *r->out.returned_language_id = 0;
3500 return NT_STATUS_OK;
3505 lsa_EnumAccountsWithUserRight
3507 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3508 TALLOC_CTX *mem_ctx,
3509 struct lsa_EnumAccountsWithUserRight *r)
3511 struct dcesrv_handle *h;
3512 struct lsa_policy_state *state;
3513 int ret, i;
3514 struct ldb_message **res;
3515 const char * const attrs[] = { "objectSid", NULL};
3516 const char *privname;
3518 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3520 state = h->data;
3522 if (r->in.name == NULL) {
3523 return NT_STATUS_NO_SUCH_PRIVILEGE;
3526 privname = r->in.name->string;
3527 if (sec_privilege_id(privname) == -1) {
3528 return NT_STATUS_NO_SUCH_PRIVILEGE;
3531 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3532 "privilege=%s", privname);
3533 if (ret < 0) {
3534 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3536 if (ret == 0) {
3537 return NT_STATUS_NO_MORE_ENTRIES;
3540 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3541 if (r->out.sids->sids == NULL) {
3542 return NT_STATUS_NO_MEMORY;
3544 for (i=0;i<ret;i++) {
3545 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3546 res[i], "objectSid");
3547 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3549 r->out.sids->num_sids = ret;
3551 return NT_STATUS_OK;
3556 lsa_AddAccountRights
3558 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3559 TALLOC_CTX *mem_ctx,
3560 struct lsa_AddAccountRights *r)
3562 struct dcesrv_handle *h;
3563 struct lsa_policy_state *state;
3565 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3567 state = h->data;
3569 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3570 LDB_FLAG_MOD_ADD,
3571 r->in.sid, r->in.rights);
3576 lsa_RemoveAccountRights
3578 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3579 TALLOC_CTX *mem_ctx,
3580 struct lsa_RemoveAccountRights *r)
3582 struct dcesrv_handle *h;
3583 struct lsa_policy_state *state;
3585 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3587 state = h->data;
3589 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3590 LDB_FLAG_MOD_DELETE,
3591 r->in.sid, r->in.rights);
3596 lsa_StorePrivateData
3598 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3599 struct lsa_StorePrivateData *r)
3601 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3606 lsa_RetrievePrivateData
3608 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3609 struct lsa_RetrievePrivateData *r)
3611 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3616 lsa_GetUserName
3618 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3619 struct lsa_GetUserName *r)
3621 NTSTATUS status = NT_STATUS_OK;
3622 const char *account_name;
3623 const char *authority_name;
3624 struct lsa_String *_account_name;
3625 struct lsa_String *_authority_name = NULL;
3627 /* this is what w2k3 does */
3628 r->out.account_name = r->in.account_name;
3629 r->out.authority_name = r->in.authority_name;
3631 if (r->in.account_name
3632 && *r->in.account_name
3633 /* && *(*r->in.account_name)->string */
3635 return NT_STATUS_INVALID_PARAMETER;
3638 if (r->in.authority_name
3639 && *r->in.authority_name
3640 /* && *(*r->in.authority_name)->string */
3642 return NT_STATUS_INVALID_PARAMETER;
3645 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
3646 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
3648 _account_name = talloc(mem_ctx, struct lsa_String);
3649 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3650 _account_name->string = account_name;
3652 if (r->in.authority_name) {
3653 _authority_name = talloc(mem_ctx, struct lsa_String);
3654 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3655 _authority_name->string = authority_name;
3658 *r->out.account_name = _account_name;
3659 if (r->out.authority_name) {
3660 *r->out.authority_name = _authority_name;
3663 return status;
3667 lsa_SetInfoPolicy2
3669 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3670 TALLOC_CTX *mem_ctx,
3671 struct lsa_SetInfoPolicy2 *r)
3673 /* need to support these */
3674 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3678 lsa_QueryDomainInformationPolicy
3680 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3681 TALLOC_CTX *mem_ctx,
3682 struct lsa_QueryDomainInformationPolicy *r)
3684 union lsa_DomainInformationPolicy *info;
3686 info = talloc(r->out.info, union lsa_DomainInformationPolicy);
3687 if (!info) {
3688 return NT_STATUS_NO_MEMORY;
3691 switch (r->in.level) {
3692 case LSA_DOMAIN_INFO_POLICY_EFS:
3693 talloc_free(info);
3694 *r->out.info = NULL;
3695 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3696 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3698 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3699 struct smb_krb5_context *smb_krb5_context;
3700 int ret = smb_krb5_init_context(mem_ctx,
3701 dce_call->event_ctx,
3702 dce_call->conn->dce_ctx->lp_ctx,
3703 &smb_krb5_context);
3704 if (ret != 0) {
3705 talloc_free(info);
3706 *r->out.info = NULL;
3707 return NT_STATUS_INTERNAL_ERROR;
3709 k->enforce_restrictions = 0; /* FIXME, details missing from MS-LSAD 2.2.53 */
3710 k->service_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
3711 k->user_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
3712 k->user_tkt_renewaltime = 0; /* Need to find somewhere to store this, and query in KDC too */
3713 k->clock_skew = krb5_get_max_time_skew(smb_krb5_context->krb5_context);
3714 talloc_free(smb_krb5_context);
3715 *r->out.info = info;
3716 return NT_STATUS_OK;
3718 default:
3719 talloc_free(info);
3720 *r->out.info = NULL;
3721 return NT_STATUS_INVALID_INFO_CLASS;
3726 lsa_SetDomInfoPolicy
3728 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3729 TALLOC_CTX *mem_ctx,
3730 struct lsa_SetDomainInformationPolicy *r)
3732 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3736 lsa_TestCall
3738 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3739 TALLOC_CTX *mem_ctx,
3740 struct lsa_TestCall *r)
3742 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3746 lsa_CREDRWRITE
3748 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3749 struct lsa_CREDRWRITE *r)
3751 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3756 lsa_CREDRREAD
3758 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3759 struct lsa_CREDRREAD *r)
3761 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3766 lsa_CREDRENUMERATE
3768 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3769 struct lsa_CREDRENUMERATE *r)
3771 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3776 lsa_CREDRWRITEDOMAINCREDENTIALS
3778 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3779 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3781 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3786 lsa_CREDRREADDOMAINCREDENTIALS
3788 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3789 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3791 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3796 lsa_CREDRDELETE
3798 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3799 struct lsa_CREDRDELETE *r)
3801 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3806 lsa_CREDRGETTARGETINFO
3808 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3809 struct lsa_CREDRGETTARGETINFO *r)
3811 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3816 lsa_CREDRPROFILELOADED
3818 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3819 struct lsa_CREDRPROFILELOADED *r)
3821 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3826 lsa_CREDRGETSESSIONTYPES
3828 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3829 struct lsa_CREDRGETSESSIONTYPES *r)
3831 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3836 lsa_LSARREGISTERAUDITEVENT
3838 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3839 struct lsa_LSARREGISTERAUDITEVENT *r)
3841 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3846 lsa_LSARGENAUDITEVENT
3848 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3849 struct lsa_LSARGENAUDITEVENT *r)
3851 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3856 lsa_LSARUNREGISTERAUDITEVENT
3858 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3859 struct lsa_LSARUNREGISTERAUDITEVENT *r)
3861 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3866 lsa_lsaRQueryForestTrustInformation
3868 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3869 struct lsa_lsaRQueryForestTrustInformation *r)
3871 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3874 #define DNS_CMP_MATCH 0
3875 #define DNS_CMP_FIRST_IS_CHILD 1
3876 #define DNS_CMP_SECOND_IS_CHILD 2
3877 #define DNS_CMP_NO_MATCH 3
3879 /* this function assumes names are well formed DNS names.
3880 * it doesn't validate them */
3881 static int dns_cmp(const char *s1, size_t l1,
3882 const char *s2, size_t l2)
3884 const char *p1, *p2;
3885 size_t t1, t2;
3886 int cret;
3888 if (l1 == l2) {
3889 if (strcasecmp_m(s1, s2) == 0) {
3890 return DNS_CMP_MATCH;
3892 return DNS_CMP_NO_MATCH;
3895 if (l1 > l2) {
3896 p1 = s1;
3897 p2 = s2;
3898 t1 = l1;
3899 t2 = l2;
3900 cret = DNS_CMP_FIRST_IS_CHILD;
3901 } else {
3902 p1 = s2;
3903 p2 = s1;
3904 t1 = l2;
3905 t2 = l1;
3906 cret = DNS_CMP_SECOND_IS_CHILD;
3909 if (p1[t1 - t2 - 1] != '.') {
3910 return DNS_CMP_NO_MATCH;
3913 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3914 return cret;
3917 return DNS_CMP_NO_MATCH;
3920 /* decode all TDOs forest trust info blobs */
3921 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3922 struct ldb_message *msg,
3923 struct ForestTrustInfo *info)
3925 const struct ldb_val *ft_blob;
3926 enum ndr_err_code ndr_err;
3928 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3929 if (!ft_blob || !ft_blob->data) {
3930 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3932 /* ldb_val is equivalent to DATA_BLOB */
3933 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3934 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3935 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3936 return NT_STATUS_INVALID_DOMAIN_STATE;
3939 return NT_STATUS_OK;
3942 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
3943 struct ForestTrustInfo *fti)
3945 struct ForestTrustDataDomainInfo *info;
3946 struct ForestTrustInfoRecord *rec;
3948 fti->version = 1;
3949 fti->count = 2;
3950 fti->records = talloc_array(fti,
3951 struct ForestTrustInfoRecordArmor, 2);
3952 if (!fti->records) {
3953 return NT_STATUS_NO_MEMORY;
3956 /* TLN info */
3957 rec = &fti->records[0].record;
3959 rec->flags = 0;
3960 rec->timestamp = 0;
3961 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
3963 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
3964 if (!rec->data.name.string) {
3965 return NT_STATUS_NO_MEMORY;
3967 rec->data.name.size = strlen(rec->data.name.string);
3969 /* DOMAIN info */
3970 rec = &fti->records[1].record;
3972 rec->flags = 0;
3973 rec->timestamp = 0;
3974 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
3976 info = &rec->data.info;
3978 info->sid = *ps->domain_sid;
3979 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
3980 if (!info->dns_name.string) {
3981 return NT_STATUS_NO_MEMORY;
3983 info->dns_name.size = strlen(info->dns_name.string);
3984 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
3985 if (!info->netbios_name.string) {
3986 return NT_STATUS_NO_MEMORY;
3988 info->netbios_name.size = strlen(info->netbios_name.string);
3990 return NT_STATUS_OK;
3993 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
3994 struct lsa_ForestTrustInformation *lfti,
3995 struct ForestTrustInfo *fti)
3997 struct lsa_ForestTrustRecord *lrec;
3998 struct ForestTrustInfoRecord *rec;
3999 struct lsa_StringLarge *tln;
4000 struct lsa_ForestTrustDomainInfo *info;
4001 uint32_t i;
4003 fti->version = 1;
4004 fti->count = lfti->count;
4005 fti->records = talloc_array(mem_ctx,
4006 struct ForestTrustInfoRecordArmor,
4007 fti->count);
4008 if (!fti->records) {
4009 return NT_STATUS_NO_MEMORY;
4011 for (i = 0; i < fti->count; i++) {
4012 lrec = lfti->entries[i];
4013 rec = &fti->records[i].record;
4015 rec->flags = lrec->flags;
4016 rec->timestamp = lrec->time;
4017 rec->type = lrec->type;
4019 switch (lrec->type) {
4020 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4021 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4022 tln = &lrec->forest_trust_data.top_level_name;
4023 rec->data.name.string =
4024 talloc_strdup(mem_ctx, tln->string);
4025 if (!rec->data.name.string) {
4026 return NT_STATUS_NO_MEMORY;
4028 rec->data.name.size = strlen(rec->data.name.string);
4029 break;
4030 case LSA_FOREST_TRUST_DOMAIN_INFO:
4031 info = &lrec->forest_trust_data.domain_info;
4032 rec->data.info.sid = *info->domain_sid;
4033 rec->data.info.dns_name.string =
4034 talloc_strdup(mem_ctx,
4035 info->dns_domain_name.string);
4036 if (!rec->data.info.dns_name.string) {
4037 return NT_STATUS_NO_MEMORY;
4039 rec->data.info.dns_name.size =
4040 strlen(rec->data.info.dns_name.string);
4041 rec->data.info.netbios_name.string =
4042 talloc_strdup(mem_ctx,
4043 info->netbios_domain_name.string);
4044 if (!rec->data.info.netbios_name.string) {
4045 return NT_STATUS_NO_MEMORY;
4047 rec->data.info.netbios_name.size =
4048 strlen(rec->data.info.netbios_name.string);
4049 break;
4050 default:
4051 return NT_STATUS_INVALID_DOMAIN_STATE;
4055 return NT_STATUS_OK;
4058 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4059 uint32_t index, uint32_t collision_type,
4060 uint32_t conflict_type, const char *tdo_name);
4062 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4063 const char *tdo_name,
4064 struct ForestTrustInfo *tdo_fti,
4065 struct ForestTrustInfo *new_fti,
4066 struct lsa_ForestTrustCollisionInfo *c_info)
4068 struct ForestTrustInfoRecord *nrec;
4069 struct ForestTrustInfoRecord *trec;
4070 const char *dns_name;
4071 const char *nb_name;
4072 struct dom_sid *sid;
4073 const char *tname;
4074 size_t dns_len;
4075 size_t nb_len;
4076 size_t tlen;
4077 NTSTATUS nt_status;
4078 uint32_t new_fti_idx;
4079 uint32_t i;
4080 /* use always TDO type, until we understand when Xref can be used */
4081 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4082 bool tln_conflict;
4083 bool sid_conflict;
4084 bool nb_conflict;
4085 bool exclusion;
4086 bool ex_rule;
4087 int ret;
4089 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4091 nrec = &new_fti->records[new_fti_idx].record;
4092 dns_name = NULL;
4093 tln_conflict = false;
4094 sid_conflict = false;
4095 nb_conflict = false;
4096 exclusion = false;
4098 switch (nrec->type) {
4099 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4100 /* exclusions do not conflict by definition */
4101 break;
4103 case FOREST_TRUST_TOP_LEVEL_NAME:
4104 dns_name = nrec->data.name.string;
4105 dns_len = nrec->data.name.size;
4106 break;
4108 case LSA_FOREST_TRUST_DOMAIN_INFO:
4109 dns_name = nrec->data.info.dns_name.string;
4110 dns_len = nrec->data.info.dns_name.size;
4111 nb_name = nrec->data.info.netbios_name.string;
4112 nb_len = nrec->data.info.netbios_name.size;
4113 sid = &nrec->data.info.sid;
4114 break;
4117 if (!dns_name) continue;
4119 /* check if this is already taken and not excluded */
4120 for (i = 0; i < tdo_fti->count; i++) {
4121 trec = &tdo_fti->records[i].record;
4123 switch (trec->type) {
4124 case FOREST_TRUST_TOP_LEVEL_NAME:
4125 ex_rule = false;
4126 tname = trec->data.name.string;
4127 tlen = trec->data.name.size;
4128 break;
4129 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4130 ex_rule = true;
4131 tname = trec->data.name.string;
4132 tlen = trec->data.name.size;
4133 break;
4134 case FOREST_TRUST_DOMAIN_INFO:
4135 ex_rule = false;
4136 tname = trec->data.info.dns_name.string;
4137 tlen = trec->data.info.dns_name.size;
4139 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4140 switch (ret) {
4141 case DNS_CMP_MATCH:
4142 /* if it matches exclusion,
4143 * it doesn't conflict */
4144 if (ex_rule) {
4145 exclusion = true;
4146 break;
4148 /* fall through */
4149 case DNS_CMP_FIRST_IS_CHILD:
4150 case DNS_CMP_SECOND_IS_CHILD:
4151 tln_conflict = true;
4152 /* fall through */
4153 default:
4154 break;
4157 /* explicit exclusion, no dns name conflict here */
4158 if (exclusion) {
4159 tln_conflict = false;
4162 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4163 continue;
4166 /* also test for domain info */
4167 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4168 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4169 sid_conflict = true;
4171 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4172 strcasecmp_m(trec->data.info.netbios_name.string,
4173 nb_name) == 0) {
4174 nb_conflict = true;
4178 if (tln_conflict) {
4179 nt_status = add_collision(c_info, new_fti_idx,
4180 collision_type,
4181 LSA_TLN_DISABLED_CONFLICT,
4182 tdo_name);
4184 if (sid_conflict) {
4185 nt_status = add_collision(c_info, new_fti_idx,
4186 collision_type,
4187 LSA_SID_DISABLED_CONFLICT,
4188 tdo_name);
4190 if (nb_conflict) {
4191 nt_status = add_collision(c_info, new_fti_idx,
4192 collision_type,
4193 LSA_NB_DISABLED_CONFLICT,
4194 tdo_name);
4198 return NT_STATUS_OK;
4201 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4202 uint32_t idx, uint32_t collision_type,
4203 uint32_t conflict_type, const char *tdo_name)
4205 struct lsa_ForestTrustCollisionRecord **es;
4206 uint32_t i = c_info->count;
4208 es = talloc_realloc(c_info, c_info->entries,
4209 struct lsa_ForestTrustCollisionRecord *, i + 1);
4210 if (!es) {
4211 return NT_STATUS_NO_MEMORY;
4213 c_info->entries = es;
4214 c_info->count = i + 1;
4216 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4217 if (!es[i]) {
4218 return NT_STATUS_NO_MEMORY;
4221 es[i]->index = idx;
4222 es[i]->type = collision_type;
4223 es[i]->flags.flags = conflict_type;
4224 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4225 if (!es[i]->name.string) {
4226 return NT_STATUS_NO_MEMORY;
4228 es[i]->name.size = strlen(es[i]->name.string);
4230 return NT_STATUS_OK;
4234 lsa_lsaRSetForestTrustInformation
4236 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4237 TALLOC_CTX *mem_ctx,
4238 struct lsa_lsaRSetForestTrustInformation *r)
4240 struct dcesrv_handle *h;
4241 struct lsa_policy_state *p_state;
4242 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4243 "msDS-TrustForestTrustInfo", NULL };
4244 struct ldb_message **dom_res = NULL;
4245 struct ldb_dn *tdo_dn;
4246 struct ldb_message *msg;
4247 int num_res, i;
4248 const char *td_name;
4249 uint32_t trust_attributes;
4250 struct lsa_ForestTrustCollisionInfo *c_info;
4251 struct ForestTrustInfo *nfti;
4252 struct ForestTrustInfo *fti;
4253 DATA_BLOB ft_blob;
4254 enum ndr_err_code ndr_err;
4255 NTSTATUS nt_status;
4256 bool am_rodc;
4257 int ret;
4259 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4261 p_state = h->data;
4263 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4264 return NT_STATUS_INVALID_DOMAIN_STATE;
4267 /* abort if we are not a PDC */
4268 if (!samdb_is_pdc(p_state->sam_ldb)) {
4269 return NT_STATUS_INVALID_DOMAIN_ROLE;
4272 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4273 if (ret == LDB_SUCCESS && am_rodc) {
4274 return NT_STATUS_NO_SUCH_DOMAIN;
4277 /* check caller has TRUSTED_SET_AUTH */
4279 /* fetch all trusted domain objects */
4280 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4281 p_state->system_dn,
4282 &dom_res, trust_attrs,
4283 "(objectclass=trustedDomain)");
4284 if (num_res == 0) {
4285 return NT_STATUS_NO_SUCH_DOMAIN;
4288 for (i = 0; i < num_res; i++) {
4289 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4290 "trustPartner", NULL);
4291 if (!td_name) {
4292 return NT_STATUS_INVALID_DOMAIN_STATE;
4294 if (strcasecmp_m(td_name,
4295 r->in.trusted_domain_name->string) == 0) {
4296 break;
4299 if (i >= num_res) {
4300 return NT_STATUS_NO_SUCH_DOMAIN;
4303 tdo_dn = dom_res[i]->dn;
4305 trust_attributes = samdb_result_uint(dom_res[i],
4306 "trustAttributes", 0);
4307 if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4308 return NT_STATUS_INVALID_PARAMETER;
4311 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4312 return NT_STATUS_INVALID_PARAMETER;
4315 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4316 if (!nfti) {
4317 return NT_STATUS_NO_MEMORY;
4320 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4321 if (!NT_STATUS_IS_OK(nt_status)) {
4322 return nt_status;
4325 c_info = talloc_zero(r->out.collision_info,
4326 struct lsa_ForestTrustCollisionInfo);
4327 if (!c_info) {
4328 return NT_STATUS_NO_MEMORY;
4331 /* first check own info, then other domains */
4332 fti = talloc(mem_ctx, struct ForestTrustInfo);
4333 if (!fti) {
4334 return NT_STATUS_NO_MEMORY;
4337 nt_status = own_ft_info(p_state, fti);
4338 if (!NT_STATUS_IS_OK(nt_status)) {
4339 return nt_status;
4342 nt_status = check_ft_info(c_info, p_state->domain_dns,
4343 fti, nfti, c_info);
4344 if (!NT_STATUS_IS_OK(nt_status)) {
4345 return nt_status;
4348 for (i = 0; i < num_res; i++) {
4349 fti = talloc(mem_ctx, struct ForestTrustInfo);
4350 if (!fti) {
4351 return NT_STATUS_NO_MEMORY;
4354 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4355 if (!NT_STATUS_IS_OK(nt_status)) {
4356 if (NT_STATUS_EQUAL(nt_status,
4357 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4358 continue;
4360 return nt_status;
4363 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4364 "trustPartner", NULL);
4365 if (!td_name) {
4366 return NT_STATUS_INVALID_DOMAIN_STATE;
4369 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4370 if (!NT_STATUS_IS_OK(nt_status)) {
4371 return nt_status;
4375 *r->out.collision_info = c_info;
4377 if (r->in.check_only != 0) {
4378 return NT_STATUS_OK;
4381 /* not just a check, write info back */
4383 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4384 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4385 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4386 return NT_STATUS_INVALID_PARAMETER;
4389 msg = ldb_msg_new(mem_ctx);
4390 if (msg == NULL) {
4391 return NT_STATUS_NO_MEMORY;
4394 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4395 if (!msg->dn) {
4396 return NT_STATUS_NO_MEMORY;
4399 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4400 LDB_FLAG_MOD_REPLACE, NULL);
4401 if (ret != LDB_SUCCESS) {
4402 return NT_STATUS_NO_MEMORY;
4404 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4405 &ft_blob, NULL);
4406 if (ret != LDB_SUCCESS) {
4407 return NT_STATUS_NO_MEMORY;
4410 ret = ldb_modify(p_state->sam_ldb, msg);
4411 if (ret != LDB_SUCCESS) {
4412 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4413 ldb_errstring(p_state->sam_ldb)));
4415 switch (ret) {
4416 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4417 return NT_STATUS_ACCESS_DENIED;
4418 default:
4419 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4423 return NT_STATUS_OK;
4427 lsa_CREDRRENAME
4429 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4430 struct lsa_CREDRRENAME *r)
4432 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4438 lsa_LSAROPENPOLICYSCE
4440 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4441 struct lsa_LSAROPENPOLICYSCE *r)
4443 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4448 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4450 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4451 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4453 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4458 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4460 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4461 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4463 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4468 lsa_LSARADTREPORTSECURITYEVENT
4470 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4471 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4473 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4477 /* include the generated boilerplate */
4478 #include "librpc/gen_ndr/ndr_lsa_s.c"
4482 /*****************************************
4483 NOTE! The remaining calls below were
4484 removed in w2k3, so the DCESRV_FAULT()
4485 replies are the correct implementation. Do
4486 not try and fill these in with anything else
4487 ******************************************/
4490 dssetup_DsRoleDnsNameToFlatName
4492 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4493 struct dssetup_DsRoleDnsNameToFlatName *r)
4495 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4500 dssetup_DsRoleDcAsDc
4502 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4503 struct dssetup_DsRoleDcAsDc *r)
4505 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4510 dssetup_DsRoleDcAsReplica
4512 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4513 struct dssetup_DsRoleDcAsReplica *r)
4515 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4520 dssetup_DsRoleDemoteDc
4522 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4523 struct dssetup_DsRoleDemoteDc *r)
4525 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4530 dssetup_DsRoleGetDcOperationProgress
4532 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4533 struct dssetup_DsRoleGetDcOperationProgress *r)
4535 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4540 dssetup_DsRoleGetDcOperationResults
4542 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4543 struct dssetup_DsRoleGetDcOperationResults *r)
4545 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4550 dssetup_DsRoleCancel
4552 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4553 struct dssetup_DsRoleCancel *r)
4555 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4560 dssetup_DsRoleServerSaveStateForUpgrade
4562 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4563 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4565 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4570 dssetup_DsRoleUpgradeDownlevelServer
4572 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4573 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4575 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4580 dssetup_DsRoleAbortDownlevelServerUpgrade
4582 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4583 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4585 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4589 /* include the generated boilerplate */
4590 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4592 NTSTATUS dcerpc_server_lsa_init(void)
4594 NTSTATUS ret;
4596 ret = dcerpc_server_dssetup_init();
4597 if (!NT_STATUS_IS_OK(ret)) {
4598 return ret;
4600 ret = dcerpc_server_lsarpc_init();
4601 if (!NT_STATUS_IS_OK(ret)) {
4602 return ret;
4604 return ret;