s4-lsa: Fix typo
[Samba/id10ts.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
blob1acde1ccaeb70a21f0f3e45943e4aa4ab1d042c3
1 /* need access mask/acl implementation */
3 /*
4 Unix SMB/CIFS implementation.
6 endpoint server for the lsarpc pipe
8 Copyright (C) Andrew Tridgell 2004
9 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "rpc_server/lsa/lsa.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_drsblobs.h"
29 #include "librpc/gen_ndr/ndr_lsa.h"
30 #include "../lib/crypto/crypto.h"
31 #include "lib/util/tsort.h"
32 #include "dsdb/common/util.h"
33 #include "libcli/security/session.h"
34 #include "kdc/kdc-policy.h"
37 this type allows us to distinguish handle types
41 state associated with a lsa_OpenAccount() operation
43 struct lsa_account_state {
44 struct lsa_policy_state *policy;
45 uint32_t access_mask;
46 struct dom_sid *account_sid;
51 state associated with a lsa_OpenSecret() operation
53 struct lsa_secret_state {
54 struct lsa_policy_state *policy;
55 uint32_t access_mask;
56 struct ldb_dn *secret_dn;
57 struct ldb_context *sam_ldb;
58 bool global;
62 state associated with a lsa_OpenTrustedDomain() operation
64 struct lsa_trusted_domain_state {
65 struct lsa_policy_state *policy;
66 uint32_t access_mask;
67 struct ldb_dn *trusted_domain_dn;
68 struct ldb_dn *trusted_domain_user_dn;
72 this is based on the samba3 function make_lsa_object_sd()
73 It uses the same logic, but with samba4 helper functions
75 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
76 struct security_descriptor **sd,
77 struct dom_sid *sid,
78 uint32_t sid_access)
80 NTSTATUS status;
81 uint32_t rid;
82 struct dom_sid *domain_sid, *domain_admins_sid;
83 const char *domain_admins_sid_str, *sidstr;
84 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
86 status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
87 NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
89 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
90 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid, tmp_ctx);
92 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
93 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid_str, tmp_ctx);
95 sidstr = dom_sid_string(tmp_ctx, sid);
96 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, tmp_ctx);
98 *sd = security_descriptor_dacl_create(mem_ctx,
99 0, sidstr, NULL,
101 SID_WORLD,
102 SEC_ACE_TYPE_ACCESS_ALLOWED,
103 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
105 SID_BUILTIN_ADMINISTRATORS,
106 SEC_ACE_TYPE_ACCESS_ALLOWED,
107 SEC_GENERIC_ALL, 0,
109 SID_BUILTIN_ACCOUNT_OPERATORS,
110 SEC_ACE_TYPE_ACCESS_ALLOWED,
111 SEC_GENERIC_ALL, 0,
113 domain_admins_sid_str,
114 SEC_ACE_TYPE_ACCESS_ALLOWED,
115 SEC_GENERIC_ALL, 0,
117 sidstr,
118 SEC_ACE_TYPE_ACCESS_ALLOWED,
119 sid_access, 0,
121 NULL);
122 talloc_free(tmp_ctx);
124 NT_STATUS_HAVE_NO_MEMORY(*sd);
126 return NT_STATUS_OK;
130 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
131 TALLOC_CTX *mem_ctx,
132 struct lsa_EnumAccountRights *r);
134 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
135 TALLOC_CTX *mem_ctx,
136 struct lsa_policy_state *state,
137 int ldb_flag,
138 struct dom_sid *sid,
139 const struct lsa_RightSet *rights);
142 lsa_Close
144 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
145 struct lsa_Close *r)
147 struct dcesrv_handle *h;
149 *r->out.handle = *r->in.handle;
151 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
153 talloc_free(h);
155 ZERO_STRUCTP(r->out.handle);
157 return NT_STATUS_OK;
162 lsa_Delete
164 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
165 struct lsa_Delete *r)
167 return NT_STATUS_NOT_SUPPORTED;
172 lsa_DeleteObject
174 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
175 struct lsa_DeleteObject *r)
177 struct dcesrv_handle *h;
178 int ret;
180 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
182 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
183 struct lsa_secret_state *secret_state = h->data;
185 /* Ensure user is permitted to delete this... */
186 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
188 case SECURITY_SYSTEM:
189 case SECURITY_ADMINISTRATOR:
190 break;
191 default:
192 /* Users and anonymous are not allowed to delete things */
193 return NT_STATUS_ACCESS_DENIED;
196 ret = ldb_delete(secret_state->sam_ldb,
197 secret_state->secret_dn);
198 if (ret != LDB_SUCCESS) {
199 return NT_STATUS_INVALID_HANDLE;
202 ZERO_STRUCTP(r->out.handle);
204 return NT_STATUS_OK;
206 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
207 struct lsa_trusted_domain_state *trusted_domain_state =
208 talloc_get_type(h->data, struct lsa_trusted_domain_state);
209 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
210 if (ret != LDB_SUCCESS) {
211 return NT_STATUS_INTERNAL_DB_CORRUPTION;
214 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
215 trusted_domain_state->trusted_domain_dn);
216 if (ret != LDB_SUCCESS) {
217 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
218 return NT_STATUS_INVALID_HANDLE;
221 if (trusted_domain_state->trusted_domain_user_dn) {
222 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
223 trusted_domain_state->trusted_domain_user_dn);
224 if (ret != LDB_SUCCESS) {
225 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
226 return NT_STATUS_INVALID_HANDLE;
230 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
231 if (ret != LDB_SUCCESS) {
232 return NT_STATUS_INTERNAL_DB_CORRUPTION;
235 ZERO_STRUCTP(r->out.handle);
237 return NT_STATUS_OK;
239 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
240 struct lsa_RightSet *rights;
241 struct lsa_account_state *astate;
242 struct lsa_EnumAccountRights r2;
243 NTSTATUS status;
245 rights = talloc(mem_ctx, struct lsa_RightSet);
247 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
249 astate = h->data;
251 r2.in.handle = &astate->policy->handle->wire_handle;
252 r2.in.sid = astate->account_sid;
253 r2.out.rights = rights;
255 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
256 but we have a LSA_HANDLE_ACCOUNT here, so this call
257 will always fail */
258 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
259 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
260 return NT_STATUS_OK;
263 if (!NT_STATUS_IS_OK(status)) {
264 return status;
267 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
268 LDB_FLAG_MOD_DELETE, astate->account_sid,
269 r2.out.rights);
270 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
271 return NT_STATUS_OK;
274 if (!NT_STATUS_IS_OK(status)) {
275 return status;
278 ZERO_STRUCTP(r->out.handle);
280 return NT_STATUS_OK;
283 return NT_STATUS_INVALID_HANDLE;
288 lsa_EnumPrivs
290 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
291 struct lsa_EnumPrivs *r)
293 struct dcesrv_handle *h;
294 struct lsa_policy_state *state;
295 uint32_t i;
296 enum sec_privilege priv;
297 const char *privname;
299 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
301 state = h->data;
303 i = *r->in.resume_handle;
305 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
306 r->out.privs->count < r->in.max_count) {
307 struct lsa_PrivEntry *e;
308 privname = sec_privilege_name(priv);
309 r->out.privs->privs = talloc_realloc(r->out.privs,
310 r->out.privs->privs,
311 struct lsa_PrivEntry,
312 r->out.privs->count+1);
313 if (r->out.privs->privs == NULL) {
314 return NT_STATUS_NO_MEMORY;
316 e = &r->out.privs->privs[r->out.privs->count];
317 e->luid.low = priv;
318 e->luid.high = 0;
319 e->name.string = privname;
320 r->out.privs->count++;
321 i++;
324 *r->out.resume_handle = i;
326 return NT_STATUS_OK;
331 lsa_QuerySecObj
333 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
334 struct lsa_QuerySecurity *r)
336 struct dcesrv_handle *h;
337 struct security_descriptor *sd;
338 NTSTATUS status;
339 struct dom_sid *sid;
341 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
343 sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
345 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
346 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
347 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
348 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid,
349 LSA_ACCOUNT_ALL_ACCESS);
350 } else {
351 return NT_STATUS_INVALID_HANDLE;
353 NT_STATUS_NOT_OK_RETURN(status);
355 (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
356 NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
358 (*r->out.sdbuf)->sd = sd;
360 return NT_STATUS_OK;
365 lsa_SetSecObj
367 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
368 struct lsa_SetSecObj *r)
370 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
375 lsa_ChangePassword
377 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
378 struct lsa_ChangePassword *r)
380 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
384 dssetup_DsRoleGetPrimaryDomainInformation
386 This is not an LSA call, but is the only call left on the DSSETUP
387 pipe (after the pipe was truncated), and needs lsa_get_policy_state
389 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
390 TALLOC_CTX *mem_ctx,
391 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
393 union dssetup_DsRoleInfo *info;
395 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
396 W_ERROR_HAVE_NO_MEMORY(info);
398 switch (r->in.level) {
399 case DS_ROLE_BASIC_INFORMATION:
401 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
402 uint32_t flags = 0;
403 const char *domain = NULL;
404 const char *dns_domain = NULL;
405 const char *forest = NULL;
406 struct GUID domain_guid;
407 struct lsa_policy_state *state;
409 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
410 if (!NT_STATUS_IS_OK(status)) {
411 return ntstatus_to_werror(status);
414 ZERO_STRUCT(domain_guid);
416 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
417 case ROLE_STANDALONE:
418 role = DS_ROLE_STANDALONE_SERVER;
419 break;
420 case ROLE_DOMAIN_MEMBER:
421 role = DS_ROLE_MEMBER_SERVER;
422 break;
423 case ROLE_DOMAIN_CONTROLLER:
424 if (samdb_is_pdc(state->sam_ldb)) {
425 role = DS_ROLE_PRIMARY_DC;
426 } else {
427 role = DS_ROLE_BACKUP_DC;
429 break;
432 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
433 case ROLE_STANDALONE:
434 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
435 W_ERROR_HAVE_NO_MEMORY(domain);
436 break;
437 case ROLE_DOMAIN_MEMBER:
438 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
439 W_ERROR_HAVE_NO_MEMORY(domain);
440 /* TODO: what is with dns_domain and forest and guid? */
441 break;
442 case ROLE_DOMAIN_CONTROLLER:
443 flags = DS_ROLE_PRIMARY_DS_RUNNING;
445 if (state->mixed_domain == 1) {
446 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
449 domain = state->domain_name;
450 dns_domain = state->domain_dns;
451 forest = state->forest_dns;
453 domain_guid = state->domain_guid;
454 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
455 break;
458 info->basic.role = role;
459 info->basic.flags = flags;
460 info->basic.domain = domain;
461 info->basic.dns_domain = dns_domain;
462 info->basic.forest = forest;
463 info->basic.domain_guid = domain_guid;
465 r->out.info = info;
466 return WERR_OK;
468 case DS_ROLE_UPGRADE_STATUS:
470 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
471 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
473 r->out.info = info;
474 return WERR_OK;
476 case DS_ROLE_OP_STATUS:
478 info->opstatus.status = DS_ROLE_OP_IDLE;
480 r->out.info = info;
481 return WERR_OK;
483 default:
484 return WERR_INVALID_PARAM;
489 fill in the AccountDomain info
491 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
492 struct lsa_DomainInfo *info)
494 info->name.string = state->domain_name;
495 info->sid = state->domain_sid;
497 return NT_STATUS_OK;
501 fill in the DNS domain info
503 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
504 struct lsa_DnsDomainInfo *info)
506 info->name.string = state->domain_name;
507 info->sid = state->domain_sid;
508 info->dns_domain.string = state->domain_dns;
509 info->dns_forest.string = state->forest_dns;
510 info->domain_guid = state->domain_guid;
512 return NT_STATUS_OK;
516 lsa_QueryInfoPolicy2
518 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
519 struct lsa_QueryInfoPolicy2 *r)
521 struct lsa_policy_state *state;
522 struct dcesrv_handle *h;
523 union lsa_PolicyInformation *info;
525 *r->out.info = NULL;
527 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
529 state = h->data;
531 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
532 if (!info) {
533 return NT_STATUS_NO_MEMORY;
535 *r->out.info = info;
537 switch (r->in.level) {
538 case LSA_POLICY_INFO_AUDIT_LOG:
539 /* we don't need to fill in any of this */
540 ZERO_STRUCT(info->audit_log);
541 return NT_STATUS_OK;
542 case LSA_POLICY_INFO_AUDIT_EVENTS:
543 /* we don't need to fill in any of this */
544 ZERO_STRUCT(info->audit_events);
545 return NT_STATUS_OK;
546 case LSA_POLICY_INFO_PD:
547 /* we don't need to fill in any of this */
548 ZERO_STRUCT(info->pd);
549 return NT_STATUS_OK;
551 case LSA_POLICY_INFO_DOMAIN:
552 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
553 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
554 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
555 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
556 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
558 case LSA_POLICY_INFO_ROLE:
559 info->role.role = LSA_ROLE_PRIMARY;
560 return NT_STATUS_OK;
562 case LSA_POLICY_INFO_DNS:
563 case LSA_POLICY_INFO_DNS_INT:
564 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
566 case LSA_POLICY_INFO_REPLICA:
567 ZERO_STRUCT(info->replica);
568 return NT_STATUS_OK;
570 case LSA_POLICY_INFO_QUOTA:
571 ZERO_STRUCT(info->quota);
572 return NT_STATUS_OK;
574 case LSA_POLICY_INFO_MOD:
575 case LSA_POLICY_INFO_AUDIT_FULL_SET:
576 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
577 /* windows gives INVALID_PARAMETER */
578 *r->out.info = NULL;
579 return NT_STATUS_INVALID_PARAMETER;
582 *r->out.info = NULL;
583 return NT_STATUS_INVALID_INFO_CLASS;
587 lsa_QueryInfoPolicy
589 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
590 struct lsa_QueryInfoPolicy *r)
592 struct lsa_QueryInfoPolicy2 r2;
593 NTSTATUS status;
595 ZERO_STRUCT(r2);
597 r2.in.handle = r->in.handle;
598 r2.in.level = r->in.level;
599 r2.out.info = r->out.info;
601 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
603 return status;
607 lsa_SetInfoPolicy
609 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
610 struct lsa_SetInfoPolicy *r)
612 /* need to support this */
613 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
618 lsa_ClearAuditLog
620 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
621 struct lsa_ClearAuditLog *r)
623 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
628 lsa_CreateAccount
630 This call does not seem to have any long-term effects, hence no database operations
632 we need to talk to the MS product group to find out what this account database means!
634 answer is that the lsa database is totally separate from the SAM and
635 ldap databases. We are going to need a separate ldb to store these
636 accounts. The SIDs on this account bear no relation to the SIDs in
639 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
640 struct lsa_CreateAccount *r)
642 struct lsa_account_state *astate;
644 struct lsa_policy_state *state;
645 struct dcesrv_handle *h, *ah;
647 ZERO_STRUCTP(r->out.acct_handle);
649 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
651 state = h->data;
653 astate = talloc(dce_call->conn, struct lsa_account_state);
654 if (astate == NULL) {
655 return NT_STATUS_NO_MEMORY;
658 astate->account_sid = dom_sid_dup(astate, r->in.sid);
659 if (astate->account_sid == NULL) {
660 talloc_free(astate);
661 return NT_STATUS_NO_MEMORY;
664 astate->policy = talloc_reference(astate, state);
665 astate->access_mask = r->in.access_mask;
667 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
668 if (!ah) {
669 talloc_free(astate);
670 return NT_STATUS_NO_MEMORY;
673 ah->data = talloc_steal(ah, astate);
675 *r->out.acct_handle = ah->wire_handle;
677 return NT_STATUS_OK;
682 lsa_EnumAccounts
684 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
685 struct lsa_EnumAccounts *r)
687 struct dcesrv_handle *h;
688 struct lsa_policy_state *state;
689 int ret;
690 struct ldb_message **res;
691 const char * const attrs[] = { "objectSid", NULL};
692 uint32_t count, i;
694 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
696 state = h->data;
698 /* NOTE: This call must only return accounts that have at least
699 one privilege set
701 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
702 "(&(objectSid=*)(privilege=*))");
703 if (ret < 0) {
704 return NT_STATUS_INTERNAL_DB_CORRUPTION;
707 if (*r->in.resume_handle >= ret) {
708 return NT_STATUS_NO_MORE_ENTRIES;
711 count = ret - *r->in.resume_handle;
712 if (count > r->in.num_entries) {
713 count = r->in.num_entries;
716 if (count == 0) {
717 return NT_STATUS_NO_MORE_ENTRIES;
720 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
721 if (r->out.sids->sids == NULL) {
722 return NT_STATUS_NO_MEMORY;
725 for (i=0;i<count;i++) {
726 r->out.sids->sids[i].sid =
727 samdb_result_dom_sid(r->out.sids->sids,
728 res[i + *r->in.resume_handle],
729 "objectSid");
730 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
733 r->out.sids->num_sids = count;
734 *r->out.resume_handle = count + *r->in.resume_handle;
736 return NT_STATUS_OK;
740 /* This decrypts and returns Trusted Domain Auth Information Internal data */
741 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
742 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
743 struct trustDomainPasswords *auth_struct)
745 DATA_BLOB session_key = data_blob(NULL, 0);
746 enum ndr_err_code ndr_err;
747 NTSTATUS nt_status;
749 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
750 if (!NT_STATUS_IS_OK(nt_status)) {
751 return nt_status;
754 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
755 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
756 auth_struct,
757 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
758 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
759 return NT_STATUS_INVALID_PARAMETER;
762 return NT_STATUS_OK;
765 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
766 TALLOC_CTX *mem_ctx,
767 struct trustAuthInOutBlob *iopw,
768 DATA_BLOB *trustauth_blob)
770 enum ndr_err_code ndr_err;
772 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
773 iopw,
774 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
775 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
776 return NT_STATUS_INVALID_PARAMETER;
779 return NT_STATUS_OK;
782 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
783 struct ldb_context *sam_ldb,
784 struct ldb_dn *base_dn,
785 const char *netbios_name,
786 struct trustAuthInOutBlob *in,
787 struct ldb_dn **user_dn)
789 struct ldb_message *msg;
790 struct ldb_dn *dn;
791 uint32_t i;
792 int ret;
794 dn = ldb_dn_copy(mem_ctx, base_dn);
795 if (!dn) {
796 return NT_STATUS_NO_MEMORY;
798 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
799 return NT_STATUS_NO_MEMORY;
802 msg = ldb_msg_new(mem_ctx);
803 if (!msg) {
804 return NT_STATUS_NO_MEMORY;
806 msg->dn = dn;
808 ret = ldb_msg_add_string(msg, "objectClass", "user");
809 if (ret != LDB_SUCCESS) {
810 return NT_STATUS_NO_MEMORY;
813 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
814 if (ret != LDB_SUCCESS) {
815 return NT_STATUS_NO_MEMORY;
818 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
819 UF_INTERDOMAIN_TRUST_ACCOUNT);
820 if (ret != LDB_SUCCESS) {
821 return NT_STATUS_NO_MEMORY;
824 for (i = 0; i < in->count; i++) {
825 const char *attribute;
826 struct ldb_val v;
827 switch (in->current.array[i].AuthType) {
828 case TRUST_AUTH_TYPE_NT4OWF:
829 attribute = "unicodePwd";
830 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
831 v.length = 16;
832 break;
833 case TRUST_AUTH_TYPE_CLEAR:
834 attribute = "clearTextPassword";
835 v.data = in->current.array[i].AuthInfo.clear.password;
836 v.length = in->current.array[i].AuthInfo.clear.size;
837 break;
838 default:
839 continue;
842 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
843 if (ret != LDB_SUCCESS) {
844 return NT_STATUS_NO_MEMORY;
848 /* create the trusted_domain user account */
849 ret = ldb_add(sam_ldb, msg);
850 if (ret != LDB_SUCCESS) {
851 DEBUG(0,("Failed to create user record %s: %s\n",
852 ldb_dn_get_linearized(msg->dn),
853 ldb_errstring(sam_ldb)));
855 switch (ret) {
856 case LDB_ERR_ENTRY_ALREADY_EXISTS:
857 return NT_STATUS_DOMAIN_EXISTS;
858 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
859 return NT_STATUS_ACCESS_DENIED;
860 default:
861 return NT_STATUS_INTERNAL_DB_CORRUPTION;
865 if (user_dn) {
866 *user_dn = dn;
868 return NT_STATUS_OK;
872 lsa_CreateTrustedDomainEx2
874 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
875 TALLOC_CTX *mem_ctx,
876 struct lsa_CreateTrustedDomainEx2 *r,
877 int op)
879 struct dcesrv_handle *policy_handle;
880 struct lsa_policy_state *policy_state;
881 struct lsa_trusted_domain_state *trusted_domain_state;
882 struct dcesrv_handle *handle;
883 struct ldb_message **msgs, *msg;
884 const char *attrs[] = {
885 NULL
887 const char *netbios_name;
888 const char *dns_name;
889 const char *name;
890 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
891 struct trustDomainPasswords auth_struct;
892 int ret;
893 NTSTATUS nt_status;
894 struct ldb_context *sam_ldb;
896 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
897 ZERO_STRUCTP(r->out.trustdom_handle);
899 policy_state = policy_handle->data;
900 sam_ldb = policy_state->sam_ldb;
902 netbios_name = r->in.info->netbios_name.string;
903 if (!netbios_name) {
904 return NT_STATUS_INVALID_PARAMETER;
907 dns_name = r->in.info->domain_name.string;
909 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
910 if (!trusted_domain_state) {
911 return NT_STATUS_NO_MEMORY;
913 trusted_domain_state->policy = policy_state;
915 if (strcasecmp(netbios_name, "BUILTIN") == 0
916 || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
917 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
918 return NT_STATUS_INVALID_PARAMETER;
921 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
922 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
923 || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
924 || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
925 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
926 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
929 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
930 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
931 /* No secrets are created at this time, for this function */
932 auth_struct.outgoing.count = 0;
933 auth_struct.incoming.count = 0;
934 } else {
935 auth_blob = data_blob_const(r->in.auth_info->auth_blob.data,
936 r->in.auth_info->auth_blob.size);
937 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
938 &auth_blob, &auth_struct);
939 if (!NT_STATUS_IS_OK(nt_status)) {
940 return nt_status;
943 if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
944 if (auth_struct.incoming.count > 1) {
945 return NT_STATUS_INVALID_PARAMETER;
950 if (auth_struct.incoming.count) {
951 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
952 &auth_struct.incoming,
953 &trustAuthIncoming);
954 if (!NT_STATUS_IS_OK(nt_status)) {
955 return nt_status;
957 } else {
958 trustAuthIncoming = data_blob(NULL, 0);
961 if (auth_struct.outgoing.count) {
962 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
963 &auth_struct.outgoing,
964 &trustAuthOutgoing);
965 if (!NT_STATUS_IS_OK(nt_status)) {
966 return nt_status;
968 } else {
969 trustAuthOutgoing = data_blob(NULL, 0);
972 ret = ldb_transaction_start(sam_ldb);
973 if (ret != LDB_SUCCESS) {
974 return NT_STATUS_INTERNAL_DB_CORRUPTION;
977 if (dns_name) {
978 char *dns_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
979 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
980 /* search for the trusted_domain record */
981 ret = gendb_search(sam_ldb,
982 mem_ctx, policy_state->system_dn, &msgs, attrs,
983 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
984 dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
985 if (ret > 0) {
986 ldb_transaction_cancel(sam_ldb);
987 return NT_STATUS_OBJECT_NAME_COLLISION;
989 } else {
990 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
991 /* search for the trusted_domain record */
992 ret = gendb_search(sam_ldb,
993 mem_ctx, policy_state->system_dn, &msgs, attrs,
994 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
995 netbios_encoded, netbios_encoded, netbios_encoded);
996 if (ret > 0) {
997 ldb_transaction_cancel(sam_ldb);
998 return NT_STATUS_OBJECT_NAME_COLLISION;
1002 if (ret < 0 ) {
1003 ldb_transaction_cancel(sam_ldb);
1004 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1007 name = dns_name ? dns_name : netbios_name;
1009 msg = ldb_msg_new(mem_ctx);
1010 if (msg == NULL) {
1011 return NT_STATUS_NO_MEMORY;
1014 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1015 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1016 ldb_transaction_cancel(sam_ldb);
1017 return NT_STATUS_NO_MEMORY;
1020 ldb_msg_add_string(msg, "flatname", netbios_name);
1022 if (r->in.info->sid) {
1023 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1024 if (ret != LDB_SUCCESS) {
1025 ldb_transaction_cancel(sam_ldb);
1026 return NT_STATUS_INVALID_PARAMETER;
1030 ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1032 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1034 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1036 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1038 if (dns_name) {
1039 ldb_msg_add_string(msg, "trustPartner", dns_name);
1042 if (trustAuthIncoming.data) {
1043 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1044 if (ret != LDB_SUCCESS) {
1045 ldb_transaction_cancel(sam_ldb);
1046 return NT_STATUS_NO_MEMORY;
1049 if (trustAuthOutgoing.data) {
1050 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1051 if (ret != LDB_SUCCESS) {
1052 ldb_transaction_cancel(sam_ldb);
1053 return NT_STATUS_NO_MEMORY;
1057 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1059 /* create the trusted_domain */
1060 ret = ldb_add(sam_ldb, msg);
1061 switch (ret) {
1062 case LDB_SUCCESS:
1063 break;
1064 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1065 ldb_transaction_cancel(sam_ldb);
1066 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1067 ldb_dn_get_linearized(msg->dn),
1068 ldb_errstring(sam_ldb)));
1069 return NT_STATUS_DOMAIN_EXISTS;
1070 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1071 ldb_transaction_cancel(sam_ldb);
1072 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1073 ldb_dn_get_linearized(msg->dn),
1074 ldb_errstring(sam_ldb)));
1075 return NT_STATUS_ACCESS_DENIED;
1076 default:
1077 ldb_transaction_cancel(sam_ldb);
1078 DEBUG(0,("Failed to create user record %s: %s\n",
1079 ldb_dn_get_linearized(msg->dn),
1080 ldb_errstring(sam_ldb)));
1081 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1084 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1085 struct ldb_dn *user_dn;
1086 /* Inbound trusts must also create a cn=users object to match */
1087 nt_status = add_trust_user(mem_ctx, sam_ldb,
1088 policy_state->domain_dn,
1089 netbios_name,
1090 &auth_struct.incoming,
1091 &user_dn);
1092 if (!NT_STATUS_IS_OK(nt_status)) {
1093 ldb_transaction_cancel(sam_ldb);
1094 return nt_status;
1097 /* save the trust user dn */
1098 trusted_domain_state->trusted_domain_user_dn
1099 = talloc_steal(trusted_domain_state, user_dn);
1102 ret = ldb_transaction_commit(sam_ldb);
1103 if (ret != LDB_SUCCESS) {
1104 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1107 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1108 if (!handle) {
1109 return NT_STATUS_NO_MEMORY;
1112 handle->data = talloc_steal(handle, trusted_domain_state);
1114 trusted_domain_state->access_mask = r->in.access_mask;
1115 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1117 *r->out.trustdom_handle = handle->wire_handle;
1119 return NT_STATUS_OK;
1123 lsa_CreateTrustedDomainEx2
1125 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1126 TALLOC_CTX *mem_ctx,
1127 struct lsa_CreateTrustedDomainEx2 *r)
1129 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2);
1132 lsa_CreateTrustedDomainEx
1134 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1135 TALLOC_CTX *mem_ctx,
1136 struct lsa_CreateTrustedDomainEx *r)
1138 struct lsa_CreateTrustedDomainEx2 r2;
1140 r2.in.policy_handle = r->in.policy_handle;
1141 r2.in.info = r->in.info;
1142 r2.in.auth_info = r->in.auth_info;
1143 r2.out.trustdom_handle = r->out.trustdom_handle;
1144 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX);
1148 lsa_CreateTrustedDomain
1150 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1151 struct lsa_CreateTrustedDomain *r)
1153 struct lsa_CreateTrustedDomainEx2 r2;
1155 r2.in.policy_handle = r->in.policy_handle;
1156 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1157 if (!r2.in.info) {
1158 return NT_STATUS_NO_MEMORY;
1161 r2.in.info->domain_name.string = NULL;
1162 r2.in.info->netbios_name = r->in.info->name;
1163 r2.in.info->sid = r->in.info->sid;
1164 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1165 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1166 r2.in.info->trust_attributes = 0;
1168 r2.in.access_mask = r->in.access_mask;
1169 r2.out.trustdom_handle = r->out.trustdom_handle;
1171 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN);
1176 lsa_OpenTrustedDomain
1178 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1179 struct lsa_OpenTrustedDomain *r)
1181 struct dcesrv_handle *policy_handle;
1183 struct lsa_policy_state *policy_state;
1184 struct lsa_trusted_domain_state *trusted_domain_state;
1185 struct dcesrv_handle *handle;
1186 struct ldb_message **msgs;
1187 const char *attrs[] = {
1188 "trustDirection",
1189 "flatname",
1190 NULL
1193 const char *sid_string;
1194 int ret;
1196 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1197 ZERO_STRUCTP(r->out.trustdom_handle);
1198 policy_state = policy_handle->data;
1200 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1201 if (!trusted_domain_state) {
1202 return NT_STATUS_NO_MEMORY;
1204 trusted_domain_state->policy = policy_state;
1206 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1207 if (!sid_string) {
1208 return NT_STATUS_NO_MEMORY;
1211 /* search for the trusted_domain record */
1212 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1213 mem_ctx, policy_state->system_dn, &msgs, attrs,
1214 "(&(securityIdentifier=%s)(objectclass=trustedDomain))",
1215 sid_string);
1216 if (ret == 0) {
1217 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1220 if (ret != 1) {
1221 DEBUG(0,("Found %d records matching DN %s\n", ret,
1222 ldb_dn_get_linearized(policy_state->system_dn)));
1223 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1226 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1228 trusted_domain_state->trusted_domain_user_dn = NULL;
1230 if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1231 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1232 /* search for the trusted_domain record */
1233 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1234 mem_ctx, policy_state->domain_dn, &msgs, attrs,
1235 "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%u))",
1236 flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1237 if (ret == 1) {
1238 trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1241 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1242 if (!handle) {
1243 return NT_STATUS_NO_MEMORY;
1246 handle->data = talloc_steal(handle, trusted_domain_state);
1248 trusted_domain_state->access_mask = r->in.access_mask;
1249 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1251 *r->out.trustdom_handle = handle->wire_handle;
1253 return NT_STATUS_OK;
1258 lsa_OpenTrustedDomainByName
1260 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1261 TALLOC_CTX *mem_ctx,
1262 struct lsa_OpenTrustedDomainByName *r)
1264 struct dcesrv_handle *policy_handle;
1266 struct lsa_policy_state *policy_state;
1267 struct lsa_trusted_domain_state *trusted_domain_state;
1268 struct dcesrv_handle *handle;
1269 struct ldb_message **msgs;
1270 const char *attrs[] = {
1271 NULL
1273 char *td_name;
1274 int ret;
1276 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1277 ZERO_STRUCTP(r->out.trustdom_handle);
1278 policy_state = policy_handle->data;
1280 if (!r->in.name.string) {
1281 return NT_STATUS_INVALID_PARAMETER;
1284 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1285 if (!trusted_domain_state) {
1286 return NT_STATUS_NO_MEMORY;
1288 trusted_domain_state->policy = policy_state;
1290 /* search for the trusted_domain record */
1291 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1292 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1293 mem_ctx, policy_state->system_dn, &msgs, attrs,
1294 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1295 "(objectclass=trustedDomain))",
1296 td_name, td_name, td_name);
1297 if (ret == 0) {
1298 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1301 if (ret != 1) {
1302 DEBUG(0,("Found %d records matching DN %s\n", ret,
1303 ldb_dn_get_linearized(policy_state->system_dn)));
1304 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1307 /* TODO: perform access checks */
1309 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1311 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1312 if (!handle) {
1313 return NT_STATUS_NO_MEMORY;
1316 handle->data = talloc_steal(handle, trusted_domain_state);
1318 trusted_domain_state->access_mask = r->in.access_mask;
1319 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1321 *r->out.trustdom_handle = handle->wire_handle;
1323 return NT_STATUS_OK;
1329 lsa_SetTrustedDomainInfo
1331 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1332 struct lsa_SetTrustedDomainInfo *r)
1334 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1339 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1340 * otherwise at least one must be provided */
1341 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1342 struct ldb_dn *basedn, const char *dns_domain,
1343 const char *netbios, struct dom_sid2 *sid,
1344 struct ldb_message ***msgs)
1346 const char *attrs[] = { "flatname", "trustPartner",
1347 "securityIdentifier", "trustDirection",
1348 "trustType", "trustAttributes",
1349 "trustPosixOffset",
1350 "msDs-supportedEncryptionTypes", NULL };
1351 char *dns = NULL;
1352 char *nbn = NULL;
1353 char *sidstr = NULL;
1354 char *filter;
1355 int ret;
1358 if (dns_domain || netbios || sid) {
1359 filter = talloc_strdup(mem_ctx,
1360 "(&(objectclass=trustedDomain)(|");
1361 } else {
1362 filter = talloc_strdup(mem_ctx,
1363 "(objectclass=trustedDomain)");
1365 if (!filter) {
1366 return NT_STATUS_NO_MEMORY;
1369 if (dns_domain) {
1370 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1371 if (!dns) {
1372 return NT_STATUS_NO_MEMORY;
1374 filter = talloc_asprintf_append(filter,
1375 "(trustPartner=%s)", dns);
1376 if (!filter) {
1377 return NT_STATUS_NO_MEMORY;
1380 if (netbios) {
1381 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1382 if (!nbn) {
1383 return NT_STATUS_NO_MEMORY;
1385 filter = talloc_asprintf_append(filter,
1386 "(flatname=%s)", nbn);
1387 if (!filter) {
1388 return NT_STATUS_NO_MEMORY;
1391 if (sid) {
1392 sidstr = dom_sid_string(mem_ctx, sid);
1393 if (!sidstr) {
1394 return NT_STATUS_INVALID_PARAMETER;
1396 filter = talloc_asprintf_append(filter,
1397 "(securityIdentifier=%s)",
1398 sidstr);
1399 if (!filter) {
1400 return NT_STATUS_NO_MEMORY;
1403 if (dns_domain || netbios || sid) {
1404 filter = talloc_asprintf_append(filter, "))");
1405 if (!filter) {
1406 return NT_STATUS_NO_MEMORY;
1410 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1411 if (ret == 0) {
1412 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1415 if (ret != 1) {
1416 return NT_STATUS_OBJECT_NAME_COLLISION;
1419 return NT_STATUS_OK;
1422 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1423 struct ldb_context *sam_ldb,
1424 struct ldb_message *orig,
1425 struct ldb_message *dest,
1426 const char *attribute,
1427 uint32_t value,
1428 uint32_t *orig_value)
1430 const struct ldb_val *orig_val;
1431 uint32_t orig_uint = 0;
1432 unsigned int flags = 0;
1433 int ret;
1435 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1436 if (!orig_val || !orig_val->data) {
1437 /* add new attribute */
1438 flags = LDB_FLAG_MOD_ADD;
1440 } else {
1441 errno = 0;
1442 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1443 if (errno != 0 || orig_uint != value) {
1444 /* replace also if can't get value */
1445 flags = LDB_FLAG_MOD_REPLACE;
1449 if (flags == 0) {
1450 /* stored value is identical, nothing to change */
1451 goto done;
1454 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1455 if (ret != LDB_SUCCESS) {
1456 return NT_STATUS_NO_MEMORY;
1459 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1460 if (ret != LDB_SUCCESS) {
1461 return NT_STATUS_NO_MEMORY;
1464 done:
1465 if (orig_value) {
1466 *orig_value = orig_uint;
1468 return NT_STATUS_OK;
1471 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1472 struct ldb_context *sam_ldb,
1473 struct ldb_dn *base_dn,
1474 bool delete_user,
1475 const char *netbios_name,
1476 struct trustAuthInOutBlob *in)
1478 const char *attrs[] = { "userAccountControl", NULL };
1479 struct ldb_message **msgs;
1480 struct ldb_message *msg;
1481 uint32_t uac;
1482 uint32_t i;
1483 int ret;
1485 ret = gendb_search(sam_ldb, mem_ctx,
1486 base_dn, &msgs, attrs,
1487 "samAccountName=%s$", netbios_name);
1488 if (ret > 1) {
1489 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1492 if (ret == 0) {
1493 if (delete_user) {
1494 return NT_STATUS_OK;
1497 /* ok no existing user, add it from scratch */
1498 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1499 netbios_name, in, NULL);
1502 /* check user is what we are looking for */
1503 uac = ldb_msg_find_attr_as_uint(msgs[0],
1504 "userAccountControl", 0);
1505 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1506 return NT_STATUS_OBJECT_NAME_COLLISION;
1509 if (delete_user) {
1510 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1511 switch (ret) {
1512 case LDB_SUCCESS:
1513 return NT_STATUS_OK;
1514 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1515 return NT_STATUS_ACCESS_DENIED;
1516 default:
1517 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1521 /* entry exists, just modify secret if any */
1522 if (in->count == 0) {
1523 return NT_STATUS_OK;
1526 msg = ldb_msg_new(mem_ctx);
1527 if (!msg) {
1528 return NT_STATUS_NO_MEMORY;
1530 msg->dn = msgs[0]->dn;
1532 for (i = 0; i < in->count; i++) {
1533 const char *attribute;
1534 struct ldb_val v;
1535 switch (in->current.array[i].AuthType) {
1536 case TRUST_AUTH_TYPE_NT4OWF:
1537 attribute = "unicodePwd";
1538 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1539 v.length = 16;
1540 break;
1541 case TRUST_AUTH_TYPE_CLEAR:
1542 attribute = "clearTextPassword";
1543 v.data = in->current.array[i].AuthInfo.clear.password;
1544 v.length = in->current.array[i].AuthInfo.clear.size;
1545 break;
1546 default:
1547 continue;
1550 ret = ldb_msg_add_empty(msg, attribute,
1551 LDB_FLAG_MOD_REPLACE, NULL);
1552 if (ret != LDB_SUCCESS) {
1553 return NT_STATUS_NO_MEMORY;
1556 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1557 if (ret != LDB_SUCCESS) {
1558 return NT_STATUS_NO_MEMORY;
1562 /* create the trusted_domain user account */
1563 ret = ldb_modify(sam_ldb, msg);
1564 if (ret != LDB_SUCCESS) {
1565 DEBUG(0,("Failed to create user record %s: %s\n",
1566 ldb_dn_get_linearized(msg->dn),
1567 ldb_errstring(sam_ldb)));
1569 switch (ret) {
1570 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1571 return NT_STATUS_DOMAIN_EXISTS;
1572 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1573 return NT_STATUS_ACCESS_DENIED;
1574 default:
1575 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1579 return NT_STATUS_OK;
1583 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1584 struct dcesrv_handle *p_handle,
1585 TALLOC_CTX *mem_ctx,
1586 struct ldb_message *dom_msg,
1587 enum lsa_TrustDomInfoEnum level,
1588 union lsa_TrustedDomainInfo *info)
1590 struct lsa_policy_state *p_state = p_handle->data;
1591 uint32_t *posix_offset = NULL;
1592 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1593 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1594 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1595 uint32_t *enc_types = NULL;
1596 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1597 struct trustDomainPasswords auth_struct;
1598 NTSTATUS nt_status;
1599 struct ldb_message **msgs;
1600 struct ldb_message *msg;
1601 bool add_outgoing = false;
1602 bool add_incoming = false;
1603 bool del_outgoing = false;
1604 bool del_incoming = false;
1605 bool in_transaction = false;
1606 int ret;
1607 bool am_rodc;
1609 switch (level) {
1610 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1611 posix_offset = &info->posix_offset.posix_offset;
1612 break;
1613 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1614 info_ex = &info->info_ex;
1615 break;
1616 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1617 auth_info = &info->auth_info;
1618 break;
1619 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1620 posix_offset = &info->full_info.posix_offset.posix_offset;
1621 info_ex = &info->full_info.info_ex;
1622 auth_info = &info->full_info.auth_info;
1623 break;
1624 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1625 auth_info_int = &info->auth_info_internal;
1626 break;
1627 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1628 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1629 info_ex = &info->full_info_internal.info_ex;
1630 auth_info_int = &info->full_info_internal.auth_info;
1631 break;
1632 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1633 enc_types = &info->enc_types.enc_types;
1634 break;
1635 default:
1636 return NT_STATUS_INVALID_PARAMETER;
1639 if (auth_info) {
1640 /* FIXME: not handled yet */
1641 return NT_STATUS_INVALID_PARAMETER;
1644 /* decode auth_info_int if set */
1645 if (auth_info_int) {
1647 /* now decrypt blob */
1648 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1649 auth_info_int->auth_blob.size);
1651 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1652 &auth_blob, &auth_struct);
1653 if (!NT_STATUS_IS_OK(nt_status)) {
1654 return nt_status;
1658 if (info_ex) {
1659 /* verify data matches */
1660 if (info_ex->trust_attributes &
1661 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1662 /* TODO: check what behavior level we have */
1663 if (strcasecmp_m(p_state->domain_dns,
1664 p_state->forest_dns) != 0) {
1665 return NT_STATUS_INVALID_DOMAIN_STATE;
1669 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1670 if (ret == LDB_SUCCESS && am_rodc) {
1671 return NT_STATUS_NO_SUCH_DOMAIN;
1674 /* verify only one object matches the dns/netbios/sid
1675 * triplet and that this is the one we already have */
1676 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1677 p_state->system_dn,
1678 info_ex->domain_name.string,
1679 info_ex->netbios_name.string,
1680 info_ex->sid, &msgs);
1681 if (!NT_STATUS_IS_OK(nt_status)) {
1682 return nt_status;
1684 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1685 return NT_STATUS_OBJECT_NAME_COLLISION;
1687 talloc_free(msgs);
1690 /* TODO: should we fetch previous values from the existing entry
1691 * and append them ? */
1692 if (auth_struct.incoming.count) {
1693 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1694 &auth_struct.incoming,
1695 &trustAuthIncoming);
1696 if (!NT_STATUS_IS_OK(nt_status)) {
1697 return nt_status;
1699 } else {
1700 trustAuthIncoming = data_blob(NULL, 0);
1703 if (auth_struct.outgoing.count) {
1704 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1705 &auth_struct.outgoing,
1706 &trustAuthOutgoing);
1707 if (!NT_STATUS_IS_OK(nt_status)) {
1708 return nt_status;
1710 } else {
1711 trustAuthOutgoing = data_blob(NULL, 0);
1714 msg = ldb_msg_new(mem_ctx);
1715 if (msg == NULL) {
1716 return NT_STATUS_NO_MEMORY;
1718 msg->dn = dom_msg->dn;
1720 if (posix_offset) {
1721 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1722 dom_msg, msg,
1723 "trustPosixOffset",
1724 *posix_offset, NULL);
1725 if (!NT_STATUS_IS_OK(nt_status)) {
1726 return nt_status;
1730 if (info_ex) {
1731 uint32_t origattrs;
1732 uint32_t origdir;
1733 uint32_t tmp;
1734 int origtype;
1736 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1737 dom_msg, msg,
1738 "trustDirection",
1739 info_ex->trust_direction,
1740 &origdir);
1741 if (!NT_STATUS_IS_OK(nt_status)) {
1742 return nt_status;
1745 tmp = info_ex->trust_direction ^ origdir;
1746 if (tmp & LSA_TRUST_DIRECTION_INBOUND) {
1747 if (origdir & LSA_TRUST_DIRECTION_INBOUND) {
1748 del_incoming = true;
1749 } else {
1750 add_incoming = true;
1753 if (tmp & LSA_TRUST_DIRECTION_OUTBOUND) {
1754 if (origdir & LSA_TRUST_DIRECTION_OUTBOUND) {
1755 del_outgoing = true;
1756 } else {
1757 add_outgoing = true;
1761 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1762 if (origtype == -1 || origtype != info_ex->trust_type) {
1763 DEBUG(1, ("Attempted to change trust type! "
1764 "Operation not handled\n"));
1765 return NT_STATUS_INVALID_PARAMETER;
1768 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1769 dom_msg, msg,
1770 "trustAttributes",
1771 info_ex->trust_attributes,
1772 &origattrs);
1773 if (!NT_STATUS_IS_OK(nt_status)) {
1774 return nt_status;
1776 /* TODO: check forestFunctionality from ldb opaque */
1777 /* TODO: check what is set makes sense */
1778 /* for now refuse changes */
1779 if (origattrs == -1 ||
1780 origattrs != info_ex->trust_attributes) {
1781 DEBUG(1, ("Attempted to change trust attributes! "
1782 "Operation not handled\n"));
1783 return NT_STATUS_INVALID_PARAMETER;
1787 if (enc_types) {
1788 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1789 dom_msg, msg,
1790 "msDS-SupportedEncryptionTypes",
1791 *enc_types, NULL);
1792 if (!NT_STATUS_IS_OK(nt_status)) {
1793 return nt_status;
1797 if (add_incoming && trustAuthIncoming.data) {
1798 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1799 LDB_FLAG_MOD_REPLACE, NULL);
1800 if (ret != LDB_SUCCESS) {
1801 return NT_STATUS_NO_MEMORY;
1803 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1804 &trustAuthIncoming, NULL);
1805 if (ret != LDB_SUCCESS) {
1806 return NT_STATUS_NO_MEMORY;
1809 if (add_outgoing && trustAuthOutgoing.data) {
1810 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1811 LDB_FLAG_MOD_REPLACE, NULL);
1812 if (ret != LDB_SUCCESS) {
1813 return NT_STATUS_NO_MEMORY;
1815 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1816 &trustAuthOutgoing, NULL);
1817 if (ret != LDB_SUCCESS) {
1818 return NT_STATUS_NO_MEMORY;
1822 /* start transaction */
1823 ret = ldb_transaction_start(p_state->sam_ldb);
1824 if (ret != LDB_SUCCESS) {
1825 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1827 in_transaction = true;
1829 ret = ldb_modify(p_state->sam_ldb, msg);
1830 if (ret != LDB_SUCCESS) {
1831 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1832 ldb_dn_get_linearized(msg->dn),
1833 ldb_errstring(p_state->sam_ldb)));
1834 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
1835 nt_status = NT_STATUS_ACCESS_DENIED;
1836 } else {
1837 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1839 goto done;
1842 if (add_incoming || del_incoming) {
1843 const char *netbios_name;
1845 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1846 "flatname", NULL);
1847 if (!netbios_name) {
1848 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1849 goto done;
1852 nt_status = update_trust_user(mem_ctx,
1853 p_state->sam_ldb,
1854 p_state->domain_dn,
1855 del_incoming,
1856 netbios_name,
1857 &auth_struct.incoming);
1858 if (!NT_STATUS_IS_OK(nt_status)) {
1859 goto done;
1863 /* ok, all fine, commit transaction and return */
1864 ret = ldb_transaction_commit(p_state->sam_ldb);
1865 if (ret != LDB_SUCCESS) {
1866 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1868 in_transaction = false;
1870 nt_status = NT_STATUS_OK;
1872 done:
1873 if (in_transaction) {
1874 ldb_transaction_cancel(p_state->sam_ldb);
1876 return nt_status;
1880 lsa_SetInfomrationTrustedDomain
1882 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1883 struct dcesrv_call_state *dce_call,
1884 TALLOC_CTX *mem_ctx,
1885 struct lsa_SetInformationTrustedDomain *r)
1887 struct dcesrv_handle *h;
1888 struct lsa_trusted_domain_state *td_state;
1889 struct ldb_message **msgs;
1890 NTSTATUS nt_status;
1892 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1893 LSA_HANDLE_TRUSTED_DOMAIN);
1895 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1897 /* get the trusted domain object */
1898 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1899 td_state->trusted_domain_dn,
1900 NULL, NULL, NULL, &msgs);
1901 if (!NT_STATUS_IS_OK(nt_status)) {
1902 if (NT_STATUS_EQUAL(nt_status,
1903 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1904 return nt_status;
1906 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1909 return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1910 msgs[0], r->in.level, r->in.info);
1915 lsa_DeleteTrustedDomain
1917 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1918 struct lsa_DeleteTrustedDomain *r)
1920 NTSTATUS status;
1921 struct lsa_OpenTrustedDomain opn;
1922 struct lsa_DeleteObject del;
1923 struct dcesrv_handle *h;
1925 opn.in.handle = r->in.handle;
1926 opn.in.sid = r->in.dom_sid;
1927 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1928 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1929 if (!opn.out.trustdom_handle) {
1930 return NT_STATUS_NO_MEMORY;
1932 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1933 if (!NT_STATUS_IS_OK(status)) {
1934 return status;
1937 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1938 talloc_steal(mem_ctx, h);
1940 del.in.handle = opn.out.trustdom_handle;
1941 del.out.handle = opn.out.trustdom_handle;
1942 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1943 if (!NT_STATUS_IS_OK(status)) {
1944 return status;
1946 return NT_STATUS_OK;
1949 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
1950 struct ldb_message *msg,
1951 struct lsa_TrustDomainInfoInfoEx *info_ex)
1953 info_ex->domain_name.string
1954 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1955 info_ex->netbios_name.string
1956 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1957 info_ex->sid
1958 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1959 info_ex->trust_direction
1960 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1961 info_ex->trust_type
1962 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1963 info_ex->trust_attributes
1964 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
1965 return NT_STATUS_OK;
1969 lsa_QueryTrustedDomainInfo
1971 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1972 struct lsa_QueryTrustedDomainInfo *r)
1974 union lsa_TrustedDomainInfo *info = NULL;
1975 struct dcesrv_handle *h;
1976 struct lsa_trusted_domain_state *trusted_domain_state;
1977 struct ldb_message *msg;
1978 int ret;
1979 struct ldb_message **res;
1980 const char *attrs[] = {
1981 "flatname",
1982 "trustPartner",
1983 "securityIdentifier",
1984 "trustDirection",
1985 "trustType",
1986 "trustAttributes",
1987 "msDs-supportedEncryptionTypes",
1988 NULL
1991 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
1993 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1995 /* pull all the user attributes */
1996 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
1997 trusted_domain_state->trusted_domain_dn, &res, attrs);
1998 if (ret != 1) {
1999 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2001 msg = res[0];
2003 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2004 if (!info) {
2005 return NT_STATUS_NO_MEMORY;
2007 *r->out.info = info;
2009 switch (r->in.level) {
2010 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2011 info->name.netbios_name.string
2012 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2013 break;
2014 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2015 info->posix_offset.posix_offset
2016 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2017 break;
2018 #if 0 /* Win2k3 doesn't implement this */
2019 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2020 r->out.info->info_basic.netbios_name.string
2021 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2022 r->out.info->info_basic.sid
2023 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2024 break;
2025 #endif
2026 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2027 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2029 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2030 ZERO_STRUCT(info->full_info);
2031 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2032 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2033 ZERO_STRUCT(info->full_info2_internal);
2034 info->full_info2_internal.posix_offset.posix_offset
2035 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2036 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2038 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2039 info->enc_types.enc_types
2040 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2041 break;
2043 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2044 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2045 /* oops, we don't want to return the info after all */
2046 talloc_free(info);
2047 *r->out.info = NULL;
2048 return NT_STATUS_INVALID_PARAMETER;
2049 default:
2050 /* oops, we don't want to return the info after all */
2051 talloc_free(info);
2052 *r->out.info = NULL;
2053 return NT_STATUS_INVALID_INFO_CLASS;
2056 return NT_STATUS_OK;
2061 lsa_QueryTrustedDomainInfoBySid
2063 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2064 struct lsa_QueryTrustedDomainInfoBySid *r)
2066 NTSTATUS status;
2067 struct lsa_OpenTrustedDomain opn;
2068 struct lsa_QueryTrustedDomainInfo query;
2069 struct dcesrv_handle *h;
2071 opn.in.handle = r->in.handle;
2072 opn.in.sid = r->in.dom_sid;
2073 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2074 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2075 if (!opn.out.trustdom_handle) {
2076 return NT_STATUS_NO_MEMORY;
2078 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2079 if (!NT_STATUS_IS_OK(status)) {
2080 return status;
2083 /* Ensure this handle goes away at the end of this call */
2084 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2085 talloc_steal(mem_ctx, h);
2087 query.in.trustdom_handle = opn.out.trustdom_handle;
2088 query.in.level = r->in.level;
2089 query.out.info = r->out.info;
2090 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2091 if (!NT_STATUS_IS_OK(status)) {
2092 return status;
2095 return NT_STATUS_OK;
2099 lsa_SetTrustedDomainInfoByName
2101 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2102 TALLOC_CTX *mem_ctx,
2103 struct lsa_SetTrustedDomainInfoByName *r)
2105 struct dcesrv_handle *policy_handle;
2106 struct lsa_policy_state *policy_state;
2107 struct ldb_message **msgs;
2108 NTSTATUS nt_status;
2110 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2111 policy_state = policy_handle->data;
2113 /* get the trusted domain object */
2114 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2115 policy_state->domain_dn,
2116 r->in.trusted_domain->string,
2117 r->in.trusted_domain->string,
2118 NULL, &msgs);
2119 if (!NT_STATUS_IS_OK(nt_status)) {
2120 if (NT_STATUS_EQUAL(nt_status,
2121 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2122 return nt_status;
2124 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2127 return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2128 msgs[0], r->in.level, r->in.info);
2132 lsa_QueryTrustedDomainInfoByName
2134 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2135 TALLOC_CTX *mem_ctx,
2136 struct lsa_QueryTrustedDomainInfoByName *r)
2138 NTSTATUS status;
2139 struct lsa_OpenTrustedDomainByName opn;
2140 struct lsa_QueryTrustedDomainInfo query;
2141 struct dcesrv_handle *h;
2143 opn.in.handle = r->in.handle;
2144 opn.in.name = *r->in.trusted_domain;
2145 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2146 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2147 if (!opn.out.trustdom_handle) {
2148 return NT_STATUS_NO_MEMORY;
2150 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2151 if (!NT_STATUS_IS_OK(status)) {
2152 return status;
2155 /* Ensure this handle goes away at the end of this call */
2156 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2157 talloc_steal(mem_ctx, h);
2159 query.in.trustdom_handle = opn.out.trustdom_handle;
2160 query.in.level = r->in.level;
2161 query.out.info = r->out.info;
2162 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2163 if (!NT_STATUS_IS_OK(status)) {
2164 return status;
2167 return NT_STATUS_OK;
2171 lsa_CloseTrustedDomainEx
2173 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2174 TALLOC_CTX *mem_ctx,
2175 struct lsa_CloseTrustedDomainEx *r)
2177 /* The result of a bad hair day from an IDL programmer? Not
2178 * implmented in Win2k3. You should always just lsa_Close
2179 * anyway. */
2180 return NT_STATUS_NOT_IMPLEMENTED;
2185 comparison function for sorting lsa_DomainInformation array
2187 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2189 return strcasecmp_m(e1->name.string, e2->name.string);
2193 lsa_EnumTrustDom
2195 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2196 struct lsa_EnumTrustDom *r)
2198 struct dcesrv_handle *policy_handle;
2199 struct lsa_DomainInfo *entries;
2200 struct lsa_policy_state *policy_state;
2201 struct ldb_message **domains;
2202 const char *attrs[] = {
2203 "flatname",
2204 "securityIdentifier",
2205 NULL
2209 int count, i;
2211 *r->out.resume_handle = 0;
2213 r->out.domains->domains = NULL;
2214 r->out.domains->count = 0;
2216 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2218 policy_state = policy_handle->data;
2220 /* search for all users in this domain. This could possibly be cached and
2221 resumed based on resume_key */
2222 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2223 "objectclass=trustedDomain");
2224 if (count < 0) {
2225 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2228 /* convert to lsa_TrustInformation format */
2229 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2230 if (!entries) {
2231 return NT_STATUS_NO_MEMORY;
2233 for (i=0;i<count;i++) {
2234 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2235 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2238 /* sort the results by name */
2239 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2241 if (*r->in.resume_handle >= count) {
2242 *r->out.resume_handle = -1;
2244 return NT_STATUS_NO_MORE_ENTRIES;
2247 /* return the rest, limit by max_size. Note that we
2248 use the w2k3 element size value of 60 */
2249 r->out.domains->count = count - *r->in.resume_handle;
2250 r->out.domains->count = MIN(r->out.domains->count,
2251 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2253 r->out.domains->domains = entries + *r->in.resume_handle;
2254 r->out.domains->count = r->out.domains->count;
2256 if (r->out.domains->count < count - *r->in.resume_handle) {
2257 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2258 return STATUS_MORE_ENTRIES;
2261 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2262 * always be larger than the previous input resume handle, in
2263 * particular when hitting the last query it is vital to set the
2264 * resume handle correctly to avoid infinite client loops, as
2265 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2266 * status is NT_STATUS_OK - gd */
2268 *r->out.resume_handle = (uint32_t)-1;
2270 return NT_STATUS_OK;
2274 comparison function for sorting lsa_DomainInformation array
2276 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2278 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2282 lsa_EnumTrustedDomainsEx
2284 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2285 struct lsa_EnumTrustedDomainsEx *r)
2287 struct dcesrv_handle *policy_handle;
2288 struct lsa_TrustDomainInfoInfoEx *entries;
2289 struct lsa_policy_state *policy_state;
2290 struct ldb_message **domains;
2291 const char *attrs[] = {
2292 "flatname",
2293 "trustPartner",
2294 "securityIdentifier",
2295 "trustDirection",
2296 "trustType",
2297 "trustAttributes",
2298 NULL
2300 NTSTATUS nt_status;
2302 int count, i;
2304 *r->out.resume_handle = 0;
2306 r->out.domains->domains = NULL;
2307 r->out.domains->count = 0;
2309 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2311 policy_state = policy_handle->data;
2313 /* search for all users in this domain. This could possibly be cached and
2314 resumed based on resume_key */
2315 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2316 "objectclass=trustedDomain");
2317 if (count < 0) {
2318 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2321 /* convert to lsa_DomainInformation format */
2322 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2323 if (!entries) {
2324 return NT_STATUS_NO_MEMORY;
2326 for (i=0;i<count;i++) {
2327 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2328 if (!NT_STATUS_IS_OK(nt_status)) {
2329 return nt_status;
2333 /* sort the results by name */
2334 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2336 if (*r->in.resume_handle >= count) {
2337 *r->out.resume_handle = -1;
2339 return NT_STATUS_NO_MORE_ENTRIES;
2342 /* return the rest, limit by max_size. Note that we
2343 use the w2k3 element size value of 60 */
2344 r->out.domains->count = count - *r->in.resume_handle;
2345 r->out.domains->count = MIN(r->out.domains->count,
2346 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2348 r->out.domains->domains = entries + *r->in.resume_handle;
2349 r->out.domains->count = r->out.domains->count;
2351 if (r->out.domains->count < count - *r->in.resume_handle) {
2352 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2353 return STATUS_MORE_ENTRIES;
2356 return NT_STATUS_OK;
2361 lsa_OpenAccount
2363 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2364 struct lsa_OpenAccount *r)
2366 struct dcesrv_handle *h, *ah;
2367 struct lsa_policy_state *state;
2368 struct lsa_account_state *astate;
2370 ZERO_STRUCTP(r->out.acct_handle);
2372 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2374 state = h->data;
2376 astate = talloc(dce_call->conn, struct lsa_account_state);
2377 if (astate == NULL) {
2378 return NT_STATUS_NO_MEMORY;
2381 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2382 if (astate->account_sid == NULL) {
2383 talloc_free(astate);
2384 return NT_STATUS_NO_MEMORY;
2387 astate->policy = talloc_reference(astate, state);
2388 astate->access_mask = r->in.access_mask;
2390 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2391 if (!ah) {
2392 talloc_free(astate);
2393 return NT_STATUS_NO_MEMORY;
2396 ah->data = talloc_steal(ah, astate);
2398 *r->out.acct_handle = ah->wire_handle;
2400 return NT_STATUS_OK;
2405 lsa_EnumPrivsAccount
2407 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2408 TALLOC_CTX *mem_ctx,
2409 struct lsa_EnumPrivsAccount *r)
2411 struct dcesrv_handle *h;
2412 struct lsa_account_state *astate;
2413 int ret;
2414 unsigned int i, j;
2415 struct ldb_message **res;
2416 const char * const attrs[] = { "privilege", NULL};
2417 struct ldb_message_element *el;
2418 const char *sidstr;
2419 struct lsa_PrivilegeSet *privs;
2421 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2423 astate = h->data;
2425 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2426 if (privs == NULL) {
2427 return NT_STATUS_NO_MEMORY;
2429 privs->count = 0;
2430 privs->unknown = 0;
2431 privs->set = NULL;
2433 *r->out.privs = privs;
2435 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2436 if (sidstr == NULL) {
2437 return NT_STATUS_NO_MEMORY;
2440 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2441 "objectSid=%s", sidstr);
2442 if (ret < 0) {
2443 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2445 if (ret != 1) {
2446 return NT_STATUS_OK;
2449 el = ldb_msg_find_element(res[0], "privilege");
2450 if (el == NULL || el->num_values == 0) {
2451 return NT_STATUS_OK;
2454 privs->set = talloc_array(privs,
2455 struct lsa_LUIDAttribute, el->num_values);
2456 if (privs->set == NULL) {
2457 return NT_STATUS_NO_MEMORY;
2460 j = 0;
2461 for (i=0;i<el->num_values;i++) {
2462 int id = sec_privilege_id((const char *)el->values[i].data);
2463 if (id == SEC_PRIV_INVALID) {
2464 /* Perhaps an account right, not a privilege */
2465 continue;
2467 privs->set[j].attribute = 0;
2468 privs->set[j].luid.low = id;
2469 privs->set[j].luid.high = 0;
2470 j++;
2473 privs->count = j;
2475 return NT_STATUS_OK;
2479 lsa_EnumAccountRights
2481 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2482 TALLOC_CTX *mem_ctx,
2483 struct lsa_EnumAccountRights *r)
2485 struct dcesrv_handle *h;
2486 struct lsa_policy_state *state;
2487 int ret;
2488 unsigned int i;
2489 struct ldb_message **res;
2490 const char * const attrs[] = { "privilege", NULL};
2491 const char *sidstr;
2492 struct ldb_message_element *el;
2494 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2496 state = h->data;
2498 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2499 if (sidstr == NULL) {
2500 return NT_STATUS_NO_MEMORY;
2503 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2504 "(&(objectSid=%s)(privilege=*))", sidstr);
2505 if (ret == 0) {
2506 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2508 if (ret != 1) {
2509 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2510 dom_sid_string(mem_ctx, r->in.sid),
2511 ldb_errstring(state->pdb)));
2512 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2515 el = ldb_msg_find_element(res[0], "privilege");
2516 if (el == NULL || el->num_values == 0) {
2517 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2520 r->out.rights->count = el->num_values;
2521 r->out.rights->names = talloc_array(r->out.rights,
2522 struct lsa_StringLarge, r->out.rights->count);
2523 if (r->out.rights->names == NULL) {
2524 return NT_STATUS_NO_MEMORY;
2527 for (i=0;i<el->num_values;i++) {
2528 r->out.rights->names[i].string = (const char *)el->values[i].data;
2531 return NT_STATUS_OK;
2537 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2539 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2540 TALLOC_CTX *mem_ctx,
2541 struct lsa_policy_state *state,
2542 int ldb_flag,
2543 struct dom_sid *sid,
2544 const struct lsa_RightSet *rights)
2546 const char *sidstr, *sidndrstr;
2547 struct ldb_message *msg;
2548 struct ldb_message_element *el;
2549 int ret;
2550 uint32_t i;
2551 struct lsa_EnumAccountRights r2;
2552 char *dnstr;
2554 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2555 SECURITY_ADMINISTRATOR) {
2556 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2557 return NT_STATUS_ACCESS_DENIED;
2560 msg = ldb_msg_new(mem_ctx);
2561 if (msg == NULL) {
2562 return NT_STATUS_NO_MEMORY;
2565 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2566 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
2568 sidstr = dom_sid_string(msg, sid);
2569 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
2571 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2572 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
2574 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2575 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
2577 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2578 NTSTATUS status;
2580 r2.in.handle = &state->handle->wire_handle;
2581 r2.in.sid = sid;
2582 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2584 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2585 if (!NT_STATUS_IS_OK(status)) {
2586 ZERO_STRUCTP(r2.out.rights);
2590 for (i=0;i<rights->count;i++) {
2591 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2592 if (sec_right_bit(rights->names[i].string) == 0) {
2593 talloc_free(msg);
2594 return NT_STATUS_NO_SUCH_PRIVILEGE;
2597 talloc_free(msg);
2598 return NT_STATUS_NO_SUCH_PRIVILEGE;
2601 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2602 uint32_t j;
2603 for (j=0;j<r2.out.rights->count;j++) {
2604 if (strcasecmp_m(r2.out.rights->names[j].string,
2605 rights->names[i].string) == 0) {
2606 break;
2609 if (j != r2.out.rights->count) continue;
2612 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2613 if (ret != LDB_SUCCESS) {
2614 talloc_free(msg);
2615 return NT_STATUS_NO_MEMORY;
2619 el = ldb_msg_find_element(msg, "privilege");
2620 if (!el) {
2621 talloc_free(msg);
2622 return NT_STATUS_OK;
2625 el->flags = ldb_flag;
2627 ret = ldb_modify(state->pdb, msg);
2628 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2629 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2630 talloc_free(msg);
2631 return NT_STATUS_NO_MEMORY;
2633 ldb_msg_add_string(msg, "comment", "added via LSA");
2634 ret = ldb_add(state->pdb, msg);
2636 if (ret != LDB_SUCCESS) {
2637 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2638 talloc_free(msg);
2639 return NT_STATUS_OK;
2641 DEBUG(3, ("Could not %s attributes from %s: %s",
2642 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2643 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2644 talloc_free(msg);
2645 return NT_STATUS_UNEXPECTED_IO_ERROR;
2648 talloc_free(msg);
2649 return NT_STATUS_OK;
2653 lsa_AddPrivilegesToAccount
2655 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2656 struct lsa_AddPrivilegesToAccount *r)
2658 struct lsa_RightSet rights;
2659 struct dcesrv_handle *h;
2660 struct lsa_account_state *astate;
2661 uint32_t i;
2663 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2665 astate = h->data;
2667 rights.count = r->in.privs->count;
2668 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2669 if (rights.names == NULL) {
2670 return NT_STATUS_NO_MEMORY;
2672 for (i=0;i<rights.count;i++) {
2673 int id = r->in.privs->set[i].luid.low;
2674 if (r->in.privs->set[i].luid.high) {
2675 return NT_STATUS_NO_SUCH_PRIVILEGE;
2677 rights.names[i].string = sec_privilege_name(id);
2678 if (rights.names[i].string == NULL) {
2679 return NT_STATUS_NO_SUCH_PRIVILEGE;
2683 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2684 LDB_FLAG_MOD_ADD, astate->account_sid,
2685 &rights);
2690 lsa_RemovePrivilegesFromAccount
2692 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2693 struct lsa_RemovePrivilegesFromAccount *r)
2695 struct lsa_RightSet *rights;
2696 struct dcesrv_handle *h;
2697 struct lsa_account_state *astate;
2698 uint32_t i;
2700 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2702 astate = h->data;
2704 rights = talloc(mem_ctx, struct lsa_RightSet);
2706 if (r->in.remove_all == 1 &&
2707 r->in.privs == NULL) {
2708 struct lsa_EnumAccountRights r2;
2709 NTSTATUS status;
2711 r2.in.handle = &astate->policy->handle->wire_handle;
2712 r2.in.sid = astate->account_sid;
2713 r2.out.rights = rights;
2715 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2716 if (!NT_STATUS_IS_OK(status)) {
2717 return status;
2720 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2721 LDB_FLAG_MOD_DELETE, astate->account_sid,
2722 r2.out.rights);
2725 if (r->in.remove_all != 0) {
2726 return NT_STATUS_INVALID_PARAMETER;
2729 rights->count = r->in.privs->count;
2730 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2731 if (rights->names == NULL) {
2732 return NT_STATUS_NO_MEMORY;
2734 for (i=0;i<rights->count;i++) {
2735 int id = r->in.privs->set[i].luid.low;
2736 if (r->in.privs->set[i].luid.high) {
2737 return NT_STATUS_NO_SUCH_PRIVILEGE;
2739 rights->names[i].string = sec_privilege_name(id);
2740 if (rights->names[i].string == NULL) {
2741 return NT_STATUS_NO_SUCH_PRIVILEGE;
2745 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2746 LDB_FLAG_MOD_DELETE, astate->account_sid,
2747 rights);
2752 lsa_GetQuotasForAccount
2754 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2755 struct lsa_GetQuotasForAccount *r)
2757 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2762 lsa_SetQuotasForAccount
2764 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2765 struct lsa_SetQuotasForAccount *r)
2767 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2772 lsa_GetSystemAccessAccount
2774 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2775 struct lsa_GetSystemAccessAccount *r)
2777 struct dcesrv_handle *h;
2778 struct lsa_account_state *astate;
2779 int ret;
2780 unsigned int i;
2781 struct ldb_message **res;
2782 const char * const attrs[] = { "privilege", NULL};
2783 struct ldb_message_element *el;
2784 const char *sidstr;
2786 *(r->out.access_mask) = 0x00000000;
2788 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2790 astate = h->data;
2792 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2793 if (sidstr == NULL) {
2794 return NT_STATUS_NO_MEMORY;
2797 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2798 "objectSid=%s", sidstr);
2799 if (ret < 0) {
2800 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2802 if (ret != 1) {
2803 return NT_STATUS_OK;
2806 el = ldb_msg_find_element(res[0], "privilege");
2807 if (el == NULL || el->num_values == 0) {
2808 return NT_STATUS_OK;
2811 for (i=0;i<el->num_values;i++) {
2812 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2813 if (right_bit == 0) {
2814 /* Perhaps an privilege, not a right */
2815 continue;
2817 *(r->out.access_mask) |= right_bit;
2820 return NT_STATUS_OK;
2825 lsa_SetSystemAccessAccount
2827 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2828 struct lsa_SetSystemAccessAccount *r)
2830 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2835 lsa_CreateSecret
2837 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2838 struct lsa_CreateSecret *r)
2840 struct dcesrv_handle *policy_handle;
2841 struct lsa_policy_state *policy_state;
2842 struct lsa_secret_state *secret_state;
2843 struct dcesrv_handle *handle;
2844 struct ldb_message **msgs, *msg;
2845 const char *attrs[] = {
2846 NULL
2849 const char *name;
2851 int ret;
2853 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2854 ZERO_STRUCTP(r->out.sec_handle);
2856 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2858 case SECURITY_SYSTEM:
2859 case SECURITY_ADMINISTRATOR:
2860 break;
2861 default:
2862 /* Users and annonymous are not allowed create secrets */
2863 return NT_STATUS_ACCESS_DENIED;
2866 policy_state = policy_handle->data;
2868 if (!r->in.name.string) {
2869 return NT_STATUS_INVALID_PARAMETER;
2872 secret_state = talloc(mem_ctx, struct lsa_secret_state);
2873 NT_STATUS_HAVE_NO_MEMORY(secret_state);
2874 secret_state->policy = policy_state;
2876 msg = ldb_msg_new(mem_ctx);
2877 if (msg == NULL) {
2878 return NT_STATUS_NO_MEMORY;
2881 if (strncmp("G$", r->in.name.string, 2) == 0) {
2882 const char *name2;
2884 secret_state->global = true;
2886 name = &r->in.name.string[2];
2887 if (strlen(name) == 0) {
2888 return NT_STATUS_INVALID_PARAMETER;
2891 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2892 ldb_binary_encode_string(mem_ctx, name));
2893 NT_STATUS_HAVE_NO_MEMORY(name2);
2895 /* We need to connect to the database as system, as this is one
2896 * of the rare RPC calls that must read the secrets (and this
2897 * is denied otherwise) */
2898 secret_state->sam_ldb = talloc_reference(secret_state,
2899 samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
2900 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2902 /* search for the secret record */
2903 ret = gendb_search(secret_state->sam_ldb,
2904 mem_ctx, policy_state->system_dn, &msgs, attrs,
2905 "(&(cn=%s)(objectclass=secret))",
2906 name2);
2907 if (ret > 0) {
2908 return NT_STATUS_OBJECT_NAME_COLLISION;
2911 if (ret < 0) {
2912 DEBUG(0,("Failure searching for CN=%s: %s\n",
2913 name2, ldb_errstring(secret_state->sam_ldb)));
2914 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2917 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2918 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2919 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2920 return NT_STATUS_NO_MEMORY;
2923 ret = ldb_msg_add_string(msg, "cn", name2);
2924 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2925 } else {
2926 secret_state->global = false;
2928 name = r->in.name.string;
2929 if (strlen(name) == 0) {
2930 return NT_STATUS_INVALID_PARAMETER;
2933 secret_state->sam_ldb = talloc_reference(secret_state,
2934 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
2935 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2937 /* search for the secret record */
2938 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2939 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2940 &msgs, attrs,
2941 "(&(cn=%s)(objectclass=secret))",
2942 ldb_binary_encode_string(mem_ctx, name));
2943 if (ret > 0) {
2944 return NT_STATUS_OBJECT_NAME_COLLISION;
2947 if (ret < 0) {
2948 DEBUG(0,("Failure searching for CN=%s: %s\n",
2949 name, ldb_errstring(secret_state->sam_ldb)));
2950 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2953 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
2954 "cn=%s,cn=LSA Secrets", name);
2955 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2956 ret = ldb_msg_add_string(msg, "cn", name);
2957 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2960 ret = ldb_msg_add_string(msg, "objectClass", "secret");
2961 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2963 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2964 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
2966 /* create the secret */
2967 ret = ldb_add(secret_state->sam_ldb, msg);
2968 if (ret != LDB_SUCCESS) {
2969 DEBUG(0,("Failed to create secret record %s: %s\n",
2970 ldb_dn_get_linearized(msg->dn),
2971 ldb_errstring(secret_state->sam_ldb)));
2972 return NT_STATUS_ACCESS_DENIED;
2975 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2976 NT_STATUS_HAVE_NO_MEMORY(handle);
2978 handle->data = talloc_steal(handle, secret_state);
2980 secret_state->access_mask = r->in.access_mask;
2981 secret_state->policy = talloc_reference(secret_state, policy_state);
2982 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
2984 *r->out.sec_handle = handle->wire_handle;
2986 return NT_STATUS_OK;
2991 lsa_OpenSecret
2993 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2994 struct lsa_OpenSecret *r)
2996 struct dcesrv_handle *policy_handle;
2998 struct lsa_policy_state *policy_state;
2999 struct lsa_secret_state *secret_state;
3000 struct dcesrv_handle *handle;
3001 struct ldb_message **msgs;
3002 const char *attrs[] = {
3003 NULL
3006 const char *name;
3008 int ret;
3010 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3011 ZERO_STRUCTP(r->out.sec_handle);
3012 policy_state = policy_handle->data;
3014 if (!r->in.name.string) {
3015 return NT_STATUS_INVALID_PARAMETER;
3018 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3020 case SECURITY_SYSTEM:
3021 case SECURITY_ADMINISTRATOR:
3022 break;
3023 default:
3024 /* Users and annonymous are not allowed to access secrets */
3025 return NT_STATUS_ACCESS_DENIED;
3028 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3029 if (!secret_state) {
3030 return NT_STATUS_NO_MEMORY;
3032 secret_state->policy = policy_state;
3034 if (strncmp("G$", r->in.name.string, 2) == 0) {
3035 name = &r->in.name.string[2];
3036 /* 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) */
3037 secret_state->sam_ldb = talloc_reference(secret_state,
3038 samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
3039 secret_state->global = true;
3041 if (strlen(name) < 1) {
3042 return NT_STATUS_INVALID_PARAMETER;
3045 /* search for the secret record */
3046 ret = gendb_search(secret_state->sam_ldb,
3047 mem_ctx, policy_state->system_dn, &msgs, attrs,
3048 "(&(cn=%s Secret)(objectclass=secret))",
3049 ldb_binary_encode_string(mem_ctx, name));
3050 if (ret == 0) {
3051 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3054 if (ret != 1) {
3055 DEBUG(0,("Found %d records matching DN %s\n", ret,
3056 ldb_dn_get_linearized(policy_state->system_dn)));
3057 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3060 } else {
3061 secret_state->global = false;
3062 secret_state->sam_ldb = talloc_reference(secret_state,
3063 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3065 name = r->in.name.string;
3066 if (strlen(name) < 1) {
3067 return NT_STATUS_INVALID_PARAMETER;
3070 /* search for the secret record */
3071 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3072 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3073 &msgs, attrs,
3074 "(&(cn=%s)(objectclass=secret))",
3075 ldb_binary_encode_string(mem_ctx, name));
3076 if (ret == 0) {
3077 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3080 if (ret != 1) {
3081 DEBUG(0,("Found %d records matching CN=%s\n",
3082 ret, ldb_binary_encode_string(mem_ctx, name)));
3083 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3087 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3089 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3090 if (!handle) {
3091 return NT_STATUS_NO_MEMORY;
3094 handle->data = talloc_steal(handle, secret_state);
3096 secret_state->access_mask = r->in.access_mask;
3097 secret_state->policy = talloc_reference(secret_state, policy_state);
3099 *r->out.sec_handle = handle->wire_handle;
3101 return NT_STATUS_OK;
3106 lsa_SetSecret
3108 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3109 struct lsa_SetSecret *r)
3112 struct dcesrv_handle *h;
3113 struct lsa_secret_state *secret_state;
3114 struct ldb_message *msg;
3115 DATA_BLOB session_key;
3116 DATA_BLOB crypt_secret, secret;
3117 struct ldb_val val;
3118 int ret;
3119 NTSTATUS status = NT_STATUS_OK;
3121 struct timeval now = timeval_current();
3122 NTTIME nt_now = timeval_to_nttime(&now);
3124 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3126 secret_state = h->data;
3128 msg = ldb_msg_new(mem_ctx);
3129 if (msg == NULL) {
3130 return NT_STATUS_NO_MEMORY;
3133 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3134 if (!msg->dn) {
3135 return NT_STATUS_NO_MEMORY;
3137 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3138 if (!NT_STATUS_IS_OK(status)) {
3139 return status;
3142 if (r->in.old_val) {
3143 /* Decrypt */
3144 crypt_secret.data = r->in.old_val->data;
3145 crypt_secret.length = r->in.old_val->size;
3147 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3148 if (!NT_STATUS_IS_OK(status)) {
3149 return status;
3152 val.data = secret.data;
3153 val.length = secret.length;
3155 /* set value */
3156 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3157 return NT_STATUS_NO_MEMORY;
3160 /* set old value mtime */
3161 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3162 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3163 return NT_STATUS_NO_MEMORY;
3166 } else {
3167 /* If the old value is not set, then migrate the
3168 * current value to the old value */
3169 const struct ldb_val *old_val;
3170 NTTIME last_set_time;
3171 struct ldb_message **res;
3172 const char *attrs[] = {
3173 "currentValue",
3174 "lastSetTime",
3175 NULL
3178 /* search for the secret record */
3179 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3180 secret_state->secret_dn, &res, attrs);
3181 if (ret == 0) {
3182 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3185 if (ret != 1) {
3186 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3187 ldb_dn_get_linearized(secret_state->secret_dn)));
3188 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3191 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3192 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3194 if (old_val) {
3195 /* set old value */
3196 if (ldb_msg_add_value(msg, "priorValue",
3197 old_val, NULL) != LDB_SUCCESS) {
3198 return NT_STATUS_NO_MEMORY;
3200 } else {
3201 if (samdb_msg_add_delete(secret_state->sam_ldb,
3202 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3203 return NT_STATUS_NO_MEMORY;
3208 /* set old value mtime */
3209 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3210 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3211 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3212 return NT_STATUS_NO_MEMORY;
3214 } else {
3215 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3216 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3217 return NT_STATUS_NO_MEMORY;
3222 if (r->in.new_val) {
3223 /* Decrypt */
3224 crypt_secret.data = r->in.new_val->data;
3225 crypt_secret.length = r->in.new_val->size;
3227 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3228 if (!NT_STATUS_IS_OK(status)) {
3229 return status;
3232 val.data = secret.data;
3233 val.length = secret.length;
3235 /* set value */
3236 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3237 return NT_STATUS_NO_MEMORY;
3240 /* set new value mtime */
3241 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3242 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3243 return NT_STATUS_NO_MEMORY;
3246 } else {
3247 /* NULL out the NEW value */
3248 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3249 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3250 return NT_STATUS_NO_MEMORY;
3252 if (samdb_msg_add_delete(secret_state->sam_ldb,
3253 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3254 return NT_STATUS_NO_MEMORY;
3258 /* modify the samdb record */
3259 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3260 if (ret != LDB_SUCCESS) {
3261 return dsdb_ldb_err_to_ntstatus(ret);
3264 return NT_STATUS_OK;
3269 lsa_QuerySecret
3271 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3272 struct lsa_QuerySecret *r)
3274 struct dcesrv_handle *h;
3275 struct lsa_secret_state *secret_state;
3276 struct ldb_message *msg;
3277 DATA_BLOB session_key;
3278 DATA_BLOB crypt_secret, secret;
3279 int ret;
3280 struct ldb_message **res;
3281 const char *attrs[] = {
3282 "currentValue",
3283 "priorValue",
3284 "lastSetTime",
3285 "priorSetTime",
3286 NULL
3289 NTSTATUS nt_status;
3291 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3293 /* Ensure user is permitted to read this... */
3294 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3296 case SECURITY_SYSTEM:
3297 case SECURITY_ADMINISTRATOR:
3298 break;
3299 default:
3300 /* Users and annonymous are not allowed to read secrets */
3301 return NT_STATUS_ACCESS_DENIED;
3304 secret_state = h->data;
3306 /* pull all the user attributes */
3307 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3308 secret_state->secret_dn, &res, attrs);
3309 if (ret != 1) {
3310 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3312 msg = res[0];
3314 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3315 if (!NT_STATUS_IS_OK(nt_status)) {
3316 return nt_status;
3319 if (r->in.old_val) {
3320 const struct ldb_val *prior_val;
3321 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3322 if (!r->out.old_val) {
3323 return NT_STATUS_NO_MEMORY;
3325 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
3327 if (prior_val && prior_val->length) {
3328 secret.data = prior_val->data;
3329 secret.length = prior_val->length;
3331 /* Encrypt */
3332 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3333 if (!crypt_secret.length) {
3334 return NT_STATUS_NO_MEMORY;
3336 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3337 if (!r->out.old_val->buf) {
3338 return NT_STATUS_NO_MEMORY;
3340 r->out.old_val->buf->size = crypt_secret.length;
3341 r->out.old_val->buf->length = crypt_secret.length;
3342 r->out.old_val->buf->data = crypt_secret.data;
3346 if (r->in.old_mtime) {
3347 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3348 if (!r->out.old_mtime) {
3349 return NT_STATUS_NO_MEMORY;
3351 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
3354 if (r->in.new_val) {
3355 const struct ldb_val *new_val;
3356 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3357 if (!r->out.new_val) {
3358 return NT_STATUS_NO_MEMORY;
3361 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3363 if (new_val && new_val->length) {
3364 secret.data = new_val->data;
3365 secret.length = new_val->length;
3367 /* Encrypt */
3368 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3369 if (!crypt_secret.length) {
3370 return NT_STATUS_NO_MEMORY;
3372 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3373 if (!r->out.new_val->buf) {
3374 return NT_STATUS_NO_MEMORY;
3376 r->out.new_val->buf->length = crypt_secret.length;
3377 r->out.new_val->buf->size = crypt_secret.length;
3378 r->out.new_val->buf->data = crypt_secret.data;
3382 if (r->in.new_mtime) {
3383 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3384 if (!r->out.new_mtime) {
3385 return NT_STATUS_NO_MEMORY;
3387 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3390 return NT_STATUS_OK;
3395 lsa_LookupPrivValue
3397 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3398 TALLOC_CTX *mem_ctx,
3399 struct lsa_LookupPrivValue *r)
3401 struct dcesrv_handle *h;
3402 struct lsa_policy_state *state;
3403 int id;
3405 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3407 state = h->data;
3409 id = sec_privilege_id(r->in.name->string);
3410 if (id == SEC_PRIV_INVALID) {
3411 return NT_STATUS_NO_SUCH_PRIVILEGE;
3414 r->out.luid->low = id;
3415 r->out.luid->high = 0;
3417 return NT_STATUS_OK;
3422 lsa_LookupPrivName
3424 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3425 TALLOC_CTX *mem_ctx,
3426 struct lsa_LookupPrivName *r)
3428 struct dcesrv_handle *h;
3429 struct lsa_policy_state *state;
3430 struct lsa_StringLarge *name;
3431 const char *privname;
3433 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3435 state = h->data;
3437 if (r->in.luid->high != 0) {
3438 return NT_STATUS_NO_SUCH_PRIVILEGE;
3441 privname = sec_privilege_name(r->in.luid->low);
3442 if (privname == NULL) {
3443 return NT_STATUS_NO_SUCH_PRIVILEGE;
3446 name = talloc(mem_ctx, struct lsa_StringLarge);
3447 if (name == NULL) {
3448 return NT_STATUS_NO_MEMORY;
3451 name->string = privname;
3453 *r->out.name = name;
3455 return NT_STATUS_OK;
3460 lsa_LookupPrivDisplayName
3462 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3463 TALLOC_CTX *mem_ctx,
3464 struct lsa_LookupPrivDisplayName *r)
3466 struct dcesrv_handle *h;
3467 struct lsa_policy_state *state;
3468 struct lsa_StringLarge *disp_name = NULL;
3469 enum sec_privilege id;
3471 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3473 state = h->data;
3475 id = sec_privilege_id(r->in.name->string);
3476 if (id == SEC_PRIV_INVALID) {
3477 return NT_STATUS_NO_SUCH_PRIVILEGE;
3480 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3481 if (disp_name == NULL) {
3482 return NT_STATUS_NO_MEMORY;
3485 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3486 if (disp_name->string == NULL) {
3487 return NT_STATUS_INTERNAL_ERROR;
3490 *r->out.disp_name = disp_name;
3491 *r->out.returned_language_id = 0;
3493 return NT_STATUS_OK;
3498 lsa_EnumAccountsWithUserRight
3500 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3501 TALLOC_CTX *mem_ctx,
3502 struct lsa_EnumAccountsWithUserRight *r)
3504 struct dcesrv_handle *h;
3505 struct lsa_policy_state *state;
3506 int ret, i;
3507 struct ldb_message **res;
3508 const char * const attrs[] = { "objectSid", NULL};
3509 const char *privname;
3511 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3513 state = h->data;
3515 if (r->in.name == NULL) {
3516 return NT_STATUS_NO_SUCH_PRIVILEGE;
3519 privname = r->in.name->string;
3520 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3521 return NT_STATUS_NO_SUCH_PRIVILEGE;
3524 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3525 "privilege=%s", privname);
3526 if (ret < 0) {
3527 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3529 if (ret == 0) {
3530 return NT_STATUS_NO_MORE_ENTRIES;
3533 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3534 if (r->out.sids->sids == NULL) {
3535 return NT_STATUS_NO_MEMORY;
3537 for (i=0;i<ret;i++) {
3538 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3539 res[i], "objectSid");
3540 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3542 r->out.sids->num_sids = ret;
3544 return NT_STATUS_OK;
3549 lsa_AddAccountRights
3551 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3552 TALLOC_CTX *mem_ctx,
3553 struct lsa_AddAccountRights *r)
3555 struct dcesrv_handle *h;
3556 struct lsa_policy_state *state;
3558 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3560 state = h->data;
3562 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3563 LDB_FLAG_MOD_ADD,
3564 r->in.sid, r->in.rights);
3569 lsa_RemoveAccountRights
3571 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3572 TALLOC_CTX *mem_ctx,
3573 struct lsa_RemoveAccountRights *r)
3575 struct dcesrv_handle *h;
3576 struct lsa_policy_state *state;
3578 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3580 state = h->data;
3582 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3583 LDB_FLAG_MOD_DELETE,
3584 r->in.sid, r->in.rights);
3589 lsa_StorePrivateData
3591 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3592 struct lsa_StorePrivateData *r)
3594 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3599 lsa_RetrievePrivateData
3601 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3602 struct lsa_RetrievePrivateData *r)
3604 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3609 lsa_GetUserName
3611 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3612 struct lsa_GetUserName *r)
3614 NTSTATUS status = NT_STATUS_OK;
3615 const char *account_name;
3616 const char *authority_name;
3617 struct lsa_String *_account_name;
3618 struct lsa_String *_authority_name = NULL;
3620 /* this is what w2k3 does */
3621 r->out.account_name = r->in.account_name;
3622 r->out.authority_name = r->in.authority_name;
3624 if (r->in.account_name
3625 && *r->in.account_name
3626 /* && *(*r->in.account_name)->string */
3628 return NT_STATUS_INVALID_PARAMETER;
3631 if (r->in.authority_name
3632 && *r->in.authority_name
3633 /* && *(*r->in.authority_name)->string */
3635 return NT_STATUS_INVALID_PARAMETER;
3638 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3639 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3641 _account_name = talloc(mem_ctx, struct lsa_String);
3642 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3643 _account_name->string = account_name;
3645 if (r->in.authority_name) {
3646 _authority_name = talloc(mem_ctx, struct lsa_String);
3647 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3648 _authority_name->string = authority_name;
3651 *r->out.account_name = _account_name;
3652 if (r->out.authority_name) {
3653 *r->out.authority_name = _authority_name;
3656 return status;
3660 lsa_SetInfoPolicy2
3662 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3663 TALLOC_CTX *mem_ctx,
3664 struct lsa_SetInfoPolicy2 *r)
3666 /* need to support these */
3667 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3671 lsa_QueryDomainInformationPolicy
3673 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3674 TALLOC_CTX *mem_ctx,
3675 struct lsa_QueryDomainInformationPolicy *r)
3677 union lsa_DomainInformationPolicy *info;
3679 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3680 if (!info) {
3681 return NT_STATUS_NO_MEMORY;
3684 switch (r->in.level) {
3685 case LSA_DOMAIN_INFO_POLICY_EFS:
3686 talloc_free(info);
3687 *r->out.info = NULL;
3688 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3689 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3691 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3692 struct smb_krb5_context *smb_krb5_context;
3693 int ret = smb_krb5_init_context(mem_ctx,
3694 dce_call->event_ctx,
3695 dce_call->conn->dce_ctx->lp_ctx,
3696 &smb_krb5_context);
3697 if (ret != 0) {
3698 talloc_free(info);
3699 *r->out.info = NULL;
3700 return NT_STATUS_INTERNAL_ERROR;
3702 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3703 smb_krb5_context,
3705 talloc_free(smb_krb5_context);
3706 *r->out.info = info;
3707 return NT_STATUS_OK;
3709 default:
3710 talloc_free(info);
3711 *r->out.info = NULL;
3712 return NT_STATUS_INVALID_INFO_CLASS;
3717 lsa_SetDomInfoPolicy
3719 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3720 TALLOC_CTX *mem_ctx,
3721 struct lsa_SetDomainInformationPolicy *r)
3723 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3727 lsa_TestCall
3729 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3730 TALLOC_CTX *mem_ctx,
3731 struct lsa_TestCall *r)
3733 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3737 lsa_CREDRWRITE
3739 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3740 struct lsa_CREDRWRITE *r)
3742 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3747 lsa_CREDRREAD
3749 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3750 struct lsa_CREDRREAD *r)
3752 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3757 lsa_CREDRENUMERATE
3759 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3760 struct lsa_CREDRENUMERATE *r)
3762 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3767 lsa_CREDRWRITEDOMAINCREDENTIALS
3769 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3770 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3772 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3777 lsa_CREDRREADDOMAINCREDENTIALS
3779 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3780 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3782 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3787 lsa_CREDRDELETE
3789 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3790 struct lsa_CREDRDELETE *r)
3792 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3797 lsa_CREDRGETTARGETINFO
3799 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3800 struct lsa_CREDRGETTARGETINFO *r)
3802 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3807 lsa_CREDRPROFILELOADED
3809 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3810 struct lsa_CREDRPROFILELOADED *r)
3812 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3817 lsa_CREDRGETSESSIONTYPES
3819 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3820 struct lsa_CREDRGETSESSIONTYPES *r)
3822 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3827 lsa_LSARREGISTERAUDITEVENT
3829 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3830 struct lsa_LSARREGISTERAUDITEVENT *r)
3832 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3837 lsa_LSARGENAUDITEVENT
3839 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3840 struct lsa_LSARGENAUDITEVENT *r)
3842 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3847 lsa_LSARUNREGISTERAUDITEVENT
3849 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3850 struct lsa_LSARUNREGISTERAUDITEVENT *r)
3852 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3857 lsa_lsaRQueryForestTrustInformation
3859 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3860 struct lsa_lsaRQueryForestTrustInformation *r)
3862 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3865 #define DNS_CMP_MATCH 0
3866 #define DNS_CMP_FIRST_IS_CHILD 1
3867 #define DNS_CMP_SECOND_IS_CHILD 2
3868 #define DNS_CMP_NO_MATCH 3
3870 /* this function assumes names are well formed DNS names.
3871 * it doesn't validate them */
3872 static int dns_cmp(const char *s1, size_t l1,
3873 const char *s2, size_t l2)
3875 const char *p1, *p2;
3876 size_t t1, t2;
3877 int cret;
3879 if (l1 == l2) {
3880 if (strcasecmp_m(s1, s2) == 0) {
3881 return DNS_CMP_MATCH;
3883 return DNS_CMP_NO_MATCH;
3886 if (l1 > l2) {
3887 p1 = s1;
3888 p2 = s2;
3889 t1 = l1;
3890 t2 = l2;
3891 cret = DNS_CMP_FIRST_IS_CHILD;
3892 } else {
3893 p1 = s2;
3894 p2 = s1;
3895 t1 = l2;
3896 t2 = l1;
3897 cret = DNS_CMP_SECOND_IS_CHILD;
3900 if (p1[t1 - t2 - 1] != '.') {
3901 return DNS_CMP_NO_MATCH;
3904 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3905 return cret;
3908 return DNS_CMP_NO_MATCH;
3911 /* decode all TDOs forest trust info blobs */
3912 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3913 struct ldb_message *msg,
3914 struct ForestTrustInfo *info)
3916 const struct ldb_val *ft_blob;
3917 enum ndr_err_code ndr_err;
3919 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3920 if (!ft_blob || !ft_blob->data) {
3921 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3923 /* ldb_val is equivalent to DATA_BLOB */
3924 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3925 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3926 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3927 return NT_STATUS_INVALID_DOMAIN_STATE;
3930 return NT_STATUS_OK;
3933 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
3934 struct ForestTrustInfo *fti)
3936 struct ForestTrustDataDomainInfo *info;
3937 struct ForestTrustInfoRecord *rec;
3939 fti->version = 1;
3940 fti->count = 2;
3941 fti->records = talloc_array(fti,
3942 struct ForestTrustInfoRecordArmor, 2);
3943 if (!fti->records) {
3944 return NT_STATUS_NO_MEMORY;
3947 /* TLN info */
3948 rec = &fti->records[0].record;
3950 rec->flags = 0;
3951 rec->timestamp = 0;
3952 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
3954 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
3955 if (!rec->data.name.string) {
3956 return NT_STATUS_NO_MEMORY;
3958 rec->data.name.size = strlen(rec->data.name.string);
3960 /* DOMAIN info */
3961 rec = &fti->records[1].record;
3963 rec->flags = 0;
3964 rec->timestamp = 0;
3965 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
3967 info = &rec->data.info;
3969 info->sid = *ps->domain_sid;
3970 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
3971 if (!info->dns_name.string) {
3972 return NT_STATUS_NO_MEMORY;
3974 info->dns_name.size = strlen(info->dns_name.string);
3975 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
3976 if (!info->netbios_name.string) {
3977 return NT_STATUS_NO_MEMORY;
3979 info->netbios_name.size = strlen(info->netbios_name.string);
3981 return NT_STATUS_OK;
3984 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
3985 struct lsa_ForestTrustInformation *lfti,
3986 struct ForestTrustInfo *fti)
3988 struct lsa_ForestTrustRecord *lrec;
3989 struct ForestTrustInfoRecord *rec;
3990 struct lsa_StringLarge *tln;
3991 struct lsa_ForestTrustDomainInfo *info;
3992 uint32_t i;
3994 fti->version = 1;
3995 fti->count = lfti->count;
3996 fti->records = talloc_array(mem_ctx,
3997 struct ForestTrustInfoRecordArmor,
3998 fti->count);
3999 if (!fti->records) {
4000 return NT_STATUS_NO_MEMORY;
4002 for (i = 0; i < fti->count; i++) {
4003 lrec = lfti->entries[i];
4004 rec = &fti->records[i].record;
4006 rec->flags = lrec->flags;
4007 rec->timestamp = lrec->time;
4008 rec->type = lrec->type;
4010 switch (lrec->type) {
4011 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4012 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4013 tln = &lrec->forest_trust_data.top_level_name;
4014 rec->data.name.string =
4015 talloc_strdup(mem_ctx, tln->string);
4016 if (!rec->data.name.string) {
4017 return NT_STATUS_NO_MEMORY;
4019 rec->data.name.size = strlen(rec->data.name.string);
4020 break;
4021 case LSA_FOREST_TRUST_DOMAIN_INFO:
4022 info = &lrec->forest_trust_data.domain_info;
4023 rec->data.info.sid = *info->domain_sid;
4024 rec->data.info.dns_name.string =
4025 talloc_strdup(mem_ctx,
4026 info->dns_domain_name.string);
4027 if (!rec->data.info.dns_name.string) {
4028 return NT_STATUS_NO_MEMORY;
4030 rec->data.info.dns_name.size =
4031 strlen(rec->data.info.dns_name.string);
4032 rec->data.info.netbios_name.string =
4033 talloc_strdup(mem_ctx,
4034 info->netbios_domain_name.string);
4035 if (!rec->data.info.netbios_name.string) {
4036 return NT_STATUS_NO_MEMORY;
4038 rec->data.info.netbios_name.size =
4039 strlen(rec->data.info.netbios_name.string);
4040 break;
4041 default:
4042 return NT_STATUS_INVALID_DOMAIN_STATE;
4046 return NT_STATUS_OK;
4049 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4050 uint32_t idx, uint32_t collision_type,
4051 uint32_t conflict_type, const char *tdo_name);
4053 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4054 const char *tdo_name,
4055 struct ForestTrustInfo *tdo_fti,
4056 struct ForestTrustInfo *new_fti,
4057 struct lsa_ForestTrustCollisionInfo *c_info)
4059 struct ForestTrustInfoRecord *nrec;
4060 struct ForestTrustInfoRecord *trec;
4061 const char *dns_name;
4062 const char *nb_name;
4063 struct dom_sid *sid;
4064 const char *tname;
4065 size_t dns_len;
4066 size_t nb_len;
4067 size_t tlen;
4068 NTSTATUS nt_status;
4069 uint32_t new_fti_idx;
4070 uint32_t i;
4071 /* use always TDO type, until we understand when Xref can be used */
4072 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4073 bool tln_conflict;
4074 bool sid_conflict;
4075 bool nb_conflict;
4076 bool exclusion;
4077 bool ex_rule;
4078 int ret;
4080 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4082 nrec = &new_fti->records[new_fti_idx].record;
4083 dns_name = NULL;
4084 tln_conflict = false;
4085 sid_conflict = false;
4086 nb_conflict = false;
4087 exclusion = false;
4089 switch (nrec->type) {
4090 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4091 /* exclusions do not conflict by definition */
4092 break;
4094 case FOREST_TRUST_TOP_LEVEL_NAME:
4095 dns_name = nrec->data.name.string;
4096 dns_len = nrec->data.name.size;
4097 break;
4099 case LSA_FOREST_TRUST_DOMAIN_INFO:
4100 dns_name = nrec->data.info.dns_name.string;
4101 dns_len = nrec->data.info.dns_name.size;
4102 nb_name = nrec->data.info.netbios_name.string;
4103 nb_len = nrec->data.info.netbios_name.size;
4104 sid = &nrec->data.info.sid;
4105 break;
4108 if (!dns_name) continue;
4110 /* check if this is already taken and not excluded */
4111 for (i = 0; i < tdo_fti->count; i++) {
4112 trec = &tdo_fti->records[i].record;
4114 switch (trec->type) {
4115 case FOREST_TRUST_TOP_LEVEL_NAME:
4116 ex_rule = false;
4117 tname = trec->data.name.string;
4118 tlen = trec->data.name.size;
4119 break;
4120 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4121 ex_rule = true;
4122 tname = trec->data.name.string;
4123 tlen = trec->data.name.size;
4124 break;
4125 case FOREST_TRUST_DOMAIN_INFO:
4126 ex_rule = false;
4127 tname = trec->data.info.dns_name.string;
4128 tlen = trec->data.info.dns_name.size;
4130 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4131 switch (ret) {
4132 case DNS_CMP_MATCH:
4133 /* if it matches exclusion,
4134 * it doesn't conflict */
4135 if (ex_rule) {
4136 exclusion = true;
4137 break;
4139 /* fall through */
4140 case DNS_CMP_FIRST_IS_CHILD:
4141 case DNS_CMP_SECOND_IS_CHILD:
4142 tln_conflict = true;
4143 /* fall through */
4144 default:
4145 break;
4148 /* explicit exclusion, no dns name conflict here */
4149 if (exclusion) {
4150 tln_conflict = false;
4153 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4154 continue;
4157 /* also test for domain info */
4158 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4159 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4160 sid_conflict = true;
4162 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4163 strcasecmp_m(trec->data.info.netbios_name.string,
4164 nb_name) == 0) {
4165 nb_conflict = true;
4169 if (tln_conflict) {
4170 nt_status = add_collision(c_info, new_fti_idx,
4171 collision_type,
4172 LSA_TLN_DISABLED_CONFLICT,
4173 tdo_name);
4175 if (sid_conflict) {
4176 nt_status = add_collision(c_info, new_fti_idx,
4177 collision_type,
4178 LSA_SID_DISABLED_CONFLICT,
4179 tdo_name);
4181 if (nb_conflict) {
4182 nt_status = add_collision(c_info, new_fti_idx,
4183 collision_type,
4184 LSA_NB_DISABLED_CONFLICT,
4185 tdo_name);
4189 return NT_STATUS_OK;
4192 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4193 uint32_t idx, uint32_t collision_type,
4194 uint32_t conflict_type, const char *tdo_name)
4196 struct lsa_ForestTrustCollisionRecord **es;
4197 uint32_t i = c_info->count;
4199 es = talloc_realloc(c_info, c_info->entries,
4200 struct lsa_ForestTrustCollisionRecord *, i + 1);
4201 if (!es) {
4202 return NT_STATUS_NO_MEMORY;
4204 c_info->entries = es;
4205 c_info->count = i + 1;
4207 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4208 if (!es[i]) {
4209 return NT_STATUS_NO_MEMORY;
4212 es[i]->index = idx;
4213 es[i]->type = collision_type;
4214 es[i]->flags.flags = conflict_type;
4215 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4216 if (!es[i]->name.string) {
4217 return NT_STATUS_NO_MEMORY;
4219 es[i]->name.size = strlen(es[i]->name.string);
4221 return NT_STATUS_OK;
4225 lsa_lsaRSetForestTrustInformation
4227 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4228 TALLOC_CTX *mem_ctx,
4229 struct lsa_lsaRSetForestTrustInformation *r)
4231 struct dcesrv_handle *h;
4232 struct lsa_policy_state *p_state;
4233 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4234 "msDS-TrustForestTrustInfo", NULL };
4235 struct ldb_message **dom_res = NULL;
4236 struct ldb_dn *tdo_dn;
4237 struct ldb_message *msg;
4238 int num_res, i;
4239 const char *td_name;
4240 uint32_t trust_attributes;
4241 struct lsa_ForestTrustCollisionInfo *c_info;
4242 struct ForestTrustInfo *nfti;
4243 struct ForestTrustInfo *fti;
4244 DATA_BLOB ft_blob;
4245 enum ndr_err_code ndr_err;
4246 NTSTATUS nt_status;
4247 bool am_rodc;
4248 int ret;
4250 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4252 p_state = h->data;
4254 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4255 return NT_STATUS_INVALID_DOMAIN_STATE;
4258 /* abort if we are not a PDC */
4259 if (!samdb_is_pdc(p_state->sam_ldb)) {
4260 return NT_STATUS_INVALID_DOMAIN_ROLE;
4263 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4264 if (ret == LDB_SUCCESS && am_rodc) {
4265 return NT_STATUS_NO_SUCH_DOMAIN;
4268 /* check caller has TRUSTED_SET_AUTH */
4270 /* fetch all trusted domain objects */
4271 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4272 p_state->system_dn,
4273 &dom_res, trust_attrs,
4274 "(objectclass=trustedDomain)");
4275 if (num_res == 0) {
4276 return NT_STATUS_NO_SUCH_DOMAIN;
4279 for (i = 0; i < num_res; i++) {
4280 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4281 "trustPartner", NULL);
4282 if (!td_name) {
4283 return NT_STATUS_INVALID_DOMAIN_STATE;
4285 if (strcasecmp_m(td_name,
4286 r->in.trusted_domain_name->string) == 0) {
4287 break;
4290 if (i >= num_res) {
4291 return NT_STATUS_NO_SUCH_DOMAIN;
4294 tdo_dn = dom_res[i]->dn;
4296 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4297 "trustAttributes", 0);
4298 if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4299 return NT_STATUS_INVALID_PARAMETER;
4302 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4303 return NT_STATUS_INVALID_PARAMETER;
4306 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4307 if (!nfti) {
4308 return NT_STATUS_NO_MEMORY;
4311 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4312 if (!NT_STATUS_IS_OK(nt_status)) {
4313 return nt_status;
4316 c_info = talloc_zero(r->out.collision_info,
4317 struct lsa_ForestTrustCollisionInfo);
4318 if (!c_info) {
4319 return NT_STATUS_NO_MEMORY;
4322 /* first check own info, then other domains */
4323 fti = talloc(mem_ctx, struct ForestTrustInfo);
4324 if (!fti) {
4325 return NT_STATUS_NO_MEMORY;
4328 nt_status = own_ft_info(p_state, fti);
4329 if (!NT_STATUS_IS_OK(nt_status)) {
4330 return nt_status;
4333 nt_status = check_ft_info(c_info, p_state->domain_dns,
4334 fti, nfti, c_info);
4335 if (!NT_STATUS_IS_OK(nt_status)) {
4336 return nt_status;
4339 for (i = 0; i < num_res; i++) {
4340 fti = talloc(mem_ctx, struct ForestTrustInfo);
4341 if (!fti) {
4342 return NT_STATUS_NO_MEMORY;
4345 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4346 if (!NT_STATUS_IS_OK(nt_status)) {
4347 if (NT_STATUS_EQUAL(nt_status,
4348 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4349 continue;
4351 return nt_status;
4354 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4355 "trustPartner", NULL);
4356 if (!td_name) {
4357 return NT_STATUS_INVALID_DOMAIN_STATE;
4360 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4361 if (!NT_STATUS_IS_OK(nt_status)) {
4362 return nt_status;
4366 *r->out.collision_info = c_info;
4368 if (r->in.check_only != 0) {
4369 return NT_STATUS_OK;
4372 /* not just a check, write info back */
4374 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4375 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4376 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4377 return NT_STATUS_INVALID_PARAMETER;
4380 msg = ldb_msg_new(mem_ctx);
4381 if (msg == NULL) {
4382 return NT_STATUS_NO_MEMORY;
4385 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4386 if (!msg->dn) {
4387 return NT_STATUS_NO_MEMORY;
4390 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4391 LDB_FLAG_MOD_REPLACE, NULL);
4392 if (ret != LDB_SUCCESS) {
4393 return NT_STATUS_NO_MEMORY;
4395 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4396 &ft_blob, NULL);
4397 if (ret != LDB_SUCCESS) {
4398 return NT_STATUS_NO_MEMORY;
4401 ret = ldb_modify(p_state->sam_ldb, msg);
4402 if (ret != LDB_SUCCESS) {
4403 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4404 ldb_errstring(p_state->sam_ldb)));
4406 switch (ret) {
4407 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4408 return NT_STATUS_ACCESS_DENIED;
4409 default:
4410 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4414 return NT_STATUS_OK;
4418 lsa_CREDRRENAME
4420 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4421 struct lsa_CREDRRENAME *r)
4423 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4429 lsa_LSAROPENPOLICYSCE
4431 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4432 struct lsa_LSAROPENPOLICYSCE *r)
4434 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4439 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4441 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4442 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4444 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4449 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4451 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4452 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4454 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4459 lsa_LSARADTREPORTSECURITYEVENT
4461 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4462 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4464 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4468 /* include the generated boilerplate */
4469 #include "librpc/gen_ndr/ndr_lsa_s.c"
4473 /*****************************************
4474 NOTE! The remaining calls below were
4475 removed in w2k3, so the DCESRV_FAULT()
4476 replies are the correct implementation. Do
4477 not try and fill these in with anything else
4478 ******************************************/
4481 dssetup_DsRoleDnsNameToFlatName
4483 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4484 struct dssetup_DsRoleDnsNameToFlatName *r)
4486 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4491 dssetup_DsRoleDcAsDc
4493 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4494 struct dssetup_DsRoleDcAsDc *r)
4496 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4501 dssetup_DsRoleDcAsReplica
4503 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4504 struct dssetup_DsRoleDcAsReplica *r)
4506 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4511 dssetup_DsRoleDemoteDc
4513 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4514 struct dssetup_DsRoleDemoteDc *r)
4516 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4521 dssetup_DsRoleGetDcOperationProgress
4523 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4524 struct dssetup_DsRoleGetDcOperationProgress *r)
4526 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4531 dssetup_DsRoleGetDcOperationResults
4533 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4534 struct dssetup_DsRoleGetDcOperationResults *r)
4536 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4541 dssetup_DsRoleCancel
4543 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4544 struct dssetup_DsRoleCancel *r)
4546 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4551 dssetup_DsRoleServerSaveStateForUpgrade
4553 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4554 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4556 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4561 dssetup_DsRoleUpgradeDownlevelServer
4563 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4564 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4566 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4571 dssetup_DsRoleAbortDownlevelServerUpgrade
4573 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4574 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4576 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4580 /* include the generated boilerplate */
4581 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4583 NTSTATUS dcerpc_server_lsa_init(void)
4585 NTSTATUS ret;
4587 ret = dcerpc_server_dssetup_init();
4588 if (!NT_STATUS_IS_OK(ret)) {
4589 return ret;
4591 ret = dcerpc_server_lsarpc_init();
4592 if (!NT_STATUS_IS_OK(ret)) {
4593 return ret;
4595 return ret;