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;
102 static bool dcesrc_lsa_valid_AccountRight(const char *right)
104 enum sec_privilege priv_id;
107 priv_id = sec_privilege_id(right);
108 if (priv_id != SEC_PRIV_INVALID) {
112 right_bit = sec_right_bit(right);
113 if (right_bit != 0) {
121 this is based on the samba3 function make_lsa_object_sd()
122 It uses the same logic, but with samba4 helper functions
124 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
125 struct security_descriptor **sd,
131 struct dom_sid *domain_sid, *domain_admins_sid;
132 const char *domain_admins_sid_str, *sidstr;
133 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
135 status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
136 if (!NT_STATUS_IS_OK(status)) {
137 TALLOC_FREE(tmp_ctx);
141 domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
142 if (domain_admins_sid == NULL) {
143 TALLOC_FREE(tmp_ctx);
144 return NT_STATUS_NO_MEMORY;
147 domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
148 if (domain_admins_sid_str == NULL) {
149 TALLOC_FREE(tmp_ctx);
150 return NT_STATUS_NO_MEMORY;
153 sidstr = dom_sid_string(tmp_ctx, sid);
154 if (sidstr == NULL) {
155 TALLOC_FREE(tmp_ctx);
156 return NT_STATUS_NO_MEMORY;
159 *sd = security_descriptor_dacl_create(mem_ctx,
163 SEC_ACE_TYPE_ACCESS_ALLOWED,
164 SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
166 SID_BUILTIN_ADMINISTRATORS,
167 SEC_ACE_TYPE_ACCESS_ALLOWED,
170 SID_BUILTIN_ACCOUNT_OPERATORS,
171 SEC_ACE_TYPE_ACCESS_ALLOWED,
174 domain_admins_sid_str,
175 SEC_ACE_TYPE_ACCESS_ALLOWED,
179 SEC_ACE_TYPE_ACCESS_ALLOWED,
183 talloc_free(tmp_ctx);
185 NT_STATUS_HAVE_NO_MEMORY(*sd);
191 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
193 struct lsa_EnumAccountRights *r);
195 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
197 struct lsa_policy_state *state,
200 const struct lsa_RightSet *rights);
205 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
208 enum dcerpc_transport_t transport =
209 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
210 struct dcesrv_handle *h;
212 if (transport != NCACN_NP && transport != NCALRPC) {
213 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
216 *r->out.handle = *r->in.handle;
218 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
222 ZERO_STRUCTP(r->out.handle);
231 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
232 struct lsa_Delete *r)
234 return NT_STATUS_NOT_SUPPORTED;
241 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
242 struct lsa_DeleteObject *r)
244 struct dcesrv_handle *h;
247 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
249 if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
250 struct lsa_secret_state *secret_state = h->data;
252 /* Ensure user is permitted to delete this... */
253 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
255 case SECURITY_SYSTEM:
256 case SECURITY_ADMINISTRATOR:
259 /* Users and anonymous are not allowed to delete things */
260 return NT_STATUS_ACCESS_DENIED;
263 ret = ldb_delete(secret_state->sam_ldb,
264 secret_state->secret_dn);
265 if (ret != LDB_SUCCESS) {
266 return NT_STATUS_INVALID_HANDLE;
269 ZERO_STRUCTP(r->out.handle);
273 } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
274 struct lsa_trusted_domain_state *trusted_domain_state =
275 talloc_get_type(h->data, struct lsa_trusted_domain_state);
276 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
277 if (ret != LDB_SUCCESS) {
278 return NT_STATUS_INTERNAL_DB_CORRUPTION;
281 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
282 trusted_domain_state->trusted_domain_dn);
283 if (ret != LDB_SUCCESS) {
284 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
285 return NT_STATUS_INVALID_HANDLE;
288 if (trusted_domain_state->trusted_domain_user_dn) {
289 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
290 trusted_domain_state->trusted_domain_user_dn);
291 if (ret != LDB_SUCCESS) {
292 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
293 return NT_STATUS_INVALID_HANDLE;
297 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
298 if (ret != LDB_SUCCESS) {
299 return NT_STATUS_INTERNAL_DB_CORRUPTION;
302 ZERO_STRUCTP(r->out.handle);
306 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
307 struct lsa_RightSet *rights;
308 struct lsa_account_state *astate;
309 struct lsa_EnumAccountRights r2;
312 rights = talloc(mem_ctx, struct lsa_RightSet);
314 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
318 r2.in.handle = &astate->policy->handle->wire_handle;
319 r2.in.sid = astate->account_sid;
320 r2.out.rights = rights;
322 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
323 but we have a LSA_HANDLE_ACCOUNT here, so this call
325 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
326 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
330 if (!NT_STATUS_IS_OK(status)) {
334 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
335 LDB_FLAG_MOD_DELETE, astate->account_sid,
337 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
341 if (!NT_STATUS_IS_OK(status)) {
345 ZERO_STRUCTP(r->out.handle);
350 return NT_STATUS_INVALID_HANDLE;
357 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
358 struct lsa_EnumPrivs *r)
360 struct dcesrv_handle *h;
362 enum sec_privilege priv;
363 const char *privname;
365 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
367 i = *r->in.resume_handle;
369 while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
370 r->out.privs->count < r->in.max_count) {
371 struct lsa_PrivEntry *e;
372 privname = sec_privilege_name(priv);
373 r->out.privs->privs = talloc_realloc(r->out.privs,
375 struct lsa_PrivEntry,
376 r->out.privs->count+1);
377 if (r->out.privs->privs == NULL) {
378 return NT_STATUS_NO_MEMORY;
380 e = &r->out.privs->privs[r->out.privs->count];
383 e->name.string = privname;
384 r->out.privs->count++;
388 *r->out.resume_handle = i;
397 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
398 struct lsa_QuerySecurity *r)
400 struct dcesrv_handle *h;
401 const struct security_descriptor *sd = NULL;
402 uint32_t access_granted = 0;
403 struct sec_desc_buf *sdbuf = NULL;
407 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
409 sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
411 if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
412 struct lsa_policy_state *pstate = h->data;
415 access_granted = pstate->access_mask;
417 } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
418 struct lsa_account_state *astate = h->data;
419 struct security_descriptor *_sd = NULL;
421 status = dcesrv_build_lsa_sd(mem_ctx, &_sd, sid,
422 LSA_ACCOUNT_ALL_ACCESS);
423 if (!NT_STATUS_IS_OK(status)) {
427 access_granted = astate->access_mask;
429 return NT_STATUS_INVALID_HANDLE;
432 sdbuf = talloc_zero(mem_ctx, struct sec_desc_buf);
434 return NT_STATUS_NO_MEMORY;
437 status = security_descriptor_for_client(sdbuf, sd, r->in.sec_info,
438 access_granted, &sdbuf->sd);
439 if (!NT_STATUS_IS_OK(status)) {
443 *r->out.sdbuf = sdbuf;
452 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
453 struct lsa_SetSecObj *r)
455 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
462 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
463 struct lsa_ChangePassword *r)
465 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
469 dssetup_DsRoleGetPrimaryDomainInformation
471 This is not an LSA call, but is the only call left on the DSSETUP
472 pipe (after the pipe was truncated), and needs lsa_get_policy_state
474 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
476 struct dssetup_DsRoleGetPrimaryDomainInformation *r)
478 union dssetup_DsRoleInfo *info;
480 info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
481 W_ERROR_HAVE_NO_MEMORY(info);
483 switch (r->in.level) {
484 case DS_ROLE_BASIC_INFORMATION:
486 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
488 const char *domain = NULL;
489 const char *dns_domain = NULL;
490 const char *forest = NULL;
491 struct GUID domain_guid;
492 struct lsa_policy_state *state;
494 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
495 0, /* we skip access checks */
497 if (!NT_STATUS_IS_OK(status)) {
498 return ntstatus_to_werror(status);
501 ZERO_STRUCT(domain_guid);
503 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
504 case ROLE_STANDALONE:
505 role = DS_ROLE_STANDALONE_SERVER;
507 case ROLE_DOMAIN_MEMBER:
508 role = DS_ROLE_MEMBER_SERVER;
510 case ROLE_ACTIVE_DIRECTORY_DC:
511 if (samdb_is_pdc(state->sam_ldb)) {
512 role = DS_ROLE_PRIMARY_DC;
514 role = DS_ROLE_BACKUP_DC;
519 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
520 case ROLE_STANDALONE:
521 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
522 W_ERROR_HAVE_NO_MEMORY(domain);
524 case ROLE_DOMAIN_MEMBER:
525 domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
526 W_ERROR_HAVE_NO_MEMORY(domain);
527 /* TODO: what is with dns_domain and forest and guid? */
529 case ROLE_ACTIVE_DIRECTORY_DC:
530 flags = DS_ROLE_PRIMARY_DS_RUNNING;
532 if (state->mixed_domain == 1) {
533 flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
536 domain = state->domain_name;
537 dns_domain = state->domain_dns;
538 forest = state->forest_dns;
540 domain_guid = state->domain_guid;
541 flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
545 info->basic.role = role;
546 info->basic.flags = flags;
547 info->basic.domain = domain;
548 info->basic.dns_domain = dns_domain;
549 info->basic.forest = forest;
550 info->basic.domain_guid = domain_guid;
555 case DS_ROLE_UPGRADE_STATUS:
557 info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
558 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
563 case DS_ROLE_OP_STATUS:
565 info->opstatus.status = DS_ROLE_OP_IDLE;
571 return WERR_INVALID_PARAMETER;
576 fill in the AccountDomain info
578 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
579 struct lsa_DomainInfo *info)
581 info->name.string = state->domain_name;
582 info->sid = state->domain_sid;
588 fill in the DNS domain info
590 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
591 struct lsa_DnsDomainInfo *info)
593 info->name.string = state->domain_name;
594 info->sid = state->domain_sid;
595 info->dns_domain.string = state->domain_dns;
596 info->dns_forest.string = state->forest_dns;
597 info->domain_guid = state->domain_guid;
605 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
606 struct lsa_QueryInfoPolicy2 *r)
608 struct lsa_policy_state *state;
609 struct dcesrv_handle *h;
610 union lsa_PolicyInformation *info;
614 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
618 info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
620 return NT_STATUS_NO_MEMORY;
624 switch (r->in.level) {
625 case LSA_POLICY_INFO_AUDIT_LOG:
626 /* we don't need to fill in any of this */
627 ZERO_STRUCT(info->audit_log);
629 case LSA_POLICY_INFO_AUDIT_EVENTS:
630 /* we don't need to fill in any of this */
631 ZERO_STRUCT(info->audit_events);
633 case LSA_POLICY_INFO_PD:
634 /* we don't need to fill in any of this */
635 ZERO_STRUCT(info->pd);
638 case LSA_POLICY_INFO_DOMAIN:
639 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
640 case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
641 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
642 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
643 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
645 case LSA_POLICY_INFO_ROLE:
646 info->role.role = LSA_ROLE_PRIMARY;
649 case LSA_POLICY_INFO_DNS:
650 case LSA_POLICY_INFO_DNS_INT:
651 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
653 case LSA_POLICY_INFO_REPLICA:
654 ZERO_STRUCT(info->replica);
657 case LSA_POLICY_INFO_QUOTA:
658 ZERO_STRUCT(info->quota);
661 case LSA_POLICY_INFO_MOD:
662 case LSA_POLICY_INFO_AUDIT_FULL_SET:
663 case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
664 /* windows gives INVALID_PARAMETER */
666 return NT_STATUS_INVALID_PARAMETER;
670 return NT_STATUS_INVALID_INFO_CLASS;
676 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
677 struct lsa_QueryInfoPolicy *r)
679 struct lsa_QueryInfoPolicy2 r2;
684 r2.in.handle = r->in.handle;
685 r2.in.level = r->in.level;
686 r2.out.info = r->out.info;
688 status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
696 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
697 struct lsa_SetInfoPolicy *r)
699 /* need to support this */
700 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
707 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
708 struct lsa_ClearAuditLog *r)
710 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
714 static const struct generic_mapping dcesrv_lsa_account_mapping = {
718 LSA_ACCOUNT_ALL_ACCESS
724 This call does not seem to have any long-term effects, hence no database operations
726 we need to talk to the MS product group to find out what this account database means!
728 answer is that the lsa database is totally separate from the SAM and
729 ldap databases. We are going to need a separate ldb to store these
730 accounts. The SIDs on this account bear no relation to the SIDs in
733 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
734 struct lsa_CreateAccount *r)
736 struct lsa_account_state *astate;
738 struct lsa_policy_state *state;
739 struct dcesrv_handle *h, *ah;
741 ZERO_STRUCTP(r->out.acct_handle);
743 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
747 astate = talloc(dce_call->conn, struct lsa_account_state);
748 if (astate == NULL) {
749 return NT_STATUS_NO_MEMORY;
752 astate->account_sid = dom_sid_dup(astate, r->in.sid);
753 if (astate->account_sid == NULL) {
755 return NT_STATUS_NO_MEMORY;
758 astate->policy = talloc_reference(astate, state);
759 astate->access_mask = r->in.access_mask;
762 * For now we grant all requested access.
764 * We will fail at the ldb layer later.
766 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
767 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
768 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
770 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
772 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X].\n",
773 __func__, dom_sid_string(mem_ctx, astate->account_sid),
774 (unsigned)r->in.access_mask,
775 (unsigned)astate->access_mask));
777 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
780 return NT_STATUS_NO_MEMORY;
783 ah->data = talloc_steal(ah, astate);
785 *r->out.acct_handle = ah->wire_handle;
794 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
795 struct lsa_EnumAccounts *r)
797 struct dcesrv_handle *h;
798 struct lsa_policy_state *state;
800 struct ldb_message **res;
801 const char * const attrs[] = { "objectSid", NULL};
804 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
808 /* NOTE: This call must only return accounts that have at least
811 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
812 "(&(objectSid=*)(privilege=*))");
814 return NT_STATUS_INTERNAL_DB_CORRUPTION;
817 if (*r->in.resume_handle >= ret) {
818 return NT_STATUS_NO_MORE_ENTRIES;
821 count = ret - *r->in.resume_handle;
822 if (count > r->in.num_entries) {
823 count = r->in.num_entries;
827 return NT_STATUS_NO_MORE_ENTRIES;
830 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
831 if (r->out.sids->sids == NULL) {
832 return NT_STATUS_NO_MEMORY;
835 for (i=0;i<count;i++) {
836 r->out.sids->sids[i].sid =
837 samdb_result_dom_sid(r->out.sids->sids,
838 res[i + *r->in.resume_handle],
840 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
843 r->out.sids->num_sids = count;
844 *r->out.resume_handle = count + *r->in.resume_handle;
849 /* This decrypts and returns Trusted Domain Auth Information Internal data */
850 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
851 TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
852 struct trustDomainPasswords *auth_struct)
854 DATA_BLOB session_key = data_blob(NULL, 0);
855 enum ndr_err_code ndr_err;
858 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
859 if (!NT_STATUS_IS_OK(nt_status)) {
863 arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
864 ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
866 (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
867 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
868 return NT_STATUS_INVALID_PARAMETER;
874 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
876 struct trustAuthInOutBlob *iopw,
877 DATA_BLOB *trustauth_blob)
879 enum ndr_err_code ndr_err;
881 if (iopw->current.count != iopw->count) {
882 return NT_STATUS_INVALID_PARAMETER;
885 if (iopw->previous.count > iopw->current.count) {
886 return NT_STATUS_INVALID_PARAMETER;
889 if (iopw->previous.count == 0) {
891 * If the previous credentials are not present
892 * we need to make a copy.
894 iopw->previous = iopw->current;
897 if (iopw->previous.count < iopw->current.count) {
898 struct AuthenticationInformationArray *c = &iopw->current;
899 struct AuthenticationInformationArray *p = &iopw->previous;
902 * The previous array needs to have the same size
903 * as the current one.
905 * We may have to fill with TRUST_AUTH_TYPE_NONE
908 p->array = talloc_realloc(mem_ctx, p->array,
909 struct AuthenticationInformation,
911 if (p->array == NULL) {
912 return NT_STATUS_NO_MEMORY;
915 while (p->count < c->count) {
916 struct AuthenticationInformation *a =
917 &p->array[p->count++];
919 *a = (struct AuthenticationInformation) {
920 .LastUpdateTime = p->array[0].LastUpdateTime,
921 .AuthType = TRUST_AUTH_TYPE_NONE,
926 ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
928 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
929 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
930 return NT_STATUS_INVALID_PARAMETER;
936 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
937 struct ldb_context *sam_ldb,
938 struct ldb_dn *base_dn,
939 const char *netbios_name,
940 struct trustAuthInOutBlob *in,
941 struct ldb_dn **user_dn)
943 struct ldb_request *req;
944 struct ldb_message *msg;
949 dn = ldb_dn_copy(mem_ctx, base_dn);
951 return NT_STATUS_NO_MEMORY;
953 if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
954 return NT_STATUS_NO_MEMORY;
957 msg = ldb_msg_new(mem_ctx);
959 return NT_STATUS_NO_MEMORY;
963 ret = ldb_msg_add_string(msg, "objectClass", "user");
964 if (ret != LDB_SUCCESS) {
965 return NT_STATUS_NO_MEMORY;
968 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
969 if (ret != LDB_SUCCESS) {
970 return NT_STATUS_NO_MEMORY;
973 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
974 UF_INTERDOMAIN_TRUST_ACCOUNT);
975 if (ret != LDB_SUCCESS) {
976 return NT_STATUS_NO_MEMORY;
979 for (i = 0; i < in->count; i++) {
980 const char *attribute;
982 switch (in->current.array[i].AuthType) {
983 case TRUST_AUTH_TYPE_NT4OWF:
984 attribute = "unicodePwd";
985 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
988 case TRUST_AUTH_TYPE_CLEAR:
989 attribute = "clearTextPassword";
990 v.data = in->current.array[i].AuthInfo.clear.password;
991 v.length = in->current.array[i].AuthInfo.clear.size;
997 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
998 if (ret != LDB_SUCCESS) {
999 return NT_STATUS_NO_MEMORY;
1003 /* create the trusted_domain user account */
1004 ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
1005 ldb_op_default_callback, NULL);
1006 if (ret != LDB_SUCCESS) {
1007 return NT_STATUS_NO_MEMORY;
1010 ret = ldb_request_add_control(req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
1012 if (ret != LDB_SUCCESS) {
1013 return NT_STATUS_NO_MEMORY;
1016 ret = dsdb_autotransaction_request(sam_ldb, req);
1017 if (ret != LDB_SUCCESS) {
1018 DEBUG(0,("Failed to create user record %s: %s\n",
1019 ldb_dn_get_linearized(msg->dn),
1020 ldb_errstring(sam_ldb)));
1023 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1024 return NT_STATUS_DOMAIN_EXISTS;
1025 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1026 return NT_STATUS_ACCESS_DENIED;
1028 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1035 return NT_STATUS_OK;
1039 lsa_CreateTrustedDomainEx2
1041 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
1042 TALLOC_CTX *mem_ctx,
1043 struct lsa_CreateTrustedDomainEx2 *r,
1045 struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
1047 struct dcesrv_handle *policy_handle;
1048 struct lsa_policy_state *policy_state;
1049 struct lsa_trusted_domain_state *trusted_domain_state;
1050 struct dcesrv_handle *handle;
1051 struct ldb_message **msgs, *msg;
1052 const char *attrs[] = {
1055 const char *netbios_name;
1056 const char *dns_name;
1057 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1058 struct trustDomainPasswords auth_struct;
1061 struct ldb_context *sam_ldb;
1062 struct server_id *server_ids = NULL;
1063 uint32_t num_server_ids = 0;
1066 char *dns_encoded = NULL;
1067 char *netbios_encoded = NULL;
1068 char *sid_encoded = NULL;
1070 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
1071 ZERO_STRUCTP(r->out.trustdom_handle);
1073 policy_state = policy_handle->data;
1074 sam_ldb = policy_state->sam_ldb;
1076 netbios_name = r->in.info->netbios_name.string;
1077 if (!netbios_name) {
1078 return NT_STATUS_INVALID_PARAMETER;
1081 dns_name = r->in.info->domain_name.string;
1082 if (dns_name == NULL) {
1083 return NT_STATUS_INVALID_PARAMETER;
1086 if (r->in.info->sid == NULL) {
1087 return NT_STATUS_INVALID_SID;
1091 * We expect S-1-5-21-A-B-C, but we don't
1092 * allow S-1-5-21-0-0-0 as this is used
1093 * for claims and compound identities.
1095 ok = dom_sid_is_valid_account_domain(r->in.info->sid);
1097 return NT_STATUS_INVALID_PARAMETER;
1100 dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1101 if (dns_encoded == NULL) {
1102 return NT_STATUS_NO_MEMORY;
1104 netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1105 if (netbios_encoded == NULL) {
1106 return NT_STATUS_NO_MEMORY;
1108 sid_encoded = ldap_encode_ndr_dom_sid(mem_ctx, r->in.info->sid);
1109 if (sid_encoded == NULL) {
1110 return NT_STATUS_NO_MEMORY;
1113 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1114 if (!trusted_domain_state) {
1115 return NT_STATUS_NO_MEMORY;
1117 trusted_domain_state->policy = policy_state;
1119 if (strcasecmp(netbios_name, "BUILTIN") == 0
1120 || (strcasecmp(dns_name, "BUILTIN") == 0)
1121 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
1122 return NT_STATUS_INVALID_PARAMETER;
1125 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
1126 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
1127 || strcasecmp(dns_name, policy_state->domain_dns) == 0
1128 || strcasecmp(dns_name, policy_state->domain_name) == 0
1129 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
1130 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
1133 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
1134 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
1135 /* No secrets are created at this time, for this function */
1136 auth_struct.outgoing.count = 0;
1137 auth_struct.incoming.count = 0;
1138 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
1139 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
1140 r->in.auth_info_internal->auth_blob.size);
1141 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1142 &auth_blob, &auth_struct);
1143 if (!NT_STATUS_IS_OK(nt_status)) {
1146 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
1148 if (unencrypted_auth_info->incoming_count > 1) {
1149 return NT_STATUS_INVALID_PARAMETER;
1152 /* more investigation required here, do not create secrets for
1154 auth_struct.outgoing.count = 0;
1155 auth_struct.incoming.count = 0;
1157 return NT_STATUS_INVALID_PARAMETER;
1160 if (auth_struct.incoming.count) {
1161 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1162 &auth_struct.incoming,
1163 &trustAuthIncoming);
1164 if (!NT_STATUS_IS_OK(nt_status)) {
1168 trustAuthIncoming = data_blob(NULL, 0);
1171 if (auth_struct.outgoing.count) {
1172 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1173 &auth_struct.outgoing,
1174 &trustAuthOutgoing);
1175 if (!NT_STATUS_IS_OK(nt_status)) {
1179 trustAuthOutgoing = data_blob(NULL, 0);
1182 ret = ldb_transaction_start(sam_ldb);
1183 if (ret != LDB_SUCCESS) {
1184 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1187 /* search for the trusted_domain record */
1188 ret = gendb_search(sam_ldb,
1189 mem_ctx, policy_state->system_dn, &msgs, attrs,
1190 "(&(objectClass=trustedDomain)(|"
1191 "(flatname=%s)(trustPartner=%s)"
1192 "(flatname=%s)(trustPartner=%s)"
1193 "(securityIdentifier=%s)))",
1194 dns_encoded, dns_encoded,
1195 netbios_encoded, netbios_encoded,
1198 ldb_transaction_cancel(sam_ldb);
1199 return NT_STATUS_OBJECT_NAME_COLLISION;
1202 ldb_transaction_cancel(sam_ldb);
1203 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1206 msg = ldb_msg_new(mem_ctx);
1208 return NT_STATUS_NO_MEMORY;
1211 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1212 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", dns_name)) {
1213 ldb_transaction_cancel(sam_ldb);
1214 return NT_STATUS_NO_MEMORY;
1217 ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1218 if (ret != LDB_SUCCESS) {
1219 ldb_transaction_cancel(sam_ldb);
1220 return NT_STATUS_NO_MEMORY;;
1223 ret = ldb_msg_add_string(msg, "flatname", netbios_name);
1224 if (ret != LDB_SUCCESS) {
1225 ldb_transaction_cancel(sam_ldb);
1226 return NT_STATUS_NO_MEMORY;
1229 ret = ldb_msg_add_string(msg, "trustPartner", dns_name);
1230 if (ret != LDB_SUCCESS) {
1231 ldb_transaction_cancel(sam_ldb);
1232 return NT_STATUS_NO_MEMORY;;
1235 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier",
1237 if (ret != LDB_SUCCESS) {
1238 ldb_transaction_cancel(sam_ldb);
1239 return NT_STATUS_NO_MEMORY;;
1242 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1243 if (ret != LDB_SUCCESS) {
1244 ldb_transaction_cancel(sam_ldb);
1245 return NT_STATUS_NO_MEMORY;;
1248 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
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, "trustDirection", r->in.info->trust_direction);
1255 if (ret != LDB_SUCCESS) {
1256 ldb_transaction_cancel(sam_ldb);
1257 return NT_STATUS_NO_MEMORY;;
1260 if (trustAuthIncoming.data) {
1261 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1262 if (ret != LDB_SUCCESS) {
1263 ldb_transaction_cancel(sam_ldb);
1264 return NT_STATUS_NO_MEMORY;
1267 if (trustAuthOutgoing.data) {
1268 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1269 if (ret != LDB_SUCCESS) {
1270 ldb_transaction_cancel(sam_ldb);
1271 return NT_STATUS_NO_MEMORY;
1275 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1277 /* create the trusted_domain */
1278 ret = ldb_add(sam_ldb, msg);
1282 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1283 ldb_transaction_cancel(sam_ldb);
1284 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1285 ldb_dn_get_linearized(msg->dn),
1286 ldb_errstring(sam_ldb)));
1287 return NT_STATUS_DOMAIN_EXISTS;
1288 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1289 ldb_transaction_cancel(sam_ldb);
1290 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1291 ldb_dn_get_linearized(msg->dn),
1292 ldb_errstring(sam_ldb)));
1293 return NT_STATUS_ACCESS_DENIED;
1295 ldb_transaction_cancel(sam_ldb);
1296 DEBUG(0,("Failed to create user record %s: %s\n",
1297 ldb_dn_get_linearized(msg->dn),
1298 ldb_errstring(sam_ldb)));
1299 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1302 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1303 struct ldb_dn *user_dn;
1304 /* Inbound trusts must also create a cn=users object to match */
1305 nt_status = add_trust_user(mem_ctx, sam_ldb,
1306 policy_state->domain_dn,
1308 &auth_struct.incoming,
1310 if (!NT_STATUS_IS_OK(nt_status)) {
1311 ldb_transaction_cancel(sam_ldb);
1315 /* save the trust user dn */
1316 trusted_domain_state->trusted_domain_user_dn
1317 = talloc_steal(trusted_domain_state, user_dn);
1320 ret = ldb_transaction_commit(sam_ldb);
1321 if (ret != LDB_SUCCESS) {
1322 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1326 * Notify winbindd that we have a new trust
1328 status = irpc_servers_byname(dce_call->msg_ctx,
1331 &num_server_ids, &server_ids);
1332 if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
1333 imessaging_send(dce_call->msg_ctx, server_ids[0],
1334 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS, NULL);
1336 TALLOC_FREE(server_ids);
1338 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1340 return NT_STATUS_NO_MEMORY;
1343 handle->data = talloc_steal(handle, trusted_domain_state);
1345 trusted_domain_state->access_mask = r->in.access_mask;
1346 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1348 *r->out.trustdom_handle = handle->wire_handle;
1350 return NT_STATUS_OK;
1354 lsa_CreateTrustedDomainEx2
1356 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1357 TALLOC_CTX *mem_ctx,
1358 struct lsa_CreateTrustedDomainEx2 *r)
1360 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1363 lsa_CreateTrustedDomainEx
1365 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1366 TALLOC_CTX *mem_ctx,
1367 struct lsa_CreateTrustedDomainEx *r)
1369 struct lsa_CreateTrustedDomainEx2 r2;
1371 r2.in.policy_handle = r->in.policy_handle;
1372 r2.in.info = r->in.info;
1373 r2.out.trustdom_handle = r->out.trustdom_handle;
1374 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1378 lsa_CreateTrustedDomain
1380 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1381 struct lsa_CreateTrustedDomain *r)
1383 struct lsa_CreateTrustedDomainEx2 r2;
1385 r2.in.policy_handle = r->in.policy_handle;
1386 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1388 return NT_STATUS_NO_MEMORY;
1391 r2.in.info->domain_name = r->in.info->name;
1392 r2.in.info->netbios_name = r->in.info->name;
1393 r2.in.info->sid = r->in.info->sid;
1394 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1395 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1396 r2.in.info->trust_attributes = 0;
1398 r2.in.access_mask = r->in.access_mask;
1399 r2.out.trustdom_handle = r->out.trustdom_handle;
1401 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1404 static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
1405 struct dcesrv_call_state *dce_call,
1406 TALLOC_CTX *tmp_mem,
1407 struct lsa_policy_state *policy_state,
1409 uint32_t access_mask,
1410 struct dcesrv_handle **_handle)
1412 struct lsa_trusted_domain_state *trusted_domain_state;
1413 struct dcesrv_handle *handle;
1414 struct ldb_message **msgs;
1415 const char *attrs[] = {
1423 /* TODO: perform access checks */
1425 /* search for the trusted_domain record */
1426 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1427 policy_state->system_dn,
1428 &msgs, attrs, "%s", filter);
1430 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1434 DEBUG(0,("Found %d records matching %s under %s\n", ret,
1436 ldb_dn_get_linearized(policy_state->system_dn)));
1437 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1440 trusted_domain_state = talloc_zero(tmp_mem,
1441 struct lsa_trusted_domain_state);
1442 if (!trusted_domain_state) {
1443 return NT_STATUS_NO_MEMORY;
1445 trusted_domain_state->policy = policy_state;
1447 trusted_domain_state->trusted_domain_dn =
1448 talloc_steal(trusted_domain_state, msgs[0]->dn);
1450 direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1451 if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1452 const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1455 /* search for the trusted_domain account */
1456 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1457 policy_state->domain_dn,
1459 "(&(samaccountname=%s$)(objectclass=user)"
1460 "(userAccountControl:%s:=%u))",
1462 LDB_OID_COMPARATOR_AND,
1463 UF_INTERDOMAIN_TRUST_ACCOUNT);
1465 trusted_domain_state->trusted_domain_user_dn =
1466 talloc_steal(trusted_domain_state, msgs[0]->dn);
1470 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1472 return NT_STATUS_NO_MEMORY;
1475 handle->data = talloc_steal(handle, trusted_domain_state);
1477 trusted_domain_state->access_mask = access_mask;
1478 trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1483 return NT_STATUS_OK;
1487 lsa_OpenTrustedDomain
1489 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1490 struct lsa_OpenTrustedDomain *r)
1492 struct dcesrv_handle *policy_handle;
1493 struct lsa_policy_state *policy_state;
1494 struct dcesrv_handle *handle;
1495 const char *sid_string;
1499 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1500 ZERO_STRUCTP(r->out.trustdom_handle);
1501 policy_state = policy_handle->data;
1503 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1505 return NT_STATUS_NO_MEMORY;
1508 filter = talloc_asprintf(mem_ctx,
1509 "(&(securityIdentifier=%s)"
1510 "(objectclass=trustedDomain))",
1512 if (filter == NULL) {
1513 return NT_STATUS_NO_MEMORY;
1516 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1521 if (!NT_STATUS_IS_OK(status)) {
1525 *r->out.trustdom_handle = handle->wire_handle;
1527 return NT_STATUS_OK;
1532 lsa_OpenTrustedDomainByName
1534 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1535 TALLOC_CTX *mem_ctx,
1536 struct lsa_OpenTrustedDomainByName *r)
1538 struct dcesrv_handle *policy_handle;
1539 struct lsa_policy_state *policy_state;
1540 struct dcesrv_handle *handle;
1545 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1546 ZERO_STRUCTP(r->out.trustdom_handle);
1547 policy_state = policy_handle->data;
1549 if (!r->in.name.string) {
1550 return NT_STATUS_INVALID_PARAMETER;
1553 /* search for the trusted_domain record */
1554 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1555 if (td_name == NULL) {
1556 return NT_STATUS_NO_MEMORY;
1559 filter = talloc_asprintf(mem_ctx,
1560 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1561 "(objectclass=trustedDomain))",
1562 td_name, td_name, td_name);
1563 if (filter == NULL) {
1564 return NT_STATUS_NO_MEMORY;
1567 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1572 if (!NT_STATUS_IS_OK(status)) {
1576 *r->out.trustdom_handle = handle->wire_handle;
1578 return NT_STATUS_OK;
1584 lsa_SetTrustedDomainInfo
1586 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1587 struct lsa_SetTrustedDomainInfo *r)
1589 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1594 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1595 * otherwise at least one must be provided */
1596 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1597 struct ldb_dn *basedn, const char *dns_domain,
1598 const char *netbios, struct dom_sid2 *sid,
1599 struct ldb_message ***msgs)
1601 const char *attrs[] = { "flatname", "trustPartner",
1602 "securityIdentifier", "trustDirection",
1603 "trustType", "trustAttributes",
1605 "msDs-supportedEncryptionTypes",
1606 "msDS-TrustForestTrustInfo",
1611 char *sidstr = NULL;
1616 if (dns_domain || netbios || sid) {
1617 filter = talloc_strdup(mem_ctx,
1618 "(&(objectclass=trustedDomain)(|");
1620 filter = talloc_strdup(mem_ctx,
1621 "(objectclass=trustedDomain)");
1624 return NT_STATUS_NO_MEMORY;
1628 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1630 return NT_STATUS_NO_MEMORY;
1632 filter = talloc_asprintf_append(filter,
1633 "(trustPartner=%s)", dns);
1635 return NT_STATUS_NO_MEMORY;
1639 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1641 return NT_STATUS_NO_MEMORY;
1643 filter = talloc_asprintf_append(filter,
1644 "(flatname=%s)", nbn);
1646 return NT_STATUS_NO_MEMORY;
1650 sidstr = dom_sid_string(mem_ctx, sid);
1652 return NT_STATUS_INVALID_PARAMETER;
1654 filter = talloc_asprintf_append(filter,
1655 "(securityIdentifier=%s)",
1658 return NT_STATUS_NO_MEMORY;
1661 if (dns_domain || netbios || sid) {
1662 filter = talloc_asprintf_append(filter, "))");
1664 return NT_STATUS_NO_MEMORY;
1668 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1670 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1674 return NT_STATUS_OBJECT_NAME_COLLISION;
1677 return NT_STATUS_OK;
1680 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1681 struct ldb_context *sam_ldb,
1682 struct ldb_message *orig,
1683 struct ldb_message *dest,
1684 const char *attribute,
1686 uint32_t *orig_value)
1688 const struct ldb_val *orig_val;
1689 uint32_t orig_uint = 0;
1690 unsigned int flags = 0;
1693 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1694 if (!orig_val || !orig_val->data) {
1695 /* add new attribute */
1696 flags = LDB_FLAG_MOD_ADD;
1700 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1701 if (errno != 0 || orig_uint != value) {
1702 /* replace also if can't get value */
1703 flags = LDB_FLAG_MOD_REPLACE;
1708 /* stored value is identical, nothing to change */
1712 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1713 if (ret != LDB_SUCCESS) {
1714 return NT_STATUS_NO_MEMORY;
1717 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1718 if (ret != LDB_SUCCESS) {
1719 return NT_STATUS_NO_MEMORY;
1724 *orig_value = orig_uint;
1726 return NT_STATUS_OK;
1729 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1730 struct ldb_context *sam_ldb,
1731 struct ldb_dn *base_dn,
1733 const char *netbios_name,
1734 struct trustAuthInOutBlob *in)
1736 const char *attrs[] = { "userAccountControl", NULL };
1737 struct ldb_message **msgs;
1738 struct ldb_message *msg;
1743 ret = gendb_search(sam_ldb, mem_ctx,
1744 base_dn, &msgs, attrs,
1745 "samAccountName=%s$", netbios_name);
1747 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1752 return NT_STATUS_OK;
1755 /* ok no existing user, add it from scratch */
1756 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1757 netbios_name, in, NULL);
1760 /* check user is what we are looking for */
1761 uac = ldb_msg_find_attr_as_uint(msgs[0],
1762 "userAccountControl", 0);
1763 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1764 return NT_STATUS_OBJECT_NAME_COLLISION;
1768 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1771 return NT_STATUS_OK;
1772 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1773 return NT_STATUS_ACCESS_DENIED;
1775 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1779 /* entry exists, just modify secret if any */
1780 if (in == NULL || in->count == 0) {
1781 return NT_STATUS_OK;
1784 msg = ldb_msg_new(mem_ctx);
1786 return NT_STATUS_NO_MEMORY;
1788 msg->dn = msgs[0]->dn;
1790 for (i = 0; i < in->count; i++) {
1791 const char *attribute;
1793 switch (in->current.array[i].AuthType) {
1794 case TRUST_AUTH_TYPE_NT4OWF:
1795 attribute = "unicodePwd";
1796 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1799 case TRUST_AUTH_TYPE_CLEAR:
1800 attribute = "clearTextPassword";
1801 v.data = in->current.array[i].AuthInfo.clear.password;
1802 v.length = in->current.array[i].AuthInfo.clear.size;
1808 ret = ldb_msg_add_empty(msg, attribute,
1809 LDB_FLAG_MOD_REPLACE, NULL);
1810 if (ret != LDB_SUCCESS) {
1811 return NT_STATUS_NO_MEMORY;
1814 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1815 if (ret != LDB_SUCCESS) {
1816 return NT_STATUS_NO_MEMORY;
1820 /* create the trusted_domain user account */
1821 ret = ldb_modify(sam_ldb, msg);
1822 if (ret != LDB_SUCCESS) {
1823 DEBUG(0,("Failed to create user record %s: %s\n",
1824 ldb_dn_get_linearized(msg->dn),
1825 ldb_errstring(sam_ldb)));
1828 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1829 return NT_STATUS_DOMAIN_EXISTS;
1830 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1831 return NT_STATUS_ACCESS_DENIED;
1833 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1837 return NT_STATUS_OK;
1841 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1842 struct lsa_policy_state *p_state,
1843 TALLOC_CTX *mem_ctx,
1844 struct ldb_message *dom_msg,
1845 enum lsa_TrustDomInfoEnum level,
1846 union lsa_TrustedDomainInfo *info)
1848 uint32_t *posix_offset = NULL;
1849 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1850 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1851 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1852 uint32_t *enc_types = NULL;
1853 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1854 struct trustDomainPasswords auth_struct;
1855 struct trustAuthInOutBlob *current_passwords = NULL;
1857 struct ldb_message **msgs;
1858 struct ldb_message *msg;
1859 bool add_outgoing = false;
1860 bool add_incoming = false;
1861 bool del_outgoing = false;
1862 bool del_incoming = false;
1863 bool del_forest_info = false;
1864 bool in_transaction = false;
1869 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1870 posix_offset = &info->posix_offset.posix_offset;
1872 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1873 info_ex = &info->info_ex;
1875 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1876 auth_info = &info->auth_info;
1878 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1879 posix_offset = &info->full_info.posix_offset.posix_offset;
1880 info_ex = &info->full_info.info_ex;
1881 auth_info = &info->full_info.auth_info;
1883 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1884 auth_info_int = &info->auth_info_internal;
1886 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1887 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1888 info_ex = &info->full_info_internal.info_ex;
1889 auth_info_int = &info->full_info_internal.auth_info;
1891 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1892 enc_types = &info->enc_types.enc_types;
1895 return NT_STATUS_INVALID_PARAMETER;
1899 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1901 &trustAuthOutgoing);
1902 if (!NT_STATUS_IS_OK(nt_status)) {
1905 if (trustAuthIncoming.data) {
1906 /* This does the decode of some of this twice, but it is easier that way */
1907 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1908 auth_info->incoming_count,
1909 auth_info->incoming_current_auth_info,
1911 ¤t_passwords);
1912 if (!NT_STATUS_IS_OK(nt_status)) {
1918 /* decode auth_info_int if set */
1919 if (auth_info_int) {
1921 /* now decrypt blob */
1922 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1923 auth_info_int->auth_blob.size);
1925 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1926 &auth_blob, &auth_struct);
1927 if (!NT_STATUS_IS_OK(nt_status)) {
1933 /* verify data matches */
1934 if (info_ex->trust_attributes &
1935 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1936 /* TODO: check what behavior level we have */
1937 if (strcasecmp_m(p_state->domain_dns,
1938 p_state->forest_dns) != 0) {
1939 return NT_STATUS_INVALID_DOMAIN_STATE;
1943 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1944 if (ret == LDB_SUCCESS && am_rodc) {
1945 return NT_STATUS_NO_SUCH_DOMAIN;
1948 /* verify only one object matches the dns/netbios/sid
1949 * triplet and that this is the one we already have */
1950 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1952 info_ex->domain_name.string,
1953 info_ex->netbios_name.string,
1954 info_ex->sid, &msgs);
1955 if (!NT_STATUS_IS_OK(nt_status)) {
1958 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1959 return NT_STATUS_OBJECT_NAME_COLLISION;
1964 /* TODO: should we fetch previous values from the existing entry
1965 * and append them ? */
1966 if (auth_info_int && auth_struct.incoming.count) {
1967 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1968 &auth_struct.incoming,
1969 &trustAuthIncoming);
1970 if (!NT_STATUS_IS_OK(nt_status)) {
1974 current_passwords = &auth_struct.incoming;
1977 trustAuthIncoming = data_blob(NULL, 0);
1980 if (auth_info_int && auth_struct.outgoing.count) {
1981 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1982 &auth_struct.outgoing,
1983 &trustAuthOutgoing);
1984 if (!NT_STATUS_IS_OK(nt_status)) {
1988 trustAuthOutgoing = data_blob(NULL, 0);
1991 msg = ldb_msg_new(mem_ctx);
1993 return NT_STATUS_NO_MEMORY;
1995 msg->dn = dom_msg->dn;
1998 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2001 *posix_offset, NULL);
2002 if (!NT_STATUS_IS_OK(nt_status)) {
2009 uint32_t changed_attrs;
2013 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2016 info_ex->trust_direction,
2018 if (!NT_STATUS_IS_OK(nt_status)) {
2022 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2023 if (auth_info != NULL && trustAuthIncoming.length > 0) {
2024 add_incoming = true;
2027 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2028 if (auth_info != NULL && trustAuthOutgoing.length > 0) {
2029 add_outgoing = true;
2033 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
2034 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
2035 del_incoming = true;
2037 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
2038 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2039 del_outgoing = true;
2042 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
2043 if (origtype == -1 || origtype != info_ex->trust_type) {
2044 DEBUG(1, ("Attempted to change trust type! "
2045 "Operation not handled\n"));
2046 return NT_STATUS_INVALID_PARAMETER;
2049 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2052 info_ex->trust_attributes,
2054 if (!NT_STATUS_IS_OK(nt_status)) {
2057 /* TODO: check forestFunctionality from ldb opaque */
2058 /* TODO: check what is set makes sense */
2060 changed_attrs = origattrs ^ info_ex->trust_attributes;
2061 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2063 * For now we only allow
2064 * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
2066 * TODO: we may need to support more attribute changes
2068 DEBUG(1, ("Attempted to change trust attributes "
2069 "(0x%08x != 0x%08x)! "
2070 "Operation not handled yet...\n",
2071 (unsigned)origattrs,
2072 (unsigned)info_ex->trust_attributes));
2073 return NT_STATUS_INVALID_PARAMETER;
2076 if (!(info_ex->trust_attributes &
2077 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
2079 struct ldb_message_element *orig_forest_el = NULL;
2081 orig_forest_el = ldb_msg_find_element(dom_msg,
2082 "msDS-TrustForestTrustInfo");
2083 if (orig_forest_el != NULL) {
2084 del_forest_info = true;
2090 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2092 "msDS-SupportedEncryptionTypes",
2094 if (!NT_STATUS_IS_OK(nt_status)) {
2099 if (add_incoming || del_incoming) {
2100 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
2101 LDB_FLAG_MOD_REPLACE, NULL);
2102 if (ret != LDB_SUCCESS) {
2103 return NT_STATUS_NO_MEMORY;
2106 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
2107 &trustAuthIncoming, NULL);
2108 if (ret != LDB_SUCCESS) {
2109 return NT_STATUS_NO_MEMORY;
2113 if (add_outgoing || del_outgoing) {
2114 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2115 LDB_FLAG_MOD_REPLACE, NULL);
2116 if (ret != LDB_SUCCESS) {
2117 return NT_STATUS_NO_MEMORY;
2120 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
2121 &trustAuthOutgoing, NULL);
2122 if (ret != LDB_SUCCESS) {
2123 return NT_STATUS_NO_MEMORY;
2127 if (del_forest_info) {
2128 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
2129 LDB_FLAG_MOD_REPLACE, NULL);
2130 if (ret != LDB_SUCCESS) {
2131 return NT_STATUS_NO_MEMORY;
2135 /* start transaction */
2136 ret = ldb_transaction_start(p_state->sam_ldb);
2137 if (ret != LDB_SUCCESS) {
2138 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2140 in_transaction = true;
2142 if (msg->num_elements) {
2143 ret = ldb_modify(p_state->sam_ldb, msg);
2144 if (ret != LDB_SUCCESS) {
2145 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
2146 ldb_dn_get_linearized(msg->dn),
2147 ldb_errstring(p_state->sam_ldb)));
2148 nt_status = dsdb_ldb_err_to_ntstatus(ret);
2153 if (add_incoming || del_incoming) {
2154 const char *netbios_name;
2156 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
2158 if (!netbios_name) {
2159 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
2163 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
2164 nt_status = update_trust_user(mem_ctx,
2170 if (!NT_STATUS_IS_OK(nt_status)) {
2175 /* ok, all fine, commit transaction and return */
2176 ret = ldb_transaction_commit(p_state->sam_ldb);
2177 if (ret != LDB_SUCCESS) {
2178 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2180 in_transaction = false;
2182 nt_status = NT_STATUS_OK;
2185 if (in_transaction) {
2186 ldb_transaction_cancel(p_state->sam_ldb);
2192 lsa_SetInfomrationTrustedDomain
2194 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
2195 struct dcesrv_call_state *dce_call,
2196 TALLOC_CTX *mem_ctx,
2197 struct lsa_SetInformationTrustedDomain *r)
2199 struct dcesrv_handle *h;
2200 struct lsa_trusted_domain_state *td_state;
2201 struct ldb_message **msgs;
2204 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
2205 LSA_HANDLE_TRUSTED_DOMAIN);
2207 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2209 /* get the trusted domain object */
2210 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
2211 td_state->trusted_domain_dn,
2212 NULL, NULL, NULL, &msgs);
2213 if (!NT_STATUS_IS_OK(nt_status)) {
2214 if (NT_STATUS_EQUAL(nt_status,
2215 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2218 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2221 return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
2222 msgs[0], r->in.level, r->in.info);
2227 lsa_DeleteTrustedDomain
2229 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2230 struct lsa_DeleteTrustedDomain *r)
2233 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2234 struct lsa_DeleteObject del;
2235 struct dcesrv_handle *h;
2237 opn.in.handle = r->in.handle;
2238 opn.in.sid = r->in.dom_sid;
2239 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2240 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2241 if (!opn.out.trustdom_handle) {
2242 return NT_STATUS_NO_MEMORY;
2244 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2245 if (!NT_STATUS_IS_OK(status)) {
2249 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2250 talloc_steal(mem_ctx, h);
2252 del.in.handle = opn.out.trustdom_handle;
2253 del.out.handle = opn.out.trustdom_handle;
2254 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2255 if (!NT_STATUS_IS_OK(status)) {
2258 return NT_STATUS_OK;
2261 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2262 struct ldb_message *msg,
2263 struct lsa_TrustDomainInfoInfoEx *info_ex)
2265 info_ex->domain_name.string
2266 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2267 info_ex->netbios_name.string
2268 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2270 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2271 info_ex->trust_direction
2272 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2274 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2275 info_ex->trust_attributes
2276 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2277 return NT_STATUS_OK;
2281 lsa_QueryTrustedDomainInfo
2283 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2284 struct lsa_QueryTrustedDomainInfo *r)
2286 union lsa_TrustedDomainInfo *info = NULL;
2287 struct dcesrv_handle *h;
2288 struct lsa_trusted_domain_state *trusted_domain_state;
2289 struct ldb_message *msg;
2291 struct ldb_message **res;
2292 const char *attrs[] = {
2295 "securityIdentifier",
2299 "msDs-supportedEncryptionTypes",
2303 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2305 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2307 /* pull all the user attributes */
2308 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2309 trusted_domain_state->trusted_domain_dn, &res, attrs);
2311 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2315 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2317 return NT_STATUS_NO_MEMORY;
2319 *r->out.info = info;
2321 switch (r->in.level) {
2322 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2323 info->name.netbios_name.string
2324 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2326 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2327 info->posix_offset.posix_offset
2328 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2330 #if 0 /* Win2k3 doesn't implement this */
2331 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2332 r->out.info->info_basic.netbios_name.string
2333 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2334 r->out.info->info_basic.sid
2335 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2338 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2339 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2341 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2342 ZERO_STRUCT(info->full_info);
2343 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2344 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2345 ZERO_STRUCT(info->full_info2_internal);
2346 info->full_info2_internal.posix_offset.posix_offset
2347 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2348 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2350 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2351 info->enc_types.enc_types
2352 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2355 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2356 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2357 /* oops, we don't want to return the info after all */
2359 *r->out.info = NULL;
2360 return NT_STATUS_INVALID_PARAMETER;
2362 /* oops, we don't want to return the info after all */
2364 *r->out.info = NULL;
2365 return NT_STATUS_INVALID_INFO_CLASS;
2368 return NT_STATUS_OK;
2373 lsa_QueryTrustedDomainInfoBySid
2375 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2376 struct lsa_QueryTrustedDomainInfoBySid *r)
2379 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2380 struct lsa_QueryTrustedDomainInfo query;
2381 struct dcesrv_handle *h;
2383 opn.in.handle = r->in.handle;
2384 opn.in.sid = r->in.dom_sid;
2385 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2386 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2387 if (!opn.out.trustdom_handle) {
2388 return NT_STATUS_NO_MEMORY;
2390 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2391 if (!NT_STATUS_IS_OK(status)) {
2395 /* Ensure this handle goes away at the end of this call */
2396 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2397 talloc_steal(mem_ctx, h);
2399 query.in.trustdom_handle = opn.out.trustdom_handle;
2400 query.in.level = r->in.level;
2401 query.out.info = r->out.info;
2402 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2403 if (!NT_STATUS_IS_OK(status)) {
2407 return NT_STATUS_OK;
2411 lsa_SetTrustedDomainInfoByName
2413 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2414 TALLOC_CTX *mem_ctx,
2415 struct lsa_SetTrustedDomainInfoByName *r)
2417 struct dcesrv_handle *policy_handle;
2418 struct lsa_policy_state *policy_state;
2419 struct ldb_message **msgs;
2422 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2423 policy_state = policy_handle->data;
2425 /* get the trusted domain object */
2426 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2427 policy_state->domain_dn,
2428 r->in.trusted_domain->string,
2429 r->in.trusted_domain->string,
2431 if (!NT_STATUS_IS_OK(nt_status)) {
2432 if (NT_STATUS_EQUAL(nt_status,
2433 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2436 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2439 return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2440 msgs[0], r->in.level, r->in.info);
2444 lsa_QueryTrustedDomainInfoByName
2446 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2447 TALLOC_CTX *mem_ctx,
2448 struct lsa_QueryTrustedDomainInfoByName *r)
2451 struct lsa_OpenTrustedDomainByName opn = {{0},{0}};
2452 struct lsa_QueryTrustedDomainInfo query;
2453 struct dcesrv_handle *h;
2455 opn.in.handle = r->in.handle;
2456 opn.in.name = *r->in.trusted_domain;
2457 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2458 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2459 if (!opn.out.trustdom_handle) {
2460 return NT_STATUS_NO_MEMORY;
2462 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2463 if (!NT_STATUS_IS_OK(status)) {
2467 /* Ensure this handle goes away at the end of this call */
2468 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2469 talloc_steal(mem_ctx, h);
2471 query.in.trustdom_handle = opn.out.trustdom_handle;
2472 query.in.level = r->in.level;
2473 query.out.info = r->out.info;
2474 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2475 if (!NT_STATUS_IS_OK(status)) {
2479 return NT_STATUS_OK;
2483 lsa_CloseTrustedDomainEx
2485 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2486 TALLOC_CTX *mem_ctx,
2487 struct lsa_CloseTrustedDomainEx *r)
2489 /* The result of a bad hair day from an IDL programmer? Not
2490 * implmented in Win2k3. You should always just lsa_Close
2492 return NT_STATUS_NOT_IMPLEMENTED;
2497 comparison function for sorting lsa_DomainInformation array
2499 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2501 return strcasecmp_m(e1->name.string, e2->name.string);
2507 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2508 struct lsa_EnumTrustDom *r)
2510 struct dcesrv_handle *policy_handle;
2511 struct lsa_DomainInfo *entries;
2512 struct lsa_policy_state *policy_state;
2513 struct ldb_message **domains;
2514 const char *attrs[] = {
2516 "securityIdentifier",
2523 *r->out.resume_handle = 0;
2525 r->out.domains->domains = NULL;
2526 r->out.domains->count = 0;
2528 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2530 policy_state = policy_handle->data;
2532 /* search for all users in this domain. This could possibly be cached and
2533 resumed based on resume_key */
2534 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2535 "objectclass=trustedDomain");
2537 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2540 /* convert to lsa_TrustInformation format */
2541 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2543 return NT_STATUS_NO_MEMORY;
2545 for (i=0;i<count;i++) {
2546 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2547 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2550 /* sort the results by name */
2551 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2553 if (*r->in.resume_handle >= count) {
2554 *r->out.resume_handle = -1;
2556 return NT_STATUS_NO_MORE_ENTRIES;
2559 /* return the rest, limit by max_size. Note that we
2560 use the w2k3 element size value of 60 */
2561 r->out.domains->count = count - *r->in.resume_handle;
2562 r->out.domains->count = MIN(r->out.domains->count,
2563 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2565 r->out.domains->domains = entries + *r->in.resume_handle;
2567 if (r->out.domains->count < count - *r->in.resume_handle) {
2568 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2569 return STATUS_MORE_ENTRIES;
2572 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2573 * always be larger than the previous input resume handle, in
2574 * particular when hitting the last query it is vital to set the
2575 * resume handle correctly to avoid infinite client loops, as
2576 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2577 * status is NT_STATUS_OK - gd */
2579 *r->out.resume_handle = (uint32_t)-1;
2581 return NT_STATUS_OK;
2585 comparison function for sorting lsa_DomainInformation array
2587 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2589 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2593 lsa_EnumTrustedDomainsEx
2595 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2596 struct lsa_EnumTrustedDomainsEx *r)
2598 struct dcesrv_handle *policy_handle;
2599 struct lsa_TrustDomainInfoInfoEx *entries;
2600 struct lsa_policy_state *policy_state;
2601 struct ldb_message **domains;
2602 const char *attrs[] = {
2605 "securityIdentifier",
2615 *r->out.resume_handle = 0;
2617 r->out.domains->domains = NULL;
2618 r->out.domains->count = 0;
2620 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2622 policy_state = policy_handle->data;
2624 /* search for all users in this domain. This could possibly be cached and
2625 resumed based on resume_key */
2626 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2627 "objectclass=trustedDomain");
2629 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2632 /* convert to lsa_DomainInformation format */
2633 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2635 return NT_STATUS_NO_MEMORY;
2637 for (i=0;i<count;i++) {
2638 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2639 if (!NT_STATUS_IS_OK(nt_status)) {
2644 /* sort the results by name */
2645 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2647 if (*r->in.resume_handle >= count) {
2648 *r->out.resume_handle = -1;
2650 return NT_STATUS_NO_MORE_ENTRIES;
2653 /* return the rest, limit by max_size. Note that we
2654 use the w2k3 element size value of 60 */
2655 r->out.domains->count = count - *r->in.resume_handle;
2656 r->out.domains->count = MIN(r->out.domains->count,
2657 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2659 r->out.domains->domains = entries + *r->in.resume_handle;
2661 if (r->out.domains->count < count - *r->in.resume_handle) {
2662 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2663 return STATUS_MORE_ENTRIES;
2666 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2668 return NT_STATUS_OK;
2675 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2676 struct lsa_OpenAccount *r)
2678 struct dcesrv_handle *h, *ah;
2679 struct lsa_policy_state *state;
2680 struct lsa_account_state *astate;
2682 ZERO_STRUCTP(r->out.acct_handle);
2684 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2688 astate = talloc(dce_call->conn, struct lsa_account_state);
2689 if (astate == NULL) {
2690 return NT_STATUS_NO_MEMORY;
2693 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2694 if (astate->account_sid == NULL) {
2695 talloc_free(astate);
2696 return NT_STATUS_NO_MEMORY;
2699 astate->policy = talloc_reference(astate, state);
2700 astate->access_mask = r->in.access_mask;
2703 * For now we grant all requested access.
2705 * We will fail at the ldb layer later.
2707 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2708 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2709 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2711 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2713 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2714 __func__, dom_sid_string(mem_ctx, astate->account_sid),
2715 (unsigned)r->in.access_mask,
2716 (unsigned)astate->access_mask));
2718 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2720 talloc_free(astate);
2721 return NT_STATUS_NO_MEMORY;
2724 ah->data = talloc_steal(ah, astate);
2726 *r->out.acct_handle = ah->wire_handle;
2728 return NT_STATUS_OK;
2733 lsa_EnumPrivsAccount
2735 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2736 TALLOC_CTX *mem_ctx,
2737 struct lsa_EnumPrivsAccount *r)
2739 struct dcesrv_handle *h;
2740 struct lsa_account_state *astate;
2743 struct ldb_message **res;
2744 const char * const attrs[] = { "privilege", NULL};
2745 struct ldb_message_element *el;
2747 struct lsa_PrivilegeSet *privs;
2749 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2753 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2754 if (privs == NULL) {
2755 return NT_STATUS_NO_MEMORY;
2761 *r->out.privs = privs;
2763 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2764 if (sidstr == NULL) {
2765 return NT_STATUS_NO_MEMORY;
2768 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2769 "objectSid=%s", sidstr);
2771 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2774 return NT_STATUS_OK;
2777 el = ldb_msg_find_element(res[0], "privilege");
2778 if (el == NULL || el->num_values == 0) {
2779 return NT_STATUS_OK;
2782 privs->set = talloc_array(privs,
2783 struct lsa_LUIDAttribute, el->num_values);
2784 if (privs->set == NULL) {
2785 return NT_STATUS_NO_MEMORY;
2789 for (i=0;i<el->num_values;i++) {
2790 int id = sec_privilege_id((const char *)el->values[i].data);
2791 if (id == SEC_PRIV_INVALID) {
2792 /* Perhaps an account right, not a privilege */
2795 privs->set[j].attribute = 0;
2796 privs->set[j].luid.low = id;
2797 privs->set[j].luid.high = 0;
2803 return NT_STATUS_OK;
2807 lsa_EnumAccountRights
2809 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2810 TALLOC_CTX *mem_ctx,
2811 struct lsa_EnumAccountRights *r)
2813 struct dcesrv_handle *h;
2814 struct lsa_policy_state *state;
2817 struct ldb_message **res;
2818 const char * const attrs[] = { "privilege", NULL};
2820 struct ldb_message_element *el;
2822 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2826 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2827 if (sidstr == NULL) {
2828 return NT_STATUS_NO_MEMORY;
2831 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2832 "(&(objectSid=%s)(privilege=*))", sidstr);
2834 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2837 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2838 dom_sid_string(mem_ctx, r->in.sid),
2839 ldb_errstring(state->pdb)));
2840 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2843 el = ldb_msg_find_element(res[0], "privilege");
2844 if (el == NULL || el->num_values == 0) {
2845 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2848 r->out.rights->count = el->num_values;
2849 r->out.rights->names = talloc_array(r->out.rights,
2850 struct lsa_StringLarge, r->out.rights->count);
2851 if (r->out.rights->names == NULL) {
2852 return NT_STATUS_NO_MEMORY;
2855 for (i=0;i<el->num_values;i++) {
2856 r->out.rights->names[i].string = (const char *)el->values[i].data;
2859 return NT_STATUS_OK;
2865 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2867 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2868 TALLOC_CTX *mem_ctx,
2869 struct lsa_policy_state *state,
2871 struct dom_sid *sid,
2872 const struct lsa_RightSet *rights)
2874 const char *sidstr, *sidndrstr;
2875 struct ldb_message *msg;
2876 struct ldb_message_element *el;
2879 struct lsa_EnumAccountRights r2;
2882 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2883 SECURITY_ADMINISTRATOR) {
2884 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2885 return NT_STATUS_ACCESS_DENIED;
2888 msg = ldb_msg_new(mem_ctx);
2890 return NT_STATUS_NO_MEMORY;
2893 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2894 if (sidndrstr == NULL) {
2896 return NT_STATUS_NO_MEMORY;
2899 sidstr = dom_sid_string(msg, sid);
2900 if (sidstr == NULL) {
2902 return NT_STATUS_NO_MEMORY;
2905 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2906 if (dnstr == NULL) {
2908 return NT_STATUS_NO_MEMORY;
2911 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2912 if (msg->dn == NULL) {
2914 return NT_STATUS_NO_MEMORY;
2917 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2920 r2.in.handle = &state->handle->wire_handle;
2922 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2924 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2925 if (!NT_STATUS_IS_OK(status)) {
2926 ZERO_STRUCTP(r2.out.rights);
2930 for (i=0;i<rights->count;i++) {
2933 ok = dcesrc_lsa_valid_AccountRight(rights->names[i].string);
2936 return NT_STATUS_NO_SUCH_PRIVILEGE;
2939 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2941 for (j=0;j<r2.out.rights->count;j++) {
2942 if (strcasecmp_m(r2.out.rights->names[j].string,
2943 rights->names[i].string) == 0) {
2947 if (j != r2.out.rights->count) continue;
2950 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2951 if (ret != LDB_SUCCESS) {
2953 return NT_STATUS_NO_MEMORY;
2957 el = ldb_msg_find_element(msg, "privilege");
2960 return NT_STATUS_OK;
2963 el->flags = ldb_flag;
2965 ret = ldb_modify(state->pdb, msg);
2966 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2967 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2969 return NT_STATUS_NO_MEMORY;
2971 ldb_msg_add_string(msg, "comment", "added via LSA");
2972 ret = ldb_add(state->pdb, msg);
2974 if (ret != LDB_SUCCESS) {
2975 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2977 return NT_STATUS_OK;
2979 DEBUG(3, ("Could not %s attributes from %s: %s",
2980 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2981 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2983 return NT_STATUS_UNEXPECTED_IO_ERROR;
2987 return NT_STATUS_OK;
2991 lsa_AddPrivilegesToAccount
2993 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2994 struct lsa_AddPrivilegesToAccount *r)
2996 struct lsa_RightSet rights;
2997 struct dcesrv_handle *h;
2998 struct lsa_account_state *astate;
3001 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3005 rights.count = r->in.privs->count;
3006 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
3007 if (rights.names == NULL) {
3008 return NT_STATUS_NO_MEMORY;
3010 for (i=0;i<rights.count;i++) {
3011 int id = r->in.privs->set[i].luid.low;
3012 if (r->in.privs->set[i].luid.high) {
3013 return NT_STATUS_NO_SUCH_PRIVILEGE;
3015 rights.names[i].string = sec_privilege_name(id);
3016 if (rights.names[i].string == NULL) {
3017 return NT_STATUS_NO_SUCH_PRIVILEGE;
3021 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3022 LDB_FLAG_MOD_ADD, astate->account_sid,
3028 lsa_RemovePrivilegesFromAccount
3030 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3031 struct lsa_RemovePrivilegesFromAccount *r)
3033 struct lsa_RightSet *rights;
3034 struct dcesrv_handle *h;
3035 struct lsa_account_state *astate;
3038 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3042 rights = talloc(mem_ctx, struct lsa_RightSet);
3044 if (r->in.remove_all == 1 &&
3045 r->in.privs == NULL) {
3046 struct lsa_EnumAccountRights r2;
3049 r2.in.handle = &astate->policy->handle->wire_handle;
3050 r2.in.sid = astate->account_sid;
3051 r2.out.rights = rights;
3053 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
3054 if (!NT_STATUS_IS_OK(status)) {
3058 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3059 LDB_FLAG_MOD_DELETE, astate->account_sid,
3063 if (r->in.remove_all != 0) {
3064 return NT_STATUS_INVALID_PARAMETER;
3067 rights->count = r->in.privs->count;
3068 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
3069 if (rights->names == NULL) {
3070 return NT_STATUS_NO_MEMORY;
3072 for (i=0;i<rights->count;i++) {
3073 int id = r->in.privs->set[i].luid.low;
3074 if (r->in.privs->set[i].luid.high) {
3075 return NT_STATUS_NO_SUCH_PRIVILEGE;
3077 rights->names[i].string = sec_privilege_name(id);
3078 if (rights->names[i].string == NULL) {
3079 return NT_STATUS_NO_SUCH_PRIVILEGE;
3083 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3084 LDB_FLAG_MOD_DELETE, astate->account_sid,
3090 lsa_GetQuotasForAccount
3092 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3093 struct lsa_GetQuotasForAccount *r)
3095 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3100 lsa_SetQuotasForAccount
3102 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3103 struct lsa_SetQuotasForAccount *r)
3105 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3110 lsa_GetSystemAccessAccount
3112 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3113 struct lsa_GetSystemAccessAccount *r)
3115 struct dcesrv_handle *h;
3116 struct lsa_account_state *astate;
3119 struct ldb_message **res;
3120 const char * const attrs[] = { "privilege", NULL};
3121 struct ldb_message_element *el;
3124 *(r->out.access_mask) = 0x00000000;
3126 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3130 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
3131 if (sidstr == NULL) {
3132 return NT_STATUS_NO_MEMORY;
3135 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
3136 "objectSid=%s", sidstr);
3138 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3141 return NT_STATUS_OK;
3144 el = ldb_msg_find_element(res[0], "privilege");
3145 if (el == NULL || el->num_values == 0) {
3146 return NT_STATUS_OK;
3149 for (i=0;i<el->num_values;i++) {
3150 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
3151 if (right_bit == 0) {
3152 /* Perhaps an privilege, not a right */
3155 *(r->out.access_mask) |= right_bit;
3158 return NT_STATUS_OK;
3163 lsa_SetSystemAccessAccount
3165 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3166 struct lsa_SetSystemAccessAccount *r)
3168 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3175 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3176 struct lsa_CreateSecret *r)
3178 struct dcesrv_handle *policy_handle;
3179 struct lsa_policy_state *policy_state;
3180 struct lsa_secret_state *secret_state;
3181 struct dcesrv_handle *handle;
3182 struct ldb_message **msgs, *msg;
3183 struct ldb_context *samdb = NULL;
3184 const char *attrs[] = {
3192 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3193 ZERO_STRUCTP(r->out.sec_handle);
3195 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3197 case SECURITY_SYSTEM:
3198 case SECURITY_ADMINISTRATOR:
3201 /* Users and annonymous are not allowed create secrets */
3202 return NT_STATUS_ACCESS_DENIED;
3205 policy_state = policy_handle->data;
3207 if (!r->in.name.string) {
3208 return NT_STATUS_INVALID_PARAMETER;
3211 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3212 NT_STATUS_HAVE_NO_MEMORY(secret_state);
3213 secret_state->policy = policy_state;
3215 msg = ldb_msg_new(mem_ctx);
3217 return NT_STATUS_NO_MEMORY;
3220 if (strncmp("G$", r->in.name.string, 2) == 0) {
3223 secret_state->global = true;
3225 name = &r->in.name.string[2];
3226 if (strlen(name) == 0) {
3227 return NT_STATUS_INVALID_PARAMETER;
3230 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3231 ldb_binary_encode_string(mem_ctx, name));
3232 NT_STATUS_HAVE_NO_MEMORY(name2);
3234 /* We need to connect to the database as system, as this is one
3235 * of the rare RPC calls that must read the secrets (and this
3236 * is denied otherwise) */
3237 samdb = samdb_connect(
3239 dce_call->event_ctx,
3240 dce_call->conn->dce_ctx->lp_ctx,
3241 system_session(dce_call->conn->dce_ctx->lp_ctx),
3242 dce_call->conn->remote_address,
3244 secret_state->sam_ldb = talloc_reference(secret_state, samdb);
3245 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3247 /* search for the secret record */
3248 ret = gendb_search(secret_state->sam_ldb,
3249 mem_ctx, policy_state->system_dn, &msgs, attrs,
3250 "(&(cn=%s)(objectclass=secret))",
3253 return NT_STATUS_OBJECT_NAME_COLLISION;
3257 DEBUG(0,("Failure searching for CN=%s: %s\n",
3258 name2, ldb_errstring(secret_state->sam_ldb)));
3259 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3262 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3263 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3264 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3265 return NT_STATUS_NO_MEMORY;
3268 ret = ldb_msg_add_string(msg, "cn", name2);
3269 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3271 secret_state->global = false;
3273 name = r->in.name.string;
3274 if (strlen(name) == 0) {
3275 return NT_STATUS_INVALID_PARAMETER;
3278 secret_state->sam_ldb = talloc_reference(secret_state,
3279 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3280 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3282 /* search for the secret record */
3283 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3284 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3286 "(&(cn=%s)(objectclass=secret))",
3287 ldb_binary_encode_string(mem_ctx, name));
3289 return NT_STATUS_OBJECT_NAME_COLLISION;
3293 DEBUG(0,("Failure searching for CN=%s: %s\n",
3294 name, ldb_errstring(secret_state->sam_ldb)));
3295 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3298 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3299 "cn=%s,cn=LSA Secrets", name);
3300 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3301 ret = ldb_msg_add_string(msg, "cn", name);
3302 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3305 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3306 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3308 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3309 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3311 /* create the secret */
3312 ret = ldb_add(secret_state->sam_ldb, msg);
3313 if (ret != LDB_SUCCESS) {
3314 DEBUG(0,("Failed to create secret record %s: %s\n",
3315 ldb_dn_get_linearized(msg->dn),
3316 ldb_errstring(secret_state->sam_ldb)));
3317 return NT_STATUS_ACCESS_DENIED;
3320 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3321 NT_STATUS_HAVE_NO_MEMORY(handle);
3323 handle->data = talloc_steal(handle, secret_state);
3325 secret_state->access_mask = r->in.access_mask;
3326 secret_state->policy = talloc_reference(secret_state, policy_state);
3327 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3329 *r->out.sec_handle = handle->wire_handle;
3331 return NT_STATUS_OK;
3338 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3339 struct lsa_OpenSecret *r)
3341 struct dcesrv_handle *policy_handle;
3343 struct lsa_policy_state *policy_state;
3344 struct lsa_secret_state *secret_state;
3345 struct dcesrv_handle *handle;
3346 struct ldb_message **msgs;
3347 struct ldb_context *samdb = NULL;
3348 const char *attrs[] = {
3356 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3357 ZERO_STRUCTP(r->out.sec_handle);
3358 policy_state = policy_handle->data;
3360 if (!r->in.name.string) {
3361 return NT_STATUS_INVALID_PARAMETER;
3364 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3366 case SECURITY_SYSTEM:
3367 case SECURITY_ADMINISTRATOR:
3370 /* Users and annonymous are not allowed to access secrets */
3371 return NT_STATUS_ACCESS_DENIED;
3374 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3375 if (!secret_state) {
3376 return NT_STATUS_NO_MEMORY;
3378 secret_state->policy = policy_state;
3380 if (strncmp("G$", r->in.name.string, 2) == 0) {
3381 name = &r->in.name.string[2];
3382 /* 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) */
3383 samdb = samdb_connect(
3385 dce_call->event_ctx,
3386 dce_call->conn->dce_ctx->lp_ctx,
3387 system_session(dce_call->conn->dce_ctx->lp_ctx),
3388 dce_call->conn->remote_address,
3390 secret_state->sam_ldb = talloc_reference(secret_state, samdb);
3391 secret_state->global = true;
3393 if (strlen(name) < 1) {
3394 return NT_STATUS_INVALID_PARAMETER;
3397 /* search for the secret record */
3398 ret = gendb_search(secret_state->sam_ldb,
3399 mem_ctx, policy_state->system_dn, &msgs, attrs,
3400 "(&(cn=%s Secret)(objectclass=secret))",
3401 ldb_binary_encode_string(mem_ctx, name));
3403 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3407 DEBUG(0,("Found %d records matching DN %s\n", ret,
3408 ldb_dn_get_linearized(policy_state->system_dn)));
3409 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3412 secret_state->global = false;
3413 secret_state->sam_ldb = talloc_reference(secret_state,
3414 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3416 name = r->in.name.string;
3417 if (strlen(name) < 1) {
3418 return NT_STATUS_INVALID_PARAMETER;
3421 /* search for the secret record */
3422 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3423 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3425 "(&(cn=%s)(objectclass=secret))",
3426 ldb_binary_encode_string(mem_ctx, name));
3428 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3432 DEBUG(0,("Found %d records matching CN=%s\n",
3433 ret, ldb_binary_encode_string(mem_ctx, name)));
3434 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3438 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3440 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3442 return NT_STATUS_NO_MEMORY;
3445 handle->data = talloc_steal(handle, secret_state);
3447 secret_state->access_mask = r->in.access_mask;
3448 secret_state->policy = talloc_reference(secret_state, policy_state);
3450 *r->out.sec_handle = handle->wire_handle;
3452 return NT_STATUS_OK;
3459 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3460 struct lsa_SetSecret *r)
3463 struct dcesrv_handle *h;
3464 struct lsa_secret_state *secret_state;
3465 struct ldb_message *msg;
3466 DATA_BLOB session_key;
3467 DATA_BLOB crypt_secret, secret;
3470 NTSTATUS status = NT_STATUS_OK;
3472 struct timeval now = timeval_current();
3473 NTTIME nt_now = timeval_to_nttime(&now);
3475 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3477 secret_state = h->data;
3479 msg = ldb_msg_new(mem_ctx);
3481 return NT_STATUS_NO_MEMORY;
3484 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3486 return NT_STATUS_NO_MEMORY;
3488 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3489 if (!NT_STATUS_IS_OK(status)) {
3493 if (r->in.old_val) {
3495 crypt_secret.data = r->in.old_val->data;
3496 crypt_secret.length = r->in.old_val->size;
3498 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3499 if (!NT_STATUS_IS_OK(status)) {
3503 val.data = secret.data;
3504 val.length = secret.length;
3507 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3508 return NT_STATUS_NO_MEMORY;
3511 /* set old value mtime */
3512 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3513 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3514 return NT_STATUS_NO_MEMORY;
3518 /* If the old value is not set, then migrate the
3519 * current value to the old value */
3520 const struct ldb_val *old_val;
3521 NTTIME last_set_time;
3522 struct ldb_message **res;
3523 const char *attrs[] = {
3529 /* search for the secret record */
3530 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3531 secret_state->secret_dn, &res, attrs);
3533 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3537 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3538 ldb_dn_get_linearized(secret_state->secret_dn)));
3539 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3542 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3543 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3547 if (ldb_msg_add_value(msg, "priorValue",
3548 old_val, NULL) != LDB_SUCCESS) {
3549 return NT_STATUS_NO_MEMORY;
3552 if (samdb_msg_add_delete(secret_state->sam_ldb,
3553 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3554 return NT_STATUS_NO_MEMORY;
3558 /* set old value mtime */
3559 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3560 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3561 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3562 return NT_STATUS_NO_MEMORY;
3565 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3566 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3567 return NT_STATUS_NO_MEMORY;
3572 if (r->in.new_val) {
3574 crypt_secret.data = r->in.new_val->data;
3575 crypt_secret.length = r->in.new_val->size;
3577 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3578 if (!NT_STATUS_IS_OK(status)) {
3582 val.data = secret.data;
3583 val.length = secret.length;
3586 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3587 return NT_STATUS_NO_MEMORY;
3590 /* set new value mtime */
3591 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3592 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3593 return NT_STATUS_NO_MEMORY;
3596 /* NULL out the NEW value */
3597 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3598 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3599 return NT_STATUS_NO_MEMORY;
3601 if (samdb_msg_add_delete(secret_state->sam_ldb,
3602 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3603 return NT_STATUS_NO_MEMORY;
3607 /* modify the samdb record */
3608 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3609 if (ret != LDB_SUCCESS) {
3610 return dsdb_ldb_err_to_ntstatus(ret);
3613 return NT_STATUS_OK;
3620 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3621 struct lsa_QuerySecret *r)
3623 struct dcesrv_handle *h;
3624 struct lsa_secret_state *secret_state;
3625 struct ldb_message *msg;
3626 DATA_BLOB session_key;
3627 DATA_BLOB crypt_secret, secret;
3629 struct ldb_message **res;
3630 const char *attrs[] = {
3640 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3642 /* Ensure user is permitted to read this... */
3643 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3645 case SECURITY_SYSTEM:
3646 case SECURITY_ADMINISTRATOR:
3649 /* Users and annonymous are not allowed to read secrets */
3650 return NT_STATUS_ACCESS_DENIED;
3653 secret_state = h->data;
3655 /* pull all the user attributes */
3656 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3657 secret_state->secret_dn, &res, attrs);
3659 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3663 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3664 if (!NT_STATUS_IS_OK(nt_status)) {
3668 if (r->in.old_val) {
3669 const struct ldb_val *prior_val;
3670 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3671 if (!r->out.old_val) {
3672 return NT_STATUS_NO_MEMORY;
3674 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3676 if (prior_val && prior_val->length) {
3677 secret.data = prior_val->data;
3678 secret.length = prior_val->length;
3681 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3682 if (!crypt_secret.length) {
3683 return NT_STATUS_NO_MEMORY;
3685 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3686 if (!r->out.old_val->buf) {
3687 return NT_STATUS_NO_MEMORY;
3689 r->out.old_val->buf->size = crypt_secret.length;
3690 r->out.old_val->buf->length = crypt_secret.length;
3691 r->out.old_val->buf->data = crypt_secret.data;
3695 if (r->in.old_mtime) {
3696 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3697 if (!r->out.old_mtime) {
3698 return NT_STATUS_NO_MEMORY;
3700 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3703 if (r->in.new_val) {
3704 const struct ldb_val *new_val;
3705 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3706 if (!r->out.new_val) {
3707 return NT_STATUS_NO_MEMORY;
3710 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3712 if (new_val && new_val->length) {
3713 secret.data = new_val->data;
3714 secret.length = new_val->length;
3717 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3718 if (!crypt_secret.length) {
3719 return NT_STATUS_NO_MEMORY;
3721 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3722 if (!r->out.new_val->buf) {
3723 return NT_STATUS_NO_MEMORY;
3725 r->out.new_val->buf->length = crypt_secret.length;
3726 r->out.new_val->buf->size = crypt_secret.length;
3727 r->out.new_val->buf->data = crypt_secret.data;
3731 if (r->in.new_mtime) {
3732 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3733 if (!r->out.new_mtime) {
3734 return NT_STATUS_NO_MEMORY;
3736 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3739 return NT_STATUS_OK;
3746 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3747 TALLOC_CTX *mem_ctx,
3748 struct lsa_LookupPrivValue *r)
3750 struct dcesrv_handle *h;
3753 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3755 id = sec_privilege_id(r->in.name->string);
3756 if (id == SEC_PRIV_INVALID) {
3757 return NT_STATUS_NO_SUCH_PRIVILEGE;
3760 r->out.luid->low = id;
3761 r->out.luid->high = 0;
3763 return NT_STATUS_OK;
3770 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3771 TALLOC_CTX *mem_ctx,
3772 struct lsa_LookupPrivName *r)
3774 struct dcesrv_handle *h;
3775 struct lsa_StringLarge *name;
3776 const char *privname;
3778 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3780 if (r->in.luid->high != 0) {
3781 return NT_STATUS_NO_SUCH_PRIVILEGE;
3784 privname = sec_privilege_name(r->in.luid->low);
3785 if (privname == NULL) {
3786 return NT_STATUS_NO_SUCH_PRIVILEGE;
3789 name = talloc(mem_ctx, struct lsa_StringLarge);
3791 return NT_STATUS_NO_MEMORY;
3794 name->string = privname;
3796 *r->out.name = name;
3798 return NT_STATUS_OK;
3803 lsa_LookupPrivDisplayName
3805 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3806 TALLOC_CTX *mem_ctx,
3807 struct lsa_LookupPrivDisplayName *r)
3809 struct dcesrv_handle *h;
3810 struct lsa_StringLarge *disp_name = NULL;
3811 enum sec_privilege id;
3813 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3815 id = sec_privilege_id(r->in.name->string);
3816 if (id == SEC_PRIV_INVALID) {
3817 return NT_STATUS_NO_SUCH_PRIVILEGE;
3820 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3821 if (disp_name == NULL) {
3822 return NT_STATUS_NO_MEMORY;
3825 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3826 if (disp_name->string == NULL) {
3827 return NT_STATUS_INTERNAL_ERROR;
3830 *r->out.disp_name = disp_name;
3831 *r->out.returned_language_id = 0;
3833 return NT_STATUS_OK;
3838 lsa_EnumAccountsWithUserRight
3840 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3841 TALLOC_CTX *mem_ctx,
3842 struct lsa_EnumAccountsWithUserRight *r)
3844 struct dcesrv_handle *h;
3845 struct lsa_policy_state *state;
3847 struct ldb_message **res;
3848 const char * const attrs[] = { "objectSid", NULL};
3849 const char *privname;
3852 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3856 if (r->in.name == NULL) {
3857 return NT_STATUS_NO_SUCH_PRIVILEGE;
3860 privname = r->in.name->string;
3862 ok = dcesrc_lsa_valid_AccountRight(privname);
3864 return NT_STATUS_NO_SUCH_PRIVILEGE;
3867 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3868 "privilege=%s", privname);
3870 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3873 return NT_STATUS_NO_MORE_ENTRIES;
3876 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3877 if (r->out.sids->sids == NULL) {
3878 return NT_STATUS_NO_MEMORY;
3880 for (i=0;i<ret;i++) {
3881 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3882 res[i], "objectSid");
3883 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3885 r->out.sids->num_sids = ret;
3887 return NT_STATUS_OK;
3892 lsa_AddAccountRights
3894 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3895 TALLOC_CTX *mem_ctx,
3896 struct lsa_AddAccountRights *r)
3898 struct dcesrv_handle *h;
3899 struct lsa_policy_state *state;
3901 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3905 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3907 r->in.sid, r->in.rights);
3912 lsa_RemoveAccountRights
3914 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3915 TALLOC_CTX *mem_ctx,
3916 struct lsa_RemoveAccountRights *r)
3918 struct dcesrv_handle *h;
3919 struct lsa_policy_state *state;
3921 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3925 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3926 LDB_FLAG_MOD_DELETE,
3927 r->in.sid, r->in.rights);
3932 lsa_StorePrivateData
3934 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3935 struct lsa_StorePrivateData *r)
3937 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3942 lsa_RetrievePrivateData
3944 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3945 struct lsa_RetrievePrivateData *r)
3947 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3954 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3955 struct lsa_GetUserName *r)
3957 enum dcerpc_transport_t transport =
3958 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3959 NTSTATUS status = NT_STATUS_OK;
3960 const char *account_name;
3961 const char *authority_name;
3962 struct lsa_String *_account_name;
3963 struct lsa_String *_authority_name = NULL;
3965 if (transport != NCACN_NP && transport != NCALRPC) {
3966 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3969 /* this is what w2k3 does */
3970 r->out.account_name = r->in.account_name;
3971 r->out.authority_name = r->in.authority_name;
3973 if (r->in.account_name
3974 && *r->in.account_name
3975 /* && *(*r->in.account_name)->string */
3977 return NT_STATUS_INVALID_PARAMETER;
3980 if (r->in.authority_name
3981 && *r->in.authority_name
3982 /* && *(*r->in.authority_name)->string */
3984 return NT_STATUS_INVALID_PARAMETER;
3987 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3988 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3990 _account_name = talloc(mem_ctx, struct lsa_String);
3991 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3992 _account_name->string = account_name;
3994 if (r->in.authority_name) {
3995 _authority_name = talloc(mem_ctx, struct lsa_String);
3996 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3997 _authority_name->string = authority_name;
4000 *r->out.account_name = _account_name;
4001 if (r->out.authority_name) {
4002 *r->out.authority_name = _authority_name;
4011 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
4012 TALLOC_CTX *mem_ctx,
4013 struct lsa_SetInfoPolicy2 *r)
4015 /* need to support these */
4016 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4019 static void kdc_get_policy(TALLOC_CTX *mem_ctx,
4020 struct loadparm_context *lp_ctx,
4021 struct smb_krb5_context *smb_krb5_context,
4022 struct lsa_DomainInfoKerberos *k)
4024 time_t svc_tkt_lifetime;
4025 time_t usr_tkt_lifetime;
4026 time_t renewal_lifetime;
4028 /* Our KDC always re-validates the client */
4029 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
4031 lpcfg_default_kdc_policy(mem_ctx, lp_ctx, &svc_tkt_lifetime,
4032 &usr_tkt_lifetime, &renewal_lifetime);
4034 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
4035 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
4036 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
4037 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
4038 However in the parent function we basically just did a full
4039 krb5_context init with the only purpose of getting a global
4040 config option (the max skew), it would probably make more sense
4041 to have a lp_ or ldb global option as the samba default */
4042 if (smb_krb5_context) {
4043 unix_to_nt_time(&k->clock_skew,
4044 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
4050 lsa_QueryDomainInformationPolicy
4052 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4053 TALLOC_CTX *mem_ctx,
4054 struct lsa_QueryDomainInformationPolicy *r)
4056 union lsa_DomainInformationPolicy *info;
4058 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
4060 return NT_STATUS_NO_MEMORY;
4063 switch (r->in.level) {
4064 case LSA_DOMAIN_INFO_POLICY_EFS:
4066 *r->out.info = NULL;
4067 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4068 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
4070 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
4071 struct smb_krb5_context *smb_krb5_context;
4072 int ret = smb_krb5_init_context(mem_ctx,
4073 dce_call->conn->dce_ctx->lp_ctx,
4077 *r->out.info = NULL;
4078 return NT_STATUS_INTERNAL_ERROR;
4080 kdc_get_policy(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
4083 talloc_free(smb_krb5_context);
4084 *r->out.info = info;
4085 return NT_STATUS_OK;
4089 *r->out.info = NULL;
4090 return NT_STATUS_INVALID_INFO_CLASS;
4095 lsa_SetDomInfoPolicy
4097 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4098 TALLOC_CTX *mem_ctx,
4099 struct lsa_SetDomainInformationPolicy *r)
4101 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4107 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
4108 TALLOC_CTX *mem_ctx,
4109 struct lsa_TestCall *r)
4111 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4117 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4118 struct lsa_CREDRWRITE *r)
4120 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4127 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4128 struct lsa_CREDRREAD *r)
4130 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4137 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4138 struct lsa_CREDRENUMERATE *r)
4140 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4145 lsa_CREDRWRITEDOMAINCREDENTIALS
4147 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4148 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
4150 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4155 lsa_CREDRREADDOMAINCREDENTIALS
4157 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4158 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
4160 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4167 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4168 struct lsa_CREDRDELETE *r)
4170 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4175 lsa_CREDRGETTARGETINFO
4177 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4178 struct lsa_CREDRGETTARGETINFO *r)
4180 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4185 lsa_CREDRPROFILELOADED
4187 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4188 struct lsa_CREDRPROFILELOADED *r)
4190 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4195 lsa_CREDRGETSESSIONTYPES
4197 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4198 struct lsa_CREDRGETSESSIONTYPES *r)
4200 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4205 lsa_LSARREGISTERAUDITEVENT
4207 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4208 struct lsa_LSARREGISTERAUDITEVENT *r)
4210 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4215 lsa_LSARGENAUDITEVENT
4217 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4218 struct lsa_LSARGENAUDITEVENT *r)
4220 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4225 lsa_LSARUNREGISTERAUDITEVENT
4227 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4228 struct lsa_LSARUNREGISTERAUDITEVENT *r)
4230 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4235 lsa_lsaRQueryForestTrustInformation
4237 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4238 struct lsa_lsaRQueryForestTrustInformation *r)
4240 struct dcesrv_handle *h = NULL;
4241 struct lsa_policy_state *p_state = NULL;
4242 int forest_level = DS_DOMAIN_FUNCTION_2000;
4243 const char * const trust_attrs[] = {
4244 "securityIdentifier",
4250 "msDS-TrustForestTrustInfo",
4253 struct ldb_message *trust_tdo_msg = NULL;
4254 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4255 struct ForestTrustInfo *trust_fti = NULL;
4256 struct lsa_ForestTrustInformation *trust_lfti = NULL;
4259 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4263 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4264 return NT_STATUS_INVALID_DOMAIN_STATE;
4267 forest_level = dsdb_forest_functional_level(p_state->sam_ldb);
4268 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4269 return NT_STATUS_INVALID_DOMAIN_STATE;
4272 if (r->in.trusted_domain_name->string == NULL) {
4273 return NT_STATUS_NO_SUCH_DOMAIN;
4276 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4277 r->in.trusted_domain_name->string,
4278 r->in.trusted_domain_name->string,
4279 trust_attrs, mem_ctx, &trust_tdo_msg);
4280 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4281 return NT_STATUS_NO_SUCH_DOMAIN;
4283 if (!NT_STATUS_IS_OK(status)) {
4287 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4288 if (!NT_STATUS_IS_OK(status)) {
4292 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4293 return NT_STATUS_INVALID_PARAMETER;
4296 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4297 return NT_STATUS_INVALID_PARAMETER;
4300 status = dsdb_trust_parse_forest_info(mem_ctx,
4303 if (!NT_STATUS_IS_OK(status)) {
4307 status = dsdb_trust_forest_info_to_lsa(mem_ctx, trust_fti,
4309 if (!NT_STATUS_IS_OK(status)) {
4313 *r->out.forest_trust_info = trust_lfti;
4314 return NT_STATUS_OK;
4318 lsa_lsaRSetForestTrustInformation
4320 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4321 TALLOC_CTX *mem_ctx,
4322 struct lsa_lsaRSetForestTrustInformation *r)
4324 struct dcesrv_handle *h;
4325 struct lsa_policy_state *p_state;
4326 const char * const trust_attrs[] = {
4327 "securityIdentifier",
4333 "msDS-TrustForestTrustInfo",
4336 struct ldb_message *trust_tdo_msg = NULL;
4337 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4338 struct lsa_ForestTrustInformation *step1_lfti = NULL;
4339 struct lsa_ForestTrustInformation *step2_lfti = NULL;
4340 struct ForestTrustInfo *trust_fti = NULL;
4341 struct ldb_result *trusts_res = NULL;
4343 struct lsa_TrustDomainInfoInfoEx *xref_tdo = NULL;
4344 struct lsa_ForestTrustInformation *xref_lfti = NULL;
4345 struct lsa_ForestTrustCollisionInfo *c_info = NULL;
4346 DATA_BLOB ft_blob = {};
4347 struct ldb_message *msg = NULL;
4348 struct server_id *server_ids = NULL;
4349 uint32_t num_server_ids = 0;
4351 enum ndr_err_code ndr_err;
4353 bool in_transaction = false;
4355 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4359 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4360 return NT_STATUS_INVALID_DOMAIN_STATE;
4363 if (r->in.check_only == 0) {
4364 ret = ldb_transaction_start(p_state->sam_ldb);
4365 if (ret != LDB_SUCCESS) {
4366 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4368 in_transaction = true;
4372 * abort if we are not a PDC
4374 * In future we should use a function like IsEffectiveRoleOwner()
4376 if (!samdb_is_pdc(p_state->sam_ldb)) {
4377 status = NT_STATUS_INVALID_DOMAIN_ROLE;
4381 if (r->in.trusted_domain_name->string == NULL) {
4382 status = NT_STATUS_NO_SUCH_DOMAIN;
4386 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4387 r->in.trusted_domain_name->string,
4388 r->in.trusted_domain_name->string,
4389 trust_attrs, mem_ctx, &trust_tdo_msg);
4390 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4391 status = NT_STATUS_NO_SUCH_DOMAIN;
4394 if (!NT_STATUS_IS_OK(status)) {
4398 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4399 if (!NT_STATUS_IS_OK(status)) {
4403 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4404 status = NT_STATUS_INVALID_PARAMETER;
4408 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4409 status = NT_STATUS_INVALID_PARAMETER;
4414 * verify and normalize the given forest trust info.
4416 * Step1: doesn't reorder yet, so step1_lfti might contain
4417 * NULL entries. This means dsdb_trust_verify_forest_info()
4418 * can generate collision entries with the callers index.
4420 status = dsdb_trust_normalize_forest_info_step1(mem_ctx,
4421 r->in.forest_trust_info,
4423 if (!NT_STATUS_IS_OK(status)) {
4427 c_info = talloc_zero(r->out.collision_info,
4428 struct lsa_ForestTrustCollisionInfo);
4429 if (c_info == NULL) {
4430 status = NT_STATUS_NO_MEMORY;
4435 * First check our own forest, then other domains/forests
4438 status = dsdb_trust_xref_tdo_info(mem_ctx, p_state->sam_ldb,
4440 if (!NT_STATUS_IS_OK(status)) {
4443 status = dsdb_trust_xref_forest_info(mem_ctx, p_state->sam_ldb,
4445 if (!NT_STATUS_IS_OK(status)) {
4450 * The documentation proposed to generate
4451 * LSA_FOREST_TRUST_COLLISION_XREF collisions.
4452 * But Windows always uses LSA_FOREST_TRUST_COLLISION_TDO.
4454 status = dsdb_trust_verify_forest_info(xref_tdo, xref_lfti,
4455 LSA_FOREST_TRUST_COLLISION_TDO,
4456 c_info, step1_lfti);
4457 if (!NT_STATUS_IS_OK(status)) {
4461 /* fetch all other trusted domain objects */
4462 status = dsdb_trust_search_tdos(p_state->sam_ldb,
4463 trust_tdo->domain_name.string,
4465 mem_ctx, &trusts_res);
4466 if (!NT_STATUS_IS_OK(status)) {
4471 * now check against the other domains.
4472 * and generate LSA_FOREST_TRUST_COLLISION_TDO collisions.
4474 for (i = 0; i < trusts_res->count; i++) {
4475 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
4476 struct ForestTrustInfo *fti = NULL;
4477 struct lsa_ForestTrustInformation *lfti = NULL;
4479 status = dsdb_trust_parse_tdo_info(mem_ctx,
4480 trusts_res->msgs[i],
4482 if (!NT_STATUS_IS_OK(status)) {
4486 status = dsdb_trust_parse_forest_info(tdo,
4487 trusts_res->msgs[i],
4489 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
4492 if (!NT_STATUS_IS_OK(status)) {
4496 status = dsdb_trust_forest_info_to_lsa(tdo, fti, &lfti);
4497 if (!NT_STATUS_IS_OK(status)) {
4501 status = dsdb_trust_verify_forest_info(tdo, lfti,
4502 LSA_FOREST_TRUST_COLLISION_TDO,
4503 c_info, step1_lfti);
4504 if (!NT_STATUS_IS_OK(status)) {
4511 if (r->in.check_only != 0) {
4512 status = NT_STATUS_OK;
4517 * not just a check, write info back
4521 * normalize the given forest trust info.
4523 * Step2: adds TOP_LEVEL_NAME[_EX] in reverse order,
4524 * followed by DOMAIN_INFO in reverse order. It also removes
4525 * possible NULL entries from Step1.
4527 status = dsdb_trust_normalize_forest_info_step2(mem_ctx, step1_lfti,
4529 if (!NT_STATUS_IS_OK(status)) {
4533 status = dsdb_trust_forest_info_from_lsa(mem_ctx, step2_lfti,
4535 if (!NT_STATUS_IS_OK(status)) {
4539 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, trust_fti,
4540 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4541 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4542 status = NT_STATUS_INVALID_PARAMETER;
4546 msg = ldb_msg_new(mem_ctx);
4548 status = NT_STATUS_NO_MEMORY;
4552 msg->dn = ldb_dn_copy(mem_ctx, trust_tdo_msg->dn);
4554 status = NT_STATUS_NO_MEMORY;
4558 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4559 LDB_FLAG_MOD_REPLACE, NULL);
4560 if (ret != LDB_SUCCESS) {
4561 status = NT_STATUS_NO_MEMORY;
4564 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4566 if (ret != LDB_SUCCESS) {
4567 status = NT_STATUS_NO_MEMORY;
4571 ret = ldb_modify(p_state->sam_ldb, msg);
4572 if (ret != LDB_SUCCESS) {
4573 status = dsdb_ldb_err_to_ntstatus(ret);
4575 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4576 ldb_errstring(p_state->sam_ldb)));
4581 /* ok, all fine, commit transaction and return */
4582 in_transaction = false;
4583 ret = ldb_transaction_commit(p_state->sam_ldb);
4584 if (ret != LDB_SUCCESS) {
4585 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4590 * Notify winbindd that we have a acquired forest trust info
4592 status = irpc_servers_byname(dce_call->msg_ctx,
4595 &num_server_ids, &server_ids);
4596 if (!NT_STATUS_IS_OK(status)) {
4597 DBG_ERR("irpc_servers_byname failed\n");
4601 imessaging_send(dce_call->msg_ctx, server_ids[0],
4602 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS, NULL);
4604 status = NT_STATUS_OK;
4607 if (NT_STATUS_IS_OK(status) && c_info->count != 0) {
4608 *r->out.collision_info = c_info;
4611 if (in_transaction) {
4612 ldb_transaction_cancel(p_state->sam_ldb);
4621 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4622 struct lsa_CREDRRENAME *r)
4624 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4630 lsa_LSAROPENPOLICYSCE
4632 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4633 struct lsa_LSAROPENPOLICYSCE *r)
4635 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4640 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4642 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4643 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4645 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4650 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4652 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4653 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4655 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4660 lsa_LSARADTREPORTSECURITYEVENT
4662 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4663 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4665 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4669 /* include the generated boilerplate */
4670 #include "librpc/gen_ndr/ndr_lsa_s.c"
4674 /*****************************************
4675 NOTE! The remaining calls below were
4676 removed in w2k3, so the DCESRV_FAULT()
4677 replies are the correct implementation. Do
4678 not try and fill these in with anything else
4679 ******************************************/
4682 dssetup_DsRoleDnsNameToFlatName
4684 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4685 struct dssetup_DsRoleDnsNameToFlatName *r)
4687 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4692 dssetup_DsRoleDcAsDc
4694 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4695 struct dssetup_DsRoleDcAsDc *r)
4697 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4702 dssetup_DsRoleDcAsReplica
4704 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4705 struct dssetup_DsRoleDcAsReplica *r)
4707 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4712 dssetup_DsRoleDemoteDc
4714 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4715 struct dssetup_DsRoleDemoteDc *r)
4717 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4722 dssetup_DsRoleGetDcOperationProgress
4724 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4725 struct dssetup_DsRoleGetDcOperationProgress *r)
4727 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4732 dssetup_DsRoleGetDcOperationResults
4734 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4735 struct dssetup_DsRoleGetDcOperationResults *r)
4737 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4742 dssetup_DsRoleCancel
4744 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4745 struct dssetup_DsRoleCancel *r)
4747 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4752 dssetup_DsRoleServerSaveStateForUpgrade
4754 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4755 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4757 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4762 dssetup_DsRoleUpgradeDownlevelServer
4764 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4765 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4767 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4772 dssetup_DsRoleAbortDownlevelServerUpgrade
4774 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4775 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4777 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4781 /* include the generated boilerplate */
4782 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4784 NTSTATUS dcerpc_server_lsa_init(TALLOC_CTX *ctx)
4788 ret = dcerpc_server_dssetup_init(ctx);
4789 if (!NT_STATUS_IS_OK(ret)) {
4792 ret = dcerpc_server_lsarpc_init(ctx);
4793 if (!NT_STATUS_IS_OK(ret)) {