s4-lsa: prepare dcesrv_lsa_CreateTrustedDomain_base() to deal with unencrypted auth...
[Samba/gebeck_regimport.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
blobd5c1b61f5840979ee38407a31a7560f264ea0610
1 /* need access mask/acl implementation */
3 /*
4 Unix SMB/CIFS implementation.
6 endpoint server for the lsarpc pipe
8 Copyright (C) Andrew Tridgell 2004
9 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "rpc_server/lsa/lsa.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_drsblobs.h"
29 #include "librpc/gen_ndr/ndr_lsa.h"
30 #include "../lib/crypto/crypto.h"
31 #include "lib/util/tsort.h"
32 #include "dsdb/common/util.h"
33 #include "libcli/security/session.h"
34 #include "kdc/kdc-policy.h"
37 this type allows us to distinguish handle types
41 state associated with a lsa_OpenAccount() operation
43 struct lsa_account_state {
44 struct lsa_policy_state *policy;
45 uint32_t access_mask;
46 struct dom_sid *account_sid;
51 state associated with a lsa_OpenSecret() operation
53 struct lsa_secret_state {
54 struct lsa_policy_state *policy;
55 uint32_t access_mask;
56 struct ldb_dn *secret_dn;
57 struct ldb_context *sam_ldb;
58 bool global;
62 state associated with a lsa_OpenTrustedDomain() operation
64 struct lsa_trusted_domain_state {
65 struct lsa_policy_state *policy;
66 uint32_t access_mask;
67 struct ldb_dn *trusted_domain_dn;
68 struct ldb_dn *trusted_domain_user_dn;
72 this is based on the samba3 function make_lsa_object_sd()
73 It uses the same logic, but with samba4 helper functions
75 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
76 struct security_descriptor **sd,
77 struct dom_sid *sid,
78 uint32_t sid_access)
80 NTSTATUS status;
81 uint32_t rid;
82 struct dom_sid *domain_sid, *domain_admins_sid;
83 const char *domain_admins_sid_str, *sidstr;
84 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
86 status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
87 NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
89 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
90 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid, tmp_ctx);
92 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
93 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid_str, tmp_ctx);
95 sidstr = dom_sid_string(tmp_ctx, sid);
96 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, tmp_ctx);
98 *sd = security_descriptor_dacl_create(mem_ctx,
99 0, sidstr, NULL,
101 SID_WORLD,
102 SEC_ACE_TYPE_ACCESS_ALLOWED,
103 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
105 SID_BUILTIN_ADMINISTRATORS,
106 SEC_ACE_TYPE_ACCESS_ALLOWED,
107 SEC_GENERIC_ALL, 0,
109 SID_BUILTIN_ACCOUNT_OPERATORS,
110 SEC_ACE_TYPE_ACCESS_ALLOWED,
111 SEC_GENERIC_ALL, 0,
113 domain_admins_sid_str,
114 SEC_ACE_TYPE_ACCESS_ALLOWED,
115 SEC_GENERIC_ALL, 0,
117 sidstr,
118 SEC_ACE_TYPE_ACCESS_ALLOWED,
119 sid_access, 0,
121 NULL);
122 talloc_free(tmp_ctx);
124 NT_STATUS_HAVE_NO_MEMORY(*sd);
126 return NT_STATUS_OK;
130 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
131 TALLOC_CTX *mem_ctx,
132 struct lsa_EnumAccountRights *r);
134 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
135 TALLOC_CTX *mem_ctx,
136 struct lsa_policy_state *state,
137 int ldb_flag,
138 struct dom_sid *sid,
139 const struct lsa_RightSet *rights);
142 lsa_Close
144 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
145 struct lsa_Close *r)
147 struct dcesrv_handle *h;
149 *r->out.handle = *r->in.handle;
151 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
153 talloc_free(h);
155 ZERO_STRUCTP(r->out.handle);
157 return NT_STATUS_OK;
162 lsa_Delete
164 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
165 struct lsa_Delete *r)
167 return NT_STATUS_NOT_SUPPORTED;
172 lsa_DeleteObject
174 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
175 struct lsa_DeleteObject *r)
177 struct dcesrv_handle *h;
178 int ret;
180 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
182 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
183 struct lsa_secret_state *secret_state = h->data;
185 /* Ensure user is permitted to delete this... */
186 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
188 case SECURITY_SYSTEM:
189 case SECURITY_ADMINISTRATOR:
190 break;
191 default:
192 /* Users and anonymous are not allowed to delete things */
193 return NT_STATUS_ACCESS_DENIED;
196 ret = ldb_delete(secret_state->sam_ldb,
197 secret_state->secret_dn);
198 if (ret != LDB_SUCCESS) {
199 return NT_STATUS_INVALID_HANDLE;
202 ZERO_STRUCTP(r->out.handle);
204 return NT_STATUS_OK;
206 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
207 struct lsa_trusted_domain_state *trusted_domain_state =
208 talloc_get_type(h->data, struct lsa_trusted_domain_state);
209 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
210 if (ret != LDB_SUCCESS) {
211 return NT_STATUS_INTERNAL_DB_CORRUPTION;
214 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
215 trusted_domain_state->trusted_domain_dn);
216 if (ret != LDB_SUCCESS) {
217 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
218 return NT_STATUS_INVALID_HANDLE;
221 if (trusted_domain_state->trusted_domain_user_dn) {
222 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
223 trusted_domain_state->trusted_domain_user_dn);
224 if (ret != LDB_SUCCESS) {
225 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
226 return NT_STATUS_INVALID_HANDLE;
230 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
231 if (ret != LDB_SUCCESS) {
232 return NT_STATUS_INTERNAL_DB_CORRUPTION;
235 ZERO_STRUCTP(r->out.handle);
237 return NT_STATUS_OK;
239 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
240 struct lsa_RightSet *rights;
241 struct lsa_account_state *astate;
242 struct lsa_EnumAccountRights r2;
243 NTSTATUS status;
245 rights = talloc(mem_ctx, struct lsa_RightSet);
247 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
249 astate = h->data;
251 r2.in.handle = &astate->policy->handle->wire_handle;
252 r2.in.sid = astate->account_sid;
253 r2.out.rights = rights;
255 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
256 but we have a LSA_HANDLE_ACCOUNT here, so this call
257 will always fail */
258 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
259 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
260 return NT_STATUS_OK;
263 if (!NT_STATUS_IS_OK(status)) {
264 return status;
267 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
268 LDB_FLAG_MOD_DELETE, astate->account_sid,
269 r2.out.rights);
270 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
271 return NT_STATUS_OK;
274 if (!NT_STATUS_IS_OK(status)) {
275 return status;
278 ZERO_STRUCTP(r->out.handle);
280 return NT_STATUS_OK;
283 return NT_STATUS_INVALID_HANDLE;
288 lsa_EnumPrivs
290 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
291 struct lsa_EnumPrivs *r)
293 struct dcesrv_handle *h;
294 struct lsa_policy_state *state;
295 uint32_t i;
296 enum sec_privilege priv;
297 const char *privname;
299 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
301 state = h->data;
303 i = *r->in.resume_handle;
305 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
306 r->out.privs->count < r->in.max_count) {
307 struct lsa_PrivEntry *e;
308 privname = sec_privilege_name(priv);
309 r->out.privs->privs = talloc_realloc(r->out.privs,
310 r->out.privs->privs,
311 struct lsa_PrivEntry,
312 r->out.privs->count+1);
313 if (r->out.privs->privs == NULL) {
314 return NT_STATUS_NO_MEMORY;
316 e = &r->out.privs->privs[r->out.privs->count];
317 e->luid.low = priv;
318 e->luid.high = 0;
319 e->name.string = privname;
320 r->out.privs->count++;
321 i++;
324 *r->out.resume_handle = i;
326 return NT_STATUS_OK;
331 lsa_QuerySecObj
333 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
334 struct lsa_QuerySecurity *r)
336 struct dcesrv_handle *h;
337 struct security_descriptor *sd;
338 NTSTATUS status;
339 struct dom_sid *sid;
341 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
343 sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
345 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
346 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
347 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
348 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid,
349 LSA_ACCOUNT_ALL_ACCESS);
350 } else {
351 return NT_STATUS_INVALID_HANDLE;
353 NT_STATUS_NOT_OK_RETURN(status);
355 (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
356 NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
358 (*r->out.sdbuf)->sd = sd;
360 return NT_STATUS_OK;
365 lsa_SetSecObj
367 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
368 struct lsa_SetSecObj *r)
370 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
375 lsa_ChangePassword
377 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
378 struct lsa_ChangePassword *r)
380 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
384 dssetup_DsRoleGetPrimaryDomainInformation
386 This is not an LSA call, but is the only call left on the DSSETUP
387 pipe (after the pipe was truncated), and needs lsa_get_policy_state
389 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
390 TALLOC_CTX *mem_ctx,
391 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
393 union dssetup_DsRoleInfo *info;
395 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
396 W_ERROR_HAVE_NO_MEMORY(info);
398 switch (r->in.level) {
399 case DS_ROLE_BASIC_INFORMATION:
401 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
402 uint32_t flags = 0;
403 const char *domain = NULL;
404 const char *dns_domain = NULL;
405 const char *forest = NULL;
406 struct GUID domain_guid;
407 struct lsa_policy_state *state;
409 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
410 if (!NT_STATUS_IS_OK(status)) {
411 return ntstatus_to_werror(status);
414 ZERO_STRUCT(domain_guid);
416 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
417 case ROLE_STANDALONE:
418 role = DS_ROLE_STANDALONE_SERVER;
419 break;
420 case ROLE_DOMAIN_MEMBER:
421 role = DS_ROLE_MEMBER_SERVER;
422 break;
423 case ROLE_DOMAIN_CONTROLLER:
424 if (samdb_is_pdc(state->sam_ldb)) {
425 role = DS_ROLE_PRIMARY_DC;
426 } else {
427 role = DS_ROLE_BACKUP_DC;
429 break;
432 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
433 case ROLE_STANDALONE:
434 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
435 W_ERROR_HAVE_NO_MEMORY(domain);
436 break;
437 case ROLE_DOMAIN_MEMBER:
438 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
439 W_ERROR_HAVE_NO_MEMORY(domain);
440 /* TODO: what is with dns_domain and forest and guid? */
441 break;
442 case ROLE_DOMAIN_CONTROLLER:
443 flags = DS_ROLE_PRIMARY_DS_RUNNING;
445 if (state->mixed_domain == 1) {
446 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
449 domain = state->domain_name;
450 dns_domain = state->domain_dns;
451 forest = state->forest_dns;
453 domain_guid = state->domain_guid;
454 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
455 break;
458 info->basic.role = role;
459 info->basic.flags = flags;
460 info->basic.domain = domain;
461 info->basic.dns_domain = dns_domain;
462 info->basic.forest = forest;
463 info->basic.domain_guid = domain_guid;
465 r->out.info = info;
466 return WERR_OK;
468 case DS_ROLE_UPGRADE_STATUS:
470 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
471 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
473 r->out.info = info;
474 return WERR_OK;
476 case DS_ROLE_OP_STATUS:
478 info->opstatus.status = DS_ROLE_OP_IDLE;
480 r->out.info = info;
481 return WERR_OK;
483 default:
484 return WERR_INVALID_PARAM;
489 fill in the AccountDomain info
491 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
492 struct lsa_DomainInfo *info)
494 info->name.string = state->domain_name;
495 info->sid = state->domain_sid;
497 return NT_STATUS_OK;
501 fill in the DNS domain info
503 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
504 struct lsa_DnsDomainInfo *info)
506 info->name.string = state->domain_name;
507 info->sid = state->domain_sid;
508 info->dns_domain.string = state->domain_dns;
509 info->dns_forest.string = state->forest_dns;
510 info->domain_guid = state->domain_guid;
512 return NT_STATUS_OK;
516 lsa_QueryInfoPolicy2
518 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
519 struct lsa_QueryInfoPolicy2 *r)
521 struct lsa_policy_state *state;
522 struct dcesrv_handle *h;
523 union lsa_PolicyInformation *info;
525 *r->out.info = NULL;
527 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
529 state = h->data;
531 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
532 if (!info) {
533 return NT_STATUS_NO_MEMORY;
535 *r->out.info = info;
537 switch (r->in.level) {
538 case LSA_POLICY_INFO_AUDIT_LOG:
539 /* we don't need to fill in any of this */
540 ZERO_STRUCT(info->audit_log);
541 return NT_STATUS_OK;
542 case LSA_POLICY_INFO_AUDIT_EVENTS:
543 /* we don't need to fill in any of this */
544 ZERO_STRUCT(info->audit_events);
545 return NT_STATUS_OK;
546 case LSA_POLICY_INFO_PD:
547 /* we don't need to fill in any of this */
548 ZERO_STRUCT(info->pd);
549 return NT_STATUS_OK;
551 case LSA_POLICY_INFO_DOMAIN:
552 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
553 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
554 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
555 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
556 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
558 case LSA_POLICY_INFO_ROLE:
559 info->role.role = LSA_ROLE_PRIMARY;
560 return NT_STATUS_OK;
562 case LSA_POLICY_INFO_DNS:
563 case LSA_POLICY_INFO_DNS_INT:
564 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
566 case LSA_POLICY_INFO_REPLICA:
567 ZERO_STRUCT(info->replica);
568 return NT_STATUS_OK;
570 case LSA_POLICY_INFO_QUOTA:
571 ZERO_STRUCT(info->quota);
572 return NT_STATUS_OK;
574 case LSA_POLICY_INFO_MOD:
575 case LSA_POLICY_INFO_AUDIT_FULL_SET:
576 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
577 /* windows gives INVALID_PARAMETER */
578 *r->out.info = NULL;
579 return NT_STATUS_INVALID_PARAMETER;
582 *r->out.info = NULL;
583 return NT_STATUS_INVALID_INFO_CLASS;
587 lsa_QueryInfoPolicy
589 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
590 struct lsa_QueryInfoPolicy *r)
592 struct lsa_QueryInfoPolicy2 r2;
593 NTSTATUS status;
595 ZERO_STRUCT(r2);
597 r2.in.handle = r->in.handle;
598 r2.in.level = r->in.level;
599 r2.out.info = r->out.info;
601 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
603 return status;
607 lsa_SetInfoPolicy
609 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
610 struct lsa_SetInfoPolicy *r)
612 /* need to support this */
613 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
618 lsa_ClearAuditLog
620 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
621 struct lsa_ClearAuditLog *r)
623 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
628 lsa_CreateAccount
630 This call does not seem to have any long-term effects, hence no database operations
632 we need to talk to the MS product group to find out what this account database means!
634 answer is that the lsa database is totally separate from the SAM and
635 ldap databases. We are going to need a separate ldb to store these
636 accounts. The SIDs on this account bear no relation to the SIDs in
639 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
640 struct lsa_CreateAccount *r)
642 struct lsa_account_state *astate;
644 struct lsa_policy_state *state;
645 struct dcesrv_handle *h, *ah;
647 ZERO_STRUCTP(r->out.acct_handle);
649 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
651 state = h->data;
653 astate = talloc(dce_call->conn, struct lsa_account_state);
654 if (astate == NULL) {
655 return NT_STATUS_NO_MEMORY;
658 astate->account_sid = dom_sid_dup(astate, r->in.sid);
659 if (astate->account_sid == NULL) {
660 talloc_free(astate);
661 return NT_STATUS_NO_MEMORY;
664 astate->policy = talloc_reference(astate, state);
665 astate->access_mask = r->in.access_mask;
667 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
668 if (!ah) {
669 talloc_free(astate);
670 return NT_STATUS_NO_MEMORY;
673 ah->data = talloc_steal(ah, astate);
675 *r->out.acct_handle = ah->wire_handle;
677 return NT_STATUS_OK;
682 lsa_EnumAccounts
684 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
685 struct lsa_EnumAccounts *r)
687 struct dcesrv_handle *h;
688 struct lsa_policy_state *state;
689 int ret;
690 struct ldb_message **res;
691 const char * const attrs[] = { "objectSid", NULL};
692 uint32_t count, i;
694 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
696 state = h->data;
698 /* NOTE: This call must only return accounts that have at least
699 one privilege set
701 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
702 "(&(objectSid=*)(privilege=*))");
703 if (ret < 0) {
704 return NT_STATUS_INTERNAL_DB_CORRUPTION;
707 if (*r->in.resume_handle >= ret) {
708 return NT_STATUS_NO_MORE_ENTRIES;
711 count = ret - *r->in.resume_handle;
712 if (count > r->in.num_entries) {
713 count = r->in.num_entries;
716 if (count == 0) {
717 return NT_STATUS_NO_MORE_ENTRIES;
720 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
721 if (r->out.sids->sids == NULL) {
722 return NT_STATUS_NO_MEMORY;
725 for (i=0;i<count;i++) {
726 r->out.sids->sids[i].sid =
727 samdb_result_dom_sid(r->out.sids->sids,
728 res[i + *r->in.resume_handle],
729 "objectSid");
730 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
733 r->out.sids->num_sids = count;
734 *r->out.resume_handle = count + *r->in.resume_handle;
736 return NT_STATUS_OK;
740 /* This decrypts and returns Trusted Domain Auth Information Internal data */
741 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
742 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
743 struct trustDomainPasswords *auth_struct)
745 DATA_BLOB session_key = data_blob(NULL, 0);
746 enum ndr_err_code ndr_err;
747 NTSTATUS nt_status;
749 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
750 if (!NT_STATUS_IS_OK(nt_status)) {
751 return nt_status;
754 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
755 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
756 auth_struct,
757 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
758 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
759 return NT_STATUS_INVALID_PARAMETER;
762 return NT_STATUS_OK;
765 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
766 TALLOC_CTX *mem_ctx,
767 struct trustAuthInOutBlob *iopw,
768 DATA_BLOB *trustauth_blob)
770 enum ndr_err_code ndr_err;
772 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
773 iopw,
774 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
775 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
776 return NT_STATUS_INVALID_PARAMETER;
779 return NT_STATUS_OK;
782 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
783 struct ldb_context *sam_ldb,
784 struct ldb_dn *base_dn,
785 const char *netbios_name,
786 struct trustAuthInOutBlob *in,
787 struct ldb_dn **user_dn)
789 struct ldb_message *msg;
790 struct ldb_dn *dn;
791 uint32_t i;
792 int ret;
794 dn = ldb_dn_copy(mem_ctx, base_dn);
795 if (!dn) {
796 return NT_STATUS_NO_MEMORY;
798 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
799 return NT_STATUS_NO_MEMORY;
802 msg = ldb_msg_new(mem_ctx);
803 if (!msg) {
804 return NT_STATUS_NO_MEMORY;
806 msg->dn = dn;
808 ret = ldb_msg_add_string(msg, "objectClass", "user");
809 if (ret != LDB_SUCCESS) {
810 return NT_STATUS_NO_MEMORY;
813 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
814 if (ret != LDB_SUCCESS) {
815 return NT_STATUS_NO_MEMORY;
818 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
819 UF_INTERDOMAIN_TRUST_ACCOUNT);
820 if (ret != LDB_SUCCESS) {
821 return NT_STATUS_NO_MEMORY;
824 for (i = 0; i < in->count; i++) {
825 const char *attribute;
826 struct ldb_val v;
827 switch (in->current.array[i].AuthType) {
828 case TRUST_AUTH_TYPE_NT4OWF:
829 attribute = "unicodePwd";
830 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
831 v.length = 16;
832 break;
833 case TRUST_AUTH_TYPE_CLEAR:
834 attribute = "clearTextPassword";
835 v.data = in->current.array[i].AuthInfo.clear.password;
836 v.length = in->current.array[i].AuthInfo.clear.size;
837 break;
838 default:
839 continue;
842 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
843 if (ret != LDB_SUCCESS) {
844 return NT_STATUS_NO_MEMORY;
848 /* create the trusted_domain user account */
849 ret = ldb_add(sam_ldb, msg);
850 if (ret != LDB_SUCCESS) {
851 DEBUG(0,("Failed to create user record %s: %s\n",
852 ldb_dn_get_linearized(msg->dn),
853 ldb_errstring(sam_ldb)));
855 switch (ret) {
856 case LDB_ERR_ENTRY_ALREADY_EXISTS:
857 return NT_STATUS_DOMAIN_EXISTS;
858 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
859 return NT_STATUS_ACCESS_DENIED;
860 default:
861 return NT_STATUS_INTERNAL_DB_CORRUPTION;
865 if (user_dn) {
866 *user_dn = dn;
868 return NT_STATUS_OK;
872 lsa_CreateTrustedDomainEx2
874 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
875 TALLOC_CTX *mem_ctx,
876 struct lsa_CreateTrustedDomainEx2 *r,
877 int op,
878 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
880 struct dcesrv_handle *policy_handle;
881 struct lsa_policy_state *policy_state;
882 struct lsa_trusted_domain_state *trusted_domain_state;
883 struct dcesrv_handle *handle;
884 struct ldb_message **msgs, *msg;
885 const char *attrs[] = {
886 NULL
888 const char *netbios_name;
889 const char *dns_name;
890 const char *name;
891 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
892 struct trustDomainPasswords auth_struct;
893 int ret;
894 NTSTATUS nt_status;
895 struct ldb_context *sam_ldb;
897 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
898 ZERO_STRUCTP(r->out.trustdom_handle);
900 policy_state = policy_handle->data;
901 sam_ldb = policy_state->sam_ldb;
903 netbios_name = r->in.info->netbios_name.string;
904 if (!netbios_name) {
905 return NT_STATUS_INVALID_PARAMETER;
908 dns_name = r->in.info->domain_name.string;
910 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
911 if (!trusted_domain_state) {
912 return NT_STATUS_NO_MEMORY;
914 trusted_domain_state->policy = policy_state;
916 if (strcasecmp(netbios_name, "BUILTIN") == 0
917 || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
918 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
919 return NT_STATUS_INVALID_PARAMETER;
922 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
923 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
924 || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
925 || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
926 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
927 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
930 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
931 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
932 /* No secrets are created at this time, for this function */
933 auth_struct.outgoing.count = 0;
934 auth_struct.incoming.count = 0;
935 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
936 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
937 r->in.auth_info_internal->auth_blob.size);
938 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
939 &auth_blob, &auth_struct);
940 if (!NT_STATUS_IS_OK(nt_status)) {
941 return nt_status;
943 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
945 if (unencrypted_auth_info->incoming_count > 1) {
946 return NT_STATUS_INVALID_PARAMETER;
949 /* more investigation required here, do not create secrets for
950 * now */
951 auth_struct.outgoing.count = 0;
952 auth_struct.incoming.count = 0;
953 } else {
954 return NT_STATUS_INVALID_PARAMETER;
957 if (auth_struct.incoming.count) {
958 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
959 &auth_struct.incoming,
960 &trustAuthIncoming);
961 if (!NT_STATUS_IS_OK(nt_status)) {
962 return nt_status;
964 } else {
965 trustAuthIncoming = data_blob(NULL, 0);
968 if (auth_struct.outgoing.count) {
969 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
970 &auth_struct.outgoing,
971 &trustAuthOutgoing);
972 if (!NT_STATUS_IS_OK(nt_status)) {
973 return nt_status;
975 } else {
976 trustAuthOutgoing = data_blob(NULL, 0);
979 ret = ldb_transaction_start(sam_ldb);
980 if (ret != LDB_SUCCESS) {
981 return NT_STATUS_INTERNAL_DB_CORRUPTION;
984 if (dns_name) {
985 char *dns_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
986 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
987 /* search for the trusted_domain record */
988 ret = gendb_search(sam_ldb,
989 mem_ctx, policy_state->system_dn, &msgs, attrs,
990 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
991 dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
992 if (ret > 0) {
993 ldb_transaction_cancel(sam_ldb);
994 return NT_STATUS_OBJECT_NAME_COLLISION;
996 } else {
997 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
998 /* search for the trusted_domain record */
999 ret = gendb_search(sam_ldb,
1000 mem_ctx, policy_state->system_dn, &msgs, attrs,
1001 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1002 netbios_encoded, netbios_encoded, netbios_encoded);
1003 if (ret > 0) {
1004 ldb_transaction_cancel(sam_ldb);
1005 return NT_STATUS_OBJECT_NAME_COLLISION;
1009 if (ret < 0 ) {
1010 ldb_transaction_cancel(sam_ldb);
1011 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1014 name = dns_name ? dns_name : netbios_name;
1016 msg = ldb_msg_new(mem_ctx);
1017 if (msg == NULL) {
1018 return NT_STATUS_NO_MEMORY;
1021 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1022 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1023 ldb_transaction_cancel(sam_ldb);
1024 return NT_STATUS_NO_MEMORY;
1027 ldb_msg_add_string(msg, "flatname", netbios_name);
1029 if (r->in.info->sid) {
1030 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1031 if (ret != LDB_SUCCESS) {
1032 ldb_transaction_cancel(sam_ldb);
1033 return NT_STATUS_INVALID_PARAMETER;
1037 ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1039 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1041 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1043 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1045 if (dns_name) {
1046 ldb_msg_add_string(msg, "trustPartner", dns_name);
1049 if (trustAuthIncoming.data) {
1050 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1051 if (ret != LDB_SUCCESS) {
1052 ldb_transaction_cancel(sam_ldb);
1053 return NT_STATUS_NO_MEMORY;
1056 if (trustAuthOutgoing.data) {
1057 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1058 if (ret != LDB_SUCCESS) {
1059 ldb_transaction_cancel(sam_ldb);
1060 return NT_STATUS_NO_MEMORY;
1064 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1066 /* create the trusted_domain */
1067 ret = ldb_add(sam_ldb, msg);
1068 switch (ret) {
1069 case LDB_SUCCESS:
1070 break;
1071 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1072 ldb_transaction_cancel(sam_ldb);
1073 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1074 ldb_dn_get_linearized(msg->dn),
1075 ldb_errstring(sam_ldb)));
1076 return NT_STATUS_DOMAIN_EXISTS;
1077 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1078 ldb_transaction_cancel(sam_ldb);
1079 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1080 ldb_dn_get_linearized(msg->dn),
1081 ldb_errstring(sam_ldb)));
1082 return NT_STATUS_ACCESS_DENIED;
1083 default:
1084 ldb_transaction_cancel(sam_ldb);
1085 DEBUG(0,("Failed to create user record %s: %s\n",
1086 ldb_dn_get_linearized(msg->dn),
1087 ldb_errstring(sam_ldb)));
1088 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1091 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1092 struct ldb_dn *user_dn;
1093 /* Inbound trusts must also create a cn=users object to match */
1094 nt_status = add_trust_user(mem_ctx, sam_ldb,
1095 policy_state->domain_dn,
1096 netbios_name,
1097 &auth_struct.incoming,
1098 &user_dn);
1099 if (!NT_STATUS_IS_OK(nt_status)) {
1100 ldb_transaction_cancel(sam_ldb);
1101 return nt_status;
1104 /* save the trust user dn */
1105 trusted_domain_state->trusted_domain_user_dn
1106 = talloc_steal(trusted_domain_state, user_dn);
1109 ret = ldb_transaction_commit(sam_ldb);
1110 if (ret != LDB_SUCCESS) {
1111 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1114 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1115 if (!handle) {
1116 return NT_STATUS_NO_MEMORY;
1119 handle->data = talloc_steal(handle, trusted_domain_state);
1121 trusted_domain_state->access_mask = r->in.access_mask;
1122 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1124 *r->out.trustdom_handle = handle->wire_handle;
1126 return NT_STATUS_OK;
1130 lsa_CreateTrustedDomainEx2
1132 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1133 TALLOC_CTX *mem_ctx,
1134 struct lsa_CreateTrustedDomainEx2 *r)
1136 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1139 lsa_CreateTrustedDomainEx
1141 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1142 TALLOC_CTX *mem_ctx,
1143 struct lsa_CreateTrustedDomainEx *r)
1145 struct lsa_CreateTrustedDomainEx2 r2;
1147 r2.in.policy_handle = r->in.policy_handle;
1148 r2.in.info = r->in.info;
1149 r2.out.trustdom_handle = r->out.trustdom_handle;
1150 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1154 lsa_CreateTrustedDomain
1156 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1157 struct lsa_CreateTrustedDomain *r)
1159 struct lsa_CreateTrustedDomainEx2 r2;
1161 r2.in.policy_handle = r->in.policy_handle;
1162 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1163 if (!r2.in.info) {
1164 return NT_STATUS_NO_MEMORY;
1167 r2.in.info->domain_name.string = NULL;
1168 r2.in.info->netbios_name = r->in.info->name;
1169 r2.in.info->sid = r->in.info->sid;
1170 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1171 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1172 r2.in.info->trust_attributes = 0;
1174 r2.in.access_mask = r->in.access_mask;
1175 r2.out.trustdom_handle = r->out.trustdom_handle;
1177 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1182 lsa_OpenTrustedDomain
1184 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1185 struct lsa_OpenTrustedDomain *r)
1187 struct dcesrv_handle *policy_handle;
1189 struct lsa_policy_state *policy_state;
1190 struct lsa_trusted_domain_state *trusted_domain_state;
1191 struct dcesrv_handle *handle;
1192 struct ldb_message **msgs;
1193 const char *attrs[] = {
1194 "trustDirection",
1195 "flatname",
1196 NULL
1199 const char *sid_string;
1200 int ret;
1202 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1203 ZERO_STRUCTP(r->out.trustdom_handle);
1204 policy_state = policy_handle->data;
1206 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1207 if (!trusted_domain_state) {
1208 return NT_STATUS_NO_MEMORY;
1210 trusted_domain_state->policy = policy_state;
1212 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1213 if (!sid_string) {
1214 return NT_STATUS_NO_MEMORY;
1217 /* search for the trusted_domain record */
1218 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1219 mem_ctx, policy_state->system_dn, &msgs, attrs,
1220 "(&(securityIdentifier=%s)(objectclass=trustedDomain))",
1221 sid_string);
1222 if (ret == 0) {
1223 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1226 if (ret != 1) {
1227 DEBUG(0,("Found %d records matching DN %s\n", ret,
1228 ldb_dn_get_linearized(policy_state->system_dn)));
1229 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1232 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1234 trusted_domain_state->trusted_domain_user_dn = NULL;
1236 if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1237 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1238 /* search for the trusted_domain record */
1239 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1240 mem_ctx, policy_state->domain_dn, &msgs, attrs,
1241 "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%u))",
1242 flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1243 if (ret == 1) {
1244 trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1247 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1248 if (!handle) {
1249 return NT_STATUS_NO_MEMORY;
1252 handle->data = talloc_steal(handle, trusted_domain_state);
1254 trusted_domain_state->access_mask = r->in.access_mask;
1255 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1257 *r->out.trustdom_handle = handle->wire_handle;
1259 return NT_STATUS_OK;
1264 lsa_OpenTrustedDomainByName
1266 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1267 TALLOC_CTX *mem_ctx,
1268 struct lsa_OpenTrustedDomainByName *r)
1270 struct dcesrv_handle *policy_handle;
1272 struct lsa_policy_state *policy_state;
1273 struct lsa_trusted_domain_state *trusted_domain_state;
1274 struct dcesrv_handle *handle;
1275 struct ldb_message **msgs;
1276 const char *attrs[] = {
1277 NULL
1279 char *td_name;
1280 int ret;
1282 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1283 ZERO_STRUCTP(r->out.trustdom_handle);
1284 policy_state = policy_handle->data;
1286 if (!r->in.name.string) {
1287 return NT_STATUS_INVALID_PARAMETER;
1290 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1291 if (!trusted_domain_state) {
1292 return NT_STATUS_NO_MEMORY;
1294 trusted_domain_state->policy = policy_state;
1296 /* search for the trusted_domain record */
1297 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1298 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1299 mem_ctx, policy_state->system_dn, &msgs, attrs,
1300 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1301 "(objectclass=trustedDomain))",
1302 td_name, td_name, td_name);
1303 if (ret == 0) {
1304 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1307 if (ret != 1) {
1308 DEBUG(0,("Found %d records matching DN %s\n", ret,
1309 ldb_dn_get_linearized(policy_state->system_dn)));
1310 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1313 /* TODO: perform access checks */
1315 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1317 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1318 if (!handle) {
1319 return NT_STATUS_NO_MEMORY;
1322 handle->data = talloc_steal(handle, trusted_domain_state);
1324 trusted_domain_state->access_mask = r->in.access_mask;
1325 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1327 *r->out.trustdom_handle = handle->wire_handle;
1329 return NT_STATUS_OK;
1335 lsa_SetTrustedDomainInfo
1337 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1338 struct lsa_SetTrustedDomainInfo *r)
1340 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1345 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1346 * otherwise at least one must be provided */
1347 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1348 struct ldb_dn *basedn, const char *dns_domain,
1349 const char *netbios, struct dom_sid2 *sid,
1350 struct ldb_message ***msgs)
1352 const char *attrs[] = { "flatname", "trustPartner",
1353 "securityIdentifier", "trustDirection",
1354 "trustType", "trustAttributes",
1355 "trustPosixOffset",
1356 "msDs-supportedEncryptionTypes", NULL };
1357 char *dns = NULL;
1358 char *nbn = NULL;
1359 char *sidstr = NULL;
1360 char *filter;
1361 int ret;
1364 if (dns_domain || netbios || sid) {
1365 filter = talloc_strdup(mem_ctx,
1366 "(&(objectclass=trustedDomain)(|");
1367 } else {
1368 filter = talloc_strdup(mem_ctx,
1369 "(objectclass=trustedDomain)");
1371 if (!filter) {
1372 return NT_STATUS_NO_MEMORY;
1375 if (dns_domain) {
1376 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1377 if (!dns) {
1378 return NT_STATUS_NO_MEMORY;
1380 filter = talloc_asprintf_append(filter,
1381 "(trustPartner=%s)", dns);
1382 if (!filter) {
1383 return NT_STATUS_NO_MEMORY;
1386 if (netbios) {
1387 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1388 if (!nbn) {
1389 return NT_STATUS_NO_MEMORY;
1391 filter = talloc_asprintf_append(filter,
1392 "(flatname=%s)", nbn);
1393 if (!filter) {
1394 return NT_STATUS_NO_MEMORY;
1397 if (sid) {
1398 sidstr = dom_sid_string(mem_ctx, sid);
1399 if (!sidstr) {
1400 return NT_STATUS_INVALID_PARAMETER;
1402 filter = talloc_asprintf_append(filter,
1403 "(securityIdentifier=%s)",
1404 sidstr);
1405 if (!filter) {
1406 return NT_STATUS_NO_MEMORY;
1409 if (dns_domain || netbios || sid) {
1410 filter = talloc_asprintf_append(filter, "))");
1411 if (!filter) {
1412 return NT_STATUS_NO_MEMORY;
1416 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1417 if (ret == 0) {
1418 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1421 if (ret != 1) {
1422 return NT_STATUS_OBJECT_NAME_COLLISION;
1425 return NT_STATUS_OK;
1428 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1429 struct ldb_context *sam_ldb,
1430 struct ldb_message *orig,
1431 struct ldb_message *dest,
1432 const char *attribute,
1433 uint32_t value,
1434 uint32_t *orig_value)
1436 const struct ldb_val *orig_val;
1437 uint32_t orig_uint = 0;
1438 unsigned int flags = 0;
1439 int ret;
1441 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1442 if (!orig_val || !orig_val->data) {
1443 /* add new attribute */
1444 flags = LDB_FLAG_MOD_ADD;
1446 } else {
1447 errno = 0;
1448 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1449 if (errno != 0 || orig_uint != value) {
1450 /* replace also if can't get value */
1451 flags = LDB_FLAG_MOD_REPLACE;
1455 if (flags == 0) {
1456 /* stored value is identical, nothing to change */
1457 goto done;
1460 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1461 if (ret != LDB_SUCCESS) {
1462 return NT_STATUS_NO_MEMORY;
1465 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1466 if (ret != LDB_SUCCESS) {
1467 return NT_STATUS_NO_MEMORY;
1470 done:
1471 if (orig_value) {
1472 *orig_value = orig_uint;
1474 return NT_STATUS_OK;
1477 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1478 struct ldb_context *sam_ldb,
1479 struct ldb_dn *base_dn,
1480 bool delete_user,
1481 const char *netbios_name,
1482 struct trustAuthInOutBlob *in)
1484 const char *attrs[] = { "userAccountControl", NULL };
1485 struct ldb_message **msgs;
1486 struct ldb_message *msg;
1487 uint32_t uac;
1488 uint32_t i;
1489 int ret;
1491 ret = gendb_search(sam_ldb, mem_ctx,
1492 base_dn, &msgs, attrs,
1493 "samAccountName=%s$", netbios_name);
1494 if (ret > 1) {
1495 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1498 if (ret == 0) {
1499 if (delete_user) {
1500 return NT_STATUS_OK;
1503 /* ok no existing user, add it from scratch */
1504 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1505 netbios_name, in, NULL);
1508 /* check user is what we are looking for */
1509 uac = ldb_msg_find_attr_as_uint(msgs[0],
1510 "userAccountControl", 0);
1511 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1512 return NT_STATUS_OBJECT_NAME_COLLISION;
1515 if (delete_user) {
1516 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1517 switch (ret) {
1518 case LDB_SUCCESS:
1519 return NT_STATUS_OK;
1520 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1521 return NT_STATUS_ACCESS_DENIED;
1522 default:
1523 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1527 /* entry exists, just modify secret if any */
1528 if (in->count == 0) {
1529 return NT_STATUS_OK;
1532 msg = ldb_msg_new(mem_ctx);
1533 if (!msg) {
1534 return NT_STATUS_NO_MEMORY;
1536 msg->dn = msgs[0]->dn;
1538 for (i = 0; i < in->count; i++) {
1539 const char *attribute;
1540 struct ldb_val v;
1541 switch (in->current.array[i].AuthType) {
1542 case TRUST_AUTH_TYPE_NT4OWF:
1543 attribute = "unicodePwd";
1544 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1545 v.length = 16;
1546 break;
1547 case TRUST_AUTH_TYPE_CLEAR:
1548 attribute = "clearTextPassword";
1549 v.data = in->current.array[i].AuthInfo.clear.password;
1550 v.length = in->current.array[i].AuthInfo.clear.size;
1551 break;
1552 default:
1553 continue;
1556 ret = ldb_msg_add_empty(msg, attribute,
1557 LDB_FLAG_MOD_REPLACE, NULL);
1558 if (ret != LDB_SUCCESS) {
1559 return NT_STATUS_NO_MEMORY;
1562 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1563 if (ret != LDB_SUCCESS) {
1564 return NT_STATUS_NO_MEMORY;
1568 /* create the trusted_domain user account */
1569 ret = ldb_modify(sam_ldb, msg);
1570 if (ret != LDB_SUCCESS) {
1571 DEBUG(0,("Failed to create user record %s: %s\n",
1572 ldb_dn_get_linearized(msg->dn),
1573 ldb_errstring(sam_ldb)));
1575 switch (ret) {
1576 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1577 return NT_STATUS_DOMAIN_EXISTS;
1578 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1579 return NT_STATUS_ACCESS_DENIED;
1580 default:
1581 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1585 return NT_STATUS_OK;
1589 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1590 struct dcesrv_handle *p_handle,
1591 TALLOC_CTX *mem_ctx,
1592 struct ldb_message *dom_msg,
1593 enum lsa_TrustDomInfoEnum level,
1594 union lsa_TrustedDomainInfo *info)
1596 struct lsa_policy_state *p_state = p_handle->data;
1597 uint32_t *posix_offset = NULL;
1598 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1599 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1600 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1601 uint32_t *enc_types = NULL;
1602 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1603 struct trustDomainPasswords auth_struct;
1604 NTSTATUS nt_status;
1605 struct ldb_message **msgs;
1606 struct ldb_message *msg;
1607 bool add_outgoing = false;
1608 bool add_incoming = false;
1609 bool del_outgoing = false;
1610 bool del_incoming = false;
1611 bool in_transaction = false;
1612 int ret;
1613 bool am_rodc;
1615 switch (level) {
1616 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1617 posix_offset = &info->posix_offset.posix_offset;
1618 break;
1619 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1620 info_ex = &info->info_ex;
1621 break;
1622 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1623 auth_info = &info->auth_info;
1624 break;
1625 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1626 posix_offset = &info->full_info.posix_offset.posix_offset;
1627 info_ex = &info->full_info.info_ex;
1628 auth_info = &info->full_info.auth_info;
1629 break;
1630 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1631 auth_info_int = &info->auth_info_internal;
1632 break;
1633 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1634 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1635 info_ex = &info->full_info_internal.info_ex;
1636 auth_info_int = &info->full_info_internal.auth_info;
1637 break;
1638 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1639 enc_types = &info->enc_types.enc_types;
1640 break;
1641 default:
1642 return NT_STATUS_INVALID_PARAMETER;
1645 if (auth_info) {
1646 /* FIXME: not handled yet */
1647 return NT_STATUS_INVALID_PARAMETER;
1650 /* decode auth_info_int if set */
1651 if (auth_info_int) {
1653 /* now decrypt blob */
1654 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1655 auth_info_int->auth_blob.size);
1657 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1658 &auth_blob, &auth_struct);
1659 if (!NT_STATUS_IS_OK(nt_status)) {
1660 return nt_status;
1664 if (info_ex) {
1665 /* verify data matches */
1666 if (info_ex->trust_attributes &
1667 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1668 /* TODO: check what behavior level we have */
1669 if (strcasecmp_m(p_state->domain_dns,
1670 p_state->forest_dns) != 0) {
1671 return NT_STATUS_INVALID_DOMAIN_STATE;
1675 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1676 if (ret == LDB_SUCCESS && am_rodc) {
1677 return NT_STATUS_NO_SUCH_DOMAIN;
1680 /* verify only one object matches the dns/netbios/sid
1681 * triplet and that this is the one we already have */
1682 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1683 p_state->system_dn,
1684 info_ex->domain_name.string,
1685 info_ex->netbios_name.string,
1686 info_ex->sid, &msgs);
1687 if (!NT_STATUS_IS_OK(nt_status)) {
1688 return nt_status;
1690 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1691 return NT_STATUS_OBJECT_NAME_COLLISION;
1693 talloc_free(msgs);
1696 /* TODO: should we fetch previous values from the existing entry
1697 * and append them ? */
1698 if (auth_struct.incoming.count) {
1699 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1700 &auth_struct.incoming,
1701 &trustAuthIncoming);
1702 if (!NT_STATUS_IS_OK(nt_status)) {
1703 return nt_status;
1705 } else {
1706 trustAuthIncoming = data_blob(NULL, 0);
1709 if (auth_struct.outgoing.count) {
1710 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1711 &auth_struct.outgoing,
1712 &trustAuthOutgoing);
1713 if (!NT_STATUS_IS_OK(nt_status)) {
1714 return nt_status;
1716 } else {
1717 trustAuthOutgoing = data_blob(NULL, 0);
1720 msg = ldb_msg_new(mem_ctx);
1721 if (msg == NULL) {
1722 return NT_STATUS_NO_MEMORY;
1724 msg->dn = dom_msg->dn;
1726 if (posix_offset) {
1727 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1728 dom_msg, msg,
1729 "trustPosixOffset",
1730 *posix_offset, NULL);
1731 if (!NT_STATUS_IS_OK(nt_status)) {
1732 return nt_status;
1736 if (info_ex) {
1737 uint32_t origattrs;
1738 uint32_t origdir;
1739 uint32_t tmp;
1740 int origtype;
1742 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1743 dom_msg, msg,
1744 "trustDirection",
1745 info_ex->trust_direction,
1746 &origdir);
1747 if (!NT_STATUS_IS_OK(nt_status)) {
1748 return nt_status;
1751 tmp = info_ex->trust_direction ^ origdir;
1752 if (tmp & LSA_TRUST_DIRECTION_INBOUND) {
1753 if (origdir & LSA_TRUST_DIRECTION_INBOUND) {
1754 del_incoming = true;
1755 } else {
1756 add_incoming = true;
1759 if (tmp & LSA_TRUST_DIRECTION_OUTBOUND) {
1760 if (origdir & LSA_TRUST_DIRECTION_OUTBOUND) {
1761 del_outgoing = true;
1762 } else {
1763 add_outgoing = true;
1767 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1768 if (origtype == -1 || origtype != info_ex->trust_type) {
1769 DEBUG(1, ("Attempted to change trust type! "
1770 "Operation not handled\n"));
1771 return NT_STATUS_INVALID_PARAMETER;
1774 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1775 dom_msg, msg,
1776 "trustAttributes",
1777 info_ex->trust_attributes,
1778 &origattrs);
1779 if (!NT_STATUS_IS_OK(nt_status)) {
1780 return nt_status;
1782 /* TODO: check forestFunctionality from ldb opaque */
1783 /* TODO: check what is set makes sense */
1784 /* for now refuse changes */
1785 if (origattrs == -1 ||
1786 origattrs != info_ex->trust_attributes) {
1787 DEBUG(1, ("Attempted to change trust attributes! "
1788 "Operation not handled\n"));
1789 return NT_STATUS_INVALID_PARAMETER;
1793 if (enc_types) {
1794 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1795 dom_msg, msg,
1796 "msDS-SupportedEncryptionTypes",
1797 *enc_types, NULL);
1798 if (!NT_STATUS_IS_OK(nt_status)) {
1799 return nt_status;
1803 if (add_incoming && trustAuthIncoming.data) {
1804 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1805 LDB_FLAG_MOD_REPLACE, NULL);
1806 if (ret != LDB_SUCCESS) {
1807 return NT_STATUS_NO_MEMORY;
1809 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1810 &trustAuthIncoming, NULL);
1811 if (ret != LDB_SUCCESS) {
1812 return NT_STATUS_NO_MEMORY;
1815 if (add_outgoing && trustAuthOutgoing.data) {
1816 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1817 LDB_FLAG_MOD_REPLACE, NULL);
1818 if (ret != LDB_SUCCESS) {
1819 return NT_STATUS_NO_MEMORY;
1821 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1822 &trustAuthOutgoing, NULL);
1823 if (ret != LDB_SUCCESS) {
1824 return NT_STATUS_NO_MEMORY;
1828 /* start transaction */
1829 ret = ldb_transaction_start(p_state->sam_ldb);
1830 if (ret != LDB_SUCCESS) {
1831 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1833 in_transaction = true;
1835 ret = ldb_modify(p_state->sam_ldb, msg);
1836 if (ret != LDB_SUCCESS) {
1837 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1838 ldb_dn_get_linearized(msg->dn),
1839 ldb_errstring(p_state->sam_ldb)));
1840 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
1841 nt_status = NT_STATUS_ACCESS_DENIED;
1842 } else {
1843 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1845 goto done;
1848 if (add_incoming || del_incoming) {
1849 const char *netbios_name;
1851 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1852 "flatname", NULL);
1853 if (!netbios_name) {
1854 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1855 goto done;
1858 nt_status = update_trust_user(mem_ctx,
1859 p_state->sam_ldb,
1860 p_state->domain_dn,
1861 del_incoming,
1862 netbios_name,
1863 &auth_struct.incoming);
1864 if (!NT_STATUS_IS_OK(nt_status)) {
1865 goto done;
1869 /* ok, all fine, commit transaction and return */
1870 ret = ldb_transaction_commit(p_state->sam_ldb);
1871 if (ret != LDB_SUCCESS) {
1872 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1874 in_transaction = false;
1876 nt_status = NT_STATUS_OK;
1878 done:
1879 if (in_transaction) {
1880 ldb_transaction_cancel(p_state->sam_ldb);
1882 return nt_status;
1886 lsa_SetInfomrationTrustedDomain
1888 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1889 struct dcesrv_call_state *dce_call,
1890 TALLOC_CTX *mem_ctx,
1891 struct lsa_SetInformationTrustedDomain *r)
1893 struct dcesrv_handle *h;
1894 struct lsa_trusted_domain_state *td_state;
1895 struct ldb_message **msgs;
1896 NTSTATUS nt_status;
1898 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1899 LSA_HANDLE_TRUSTED_DOMAIN);
1901 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1903 /* get the trusted domain object */
1904 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1905 td_state->trusted_domain_dn,
1906 NULL, NULL, NULL, &msgs);
1907 if (!NT_STATUS_IS_OK(nt_status)) {
1908 if (NT_STATUS_EQUAL(nt_status,
1909 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1910 return nt_status;
1912 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1915 return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1916 msgs[0], r->in.level, r->in.info);
1921 lsa_DeleteTrustedDomain
1923 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1924 struct lsa_DeleteTrustedDomain *r)
1926 NTSTATUS status;
1927 struct lsa_OpenTrustedDomain opn;
1928 struct lsa_DeleteObject del;
1929 struct dcesrv_handle *h;
1931 opn.in.handle = r->in.handle;
1932 opn.in.sid = r->in.dom_sid;
1933 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1934 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1935 if (!opn.out.trustdom_handle) {
1936 return NT_STATUS_NO_MEMORY;
1938 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1939 if (!NT_STATUS_IS_OK(status)) {
1940 return status;
1943 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1944 talloc_steal(mem_ctx, h);
1946 del.in.handle = opn.out.trustdom_handle;
1947 del.out.handle = opn.out.trustdom_handle;
1948 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1949 if (!NT_STATUS_IS_OK(status)) {
1950 return status;
1952 return NT_STATUS_OK;
1955 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
1956 struct ldb_message *msg,
1957 struct lsa_TrustDomainInfoInfoEx *info_ex)
1959 info_ex->domain_name.string
1960 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1961 info_ex->netbios_name.string
1962 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1963 info_ex->sid
1964 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1965 info_ex->trust_direction
1966 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1967 info_ex->trust_type
1968 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1969 info_ex->trust_attributes
1970 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
1971 return NT_STATUS_OK;
1975 lsa_QueryTrustedDomainInfo
1977 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1978 struct lsa_QueryTrustedDomainInfo *r)
1980 union lsa_TrustedDomainInfo *info = NULL;
1981 struct dcesrv_handle *h;
1982 struct lsa_trusted_domain_state *trusted_domain_state;
1983 struct ldb_message *msg;
1984 int ret;
1985 struct ldb_message **res;
1986 const char *attrs[] = {
1987 "flatname",
1988 "trustPartner",
1989 "securityIdentifier",
1990 "trustDirection",
1991 "trustType",
1992 "trustAttributes",
1993 "msDs-supportedEncryptionTypes",
1994 NULL
1997 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
1999 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2001 /* pull all the user attributes */
2002 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2003 trusted_domain_state->trusted_domain_dn, &res, attrs);
2004 if (ret != 1) {
2005 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2007 msg = res[0];
2009 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2010 if (!info) {
2011 return NT_STATUS_NO_MEMORY;
2013 *r->out.info = info;
2015 switch (r->in.level) {
2016 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2017 info->name.netbios_name.string
2018 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2019 break;
2020 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2021 info->posix_offset.posix_offset
2022 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2023 break;
2024 #if 0 /* Win2k3 doesn't implement this */
2025 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2026 r->out.info->info_basic.netbios_name.string
2027 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2028 r->out.info->info_basic.sid
2029 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2030 break;
2031 #endif
2032 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2033 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2035 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2036 ZERO_STRUCT(info->full_info);
2037 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2038 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2039 ZERO_STRUCT(info->full_info2_internal);
2040 info->full_info2_internal.posix_offset.posix_offset
2041 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2042 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2044 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2045 info->enc_types.enc_types
2046 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2047 break;
2049 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2050 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2051 /* oops, we don't want to return the info after all */
2052 talloc_free(info);
2053 *r->out.info = NULL;
2054 return NT_STATUS_INVALID_PARAMETER;
2055 default:
2056 /* oops, we don't want to return the info after all */
2057 talloc_free(info);
2058 *r->out.info = NULL;
2059 return NT_STATUS_INVALID_INFO_CLASS;
2062 return NT_STATUS_OK;
2067 lsa_QueryTrustedDomainInfoBySid
2069 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2070 struct lsa_QueryTrustedDomainInfoBySid *r)
2072 NTSTATUS status;
2073 struct lsa_OpenTrustedDomain opn;
2074 struct lsa_QueryTrustedDomainInfo query;
2075 struct dcesrv_handle *h;
2077 opn.in.handle = r->in.handle;
2078 opn.in.sid = r->in.dom_sid;
2079 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2080 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2081 if (!opn.out.trustdom_handle) {
2082 return NT_STATUS_NO_MEMORY;
2084 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2085 if (!NT_STATUS_IS_OK(status)) {
2086 return status;
2089 /* Ensure this handle goes away at the end of this call */
2090 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2091 talloc_steal(mem_ctx, h);
2093 query.in.trustdom_handle = opn.out.trustdom_handle;
2094 query.in.level = r->in.level;
2095 query.out.info = r->out.info;
2096 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2097 if (!NT_STATUS_IS_OK(status)) {
2098 return status;
2101 return NT_STATUS_OK;
2105 lsa_SetTrustedDomainInfoByName
2107 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2108 TALLOC_CTX *mem_ctx,
2109 struct lsa_SetTrustedDomainInfoByName *r)
2111 struct dcesrv_handle *policy_handle;
2112 struct lsa_policy_state *policy_state;
2113 struct ldb_message **msgs;
2114 NTSTATUS nt_status;
2116 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2117 policy_state = policy_handle->data;
2119 /* get the trusted domain object */
2120 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2121 policy_state->domain_dn,
2122 r->in.trusted_domain->string,
2123 r->in.trusted_domain->string,
2124 NULL, &msgs);
2125 if (!NT_STATUS_IS_OK(nt_status)) {
2126 if (NT_STATUS_EQUAL(nt_status,
2127 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2128 return nt_status;
2130 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2133 return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2134 msgs[0], r->in.level, r->in.info);
2138 lsa_QueryTrustedDomainInfoByName
2140 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2141 TALLOC_CTX *mem_ctx,
2142 struct lsa_QueryTrustedDomainInfoByName *r)
2144 NTSTATUS status;
2145 struct lsa_OpenTrustedDomainByName opn;
2146 struct lsa_QueryTrustedDomainInfo query;
2147 struct dcesrv_handle *h;
2149 opn.in.handle = r->in.handle;
2150 opn.in.name = *r->in.trusted_domain;
2151 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2152 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2153 if (!opn.out.trustdom_handle) {
2154 return NT_STATUS_NO_MEMORY;
2156 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2157 if (!NT_STATUS_IS_OK(status)) {
2158 return status;
2161 /* Ensure this handle goes away at the end of this call */
2162 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2163 talloc_steal(mem_ctx, h);
2165 query.in.trustdom_handle = opn.out.trustdom_handle;
2166 query.in.level = r->in.level;
2167 query.out.info = r->out.info;
2168 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2169 if (!NT_STATUS_IS_OK(status)) {
2170 return status;
2173 return NT_STATUS_OK;
2177 lsa_CloseTrustedDomainEx
2179 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2180 TALLOC_CTX *mem_ctx,
2181 struct lsa_CloseTrustedDomainEx *r)
2183 /* The result of a bad hair day from an IDL programmer? Not
2184 * implmented in Win2k3. You should always just lsa_Close
2185 * anyway. */
2186 return NT_STATUS_NOT_IMPLEMENTED;
2191 comparison function for sorting lsa_DomainInformation array
2193 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2195 return strcasecmp_m(e1->name.string, e2->name.string);
2199 lsa_EnumTrustDom
2201 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2202 struct lsa_EnumTrustDom *r)
2204 struct dcesrv_handle *policy_handle;
2205 struct lsa_DomainInfo *entries;
2206 struct lsa_policy_state *policy_state;
2207 struct ldb_message **domains;
2208 const char *attrs[] = {
2209 "flatname",
2210 "securityIdentifier",
2211 NULL
2215 int count, i;
2217 *r->out.resume_handle = 0;
2219 r->out.domains->domains = NULL;
2220 r->out.domains->count = 0;
2222 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2224 policy_state = policy_handle->data;
2226 /* search for all users in this domain. This could possibly be cached and
2227 resumed based on resume_key */
2228 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2229 "objectclass=trustedDomain");
2230 if (count < 0) {
2231 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2234 /* convert to lsa_TrustInformation format */
2235 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2236 if (!entries) {
2237 return NT_STATUS_NO_MEMORY;
2239 for (i=0;i<count;i++) {
2240 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2241 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2244 /* sort the results by name */
2245 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2247 if (*r->in.resume_handle >= count) {
2248 *r->out.resume_handle = -1;
2250 return NT_STATUS_NO_MORE_ENTRIES;
2253 /* return the rest, limit by max_size. Note that we
2254 use the w2k3 element size value of 60 */
2255 r->out.domains->count = count - *r->in.resume_handle;
2256 r->out.domains->count = MIN(r->out.domains->count,
2257 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2259 r->out.domains->domains = entries + *r->in.resume_handle;
2260 r->out.domains->count = r->out.domains->count;
2262 if (r->out.domains->count < count - *r->in.resume_handle) {
2263 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2264 return STATUS_MORE_ENTRIES;
2267 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2268 * always be larger than the previous input resume handle, in
2269 * particular when hitting the last query it is vital to set the
2270 * resume handle correctly to avoid infinite client loops, as
2271 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2272 * status is NT_STATUS_OK - gd */
2274 *r->out.resume_handle = (uint32_t)-1;
2276 return NT_STATUS_OK;
2280 comparison function for sorting lsa_DomainInformation array
2282 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2284 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2288 lsa_EnumTrustedDomainsEx
2290 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2291 struct lsa_EnumTrustedDomainsEx *r)
2293 struct dcesrv_handle *policy_handle;
2294 struct lsa_TrustDomainInfoInfoEx *entries;
2295 struct lsa_policy_state *policy_state;
2296 struct ldb_message **domains;
2297 const char *attrs[] = {
2298 "flatname",
2299 "trustPartner",
2300 "securityIdentifier",
2301 "trustDirection",
2302 "trustType",
2303 "trustAttributes",
2304 NULL
2306 NTSTATUS nt_status;
2308 int count, i;
2310 *r->out.resume_handle = 0;
2312 r->out.domains->domains = NULL;
2313 r->out.domains->count = 0;
2315 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2317 policy_state = policy_handle->data;
2319 /* search for all users in this domain. This could possibly be cached and
2320 resumed based on resume_key */
2321 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2322 "objectclass=trustedDomain");
2323 if (count < 0) {
2324 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2327 /* convert to lsa_DomainInformation format */
2328 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2329 if (!entries) {
2330 return NT_STATUS_NO_MEMORY;
2332 for (i=0;i<count;i++) {
2333 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2334 if (!NT_STATUS_IS_OK(nt_status)) {
2335 return nt_status;
2339 /* sort the results by name */
2340 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2342 if (*r->in.resume_handle >= count) {
2343 *r->out.resume_handle = -1;
2345 return NT_STATUS_NO_MORE_ENTRIES;
2348 /* return the rest, limit by max_size. Note that we
2349 use the w2k3 element size value of 60 */
2350 r->out.domains->count = count - *r->in.resume_handle;
2351 r->out.domains->count = MIN(r->out.domains->count,
2352 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2354 r->out.domains->domains = entries + *r->in.resume_handle;
2355 r->out.domains->count = r->out.domains->count;
2357 if (r->out.domains->count < count - *r->in.resume_handle) {
2358 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2359 return STATUS_MORE_ENTRIES;
2362 return NT_STATUS_OK;
2367 lsa_OpenAccount
2369 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2370 struct lsa_OpenAccount *r)
2372 struct dcesrv_handle *h, *ah;
2373 struct lsa_policy_state *state;
2374 struct lsa_account_state *astate;
2376 ZERO_STRUCTP(r->out.acct_handle);
2378 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2380 state = h->data;
2382 astate = talloc(dce_call->conn, struct lsa_account_state);
2383 if (astate == NULL) {
2384 return NT_STATUS_NO_MEMORY;
2387 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2388 if (astate->account_sid == NULL) {
2389 talloc_free(astate);
2390 return NT_STATUS_NO_MEMORY;
2393 astate->policy = talloc_reference(astate, state);
2394 astate->access_mask = r->in.access_mask;
2396 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2397 if (!ah) {
2398 talloc_free(astate);
2399 return NT_STATUS_NO_MEMORY;
2402 ah->data = talloc_steal(ah, astate);
2404 *r->out.acct_handle = ah->wire_handle;
2406 return NT_STATUS_OK;
2411 lsa_EnumPrivsAccount
2413 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2414 TALLOC_CTX *mem_ctx,
2415 struct lsa_EnumPrivsAccount *r)
2417 struct dcesrv_handle *h;
2418 struct lsa_account_state *astate;
2419 int ret;
2420 unsigned int i, j;
2421 struct ldb_message **res;
2422 const char * const attrs[] = { "privilege", NULL};
2423 struct ldb_message_element *el;
2424 const char *sidstr;
2425 struct lsa_PrivilegeSet *privs;
2427 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2429 astate = h->data;
2431 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2432 if (privs == NULL) {
2433 return NT_STATUS_NO_MEMORY;
2435 privs->count = 0;
2436 privs->unknown = 0;
2437 privs->set = NULL;
2439 *r->out.privs = privs;
2441 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2442 if (sidstr == NULL) {
2443 return NT_STATUS_NO_MEMORY;
2446 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2447 "objectSid=%s", sidstr);
2448 if (ret < 0) {
2449 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2451 if (ret != 1) {
2452 return NT_STATUS_OK;
2455 el = ldb_msg_find_element(res[0], "privilege");
2456 if (el == NULL || el->num_values == 0) {
2457 return NT_STATUS_OK;
2460 privs->set = talloc_array(privs,
2461 struct lsa_LUIDAttribute, el->num_values);
2462 if (privs->set == NULL) {
2463 return NT_STATUS_NO_MEMORY;
2466 j = 0;
2467 for (i=0;i<el->num_values;i++) {
2468 int id = sec_privilege_id((const char *)el->values[i].data);
2469 if (id == SEC_PRIV_INVALID) {
2470 /* Perhaps an account right, not a privilege */
2471 continue;
2473 privs->set[j].attribute = 0;
2474 privs->set[j].luid.low = id;
2475 privs->set[j].luid.high = 0;
2476 j++;
2479 privs->count = j;
2481 return NT_STATUS_OK;
2485 lsa_EnumAccountRights
2487 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2488 TALLOC_CTX *mem_ctx,
2489 struct lsa_EnumAccountRights *r)
2491 struct dcesrv_handle *h;
2492 struct lsa_policy_state *state;
2493 int ret;
2494 unsigned int i;
2495 struct ldb_message **res;
2496 const char * const attrs[] = { "privilege", NULL};
2497 const char *sidstr;
2498 struct ldb_message_element *el;
2500 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2502 state = h->data;
2504 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2505 if (sidstr == NULL) {
2506 return NT_STATUS_NO_MEMORY;
2509 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2510 "(&(objectSid=%s)(privilege=*))", sidstr);
2511 if (ret == 0) {
2512 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2514 if (ret != 1) {
2515 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2516 dom_sid_string(mem_ctx, r->in.sid),
2517 ldb_errstring(state->pdb)));
2518 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2521 el = ldb_msg_find_element(res[0], "privilege");
2522 if (el == NULL || el->num_values == 0) {
2523 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2526 r->out.rights->count = el->num_values;
2527 r->out.rights->names = talloc_array(r->out.rights,
2528 struct lsa_StringLarge, r->out.rights->count);
2529 if (r->out.rights->names == NULL) {
2530 return NT_STATUS_NO_MEMORY;
2533 for (i=0;i<el->num_values;i++) {
2534 r->out.rights->names[i].string = (const char *)el->values[i].data;
2537 return NT_STATUS_OK;
2543 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2545 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2546 TALLOC_CTX *mem_ctx,
2547 struct lsa_policy_state *state,
2548 int ldb_flag,
2549 struct dom_sid *sid,
2550 const struct lsa_RightSet *rights)
2552 const char *sidstr, *sidndrstr;
2553 struct ldb_message *msg;
2554 struct ldb_message_element *el;
2555 int ret;
2556 uint32_t i;
2557 struct lsa_EnumAccountRights r2;
2558 char *dnstr;
2560 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2561 SECURITY_ADMINISTRATOR) {
2562 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2563 return NT_STATUS_ACCESS_DENIED;
2566 msg = ldb_msg_new(mem_ctx);
2567 if (msg == NULL) {
2568 return NT_STATUS_NO_MEMORY;
2571 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2572 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
2574 sidstr = dom_sid_string(msg, sid);
2575 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
2577 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2578 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
2580 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2581 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
2583 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2584 NTSTATUS status;
2586 r2.in.handle = &state->handle->wire_handle;
2587 r2.in.sid = sid;
2588 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2590 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2591 if (!NT_STATUS_IS_OK(status)) {
2592 ZERO_STRUCTP(r2.out.rights);
2596 for (i=0;i<rights->count;i++) {
2597 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2598 if (sec_right_bit(rights->names[i].string) == 0) {
2599 talloc_free(msg);
2600 return NT_STATUS_NO_SUCH_PRIVILEGE;
2603 talloc_free(msg);
2604 return NT_STATUS_NO_SUCH_PRIVILEGE;
2607 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2608 uint32_t j;
2609 for (j=0;j<r2.out.rights->count;j++) {
2610 if (strcasecmp_m(r2.out.rights->names[j].string,
2611 rights->names[i].string) == 0) {
2612 break;
2615 if (j != r2.out.rights->count) continue;
2618 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2619 if (ret != LDB_SUCCESS) {
2620 talloc_free(msg);
2621 return NT_STATUS_NO_MEMORY;
2625 el = ldb_msg_find_element(msg, "privilege");
2626 if (!el) {
2627 talloc_free(msg);
2628 return NT_STATUS_OK;
2631 el->flags = ldb_flag;
2633 ret = ldb_modify(state->pdb, msg);
2634 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2635 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2636 talloc_free(msg);
2637 return NT_STATUS_NO_MEMORY;
2639 ldb_msg_add_string(msg, "comment", "added via LSA");
2640 ret = ldb_add(state->pdb, msg);
2642 if (ret != LDB_SUCCESS) {
2643 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2644 talloc_free(msg);
2645 return NT_STATUS_OK;
2647 DEBUG(3, ("Could not %s attributes from %s: %s",
2648 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2649 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2650 talloc_free(msg);
2651 return NT_STATUS_UNEXPECTED_IO_ERROR;
2654 talloc_free(msg);
2655 return NT_STATUS_OK;
2659 lsa_AddPrivilegesToAccount
2661 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2662 struct lsa_AddPrivilegesToAccount *r)
2664 struct lsa_RightSet rights;
2665 struct dcesrv_handle *h;
2666 struct lsa_account_state *astate;
2667 uint32_t i;
2669 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2671 astate = h->data;
2673 rights.count = r->in.privs->count;
2674 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2675 if (rights.names == NULL) {
2676 return NT_STATUS_NO_MEMORY;
2678 for (i=0;i<rights.count;i++) {
2679 int id = r->in.privs->set[i].luid.low;
2680 if (r->in.privs->set[i].luid.high) {
2681 return NT_STATUS_NO_SUCH_PRIVILEGE;
2683 rights.names[i].string = sec_privilege_name(id);
2684 if (rights.names[i].string == NULL) {
2685 return NT_STATUS_NO_SUCH_PRIVILEGE;
2689 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2690 LDB_FLAG_MOD_ADD, astate->account_sid,
2691 &rights);
2696 lsa_RemovePrivilegesFromAccount
2698 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2699 struct lsa_RemovePrivilegesFromAccount *r)
2701 struct lsa_RightSet *rights;
2702 struct dcesrv_handle *h;
2703 struct lsa_account_state *astate;
2704 uint32_t i;
2706 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2708 astate = h->data;
2710 rights = talloc(mem_ctx, struct lsa_RightSet);
2712 if (r->in.remove_all == 1 &&
2713 r->in.privs == NULL) {
2714 struct lsa_EnumAccountRights r2;
2715 NTSTATUS status;
2717 r2.in.handle = &astate->policy->handle->wire_handle;
2718 r2.in.sid = astate->account_sid;
2719 r2.out.rights = rights;
2721 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2722 if (!NT_STATUS_IS_OK(status)) {
2723 return status;
2726 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2727 LDB_FLAG_MOD_DELETE, astate->account_sid,
2728 r2.out.rights);
2731 if (r->in.remove_all != 0) {
2732 return NT_STATUS_INVALID_PARAMETER;
2735 rights->count = r->in.privs->count;
2736 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2737 if (rights->names == NULL) {
2738 return NT_STATUS_NO_MEMORY;
2740 for (i=0;i<rights->count;i++) {
2741 int id = r->in.privs->set[i].luid.low;
2742 if (r->in.privs->set[i].luid.high) {
2743 return NT_STATUS_NO_SUCH_PRIVILEGE;
2745 rights->names[i].string = sec_privilege_name(id);
2746 if (rights->names[i].string == NULL) {
2747 return NT_STATUS_NO_SUCH_PRIVILEGE;
2751 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2752 LDB_FLAG_MOD_DELETE, astate->account_sid,
2753 rights);
2758 lsa_GetQuotasForAccount
2760 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2761 struct lsa_GetQuotasForAccount *r)
2763 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2768 lsa_SetQuotasForAccount
2770 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2771 struct lsa_SetQuotasForAccount *r)
2773 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2778 lsa_GetSystemAccessAccount
2780 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2781 struct lsa_GetSystemAccessAccount *r)
2783 struct dcesrv_handle *h;
2784 struct lsa_account_state *astate;
2785 int ret;
2786 unsigned int i;
2787 struct ldb_message **res;
2788 const char * const attrs[] = { "privilege", NULL};
2789 struct ldb_message_element *el;
2790 const char *sidstr;
2792 *(r->out.access_mask) = 0x00000000;
2794 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2796 astate = h->data;
2798 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2799 if (sidstr == NULL) {
2800 return NT_STATUS_NO_MEMORY;
2803 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2804 "objectSid=%s", sidstr);
2805 if (ret < 0) {
2806 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2808 if (ret != 1) {
2809 return NT_STATUS_OK;
2812 el = ldb_msg_find_element(res[0], "privilege");
2813 if (el == NULL || el->num_values == 0) {
2814 return NT_STATUS_OK;
2817 for (i=0;i<el->num_values;i++) {
2818 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2819 if (right_bit == 0) {
2820 /* Perhaps an privilege, not a right */
2821 continue;
2823 *(r->out.access_mask) |= right_bit;
2826 return NT_STATUS_OK;
2831 lsa_SetSystemAccessAccount
2833 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2834 struct lsa_SetSystemAccessAccount *r)
2836 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2841 lsa_CreateSecret
2843 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2844 struct lsa_CreateSecret *r)
2846 struct dcesrv_handle *policy_handle;
2847 struct lsa_policy_state *policy_state;
2848 struct lsa_secret_state *secret_state;
2849 struct dcesrv_handle *handle;
2850 struct ldb_message **msgs, *msg;
2851 const char *attrs[] = {
2852 NULL
2855 const char *name;
2857 int ret;
2859 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2860 ZERO_STRUCTP(r->out.sec_handle);
2862 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2864 case SECURITY_SYSTEM:
2865 case SECURITY_ADMINISTRATOR:
2866 break;
2867 default:
2868 /* Users and annonymous are not allowed create secrets */
2869 return NT_STATUS_ACCESS_DENIED;
2872 policy_state = policy_handle->data;
2874 if (!r->in.name.string) {
2875 return NT_STATUS_INVALID_PARAMETER;
2878 secret_state = talloc(mem_ctx, struct lsa_secret_state);
2879 NT_STATUS_HAVE_NO_MEMORY(secret_state);
2880 secret_state->policy = policy_state;
2882 msg = ldb_msg_new(mem_ctx);
2883 if (msg == NULL) {
2884 return NT_STATUS_NO_MEMORY;
2887 if (strncmp("G$", r->in.name.string, 2) == 0) {
2888 const char *name2;
2890 secret_state->global = true;
2892 name = &r->in.name.string[2];
2893 if (strlen(name) == 0) {
2894 return NT_STATUS_INVALID_PARAMETER;
2897 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2898 ldb_binary_encode_string(mem_ctx, name));
2899 NT_STATUS_HAVE_NO_MEMORY(name2);
2901 /* We need to connect to the database as system, as this is one
2902 * of the rare RPC calls that must read the secrets (and this
2903 * is denied otherwise) */
2904 secret_state->sam_ldb = talloc_reference(secret_state,
2905 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));
2906 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2908 /* search for the secret record */
2909 ret = gendb_search(secret_state->sam_ldb,
2910 mem_ctx, policy_state->system_dn, &msgs, attrs,
2911 "(&(cn=%s)(objectclass=secret))",
2912 name2);
2913 if (ret > 0) {
2914 return NT_STATUS_OBJECT_NAME_COLLISION;
2917 if (ret < 0) {
2918 DEBUG(0,("Failure searching for CN=%s: %s\n",
2919 name2, ldb_errstring(secret_state->sam_ldb)));
2920 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2923 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2924 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2925 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2926 return NT_STATUS_NO_MEMORY;
2929 ret = ldb_msg_add_string(msg, "cn", name2);
2930 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2931 } else {
2932 secret_state->global = false;
2934 name = r->in.name.string;
2935 if (strlen(name) == 0) {
2936 return NT_STATUS_INVALID_PARAMETER;
2939 secret_state->sam_ldb = talloc_reference(secret_state,
2940 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
2941 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2943 /* search for the secret record */
2944 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2945 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2946 &msgs, attrs,
2947 "(&(cn=%s)(objectclass=secret))",
2948 ldb_binary_encode_string(mem_ctx, name));
2949 if (ret > 0) {
2950 return NT_STATUS_OBJECT_NAME_COLLISION;
2953 if (ret < 0) {
2954 DEBUG(0,("Failure searching for CN=%s: %s\n",
2955 name, ldb_errstring(secret_state->sam_ldb)));
2956 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2959 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
2960 "cn=%s,cn=LSA Secrets", name);
2961 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2962 ret = ldb_msg_add_string(msg, "cn", name);
2963 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2966 ret = ldb_msg_add_string(msg, "objectClass", "secret");
2967 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2969 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2970 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
2972 /* create the secret */
2973 ret = ldb_add(secret_state->sam_ldb, msg);
2974 if (ret != LDB_SUCCESS) {
2975 DEBUG(0,("Failed to create secret record %s: %s\n",
2976 ldb_dn_get_linearized(msg->dn),
2977 ldb_errstring(secret_state->sam_ldb)));
2978 return NT_STATUS_ACCESS_DENIED;
2981 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2982 NT_STATUS_HAVE_NO_MEMORY(handle);
2984 handle->data = talloc_steal(handle, secret_state);
2986 secret_state->access_mask = r->in.access_mask;
2987 secret_state->policy = talloc_reference(secret_state, policy_state);
2988 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
2990 *r->out.sec_handle = handle->wire_handle;
2992 return NT_STATUS_OK;
2997 lsa_OpenSecret
2999 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3000 struct lsa_OpenSecret *r)
3002 struct dcesrv_handle *policy_handle;
3004 struct lsa_policy_state *policy_state;
3005 struct lsa_secret_state *secret_state;
3006 struct dcesrv_handle *handle;
3007 struct ldb_message **msgs;
3008 const char *attrs[] = {
3009 NULL
3012 const char *name;
3014 int ret;
3016 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3017 ZERO_STRUCTP(r->out.sec_handle);
3018 policy_state = policy_handle->data;
3020 if (!r->in.name.string) {
3021 return NT_STATUS_INVALID_PARAMETER;
3024 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3026 case SECURITY_SYSTEM:
3027 case SECURITY_ADMINISTRATOR:
3028 break;
3029 default:
3030 /* Users and annonymous are not allowed to access secrets */
3031 return NT_STATUS_ACCESS_DENIED;
3034 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3035 if (!secret_state) {
3036 return NT_STATUS_NO_MEMORY;
3038 secret_state->policy = policy_state;
3040 if (strncmp("G$", r->in.name.string, 2) == 0) {
3041 name = &r->in.name.string[2];
3042 /* 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) */
3043 secret_state->sam_ldb = talloc_reference(secret_state,
3044 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));
3045 secret_state->global = true;
3047 if (strlen(name) < 1) {
3048 return NT_STATUS_INVALID_PARAMETER;
3051 /* search for the secret record */
3052 ret = gendb_search(secret_state->sam_ldb,
3053 mem_ctx, policy_state->system_dn, &msgs, attrs,
3054 "(&(cn=%s Secret)(objectclass=secret))",
3055 ldb_binary_encode_string(mem_ctx, name));
3056 if (ret == 0) {
3057 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3060 if (ret != 1) {
3061 DEBUG(0,("Found %d records matching DN %s\n", ret,
3062 ldb_dn_get_linearized(policy_state->system_dn)));
3063 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3066 } else {
3067 secret_state->global = false;
3068 secret_state->sam_ldb = talloc_reference(secret_state,
3069 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3071 name = r->in.name.string;
3072 if (strlen(name) < 1) {
3073 return NT_STATUS_INVALID_PARAMETER;
3076 /* search for the secret record */
3077 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3078 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3079 &msgs, attrs,
3080 "(&(cn=%s)(objectclass=secret))",
3081 ldb_binary_encode_string(mem_ctx, name));
3082 if (ret == 0) {
3083 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3086 if (ret != 1) {
3087 DEBUG(0,("Found %d records matching CN=%s\n",
3088 ret, ldb_binary_encode_string(mem_ctx, name)));
3089 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3093 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3095 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3096 if (!handle) {
3097 return NT_STATUS_NO_MEMORY;
3100 handle->data = talloc_steal(handle, secret_state);
3102 secret_state->access_mask = r->in.access_mask;
3103 secret_state->policy = talloc_reference(secret_state, policy_state);
3105 *r->out.sec_handle = handle->wire_handle;
3107 return NT_STATUS_OK;
3112 lsa_SetSecret
3114 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3115 struct lsa_SetSecret *r)
3118 struct dcesrv_handle *h;
3119 struct lsa_secret_state *secret_state;
3120 struct ldb_message *msg;
3121 DATA_BLOB session_key;
3122 DATA_BLOB crypt_secret, secret;
3123 struct ldb_val val;
3124 int ret;
3125 NTSTATUS status = NT_STATUS_OK;
3127 struct timeval now = timeval_current();
3128 NTTIME nt_now = timeval_to_nttime(&now);
3130 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3132 secret_state = h->data;
3134 msg = ldb_msg_new(mem_ctx);
3135 if (msg == NULL) {
3136 return NT_STATUS_NO_MEMORY;
3139 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3140 if (!msg->dn) {
3141 return NT_STATUS_NO_MEMORY;
3143 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3144 if (!NT_STATUS_IS_OK(status)) {
3145 return status;
3148 if (r->in.old_val) {
3149 /* Decrypt */
3150 crypt_secret.data = r->in.old_val->data;
3151 crypt_secret.length = r->in.old_val->size;
3153 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3154 if (!NT_STATUS_IS_OK(status)) {
3155 return status;
3158 val.data = secret.data;
3159 val.length = secret.length;
3161 /* set value */
3162 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3163 return NT_STATUS_NO_MEMORY;
3166 /* set old value mtime */
3167 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3168 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3169 return NT_STATUS_NO_MEMORY;
3172 } else {
3173 /* If the old value is not set, then migrate the
3174 * current value to the old value */
3175 const struct ldb_val *old_val;
3176 NTTIME last_set_time;
3177 struct ldb_message **res;
3178 const char *attrs[] = {
3179 "currentValue",
3180 "lastSetTime",
3181 NULL
3184 /* search for the secret record */
3185 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3186 secret_state->secret_dn, &res, attrs);
3187 if (ret == 0) {
3188 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3191 if (ret != 1) {
3192 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3193 ldb_dn_get_linearized(secret_state->secret_dn)));
3194 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3197 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3198 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3200 if (old_val) {
3201 /* set old value */
3202 if (ldb_msg_add_value(msg, "priorValue",
3203 old_val, NULL) != LDB_SUCCESS) {
3204 return NT_STATUS_NO_MEMORY;
3206 } else {
3207 if (samdb_msg_add_delete(secret_state->sam_ldb,
3208 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3209 return NT_STATUS_NO_MEMORY;
3214 /* set old value mtime */
3215 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3216 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3217 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3218 return NT_STATUS_NO_MEMORY;
3220 } else {
3221 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3222 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3223 return NT_STATUS_NO_MEMORY;
3228 if (r->in.new_val) {
3229 /* Decrypt */
3230 crypt_secret.data = r->in.new_val->data;
3231 crypt_secret.length = r->in.new_val->size;
3233 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3234 if (!NT_STATUS_IS_OK(status)) {
3235 return status;
3238 val.data = secret.data;
3239 val.length = secret.length;
3241 /* set value */
3242 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3243 return NT_STATUS_NO_MEMORY;
3246 /* set new value mtime */
3247 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3248 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3249 return NT_STATUS_NO_MEMORY;
3252 } else {
3253 /* NULL out the NEW value */
3254 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3255 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3256 return NT_STATUS_NO_MEMORY;
3258 if (samdb_msg_add_delete(secret_state->sam_ldb,
3259 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3260 return NT_STATUS_NO_MEMORY;
3264 /* modify the samdb record */
3265 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3266 if (ret != LDB_SUCCESS) {
3267 return dsdb_ldb_err_to_ntstatus(ret);
3270 return NT_STATUS_OK;
3275 lsa_QuerySecret
3277 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3278 struct lsa_QuerySecret *r)
3280 struct dcesrv_handle *h;
3281 struct lsa_secret_state *secret_state;
3282 struct ldb_message *msg;
3283 DATA_BLOB session_key;
3284 DATA_BLOB crypt_secret, secret;
3285 int ret;
3286 struct ldb_message **res;
3287 const char *attrs[] = {
3288 "currentValue",
3289 "priorValue",
3290 "lastSetTime",
3291 "priorSetTime",
3292 NULL
3295 NTSTATUS nt_status;
3297 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3299 /* Ensure user is permitted to read this... */
3300 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3302 case SECURITY_SYSTEM:
3303 case SECURITY_ADMINISTRATOR:
3304 break;
3305 default:
3306 /* Users and annonymous are not allowed to read secrets */
3307 return NT_STATUS_ACCESS_DENIED;
3310 secret_state = h->data;
3312 /* pull all the user attributes */
3313 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3314 secret_state->secret_dn, &res, attrs);
3315 if (ret != 1) {
3316 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3318 msg = res[0];
3320 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3321 if (!NT_STATUS_IS_OK(nt_status)) {
3322 return nt_status;
3325 if (r->in.old_val) {
3326 const struct ldb_val *prior_val;
3327 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3328 if (!r->out.old_val) {
3329 return NT_STATUS_NO_MEMORY;
3331 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
3333 if (prior_val && prior_val->length) {
3334 secret.data = prior_val->data;
3335 secret.length = prior_val->length;
3337 /* Encrypt */
3338 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3339 if (!crypt_secret.length) {
3340 return NT_STATUS_NO_MEMORY;
3342 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3343 if (!r->out.old_val->buf) {
3344 return NT_STATUS_NO_MEMORY;
3346 r->out.old_val->buf->size = crypt_secret.length;
3347 r->out.old_val->buf->length = crypt_secret.length;
3348 r->out.old_val->buf->data = crypt_secret.data;
3352 if (r->in.old_mtime) {
3353 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3354 if (!r->out.old_mtime) {
3355 return NT_STATUS_NO_MEMORY;
3357 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
3360 if (r->in.new_val) {
3361 const struct ldb_val *new_val;
3362 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3363 if (!r->out.new_val) {
3364 return NT_STATUS_NO_MEMORY;
3367 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3369 if (new_val && new_val->length) {
3370 secret.data = new_val->data;
3371 secret.length = new_val->length;
3373 /* Encrypt */
3374 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3375 if (!crypt_secret.length) {
3376 return NT_STATUS_NO_MEMORY;
3378 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3379 if (!r->out.new_val->buf) {
3380 return NT_STATUS_NO_MEMORY;
3382 r->out.new_val->buf->length = crypt_secret.length;
3383 r->out.new_val->buf->size = crypt_secret.length;
3384 r->out.new_val->buf->data = crypt_secret.data;
3388 if (r->in.new_mtime) {
3389 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3390 if (!r->out.new_mtime) {
3391 return NT_STATUS_NO_MEMORY;
3393 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3396 return NT_STATUS_OK;
3401 lsa_LookupPrivValue
3403 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3404 TALLOC_CTX *mem_ctx,
3405 struct lsa_LookupPrivValue *r)
3407 struct dcesrv_handle *h;
3408 struct lsa_policy_state *state;
3409 int id;
3411 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3413 state = h->data;
3415 id = sec_privilege_id(r->in.name->string);
3416 if (id == SEC_PRIV_INVALID) {
3417 return NT_STATUS_NO_SUCH_PRIVILEGE;
3420 r->out.luid->low = id;
3421 r->out.luid->high = 0;
3423 return NT_STATUS_OK;
3428 lsa_LookupPrivName
3430 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3431 TALLOC_CTX *mem_ctx,
3432 struct lsa_LookupPrivName *r)
3434 struct dcesrv_handle *h;
3435 struct lsa_policy_state *state;
3436 struct lsa_StringLarge *name;
3437 const char *privname;
3439 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3441 state = h->data;
3443 if (r->in.luid->high != 0) {
3444 return NT_STATUS_NO_SUCH_PRIVILEGE;
3447 privname = sec_privilege_name(r->in.luid->low);
3448 if (privname == NULL) {
3449 return NT_STATUS_NO_SUCH_PRIVILEGE;
3452 name = talloc(mem_ctx, struct lsa_StringLarge);
3453 if (name == NULL) {
3454 return NT_STATUS_NO_MEMORY;
3457 name->string = privname;
3459 *r->out.name = name;
3461 return NT_STATUS_OK;
3466 lsa_LookupPrivDisplayName
3468 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3469 TALLOC_CTX *mem_ctx,
3470 struct lsa_LookupPrivDisplayName *r)
3472 struct dcesrv_handle *h;
3473 struct lsa_policy_state *state;
3474 struct lsa_StringLarge *disp_name = NULL;
3475 enum sec_privilege id;
3477 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3479 state = h->data;
3481 id = sec_privilege_id(r->in.name->string);
3482 if (id == SEC_PRIV_INVALID) {
3483 return NT_STATUS_NO_SUCH_PRIVILEGE;
3486 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3487 if (disp_name == NULL) {
3488 return NT_STATUS_NO_MEMORY;
3491 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3492 if (disp_name->string == NULL) {
3493 return NT_STATUS_INTERNAL_ERROR;
3496 *r->out.disp_name = disp_name;
3497 *r->out.returned_language_id = 0;
3499 return NT_STATUS_OK;
3504 lsa_EnumAccountsWithUserRight
3506 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3507 TALLOC_CTX *mem_ctx,
3508 struct lsa_EnumAccountsWithUserRight *r)
3510 struct dcesrv_handle *h;
3511 struct lsa_policy_state *state;
3512 int ret, i;
3513 struct ldb_message **res;
3514 const char * const attrs[] = { "objectSid", NULL};
3515 const char *privname;
3517 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3519 state = h->data;
3521 if (r->in.name == NULL) {
3522 return NT_STATUS_NO_SUCH_PRIVILEGE;
3525 privname = r->in.name->string;
3526 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3527 return NT_STATUS_NO_SUCH_PRIVILEGE;
3530 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3531 "privilege=%s", privname);
3532 if (ret < 0) {
3533 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3535 if (ret == 0) {
3536 return NT_STATUS_NO_MORE_ENTRIES;
3539 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3540 if (r->out.sids->sids == NULL) {
3541 return NT_STATUS_NO_MEMORY;
3543 for (i=0;i<ret;i++) {
3544 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3545 res[i], "objectSid");
3546 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3548 r->out.sids->num_sids = ret;
3550 return NT_STATUS_OK;
3555 lsa_AddAccountRights
3557 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3558 TALLOC_CTX *mem_ctx,
3559 struct lsa_AddAccountRights *r)
3561 struct dcesrv_handle *h;
3562 struct lsa_policy_state *state;
3564 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3566 state = h->data;
3568 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3569 LDB_FLAG_MOD_ADD,
3570 r->in.sid, r->in.rights);
3575 lsa_RemoveAccountRights
3577 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3578 TALLOC_CTX *mem_ctx,
3579 struct lsa_RemoveAccountRights *r)
3581 struct dcesrv_handle *h;
3582 struct lsa_policy_state *state;
3584 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3586 state = h->data;
3588 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3589 LDB_FLAG_MOD_DELETE,
3590 r->in.sid, r->in.rights);
3595 lsa_StorePrivateData
3597 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3598 struct lsa_StorePrivateData *r)
3600 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3605 lsa_RetrievePrivateData
3607 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3608 struct lsa_RetrievePrivateData *r)
3610 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3615 lsa_GetUserName
3617 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3618 struct lsa_GetUserName *r)
3620 NTSTATUS status = NT_STATUS_OK;
3621 const char *account_name;
3622 const char *authority_name;
3623 struct lsa_String *_account_name;
3624 struct lsa_String *_authority_name = NULL;
3626 /* this is what w2k3 does */
3627 r->out.account_name = r->in.account_name;
3628 r->out.authority_name = r->in.authority_name;
3630 if (r->in.account_name
3631 && *r->in.account_name
3632 /* && *(*r->in.account_name)->string */
3634 return NT_STATUS_INVALID_PARAMETER;
3637 if (r->in.authority_name
3638 && *r->in.authority_name
3639 /* && *(*r->in.authority_name)->string */
3641 return NT_STATUS_INVALID_PARAMETER;
3644 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3645 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3647 _account_name = talloc(mem_ctx, struct lsa_String);
3648 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3649 _account_name->string = account_name;
3651 if (r->in.authority_name) {
3652 _authority_name = talloc(mem_ctx, struct lsa_String);
3653 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3654 _authority_name->string = authority_name;
3657 *r->out.account_name = _account_name;
3658 if (r->out.authority_name) {
3659 *r->out.authority_name = _authority_name;
3662 return status;
3666 lsa_SetInfoPolicy2
3668 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3669 TALLOC_CTX *mem_ctx,
3670 struct lsa_SetInfoPolicy2 *r)
3672 /* need to support these */
3673 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3677 lsa_QueryDomainInformationPolicy
3679 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3680 TALLOC_CTX *mem_ctx,
3681 struct lsa_QueryDomainInformationPolicy *r)
3683 union lsa_DomainInformationPolicy *info;
3685 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3686 if (!info) {
3687 return NT_STATUS_NO_MEMORY;
3690 switch (r->in.level) {
3691 case LSA_DOMAIN_INFO_POLICY_EFS:
3692 talloc_free(info);
3693 *r->out.info = NULL;
3694 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3695 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3697 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3698 struct smb_krb5_context *smb_krb5_context;
3699 int ret = smb_krb5_init_context(mem_ctx,
3700 dce_call->event_ctx,
3701 dce_call->conn->dce_ctx->lp_ctx,
3702 &smb_krb5_context);
3703 if (ret != 0) {
3704 talloc_free(info);
3705 *r->out.info = NULL;
3706 return NT_STATUS_INTERNAL_ERROR;
3708 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3709 smb_krb5_context,
3711 talloc_free(smb_krb5_context);
3712 *r->out.info = info;
3713 return NT_STATUS_OK;
3715 default:
3716 talloc_free(info);
3717 *r->out.info = NULL;
3718 return NT_STATUS_INVALID_INFO_CLASS;
3723 lsa_SetDomInfoPolicy
3725 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3726 TALLOC_CTX *mem_ctx,
3727 struct lsa_SetDomainInformationPolicy *r)
3729 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3733 lsa_TestCall
3735 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3736 TALLOC_CTX *mem_ctx,
3737 struct lsa_TestCall *r)
3739 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3743 lsa_CREDRWRITE
3745 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3746 struct lsa_CREDRWRITE *r)
3748 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3753 lsa_CREDRREAD
3755 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3756 struct lsa_CREDRREAD *r)
3758 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3763 lsa_CREDRENUMERATE
3765 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3766 struct lsa_CREDRENUMERATE *r)
3768 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3773 lsa_CREDRWRITEDOMAINCREDENTIALS
3775 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3776 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3778 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3783 lsa_CREDRREADDOMAINCREDENTIALS
3785 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3786 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3788 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3793 lsa_CREDRDELETE
3795 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3796 struct lsa_CREDRDELETE *r)
3798 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3803 lsa_CREDRGETTARGETINFO
3805 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3806 struct lsa_CREDRGETTARGETINFO *r)
3808 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3813 lsa_CREDRPROFILELOADED
3815 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3816 struct lsa_CREDRPROFILELOADED *r)
3818 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3823 lsa_CREDRGETSESSIONTYPES
3825 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3826 struct lsa_CREDRGETSESSIONTYPES *r)
3828 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3833 lsa_LSARREGISTERAUDITEVENT
3835 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3836 struct lsa_LSARREGISTERAUDITEVENT *r)
3838 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3843 lsa_LSARGENAUDITEVENT
3845 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3846 struct lsa_LSARGENAUDITEVENT *r)
3848 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3853 lsa_LSARUNREGISTERAUDITEVENT
3855 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3856 struct lsa_LSARUNREGISTERAUDITEVENT *r)
3858 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3863 lsa_lsaRQueryForestTrustInformation
3865 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3866 struct lsa_lsaRQueryForestTrustInformation *r)
3868 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3871 #define DNS_CMP_MATCH 0
3872 #define DNS_CMP_FIRST_IS_CHILD 1
3873 #define DNS_CMP_SECOND_IS_CHILD 2
3874 #define DNS_CMP_NO_MATCH 3
3876 /* this function assumes names are well formed DNS names.
3877 * it doesn't validate them */
3878 static int dns_cmp(const char *s1, size_t l1,
3879 const char *s2, size_t l2)
3881 const char *p1, *p2;
3882 size_t t1, t2;
3883 int cret;
3885 if (l1 == l2) {
3886 if (strcasecmp_m(s1, s2) == 0) {
3887 return DNS_CMP_MATCH;
3889 return DNS_CMP_NO_MATCH;
3892 if (l1 > l2) {
3893 p1 = s1;
3894 p2 = s2;
3895 t1 = l1;
3896 t2 = l2;
3897 cret = DNS_CMP_FIRST_IS_CHILD;
3898 } else {
3899 p1 = s2;
3900 p2 = s1;
3901 t1 = l2;
3902 t2 = l1;
3903 cret = DNS_CMP_SECOND_IS_CHILD;
3906 if (p1[t1 - t2 - 1] != '.') {
3907 return DNS_CMP_NO_MATCH;
3910 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3911 return cret;
3914 return DNS_CMP_NO_MATCH;
3917 /* decode all TDOs forest trust info blobs */
3918 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3919 struct ldb_message *msg,
3920 struct ForestTrustInfo *info)
3922 const struct ldb_val *ft_blob;
3923 enum ndr_err_code ndr_err;
3925 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3926 if (!ft_blob || !ft_blob->data) {
3927 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3929 /* ldb_val is equivalent to DATA_BLOB */
3930 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3931 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3932 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3933 return NT_STATUS_INVALID_DOMAIN_STATE;
3936 return NT_STATUS_OK;
3939 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
3940 struct ForestTrustInfo *fti)
3942 struct ForestTrustDataDomainInfo *info;
3943 struct ForestTrustInfoRecord *rec;
3945 fti->version = 1;
3946 fti->count = 2;
3947 fti->records = talloc_array(fti,
3948 struct ForestTrustInfoRecordArmor, 2);
3949 if (!fti->records) {
3950 return NT_STATUS_NO_MEMORY;
3953 /* TLN info */
3954 rec = &fti->records[0].record;
3956 rec->flags = 0;
3957 rec->timestamp = 0;
3958 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
3960 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
3961 if (!rec->data.name.string) {
3962 return NT_STATUS_NO_MEMORY;
3964 rec->data.name.size = strlen(rec->data.name.string);
3966 /* DOMAIN info */
3967 rec = &fti->records[1].record;
3969 rec->flags = 0;
3970 rec->timestamp = 0;
3971 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
3973 info = &rec->data.info;
3975 info->sid = *ps->domain_sid;
3976 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
3977 if (!info->dns_name.string) {
3978 return NT_STATUS_NO_MEMORY;
3980 info->dns_name.size = strlen(info->dns_name.string);
3981 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
3982 if (!info->netbios_name.string) {
3983 return NT_STATUS_NO_MEMORY;
3985 info->netbios_name.size = strlen(info->netbios_name.string);
3987 return NT_STATUS_OK;
3990 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
3991 struct lsa_ForestTrustInformation *lfti,
3992 struct ForestTrustInfo *fti)
3994 struct lsa_ForestTrustRecord *lrec;
3995 struct ForestTrustInfoRecord *rec;
3996 struct lsa_StringLarge *tln;
3997 struct lsa_ForestTrustDomainInfo *info;
3998 uint32_t i;
4000 fti->version = 1;
4001 fti->count = lfti->count;
4002 fti->records = talloc_array(mem_ctx,
4003 struct ForestTrustInfoRecordArmor,
4004 fti->count);
4005 if (!fti->records) {
4006 return NT_STATUS_NO_MEMORY;
4008 for (i = 0; i < fti->count; i++) {
4009 lrec = lfti->entries[i];
4010 rec = &fti->records[i].record;
4012 rec->flags = lrec->flags;
4013 rec->timestamp = lrec->time;
4014 rec->type = lrec->type;
4016 switch (lrec->type) {
4017 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4018 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4019 tln = &lrec->forest_trust_data.top_level_name;
4020 rec->data.name.string =
4021 talloc_strdup(mem_ctx, tln->string);
4022 if (!rec->data.name.string) {
4023 return NT_STATUS_NO_MEMORY;
4025 rec->data.name.size = strlen(rec->data.name.string);
4026 break;
4027 case LSA_FOREST_TRUST_DOMAIN_INFO:
4028 info = &lrec->forest_trust_data.domain_info;
4029 rec->data.info.sid = *info->domain_sid;
4030 rec->data.info.dns_name.string =
4031 talloc_strdup(mem_ctx,
4032 info->dns_domain_name.string);
4033 if (!rec->data.info.dns_name.string) {
4034 return NT_STATUS_NO_MEMORY;
4036 rec->data.info.dns_name.size =
4037 strlen(rec->data.info.dns_name.string);
4038 rec->data.info.netbios_name.string =
4039 talloc_strdup(mem_ctx,
4040 info->netbios_domain_name.string);
4041 if (!rec->data.info.netbios_name.string) {
4042 return NT_STATUS_NO_MEMORY;
4044 rec->data.info.netbios_name.size =
4045 strlen(rec->data.info.netbios_name.string);
4046 break;
4047 default:
4048 return NT_STATUS_INVALID_DOMAIN_STATE;
4052 return NT_STATUS_OK;
4055 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4056 uint32_t idx, uint32_t collision_type,
4057 uint32_t conflict_type, const char *tdo_name);
4059 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4060 const char *tdo_name,
4061 struct ForestTrustInfo *tdo_fti,
4062 struct ForestTrustInfo *new_fti,
4063 struct lsa_ForestTrustCollisionInfo *c_info)
4065 struct ForestTrustInfoRecord *nrec;
4066 struct ForestTrustInfoRecord *trec;
4067 const char *dns_name;
4068 const char *nb_name;
4069 struct dom_sid *sid;
4070 const char *tname;
4071 size_t dns_len;
4072 size_t nb_len;
4073 size_t tlen;
4074 NTSTATUS nt_status;
4075 uint32_t new_fti_idx;
4076 uint32_t i;
4077 /* use always TDO type, until we understand when Xref can be used */
4078 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4079 bool tln_conflict;
4080 bool sid_conflict;
4081 bool nb_conflict;
4082 bool exclusion;
4083 bool ex_rule;
4084 int ret;
4086 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4088 nrec = &new_fti->records[new_fti_idx].record;
4089 dns_name = NULL;
4090 tln_conflict = false;
4091 sid_conflict = false;
4092 nb_conflict = false;
4093 exclusion = false;
4095 switch (nrec->type) {
4096 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4097 /* exclusions do not conflict by definition */
4098 break;
4100 case FOREST_TRUST_TOP_LEVEL_NAME:
4101 dns_name = nrec->data.name.string;
4102 dns_len = nrec->data.name.size;
4103 break;
4105 case LSA_FOREST_TRUST_DOMAIN_INFO:
4106 dns_name = nrec->data.info.dns_name.string;
4107 dns_len = nrec->data.info.dns_name.size;
4108 nb_name = nrec->data.info.netbios_name.string;
4109 nb_len = nrec->data.info.netbios_name.size;
4110 sid = &nrec->data.info.sid;
4111 break;
4114 if (!dns_name) continue;
4116 /* check if this is already taken and not excluded */
4117 for (i = 0; i < tdo_fti->count; i++) {
4118 trec = &tdo_fti->records[i].record;
4120 switch (trec->type) {
4121 case FOREST_TRUST_TOP_LEVEL_NAME:
4122 ex_rule = false;
4123 tname = trec->data.name.string;
4124 tlen = trec->data.name.size;
4125 break;
4126 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4127 ex_rule = true;
4128 tname = trec->data.name.string;
4129 tlen = trec->data.name.size;
4130 break;
4131 case FOREST_TRUST_DOMAIN_INFO:
4132 ex_rule = false;
4133 tname = trec->data.info.dns_name.string;
4134 tlen = trec->data.info.dns_name.size;
4136 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4137 switch (ret) {
4138 case DNS_CMP_MATCH:
4139 /* if it matches exclusion,
4140 * it doesn't conflict */
4141 if (ex_rule) {
4142 exclusion = true;
4143 break;
4145 /* fall through */
4146 case DNS_CMP_FIRST_IS_CHILD:
4147 case DNS_CMP_SECOND_IS_CHILD:
4148 tln_conflict = true;
4149 /* fall through */
4150 default:
4151 break;
4154 /* explicit exclusion, no dns name conflict here */
4155 if (exclusion) {
4156 tln_conflict = false;
4159 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4160 continue;
4163 /* also test for domain info */
4164 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4165 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4166 sid_conflict = true;
4168 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4169 strcasecmp_m(trec->data.info.netbios_name.string,
4170 nb_name) == 0) {
4171 nb_conflict = true;
4175 if (tln_conflict) {
4176 nt_status = add_collision(c_info, new_fti_idx,
4177 collision_type,
4178 LSA_TLN_DISABLED_CONFLICT,
4179 tdo_name);
4181 if (sid_conflict) {
4182 nt_status = add_collision(c_info, new_fti_idx,
4183 collision_type,
4184 LSA_SID_DISABLED_CONFLICT,
4185 tdo_name);
4187 if (nb_conflict) {
4188 nt_status = add_collision(c_info, new_fti_idx,
4189 collision_type,
4190 LSA_NB_DISABLED_CONFLICT,
4191 tdo_name);
4195 return NT_STATUS_OK;
4198 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4199 uint32_t idx, uint32_t collision_type,
4200 uint32_t conflict_type, const char *tdo_name)
4202 struct lsa_ForestTrustCollisionRecord **es;
4203 uint32_t i = c_info->count;
4205 es = talloc_realloc(c_info, c_info->entries,
4206 struct lsa_ForestTrustCollisionRecord *, i + 1);
4207 if (!es) {
4208 return NT_STATUS_NO_MEMORY;
4210 c_info->entries = es;
4211 c_info->count = i + 1;
4213 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4214 if (!es[i]) {
4215 return NT_STATUS_NO_MEMORY;
4218 es[i]->index = idx;
4219 es[i]->type = collision_type;
4220 es[i]->flags.flags = conflict_type;
4221 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4222 if (!es[i]->name.string) {
4223 return NT_STATUS_NO_MEMORY;
4225 es[i]->name.size = strlen(es[i]->name.string);
4227 return NT_STATUS_OK;
4231 lsa_lsaRSetForestTrustInformation
4233 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4234 TALLOC_CTX *mem_ctx,
4235 struct lsa_lsaRSetForestTrustInformation *r)
4237 struct dcesrv_handle *h;
4238 struct lsa_policy_state *p_state;
4239 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4240 "msDS-TrustForestTrustInfo", NULL };
4241 struct ldb_message **dom_res = NULL;
4242 struct ldb_dn *tdo_dn;
4243 struct ldb_message *msg;
4244 int num_res, i;
4245 const char *td_name;
4246 uint32_t trust_attributes;
4247 struct lsa_ForestTrustCollisionInfo *c_info;
4248 struct ForestTrustInfo *nfti;
4249 struct ForestTrustInfo *fti;
4250 DATA_BLOB ft_blob;
4251 enum ndr_err_code ndr_err;
4252 NTSTATUS nt_status;
4253 bool am_rodc;
4254 int ret;
4256 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4258 p_state = h->data;
4260 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4261 return NT_STATUS_INVALID_DOMAIN_STATE;
4264 /* abort if we are not a PDC */
4265 if (!samdb_is_pdc(p_state->sam_ldb)) {
4266 return NT_STATUS_INVALID_DOMAIN_ROLE;
4269 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4270 if (ret == LDB_SUCCESS && am_rodc) {
4271 return NT_STATUS_NO_SUCH_DOMAIN;
4274 /* check caller has TRUSTED_SET_AUTH */
4276 /* fetch all trusted domain objects */
4277 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4278 p_state->system_dn,
4279 &dom_res, trust_attrs,
4280 "(objectclass=trustedDomain)");
4281 if (num_res == 0) {
4282 return NT_STATUS_NO_SUCH_DOMAIN;
4285 for (i = 0; i < num_res; i++) {
4286 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4287 "trustPartner", NULL);
4288 if (!td_name) {
4289 return NT_STATUS_INVALID_DOMAIN_STATE;
4291 if (strcasecmp_m(td_name,
4292 r->in.trusted_domain_name->string) == 0) {
4293 break;
4296 if (i >= num_res) {
4297 return NT_STATUS_NO_SUCH_DOMAIN;
4300 tdo_dn = dom_res[i]->dn;
4302 trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4303 "trustAttributes", 0);
4304 if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4305 return NT_STATUS_INVALID_PARAMETER;
4308 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4309 return NT_STATUS_INVALID_PARAMETER;
4312 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4313 if (!nfti) {
4314 return NT_STATUS_NO_MEMORY;
4317 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4318 if (!NT_STATUS_IS_OK(nt_status)) {
4319 return nt_status;
4322 c_info = talloc_zero(r->out.collision_info,
4323 struct lsa_ForestTrustCollisionInfo);
4324 if (!c_info) {
4325 return NT_STATUS_NO_MEMORY;
4328 /* first check own info, then other domains */
4329 fti = talloc(mem_ctx, struct ForestTrustInfo);
4330 if (!fti) {
4331 return NT_STATUS_NO_MEMORY;
4334 nt_status = own_ft_info(p_state, fti);
4335 if (!NT_STATUS_IS_OK(nt_status)) {
4336 return nt_status;
4339 nt_status = check_ft_info(c_info, p_state->domain_dns,
4340 fti, nfti, c_info);
4341 if (!NT_STATUS_IS_OK(nt_status)) {
4342 return nt_status;
4345 for (i = 0; i < num_res; i++) {
4346 fti = talloc(mem_ctx, struct ForestTrustInfo);
4347 if (!fti) {
4348 return NT_STATUS_NO_MEMORY;
4351 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4352 if (!NT_STATUS_IS_OK(nt_status)) {
4353 if (NT_STATUS_EQUAL(nt_status,
4354 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4355 continue;
4357 return nt_status;
4360 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4361 "trustPartner", NULL);
4362 if (!td_name) {
4363 return NT_STATUS_INVALID_DOMAIN_STATE;
4366 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4367 if (!NT_STATUS_IS_OK(nt_status)) {
4368 return nt_status;
4372 *r->out.collision_info = c_info;
4374 if (r->in.check_only != 0) {
4375 return NT_STATUS_OK;
4378 /* not just a check, write info back */
4380 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4381 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4382 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4383 return NT_STATUS_INVALID_PARAMETER;
4386 msg = ldb_msg_new(mem_ctx);
4387 if (msg == NULL) {
4388 return NT_STATUS_NO_MEMORY;
4391 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4392 if (!msg->dn) {
4393 return NT_STATUS_NO_MEMORY;
4396 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4397 LDB_FLAG_MOD_REPLACE, NULL);
4398 if (ret != LDB_SUCCESS) {
4399 return NT_STATUS_NO_MEMORY;
4401 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4402 &ft_blob, NULL);
4403 if (ret != LDB_SUCCESS) {
4404 return NT_STATUS_NO_MEMORY;
4407 ret = ldb_modify(p_state->sam_ldb, msg);
4408 if (ret != LDB_SUCCESS) {
4409 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4410 ldb_errstring(p_state->sam_ldb)));
4412 switch (ret) {
4413 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4414 return NT_STATUS_ACCESS_DENIED;
4415 default:
4416 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4420 return NT_STATUS_OK;
4424 lsa_CREDRRENAME
4426 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4427 struct lsa_CREDRRENAME *r)
4429 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4435 lsa_LSAROPENPOLICYSCE
4437 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4438 struct lsa_LSAROPENPOLICYSCE *r)
4440 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4445 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4447 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4448 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4450 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4455 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4457 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4458 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4460 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4465 lsa_LSARADTREPORTSECURITYEVENT
4467 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4468 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4470 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4474 /* include the generated boilerplate */
4475 #include "librpc/gen_ndr/ndr_lsa_s.c"
4479 /*****************************************
4480 NOTE! The remaining calls below were
4481 removed in w2k3, so the DCESRV_FAULT()
4482 replies are the correct implementation. Do
4483 not try and fill these in with anything else
4484 ******************************************/
4487 dssetup_DsRoleDnsNameToFlatName
4489 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4490 struct dssetup_DsRoleDnsNameToFlatName *r)
4492 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4497 dssetup_DsRoleDcAsDc
4499 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4500 struct dssetup_DsRoleDcAsDc *r)
4502 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4507 dssetup_DsRoleDcAsReplica
4509 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4510 struct dssetup_DsRoleDcAsReplica *r)
4512 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4517 dssetup_DsRoleDemoteDc
4519 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4520 struct dssetup_DsRoleDemoteDc *r)
4522 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4527 dssetup_DsRoleGetDcOperationProgress
4529 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4530 struct dssetup_DsRoleGetDcOperationProgress *r)
4532 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4537 dssetup_DsRoleGetDcOperationResults
4539 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4540 struct dssetup_DsRoleGetDcOperationResults *r)
4542 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4547 dssetup_DsRoleCancel
4549 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4550 struct dssetup_DsRoleCancel *r)
4552 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4557 dssetup_DsRoleServerSaveStateForUpgrade
4559 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4560 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4562 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4567 dssetup_DsRoleUpgradeDownlevelServer
4569 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4570 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4572 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4577 dssetup_DsRoleAbortDownlevelServerUpgrade
4579 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4580 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4582 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4586 /* include the generated boilerplate */
4587 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4589 NTSTATUS dcerpc_server_lsa_init(void)
4591 NTSTATUS ret;
4593 ret = dcerpc_server_dssetup_init();
4594 if (!NT_STATUS_IS_OK(ret)) {
4595 return ret;
4597 ret = dcerpc_server_lsarpc_init();
4598 if (!NT_STATUS_IS_OK(ret)) {
4599 return ret;
4601 return ret;