s4:rpc_server/lsa: better include a .h file don't include a .c file
[Samba/gebeck_regimport.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
blob0a94a874809e07df6d00161294f2c51fd55e13d9
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"
35 this type allows us to distinguish handle types
39 state associated with a lsa_OpenAccount() operation
41 struct lsa_account_state {
42 struct lsa_policy_state *policy;
43 uint32_t access_mask;
44 struct dom_sid *account_sid;
49 state associated with a lsa_OpenSecret() operation
51 struct lsa_secret_state {
52 struct lsa_policy_state *policy;
53 uint32_t access_mask;
54 struct ldb_dn *secret_dn;
55 struct ldb_context *sam_ldb;
56 bool global;
60 state associated with a lsa_OpenTrustedDomain() operation
62 struct lsa_trusted_domain_state {
63 struct lsa_policy_state *policy;
64 uint32_t access_mask;
65 struct ldb_dn *trusted_domain_dn;
66 struct ldb_dn *trusted_domain_user_dn;
70 this is based on the samba3 function make_lsa_object_sd()
71 It uses the same logic, but with samba4 helper functions
73 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
74 struct security_descriptor **sd,
75 struct dom_sid *sid,
76 uint32_t sid_access)
78 NTSTATUS status;
79 uint32_t rid;
80 struct dom_sid *domain_sid, *domain_admins_sid;
81 const char *domain_admins_sid_str, *sidstr;
82 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
84 status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
85 NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
87 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
88 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid, tmp_ctx);
90 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
91 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid_str, tmp_ctx);
93 sidstr = dom_sid_string(tmp_ctx, sid);
94 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, tmp_ctx);
96 *sd = security_descriptor_dacl_create(mem_ctx,
97 0, sidstr, NULL,
99 SID_WORLD,
100 SEC_ACE_TYPE_ACCESS_ALLOWED,
101 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
103 SID_BUILTIN_ADMINISTRATORS,
104 SEC_ACE_TYPE_ACCESS_ALLOWED,
105 SEC_GENERIC_ALL, 0,
107 SID_BUILTIN_ACCOUNT_OPERATORS,
108 SEC_ACE_TYPE_ACCESS_ALLOWED,
109 SEC_GENERIC_ALL, 0,
111 domain_admins_sid_str,
112 SEC_ACE_TYPE_ACCESS_ALLOWED,
113 SEC_GENERIC_ALL, 0,
115 sidstr,
116 SEC_ACE_TYPE_ACCESS_ALLOWED,
117 sid_access, 0,
119 NULL);
120 talloc_free(tmp_ctx);
122 NT_STATUS_HAVE_NO_MEMORY(*sd);
124 return NT_STATUS_OK;
128 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
129 TALLOC_CTX *mem_ctx,
130 struct lsa_EnumAccountRights *r);
132 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
133 TALLOC_CTX *mem_ctx,
134 struct lsa_policy_state *state,
135 int ldb_flag,
136 struct dom_sid *sid,
137 const struct lsa_RightSet *rights);
140 lsa_Close
142 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
143 struct lsa_Close *r)
145 struct dcesrv_handle *h;
147 *r->out.handle = *r->in.handle;
149 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
151 talloc_free(h);
153 ZERO_STRUCTP(r->out.handle);
155 return NT_STATUS_OK;
160 lsa_Delete
162 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
163 struct lsa_Delete *r)
165 return NT_STATUS_NOT_SUPPORTED;
170 lsa_DeleteObject
172 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
173 struct lsa_DeleteObject *r)
175 struct dcesrv_handle *h;
176 int ret;
178 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
180 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
181 struct lsa_secret_state *secret_state = h->data;
183 /* Ensure user is permitted to delete this... */
184 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
186 case SECURITY_SYSTEM:
187 case SECURITY_ADMINISTRATOR:
188 break;
189 default:
190 /* Users and anonymous are not allowed to delete things */
191 return NT_STATUS_ACCESS_DENIED;
194 ret = ldb_delete(secret_state->sam_ldb,
195 secret_state->secret_dn);
196 if (ret != LDB_SUCCESS) {
197 return NT_STATUS_INVALID_HANDLE;
200 ZERO_STRUCTP(r->out.handle);
202 return NT_STATUS_OK;
204 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
205 struct lsa_trusted_domain_state *trusted_domain_state =
206 talloc_get_type(h->data, struct lsa_trusted_domain_state);
207 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
208 if (ret != LDB_SUCCESS) {
209 return NT_STATUS_INTERNAL_DB_CORRUPTION;
212 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
213 trusted_domain_state->trusted_domain_dn);
214 if (ret != LDB_SUCCESS) {
215 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
216 return NT_STATUS_INVALID_HANDLE;
219 if (trusted_domain_state->trusted_domain_user_dn) {
220 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
221 trusted_domain_state->trusted_domain_user_dn);
222 if (ret != LDB_SUCCESS) {
223 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
224 return NT_STATUS_INVALID_HANDLE;
228 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
229 if (ret != LDB_SUCCESS) {
230 return NT_STATUS_INTERNAL_DB_CORRUPTION;
233 ZERO_STRUCTP(r->out.handle);
235 return NT_STATUS_OK;
237 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
238 struct lsa_RightSet *rights;
239 struct lsa_account_state *astate;
240 struct lsa_EnumAccountRights r2;
241 NTSTATUS status;
243 rights = talloc(mem_ctx, struct lsa_RightSet);
245 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
247 astate = h->data;
249 r2.in.handle = &astate->policy->handle->wire_handle;
250 r2.in.sid = astate->account_sid;
251 r2.out.rights = rights;
253 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
254 but we have a LSA_HANDLE_ACCOUNT here, so this call
255 will always fail */
256 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
257 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
258 return NT_STATUS_OK;
261 if (!NT_STATUS_IS_OK(status)) {
262 return status;
265 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
266 LDB_FLAG_MOD_DELETE, astate->account_sid,
267 r2.out.rights);
268 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
269 return NT_STATUS_OK;
272 if (!NT_STATUS_IS_OK(status)) {
273 return status;
276 ZERO_STRUCTP(r->out.handle);
278 return NT_STATUS_OK;
281 return NT_STATUS_INVALID_HANDLE;
286 lsa_EnumPrivs
288 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
289 struct lsa_EnumPrivs *r)
291 struct dcesrv_handle *h;
292 struct lsa_policy_state *state;
293 uint32_t i;
294 const char *privname;
296 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
298 state = h->data;
300 i = *r->in.resume_handle;
301 if (i == 0) i = 1;
303 while ((privname = sec_privilege_name(i)) &&
304 r->out.privs->count < r->in.max_count) {
305 struct lsa_PrivEntry *e;
307 r->out.privs->privs = talloc_realloc(r->out.privs,
308 r->out.privs->privs,
309 struct lsa_PrivEntry,
310 r->out.privs->count+1);
311 if (r->out.privs->privs == NULL) {
312 return NT_STATUS_NO_MEMORY;
314 e = &r->out.privs->privs[r->out.privs->count];
315 e->luid.low = i;
316 e->luid.high = 0;
317 e->name.string = privname;
318 r->out.privs->count++;
319 i++;
322 *r->out.resume_handle = i;
324 return NT_STATUS_OK;
329 lsa_QuerySecObj
331 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
332 struct lsa_QuerySecurity *r)
334 struct dcesrv_handle *h;
335 struct security_descriptor *sd;
336 NTSTATUS status;
337 struct dom_sid *sid;
339 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
341 sid = dce_call->conn->auth_state.session_info->security_token->user_sid;
343 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
344 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
345 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
346 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid,
347 LSA_ACCOUNT_ALL_ACCESS);
348 } else {
349 return NT_STATUS_INVALID_HANDLE;
351 NT_STATUS_NOT_OK_RETURN(status);
353 (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
354 NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
356 (*r->out.sdbuf)->sd = sd;
358 return NT_STATUS_OK;
363 lsa_SetSecObj
365 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
366 struct lsa_SetSecObj *r)
368 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
373 lsa_ChangePassword
375 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
376 struct lsa_ChangePassword *r)
378 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
382 dssetup_DsRoleGetPrimaryDomainInformation
384 This is not an LSA call, but is the only call left on the DSSETUP
385 pipe (after the pipe was truncated), and needs lsa_get_policy_state
387 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
388 TALLOC_CTX *mem_ctx,
389 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
391 union dssetup_DsRoleInfo *info;
393 info = talloc(mem_ctx, union dssetup_DsRoleInfo);
394 W_ERROR_HAVE_NO_MEMORY(info);
396 switch (r->in.level) {
397 case DS_ROLE_BASIC_INFORMATION:
399 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
400 uint32_t flags = 0;
401 const char *domain = NULL;
402 const char *dns_domain = NULL;
403 const char *forest = NULL;
404 struct GUID domain_guid;
405 struct lsa_policy_state *state;
407 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
408 if (!NT_STATUS_IS_OK(status)) {
409 return ntstatus_to_werror(status);
412 ZERO_STRUCT(domain_guid);
414 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
415 case ROLE_STANDALONE:
416 role = DS_ROLE_STANDALONE_SERVER;
417 break;
418 case ROLE_DOMAIN_MEMBER:
419 role = DS_ROLE_MEMBER_SERVER;
420 break;
421 case ROLE_DOMAIN_CONTROLLER:
422 if (samdb_is_pdc(state->sam_ldb)) {
423 role = DS_ROLE_PRIMARY_DC;
424 } else {
425 role = DS_ROLE_BACKUP_DC;
427 break;
430 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
431 case ROLE_STANDALONE:
432 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
433 W_ERROR_HAVE_NO_MEMORY(domain);
434 break;
435 case ROLE_DOMAIN_MEMBER:
436 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
437 W_ERROR_HAVE_NO_MEMORY(domain);
438 /* TODO: what is with dns_domain and forest and guid? */
439 break;
440 case ROLE_DOMAIN_CONTROLLER:
441 flags = DS_ROLE_PRIMARY_DS_RUNNING;
443 if (state->mixed_domain == 1) {
444 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
447 domain = state->domain_name;
448 dns_domain = state->domain_dns;
449 forest = state->forest_dns;
451 domain_guid = state->domain_guid;
452 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
453 break;
456 info->basic.role = role;
457 info->basic.flags = flags;
458 info->basic.domain = domain;
459 info->basic.dns_domain = dns_domain;
460 info->basic.forest = forest;
461 info->basic.domain_guid = domain_guid;
463 r->out.info = info;
464 return WERR_OK;
466 case DS_ROLE_UPGRADE_STATUS:
468 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
469 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
471 r->out.info = info;
472 return WERR_OK;
474 case DS_ROLE_OP_STATUS:
476 info->opstatus.status = DS_ROLE_OP_IDLE;
478 r->out.info = info;
479 return WERR_OK;
481 default:
482 return WERR_INVALID_PARAM;
487 fill in the AccountDomain info
489 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
490 struct lsa_DomainInfo *info)
492 info->name.string = state->domain_name;
493 info->sid = state->domain_sid;
495 return NT_STATUS_OK;
499 fill in the DNS domain info
501 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
502 struct lsa_DnsDomainInfo *info)
504 info->name.string = state->domain_name;
505 info->sid = state->domain_sid;
506 info->dns_domain.string = state->domain_dns;
507 info->dns_forest.string = state->forest_dns;
508 info->domain_guid = state->domain_guid;
510 return NT_STATUS_OK;
514 lsa_QueryInfoPolicy2
516 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
517 struct lsa_QueryInfoPolicy2 *r)
519 struct lsa_policy_state *state;
520 struct dcesrv_handle *h;
521 union lsa_PolicyInformation *info;
523 *r->out.info = NULL;
525 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
527 state = h->data;
529 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
530 if (!info) {
531 return NT_STATUS_NO_MEMORY;
533 *r->out.info = info;
535 switch (r->in.level) {
536 case LSA_POLICY_INFO_AUDIT_LOG:
537 /* we don't need to fill in any of this */
538 ZERO_STRUCT(info->audit_log);
539 return NT_STATUS_OK;
540 case LSA_POLICY_INFO_AUDIT_EVENTS:
541 /* we don't need to fill in any of this */
542 ZERO_STRUCT(info->audit_events);
543 return NT_STATUS_OK;
544 case LSA_POLICY_INFO_PD:
545 /* we don't need to fill in any of this */
546 ZERO_STRUCT(info->pd);
547 return NT_STATUS_OK;
549 case LSA_POLICY_INFO_DOMAIN:
550 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
551 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
552 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
553 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
554 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
556 case LSA_POLICY_INFO_ROLE:
557 info->role.role = LSA_ROLE_PRIMARY;
558 return NT_STATUS_OK;
560 case LSA_POLICY_INFO_DNS:
561 case LSA_POLICY_INFO_DNS_INT:
562 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
564 case LSA_POLICY_INFO_REPLICA:
565 ZERO_STRUCT(info->replica);
566 return NT_STATUS_OK;
568 case LSA_POLICY_INFO_QUOTA:
569 ZERO_STRUCT(info->quota);
570 return NT_STATUS_OK;
572 case LSA_POLICY_INFO_MOD:
573 case LSA_POLICY_INFO_AUDIT_FULL_SET:
574 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
575 /* windows gives INVALID_PARAMETER */
576 *r->out.info = NULL;
577 return NT_STATUS_INVALID_PARAMETER;
580 *r->out.info = NULL;
581 return NT_STATUS_INVALID_INFO_CLASS;
585 lsa_QueryInfoPolicy
587 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
588 struct lsa_QueryInfoPolicy *r)
590 struct lsa_QueryInfoPolicy2 r2;
591 NTSTATUS status;
593 ZERO_STRUCT(r2);
595 r2.in.handle = r->in.handle;
596 r2.in.level = r->in.level;
597 r2.out.info = r->out.info;
599 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
601 return status;
605 lsa_SetInfoPolicy
607 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
608 struct lsa_SetInfoPolicy *r)
610 /* need to support this */
611 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
616 lsa_ClearAuditLog
618 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
619 struct lsa_ClearAuditLog *r)
621 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
626 lsa_CreateAccount
628 This call does not seem to have any long-term effects, hence no database operations
630 we need to talk to the MS product group to find out what this account database means!
632 answer is that the lsa database is totally separate from the SAM and
633 ldap databases. We are going to need a separate ldb to store these
634 accounts. The SIDs on this account bear no relation to the SIDs in
637 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
638 struct lsa_CreateAccount *r)
640 struct lsa_account_state *astate;
642 struct lsa_policy_state *state;
643 struct dcesrv_handle *h, *ah;
645 ZERO_STRUCTP(r->out.acct_handle);
647 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
649 state = h->data;
651 astate = talloc(dce_call->conn, struct lsa_account_state);
652 if (astate == NULL) {
653 return NT_STATUS_NO_MEMORY;
656 astate->account_sid = dom_sid_dup(astate, r->in.sid);
657 if (astate->account_sid == NULL) {
658 talloc_free(astate);
659 return NT_STATUS_NO_MEMORY;
662 astate->policy = talloc_reference(astate, state);
663 astate->access_mask = r->in.access_mask;
665 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
666 if (!ah) {
667 talloc_free(astate);
668 return NT_STATUS_NO_MEMORY;
671 ah->data = talloc_steal(ah, astate);
673 *r->out.acct_handle = ah->wire_handle;
675 return NT_STATUS_OK;
680 lsa_EnumAccounts
682 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
683 struct lsa_EnumAccounts *r)
685 struct dcesrv_handle *h;
686 struct lsa_policy_state *state;
687 int ret;
688 struct ldb_message **res;
689 const char * const attrs[] = { "objectSid", NULL};
690 uint32_t count, i;
692 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
694 state = h->data;
696 /* NOTE: This call must only return accounts that have at least
697 one privilege set
699 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
700 "(&(objectSid=*)(privilege=*))");
701 if (ret < 0) {
702 return NT_STATUS_INTERNAL_DB_CORRUPTION;
705 if (*r->in.resume_handle >= ret) {
706 return NT_STATUS_NO_MORE_ENTRIES;
709 count = ret - *r->in.resume_handle;
710 if (count > r->in.num_entries) {
711 count = r->in.num_entries;
714 if (count == 0) {
715 return NT_STATUS_NO_MORE_ENTRIES;
718 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
719 if (r->out.sids->sids == NULL) {
720 return NT_STATUS_NO_MEMORY;
723 for (i=0;i<count;i++) {
724 r->out.sids->sids[i].sid =
725 samdb_result_dom_sid(r->out.sids->sids,
726 res[i + *r->in.resume_handle],
727 "objectSid");
728 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
731 r->out.sids->num_sids = count;
732 *r->out.resume_handle = count + *r->in.resume_handle;
734 return NT_STATUS_OK;
738 /* This decrypts and returns Trusted Domain Auth Information Internal data */
739 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
740 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
741 struct trustDomainPasswords *auth_struct)
743 DATA_BLOB session_key = data_blob(NULL, 0);
744 enum ndr_err_code ndr_err;
745 NTSTATUS nt_status;
747 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
748 if (!NT_STATUS_IS_OK(nt_status)) {
749 return nt_status;
752 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
753 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
754 auth_struct,
755 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
756 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
757 return NT_STATUS_INVALID_PARAMETER;
760 return NT_STATUS_OK;
763 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
764 TALLOC_CTX *mem_ctx,
765 struct trustCurrentPasswords *iopw,
766 DATA_BLOB *trustauth_blob)
768 uint32_t i;
769 struct trustAuthInOutBlob ioblob;
770 enum ndr_err_code ndr_err;
772 ioblob.count = iopw->count;
773 ioblob.current = talloc(mem_ctx,
774 struct AuthenticationInformationArray);
775 if (!ioblob.current) {
776 return NT_STATUS_NO_MEMORY;
779 ioblob.current->array = *iopw->current;
780 if (!ioblob.current->array) {
781 return NT_STATUS_NO_MEMORY;
784 ioblob.previous = talloc(mem_ctx,
785 struct AuthenticationInformationArray);
786 if (!ioblob.previous) {
787 return NT_STATUS_NO_MEMORY;
789 ioblob.previous->array = talloc_array(mem_ctx,
790 struct AuthenticationInformation,
791 ioblob.count);
792 if (!ioblob.previous->array) {
793 return NT_STATUS_NO_MEMORY;
796 for (i = 0; i < ioblob.count; i++) {
797 ioblob.previous->array[i].LastUpdateTime = 0;
798 ioblob.previous->array[i].AuthType = 0;
800 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
801 &ioblob,
802 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
803 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
804 return NT_STATUS_INVALID_PARAMETER;
807 return NT_STATUS_OK;
810 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
811 struct ldb_context *sam_ldb,
812 struct ldb_dn *base_dn,
813 const char *netbios_name,
814 struct trustCurrentPasswords *in,
815 struct ldb_dn **user_dn)
817 struct ldb_message *msg;
818 struct ldb_dn *dn;
819 uint32_t i;
820 int ret;
822 dn = ldb_dn_copy(mem_ctx, base_dn);
823 if (!dn) {
824 return NT_STATUS_NO_MEMORY;
826 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
827 return NT_STATUS_NO_MEMORY;
830 msg = ldb_msg_new(mem_ctx);
831 if (!msg) {
832 return NT_STATUS_NO_MEMORY;
834 msg->dn = dn;
836 ret = ldb_msg_add_string(msg, "objectClass", "user");
837 if (ret != LDB_SUCCESS) {
838 return NT_STATUS_NO_MEMORY;
841 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
842 if (ret != LDB_SUCCESS) {
843 return NT_STATUS_NO_MEMORY;
846 ret = ldb_msg_add_fmt(msg, "userAccountControl", "%u",
847 UF_INTERDOMAIN_TRUST_ACCOUNT);
848 if (ret != LDB_SUCCESS) {
849 return NT_STATUS_NO_MEMORY;
852 for (i = 0; i < in->count; i++) {
853 const char *attribute;
854 struct ldb_val v;
855 switch (in->current[i]->AuthType) {
856 case TRUST_AUTH_TYPE_NT4OWF:
857 attribute = "unicodePwd";
858 v.data = (uint8_t *)&in->current[i]->AuthInfo.nt4owf.password;
859 v.length = 16;
860 break;
861 case TRUST_AUTH_TYPE_CLEAR:
862 attribute = "clearTextPassword";
863 v.data = in->current[i]->AuthInfo.clear.password;
864 v.length = in->current[i]->AuthInfo.clear.size;
865 break;
866 default:
867 continue;
870 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
871 if (ret != LDB_SUCCESS) {
872 return NT_STATUS_NO_MEMORY;
876 /* create the trusted_domain user account */
877 ret = ldb_add(sam_ldb, msg);
878 if (ret != LDB_SUCCESS) {
879 DEBUG(0,("Failed to create user record %s: %s\n",
880 ldb_dn_get_linearized(msg->dn),
881 ldb_errstring(sam_ldb)));
883 switch (ret) {
884 case LDB_ERR_ENTRY_ALREADY_EXISTS:
885 return NT_STATUS_DOMAIN_EXISTS;
886 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
887 return NT_STATUS_ACCESS_DENIED;
888 default:
889 return NT_STATUS_INTERNAL_DB_CORRUPTION;
893 if (user_dn) {
894 *user_dn = dn;
896 return NT_STATUS_OK;
900 lsa_CreateTrustedDomainEx2
902 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
903 TALLOC_CTX *mem_ctx,
904 struct lsa_CreateTrustedDomainEx2 *r,
905 int op)
907 struct dcesrv_handle *policy_handle;
908 struct lsa_policy_state *policy_state;
909 struct lsa_trusted_domain_state *trusted_domain_state;
910 struct dcesrv_handle *handle;
911 struct ldb_message **msgs, *msg;
912 const char *attrs[] = {
913 NULL
915 const char *netbios_name;
916 const char *dns_name;
917 const char *name;
918 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
919 struct trustDomainPasswords auth_struct;
920 int ret;
921 NTSTATUS nt_status;
922 struct ldb_context *sam_ldb;
924 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
925 ZERO_STRUCTP(r->out.trustdom_handle);
927 policy_state = policy_handle->data;
928 sam_ldb = policy_state->sam_ldb;
930 netbios_name = r->in.info->netbios_name.string;
931 if (!netbios_name) {
932 return NT_STATUS_INVALID_PARAMETER;
935 dns_name = r->in.info->domain_name.string;
937 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
938 if (!trusted_domain_state) {
939 return NT_STATUS_NO_MEMORY;
941 trusted_domain_state->policy = policy_state;
943 if (strcasecmp(netbios_name, "BUILTIN") == 0
944 || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
945 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
946 return NT_STATUS_INVALID_PARAMETER;
949 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
950 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
951 || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
952 || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
953 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
954 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
957 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
958 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
959 /* No secrets are created at this time, for this function */
960 auth_struct.outgoing.count = 0;
961 auth_struct.incoming.count = 0;
962 } else {
963 auth_blob = data_blob_const(r->in.auth_info->auth_blob.data,
964 r->in.auth_info->auth_blob.size);
965 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
966 &auth_blob, &auth_struct);
967 if (!NT_STATUS_IS_OK(nt_status)) {
968 return nt_status;
971 if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
972 if (auth_struct.incoming.count > 1) {
973 return NT_STATUS_INVALID_PARAMETER;
978 if (auth_struct.incoming.count) {
979 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
980 &auth_struct.incoming,
981 &trustAuthIncoming);
982 if (!NT_STATUS_IS_OK(nt_status)) {
983 return nt_status;
985 } else {
986 trustAuthIncoming = data_blob(NULL, 0);
989 if (auth_struct.outgoing.count) {
990 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
991 &auth_struct.outgoing,
992 &trustAuthOutgoing);
993 if (!NT_STATUS_IS_OK(nt_status)) {
994 return nt_status;
996 } else {
997 trustAuthOutgoing = data_blob(NULL, 0);
1000 ret = ldb_transaction_start(sam_ldb);
1001 if (ret != LDB_SUCCESS) {
1002 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1005 if (dns_name) {
1006 char *dns_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1007 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1008 /* search for the trusted_domain record */
1009 ret = gendb_search(sam_ldb,
1010 mem_ctx, policy_state->system_dn, &msgs, attrs,
1011 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1012 dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
1013 if (ret > 0) {
1014 ldb_transaction_cancel(sam_ldb);
1015 return NT_STATUS_OBJECT_NAME_COLLISION;
1017 } else {
1018 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1019 /* search for the trusted_domain record */
1020 ret = gendb_search(sam_ldb,
1021 mem_ctx, policy_state->system_dn, &msgs, attrs,
1022 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1023 netbios_encoded, netbios_encoded, netbios_encoded);
1024 if (ret > 0) {
1025 ldb_transaction_cancel(sam_ldb);
1026 return NT_STATUS_OBJECT_NAME_COLLISION;
1030 if (ret < 0 ) {
1031 ldb_transaction_cancel(sam_ldb);
1032 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1035 name = dns_name ? dns_name : netbios_name;
1037 msg = ldb_msg_new(mem_ctx);
1038 if (msg == NULL) {
1039 return NT_STATUS_NO_MEMORY;
1042 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1043 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1044 ldb_transaction_cancel(sam_ldb);
1045 return NT_STATUS_NO_MEMORY;
1048 samdb_msg_add_string(sam_ldb, mem_ctx, msg, "flatname", netbios_name);
1050 if (r->in.info->sid) {
1051 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1052 if (ret != LDB_SUCCESS) {
1053 ldb_transaction_cancel(sam_ldb);
1054 return NT_STATUS_INVALID_PARAMETER;
1058 samdb_msg_add_string(sam_ldb, mem_ctx, msg, "objectClass", "trustedDomain");
1060 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1062 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1064 samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1066 if (dns_name) {
1067 samdb_msg_add_string(sam_ldb, mem_ctx, msg, "trustPartner", dns_name);
1070 if (trustAuthIncoming.data) {
1071 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1072 if (ret != LDB_SUCCESS) {
1073 ldb_transaction_cancel(sam_ldb);
1074 return NT_STATUS_NO_MEMORY;
1077 if (trustAuthOutgoing.data) {
1078 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1079 if (ret != LDB_SUCCESS) {
1080 ldb_transaction_cancel(sam_ldb);
1081 return NT_STATUS_NO_MEMORY;
1085 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1087 /* create the trusted_domain */
1088 ret = dsdb_add(sam_ldb, msg, DSDB_MODIFY_RELAX);
1089 switch (ret) {
1090 case LDB_SUCCESS:
1091 break;
1092 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1093 ldb_transaction_cancel(sam_ldb);
1094 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1095 ldb_dn_get_linearized(msg->dn),
1096 ldb_errstring(sam_ldb)));
1097 return NT_STATUS_DOMAIN_EXISTS;
1098 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1099 ldb_transaction_cancel(sam_ldb);
1100 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1101 ldb_dn_get_linearized(msg->dn),
1102 ldb_errstring(sam_ldb)));
1103 return NT_STATUS_ACCESS_DENIED;
1104 default:
1105 ldb_transaction_cancel(sam_ldb);
1106 DEBUG(0,("Failed to create user record %s: %s\n",
1107 ldb_dn_get_linearized(msg->dn),
1108 ldb_errstring(sam_ldb)));
1109 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1112 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1113 struct ldb_dn *user_dn;
1114 /* Inbound trusts must also create a cn=users object to match */
1115 nt_status = add_trust_user(mem_ctx, sam_ldb,
1116 policy_state->domain_dn,
1117 netbios_name,
1118 &auth_struct.incoming,
1119 &user_dn);
1120 if (!NT_STATUS_IS_OK(nt_status)) {
1121 ldb_transaction_cancel(sam_ldb);
1122 return nt_status;
1125 /* save the trust user dn */
1126 trusted_domain_state->trusted_domain_user_dn
1127 = talloc_steal(trusted_domain_state, user_dn);
1130 ret = ldb_transaction_commit(sam_ldb);
1131 if (ret != LDB_SUCCESS) {
1132 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1135 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1136 if (!handle) {
1137 return NT_STATUS_NO_MEMORY;
1140 handle->data = talloc_steal(handle, trusted_domain_state);
1142 trusted_domain_state->access_mask = r->in.access_mask;
1143 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1145 *r->out.trustdom_handle = handle->wire_handle;
1147 return NT_STATUS_OK;
1151 lsa_CreateTrustedDomainEx2
1153 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1154 TALLOC_CTX *mem_ctx,
1155 struct lsa_CreateTrustedDomainEx2 *r)
1157 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2);
1160 lsa_CreateTrustedDomainEx
1162 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1163 TALLOC_CTX *mem_ctx,
1164 struct lsa_CreateTrustedDomainEx *r)
1166 struct lsa_CreateTrustedDomainEx2 r2;
1168 r2.in.policy_handle = r->in.policy_handle;
1169 r2.in.info = r->in.info;
1170 r2.in.auth_info = r->in.auth_info;
1171 r2.out.trustdom_handle = r->out.trustdom_handle;
1172 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX);
1176 lsa_CreateTrustedDomain
1178 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1179 struct lsa_CreateTrustedDomain *r)
1181 struct lsa_CreateTrustedDomainEx2 r2;
1183 r2.in.policy_handle = r->in.policy_handle;
1184 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1185 if (!r2.in.info) {
1186 return NT_STATUS_NO_MEMORY;
1189 r2.in.info->domain_name.string = NULL;
1190 r2.in.info->netbios_name = r->in.info->name;
1191 r2.in.info->sid = r->in.info->sid;
1192 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1193 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1194 r2.in.info->trust_attributes = 0;
1196 r2.in.access_mask = r->in.access_mask;
1197 r2.out.trustdom_handle = r->out.trustdom_handle;
1199 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN);
1204 lsa_OpenTrustedDomain
1206 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1207 struct lsa_OpenTrustedDomain *r)
1209 struct dcesrv_handle *policy_handle;
1211 struct lsa_policy_state *policy_state;
1212 struct lsa_trusted_domain_state *trusted_domain_state;
1213 struct dcesrv_handle *handle;
1214 struct ldb_message **msgs;
1215 const char *attrs[] = {
1216 "trustDirection",
1217 "flatname",
1218 NULL
1221 const char *sid_string;
1222 int ret;
1224 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1225 ZERO_STRUCTP(r->out.trustdom_handle);
1226 policy_state = policy_handle->data;
1228 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1229 if (!trusted_domain_state) {
1230 return NT_STATUS_NO_MEMORY;
1232 trusted_domain_state->policy = policy_state;
1234 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1235 if (!sid_string) {
1236 return NT_STATUS_NO_MEMORY;
1239 /* search for the trusted_domain record */
1240 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1241 mem_ctx, policy_state->system_dn, &msgs, attrs,
1242 "(&(securityIdentifier=%s)(objectclass=trustedDomain))",
1243 sid_string);
1244 if (ret == 0) {
1245 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1248 if (ret != 1) {
1249 DEBUG(0,("Found %d records matching DN %s\n", ret,
1250 ldb_dn_get_linearized(policy_state->system_dn)));
1251 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1254 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1256 trusted_domain_state->trusted_domain_user_dn = NULL;
1258 if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1259 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1260 /* search for the trusted_domain record */
1261 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1262 mem_ctx, policy_state->domain_dn, &msgs, attrs,
1263 "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%d))",
1264 flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1265 if (ret == 1) {
1266 trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1269 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1270 if (!handle) {
1271 return NT_STATUS_NO_MEMORY;
1274 handle->data = talloc_steal(handle, trusted_domain_state);
1276 trusted_domain_state->access_mask = r->in.access_mask;
1277 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1279 *r->out.trustdom_handle = handle->wire_handle;
1281 return NT_STATUS_OK;
1286 lsa_OpenTrustedDomainByName
1288 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1289 TALLOC_CTX *mem_ctx,
1290 struct lsa_OpenTrustedDomainByName *r)
1292 struct dcesrv_handle *policy_handle;
1294 struct lsa_policy_state *policy_state;
1295 struct lsa_trusted_domain_state *trusted_domain_state;
1296 struct dcesrv_handle *handle;
1297 struct ldb_message **msgs;
1298 const char *attrs[] = {
1299 NULL
1301 char *td_name;
1302 int ret;
1304 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1305 ZERO_STRUCTP(r->out.trustdom_handle);
1306 policy_state = policy_handle->data;
1308 if (!r->in.name.string) {
1309 return NT_STATUS_INVALID_PARAMETER;
1312 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1313 if (!trusted_domain_state) {
1314 return NT_STATUS_NO_MEMORY;
1316 trusted_domain_state->policy = policy_state;
1318 /* search for the trusted_domain record */
1319 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1320 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1321 mem_ctx, policy_state->system_dn, &msgs, attrs,
1322 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1323 "(objectclass=trustedDomain))",
1324 td_name, td_name, td_name);
1325 if (ret == 0) {
1326 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1329 if (ret != 1) {
1330 DEBUG(0,("Found %d records matching DN %s\n", ret,
1331 ldb_dn_get_linearized(policy_state->system_dn)));
1332 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1335 /* TODO: perform access checks */
1337 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1339 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1340 if (!handle) {
1341 return NT_STATUS_NO_MEMORY;
1344 handle->data = talloc_steal(handle, trusted_domain_state);
1346 trusted_domain_state->access_mask = r->in.access_mask;
1347 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1349 *r->out.trustdom_handle = handle->wire_handle;
1351 return NT_STATUS_OK;
1357 lsa_SetTrustedDomainInfo
1359 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1360 struct lsa_SetTrustedDomainInfo *r)
1362 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1367 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1368 * otherwise at least one must be provided */
1369 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1370 struct ldb_dn *basedn, const char *dns_domain,
1371 const char *netbios, struct dom_sid2 *sid,
1372 struct ldb_message ***msgs)
1374 const char *attrs[] = { "flatname", "trustPartner",
1375 "securityIdentifier", "trustDirection",
1376 "trustType", "trustAttributes",
1377 "trustPosixOffset",
1378 "msDs-supportedEncryptionTypes", NULL };
1379 char *dns = NULL;
1380 char *nbn = NULL;
1381 char *sidstr = NULL;
1382 char *filter;
1383 int ret;
1386 if (dns_domain || netbios || sid) {
1387 filter = talloc_strdup(mem_ctx,
1388 "(&(objectclass=trustedDomain)(|");
1389 } else {
1390 filter = talloc_strdup(mem_ctx,
1391 "(objectclass=trustedDomain)");
1393 if (!filter) {
1394 return NT_STATUS_NO_MEMORY;
1397 if (dns_domain) {
1398 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1399 if (!dns) {
1400 return NT_STATUS_NO_MEMORY;
1402 filter = talloc_asprintf_append(filter,
1403 "(trustPartner=%s)", dns);
1404 if (!filter) {
1405 return NT_STATUS_NO_MEMORY;
1408 if (netbios) {
1409 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1410 if (!nbn) {
1411 return NT_STATUS_NO_MEMORY;
1413 filter = talloc_asprintf_append(filter,
1414 "(flatname=%s)", nbn);
1415 if (!filter) {
1416 return NT_STATUS_NO_MEMORY;
1419 if (sid) {
1420 sidstr = dom_sid_string(mem_ctx, sid);
1421 if (!sidstr) {
1422 return NT_STATUS_INVALID_PARAMETER;
1424 filter = talloc_asprintf_append(filter,
1425 "(securityIdentifier=%s)",
1426 sidstr);
1427 if (!filter) {
1428 return NT_STATUS_NO_MEMORY;
1431 if (dns_domain || netbios || sid) {
1432 filter = talloc_asprintf_append(filter, "))");
1433 if (!filter) {
1434 return NT_STATUS_NO_MEMORY;
1438 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1439 if (ret == 0) {
1440 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1443 if (ret != 1) {
1444 return NT_STATUS_OBJECT_NAME_COLLISION;
1447 return NT_STATUS_OK;
1450 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1451 struct ldb_message *orig,
1452 struct ldb_message *dest,
1453 const char *attribute,
1454 uint32_t value,
1455 uint32_t *orig_value)
1457 const struct ldb_val *orig_val;
1458 uint32_t orig_uint = 0;
1459 char *str_val;
1460 int flags = 0;
1461 int ret;
1463 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1464 if (!orig_val || !orig_val->data) {
1465 /* add new attribute */
1466 flags = LDB_FLAG_MOD_ADD;
1468 } else {
1469 errno = 0;
1470 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1471 if (errno != 0 || orig_uint != value) {
1472 /* replace also if can't get value */
1473 flags = LDB_FLAG_MOD_REPLACE;
1477 if (flags == 0) {
1478 /* stored value is identical, nothing to change */
1479 goto done;
1482 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1483 if (ret != LDB_SUCCESS) {
1484 return NT_STATUS_NO_MEMORY;
1487 str_val = talloc_asprintf(mem_ctx, "%u", value);
1488 if (!str_val) {
1489 return NT_STATUS_NO_MEMORY;
1491 ret = ldb_msg_add_steal_string(dest, attribute, str_val);
1492 if (ret != LDB_SUCCESS) {
1493 return NT_STATUS_NO_MEMORY;
1496 done:
1497 if (orig_value) {
1498 *orig_value = orig_uint;
1500 return NT_STATUS_OK;
1503 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1504 struct ldb_context *sam_ldb,
1505 struct ldb_dn *base_dn,
1506 bool delete_user,
1507 const char *netbios_name,
1508 struct trustCurrentPasswords *in)
1510 const char *attrs[] = { "userAccountControl", NULL };
1511 struct ldb_message **msgs;
1512 struct ldb_message *msg;
1513 uint32_t uac;
1514 uint32_t i;
1515 int ret;
1517 ret = gendb_search(sam_ldb, mem_ctx,
1518 base_dn, &msgs, attrs,
1519 "samAccountName=%s$", netbios_name);
1520 if (ret > 1) {
1521 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1524 if (ret == 0) {
1525 if (delete_user) {
1526 return NT_STATUS_OK;
1529 /* ok no existing user, add it from scratch */
1530 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1531 netbios_name, in, NULL);
1534 /* check user is what we are looking for */
1535 uac = ldb_msg_find_attr_as_uint(msgs[0],
1536 "userAccountControl", 0);
1537 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1538 return NT_STATUS_OBJECT_NAME_COLLISION;
1541 if (delete_user) {
1542 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1543 switch (ret) {
1544 case LDB_SUCCESS:
1545 return NT_STATUS_OK;
1546 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1547 return NT_STATUS_ACCESS_DENIED;
1548 default:
1549 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1553 /* entry exists, just modify secret if any */
1554 if (in->count == 0) {
1555 return NT_STATUS_OK;
1558 msg = ldb_msg_new(mem_ctx);
1559 if (!msg) {
1560 return NT_STATUS_NO_MEMORY;
1562 msg->dn = msgs[0]->dn;
1564 for (i = 0; i < in->count; i++) {
1565 const char *attribute;
1566 struct ldb_val v;
1567 switch (in->current[i]->AuthType) {
1568 case TRUST_AUTH_TYPE_NT4OWF:
1569 attribute = "unicodePwd";
1570 v.data = (uint8_t *)&in->current[i]->AuthInfo.nt4owf.password;
1571 v.length = 16;
1572 break;
1573 case TRUST_AUTH_TYPE_CLEAR:
1574 attribute = "clearTextPassword";
1575 v.data = in->current[i]->AuthInfo.clear.password;
1576 v.length = in->current[i]->AuthInfo.clear.size;
1577 break;
1578 default:
1579 continue;
1582 ret = ldb_msg_add_empty(msg, attribute,
1583 LDB_FLAG_MOD_REPLACE, NULL);
1584 if (ret != LDB_SUCCESS) {
1585 return NT_STATUS_NO_MEMORY;
1588 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1589 if (ret != LDB_SUCCESS) {
1590 return NT_STATUS_NO_MEMORY;
1594 /* create the trusted_domain user account */
1595 ret = ldb_modify(sam_ldb, msg);
1596 if (ret != LDB_SUCCESS) {
1597 DEBUG(0,("Failed to create user record %s: %s\n",
1598 ldb_dn_get_linearized(msg->dn),
1599 ldb_errstring(sam_ldb)));
1601 switch (ret) {
1602 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1603 return NT_STATUS_DOMAIN_EXISTS;
1604 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1605 return NT_STATUS_ACCESS_DENIED;
1606 default:
1607 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1611 return NT_STATUS_OK;
1615 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1616 struct dcesrv_handle *p_handle,
1617 TALLOC_CTX *mem_ctx,
1618 struct ldb_message *dom_msg,
1619 enum lsa_TrustDomInfoEnum level,
1620 union lsa_TrustedDomainInfo *info)
1622 struct lsa_policy_state *p_state = p_handle->data;
1623 uint32_t *posix_offset = NULL;
1624 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1625 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1626 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1627 uint32_t *enc_types = NULL;
1628 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1629 struct trustDomainPasswords auth_struct;
1630 NTSTATUS nt_status;
1631 struct ldb_message **msgs;
1632 struct ldb_message *msg;
1633 bool add_outgoing = false;
1634 bool add_incoming = false;
1635 bool del_outgoing = false;
1636 bool del_incoming = false;
1637 bool in_transaction = false;
1638 int ret;
1639 bool am_rodc;
1641 switch (level) {
1642 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1643 posix_offset = &info->posix_offset.posix_offset;
1644 break;
1645 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1646 info_ex = &info->info_ex;
1647 break;
1648 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1649 auth_info = &info->auth_info;
1650 break;
1651 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1652 posix_offset = &info->full_info.posix_offset.posix_offset;
1653 info_ex = &info->full_info.info_ex;
1654 auth_info = &info->full_info.auth_info;
1655 break;
1656 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1657 auth_info_int = &info->auth_info_internal;
1658 break;
1659 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1660 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1661 info_ex = &info->full_info_internal.info_ex;
1662 auth_info_int = &info->full_info_internal.auth_info;
1663 break;
1664 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1665 enc_types = &info->enc_types.enc_types;
1666 break;
1667 default:
1668 return NT_STATUS_INVALID_PARAMETER;
1671 if (auth_info) {
1672 /* FIXME: not handled yet */
1673 return NT_STATUS_INVALID_PARAMETER;
1676 /* decode auth_info_int if set */
1677 if (auth_info_int) {
1679 /* now decrypt blob */
1680 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1681 auth_info_int->auth_blob.size);
1683 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1684 &auth_blob, &auth_struct);
1685 if (!NT_STATUS_IS_OK(nt_status)) {
1686 return nt_status;
1690 if (info_ex) {
1691 /* verify data matches */
1692 if (info_ex->trust_attributes &
1693 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1694 /* TODO: check what behavior level we have */
1695 if (strcasecmp_m(p_state->domain_dns,
1696 p_state->forest_dns) != 0) {
1697 return NT_STATUS_INVALID_DOMAIN_STATE;
1701 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1702 if (ret == LDB_SUCCESS && am_rodc) {
1703 return NT_STATUS_NO_SUCH_DOMAIN;
1706 /* verify only one object matches the dns/netbios/sid
1707 * triplet and that this is the one we already have */
1708 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1709 p_state->system_dn,
1710 info_ex->domain_name.string,
1711 info_ex->netbios_name.string,
1712 info_ex->sid, &msgs);
1713 if (!NT_STATUS_IS_OK(nt_status)) {
1714 return nt_status;
1716 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1717 return NT_STATUS_OBJECT_NAME_COLLISION;
1719 talloc_free(msgs);
1722 /* TODO: should we fetch previous values from the existing entry
1723 * and append them ? */
1724 if (auth_struct.incoming.count) {
1725 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1726 &auth_struct.incoming,
1727 &trustAuthIncoming);
1728 if (!NT_STATUS_IS_OK(nt_status)) {
1729 return nt_status;
1731 } else {
1732 trustAuthIncoming = data_blob(NULL, 0);
1735 if (auth_struct.outgoing.count) {
1736 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1737 &auth_struct.outgoing,
1738 &trustAuthOutgoing);
1739 if (!NT_STATUS_IS_OK(nt_status)) {
1740 return nt_status;
1742 } else {
1743 trustAuthOutgoing = data_blob(NULL, 0);
1746 msg = ldb_msg_new(mem_ctx);
1747 if (msg == NULL) {
1748 return NT_STATUS_NO_MEMORY;
1750 msg->dn = dom_msg->dn;
1752 if (posix_offset) {
1753 nt_status = update_uint32_t_value(mem_ctx, dom_msg, msg,
1754 "trustPosixOffset",
1755 *posix_offset, NULL);
1756 if (!NT_STATUS_IS_OK(nt_status)) {
1757 return nt_status;
1761 if (info_ex) {
1762 uint32_t origattrs;
1763 uint32_t origdir;
1764 uint32_t tmp;
1765 int origtype;
1767 nt_status = update_uint32_t_value(mem_ctx, dom_msg, msg,
1768 "trustDirection",
1769 info_ex->trust_direction,
1770 &origdir);
1771 if (!NT_STATUS_IS_OK(nt_status)) {
1772 return nt_status;
1775 tmp = info_ex->trust_direction ^ origdir;
1776 if (tmp & LSA_TRUST_DIRECTION_INBOUND) {
1777 if (origdir & LSA_TRUST_DIRECTION_INBOUND) {
1778 del_incoming = true;
1779 } else {
1780 add_incoming = true;
1783 if (tmp & LSA_TRUST_DIRECTION_OUTBOUND) {
1784 if (origdir & LSA_TRUST_DIRECTION_OUTBOUND) {
1785 del_outgoing = true;
1786 } else {
1787 add_outgoing = true;
1791 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1792 if (origtype == -1 || origtype != info_ex->trust_type) {
1793 DEBUG(1, ("Attempted to change trust type! "
1794 "Operation not handled\n"));
1795 return NT_STATUS_INVALID_PARAMETER;
1798 nt_status = update_uint32_t_value(mem_ctx, dom_msg, msg,
1799 "trustAttributes",
1800 info_ex->trust_attributes,
1801 &origattrs);
1802 if (!NT_STATUS_IS_OK(nt_status)) {
1803 return nt_status;
1805 /* TODO: check forestFunctionality from ldb opaque */
1806 /* TODO: check what is set makes sense */
1807 /* for now refuse changes */
1808 if (origattrs == -1 ||
1809 origattrs != info_ex->trust_attributes) {
1810 DEBUG(1, ("Attempted to change trust attributes! "
1811 "Operation not handled\n"));
1812 return NT_STATUS_INVALID_PARAMETER;
1816 if (enc_types) {
1817 nt_status = update_uint32_t_value(mem_ctx, dom_msg, msg,
1818 "msDS-SupportedEncryptionTypes",
1819 *enc_types, NULL);
1820 if (!NT_STATUS_IS_OK(nt_status)) {
1821 return nt_status;
1825 if (add_incoming && trustAuthIncoming.data) {
1826 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1827 LDB_FLAG_MOD_REPLACE, NULL);
1828 if (ret != LDB_SUCCESS) {
1829 return NT_STATUS_NO_MEMORY;
1831 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1832 &trustAuthIncoming, NULL);
1833 if (ret != LDB_SUCCESS) {
1834 return NT_STATUS_NO_MEMORY;
1837 if (add_outgoing && trustAuthOutgoing.data) {
1838 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1839 LDB_FLAG_MOD_REPLACE, NULL);
1840 if (ret != LDB_SUCCESS) {
1841 return NT_STATUS_NO_MEMORY;
1843 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1844 &trustAuthOutgoing, NULL);
1845 if (ret != LDB_SUCCESS) {
1846 return NT_STATUS_NO_MEMORY;
1850 /* start transaction */
1851 ret = ldb_transaction_start(p_state->sam_ldb);
1852 if (ret != LDB_SUCCESS) {
1853 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1855 in_transaction = true;
1857 ret = ldb_modify(p_state->sam_ldb, msg);
1858 if (ret != LDB_SUCCESS) {
1859 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1860 ldb_dn_get_linearized(msg->dn),
1861 ldb_errstring(p_state->sam_ldb)));
1862 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
1863 nt_status = NT_STATUS_ACCESS_DENIED;
1864 } else {
1865 nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1867 goto done;
1870 if (add_incoming || del_incoming) {
1871 const char *netbios_name;
1873 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1874 "flatname", NULL);
1875 if (!netbios_name) {
1876 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1877 goto done;
1880 nt_status = update_trust_user(mem_ctx,
1881 p_state->sam_ldb,
1882 p_state->domain_dn,
1883 del_incoming,
1884 netbios_name,
1885 &auth_struct.incoming);
1886 if (!NT_STATUS_IS_OK(nt_status)) {
1887 goto done;
1891 /* ok, all fine, commit transaction and return */
1892 ret = ldb_transaction_commit(p_state->sam_ldb);
1893 if (ret != LDB_SUCCESS) {
1894 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1896 in_transaction = false;
1898 nt_status = NT_STATUS_OK;
1900 done:
1901 if (in_transaction) {
1902 ldb_transaction_cancel(p_state->sam_ldb);
1904 return nt_status;
1908 lsa_SetInfomrationTrustedDomain
1910 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1911 struct dcesrv_call_state *dce_call,
1912 TALLOC_CTX *mem_ctx,
1913 struct lsa_SetInformationTrustedDomain *r)
1915 struct dcesrv_handle *h;
1916 struct lsa_trusted_domain_state *td_state;
1917 struct ldb_message **msgs;
1918 NTSTATUS nt_status;
1920 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1921 LSA_HANDLE_TRUSTED_DOMAIN);
1923 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1925 /* get the trusted domain object */
1926 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1927 td_state->trusted_domain_dn,
1928 NULL, NULL, NULL, &msgs);
1929 if (!NT_STATUS_IS_OK(nt_status)) {
1930 if (NT_STATUS_EQUAL(nt_status,
1931 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1932 return nt_status;
1934 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1937 return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1938 msgs[0], r->in.level, r->in.info);
1943 lsa_DeleteTrustedDomain
1945 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1946 struct lsa_DeleteTrustedDomain *r)
1948 NTSTATUS status;
1949 struct lsa_OpenTrustedDomain opn;
1950 struct lsa_DeleteObject del;
1951 struct dcesrv_handle *h;
1953 opn.in.handle = r->in.handle;
1954 opn.in.sid = r->in.dom_sid;
1955 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1956 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1957 if (!opn.out.trustdom_handle) {
1958 return NT_STATUS_NO_MEMORY;
1960 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1961 if (!NT_STATUS_IS_OK(status)) {
1962 return status;
1965 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1966 talloc_steal(mem_ctx, h);
1968 del.in.handle = opn.out.trustdom_handle;
1969 del.out.handle = opn.out.trustdom_handle;
1970 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1971 if (!NT_STATUS_IS_OK(status)) {
1972 return status;
1974 return NT_STATUS_OK;
1977 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
1978 struct ldb_message *msg,
1979 struct lsa_TrustDomainInfoInfoEx *info_ex)
1981 info_ex->domain_name.string
1982 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1983 info_ex->netbios_name.string
1984 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1985 info_ex->sid
1986 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1987 info_ex->trust_direction
1988 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1989 info_ex->trust_type
1990 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1991 info_ex->trust_attributes
1992 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
1993 return NT_STATUS_OK;
1997 lsa_QueryTrustedDomainInfo
1999 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2000 struct lsa_QueryTrustedDomainInfo *r)
2002 union lsa_TrustedDomainInfo *info = NULL;
2003 struct dcesrv_handle *h;
2004 struct lsa_trusted_domain_state *trusted_domain_state;
2005 struct ldb_message *msg;
2006 int ret;
2007 struct ldb_message **res;
2008 const char *attrs[] = {
2009 "flatname",
2010 "trustPartner",
2011 "securityIdentifier",
2012 "trustDirection",
2013 "trustType",
2014 "trustAttributes",
2015 "msDs-supportedEncryptionTypes",
2016 NULL
2019 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2021 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2023 /* pull all the user attributes */
2024 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2025 trusted_domain_state->trusted_domain_dn, &res, attrs);
2026 if (ret != 1) {
2027 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2029 msg = res[0];
2031 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2032 if (!info) {
2033 return NT_STATUS_NO_MEMORY;
2035 *r->out.info = info;
2037 switch (r->in.level) {
2038 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2039 info->name.netbios_name.string
2040 = samdb_result_string(msg, "flatname", NULL);
2041 break;
2042 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2043 info->posix_offset.posix_offset
2044 = samdb_result_uint(msg, "posixOffset", 0);
2045 break;
2046 #if 0 /* Win2k3 doesn't implement this */
2047 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2048 r->out.info->info_basic.netbios_name.string
2049 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2050 r->out.info->info_basic.sid
2051 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2052 break;
2053 #endif
2054 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2055 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2057 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2058 ZERO_STRUCT(info->full_info);
2059 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2061 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2062 ZERO_STRUCT(info->full_info2_internal);
2063 info->full_info2_internal.posix_offset.posix_offset
2064 = samdb_result_uint(msg, "posixOffset", 0);
2065 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2067 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2068 info->enc_types.enc_types
2069 = samdb_result_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2070 break;
2072 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2073 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2074 /* oops, we don't want to return the info after all */
2075 talloc_free(info);
2076 *r->out.info = NULL;
2077 return NT_STATUS_INVALID_PARAMETER;
2078 default:
2079 /* oops, we don't want to return the info after all */
2080 talloc_free(info);
2081 *r->out.info = NULL;
2082 return NT_STATUS_INVALID_INFO_CLASS;
2085 return NT_STATUS_OK;
2090 lsa_QueryTrustedDomainInfoBySid
2092 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2093 struct lsa_QueryTrustedDomainInfoBySid *r)
2095 NTSTATUS status;
2096 struct lsa_OpenTrustedDomain opn;
2097 struct lsa_QueryTrustedDomainInfo query;
2098 struct dcesrv_handle *h;
2100 opn.in.handle = r->in.handle;
2101 opn.in.sid = r->in.dom_sid;
2102 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2103 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2104 if (!opn.out.trustdom_handle) {
2105 return NT_STATUS_NO_MEMORY;
2107 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2108 if (!NT_STATUS_IS_OK(status)) {
2109 return status;
2112 /* Ensure this handle goes away at the end of this call */
2113 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2114 talloc_steal(mem_ctx, h);
2116 query.in.trustdom_handle = opn.out.trustdom_handle;
2117 query.in.level = r->in.level;
2118 query.out.info = r->out.info;
2119 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2120 if (!NT_STATUS_IS_OK(status)) {
2121 return status;
2124 return NT_STATUS_OK;
2128 lsa_SetTrustedDomainInfoByName
2130 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2131 TALLOC_CTX *mem_ctx,
2132 struct lsa_SetTrustedDomainInfoByName *r)
2134 struct dcesrv_handle *policy_handle;
2135 struct lsa_policy_state *policy_state;
2136 struct ldb_message **msgs;
2137 NTSTATUS nt_status;
2139 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2140 policy_state = policy_handle->data;
2142 /* get the trusted domain object */
2143 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2144 policy_state->domain_dn,
2145 r->in.trusted_domain->string,
2146 r->in.trusted_domain->string,
2147 NULL, &msgs);
2148 if (!NT_STATUS_IS_OK(nt_status)) {
2149 if (NT_STATUS_EQUAL(nt_status,
2150 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2151 return nt_status;
2153 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2156 return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2157 msgs[0], r->in.level, r->in.info);
2161 lsa_QueryTrustedDomainInfoByName
2163 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2164 TALLOC_CTX *mem_ctx,
2165 struct lsa_QueryTrustedDomainInfoByName *r)
2167 NTSTATUS status;
2168 struct lsa_OpenTrustedDomainByName opn;
2169 struct lsa_QueryTrustedDomainInfo query;
2170 struct dcesrv_handle *h;
2172 opn.in.handle = r->in.handle;
2173 opn.in.name = *r->in.trusted_domain;
2174 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2175 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2176 if (!opn.out.trustdom_handle) {
2177 return NT_STATUS_NO_MEMORY;
2179 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2180 if (!NT_STATUS_IS_OK(status)) {
2181 return status;
2184 /* Ensure this handle goes away at the end of this call */
2185 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2186 talloc_steal(mem_ctx, h);
2188 query.in.trustdom_handle = opn.out.trustdom_handle;
2189 query.in.level = r->in.level;
2190 query.out.info = r->out.info;
2191 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2192 if (!NT_STATUS_IS_OK(status)) {
2193 return status;
2196 return NT_STATUS_OK;
2200 lsa_CloseTrustedDomainEx
2202 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2203 TALLOC_CTX *mem_ctx,
2204 struct lsa_CloseTrustedDomainEx *r)
2206 /* The result of a bad hair day from an IDL programmer? Not
2207 * implmented in Win2k3. You should always just lsa_Close
2208 * anyway. */
2209 return NT_STATUS_NOT_IMPLEMENTED;
2214 comparison function for sorting lsa_DomainInformation array
2216 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2218 return strcasecmp_m(e1->name.string, e2->name.string);
2222 lsa_EnumTrustDom
2224 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2225 struct lsa_EnumTrustDom *r)
2227 struct dcesrv_handle *policy_handle;
2228 struct lsa_DomainInfo *entries;
2229 struct lsa_policy_state *policy_state;
2230 struct ldb_message **domains;
2231 const char *attrs[] = {
2232 "flatname",
2233 "securityIdentifier",
2234 NULL
2238 int count, i;
2240 *r->out.resume_handle = 0;
2242 r->out.domains->domains = NULL;
2243 r->out.domains->count = 0;
2245 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2247 policy_state = policy_handle->data;
2249 /* search for all users in this domain. This could possibly be cached and
2250 resumed based on resume_key */
2251 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2252 "objectclass=trustedDomain");
2253 if (count < 0) {
2254 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2257 /* convert to lsa_TrustInformation format */
2258 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2259 if (!entries) {
2260 return NT_STATUS_NO_MEMORY;
2262 for (i=0;i<count;i++) {
2263 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2264 entries[i].name.string = samdb_result_string(domains[i], "flatname", NULL);
2267 /* sort the results by name */
2268 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2270 if (*r->in.resume_handle >= count) {
2271 *r->out.resume_handle = -1;
2273 return NT_STATUS_NO_MORE_ENTRIES;
2276 /* return the rest, limit by max_size. Note that we
2277 use the w2k3 element size value of 60 */
2278 r->out.domains->count = count - *r->in.resume_handle;
2279 r->out.domains->count = MIN(r->out.domains->count,
2280 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2282 r->out.domains->domains = entries + *r->in.resume_handle;
2283 r->out.domains->count = r->out.domains->count;
2285 if (r->out.domains->count < count - *r->in.resume_handle) {
2286 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2287 return STATUS_MORE_ENTRIES;
2290 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2291 * always be larger than the previous input resume handle, in
2292 * particular when hitting the last query it is vital to set the
2293 * resume handle correctly to avoid infinite client loops, as
2294 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2295 * status is NT_STATUS_OK - gd */
2297 *r->out.resume_handle = (uint32_t)-1;
2299 return NT_STATUS_OK;
2303 comparison function for sorting lsa_DomainInformation array
2305 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2307 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2311 lsa_EnumTrustedDomainsEx
2313 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2314 struct lsa_EnumTrustedDomainsEx *r)
2316 struct dcesrv_handle *policy_handle;
2317 struct lsa_TrustDomainInfoInfoEx *entries;
2318 struct lsa_policy_state *policy_state;
2319 struct ldb_message **domains;
2320 const char *attrs[] = {
2321 "flatname",
2322 "trustPartner",
2323 "securityIdentifier",
2324 "trustDirection",
2325 "trustType",
2326 "trustAttributes",
2327 NULL
2329 NTSTATUS nt_status;
2331 int count, i;
2333 *r->out.resume_handle = 0;
2335 r->out.domains->domains = NULL;
2336 r->out.domains->count = 0;
2338 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2340 policy_state = policy_handle->data;
2342 /* search for all users in this domain. This could possibly be cached and
2343 resumed based on resume_key */
2344 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2345 "objectclass=trustedDomain");
2346 if (count < 0) {
2347 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2350 /* convert to lsa_DomainInformation format */
2351 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2352 if (!entries) {
2353 return NT_STATUS_NO_MEMORY;
2355 for (i=0;i<count;i++) {
2356 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2357 if (!NT_STATUS_IS_OK(nt_status)) {
2358 return nt_status;
2362 /* sort the results by name */
2363 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2365 if (*r->in.resume_handle >= count) {
2366 *r->out.resume_handle = -1;
2368 return NT_STATUS_NO_MORE_ENTRIES;
2371 /* return the rest, limit by max_size. Note that we
2372 use the w2k3 element size value of 60 */
2373 r->out.domains->count = count - *r->in.resume_handle;
2374 r->out.domains->count = MIN(r->out.domains->count,
2375 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2377 r->out.domains->domains = entries + *r->in.resume_handle;
2378 r->out.domains->count = r->out.domains->count;
2380 if (r->out.domains->count < count - *r->in.resume_handle) {
2381 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2382 return STATUS_MORE_ENTRIES;
2385 return NT_STATUS_OK;
2390 lsa_OpenAccount
2392 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2393 struct lsa_OpenAccount *r)
2395 struct dcesrv_handle *h, *ah;
2396 struct lsa_policy_state *state;
2397 struct lsa_account_state *astate;
2399 ZERO_STRUCTP(r->out.acct_handle);
2401 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2403 state = h->data;
2405 astate = talloc(dce_call->conn, struct lsa_account_state);
2406 if (astate == NULL) {
2407 return NT_STATUS_NO_MEMORY;
2410 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2411 if (astate->account_sid == NULL) {
2412 talloc_free(astate);
2413 return NT_STATUS_NO_MEMORY;
2416 astate->policy = talloc_reference(astate, state);
2417 astate->access_mask = r->in.access_mask;
2419 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2420 if (!ah) {
2421 talloc_free(astate);
2422 return NT_STATUS_NO_MEMORY;
2425 ah->data = talloc_steal(ah, astate);
2427 *r->out.acct_handle = ah->wire_handle;
2429 return NT_STATUS_OK;
2434 lsa_EnumPrivsAccount
2436 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2437 TALLOC_CTX *mem_ctx,
2438 struct lsa_EnumPrivsAccount *r)
2440 struct dcesrv_handle *h;
2441 struct lsa_account_state *astate;
2442 int ret;
2443 unsigned int i;
2444 struct ldb_message **res;
2445 const char * const attrs[] = { "privilege", NULL};
2446 struct ldb_message_element *el;
2447 const char *sidstr;
2448 struct lsa_PrivilegeSet *privs;
2450 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2452 astate = h->data;
2454 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2455 if (privs == NULL) {
2456 return NT_STATUS_NO_MEMORY;
2458 privs->count = 0;
2459 privs->unknown = 0;
2460 privs->set = NULL;
2462 *r->out.privs = privs;
2464 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2465 if (sidstr == NULL) {
2466 return NT_STATUS_NO_MEMORY;
2469 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2470 "objectSid=%s", sidstr);
2471 if (ret < 0) {
2472 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2474 if (ret != 1) {
2475 return NT_STATUS_OK;
2478 el = ldb_msg_find_element(res[0], "privilege");
2479 if (el == NULL || el->num_values == 0) {
2480 return NT_STATUS_OK;
2483 privs->set = talloc_array(privs,
2484 struct lsa_LUIDAttribute, el->num_values);
2485 if (privs->set == NULL) {
2486 return NT_STATUS_NO_MEMORY;
2489 for (i=0;i<el->num_values;i++) {
2490 int id = sec_privilege_id((const char *)el->values[i].data);
2491 if (id == -1) {
2492 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2494 privs->set[i].attribute = 0;
2495 privs->set[i].luid.low = id;
2496 privs->set[i].luid.high = 0;
2499 privs->count = el->num_values;
2501 return NT_STATUS_OK;
2505 lsa_EnumAccountRights
2507 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2508 TALLOC_CTX *mem_ctx,
2509 struct lsa_EnumAccountRights *r)
2511 struct dcesrv_handle *h;
2512 struct lsa_policy_state *state;
2513 int ret;
2514 unsigned int i;
2515 struct ldb_message **res;
2516 const char * const attrs[] = { "privilege", NULL};
2517 const char *sidstr;
2518 struct ldb_message_element *el;
2520 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2522 state = h->data;
2524 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2525 if (sidstr == NULL) {
2526 return NT_STATUS_NO_MEMORY;
2529 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2530 "(&(objectSid=%s)(privilege=*))", sidstr);
2531 if (ret == 0) {
2532 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2534 if (ret != 1) {
2535 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2536 dom_sid_string(mem_ctx, r->in.sid),
2537 ldb_errstring(state->pdb)));
2538 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2541 el = ldb_msg_find_element(res[0], "privilege");
2542 if (el == NULL || el->num_values == 0) {
2543 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2546 r->out.rights->count = el->num_values;
2547 r->out.rights->names = talloc_array(r->out.rights,
2548 struct lsa_StringLarge, r->out.rights->count);
2549 if (r->out.rights->names == NULL) {
2550 return NT_STATUS_NO_MEMORY;
2553 for (i=0;i<el->num_values;i++) {
2554 r->out.rights->names[i].string = (const char *)el->values[i].data;
2557 return NT_STATUS_OK;
2563 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2565 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2566 TALLOC_CTX *mem_ctx,
2567 struct lsa_policy_state *state,
2568 int ldb_flag,
2569 struct dom_sid *sid,
2570 const struct lsa_RightSet *rights)
2572 const char *sidstr, *sidndrstr;
2573 struct ldb_message *msg;
2574 struct ldb_message_element *el;
2575 int ret;
2576 uint32_t i;
2577 struct lsa_EnumAccountRights r2;
2578 char *dnstr;
2580 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2581 SECURITY_ADMINISTRATOR) {
2582 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2583 return NT_STATUS_ACCESS_DENIED;
2586 msg = ldb_msg_new(mem_ctx);
2587 if (msg == NULL) {
2588 return NT_STATUS_NO_MEMORY;
2591 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2592 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
2594 sidstr = dom_sid_string(msg, sid);
2595 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
2597 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2598 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
2600 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2601 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
2603 if (ldb_flag == LDB_FLAG_MOD_ADD) {
2604 NTSTATUS status;
2606 r2.in.handle = &state->handle->wire_handle;
2607 r2.in.sid = sid;
2608 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2610 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2611 if (!NT_STATUS_IS_OK(status)) {
2612 ZERO_STRUCTP(r2.out.rights);
2616 for (i=0;i<rights->count;i++) {
2617 if (sec_privilege_id(rights->names[i].string) == -1) {
2618 talloc_free(msg);
2619 return NT_STATUS_NO_SUCH_PRIVILEGE;
2622 if (ldb_flag == LDB_FLAG_MOD_ADD) {
2623 uint32_t j;
2624 for (j=0;j<r2.out.rights->count;j++) {
2625 if (strcasecmp_m(r2.out.rights->names[j].string,
2626 rights->names[i].string) == 0) {
2627 break;
2630 if (j != r2.out.rights->count) continue;
2633 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2634 if (ret != LDB_SUCCESS) {
2635 talloc_free(msg);
2636 return NT_STATUS_NO_MEMORY;
2640 el = ldb_msg_find_element(msg, "privilege");
2641 if (!el) {
2642 talloc_free(msg);
2643 return NT_STATUS_OK;
2646 el->flags = ldb_flag;
2648 ret = ldb_modify(state->pdb, msg);
2649 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2650 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2651 talloc_free(msg);
2652 return NT_STATUS_NO_MEMORY;
2654 samdb_msg_add_string(state->pdb, msg, msg, "comment", "added via LSA");
2655 ret = ldb_add(state->pdb, msg);
2657 if (ret != LDB_SUCCESS) {
2658 if (ldb_flag == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2659 talloc_free(msg);
2660 return NT_STATUS_OK;
2662 DEBUG(3, ("Could not %s attributes from %s: %s",
2663 ldb_flag == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2664 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2665 talloc_free(msg);
2666 return NT_STATUS_UNEXPECTED_IO_ERROR;
2669 talloc_free(msg);
2670 return NT_STATUS_OK;
2674 lsa_AddPrivilegesToAccount
2676 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2677 struct lsa_AddPrivilegesToAccount *r)
2679 struct lsa_RightSet rights;
2680 struct dcesrv_handle *h;
2681 struct lsa_account_state *astate;
2682 uint32_t i;
2684 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2686 astate = h->data;
2688 rights.count = r->in.privs->count;
2689 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2690 if (rights.names == NULL) {
2691 return NT_STATUS_NO_MEMORY;
2693 for (i=0;i<rights.count;i++) {
2694 int id = r->in.privs->set[i].luid.low;
2695 if (r->in.privs->set[i].luid.high) {
2696 return NT_STATUS_NO_SUCH_PRIVILEGE;
2698 rights.names[i].string = sec_privilege_name(id);
2699 if (rights.names[i].string == NULL) {
2700 return NT_STATUS_NO_SUCH_PRIVILEGE;
2704 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2705 LDB_FLAG_MOD_ADD, astate->account_sid,
2706 &rights);
2711 lsa_RemovePrivilegesFromAccount
2713 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2714 struct lsa_RemovePrivilegesFromAccount *r)
2716 struct lsa_RightSet *rights;
2717 struct dcesrv_handle *h;
2718 struct lsa_account_state *astate;
2719 uint32_t i;
2721 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2723 astate = h->data;
2725 rights = talloc(mem_ctx, struct lsa_RightSet);
2727 if (r->in.remove_all == 1 &&
2728 r->in.privs == NULL) {
2729 struct lsa_EnumAccountRights r2;
2730 NTSTATUS status;
2732 r2.in.handle = &astate->policy->handle->wire_handle;
2733 r2.in.sid = astate->account_sid;
2734 r2.out.rights = rights;
2736 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2737 if (!NT_STATUS_IS_OK(status)) {
2738 return status;
2741 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2742 LDB_FLAG_MOD_DELETE, astate->account_sid,
2743 r2.out.rights);
2746 if (r->in.remove_all != 0) {
2747 return NT_STATUS_INVALID_PARAMETER;
2750 rights->count = r->in.privs->count;
2751 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2752 if (rights->names == NULL) {
2753 return NT_STATUS_NO_MEMORY;
2755 for (i=0;i<rights->count;i++) {
2756 int id = r->in.privs->set[i].luid.low;
2757 if (r->in.privs->set[i].luid.high) {
2758 return NT_STATUS_NO_SUCH_PRIVILEGE;
2760 rights->names[i].string = sec_privilege_name(id);
2761 if (rights->names[i].string == NULL) {
2762 return NT_STATUS_NO_SUCH_PRIVILEGE;
2766 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2767 LDB_FLAG_MOD_DELETE, astate->account_sid,
2768 rights);
2773 lsa_GetQuotasForAccount
2775 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2776 struct lsa_GetQuotasForAccount *r)
2778 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2783 lsa_SetQuotasForAccount
2785 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2786 struct lsa_SetQuotasForAccount *r)
2788 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2793 lsa_GetSystemAccessAccount
2795 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2796 struct lsa_GetSystemAccessAccount *r)
2798 uint32_t i;
2799 NTSTATUS status;
2800 struct lsa_EnumPrivsAccount enumPrivs;
2801 struct lsa_PrivilegeSet *privs;
2803 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2804 if (!privs) {
2805 return NT_STATUS_NO_MEMORY;
2807 privs->count = 0;
2808 privs->unknown = 0;
2809 privs->set = NULL;
2811 enumPrivs.in.handle = r->in.handle;
2812 enumPrivs.out.privs = &privs;
2814 status = dcesrv_lsa_EnumPrivsAccount(dce_call, mem_ctx, &enumPrivs);
2815 if (!NT_STATUS_IS_OK(status)) {
2816 return status;
2819 *(r->out.access_mask) = 0x00000000;
2821 for (i = 0; i < privs->count; i++) {
2822 int priv = privs->set[i].luid.low;
2824 switch (priv) {
2825 case SEC_PRIV_INTERACTIVE_LOGON:
2826 *(r->out.access_mask) |= LSA_POLICY_MODE_INTERACTIVE;
2827 break;
2828 case SEC_PRIV_NETWORK_LOGON:
2829 *(r->out.access_mask) |= LSA_POLICY_MODE_NETWORK;
2830 break;
2831 case SEC_PRIV_REMOTE_INTERACTIVE_LOGON:
2832 *(r->out.access_mask) |= LSA_POLICY_MODE_REMOTE_INTERACTIVE;
2833 break;
2837 return NT_STATUS_OK;
2842 lsa_SetSystemAccessAccount
2844 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2845 struct lsa_SetSystemAccessAccount *r)
2847 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2852 lsa_CreateSecret
2854 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2855 struct lsa_CreateSecret *r)
2857 struct dcesrv_handle *policy_handle;
2858 struct lsa_policy_state *policy_state;
2859 struct lsa_secret_state *secret_state;
2860 struct dcesrv_handle *handle;
2861 struct ldb_message **msgs, *msg;
2862 const char *attrs[] = {
2863 NULL
2866 const char *name;
2868 int ret;
2870 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2871 ZERO_STRUCTP(r->out.sec_handle);
2873 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2875 case SECURITY_SYSTEM:
2876 case SECURITY_ADMINISTRATOR:
2877 break;
2878 default:
2879 /* Users and annonymous are not allowed create secrets */
2880 return NT_STATUS_ACCESS_DENIED;
2883 policy_state = policy_handle->data;
2885 if (!r->in.name.string) {
2886 return NT_STATUS_INVALID_PARAMETER;
2889 secret_state = talloc(mem_ctx, struct lsa_secret_state);
2890 if (!secret_state) {
2891 return NT_STATUS_NO_MEMORY;
2893 secret_state->policy = policy_state;
2895 msg = ldb_msg_new(mem_ctx);
2896 if (msg == NULL) {
2897 return NT_STATUS_NO_MEMORY;
2900 if (strncmp("G$", r->in.name.string, 2) == 0) {
2901 const char *name2;
2902 name = &r->in.name.string[2];
2903 /* 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) */
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)));
2906 secret_state->global = true;
2908 if (strlen(name) < 1) {
2909 return NT_STATUS_INVALID_PARAMETER;
2912 name2 = talloc_asprintf(mem_ctx, "%s Secret", ldb_binary_encode_string(mem_ctx, name));
2913 /* search for the secret record */
2914 ret = gendb_search(secret_state->sam_ldb,
2915 mem_ctx, policy_state->system_dn, &msgs, attrs,
2916 "(&(cn=%s)(objectclass=secret))",
2917 name2);
2918 if (ret > 0) {
2919 return NT_STATUS_OBJECT_NAME_COLLISION;
2922 if (ret < 0) {
2923 DEBUG(0,("Failure searching for CN=%s: %s\n",
2924 name2, ldb_errstring(secret_state->sam_ldb)));
2925 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2928 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2929 if (!name2 || ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2930 return NT_STATUS_NO_MEMORY;
2933 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name2);
2935 } else {
2936 secret_state->global = false;
2938 name = r->in.name.string;
2939 if (strlen(name) < 1) {
2940 return NT_STATUS_INVALID_PARAMETER;
2943 secret_state->sam_ldb = talloc_reference(secret_state,
2944 secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
2945 /* search for the secret record */
2946 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2947 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2948 &msgs, attrs,
2949 "(&(cn=%s)(objectclass=secret))",
2950 ldb_binary_encode_string(mem_ctx, name));
2951 if (ret > 0) {
2952 return NT_STATUS_OBJECT_NAME_COLLISION;
2955 if (ret < 0) {
2956 DEBUG(0,("Failure searching for CN=%s: %s\n",
2957 name, ldb_errstring(secret_state->sam_ldb)));
2958 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2961 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb, "cn=%s,cn=LSA Secrets", name);
2962 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name);
2965 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "objectClass", "secret");
2967 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2969 /* create the secret */
2970 ret = dsdb_add(secret_state->sam_ldb, msg, DSDB_MODIFY_RELAX);
2971 if (ret != LDB_SUCCESS) {
2972 DEBUG(0,("Failed to create secret record %s: %s\n",
2973 ldb_dn_get_linearized(msg->dn),
2974 ldb_errstring(secret_state->sam_ldb)));
2975 return NT_STATUS_ACCESS_DENIED;
2978 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2979 if (!handle) {
2980 return NT_STATUS_NO_MEMORY;
2983 handle->data = talloc_steal(handle, secret_state);
2985 secret_state->access_mask = r->in.access_mask;
2986 secret_state->policy = talloc_reference(secret_state, policy_state);
2988 *r->out.sec_handle = handle->wire_handle;
2990 return NT_STATUS_OK;
2995 lsa_OpenSecret
2997 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2998 struct lsa_OpenSecret *r)
3000 struct dcesrv_handle *policy_handle;
3002 struct lsa_policy_state *policy_state;
3003 struct lsa_secret_state *secret_state;
3004 struct dcesrv_handle *handle;
3005 struct ldb_message **msgs;
3006 const char *attrs[] = {
3007 NULL
3010 const char *name;
3012 int ret;
3014 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3015 ZERO_STRUCTP(r->out.sec_handle);
3016 policy_state = policy_handle->data;
3018 if (!r->in.name.string) {
3019 return NT_STATUS_INVALID_PARAMETER;
3022 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3024 case SECURITY_SYSTEM:
3025 case SECURITY_ADMINISTRATOR:
3026 break;
3027 default:
3028 /* Users and annonymous are not allowed to access secrets */
3029 return NT_STATUS_ACCESS_DENIED;
3032 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3033 if (!secret_state) {
3034 return NT_STATUS_NO_MEMORY;
3036 secret_state->policy = policy_state;
3038 if (strncmp("G$", r->in.name.string, 2) == 0) {
3039 name = &r->in.name.string[2];
3040 /* 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) */
3041 secret_state->sam_ldb = talloc_reference(secret_state,
3042 samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx)));
3043 secret_state->global = true;
3045 if (strlen(name) < 1) {
3046 return NT_STATUS_INVALID_PARAMETER;
3049 /* search for the secret record */
3050 ret = gendb_search(secret_state->sam_ldb,
3051 mem_ctx, policy_state->system_dn, &msgs, attrs,
3052 "(&(cn=%s Secret)(objectclass=secret))",
3053 ldb_binary_encode_string(mem_ctx, name));
3054 if (ret == 0) {
3055 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3058 if (ret != 1) {
3059 DEBUG(0,("Found %d records matching DN %s\n", ret,
3060 ldb_dn_get_linearized(policy_state->system_dn)));
3061 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3064 } else {
3065 secret_state->global = false;
3066 secret_state->sam_ldb = talloc_reference(secret_state,
3067 secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
3069 name = r->in.name.string;
3070 if (strlen(name) < 1) {
3071 return NT_STATUS_INVALID_PARAMETER;
3074 /* search for the secret record */
3075 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3076 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3077 &msgs, attrs,
3078 "(&(cn=%s)(objectclass=secret))",
3079 ldb_binary_encode_string(mem_ctx, name));
3080 if (ret == 0) {
3081 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3084 if (ret != 1) {
3085 DEBUG(0,("Found %d records matching CN=%s\n",
3086 ret, ldb_binary_encode_string(mem_ctx, name)));
3087 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3091 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3093 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3094 if (!handle) {
3095 return NT_STATUS_NO_MEMORY;
3098 handle->data = talloc_steal(handle, secret_state);
3100 secret_state->access_mask = r->in.access_mask;
3101 secret_state->policy = talloc_reference(secret_state, policy_state);
3103 *r->out.sec_handle = handle->wire_handle;
3105 return NT_STATUS_OK;
3110 lsa_SetSecret
3112 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3113 struct lsa_SetSecret *r)
3116 struct dcesrv_handle *h;
3117 struct lsa_secret_state *secret_state;
3118 struct ldb_message *msg;
3119 DATA_BLOB session_key;
3120 DATA_BLOB crypt_secret, secret;
3121 struct ldb_val val;
3122 int ret;
3123 NTSTATUS status = NT_STATUS_OK;
3125 struct timeval now = timeval_current();
3126 NTTIME nt_now = timeval_to_nttime(&now);
3128 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3130 secret_state = h->data;
3132 msg = ldb_msg_new(mem_ctx);
3133 if (msg == NULL) {
3134 return NT_STATUS_NO_MEMORY;
3137 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3138 if (!msg->dn) {
3139 return NT_STATUS_NO_MEMORY;
3141 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3142 if (!NT_STATUS_IS_OK(status)) {
3143 return status;
3146 if (r->in.old_val) {
3147 /* Decrypt */
3148 crypt_secret.data = r->in.old_val->data;
3149 crypt_secret.length = r->in.old_val->size;
3151 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3152 if (!NT_STATUS_IS_OK(status)) {
3153 return status;
3156 val.data = secret.data;
3157 val.length = secret.length;
3159 /* set value */
3160 if (samdb_msg_add_value(secret_state->sam_ldb,
3161 mem_ctx, msg, "priorValue", &val) != LDB_SUCCESS) {
3162 return NT_STATUS_NO_MEMORY;
3165 /* set old value mtime */
3166 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3167 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3168 return NT_STATUS_NO_MEMORY;
3171 } else {
3172 /* If the old value is not set, then migrate the
3173 * current value to the old value */
3174 const struct ldb_val *old_val;
3175 NTTIME last_set_time;
3176 struct ldb_message **res;
3177 const char *attrs[] = {
3178 "currentValue",
3179 "lastSetTime",
3180 NULL
3183 /* search for the secret record */
3184 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3185 secret_state->secret_dn, &res, attrs);
3186 if (ret == 0) {
3187 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3190 if (ret != 1) {
3191 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3192 ldb_dn_get_linearized(secret_state->secret_dn)));
3193 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3196 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3197 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3199 if (old_val) {
3200 /* set old value */
3201 if (samdb_msg_add_value(secret_state->sam_ldb,
3202 mem_ctx, msg, "priorValue",
3203 old_val) != 0) {
3204 return NT_STATUS_NO_MEMORY;
3206 } else {
3207 if (samdb_msg_add_delete(secret_state->sam_ldb,
3208 mem_ctx, msg, "priorValue")) {
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 (samdb_msg_add_value(secret_state->sam_ldb,
3243 mem_ctx, msg, "currentValue", &val) != LDB_SUCCESS) {
3244 return NT_STATUS_NO_MEMORY;
3247 /* set new value mtime */
3248 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3249 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3250 return NT_STATUS_NO_MEMORY;
3253 } else {
3254 /* NULL out the NEW value */
3255 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3256 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3257 return NT_STATUS_NO_MEMORY;
3259 if (samdb_msg_add_delete(secret_state->sam_ldb,
3260 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3261 return NT_STATUS_NO_MEMORY;
3265 /* modify the samdb record */
3266 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3267 if (ret != LDB_SUCCESS) {
3268 /* we really need samdb.c to return NTSTATUS */
3269 return NT_STATUS_UNSUCCESSFUL;
3272 return NT_STATUS_OK;
3277 lsa_QuerySecret
3279 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3280 struct lsa_QuerySecret *r)
3282 struct dcesrv_handle *h;
3283 struct lsa_secret_state *secret_state;
3284 struct ldb_message *msg;
3285 DATA_BLOB session_key;
3286 DATA_BLOB crypt_secret, secret;
3287 int ret;
3288 struct ldb_message **res;
3289 const char *attrs[] = {
3290 "currentValue",
3291 "priorValue",
3292 "lastSetTime",
3293 "priorSetTime",
3294 NULL
3297 NTSTATUS nt_status;
3299 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3301 /* Ensure user is permitted to read this... */
3302 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3304 case SECURITY_SYSTEM:
3305 case SECURITY_ADMINISTRATOR:
3306 break;
3307 default:
3308 /* Users and annonymous are not allowed to read secrets */
3309 return NT_STATUS_ACCESS_DENIED;
3312 secret_state = h->data;
3314 /* pull all the user attributes */
3315 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3316 secret_state->secret_dn, &res, attrs);
3317 if (ret != 1) {
3318 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3320 msg = res[0];
3322 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3323 if (!NT_STATUS_IS_OK(nt_status)) {
3324 return nt_status;
3327 if (r->in.old_val) {
3328 const struct ldb_val *prior_val;
3329 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3330 if (!r->out.old_val) {
3331 return NT_STATUS_NO_MEMORY;
3333 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
3335 if (prior_val && prior_val->length) {
3336 secret.data = prior_val->data;
3337 secret.length = prior_val->length;
3339 /* Encrypt */
3340 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3341 if (!crypt_secret.length) {
3342 return NT_STATUS_NO_MEMORY;
3344 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3345 if (!r->out.old_val->buf) {
3346 return NT_STATUS_NO_MEMORY;
3348 r->out.old_val->buf->size = crypt_secret.length;
3349 r->out.old_val->buf->length = crypt_secret.length;
3350 r->out.old_val->buf->data = crypt_secret.data;
3354 if (r->in.old_mtime) {
3355 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3356 if (!r->out.old_mtime) {
3357 return NT_STATUS_NO_MEMORY;
3359 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
3362 if (r->in.new_val) {
3363 const struct ldb_val *new_val;
3364 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3365 if (!r->out.new_val) {
3366 return NT_STATUS_NO_MEMORY;
3369 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3371 if (new_val && new_val->length) {
3372 secret.data = new_val->data;
3373 secret.length = new_val->length;
3375 /* Encrypt */
3376 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3377 if (!crypt_secret.length) {
3378 return NT_STATUS_NO_MEMORY;
3380 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3381 if (!r->out.new_val->buf) {
3382 return NT_STATUS_NO_MEMORY;
3384 r->out.new_val->buf->length = crypt_secret.length;
3385 r->out.new_val->buf->size = crypt_secret.length;
3386 r->out.new_val->buf->data = crypt_secret.data;
3390 if (r->in.new_mtime) {
3391 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3392 if (!r->out.new_mtime) {
3393 return NT_STATUS_NO_MEMORY;
3395 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3398 return NT_STATUS_OK;
3403 lsa_LookupPrivValue
3405 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3406 TALLOC_CTX *mem_ctx,
3407 struct lsa_LookupPrivValue *r)
3409 struct dcesrv_handle *h;
3410 struct lsa_policy_state *state;
3411 int id;
3413 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3415 state = h->data;
3417 id = sec_privilege_id(r->in.name->string);
3418 if (id == -1) {
3419 return NT_STATUS_NO_SUCH_PRIVILEGE;
3422 r->out.luid->low = id;
3423 r->out.luid->high = 0;
3425 return NT_STATUS_OK;
3430 lsa_LookupPrivName
3432 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3433 TALLOC_CTX *mem_ctx,
3434 struct lsa_LookupPrivName *r)
3436 struct dcesrv_handle *h;
3437 struct lsa_policy_state *state;
3438 struct lsa_StringLarge *name;
3439 const char *privname;
3441 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3443 state = h->data;
3445 if (r->in.luid->high != 0) {
3446 return NT_STATUS_NO_SUCH_PRIVILEGE;
3449 privname = sec_privilege_name(r->in.luid->low);
3450 if (privname == NULL) {
3451 return NT_STATUS_NO_SUCH_PRIVILEGE;
3454 name = talloc(mem_ctx, struct lsa_StringLarge);
3455 if (name == NULL) {
3456 return NT_STATUS_NO_MEMORY;
3459 name->string = privname;
3461 *r->out.name = name;
3463 return NT_STATUS_OK;
3468 lsa_LookupPrivDisplayName
3470 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3471 TALLOC_CTX *mem_ctx,
3472 struct lsa_LookupPrivDisplayName *r)
3474 struct dcesrv_handle *h;
3475 struct lsa_policy_state *state;
3476 struct lsa_StringLarge *disp_name = NULL;
3477 int id;
3479 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3481 state = h->data;
3483 id = sec_privilege_id(r->in.name->string);
3484 if (id == -1) {
3485 return NT_STATUS_NO_SUCH_PRIVILEGE;
3488 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3489 if (disp_name == NULL) {
3490 return NT_STATUS_NO_MEMORY;
3493 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3494 if (disp_name->string == NULL) {
3495 return NT_STATUS_INTERNAL_ERROR;
3498 *r->out.disp_name = disp_name;
3499 *r->out.returned_language_id = 0;
3501 return NT_STATUS_OK;
3506 lsa_EnumAccountsWithUserRight
3508 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3509 TALLOC_CTX *mem_ctx,
3510 struct lsa_EnumAccountsWithUserRight *r)
3512 struct dcesrv_handle *h;
3513 struct lsa_policy_state *state;
3514 int ret, i;
3515 struct ldb_message **res;
3516 const char * const attrs[] = { "objectSid", NULL};
3517 const char *privname;
3519 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3521 state = h->data;
3523 if (r->in.name == NULL) {
3524 return NT_STATUS_NO_SUCH_PRIVILEGE;
3527 privname = r->in.name->string;
3528 if (sec_privilege_id(privname) == -1) {
3529 return NT_STATUS_NO_SUCH_PRIVILEGE;
3532 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3533 "privilege=%s", privname);
3534 if (ret < 0) {
3535 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3537 if (ret == 0) {
3538 return NT_STATUS_NO_MORE_ENTRIES;
3541 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3542 if (r->out.sids->sids == NULL) {
3543 return NT_STATUS_NO_MEMORY;
3545 for (i=0;i<ret;i++) {
3546 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3547 res[i], "objectSid");
3548 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3550 r->out.sids->num_sids = ret;
3552 return NT_STATUS_OK;
3557 lsa_AddAccountRights
3559 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3560 TALLOC_CTX *mem_ctx,
3561 struct lsa_AddAccountRights *r)
3563 struct dcesrv_handle *h;
3564 struct lsa_policy_state *state;
3566 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3568 state = h->data;
3570 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3571 LDB_FLAG_MOD_ADD,
3572 r->in.sid, r->in.rights);
3577 lsa_RemoveAccountRights
3579 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3580 TALLOC_CTX *mem_ctx,
3581 struct lsa_RemoveAccountRights *r)
3583 struct dcesrv_handle *h;
3584 struct lsa_policy_state *state;
3586 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3588 state = h->data;
3590 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3591 LDB_FLAG_MOD_DELETE,
3592 r->in.sid, r->in.rights);
3597 lsa_StorePrivateData
3599 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3600 struct lsa_StorePrivateData *r)
3602 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3607 lsa_RetrievePrivateData
3609 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3610 struct lsa_RetrievePrivateData *r)
3612 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3617 lsa_GetUserName
3619 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3620 struct lsa_GetUserName *r)
3622 NTSTATUS status = NT_STATUS_OK;
3623 const char *account_name;
3624 const char *authority_name;
3625 struct lsa_String *_account_name;
3626 struct lsa_String *_authority_name = NULL;
3628 /* this is what w2k3 does */
3629 r->out.account_name = r->in.account_name;
3630 r->out.authority_name = r->in.authority_name;
3632 if (r->in.account_name
3633 && *r->in.account_name
3634 /* && *(*r->in.account_name)->string */
3636 return NT_STATUS_INVALID_PARAMETER;
3639 if (r->in.authority_name
3640 && *r->in.authority_name
3641 /* && *(*r->in.authority_name)->string */
3643 return NT_STATUS_INVALID_PARAMETER;
3646 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
3647 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
3649 _account_name = talloc(mem_ctx, struct lsa_String);
3650 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3651 _account_name->string = account_name;
3653 if (r->in.authority_name) {
3654 _authority_name = talloc(mem_ctx, struct lsa_String);
3655 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3656 _authority_name->string = authority_name;
3659 *r->out.account_name = _account_name;
3660 if (r->out.authority_name) {
3661 *r->out.authority_name = _authority_name;
3664 return status;
3668 lsa_SetInfoPolicy2
3670 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3671 TALLOC_CTX *mem_ctx,
3672 struct lsa_SetInfoPolicy2 *r)
3674 /* need to support these */
3675 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3679 lsa_QueryDomainInformationPolicy
3681 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3682 TALLOC_CTX *mem_ctx,
3683 struct lsa_QueryDomainInformationPolicy *r)
3685 union lsa_DomainInformationPolicy *info;
3687 info = talloc(r->out.info, union lsa_DomainInformationPolicy);
3688 if (!info) {
3689 return NT_STATUS_NO_MEMORY;
3692 switch (r->in.level) {
3693 case LSA_DOMAIN_INFO_POLICY_EFS:
3694 talloc_free(info);
3695 *r->out.info = NULL;
3696 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3697 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3699 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3700 struct smb_krb5_context *smb_krb5_context;
3701 int ret = smb_krb5_init_context(mem_ctx,
3702 dce_call->event_ctx,
3703 dce_call->conn->dce_ctx->lp_ctx,
3704 &smb_krb5_context);
3705 if (ret != 0) {
3706 talloc_free(info);
3707 *r->out.info = NULL;
3708 return NT_STATUS_INTERNAL_ERROR;
3710 k->enforce_restrictions = 0; /* FIXME, details missing from MS-LSAD 2.2.53 */
3711 k->service_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
3712 k->user_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
3713 k->user_tkt_renewaltime = 0; /* Need to find somewhere to store this, and query in KDC too */
3714 k->clock_skew = krb5_get_max_time_skew(smb_krb5_context->krb5_context);
3715 talloc_free(smb_krb5_context);
3716 *r->out.info = info;
3717 return NT_STATUS_OK;
3719 default:
3720 talloc_free(info);
3721 *r->out.info = NULL;
3722 return NT_STATUS_INVALID_INFO_CLASS;
3727 lsa_SetDomInfoPolicy
3729 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3730 TALLOC_CTX *mem_ctx,
3731 struct lsa_SetDomainInformationPolicy *r)
3733 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3737 lsa_TestCall
3739 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3740 TALLOC_CTX *mem_ctx,
3741 struct lsa_TestCall *r)
3743 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3747 lsa_CREDRWRITE
3749 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3750 struct lsa_CREDRWRITE *r)
3752 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3757 lsa_CREDRREAD
3759 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3760 struct lsa_CREDRREAD *r)
3762 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3767 lsa_CREDRENUMERATE
3769 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3770 struct lsa_CREDRENUMERATE *r)
3772 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3777 lsa_CREDRWRITEDOMAINCREDENTIALS
3779 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3780 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3782 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3787 lsa_CREDRREADDOMAINCREDENTIALS
3789 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3790 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3792 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3797 lsa_CREDRDELETE
3799 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3800 struct lsa_CREDRDELETE *r)
3802 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3807 lsa_CREDRGETTARGETINFO
3809 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3810 struct lsa_CREDRGETTARGETINFO *r)
3812 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3817 lsa_CREDRPROFILELOADED
3819 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3820 struct lsa_CREDRPROFILELOADED *r)
3822 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3827 lsa_CREDRGETSESSIONTYPES
3829 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3830 struct lsa_CREDRGETSESSIONTYPES *r)
3832 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3837 lsa_LSARREGISTERAUDITEVENT
3839 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3840 struct lsa_LSARREGISTERAUDITEVENT *r)
3842 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3847 lsa_LSARGENAUDITEVENT
3849 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3850 struct lsa_LSARGENAUDITEVENT *r)
3852 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3857 lsa_LSARUNREGISTERAUDITEVENT
3859 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3860 struct lsa_LSARUNREGISTERAUDITEVENT *r)
3862 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3867 lsa_lsaRQueryForestTrustInformation
3869 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3870 struct lsa_lsaRQueryForestTrustInformation *r)
3872 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3875 #define DNS_CMP_MATCH 0
3876 #define DNS_CMP_FIRST_IS_CHILD 1
3877 #define DNS_CMP_SECOND_IS_CHILD 2
3878 #define DNS_CMP_NO_MATCH 3
3880 /* this function assumes names are well formed DNS names.
3881 * it doesn't validate them */
3882 static int dns_cmp(const char *s1, size_t l1,
3883 const char *s2, size_t l2)
3885 const char *p1, *p2;
3886 size_t t1, t2;
3887 int cret;
3889 if (l1 == l2) {
3890 if (strcasecmp_m(s1, s2) == 0) {
3891 return DNS_CMP_MATCH;
3893 return DNS_CMP_NO_MATCH;
3896 if (l1 > l2) {
3897 p1 = s1;
3898 p2 = s2;
3899 t1 = l1;
3900 t2 = l2;
3901 cret = DNS_CMP_FIRST_IS_CHILD;
3902 } else {
3903 p1 = s2;
3904 p2 = s1;
3905 t1 = l2;
3906 t2 = l1;
3907 cret = DNS_CMP_SECOND_IS_CHILD;
3910 if (p1[t1 - t2 - 1] != '.') {
3911 return DNS_CMP_NO_MATCH;
3914 if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3915 return cret;
3918 return DNS_CMP_NO_MATCH;
3921 /* decode all TDOs forest trust info blobs */
3922 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3923 struct ldb_message *msg,
3924 struct ForestTrustInfo *info)
3926 const struct ldb_val *ft_blob;
3927 enum ndr_err_code ndr_err;
3929 ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3930 if (!ft_blob || !ft_blob->data) {
3931 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3933 /* ldb_val is equivalent to DATA_BLOB */
3934 ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3935 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3936 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3937 return NT_STATUS_INVALID_DOMAIN_STATE;
3940 return NT_STATUS_OK;
3943 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
3944 struct ForestTrustInfo *fti)
3946 struct ForestTrustDataDomainInfo *info;
3947 struct ForestTrustInfoRecord *rec;
3949 fti->version = 1;
3950 fti->count = 2;
3951 fti->records = talloc_array(fti,
3952 struct ForestTrustInfoRecordArmor, 2);
3953 if (!fti->records) {
3954 return NT_STATUS_NO_MEMORY;
3957 /* TLN info */
3958 rec = &fti->records[0].record;
3960 rec->flags = 0;
3961 rec->timestamp = 0;
3962 rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
3964 rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
3965 if (!rec->data.name.string) {
3966 return NT_STATUS_NO_MEMORY;
3968 rec->data.name.size = strlen(rec->data.name.string);
3970 /* DOMAIN info */
3971 rec = &fti->records[1].record;
3973 rec->flags = 0;
3974 rec->timestamp = 0;
3975 rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
3977 info = &rec->data.info;
3979 info->sid = *ps->domain_sid;
3980 info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
3981 if (!info->dns_name.string) {
3982 return NT_STATUS_NO_MEMORY;
3984 info->dns_name.size = strlen(info->dns_name.string);
3985 info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
3986 if (!info->netbios_name.string) {
3987 return NT_STATUS_NO_MEMORY;
3989 info->netbios_name.size = strlen(info->netbios_name.string);
3991 return NT_STATUS_OK;
3994 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
3995 struct lsa_ForestTrustInformation *lfti,
3996 struct ForestTrustInfo *fti)
3998 struct lsa_ForestTrustRecord *lrec;
3999 struct ForestTrustInfoRecord *rec;
4000 struct lsa_StringLarge *tln;
4001 struct lsa_ForestTrustDomainInfo *info;
4002 uint32_t i;
4004 fti->version = 1;
4005 fti->count = lfti->count;
4006 fti->records = talloc_array(mem_ctx,
4007 struct ForestTrustInfoRecordArmor,
4008 fti->count);
4009 if (!fti->records) {
4010 return NT_STATUS_NO_MEMORY;
4012 for (i = 0; i < fti->count; i++) {
4013 lrec = lfti->entries[i];
4014 rec = &fti->records[i].record;
4016 rec->flags = lrec->flags;
4017 rec->timestamp = lrec->time;
4018 rec->type = lrec->type;
4020 switch (lrec->type) {
4021 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4022 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4023 tln = &lrec->forest_trust_data.top_level_name;
4024 rec->data.name.string =
4025 talloc_strdup(mem_ctx, tln->string);
4026 if (!rec->data.name.string) {
4027 return NT_STATUS_NO_MEMORY;
4029 rec->data.name.size = strlen(rec->data.name.string);
4030 break;
4031 case LSA_FOREST_TRUST_DOMAIN_INFO:
4032 info = &lrec->forest_trust_data.domain_info;
4033 rec->data.info.sid = *info->domain_sid;
4034 rec->data.info.dns_name.string =
4035 talloc_strdup(mem_ctx,
4036 info->dns_domain_name.string);
4037 if (!rec->data.info.dns_name.string) {
4038 return NT_STATUS_NO_MEMORY;
4040 rec->data.info.dns_name.size =
4041 strlen(rec->data.info.dns_name.string);
4042 rec->data.info.netbios_name.string =
4043 talloc_strdup(mem_ctx,
4044 info->netbios_domain_name.string);
4045 if (!rec->data.info.netbios_name.string) {
4046 return NT_STATUS_NO_MEMORY;
4048 rec->data.info.netbios_name.size =
4049 strlen(rec->data.info.netbios_name.string);
4050 break;
4051 default:
4052 return NT_STATUS_INVALID_DOMAIN_STATE;
4056 return NT_STATUS_OK;
4059 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4060 uint32_t index, uint32_t collision_type,
4061 uint32_t conflict_type, const char *tdo_name);
4063 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4064 const char *tdo_name,
4065 struct ForestTrustInfo *tdo_fti,
4066 struct ForestTrustInfo *new_fti,
4067 struct lsa_ForestTrustCollisionInfo *c_info)
4069 struct ForestTrustInfoRecord *nrec;
4070 struct ForestTrustInfoRecord *trec;
4071 const char *dns_name;
4072 const char *nb_name;
4073 struct dom_sid *sid;
4074 const char *tname;
4075 size_t dns_len;
4076 size_t nb_len;
4077 size_t tlen;
4078 NTSTATUS nt_status;
4079 uint32_t new_fti_idx;
4080 uint32_t i;
4081 /* use always TDO type, until we understand when Xref can be used */
4082 uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4083 bool tln_conflict;
4084 bool sid_conflict;
4085 bool nb_conflict;
4086 bool exclusion;
4087 bool ex_rule;
4088 int ret;
4090 for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4092 nrec = &new_fti->records[new_fti_idx].record;
4093 dns_name = NULL;
4094 tln_conflict = false;
4095 sid_conflict = false;
4096 nb_conflict = false;
4097 exclusion = false;
4099 switch (nrec->type) {
4100 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4101 /* exclusions do not conflict by definition */
4102 break;
4104 case FOREST_TRUST_TOP_LEVEL_NAME:
4105 dns_name = nrec->data.name.string;
4106 dns_len = nrec->data.name.size;
4107 break;
4109 case LSA_FOREST_TRUST_DOMAIN_INFO:
4110 dns_name = nrec->data.info.dns_name.string;
4111 dns_len = nrec->data.info.dns_name.size;
4112 nb_name = nrec->data.info.netbios_name.string;
4113 nb_len = nrec->data.info.netbios_name.size;
4114 sid = &nrec->data.info.sid;
4115 break;
4118 if (!dns_name) continue;
4120 /* check if this is already taken and not excluded */
4121 for (i = 0; i < tdo_fti->count; i++) {
4122 trec = &tdo_fti->records[i].record;
4124 switch (trec->type) {
4125 case FOREST_TRUST_TOP_LEVEL_NAME:
4126 ex_rule = false;
4127 tname = trec->data.name.string;
4128 tlen = trec->data.name.size;
4129 break;
4130 case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4131 ex_rule = true;
4132 tname = trec->data.name.string;
4133 tlen = trec->data.name.size;
4134 break;
4135 case FOREST_TRUST_DOMAIN_INFO:
4136 ex_rule = false;
4137 tname = trec->data.info.dns_name.string;
4138 tlen = trec->data.info.dns_name.size;
4140 ret = dns_cmp(dns_name, dns_len, tname, tlen);
4141 switch (ret) {
4142 case DNS_CMP_MATCH:
4143 /* if it matches exclusion,
4144 * it doesn't conflict */
4145 if (ex_rule) {
4146 exclusion = true;
4147 break;
4149 /* fall through */
4150 case DNS_CMP_FIRST_IS_CHILD:
4151 case DNS_CMP_SECOND_IS_CHILD:
4152 tln_conflict = true;
4153 /* fall through */
4154 default:
4155 break;
4158 /* explicit exclusion, no dns name conflict here */
4159 if (exclusion) {
4160 tln_conflict = false;
4163 if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4164 continue;
4167 /* also test for domain info */
4168 if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4169 dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4170 sid_conflict = true;
4172 if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4173 strcasecmp_m(trec->data.info.netbios_name.string,
4174 nb_name) == 0) {
4175 nb_conflict = true;
4179 if (tln_conflict) {
4180 nt_status = add_collision(c_info, new_fti_idx,
4181 collision_type,
4182 LSA_TLN_DISABLED_CONFLICT,
4183 tdo_name);
4185 if (sid_conflict) {
4186 nt_status = add_collision(c_info, new_fti_idx,
4187 collision_type,
4188 LSA_SID_DISABLED_CONFLICT,
4189 tdo_name);
4191 if (nb_conflict) {
4192 nt_status = add_collision(c_info, new_fti_idx,
4193 collision_type,
4194 LSA_NB_DISABLED_CONFLICT,
4195 tdo_name);
4199 return NT_STATUS_OK;
4202 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4203 uint32_t idx, uint32_t collision_type,
4204 uint32_t conflict_type, const char *tdo_name)
4206 struct lsa_ForestTrustCollisionRecord **es;
4207 uint32_t i = c_info->count;
4209 es = talloc_realloc(c_info, c_info->entries,
4210 struct lsa_ForestTrustCollisionRecord *, i + 1);
4211 if (!es) {
4212 return NT_STATUS_NO_MEMORY;
4214 c_info->entries = es;
4215 c_info->count = i + 1;
4217 es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4218 if (!es[i]) {
4219 return NT_STATUS_NO_MEMORY;
4222 es[i]->index = idx;
4223 es[i]->type = collision_type;
4224 es[i]->flags.flags = conflict_type;
4225 es[i]->name.string = talloc_strdup(es[i], tdo_name);
4226 if (!es[i]->name.string) {
4227 return NT_STATUS_NO_MEMORY;
4229 es[i]->name.size = strlen(es[i]->name.string);
4231 return NT_STATUS_OK;
4235 lsa_lsaRSetForestTrustInformation
4237 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4238 TALLOC_CTX *mem_ctx,
4239 struct lsa_lsaRSetForestTrustInformation *r)
4241 struct dcesrv_handle *h;
4242 struct lsa_policy_state *p_state;
4243 const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4244 "msDS-TrustForestTrustInfo", NULL };
4245 struct ldb_message **dom_res = NULL;
4246 struct ldb_dn *tdo_dn;
4247 struct ldb_message *msg;
4248 int num_res, i;
4249 const char *td_name;
4250 uint32_t trust_attributes;
4251 struct lsa_ForestTrustCollisionInfo *c_info;
4252 struct ForestTrustInfo *nfti;
4253 struct ForestTrustInfo *fti;
4254 DATA_BLOB ft_blob;
4255 enum ndr_err_code ndr_err;
4256 NTSTATUS nt_status;
4257 bool am_rodc;
4258 int ret;
4260 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4262 p_state = h->data;
4264 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4265 return NT_STATUS_INVALID_DOMAIN_STATE;
4268 /* abort if we are not a PDC */
4269 if (!samdb_is_pdc(p_state->sam_ldb)) {
4270 return NT_STATUS_INVALID_DOMAIN_ROLE;
4273 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4274 if (ret == LDB_SUCCESS && am_rodc) {
4275 return NT_STATUS_NO_SUCH_DOMAIN;
4278 /* check caller has TRUSTED_SET_AUTH */
4280 /* fetch all trusted domain objects */
4281 num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4282 p_state->system_dn,
4283 &dom_res, trust_attrs,
4284 "(objectclass=trustedDomain)");
4285 if (num_res == 0) {
4286 return NT_STATUS_NO_SUCH_DOMAIN;
4289 for (i = 0; i < num_res; i++) {
4290 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4291 "trustPartner", NULL);
4292 if (!td_name) {
4293 return NT_STATUS_INVALID_DOMAIN_STATE;
4295 if (strcasecmp_m(td_name,
4296 r->in.trusted_domain_name->string) == 0) {
4297 break;
4300 if (i >= num_res) {
4301 return NT_STATUS_NO_SUCH_DOMAIN;
4304 tdo_dn = dom_res[i]->dn;
4306 trust_attributes = samdb_result_uint(dom_res[i],
4307 "trustAttributes", 0);
4308 if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4309 return NT_STATUS_INVALID_PARAMETER;
4312 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4313 return NT_STATUS_INVALID_PARAMETER;
4316 nfti = talloc(mem_ctx, struct ForestTrustInfo);
4317 if (!nfti) {
4318 return NT_STATUS_NO_MEMORY;
4321 nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4322 if (!NT_STATUS_IS_OK(nt_status)) {
4323 return nt_status;
4326 c_info = talloc_zero(r->out.collision_info,
4327 struct lsa_ForestTrustCollisionInfo);
4328 if (!c_info) {
4329 return NT_STATUS_NO_MEMORY;
4332 /* first check own info, then other domains */
4333 fti = talloc(mem_ctx, struct ForestTrustInfo);
4334 if (!fti) {
4335 return NT_STATUS_NO_MEMORY;
4338 nt_status = own_ft_info(p_state, fti);
4339 if (!NT_STATUS_IS_OK(nt_status)) {
4340 return nt_status;
4343 nt_status = check_ft_info(c_info, p_state->domain_dns,
4344 fti, nfti, c_info);
4345 if (!NT_STATUS_IS_OK(nt_status)) {
4346 return nt_status;
4349 for (i = 0; i < num_res; i++) {
4350 fti = talloc(mem_ctx, struct ForestTrustInfo);
4351 if (!fti) {
4352 return NT_STATUS_NO_MEMORY;
4355 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4356 if (!NT_STATUS_IS_OK(nt_status)) {
4357 if (NT_STATUS_EQUAL(nt_status,
4358 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4359 continue;
4361 return nt_status;
4364 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4365 "trustPartner", NULL);
4366 if (!td_name) {
4367 return NT_STATUS_INVALID_DOMAIN_STATE;
4370 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4371 if (!NT_STATUS_IS_OK(nt_status)) {
4372 return nt_status;
4376 *r->out.collision_info = c_info;
4378 if (r->in.check_only != 0) {
4379 return NT_STATUS_OK;
4382 /* not just a check, write info back */
4384 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4385 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4386 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4387 return NT_STATUS_INVALID_PARAMETER;
4390 msg = ldb_msg_new(mem_ctx);
4391 if (msg == NULL) {
4392 return NT_STATUS_NO_MEMORY;
4395 msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4396 if (!msg->dn) {
4397 return NT_STATUS_NO_MEMORY;
4400 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4401 LDB_FLAG_MOD_REPLACE, NULL);
4402 if (ret != LDB_SUCCESS) {
4403 return NT_STATUS_NO_MEMORY;
4405 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4406 &ft_blob, NULL);
4407 if (ret != LDB_SUCCESS) {
4408 return NT_STATUS_NO_MEMORY;
4411 ret = ldb_modify(p_state->sam_ldb, msg);
4412 if (ret != LDB_SUCCESS) {
4413 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4414 ldb_errstring(p_state->sam_ldb)));
4416 switch (ret) {
4417 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4418 return NT_STATUS_ACCESS_DENIED;
4419 default:
4420 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4424 return NT_STATUS_OK;
4428 lsa_CREDRRENAME
4430 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4431 struct lsa_CREDRRENAME *r)
4433 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4439 lsa_LSAROPENPOLICYSCE
4441 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4442 struct lsa_LSAROPENPOLICYSCE *r)
4444 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4449 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4451 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4452 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4454 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4459 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4461 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4462 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4464 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4469 lsa_LSARADTREPORTSECURITYEVENT
4471 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4472 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4474 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4478 /* include the generated boilerplate */
4479 #include "librpc/gen_ndr/ndr_lsa_s.c"
4483 /*****************************************
4484 NOTE! The remaining calls below were
4485 removed in w2k3, so the DCESRV_FAULT()
4486 replies are the correct implementation. Do
4487 not try and fill these in with anything else
4488 ******************************************/
4491 dssetup_DsRoleDnsNameToFlatName
4493 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4494 struct dssetup_DsRoleDnsNameToFlatName *r)
4496 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4501 dssetup_DsRoleDcAsDc
4503 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4504 struct dssetup_DsRoleDcAsDc *r)
4506 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4511 dssetup_DsRoleDcAsReplica
4513 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4514 struct dssetup_DsRoleDcAsReplica *r)
4516 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4521 dssetup_DsRoleDemoteDc
4523 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4524 struct dssetup_DsRoleDemoteDc *r)
4526 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4531 dssetup_DsRoleGetDcOperationProgress
4533 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4534 struct dssetup_DsRoleGetDcOperationProgress *r)
4536 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4541 dssetup_DsRoleGetDcOperationResults
4543 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4544 struct dssetup_DsRoleGetDcOperationResults *r)
4546 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4551 dssetup_DsRoleCancel
4553 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4554 struct dssetup_DsRoleCancel *r)
4556 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4561 dssetup_DsRoleServerSaveStateForUpgrade
4563 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4564 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4566 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4571 dssetup_DsRoleUpgradeDownlevelServer
4573 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4574 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4576 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4581 dssetup_DsRoleAbortDownlevelServerUpgrade
4583 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4584 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4586 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4590 /* include the generated boilerplate */
4591 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4593 NTSTATUS dcerpc_server_lsa_init(void)
4595 NTSTATUS ret;
4597 ret = dcerpc_server_dssetup_init();
4598 if (!NT_STATUS_IS_OK(ret)) {
4599 return ret;
4601 ret = dcerpc_server_lsarpc_init();
4602 if (!NT_STATUS_IS_OK(ret)) {
4603 return ret;
4605 return ret;