1 /* need access mask/acl implementation */
4 Unix SMB/CIFS implementation.
6 endpoint server for the lsarpc pipe
8 Copyright (C) Andrew Tridgell 2004
9 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "rpc_server/lsa/lsa.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_drsblobs.h"
29 #include "librpc/gen_ndr/ndr_lsa.h"
30 #include "../lib/crypto/crypto.h"
31 #include "lib/util/tsort.h"
32 #include "dsdb/common/util.h"
33 #include "libcli/security/session.h"
34 #include "libcli/lsarpc/util_lsarpc.h"
35 #include "lib/messaging/irpc.h"
36 #include "libds/common/roles.h"
38 #define DCESRV_INTERFACE_LSARPC_BIND(call, iface) \
39 dcesrv_interface_lsarpc_bind(call, iface)
40 static NTSTATUS dcesrv_interface_lsarpc_bind(struct dcesrv_call_state *dce_call,
41 const struct dcesrv_interface *iface)
43 return dcesrv_interface_bind_reject_connect(dce_call, iface);
46 static NTSTATUS lsarpc__op_init_server(struct dcesrv_context *dce_ctx,
47 const struct dcesrv_endpoint_server *ep_server);
48 static const struct dcesrv_interface dcesrv_lsarpc_interface;
50 #define DCESRV_INTERFACE_LSARPC_INIT_SERVER \
51 dcesrv_interface_lsarpc_init_server
52 static NTSTATUS dcesrv_interface_lsarpc_init_server(struct dcesrv_context *dce_ctx,
53 const struct dcesrv_endpoint_server *ep_server)
55 if (lpcfg_lsa_over_netlogon(dce_ctx->lp_ctx)) {
56 NTSTATUS ret = dcesrv_interface_register(dce_ctx,
57 "ncacn_np:[\\pipe\\netlogon]",
58 &dcesrv_lsarpc_interface, NULL);
59 if (!NT_STATUS_IS_OK(ret)) {
60 DEBUG(1,("lsarpc_op_init_server: failed to register endpoint '\\pipe\\netlogon'\n"));
64 return lsarpc__op_init_server(dce_ctx, ep_server);
68 this type allows us to distinguish handle types
72 state associated with a lsa_OpenAccount() operation
74 struct lsa_account_state {
75 struct lsa_policy_state *policy;
77 struct dom_sid *account_sid;
82 state associated with a lsa_OpenSecret() operation
84 struct lsa_secret_state {
85 struct lsa_policy_state *policy;
87 struct ldb_dn *secret_dn;
88 struct ldb_context *sam_ldb;
93 state associated with a lsa_OpenTrustedDomain() operation
95 struct lsa_trusted_domain_state {
96 struct lsa_policy_state *policy;
98 struct ldb_dn *trusted_domain_dn;
99 struct ldb_dn *trusted_domain_user_dn;
103 this is based on the samba3 function make_lsa_object_sd()
104 It uses the same logic, but with samba4 helper functions
106 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
107 struct security_descriptor **sd,
113 struct dom_sid *domain_sid, *domain_admins_sid;
114 const char *domain_admins_sid_str, *sidstr;
115 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
117 status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
118 if (!NT_STATUS_IS_OK(status)) {
119 TALLOC_FREE(tmp_ctx);
123 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
124 if (domain_admins_sid == NULL) {
125 TALLOC_FREE(tmp_ctx);
126 return NT_STATUS_NO_MEMORY;
129 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
130 if (domain_admins_sid_str == NULL) {
131 TALLOC_FREE(tmp_ctx);
132 return NT_STATUS_NO_MEMORY;
135 sidstr = dom_sid_string(tmp_ctx, sid);
136 if (sidstr == NULL) {
137 TALLOC_FREE(tmp_ctx);
138 return NT_STATUS_NO_MEMORY;
141 *sd = security_descriptor_dacl_create(mem_ctx,
145 SEC_ACE_TYPE_ACCESS_ALLOWED,
146 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
148 SID_BUILTIN_ADMINISTRATORS,
149 SEC_ACE_TYPE_ACCESS_ALLOWED,
152 SID_BUILTIN_ACCOUNT_OPERATORS,
153 SEC_ACE_TYPE_ACCESS_ALLOWED,
156 domain_admins_sid_str,
157 SEC_ACE_TYPE_ACCESS_ALLOWED,
161 SEC_ACE_TYPE_ACCESS_ALLOWED,
165 talloc_free(tmp_ctx);
167 NT_STATUS_HAVE_NO_MEMORY(*sd);
173 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
175 struct lsa_EnumAccountRights *r);
177 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
179 struct lsa_policy_state *state,
182 const struct lsa_RightSet *rights);
187 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
190 enum dcerpc_transport_t transport =
191 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
192 struct dcesrv_handle *h;
194 if (transport != NCACN_NP && transport != NCALRPC) {
195 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
198 *r->out.handle = *r->in.handle;
200 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
204 ZERO_STRUCTP(r->out.handle);
213 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
214 struct lsa_Delete *r)
216 return NT_STATUS_NOT_SUPPORTED;
223 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
224 struct lsa_DeleteObject *r)
226 struct dcesrv_handle *h;
229 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
231 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
232 struct lsa_secret_state *secret_state = h->data;
234 /* Ensure user is permitted to delete this... */
235 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
237 case SECURITY_SYSTEM:
238 case SECURITY_ADMINISTRATOR:
241 /* Users and anonymous are not allowed to delete things */
242 return NT_STATUS_ACCESS_DENIED;
245 ret = ldb_delete(secret_state->sam_ldb,
246 secret_state->secret_dn);
247 if (ret != LDB_SUCCESS) {
248 return NT_STATUS_INVALID_HANDLE;
251 ZERO_STRUCTP(r->out.handle);
255 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
256 struct lsa_trusted_domain_state *trusted_domain_state =
257 talloc_get_type(h->data, struct lsa_trusted_domain_state);
258 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
259 if (ret != LDB_SUCCESS) {
260 return NT_STATUS_INTERNAL_DB_CORRUPTION;
263 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
264 trusted_domain_state->trusted_domain_dn);
265 if (ret != LDB_SUCCESS) {
266 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
267 return NT_STATUS_INVALID_HANDLE;
270 if (trusted_domain_state->trusted_domain_user_dn) {
271 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
272 trusted_domain_state->trusted_domain_user_dn);
273 if (ret != LDB_SUCCESS) {
274 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
275 return NT_STATUS_INVALID_HANDLE;
279 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
280 if (ret != LDB_SUCCESS) {
281 return NT_STATUS_INTERNAL_DB_CORRUPTION;
284 ZERO_STRUCTP(r->out.handle);
288 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
289 struct lsa_RightSet *rights;
290 struct lsa_account_state *astate;
291 struct lsa_EnumAccountRights r2;
294 rights = talloc(mem_ctx, struct lsa_RightSet);
296 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
300 r2.in.handle = &astate->policy->handle->wire_handle;
301 r2.in.sid = astate->account_sid;
302 r2.out.rights = rights;
304 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
305 but we have a LSA_HANDLE_ACCOUNT here, so this call
307 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
308 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
312 if (!NT_STATUS_IS_OK(status)) {
316 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
317 LDB_FLAG_MOD_DELETE, astate->account_sid,
319 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
323 if (!NT_STATUS_IS_OK(status)) {
327 ZERO_STRUCTP(r->out.handle);
332 return NT_STATUS_INVALID_HANDLE;
339 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
340 struct lsa_EnumPrivs *r)
342 struct dcesrv_handle *h;
344 enum sec_privilege priv;
345 const char *privname;
347 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
349 i = *r->in.resume_handle;
351 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
352 r->out.privs->count < r->in.max_count) {
353 struct lsa_PrivEntry *e;
354 privname = sec_privilege_name(priv);
355 r->out.privs->privs = talloc_realloc(r->out.privs,
357 struct lsa_PrivEntry,
358 r->out.privs->count+1);
359 if (r->out.privs->privs == NULL) {
360 return NT_STATUS_NO_MEMORY;
362 e = &r->out.privs->privs[r->out.privs->count];
365 e->name.string = privname;
366 r->out.privs->count++;
370 *r->out.resume_handle = i;
379 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
380 struct lsa_QuerySecurity *r)
382 struct dcesrv_handle *h;
383 const struct security_descriptor *sd = NULL;
384 uint32_t access_granted = 0;
385 struct sec_desc_buf *sdbuf = NULL;
389 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
391 sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
393 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
394 struct lsa_policy_state *pstate = h->data;
397 access_granted = pstate->access_mask;
399 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
400 struct lsa_account_state *astate = h->data;
401 struct security_descriptor *_sd = NULL;
403 status = dcesrv_build_lsa_sd(mem_ctx, &_sd, sid,
404 LSA_ACCOUNT_ALL_ACCESS);
405 if (!NT_STATUS_IS_OK(status)) {
409 access_granted = astate->access_mask;
411 return NT_STATUS_INVALID_HANDLE;
414 sdbuf = talloc_zero(mem_ctx, struct sec_desc_buf);
416 return NT_STATUS_NO_MEMORY;
419 status = security_descriptor_for_client(sdbuf, sd, r->in.sec_info,
420 access_granted, &sdbuf->sd);
421 if (!NT_STATUS_IS_OK(status)) {
425 *r->out.sdbuf = sdbuf;
434 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
435 struct lsa_SetSecObj *r)
437 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
444 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
445 struct lsa_ChangePassword *r)
447 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
451 dssetup_DsRoleGetPrimaryDomainInformation
453 This is not an LSA call, but is the only call left on the DSSETUP
454 pipe (after the pipe was truncated), and needs lsa_get_policy_state
456 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
458 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
460 union dssetup_DsRoleInfo *info;
462 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
463 W_ERROR_HAVE_NO_MEMORY(info);
465 switch (r->in.level) {
466 case DS_ROLE_BASIC_INFORMATION:
468 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
470 const char *domain = NULL;
471 const char *dns_domain = NULL;
472 const char *forest = NULL;
473 struct GUID domain_guid;
474 struct lsa_policy_state *state;
476 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
477 0, /* we skip access checks */
479 if (!NT_STATUS_IS_OK(status)) {
480 return ntstatus_to_werror(status);
483 ZERO_STRUCT(domain_guid);
485 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
486 case ROLE_STANDALONE:
487 role = DS_ROLE_STANDALONE_SERVER;
489 case ROLE_DOMAIN_MEMBER:
490 role = DS_ROLE_MEMBER_SERVER;
492 case ROLE_ACTIVE_DIRECTORY_DC:
493 if (samdb_is_pdc(state->sam_ldb)) {
494 role = DS_ROLE_PRIMARY_DC;
496 role = DS_ROLE_BACKUP_DC;
501 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
502 case ROLE_STANDALONE:
503 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
504 W_ERROR_HAVE_NO_MEMORY(domain);
506 case ROLE_DOMAIN_MEMBER:
507 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
508 W_ERROR_HAVE_NO_MEMORY(domain);
509 /* TODO: what is with dns_domain and forest and guid? */
511 case ROLE_ACTIVE_DIRECTORY_DC:
512 flags = DS_ROLE_PRIMARY_DS_RUNNING;
514 if (state->mixed_domain == 1) {
515 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
518 domain = state->domain_name;
519 dns_domain = state->domain_dns;
520 forest = state->forest_dns;
522 domain_guid = state->domain_guid;
523 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
527 info->basic.role = role;
528 info->basic.flags = flags;
529 info->basic.domain = domain;
530 info->basic.dns_domain = dns_domain;
531 info->basic.forest = forest;
532 info->basic.domain_guid = domain_guid;
537 case DS_ROLE_UPGRADE_STATUS:
539 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
540 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
545 case DS_ROLE_OP_STATUS:
547 info->opstatus.status = DS_ROLE_OP_IDLE;
553 return WERR_INVALID_PARAMETER;
558 fill in the AccountDomain info
560 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
561 struct lsa_DomainInfo *info)
563 info->name.string = state->domain_name;
564 info->sid = state->domain_sid;
570 fill in the DNS domain info
572 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
573 struct lsa_DnsDomainInfo *info)
575 info->name.string = state->domain_name;
576 info->sid = state->domain_sid;
577 info->dns_domain.string = state->domain_dns;
578 info->dns_forest.string = state->forest_dns;
579 info->domain_guid = state->domain_guid;
587 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
588 struct lsa_QueryInfoPolicy2 *r)
590 struct lsa_policy_state *state;
591 struct dcesrv_handle *h;
592 union lsa_PolicyInformation *info;
596 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
600 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
602 return NT_STATUS_NO_MEMORY;
606 switch (r->in.level) {
607 case LSA_POLICY_INFO_AUDIT_LOG:
608 /* we don't need to fill in any of this */
609 ZERO_STRUCT(info->audit_log);
611 case LSA_POLICY_INFO_AUDIT_EVENTS:
612 /* we don't need to fill in any of this */
613 ZERO_STRUCT(info->audit_events);
615 case LSA_POLICY_INFO_PD:
616 /* we don't need to fill in any of this */
617 ZERO_STRUCT(info->pd);
620 case LSA_POLICY_INFO_DOMAIN:
621 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
622 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
623 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
624 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
625 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
627 case LSA_POLICY_INFO_ROLE:
628 info->role.role = LSA_ROLE_PRIMARY;
631 case LSA_POLICY_INFO_DNS:
632 case LSA_POLICY_INFO_DNS_INT:
633 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
635 case LSA_POLICY_INFO_REPLICA:
636 ZERO_STRUCT(info->replica);
639 case LSA_POLICY_INFO_QUOTA:
640 ZERO_STRUCT(info->quota);
643 case LSA_POLICY_INFO_MOD:
644 case LSA_POLICY_INFO_AUDIT_FULL_SET:
645 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
646 /* windows gives INVALID_PARAMETER */
648 return NT_STATUS_INVALID_PARAMETER;
652 return NT_STATUS_INVALID_INFO_CLASS;
658 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
659 struct lsa_QueryInfoPolicy *r)
661 struct lsa_QueryInfoPolicy2 r2;
666 r2.in.handle = r->in.handle;
667 r2.in.level = r->in.level;
668 r2.out.info = r->out.info;
670 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
678 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
679 struct lsa_SetInfoPolicy *r)
681 /* need to support this */
682 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
689 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
690 struct lsa_ClearAuditLog *r)
692 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
696 static const struct generic_mapping dcesrv_lsa_account_mapping = {
700 LSA_ACCOUNT_ALL_ACCESS
706 This call does not seem to have any long-term effects, hence no database operations
708 we need to talk to the MS product group to find out what this account database means!
710 answer is that the lsa database is totally separate from the SAM and
711 ldap databases. We are going to need a separate ldb to store these
712 accounts. The SIDs on this account bear no relation to the SIDs in
715 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
716 struct lsa_CreateAccount *r)
718 struct lsa_account_state *astate;
720 struct lsa_policy_state *state;
721 struct dcesrv_handle *h, *ah;
723 ZERO_STRUCTP(r->out.acct_handle);
725 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
729 astate = talloc(dce_call->conn, struct lsa_account_state);
730 if (astate == NULL) {
731 return NT_STATUS_NO_MEMORY;
734 astate->account_sid = dom_sid_dup(astate, r->in.sid);
735 if (astate->account_sid == NULL) {
737 return NT_STATUS_NO_MEMORY;
740 astate->policy = talloc_reference(astate, state);
741 astate->access_mask = r->in.access_mask;
744 * For now we grant all requested access.
746 * We will fail at the ldb layer later.
748 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
749 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
750 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
752 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
754 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X].\n",
755 __func__, dom_sid_string(mem_ctx, astate->account_sid),
756 (unsigned)r->in.access_mask,
757 (unsigned)astate->access_mask));
759 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
762 return NT_STATUS_NO_MEMORY;
765 ah->data = talloc_steal(ah, astate);
767 *r->out.acct_handle = ah->wire_handle;
776 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
777 struct lsa_EnumAccounts *r)
779 struct dcesrv_handle *h;
780 struct lsa_policy_state *state;
782 struct ldb_message **res;
783 const char * const attrs[] = { "objectSid", NULL};
786 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
790 /* NOTE: This call must only return accounts that have at least
793 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
794 "(&(objectSid=*)(privilege=*))");
796 return NT_STATUS_INTERNAL_DB_CORRUPTION;
799 if (*r->in.resume_handle >= ret) {
800 return NT_STATUS_NO_MORE_ENTRIES;
803 count = ret - *r->in.resume_handle;
804 if (count > r->in.num_entries) {
805 count = r->in.num_entries;
809 return NT_STATUS_NO_MORE_ENTRIES;
812 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
813 if (r->out.sids->sids == NULL) {
814 return NT_STATUS_NO_MEMORY;
817 for (i=0;i<count;i++) {
818 r->out.sids->sids[i].sid =
819 samdb_result_dom_sid(r->out.sids->sids,
820 res[i + *r->in.resume_handle],
822 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
825 r->out.sids->num_sids = count;
826 *r->out.resume_handle = count + *r->in.resume_handle;
831 /* This decrypts and returns Trusted Domain Auth Information Internal data */
832 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
833 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
834 struct trustDomainPasswords *auth_struct)
836 DATA_BLOB session_key = data_blob(NULL, 0);
837 enum ndr_err_code ndr_err;
840 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
841 if (!NT_STATUS_IS_OK(nt_status)) {
845 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
846 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
848 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
849 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
850 return NT_STATUS_INVALID_PARAMETER;
856 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
858 struct trustAuthInOutBlob *iopw,
859 DATA_BLOB *trustauth_blob)
861 enum ndr_err_code ndr_err;
863 if (iopw->current.count != iopw->count) {
864 return NT_STATUS_INVALID_PARAMETER;
867 if (iopw->previous.count > iopw->current.count) {
868 return NT_STATUS_INVALID_PARAMETER;
871 if (iopw->previous.count == 0) {
873 * If the previous credentials are not present
874 * we need to make a copy.
876 iopw->previous = iopw->current;
879 if (iopw->previous.count < iopw->current.count) {
880 struct AuthenticationInformationArray *c = &iopw->current;
881 struct AuthenticationInformationArray *p = &iopw->previous;
884 * The previous array needs to have the same size
885 * as the current one.
887 * We may have to fill with TRUST_AUTH_TYPE_NONE
890 p->array = talloc_realloc(mem_ctx, p->array,
891 struct AuthenticationInformation,
893 if (p->array == NULL) {
894 return NT_STATUS_NO_MEMORY;
897 while (p->count < c->count) {
898 struct AuthenticationInformation *a =
899 &p->array[p->count++];
901 *a = (struct AuthenticationInformation) {
902 .LastUpdateTime = p->array[0].LastUpdateTime,
903 .AuthType = TRUST_AUTH_TYPE_NONE,
908 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
910 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
911 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
912 return NT_STATUS_INVALID_PARAMETER;
918 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
919 struct ldb_context *sam_ldb,
920 struct ldb_dn *base_dn,
921 const char *netbios_name,
922 struct trustAuthInOutBlob *in,
923 struct ldb_dn **user_dn)
925 struct ldb_request *req;
926 struct ldb_message *msg;
931 dn = ldb_dn_copy(mem_ctx, base_dn);
933 return NT_STATUS_NO_MEMORY;
935 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
936 return NT_STATUS_NO_MEMORY;
939 msg = ldb_msg_new(mem_ctx);
941 return NT_STATUS_NO_MEMORY;
945 ret = ldb_msg_add_string(msg, "objectClass", "user");
946 if (ret != LDB_SUCCESS) {
947 return NT_STATUS_NO_MEMORY;
950 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
951 if (ret != LDB_SUCCESS) {
952 return NT_STATUS_NO_MEMORY;
955 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
956 UF_INTERDOMAIN_TRUST_ACCOUNT);
957 if (ret != LDB_SUCCESS) {
958 return NT_STATUS_NO_MEMORY;
961 for (i = 0; i < in->count; i++) {
962 const char *attribute;
964 switch (in->current.array[i].AuthType) {
965 case TRUST_AUTH_TYPE_NT4OWF:
966 attribute = "unicodePwd";
967 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
970 case TRUST_AUTH_TYPE_CLEAR:
971 attribute = "clearTextPassword";
972 v.data = in->current.array[i].AuthInfo.clear.password;
973 v.length = in->current.array[i].AuthInfo.clear.size;
979 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
980 if (ret != LDB_SUCCESS) {
981 return NT_STATUS_NO_MEMORY;
985 /* create the trusted_domain user account */
986 ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
987 ldb_op_default_callback, NULL);
988 if (ret != LDB_SUCCESS) {
989 return NT_STATUS_NO_MEMORY;
992 ret = ldb_request_add_control(req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
994 if (ret != LDB_SUCCESS) {
995 return NT_STATUS_NO_MEMORY;
998 ret = dsdb_autotransaction_request(sam_ldb, req);
999 if (ret != LDB_SUCCESS) {
1000 DEBUG(0,("Failed to create user record %s: %s\n",
1001 ldb_dn_get_linearized(msg->dn),
1002 ldb_errstring(sam_ldb)));
1005 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1006 return NT_STATUS_DOMAIN_EXISTS;
1007 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1008 return NT_STATUS_ACCESS_DENIED;
1010 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1017 return NT_STATUS_OK;
1021 lsa_CreateTrustedDomainEx2
1023 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
1024 TALLOC_CTX *mem_ctx,
1025 struct lsa_CreateTrustedDomainEx2 *r,
1027 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
1029 struct dcesrv_handle *policy_handle;
1030 struct lsa_policy_state *policy_state;
1031 struct lsa_trusted_domain_state *trusted_domain_state;
1032 struct dcesrv_handle *handle;
1033 struct ldb_message **msgs, *msg;
1034 const char *attrs[] = {
1037 const char *netbios_name;
1038 const char *dns_name;
1039 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1040 struct trustDomainPasswords auth_struct;
1043 struct ldb_context *sam_ldb;
1044 struct server_id *server_ids = NULL;
1045 uint32_t num_server_ids = 0;
1047 struct dom_sid *tmp_sid1;
1048 struct dom_sid *tmp_sid2;
1051 char *dns_encoded = NULL;
1052 char *netbios_encoded = NULL;
1053 char *sid_encoded = NULL;
1055 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
1056 ZERO_STRUCTP(r->out.trustdom_handle);
1058 policy_state = policy_handle->data;
1059 sam_ldb = policy_state->sam_ldb;
1061 netbios_name = r->in.info->netbios_name.string;
1062 if (!netbios_name) {
1063 return NT_STATUS_INVALID_PARAMETER;
1066 dns_name = r->in.info->domain_name.string;
1067 if (dns_name == NULL) {
1068 return NT_STATUS_INVALID_PARAMETER;
1071 if (r->in.info->sid == NULL) {
1072 return NT_STATUS_INVALID_SID;
1076 * We expect S-1-5-21-A-B-C, but we don't
1077 * allow S-1-5-21-0-0-0 as this is used
1078 * for claims and compound identities.
1080 * So we call dom_sid_split_rid() 3 times
1081 * and compare the result to S-1-5-21
1083 status = dom_sid_split_rid(mem_ctx, r->in.info->sid, &tmp_sid1, &tmp_rid);
1084 if (!NT_STATUS_IS_OK(status)) {
1087 status = dom_sid_split_rid(mem_ctx, tmp_sid1, &tmp_sid2, &tmp_rid);
1088 if (!NT_STATUS_IS_OK(status)) {
1091 status = dom_sid_split_rid(mem_ctx, tmp_sid2, &tmp_sid1, &tmp_rid);
1092 if (!NT_STATUS_IS_OK(status)) {
1095 ok = dom_sid_parse("S-1-5-21", tmp_sid2);
1097 return NT_STATUS_INTERNAL_ERROR;
1099 ok = dom_sid_equal(tmp_sid1, tmp_sid2);
1101 return NT_STATUS_INVALID_PARAMETER;
1103 ok = dom_sid_parse("S-1-5-21-0-0-0", tmp_sid2);
1105 return NT_STATUS_INTERNAL_ERROR;
1107 ok = !dom_sid_equal(r->in.info->sid, tmp_sid2);
1109 return NT_STATUS_INVALID_PARAMETER;
1112 dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1113 if (dns_encoded == NULL) {
1114 return NT_STATUS_NO_MEMORY;
1116 netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1117 if (netbios_encoded == NULL) {
1118 return NT_STATUS_NO_MEMORY;
1120 sid_encoded = ldap_encode_ndr_dom_sid(mem_ctx, r->in.info->sid);
1121 if (sid_encoded == NULL) {
1122 return NT_STATUS_NO_MEMORY;
1125 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1126 if (!trusted_domain_state) {
1127 return NT_STATUS_NO_MEMORY;
1129 trusted_domain_state->policy = policy_state;
1131 if (strcasecmp(netbios_name, "BUILTIN") == 0
1132 || (strcasecmp(dns_name, "BUILTIN") == 0)
1133 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
1134 return NT_STATUS_INVALID_PARAMETER;
1137 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
1138 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
1139 || strcasecmp(dns_name, policy_state->domain_dns) == 0
1140 || strcasecmp(dns_name, policy_state->domain_name) == 0
1141 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
1142 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
1145 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
1146 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
1147 /* No secrets are created at this time, for this function */
1148 auth_struct.outgoing.count = 0;
1149 auth_struct.incoming.count = 0;
1150 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
1151 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
1152 r->in.auth_info_internal->auth_blob.size);
1153 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1154 &auth_blob, &auth_struct);
1155 if (!NT_STATUS_IS_OK(nt_status)) {
1158 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
1160 if (unencrypted_auth_info->incoming_count > 1) {
1161 return NT_STATUS_INVALID_PARAMETER;
1164 /* more investigation required here, do not create secrets for
1166 auth_struct.outgoing.count = 0;
1167 auth_struct.incoming.count = 0;
1169 return NT_STATUS_INVALID_PARAMETER;
1172 if (auth_struct.incoming.count) {
1173 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1174 &auth_struct.incoming,
1175 &trustAuthIncoming);
1176 if (!NT_STATUS_IS_OK(nt_status)) {
1180 trustAuthIncoming = data_blob(NULL, 0);
1183 if (auth_struct.outgoing.count) {
1184 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1185 &auth_struct.outgoing,
1186 &trustAuthOutgoing);
1187 if (!NT_STATUS_IS_OK(nt_status)) {
1191 trustAuthOutgoing = data_blob(NULL, 0);
1194 ret = ldb_transaction_start(sam_ldb);
1195 if (ret != LDB_SUCCESS) {
1196 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1199 /* search for the trusted_domain record */
1200 ret = gendb_search(sam_ldb,
1201 mem_ctx, policy_state->system_dn, &msgs, attrs,
1202 "(&(objectClass=trustedDomain)(|"
1203 "(flatname=%s)(trustPartner=%s)"
1204 "(flatname=%s)(trustPartner=%s)"
1205 "(securityIdentifier=%s)))",
1206 dns_encoded, dns_encoded,
1207 netbios_encoded, netbios_encoded,
1210 ldb_transaction_cancel(sam_ldb);
1211 return NT_STATUS_OBJECT_NAME_COLLISION;
1214 ldb_transaction_cancel(sam_ldb);
1215 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1218 msg = ldb_msg_new(mem_ctx);
1220 return NT_STATUS_NO_MEMORY;
1223 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1224 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", dns_name)) {
1225 ldb_transaction_cancel(sam_ldb);
1226 return NT_STATUS_NO_MEMORY;
1229 ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1230 if (ret != LDB_SUCCESS) {
1231 ldb_transaction_cancel(sam_ldb);
1232 return NT_STATUS_NO_MEMORY;;
1235 ret = ldb_msg_add_string(msg, "flatname", netbios_name);
1236 if (ret != LDB_SUCCESS) {
1237 ldb_transaction_cancel(sam_ldb);
1238 return NT_STATUS_NO_MEMORY;
1241 ret = ldb_msg_add_string(msg, "trustPartner", dns_name);
1242 if (ret != LDB_SUCCESS) {
1243 ldb_transaction_cancel(sam_ldb);
1244 return NT_STATUS_NO_MEMORY;;
1247 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier",
1249 if (ret != LDB_SUCCESS) {
1250 ldb_transaction_cancel(sam_ldb);
1251 return NT_STATUS_NO_MEMORY;;
1254 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1255 if (ret != LDB_SUCCESS) {
1256 ldb_transaction_cancel(sam_ldb);
1257 return NT_STATUS_NO_MEMORY;;
1260 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1261 if (ret != LDB_SUCCESS) {
1262 ldb_transaction_cancel(sam_ldb);
1263 return NT_STATUS_NO_MEMORY;;
1266 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1267 if (ret != LDB_SUCCESS) {
1268 ldb_transaction_cancel(sam_ldb);
1269 return NT_STATUS_NO_MEMORY;;
1272 if (trustAuthIncoming.data) {
1273 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1274 if (ret != LDB_SUCCESS) {
1275 ldb_transaction_cancel(sam_ldb);
1276 return NT_STATUS_NO_MEMORY;
1279 if (trustAuthOutgoing.data) {
1280 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1281 if (ret != LDB_SUCCESS) {
1282 ldb_transaction_cancel(sam_ldb);
1283 return NT_STATUS_NO_MEMORY;
1287 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1289 /* create the trusted_domain */
1290 ret = ldb_add(sam_ldb, msg);
1294 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1295 ldb_transaction_cancel(sam_ldb);
1296 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1297 ldb_dn_get_linearized(msg->dn),
1298 ldb_errstring(sam_ldb)));
1299 return NT_STATUS_DOMAIN_EXISTS;
1300 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1301 ldb_transaction_cancel(sam_ldb);
1302 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1303 ldb_dn_get_linearized(msg->dn),
1304 ldb_errstring(sam_ldb)));
1305 return NT_STATUS_ACCESS_DENIED;
1307 ldb_transaction_cancel(sam_ldb);
1308 DEBUG(0,("Failed to create user record %s: %s\n",
1309 ldb_dn_get_linearized(msg->dn),
1310 ldb_errstring(sam_ldb)));
1311 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1314 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1315 struct ldb_dn *user_dn;
1316 /* Inbound trusts must also create a cn=users object to match */
1317 nt_status = add_trust_user(mem_ctx, sam_ldb,
1318 policy_state->domain_dn,
1320 &auth_struct.incoming,
1322 if (!NT_STATUS_IS_OK(nt_status)) {
1323 ldb_transaction_cancel(sam_ldb);
1327 /* save the trust user dn */
1328 trusted_domain_state->trusted_domain_user_dn
1329 = talloc_steal(trusted_domain_state, user_dn);
1332 ret = ldb_transaction_commit(sam_ldb);
1333 if (ret != LDB_SUCCESS) {
1334 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1338 * Notify winbindd that we have a new trust
1340 status = irpc_servers_byname(dce_call->msg_ctx,
1343 &num_server_ids, &server_ids);
1344 if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
1345 enum ndr_err_code ndr_err;
1348 ndr_err = ndr_push_struct_blob(&b, mem_ctx, r->in.info,
1349 (ndr_push_flags_fn_t)ndr_push_lsa_TrustDomainInfoInfoEx);
1350 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1351 imessaging_send(dce_call->msg_ctx, server_ids[0],
1352 MSG_WINBIND_NEW_TRUSTED_DOMAIN, &b);
1355 TALLOC_FREE(server_ids);
1357 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1359 return NT_STATUS_NO_MEMORY;
1362 handle->data = talloc_steal(handle, trusted_domain_state);
1364 trusted_domain_state->access_mask = r->in.access_mask;
1365 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1367 *r->out.trustdom_handle = handle->wire_handle;
1369 return NT_STATUS_OK;
1373 lsa_CreateTrustedDomainEx2
1375 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1376 TALLOC_CTX *mem_ctx,
1377 struct lsa_CreateTrustedDomainEx2 *r)
1379 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1382 lsa_CreateTrustedDomainEx
1384 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1385 TALLOC_CTX *mem_ctx,
1386 struct lsa_CreateTrustedDomainEx *r)
1388 struct lsa_CreateTrustedDomainEx2 r2;
1390 r2.in.policy_handle = r->in.policy_handle;
1391 r2.in.info = r->in.info;
1392 r2.out.trustdom_handle = r->out.trustdom_handle;
1393 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1397 lsa_CreateTrustedDomain
1399 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1400 struct lsa_CreateTrustedDomain *r)
1402 struct lsa_CreateTrustedDomainEx2 r2;
1404 r2.in.policy_handle = r->in.policy_handle;
1405 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1407 return NT_STATUS_NO_MEMORY;
1410 r2.in.info->domain_name = r->in.info->name;
1411 r2.in.info->netbios_name = r->in.info->name;
1412 r2.in.info->sid = r->in.info->sid;
1413 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1414 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1415 r2.in.info->trust_attributes = 0;
1417 r2.in.access_mask = r->in.access_mask;
1418 r2.out.trustdom_handle = r->out.trustdom_handle;
1420 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1423 static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
1424 struct dcesrv_call_state *dce_call,
1425 TALLOC_CTX *tmp_mem,
1426 struct lsa_policy_state *policy_state,
1428 uint32_t access_mask,
1429 struct dcesrv_handle **_handle)
1431 struct lsa_trusted_domain_state *trusted_domain_state;
1432 struct dcesrv_handle *handle;
1433 struct ldb_message **msgs;
1434 const char *attrs[] = {
1442 /* TODO: perform access checks */
1444 /* search for the trusted_domain record */
1445 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1446 policy_state->system_dn,
1447 &msgs, attrs, "%s", filter);
1449 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1453 DEBUG(0,("Found %d records matching %s under %s\n", ret,
1455 ldb_dn_get_linearized(policy_state->system_dn)));
1456 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1459 trusted_domain_state = talloc_zero(tmp_mem,
1460 struct lsa_trusted_domain_state);
1461 if (!trusted_domain_state) {
1462 return NT_STATUS_NO_MEMORY;
1464 trusted_domain_state->policy = policy_state;
1466 trusted_domain_state->trusted_domain_dn =
1467 talloc_steal(trusted_domain_state, msgs[0]->dn);
1469 direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1470 if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1471 const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1474 /* search for the trusted_domain account */
1475 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1476 policy_state->domain_dn,
1478 "(&(samaccountname=%s$)(objectclass=user)"
1479 "(userAccountControl:%s:=%u))",
1481 LDB_OID_COMPARATOR_AND,
1482 UF_INTERDOMAIN_TRUST_ACCOUNT);
1484 trusted_domain_state->trusted_domain_user_dn =
1485 talloc_steal(trusted_domain_state, msgs[0]->dn);
1489 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1491 return NT_STATUS_NO_MEMORY;
1494 handle->data = talloc_steal(handle, trusted_domain_state);
1496 trusted_domain_state->access_mask = access_mask;
1497 trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1502 return NT_STATUS_OK;
1506 lsa_OpenTrustedDomain
1508 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1509 struct lsa_OpenTrustedDomain *r)
1511 struct dcesrv_handle *policy_handle;
1512 struct lsa_policy_state *policy_state;
1513 struct dcesrv_handle *handle;
1514 const char *sid_string;
1518 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1519 ZERO_STRUCTP(r->out.trustdom_handle);
1520 policy_state = policy_handle->data;
1522 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1524 return NT_STATUS_NO_MEMORY;
1527 filter = talloc_asprintf(mem_ctx,
1528 "(&(securityIdentifier=%s)"
1529 "(objectclass=trustedDomain))",
1531 if (filter == NULL) {
1532 return NT_STATUS_NO_MEMORY;
1535 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1540 if (!NT_STATUS_IS_OK(status)) {
1544 *r->out.trustdom_handle = handle->wire_handle;
1546 return NT_STATUS_OK;
1551 lsa_OpenTrustedDomainByName
1553 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1554 TALLOC_CTX *mem_ctx,
1555 struct lsa_OpenTrustedDomainByName *r)
1557 struct dcesrv_handle *policy_handle;
1558 struct lsa_policy_state *policy_state;
1559 struct dcesrv_handle *handle;
1564 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1565 ZERO_STRUCTP(r->out.trustdom_handle);
1566 policy_state = policy_handle->data;
1568 if (!r->in.name.string) {
1569 return NT_STATUS_INVALID_PARAMETER;
1572 /* search for the trusted_domain record */
1573 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1574 if (td_name == NULL) {
1575 return NT_STATUS_NO_MEMORY;
1578 filter = talloc_asprintf(mem_ctx,
1579 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1580 "(objectclass=trustedDomain))",
1581 td_name, td_name, td_name);
1582 if (filter == NULL) {
1583 return NT_STATUS_NO_MEMORY;
1586 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1591 if (!NT_STATUS_IS_OK(status)) {
1595 *r->out.trustdom_handle = handle->wire_handle;
1597 return NT_STATUS_OK;
1603 lsa_SetTrustedDomainInfo
1605 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1606 struct lsa_SetTrustedDomainInfo *r)
1608 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1613 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1614 * otherwise at least one must be provided */
1615 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1616 struct ldb_dn *basedn, const char *dns_domain,
1617 const char *netbios, struct dom_sid2 *sid,
1618 struct ldb_message ***msgs)
1620 const char *attrs[] = { "flatname", "trustPartner",
1621 "securityIdentifier", "trustDirection",
1622 "trustType", "trustAttributes",
1624 "msDs-supportedEncryptionTypes",
1625 "msDS-TrustForestTrustInfo",
1630 char *sidstr = NULL;
1635 if (dns_domain || netbios || sid) {
1636 filter = talloc_strdup(mem_ctx,
1637 "(&(objectclass=trustedDomain)(|");
1639 filter = talloc_strdup(mem_ctx,
1640 "(objectclass=trustedDomain)");
1643 return NT_STATUS_NO_MEMORY;
1647 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1649 return NT_STATUS_NO_MEMORY;
1651 filter = talloc_asprintf_append(filter,
1652 "(trustPartner=%s)", dns);
1654 return NT_STATUS_NO_MEMORY;
1658 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1660 return NT_STATUS_NO_MEMORY;
1662 filter = talloc_asprintf_append(filter,
1663 "(flatname=%s)", nbn);
1665 return NT_STATUS_NO_MEMORY;
1669 sidstr = dom_sid_string(mem_ctx, sid);
1671 return NT_STATUS_INVALID_PARAMETER;
1673 filter = talloc_asprintf_append(filter,
1674 "(securityIdentifier=%s)",
1677 return NT_STATUS_NO_MEMORY;
1680 if (dns_domain || netbios || sid) {
1681 filter = talloc_asprintf_append(filter, "))");
1683 return NT_STATUS_NO_MEMORY;
1687 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1689 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1693 return NT_STATUS_OBJECT_NAME_COLLISION;
1696 return NT_STATUS_OK;
1699 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1700 struct ldb_context *sam_ldb,
1701 struct ldb_message *orig,
1702 struct ldb_message *dest,
1703 const char *attribute,
1705 uint32_t *orig_value)
1707 const struct ldb_val *orig_val;
1708 uint32_t orig_uint = 0;
1709 unsigned int flags = 0;
1712 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1713 if (!orig_val || !orig_val->data) {
1714 /* add new attribute */
1715 flags = LDB_FLAG_MOD_ADD;
1719 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1720 if (errno != 0 || orig_uint != value) {
1721 /* replace also if can't get value */
1722 flags = LDB_FLAG_MOD_REPLACE;
1727 /* stored value is identical, nothing to change */
1731 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1732 if (ret != LDB_SUCCESS) {
1733 return NT_STATUS_NO_MEMORY;
1736 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1737 if (ret != LDB_SUCCESS) {
1738 return NT_STATUS_NO_MEMORY;
1743 *orig_value = orig_uint;
1745 return NT_STATUS_OK;
1748 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1749 struct ldb_context *sam_ldb,
1750 struct ldb_dn *base_dn,
1752 const char *netbios_name,
1753 struct trustAuthInOutBlob *in)
1755 const char *attrs[] = { "userAccountControl", NULL };
1756 struct ldb_message **msgs;
1757 struct ldb_message *msg;
1762 ret = gendb_search(sam_ldb, mem_ctx,
1763 base_dn, &msgs, attrs,
1764 "samAccountName=%s$", netbios_name);
1766 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1771 return NT_STATUS_OK;
1774 /* ok no existing user, add it from scratch */
1775 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1776 netbios_name, in, NULL);
1779 /* check user is what we are looking for */
1780 uac = ldb_msg_find_attr_as_uint(msgs[0],
1781 "userAccountControl", 0);
1782 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1783 return NT_STATUS_OBJECT_NAME_COLLISION;
1787 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1790 return NT_STATUS_OK;
1791 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1792 return NT_STATUS_ACCESS_DENIED;
1794 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1798 /* entry exists, just modify secret if any */
1799 if (in == NULL || in->count == 0) {
1800 return NT_STATUS_OK;
1803 msg = ldb_msg_new(mem_ctx);
1805 return NT_STATUS_NO_MEMORY;
1807 msg->dn = msgs[0]->dn;
1809 for (i = 0; i < in->count; i++) {
1810 const char *attribute;
1812 switch (in->current.array[i].AuthType) {
1813 case TRUST_AUTH_TYPE_NT4OWF:
1814 attribute = "unicodePwd";
1815 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1818 case TRUST_AUTH_TYPE_CLEAR:
1819 attribute = "clearTextPassword";
1820 v.data = in->current.array[i].AuthInfo.clear.password;
1821 v.length = in->current.array[i].AuthInfo.clear.size;
1827 ret = ldb_msg_add_empty(msg, attribute,
1828 LDB_FLAG_MOD_REPLACE, NULL);
1829 if (ret != LDB_SUCCESS) {
1830 return NT_STATUS_NO_MEMORY;
1833 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1834 if (ret != LDB_SUCCESS) {
1835 return NT_STATUS_NO_MEMORY;
1839 /* create the trusted_domain user account */
1840 ret = ldb_modify(sam_ldb, msg);
1841 if (ret != LDB_SUCCESS) {
1842 DEBUG(0,("Failed to create user record %s: %s\n",
1843 ldb_dn_get_linearized(msg->dn),
1844 ldb_errstring(sam_ldb)));
1847 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1848 return NT_STATUS_DOMAIN_EXISTS;
1849 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1850 return NT_STATUS_ACCESS_DENIED;
1852 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1856 return NT_STATUS_OK;
1860 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1861 struct lsa_policy_state *p_state,
1862 TALLOC_CTX *mem_ctx,
1863 struct ldb_message *dom_msg,
1864 enum lsa_TrustDomInfoEnum level,
1865 union lsa_TrustedDomainInfo *info)
1867 uint32_t *posix_offset = NULL;
1868 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1869 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1870 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1871 uint32_t *enc_types = NULL;
1872 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1873 struct trustDomainPasswords auth_struct;
1874 struct trustAuthInOutBlob *current_passwords = NULL;
1876 struct ldb_message **msgs;
1877 struct ldb_message *msg;
1878 bool add_outgoing = false;
1879 bool add_incoming = false;
1880 bool del_outgoing = false;
1881 bool del_incoming = false;
1882 bool del_forest_info = false;
1883 bool in_transaction = false;
1888 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1889 posix_offset = &info->posix_offset.posix_offset;
1891 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1892 info_ex = &info->info_ex;
1894 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1895 auth_info = &info->auth_info;
1897 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1898 posix_offset = &info->full_info.posix_offset.posix_offset;
1899 info_ex = &info->full_info.info_ex;
1900 auth_info = &info->full_info.auth_info;
1902 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1903 auth_info_int = &info->auth_info_internal;
1905 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1906 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1907 info_ex = &info->full_info_internal.info_ex;
1908 auth_info_int = &info->full_info_internal.auth_info;
1910 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1911 enc_types = &info->enc_types.enc_types;
1914 return NT_STATUS_INVALID_PARAMETER;
1918 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1920 &trustAuthOutgoing);
1921 if (!NT_STATUS_IS_OK(nt_status)) {
1924 if (trustAuthIncoming.data) {
1925 /* This does the decode of some of this twice, but it is easier that way */
1926 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1927 auth_info->incoming_count,
1928 auth_info->incoming_current_auth_info,
1930 ¤t_passwords);
1931 if (!NT_STATUS_IS_OK(nt_status)) {
1937 /* decode auth_info_int if set */
1938 if (auth_info_int) {
1940 /* now decrypt blob */
1941 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1942 auth_info_int->auth_blob.size);
1944 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1945 &auth_blob, &auth_struct);
1946 if (!NT_STATUS_IS_OK(nt_status)) {
1952 /* verify data matches */
1953 if (info_ex->trust_attributes &
1954 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1955 /* TODO: check what behavior level we have */
1956 if (strcasecmp_m(p_state->domain_dns,
1957 p_state->forest_dns) != 0) {
1958 return NT_STATUS_INVALID_DOMAIN_STATE;
1962 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1963 if (ret == LDB_SUCCESS && am_rodc) {
1964 return NT_STATUS_NO_SUCH_DOMAIN;
1967 /* verify only one object matches the dns/netbios/sid
1968 * triplet and that this is the one we already have */
1969 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1971 info_ex->domain_name.string,
1972 info_ex->netbios_name.string,
1973 info_ex->sid, &msgs);
1974 if (!NT_STATUS_IS_OK(nt_status)) {
1977 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1978 return NT_STATUS_OBJECT_NAME_COLLISION;
1983 /* TODO: should we fetch previous values from the existing entry
1984 * and append them ? */
1985 if (auth_info_int && auth_struct.incoming.count) {
1986 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1987 &auth_struct.incoming,
1988 &trustAuthIncoming);
1989 if (!NT_STATUS_IS_OK(nt_status)) {
1993 current_passwords = &auth_struct.incoming;
1996 trustAuthIncoming = data_blob(NULL, 0);
1999 if (auth_info_int && auth_struct.outgoing.count) {
2000 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
2001 &auth_struct.outgoing,
2002 &trustAuthOutgoing);
2003 if (!NT_STATUS_IS_OK(nt_status)) {
2007 trustAuthOutgoing = data_blob(NULL, 0);
2010 msg = ldb_msg_new(mem_ctx);
2012 return NT_STATUS_NO_MEMORY;
2014 msg->dn = dom_msg->dn;
2017 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2020 *posix_offset, NULL);
2021 if (!NT_STATUS_IS_OK(nt_status)) {
2028 uint32_t changed_attrs;
2032 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2035 info_ex->trust_direction,
2037 if (!NT_STATUS_IS_OK(nt_status)) {
2041 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2042 if (auth_info != NULL && trustAuthIncoming.length > 0) {
2043 add_incoming = true;
2046 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2047 if (auth_info != NULL && trustAuthOutgoing.length > 0) {
2048 add_outgoing = true;
2052 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
2053 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
2054 del_incoming = true;
2056 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
2057 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2058 del_outgoing = true;
2061 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
2062 if (origtype == -1 || origtype != info_ex->trust_type) {
2063 DEBUG(1, ("Attempted to change trust type! "
2064 "Operation not handled\n"));
2065 return NT_STATUS_INVALID_PARAMETER;
2068 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2071 info_ex->trust_attributes,
2073 if (!NT_STATUS_IS_OK(nt_status)) {
2076 /* TODO: check forestFunctionality from ldb opaque */
2077 /* TODO: check what is set makes sense */
2079 changed_attrs = origattrs ^ info_ex->trust_attributes;
2080 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2082 * For now we only allow
2083 * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
2085 * TODO: we may need to support more attribute changes
2087 DEBUG(1, ("Attempted to change trust attributes "
2088 "(0x%08x != 0x%08x)! "
2089 "Operation not handled yet...\n",
2090 (unsigned)origattrs,
2091 (unsigned)info_ex->trust_attributes));
2092 return NT_STATUS_INVALID_PARAMETER;
2095 if (!(info_ex->trust_attributes &
2096 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
2098 struct ldb_message_element *orig_forest_el = NULL;
2100 orig_forest_el = ldb_msg_find_element(dom_msg,
2101 "msDS-TrustForestTrustInfo");
2102 if (orig_forest_el != NULL) {
2103 del_forest_info = true;
2109 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2111 "msDS-SupportedEncryptionTypes",
2113 if (!NT_STATUS_IS_OK(nt_status)) {
2118 if (add_incoming || del_incoming) {
2119 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
2120 LDB_FLAG_MOD_REPLACE, NULL);
2121 if (ret != LDB_SUCCESS) {
2122 return NT_STATUS_NO_MEMORY;
2125 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
2126 &trustAuthIncoming, NULL);
2127 if (ret != LDB_SUCCESS) {
2128 return NT_STATUS_NO_MEMORY;
2132 if (add_outgoing || del_outgoing) {
2133 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2134 LDB_FLAG_MOD_REPLACE, NULL);
2135 if (ret != LDB_SUCCESS) {
2136 return NT_STATUS_NO_MEMORY;
2139 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
2140 &trustAuthOutgoing, NULL);
2141 if (ret != LDB_SUCCESS) {
2142 return NT_STATUS_NO_MEMORY;
2146 if (del_forest_info) {
2147 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
2148 LDB_FLAG_MOD_REPLACE, NULL);
2149 if (ret != LDB_SUCCESS) {
2150 return NT_STATUS_NO_MEMORY;
2154 /* start transaction */
2155 ret = ldb_transaction_start(p_state->sam_ldb);
2156 if (ret != LDB_SUCCESS) {
2157 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2159 in_transaction = true;
2161 if (msg->num_elements) {
2162 ret = ldb_modify(p_state->sam_ldb, msg);
2163 if (ret != LDB_SUCCESS) {
2164 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
2165 ldb_dn_get_linearized(msg->dn),
2166 ldb_errstring(p_state->sam_ldb)));
2167 nt_status = dsdb_ldb_err_to_ntstatus(ret);
2172 if (add_incoming || del_incoming) {
2173 const char *netbios_name;
2175 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
2177 if (!netbios_name) {
2178 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
2182 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
2183 nt_status = update_trust_user(mem_ctx,
2189 if (!NT_STATUS_IS_OK(nt_status)) {
2194 /* ok, all fine, commit transaction and return */
2195 ret = ldb_transaction_commit(p_state->sam_ldb);
2196 if (ret != LDB_SUCCESS) {
2197 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2199 in_transaction = false;
2201 nt_status = NT_STATUS_OK;
2204 if (in_transaction) {
2205 ldb_transaction_cancel(p_state->sam_ldb);
2211 lsa_SetInfomrationTrustedDomain
2213 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
2214 struct dcesrv_call_state *dce_call,
2215 TALLOC_CTX *mem_ctx,
2216 struct lsa_SetInformationTrustedDomain *r)
2218 struct dcesrv_handle *h;
2219 struct lsa_trusted_domain_state *td_state;
2220 struct ldb_message **msgs;
2223 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
2224 LSA_HANDLE_TRUSTED_DOMAIN);
2226 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2228 /* get the trusted domain object */
2229 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
2230 td_state->trusted_domain_dn,
2231 NULL, NULL, NULL, &msgs);
2232 if (!NT_STATUS_IS_OK(nt_status)) {
2233 if (NT_STATUS_EQUAL(nt_status,
2234 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2237 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2240 return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
2241 msgs[0], r->in.level, r->in.info);
2246 lsa_DeleteTrustedDomain
2248 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2249 struct lsa_DeleteTrustedDomain *r)
2252 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2253 struct lsa_DeleteObject del;
2254 struct dcesrv_handle *h;
2256 opn.in.handle = r->in.handle;
2257 opn.in.sid = r->in.dom_sid;
2258 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2259 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2260 if (!opn.out.trustdom_handle) {
2261 return NT_STATUS_NO_MEMORY;
2263 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2264 if (!NT_STATUS_IS_OK(status)) {
2268 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2269 talloc_steal(mem_ctx, h);
2271 del.in.handle = opn.out.trustdom_handle;
2272 del.out.handle = opn.out.trustdom_handle;
2273 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2274 if (!NT_STATUS_IS_OK(status)) {
2277 return NT_STATUS_OK;
2280 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2281 struct ldb_message *msg,
2282 struct lsa_TrustDomainInfoInfoEx *info_ex)
2284 info_ex->domain_name.string
2285 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2286 info_ex->netbios_name.string
2287 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2289 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2290 info_ex->trust_direction
2291 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2293 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2294 info_ex->trust_attributes
2295 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2296 return NT_STATUS_OK;
2300 lsa_QueryTrustedDomainInfo
2302 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2303 struct lsa_QueryTrustedDomainInfo *r)
2305 union lsa_TrustedDomainInfo *info = NULL;
2306 struct dcesrv_handle *h;
2307 struct lsa_trusted_domain_state *trusted_domain_state;
2308 struct ldb_message *msg;
2310 struct ldb_message **res;
2311 const char *attrs[] = {
2314 "securityIdentifier",
2318 "msDs-supportedEncryptionTypes",
2322 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2324 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2326 /* pull all the user attributes */
2327 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2328 trusted_domain_state->trusted_domain_dn, &res, attrs);
2330 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2334 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2336 return NT_STATUS_NO_MEMORY;
2338 *r->out.info = info;
2340 switch (r->in.level) {
2341 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2342 info->name.netbios_name.string
2343 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2345 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2346 info->posix_offset.posix_offset
2347 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2349 #if 0 /* Win2k3 doesn't implement this */
2350 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2351 r->out.info->info_basic.netbios_name.string
2352 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2353 r->out.info->info_basic.sid
2354 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2357 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2358 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2360 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2361 ZERO_STRUCT(info->full_info);
2362 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2363 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2364 ZERO_STRUCT(info->full_info2_internal);
2365 info->full_info2_internal.posix_offset.posix_offset
2366 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2367 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2369 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2370 info->enc_types.enc_types
2371 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2374 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2375 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2376 /* oops, we don't want to return the info after all */
2378 *r->out.info = NULL;
2379 return NT_STATUS_INVALID_PARAMETER;
2381 /* oops, we don't want to return the info after all */
2383 *r->out.info = NULL;
2384 return NT_STATUS_INVALID_INFO_CLASS;
2387 return NT_STATUS_OK;
2392 lsa_QueryTrustedDomainInfoBySid
2394 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2395 struct lsa_QueryTrustedDomainInfoBySid *r)
2398 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2399 struct lsa_QueryTrustedDomainInfo query;
2400 struct dcesrv_handle *h;
2402 opn.in.handle = r->in.handle;
2403 opn.in.sid = r->in.dom_sid;
2404 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2405 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2406 if (!opn.out.trustdom_handle) {
2407 return NT_STATUS_NO_MEMORY;
2409 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2410 if (!NT_STATUS_IS_OK(status)) {
2414 /* Ensure this handle goes away at the end of this call */
2415 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2416 talloc_steal(mem_ctx, h);
2418 query.in.trustdom_handle = opn.out.trustdom_handle;
2419 query.in.level = r->in.level;
2420 query.out.info = r->out.info;
2421 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2422 if (!NT_STATUS_IS_OK(status)) {
2426 return NT_STATUS_OK;
2430 lsa_SetTrustedDomainInfoByName
2432 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2433 TALLOC_CTX *mem_ctx,
2434 struct lsa_SetTrustedDomainInfoByName *r)
2436 struct dcesrv_handle *policy_handle;
2437 struct lsa_policy_state *policy_state;
2438 struct ldb_message **msgs;
2441 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2442 policy_state = policy_handle->data;
2444 /* get the trusted domain object */
2445 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2446 policy_state->domain_dn,
2447 r->in.trusted_domain->string,
2448 r->in.trusted_domain->string,
2450 if (!NT_STATUS_IS_OK(nt_status)) {
2451 if (NT_STATUS_EQUAL(nt_status,
2452 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2455 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2458 return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2459 msgs[0], r->in.level, r->in.info);
2463 lsa_QueryTrustedDomainInfoByName
2465 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2466 TALLOC_CTX *mem_ctx,
2467 struct lsa_QueryTrustedDomainInfoByName *r)
2470 struct lsa_OpenTrustedDomainByName opn = {{0},{0}};
2471 struct lsa_QueryTrustedDomainInfo query;
2472 struct dcesrv_handle *h;
2474 opn.in.handle = r->in.handle;
2475 opn.in.name = *r->in.trusted_domain;
2476 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2477 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2478 if (!opn.out.trustdom_handle) {
2479 return NT_STATUS_NO_MEMORY;
2481 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2482 if (!NT_STATUS_IS_OK(status)) {
2486 /* Ensure this handle goes away at the end of this call */
2487 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2488 talloc_steal(mem_ctx, h);
2490 query.in.trustdom_handle = opn.out.trustdom_handle;
2491 query.in.level = r->in.level;
2492 query.out.info = r->out.info;
2493 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2494 if (!NT_STATUS_IS_OK(status)) {
2498 return NT_STATUS_OK;
2502 lsa_CloseTrustedDomainEx
2504 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2505 TALLOC_CTX *mem_ctx,
2506 struct lsa_CloseTrustedDomainEx *r)
2508 /* The result of a bad hair day from an IDL programmer? Not
2509 * implmented in Win2k3. You should always just lsa_Close
2511 return NT_STATUS_NOT_IMPLEMENTED;
2516 comparison function for sorting lsa_DomainInformation array
2518 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2520 return strcasecmp_m(e1->name.string, e2->name.string);
2526 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2527 struct lsa_EnumTrustDom *r)
2529 struct dcesrv_handle *policy_handle;
2530 struct lsa_DomainInfo *entries;
2531 struct lsa_policy_state *policy_state;
2532 struct ldb_message **domains;
2533 const char *attrs[] = {
2535 "securityIdentifier",
2542 *r->out.resume_handle = 0;
2544 r->out.domains->domains = NULL;
2545 r->out.domains->count = 0;
2547 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2549 policy_state = policy_handle->data;
2551 /* search for all users in this domain. This could possibly be cached and
2552 resumed based on resume_key */
2553 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2554 "objectclass=trustedDomain");
2556 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2559 /* convert to lsa_TrustInformation format */
2560 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2562 return NT_STATUS_NO_MEMORY;
2564 for (i=0;i<count;i++) {
2565 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2566 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2569 /* sort the results by name */
2570 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2572 if (*r->in.resume_handle >= count) {
2573 *r->out.resume_handle = -1;
2575 return NT_STATUS_NO_MORE_ENTRIES;
2578 /* return the rest, limit by max_size. Note that we
2579 use the w2k3 element size value of 60 */
2580 r->out.domains->count = count - *r->in.resume_handle;
2581 r->out.domains->count = MIN(r->out.domains->count,
2582 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2584 r->out.domains->domains = entries + *r->in.resume_handle;
2585 r->out.domains->count = r->out.domains->count;
2587 if (r->out.domains->count < count - *r->in.resume_handle) {
2588 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2589 return STATUS_MORE_ENTRIES;
2592 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2593 * always be larger than the previous input resume handle, in
2594 * particular when hitting the last query it is vital to set the
2595 * resume handle correctly to avoid infinite client loops, as
2596 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2597 * status is NT_STATUS_OK - gd */
2599 *r->out.resume_handle = (uint32_t)-1;
2601 return NT_STATUS_OK;
2605 comparison function for sorting lsa_DomainInformation array
2607 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2609 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2613 lsa_EnumTrustedDomainsEx
2615 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2616 struct lsa_EnumTrustedDomainsEx *r)
2618 struct dcesrv_handle *policy_handle;
2619 struct lsa_TrustDomainInfoInfoEx *entries;
2620 struct lsa_policy_state *policy_state;
2621 struct ldb_message **domains;
2622 const char *attrs[] = {
2625 "securityIdentifier",
2635 *r->out.resume_handle = 0;
2637 r->out.domains->domains = NULL;
2638 r->out.domains->count = 0;
2640 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2642 policy_state = policy_handle->data;
2644 /* search for all users in this domain. This could possibly be cached and
2645 resumed based on resume_key */
2646 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2647 "objectclass=trustedDomain");
2649 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2652 /* convert to lsa_DomainInformation format */
2653 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2655 return NT_STATUS_NO_MEMORY;
2657 for (i=0;i<count;i++) {
2658 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2659 if (!NT_STATUS_IS_OK(nt_status)) {
2664 /* sort the results by name */
2665 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2667 if (*r->in.resume_handle >= count) {
2668 *r->out.resume_handle = -1;
2670 return NT_STATUS_NO_MORE_ENTRIES;
2673 /* return the rest, limit by max_size. Note that we
2674 use the w2k3 element size value of 60 */
2675 r->out.domains->count = count - *r->in.resume_handle;
2676 r->out.domains->count = MIN(r->out.domains->count,
2677 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2679 r->out.domains->domains = entries + *r->in.resume_handle;
2680 r->out.domains->count = r->out.domains->count;
2682 if (r->out.domains->count < count - *r->in.resume_handle) {
2683 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2684 return STATUS_MORE_ENTRIES;
2687 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2689 return NT_STATUS_OK;
2696 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2697 struct lsa_OpenAccount *r)
2699 struct dcesrv_handle *h, *ah;
2700 struct lsa_policy_state *state;
2701 struct lsa_account_state *astate;
2703 ZERO_STRUCTP(r->out.acct_handle);
2705 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2709 astate = talloc(dce_call->conn, struct lsa_account_state);
2710 if (astate == NULL) {
2711 return NT_STATUS_NO_MEMORY;
2714 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2715 if (astate->account_sid == NULL) {
2716 talloc_free(astate);
2717 return NT_STATUS_NO_MEMORY;
2720 astate->policy = talloc_reference(astate, state);
2721 astate->access_mask = r->in.access_mask;
2724 * For now we grant all requested access.
2726 * We will fail at the ldb layer later.
2728 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2729 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2730 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2732 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2734 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2735 __func__, dom_sid_string(mem_ctx, astate->account_sid),
2736 (unsigned)r->in.access_mask,
2737 (unsigned)astate->access_mask));
2739 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2741 talloc_free(astate);
2742 return NT_STATUS_NO_MEMORY;
2745 ah->data = talloc_steal(ah, astate);
2747 *r->out.acct_handle = ah->wire_handle;
2749 return NT_STATUS_OK;
2754 lsa_EnumPrivsAccount
2756 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2757 TALLOC_CTX *mem_ctx,
2758 struct lsa_EnumPrivsAccount *r)
2760 struct dcesrv_handle *h;
2761 struct lsa_account_state *astate;
2764 struct ldb_message **res;
2765 const char * const attrs[] = { "privilege", NULL};
2766 struct ldb_message_element *el;
2768 struct lsa_PrivilegeSet *privs;
2770 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2774 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2775 if (privs == NULL) {
2776 return NT_STATUS_NO_MEMORY;
2782 *r->out.privs = privs;
2784 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2785 if (sidstr == NULL) {
2786 return NT_STATUS_NO_MEMORY;
2789 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2790 "objectSid=%s", sidstr);
2792 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2795 return NT_STATUS_OK;
2798 el = ldb_msg_find_element(res[0], "privilege");
2799 if (el == NULL || el->num_values == 0) {
2800 return NT_STATUS_OK;
2803 privs->set = talloc_array(privs,
2804 struct lsa_LUIDAttribute, el->num_values);
2805 if (privs->set == NULL) {
2806 return NT_STATUS_NO_MEMORY;
2810 for (i=0;i<el->num_values;i++) {
2811 int id = sec_privilege_id((const char *)el->values[i].data);
2812 if (id == SEC_PRIV_INVALID) {
2813 /* Perhaps an account right, not a privilege */
2816 privs->set[j].attribute = 0;
2817 privs->set[j].luid.low = id;
2818 privs->set[j].luid.high = 0;
2824 return NT_STATUS_OK;
2828 lsa_EnumAccountRights
2830 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2831 TALLOC_CTX *mem_ctx,
2832 struct lsa_EnumAccountRights *r)
2834 struct dcesrv_handle *h;
2835 struct lsa_policy_state *state;
2838 struct ldb_message **res;
2839 const char * const attrs[] = { "privilege", NULL};
2841 struct ldb_message_element *el;
2843 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2847 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2848 if (sidstr == NULL) {
2849 return NT_STATUS_NO_MEMORY;
2852 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2853 "(&(objectSid=%s)(privilege=*))", sidstr);
2855 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2858 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2859 dom_sid_string(mem_ctx, r->in.sid),
2860 ldb_errstring(state->pdb)));
2861 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2864 el = ldb_msg_find_element(res[0], "privilege");
2865 if (el == NULL || el->num_values == 0) {
2866 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2869 r->out.rights->count = el->num_values;
2870 r->out.rights->names = talloc_array(r->out.rights,
2871 struct lsa_StringLarge, r->out.rights->count);
2872 if (r->out.rights->names == NULL) {
2873 return NT_STATUS_NO_MEMORY;
2876 for (i=0;i<el->num_values;i++) {
2877 r->out.rights->names[i].string = (const char *)el->values[i].data;
2880 return NT_STATUS_OK;
2886 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2888 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2889 TALLOC_CTX *mem_ctx,
2890 struct lsa_policy_state *state,
2892 struct dom_sid *sid,
2893 const struct lsa_RightSet *rights)
2895 const char *sidstr, *sidndrstr;
2896 struct ldb_message *msg;
2897 struct ldb_message_element *el;
2900 struct lsa_EnumAccountRights r2;
2903 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2904 SECURITY_ADMINISTRATOR) {
2905 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2906 return NT_STATUS_ACCESS_DENIED;
2909 msg = ldb_msg_new(mem_ctx);
2911 return NT_STATUS_NO_MEMORY;
2914 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2915 if (sidndrstr == NULL) {
2917 return NT_STATUS_NO_MEMORY;
2920 sidstr = dom_sid_string(msg, sid);
2921 if (sidstr == NULL) {
2923 return NT_STATUS_NO_MEMORY;
2926 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2927 if (dnstr == NULL) {
2929 return NT_STATUS_NO_MEMORY;
2932 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2933 if (msg->dn == NULL) {
2935 return NT_STATUS_NO_MEMORY;
2938 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2941 r2.in.handle = &state->handle->wire_handle;
2943 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2945 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2946 if (!NT_STATUS_IS_OK(status)) {
2947 ZERO_STRUCTP(r2.out.rights);
2951 for (i=0;i<rights->count;i++) {
2952 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2953 if (sec_right_bit(rights->names[i].string) == 0) {
2955 return NT_STATUS_NO_SUCH_PRIVILEGE;
2959 return NT_STATUS_NO_SUCH_PRIVILEGE;
2962 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2964 for (j=0;j<r2.out.rights->count;j++) {
2965 if (strcasecmp_m(r2.out.rights->names[j].string,
2966 rights->names[i].string) == 0) {
2970 if (j != r2.out.rights->count) continue;
2973 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2974 if (ret != LDB_SUCCESS) {
2976 return NT_STATUS_NO_MEMORY;
2980 el = ldb_msg_find_element(msg, "privilege");
2983 return NT_STATUS_OK;
2986 el->flags = ldb_flag;
2988 ret = ldb_modify(state->pdb, msg);
2989 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2990 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2992 return NT_STATUS_NO_MEMORY;
2994 ldb_msg_add_string(msg, "comment", "added via LSA");
2995 ret = ldb_add(state->pdb, msg);
2997 if (ret != LDB_SUCCESS) {
2998 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
3000 return NT_STATUS_OK;
3002 DEBUG(3, ("Could not %s attributes from %s: %s",
3003 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
3004 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
3006 return NT_STATUS_UNEXPECTED_IO_ERROR;
3010 return NT_STATUS_OK;
3014 lsa_AddPrivilegesToAccount
3016 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3017 struct lsa_AddPrivilegesToAccount *r)
3019 struct lsa_RightSet rights;
3020 struct dcesrv_handle *h;
3021 struct lsa_account_state *astate;
3024 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3028 rights.count = r->in.privs->count;
3029 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
3030 if (rights.names == NULL) {
3031 return NT_STATUS_NO_MEMORY;
3033 for (i=0;i<rights.count;i++) {
3034 int id = r->in.privs->set[i].luid.low;
3035 if (r->in.privs->set[i].luid.high) {
3036 return NT_STATUS_NO_SUCH_PRIVILEGE;
3038 rights.names[i].string = sec_privilege_name(id);
3039 if (rights.names[i].string == NULL) {
3040 return NT_STATUS_NO_SUCH_PRIVILEGE;
3044 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3045 LDB_FLAG_MOD_ADD, astate->account_sid,
3051 lsa_RemovePrivilegesFromAccount
3053 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3054 struct lsa_RemovePrivilegesFromAccount *r)
3056 struct lsa_RightSet *rights;
3057 struct dcesrv_handle *h;
3058 struct lsa_account_state *astate;
3061 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3065 rights = talloc(mem_ctx, struct lsa_RightSet);
3067 if (r->in.remove_all == 1 &&
3068 r->in.privs == NULL) {
3069 struct lsa_EnumAccountRights r2;
3072 r2.in.handle = &astate->policy->handle->wire_handle;
3073 r2.in.sid = astate->account_sid;
3074 r2.out.rights = rights;
3076 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
3077 if (!NT_STATUS_IS_OK(status)) {
3081 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3082 LDB_FLAG_MOD_DELETE, astate->account_sid,
3086 if (r->in.remove_all != 0) {
3087 return NT_STATUS_INVALID_PARAMETER;
3090 rights->count = r->in.privs->count;
3091 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
3092 if (rights->names == NULL) {
3093 return NT_STATUS_NO_MEMORY;
3095 for (i=0;i<rights->count;i++) {
3096 int id = r->in.privs->set[i].luid.low;
3097 if (r->in.privs->set[i].luid.high) {
3098 return NT_STATUS_NO_SUCH_PRIVILEGE;
3100 rights->names[i].string = sec_privilege_name(id);
3101 if (rights->names[i].string == NULL) {
3102 return NT_STATUS_NO_SUCH_PRIVILEGE;
3106 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3107 LDB_FLAG_MOD_DELETE, astate->account_sid,
3113 lsa_GetQuotasForAccount
3115 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3116 struct lsa_GetQuotasForAccount *r)
3118 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3123 lsa_SetQuotasForAccount
3125 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3126 struct lsa_SetQuotasForAccount *r)
3128 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3133 lsa_GetSystemAccessAccount
3135 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3136 struct lsa_GetSystemAccessAccount *r)
3138 struct dcesrv_handle *h;
3139 struct lsa_account_state *astate;
3142 struct ldb_message **res;
3143 const char * const attrs[] = { "privilege", NULL};
3144 struct ldb_message_element *el;
3147 *(r->out.access_mask) = 0x00000000;
3149 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3153 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
3154 if (sidstr == NULL) {
3155 return NT_STATUS_NO_MEMORY;
3158 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
3159 "objectSid=%s", sidstr);
3161 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3164 return NT_STATUS_OK;
3167 el = ldb_msg_find_element(res[0], "privilege");
3168 if (el == NULL || el->num_values == 0) {
3169 return NT_STATUS_OK;
3172 for (i=0;i<el->num_values;i++) {
3173 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
3174 if (right_bit == 0) {
3175 /* Perhaps an privilege, not a right */
3178 *(r->out.access_mask) |= right_bit;
3181 return NT_STATUS_OK;
3186 lsa_SetSystemAccessAccount
3188 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3189 struct lsa_SetSystemAccessAccount *r)
3191 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3198 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3199 struct lsa_CreateSecret *r)
3201 struct dcesrv_handle *policy_handle;
3202 struct lsa_policy_state *policy_state;
3203 struct lsa_secret_state *secret_state;
3204 struct dcesrv_handle *handle;
3205 struct ldb_message **msgs, *msg;
3206 const char *attrs[] = {
3214 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3215 ZERO_STRUCTP(r->out.sec_handle);
3217 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3219 case SECURITY_SYSTEM:
3220 case SECURITY_ADMINISTRATOR:
3223 /* Users and annonymous are not allowed create secrets */
3224 return NT_STATUS_ACCESS_DENIED;
3227 policy_state = policy_handle->data;
3229 if (!r->in.name.string) {
3230 return NT_STATUS_INVALID_PARAMETER;
3233 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3234 NT_STATUS_HAVE_NO_MEMORY(secret_state);
3235 secret_state->policy = policy_state;
3237 msg = ldb_msg_new(mem_ctx);
3239 return NT_STATUS_NO_MEMORY;
3242 if (strncmp("G$", r->in.name.string, 2) == 0) {
3245 secret_state->global = true;
3247 name = &r->in.name.string[2];
3248 if (strlen(name) == 0) {
3249 return NT_STATUS_INVALID_PARAMETER;
3252 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3253 ldb_binary_encode_string(mem_ctx, name));
3254 NT_STATUS_HAVE_NO_MEMORY(name2);
3256 /* We need to connect to the database as system, as this is one
3257 * of the rare RPC calls that must read the secrets (and this
3258 * is denied otherwise) */
3259 secret_state->sam_ldb = talloc_reference(secret_state,
3260 samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
3261 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3263 /* search for the secret record */
3264 ret = gendb_search(secret_state->sam_ldb,
3265 mem_ctx, policy_state->system_dn, &msgs, attrs,
3266 "(&(cn=%s)(objectclass=secret))",
3269 return NT_STATUS_OBJECT_NAME_COLLISION;
3273 DEBUG(0,("Failure searching for CN=%s: %s\n",
3274 name2, ldb_errstring(secret_state->sam_ldb)));
3275 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3278 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3279 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3280 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3281 return NT_STATUS_NO_MEMORY;
3284 ret = ldb_msg_add_string(msg, "cn", name2);
3285 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3287 secret_state->global = false;
3289 name = r->in.name.string;
3290 if (strlen(name) == 0) {
3291 return NT_STATUS_INVALID_PARAMETER;
3294 secret_state->sam_ldb = talloc_reference(secret_state,
3295 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3296 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3298 /* search for the secret record */
3299 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3300 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3302 "(&(cn=%s)(objectclass=secret))",
3303 ldb_binary_encode_string(mem_ctx, name));
3305 return NT_STATUS_OBJECT_NAME_COLLISION;
3309 DEBUG(0,("Failure searching for CN=%s: %s\n",
3310 name, ldb_errstring(secret_state->sam_ldb)));
3311 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3314 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3315 "cn=%s,cn=LSA Secrets", name);
3316 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3317 ret = ldb_msg_add_string(msg, "cn", name);
3318 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3321 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3322 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3324 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3325 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3327 /* create the secret */
3328 ret = ldb_add(secret_state->sam_ldb, msg);
3329 if (ret != LDB_SUCCESS) {
3330 DEBUG(0,("Failed to create secret record %s: %s\n",
3331 ldb_dn_get_linearized(msg->dn),
3332 ldb_errstring(secret_state->sam_ldb)));
3333 return NT_STATUS_ACCESS_DENIED;
3336 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3337 NT_STATUS_HAVE_NO_MEMORY(handle);
3339 handle->data = talloc_steal(handle, secret_state);
3341 secret_state->access_mask = r->in.access_mask;
3342 secret_state->policy = talloc_reference(secret_state, policy_state);
3343 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3345 *r->out.sec_handle = handle->wire_handle;
3347 return NT_STATUS_OK;
3354 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3355 struct lsa_OpenSecret *r)
3357 struct dcesrv_handle *policy_handle;
3359 struct lsa_policy_state *policy_state;
3360 struct lsa_secret_state *secret_state;
3361 struct dcesrv_handle *handle;
3362 struct ldb_message **msgs;
3363 const char *attrs[] = {
3371 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3372 ZERO_STRUCTP(r->out.sec_handle);
3373 policy_state = policy_handle->data;
3375 if (!r->in.name.string) {
3376 return NT_STATUS_INVALID_PARAMETER;
3379 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3381 case SECURITY_SYSTEM:
3382 case SECURITY_ADMINISTRATOR:
3385 /* Users and annonymous are not allowed to access secrets */
3386 return NT_STATUS_ACCESS_DENIED;
3389 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3390 if (!secret_state) {
3391 return NT_STATUS_NO_MEMORY;
3393 secret_state->policy = policy_state;
3395 if (strncmp("G$", r->in.name.string, 2) == 0) {
3396 name = &r->in.name.string[2];
3397 /* 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) */
3398 secret_state->sam_ldb = talloc_reference(secret_state,
3399 samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
3400 secret_state->global = true;
3402 if (strlen(name) < 1) {
3403 return NT_STATUS_INVALID_PARAMETER;
3406 /* search for the secret record */
3407 ret = gendb_search(secret_state->sam_ldb,
3408 mem_ctx, policy_state->system_dn, &msgs, attrs,
3409 "(&(cn=%s Secret)(objectclass=secret))",
3410 ldb_binary_encode_string(mem_ctx, name));
3412 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3416 DEBUG(0,("Found %d records matching DN %s\n", ret,
3417 ldb_dn_get_linearized(policy_state->system_dn)));
3418 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3421 secret_state->global = false;
3422 secret_state->sam_ldb = talloc_reference(secret_state,
3423 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3425 name = r->in.name.string;
3426 if (strlen(name) < 1) {
3427 return NT_STATUS_INVALID_PARAMETER;
3430 /* search for the secret record */
3431 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3432 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3434 "(&(cn=%s)(objectclass=secret))",
3435 ldb_binary_encode_string(mem_ctx, name));
3437 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3441 DEBUG(0,("Found %d records matching CN=%s\n",
3442 ret, ldb_binary_encode_string(mem_ctx, name)));
3443 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3447 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3449 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3451 return NT_STATUS_NO_MEMORY;
3454 handle->data = talloc_steal(handle, secret_state);
3456 secret_state->access_mask = r->in.access_mask;
3457 secret_state->policy = talloc_reference(secret_state, policy_state);
3459 *r->out.sec_handle = handle->wire_handle;
3461 return NT_STATUS_OK;
3468 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3469 struct lsa_SetSecret *r)
3472 struct dcesrv_handle *h;
3473 struct lsa_secret_state *secret_state;
3474 struct ldb_message *msg;
3475 DATA_BLOB session_key;
3476 DATA_BLOB crypt_secret, secret;
3479 NTSTATUS status = NT_STATUS_OK;
3481 struct timeval now = timeval_current();
3482 NTTIME nt_now = timeval_to_nttime(&now);
3484 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3486 secret_state = h->data;
3488 msg = ldb_msg_new(mem_ctx);
3490 return NT_STATUS_NO_MEMORY;
3493 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3495 return NT_STATUS_NO_MEMORY;
3497 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3498 if (!NT_STATUS_IS_OK(status)) {
3502 if (r->in.old_val) {
3504 crypt_secret.data = r->in.old_val->data;
3505 crypt_secret.length = r->in.old_val->size;
3507 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3508 if (!NT_STATUS_IS_OK(status)) {
3512 val.data = secret.data;
3513 val.length = secret.length;
3516 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3517 return NT_STATUS_NO_MEMORY;
3520 /* set old value mtime */
3521 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3522 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3523 return NT_STATUS_NO_MEMORY;
3527 /* If the old value is not set, then migrate the
3528 * current value to the old value */
3529 const struct ldb_val *old_val;
3530 NTTIME last_set_time;
3531 struct ldb_message **res;
3532 const char *attrs[] = {
3538 /* search for the secret record */
3539 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3540 secret_state->secret_dn, &res, attrs);
3542 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3546 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3547 ldb_dn_get_linearized(secret_state->secret_dn)));
3548 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3551 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3552 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3556 if (ldb_msg_add_value(msg, "priorValue",
3557 old_val, NULL) != LDB_SUCCESS) {
3558 return NT_STATUS_NO_MEMORY;
3561 if (samdb_msg_add_delete(secret_state->sam_ldb,
3562 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3563 return NT_STATUS_NO_MEMORY;
3567 /* set old value mtime */
3568 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3569 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3570 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3571 return NT_STATUS_NO_MEMORY;
3574 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3575 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3576 return NT_STATUS_NO_MEMORY;
3581 if (r->in.new_val) {
3583 crypt_secret.data = r->in.new_val->data;
3584 crypt_secret.length = r->in.new_val->size;
3586 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3587 if (!NT_STATUS_IS_OK(status)) {
3591 val.data = secret.data;
3592 val.length = secret.length;
3595 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3596 return NT_STATUS_NO_MEMORY;
3599 /* set new value mtime */
3600 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3601 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3602 return NT_STATUS_NO_MEMORY;
3605 /* NULL out the NEW value */
3606 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3607 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3608 return NT_STATUS_NO_MEMORY;
3610 if (samdb_msg_add_delete(secret_state->sam_ldb,
3611 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3612 return NT_STATUS_NO_MEMORY;
3616 /* modify the samdb record */
3617 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3618 if (ret != LDB_SUCCESS) {
3619 return dsdb_ldb_err_to_ntstatus(ret);
3622 return NT_STATUS_OK;
3629 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3630 struct lsa_QuerySecret *r)
3632 struct dcesrv_handle *h;
3633 struct lsa_secret_state *secret_state;
3634 struct ldb_message *msg;
3635 DATA_BLOB session_key;
3636 DATA_BLOB crypt_secret, secret;
3638 struct ldb_message **res;
3639 const char *attrs[] = {
3649 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3651 /* Ensure user is permitted to read this... */
3652 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3654 case SECURITY_SYSTEM:
3655 case SECURITY_ADMINISTRATOR:
3658 /* Users and annonymous are not allowed to read secrets */
3659 return NT_STATUS_ACCESS_DENIED;
3662 secret_state = h->data;
3664 /* pull all the user attributes */
3665 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3666 secret_state->secret_dn, &res, attrs);
3668 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3672 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3673 if (!NT_STATUS_IS_OK(nt_status)) {
3677 if (r->in.old_val) {
3678 const struct ldb_val *prior_val;
3679 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3680 if (!r->out.old_val) {
3681 return NT_STATUS_NO_MEMORY;
3683 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3685 if (prior_val && prior_val->length) {
3686 secret.data = prior_val->data;
3687 secret.length = prior_val->length;
3690 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3691 if (!crypt_secret.length) {
3692 return NT_STATUS_NO_MEMORY;
3694 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3695 if (!r->out.old_val->buf) {
3696 return NT_STATUS_NO_MEMORY;
3698 r->out.old_val->buf->size = crypt_secret.length;
3699 r->out.old_val->buf->length = crypt_secret.length;
3700 r->out.old_val->buf->data = crypt_secret.data;
3704 if (r->in.old_mtime) {
3705 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3706 if (!r->out.old_mtime) {
3707 return NT_STATUS_NO_MEMORY;
3709 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3712 if (r->in.new_val) {
3713 const struct ldb_val *new_val;
3714 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3715 if (!r->out.new_val) {
3716 return NT_STATUS_NO_MEMORY;
3719 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3721 if (new_val && new_val->length) {
3722 secret.data = new_val->data;
3723 secret.length = new_val->length;
3726 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3727 if (!crypt_secret.length) {
3728 return NT_STATUS_NO_MEMORY;
3730 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3731 if (!r->out.new_val->buf) {
3732 return NT_STATUS_NO_MEMORY;
3734 r->out.new_val->buf->length = crypt_secret.length;
3735 r->out.new_val->buf->size = crypt_secret.length;
3736 r->out.new_val->buf->data = crypt_secret.data;
3740 if (r->in.new_mtime) {
3741 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3742 if (!r->out.new_mtime) {
3743 return NT_STATUS_NO_MEMORY;
3745 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3748 return NT_STATUS_OK;
3755 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3756 TALLOC_CTX *mem_ctx,
3757 struct lsa_LookupPrivValue *r)
3759 struct dcesrv_handle *h;
3762 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3764 id = sec_privilege_id(r->in.name->string);
3765 if (id == SEC_PRIV_INVALID) {
3766 return NT_STATUS_NO_SUCH_PRIVILEGE;
3769 r->out.luid->low = id;
3770 r->out.luid->high = 0;
3772 return NT_STATUS_OK;
3779 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3780 TALLOC_CTX *mem_ctx,
3781 struct lsa_LookupPrivName *r)
3783 struct dcesrv_handle *h;
3784 struct lsa_StringLarge *name;
3785 const char *privname;
3787 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3789 if (r->in.luid->high != 0) {
3790 return NT_STATUS_NO_SUCH_PRIVILEGE;
3793 privname = sec_privilege_name(r->in.luid->low);
3794 if (privname == NULL) {
3795 return NT_STATUS_NO_SUCH_PRIVILEGE;
3798 name = talloc(mem_ctx, struct lsa_StringLarge);
3800 return NT_STATUS_NO_MEMORY;
3803 name->string = privname;
3805 *r->out.name = name;
3807 return NT_STATUS_OK;
3812 lsa_LookupPrivDisplayName
3814 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3815 TALLOC_CTX *mem_ctx,
3816 struct lsa_LookupPrivDisplayName *r)
3818 struct dcesrv_handle *h;
3819 struct lsa_StringLarge *disp_name = NULL;
3820 enum sec_privilege id;
3822 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3824 id = sec_privilege_id(r->in.name->string);
3825 if (id == SEC_PRIV_INVALID) {
3826 return NT_STATUS_NO_SUCH_PRIVILEGE;
3829 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3830 if (disp_name == NULL) {
3831 return NT_STATUS_NO_MEMORY;
3834 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3835 if (disp_name->string == NULL) {
3836 return NT_STATUS_INTERNAL_ERROR;
3839 *r->out.disp_name = disp_name;
3840 *r->out.returned_language_id = 0;
3842 return NT_STATUS_OK;
3847 lsa_EnumAccountsWithUserRight
3849 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3850 TALLOC_CTX *mem_ctx,
3851 struct lsa_EnumAccountsWithUserRight *r)
3853 struct dcesrv_handle *h;
3854 struct lsa_policy_state *state;
3856 struct ldb_message **res;
3857 const char * const attrs[] = { "objectSid", NULL};
3858 const char *privname;
3860 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3864 if (r->in.name == NULL) {
3865 return NT_STATUS_NO_SUCH_PRIVILEGE;
3868 privname = r->in.name->string;
3869 if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3870 return NT_STATUS_NO_SUCH_PRIVILEGE;
3873 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3874 "privilege=%s", privname);
3876 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3879 return NT_STATUS_NO_MORE_ENTRIES;
3882 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3883 if (r->out.sids->sids == NULL) {
3884 return NT_STATUS_NO_MEMORY;
3886 for (i=0;i<ret;i++) {
3887 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3888 res[i], "objectSid");
3889 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3891 r->out.sids->num_sids = ret;
3893 return NT_STATUS_OK;
3898 lsa_AddAccountRights
3900 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3901 TALLOC_CTX *mem_ctx,
3902 struct lsa_AddAccountRights *r)
3904 struct dcesrv_handle *h;
3905 struct lsa_policy_state *state;
3907 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3911 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3913 r->in.sid, r->in.rights);
3918 lsa_RemoveAccountRights
3920 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3921 TALLOC_CTX *mem_ctx,
3922 struct lsa_RemoveAccountRights *r)
3924 struct dcesrv_handle *h;
3925 struct lsa_policy_state *state;
3927 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3931 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3932 LDB_FLAG_MOD_DELETE,
3933 r->in.sid, r->in.rights);
3938 lsa_StorePrivateData
3940 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3941 struct lsa_StorePrivateData *r)
3943 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3948 lsa_RetrievePrivateData
3950 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3951 struct lsa_RetrievePrivateData *r)
3953 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3960 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3961 struct lsa_GetUserName *r)
3963 enum dcerpc_transport_t transport =
3964 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3965 NTSTATUS status = NT_STATUS_OK;
3966 const char *account_name;
3967 const char *authority_name;
3968 struct lsa_String *_account_name;
3969 struct lsa_String *_authority_name = NULL;
3971 if (transport != NCACN_NP && transport != NCALRPC) {
3972 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3975 /* this is what w2k3 does */
3976 r->out.account_name = r->in.account_name;
3977 r->out.authority_name = r->in.authority_name;
3979 if (r->in.account_name
3980 && *r->in.account_name
3981 /* && *(*r->in.account_name)->string */
3983 return NT_STATUS_INVALID_PARAMETER;
3986 if (r->in.authority_name
3987 && *r->in.authority_name
3988 /* && *(*r->in.authority_name)->string */
3990 return NT_STATUS_INVALID_PARAMETER;
3993 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3994 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3996 _account_name = talloc(mem_ctx, struct lsa_String);
3997 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3998 _account_name->string = account_name;
4000 if (r->in.authority_name) {
4001 _authority_name = talloc(mem_ctx, struct lsa_String);
4002 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
4003 _authority_name->string = authority_name;
4006 *r->out.account_name = _account_name;
4007 if (r->out.authority_name) {
4008 *r->out.authority_name = _authority_name;
4017 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
4018 TALLOC_CTX *mem_ctx,
4019 struct lsa_SetInfoPolicy2 *r)
4021 /* need to support these */
4022 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4025 static void kdc_get_policy(struct loadparm_context *lp_ctx,
4026 struct smb_krb5_context *smb_krb5_context,
4027 struct lsa_DomainInfoKerberos *k)
4029 time_t svc_tkt_lifetime;
4030 time_t usr_tkt_lifetime;
4031 time_t renewal_lifetime;
4033 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
4035 /* Our KDC always re-validates the client */
4036 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
4038 lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
4039 &usr_tkt_lifetime, &renewal_lifetime);
4041 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
4042 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
4043 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
4044 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
4045 However in the parent function we basically just did a full
4046 krb5_context init with the only purpose of getting a global
4047 config option (the max skew), it would probably make more sense
4048 to have a lp_ or ldb global option as the samba default */
4049 if (smb_krb5_context) {
4050 unix_to_nt_time(&k->clock_skew,
4051 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
4057 lsa_QueryDomainInformationPolicy
4059 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4060 TALLOC_CTX *mem_ctx,
4061 struct lsa_QueryDomainInformationPolicy *r)
4063 union lsa_DomainInformationPolicy *info;
4065 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
4067 return NT_STATUS_NO_MEMORY;
4070 switch (r->in.level) {
4071 case LSA_DOMAIN_INFO_POLICY_EFS:
4073 *r->out.info = NULL;
4074 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4075 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
4077 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
4078 struct smb_krb5_context *smb_krb5_context;
4079 int ret = smb_krb5_init_context(mem_ctx,
4080 dce_call->conn->dce_ctx->lp_ctx,
4084 *r->out.info = NULL;
4085 return NT_STATUS_INTERNAL_ERROR;
4087 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
4090 talloc_free(smb_krb5_context);
4091 *r->out.info = info;
4092 return NT_STATUS_OK;
4096 *r->out.info = NULL;
4097 return NT_STATUS_INVALID_INFO_CLASS;
4102 lsa_SetDomInfoPolicy
4104 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4105 TALLOC_CTX *mem_ctx,
4106 struct lsa_SetDomainInformationPolicy *r)
4108 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4114 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
4115 TALLOC_CTX *mem_ctx,
4116 struct lsa_TestCall *r)
4118 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4124 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4125 struct lsa_CREDRWRITE *r)
4127 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4134 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4135 struct lsa_CREDRREAD *r)
4137 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4144 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4145 struct lsa_CREDRENUMERATE *r)
4147 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4152 lsa_CREDRWRITEDOMAINCREDENTIALS
4154 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4155 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
4157 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4162 lsa_CREDRREADDOMAINCREDENTIALS
4164 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4165 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
4167 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4174 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4175 struct lsa_CREDRDELETE *r)
4177 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4182 lsa_CREDRGETTARGETINFO
4184 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4185 struct lsa_CREDRGETTARGETINFO *r)
4187 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4192 lsa_CREDRPROFILELOADED
4194 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4195 struct lsa_CREDRPROFILELOADED *r)
4197 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4202 lsa_CREDRGETSESSIONTYPES
4204 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4205 struct lsa_CREDRGETSESSIONTYPES *r)
4207 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4212 lsa_LSARREGISTERAUDITEVENT
4214 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4215 struct lsa_LSARREGISTERAUDITEVENT *r)
4217 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4222 lsa_LSARGENAUDITEVENT
4224 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4225 struct lsa_LSARGENAUDITEVENT *r)
4227 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4232 lsa_LSARUNREGISTERAUDITEVENT
4234 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4235 struct lsa_LSARUNREGISTERAUDITEVENT *r)
4237 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4242 lsa_lsaRQueryForestTrustInformation
4244 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4245 struct lsa_lsaRQueryForestTrustInformation *r)
4247 struct dcesrv_handle *h = NULL;
4248 struct lsa_policy_state *p_state = NULL;
4249 int forest_level = DS_DOMAIN_FUNCTION_2000;
4250 const char * const trust_attrs[] = {
4251 "securityIdentifier",
4257 "msDS-TrustForestTrustInfo",
4260 struct ldb_message *trust_tdo_msg = NULL;
4261 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4262 struct ForestTrustInfo *trust_fti = NULL;
4263 struct lsa_ForestTrustInformation *trust_lfti = NULL;
4266 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4270 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4271 return NT_STATUS_INVALID_DOMAIN_STATE;
4274 forest_level = dsdb_forest_functional_level(p_state->sam_ldb);
4275 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4276 return NT_STATUS_INVALID_DOMAIN_STATE;
4279 if (r->in.trusted_domain_name->string == NULL) {
4280 return NT_STATUS_NO_SUCH_DOMAIN;
4283 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4284 r->in.trusted_domain_name->string,
4285 r->in.trusted_domain_name->string,
4286 trust_attrs, mem_ctx, &trust_tdo_msg);
4287 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4288 return NT_STATUS_NO_SUCH_DOMAIN;
4290 if (!NT_STATUS_IS_OK(status)) {
4294 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4295 if (!NT_STATUS_IS_OK(status)) {
4299 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4300 return NT_STATUS_INVALID_PARAMETER;
4303 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4304 return NT_STATUS_INVALID_PARAMETER;
4307 status = dsdb_trust_parse_forest_info(mem_ctx,
4310 if (!NT_STATUS_IS_OK(status)) {
4314 status = dsdb_trust_forest_info_to_lsa(mem_ctx, trust_fti,
4316 if (!NT_STATUS_IS_OK(status)) {
4320 *r->out.forest_trust_info = trust_lfti;
4321 return NT_STATUS_OK;
4325 lsa_lsaRSetForestTrustInformation
4327 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4328 TALLOC_CTX *mem_ctx,
4329 struct lsa_lsaRSetForestTrustInformation *r)
4331 struct dcesrv_handle *h;
4332 struct lsa_policy_state *p_state;
4333 const char * const trust_attrs[] = {
4334 "securityIdentifier",
4340 "msDS-TrustForestTrustInfo",
4343 struct ldb_message *trust_tdo_msg = NULL;
4344 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4345 struct lsa_ForestTrustInformation *step1_lfti = NULL;
4346 struct lsa_ForestTrustInformation *step2_lfti = NULL;
4347 struct ForestTrustInfo *trust_fti = NULL;
4348 struct ldb_result *trusts_res = NULL;
4350 struct lsa_TrustDomainInfoInfoEx *xref_tdo = NULL;
4351 struct lsa_ForestTrustInformation *xref_lfti = NULL;
4352 struct lsa_ForestTrustCollisionInfo *c_info = NULL;
4353 DATA_BLOB ft_blob = {};
4354 struct ldb_message *msg = NULL;
4356 enum ndr_err_code ndr_err;
4358 bool in_transaction = false;
4360 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4364 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4365 return NT_STATUS_INVALID_DOMAIN_STATE;
4368 if (r->in.check_only == 0) {
4369 ret = ldb_transaction_start(p_state->sam_ldb);
4370 if (ret != LDB_SUCCESS) {
4371 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4373 in_transaction = true;
4377 * abort if we are not a PDC
4379 * In future we should use a function like IsEffectiveRoleOwner()
4381 if (!samdb_is_pdc(p_state->sam_ldb)) {
4382 status = NT_STATUS_INVALID_DOMAIN_ROLE;
4386 if (r->in.trusted_domain_name->string == NULL) {
4387 status = NT_STATUS_NO_SUCH_DOMAIN;
4391 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4392 r->in.trusted_domain_name->string,
4393 r->in.trusted_domain_name->string,
4394 trust_attrs, mem_ctx, &trust_tdo_msg);
4395 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4396 status = NT_STATUS_NO_SUCH_DOMAIN;
4399 if (!NT_STATUS_IS_OK(status)) {
4403 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4404 if (!NT_STATUS_IS_OK(status)) {
4408 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4409 status = NT_STATUS_INVALID_PARAMETER;
4413 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4414 status = NT_STATUS_INVALID_PARAMETER;
4419 * verify and normalize the given forest trust info.
4421 * Step1: doesn't reorder yet, so step1_lfti might contain
4422 * NULL entries. This means dsdb_trust_verify_forest_info()
4423 * can generate collision entries with the callers index.
4425 status = dsdb_trust_normalize_forest_info_step1(mem_ctx,
4426 r->in.forest_trust_info,
4428 if (!NT_STATUS_IS_OK(status)) {
4432 c_info = talloc_zero(r->out.collision_info,
4433 struct lsa_ForestTrustCollisionInfo);
4434 if (c_info == NULL) {
4435 status = NT_STATUS_NO_MEMORY;
4440 * First check our own forest, then other domains/forests
4443 status = dsdb_trust_xref_tdo_info(mem_ctx, p_state->sam_ldb,
4445 if (!NT_STATUS_IS_OK(status)) {
4448 status = dsdb_trust_xref_forest_info(mem_ctx, p_state->sam_ldb,
4450 if (!NT_STATUS_IS_OK(status)) {
4455 * The documentation proposed to generate
4456 * LSA_FOREST_TRUST_COLLISION_XREF collisions.
4457 * But Windows always uses LSA_FOREST_TRUST_COLLISION_TDO.
4459 status = dsdb_trust_verify_forest_info(xref_tdo, xref_lfti,
4460 LSA_FOREST_TRUST_COLLISION_TDO,
4461 c_info, step1_lfti);
4462 if (!NT_STATUS_IS_OK(status)) {
4466 /* fetch all other trusted domain objects */
4467 status = dsdb_trust_search_tdos(p_state->sam_ldb,
4468 trust_tdo->domain_name.string,
4470 mem_ctx, &trusts_res);
4471 if (!NT_STATUS_IS_OK(status)) {
4476 * now check against the other domains.
4477 * and generate LSA_FOREST_TRUST_COLLISION_TDO collisions.
4479 for (i = 0; i < trusts_res->count; i++) {
4480 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
4481 struct ForestTrustInfo *fti = NULL;
4482 struct lsa_ForestTrustInformation *lfti = NULL;
4484 status = dsdb_trust_parse_tdo_info(mem_ctx,
4485 trusts_res->msgs[i],
4487 if (!NT_STATUS_IS_OK(status)) {
4491 status = dsdb_trust_parse_forest_info(tdo,
4492 trusts_res->msgs[i],
4494 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
4497 if (!NT_STATUS_IS_OK(status)) {
4501 status = dsdb_trust_forest_info_to_lsa(tdo, fti, &lfti);
4502 if (!NT_STATUS_IS_OK(status)) {
4506 status = dsdb_trust_verify_forest_info(tdo, lfti,
4507 LSA_FOREST_TRUST_COLLISION_TDO,
4508 c_info, step1_lfti);
4509 if (!NT_STATUS_IS_OK(status)) {
4516 if (r->in.check_only != 0) {
4517 status = NT_STATUS_OK;
4522 * not just a check, write info back
4526 * normalize the given forest trust info.
4528 * Step2: adds TOP_LEVEL_NAME[_EX] in reverse order,
4529 * followed by DOMAIN_INFO in reverse order. It also removes
4530 * possible NULL entries from Step1.
4532 status = dsdb_trust_normalize_forest_info_step2(mem_ctx, step1_lfti,
4534 if (!NT_STATUS_IS_OK(status)) {
4538 status = dsdb_trust_forest_info_from_lsa(mem_ctx, step2_lfti,
4540 if (!NT_STATUS_IS_OK(status)) {
4544 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, trust_fti,
4545 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4546 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4547 status = NT_STATUS_INVALID_PARAMETER;
4551 msg = ldb_msg_new(mem_ctx);
4553 status = NT_STATUS_NO_MEMORY;
4557 msg->dn = ldb_dn_copy(mem_ctx, trust_tdo_msg->dn);
4559 status = NT_STATUS_NO_MEMORY;
4563 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4564 LDB_FLAG_MOD_REPLACE, NULL);
4565 if (ret != LDB_SUCCESS) {
4566 status = NT_STATUS_NO_MEMORY;
4569 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4571 if (ret != LDB_SUCCESS) {
4572 status = NT_STATUS_NO_MEMORY;
4576 ret = ldb_modify(p_state->sam_ldb, msg);
4577 if (ret != LDB_SUCCESS) {
4578 status = dsdb_ldb_err_to_ntstatus(ret);
4580 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4581 ldb_errstring(p_state->sam_ldb)));
4586 /* ok, all fine, commit transaction and return */
4587 in_transaction = false;
4588 ret = ldb_transaction_commit(p_state->sam_ldb);
4589 if (ret != LDB_SUCCESS) {
4590 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4594 status = NT_STATUS_OK;
4597 if (NT_STATUS_IS_OK(status) && c_info->count != 0) {
4598 *r->out.collision_info = c_info;
4601 if (in_transaction) {
4602 ldb_transaction_cancel(p_state->sam_ldb);
4611 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4612 struct lsa_CREDRRENAME *r)
4614 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4620 lsa_LSAROPENPOLICYSCE
4622 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4623 struct lsa_LSAROPENPOLICYSCE *r)
4625 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4630 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4632 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4633 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4635 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4640 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4642 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4643 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4645 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4650 lsa_LSARADTREPORTSECURITYEVENT
4652 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4653 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4655 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4659 /* include the generated boilerplate */
4660 #include "librpc/gen_ndr/ndr_lsa_s.c"
4664 /*****************************************
4665 NOTE! The remaining calls below were
4666 removed in w2k3, so the DCESRV_FAULT()
4667 replies are the correct implementation. Do
4668 not try and fill these in with anything else
4669 ******************************************/
4672 dssetup_DsRoleDnsNameToFlatName
4674 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4675 struct dssetup_DsRoleDnsNameToFlatName *r)
4677 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4682 dssetup_DsRoleDcAsDc
4684 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4685 struct dssetup_DsRoleDcAsDc *r)
4687 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4692 dssetup_DsRoleDcAsReplica
4694 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4695 struct dssetup_DsRoleDcAsReplica *r)
4697 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4702 dssetup_DsRoleDemoteDc
4704 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4705 struct dssetup_DsRoleDemoteDc *r)
4707 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4712 dssetup_DsRoleGetDcOperationProgress
4714 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4715 struct dssetup_DsRoleGetDcOperationProgress *r)
4717 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4722 dssetup_DsRoleGetDcOperationResults
4724 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4725 struct dssetup_DsRoleGetDcOperationResults *r)
4727 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4732 dssetup_DsRoleCancel
4734 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4735 struct dssetup_DsRoleCancel *r)
4737 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4742 dssetup_DsRoleServerSaveStateForUpgrade
4744 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4745 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4747 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4752 dssetup_DsRoleUpgradeDownlevelServer
4754 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4755 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4757 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4762 dssetup_DsRoleAbortDownlevelServerUpgrade
4764 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4765 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4767 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4771 /* include the generated boilerplate */
4772 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4774 NTSTATUS dcerpc_server_lsa_init(TALLOC_CTX *ctx)
4778 ret = dcerpc_server_dssetup_init(ctx);
4779 if (!NT_STATUS_IS_OK(ret)) {
4782 ret = dcerpc_server_lsarpc_init(ctx);
4783 if (!NT_STATUS_IS_OK(ret)) {