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 const char *attrs[] = {
3191 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3192 ZERO_STRUCTP(r->out.sec_handle);
3194 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3196 case SECURITY_SYSTEM:
3197 case SECURITY_ADMINISTRATOR:
3200 /* Users and annonymous are not allowed create secrets */
3201 return NT_STATUS_ACCESS_DENIED;
3204 policy_state = policy_handle->data;
3206 if (!r->in.name.string) {
3207 return NT_STATUS_INVALID_PARAMETER;
3210 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3211 NT_STATUS_HAVE_NO_MEMORY(secret_state);
3212 secret_state->policy = policy_state;
3214 msg = ldb_msg_new(mem_ctx);
3216 return NT_STATUS_NO_MEMORY;
3219 if (strncmp("G$", r->in.name.string, 2) == 0) {
3222 secret_state->global = true;
3224 name = &r->in.name.string[2];
3225 if (strlen(name) == 0) {
3226 return NT_STATUS_INVALID_PARAMETER;
3229 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3230 ldb_binary_encode_string(mem_ctx, name));
3231 NT_STATUS_HAVE_NO_MEMORY(name2);
3233 /* We need to connect to the database as system, as this is one
3234 * of the rare RPC calls that must read the secrets (and this
3235 * is denied otherwise) */
3236 secret_state->sam_ldb = talloc_reference(secret_state,
3237 samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
3238 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3240 /* search for the secret record */
3241 ret = gendb_search(secret_state->sam_ldb,
3242 mem_ctx, policy_state->system_dn, &msgs, attrs,
3243 "(&(cn=%s)(objectclass=secret))",
3246 return NT_STATUS_OBJECT_NAME_COLLISION;
3250 DEBUG(0,("Failure searching for CN=%s: %s\n",
3251 name2, ldb_errstring(secret_state->sam_ldb)));
3252 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3255 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3256 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3257 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3258 return NT_STATUS_NO_MEMORY;
3261 ret = ldb_msg_add_string(msg, "cn", name2);
3262 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3264 secret_state->global = false;
3266 name = r->in.name.string;
3267 if (strlen(name) == 0) {
3268 return NT_STATUS_INVALID_PARAMETER;
3271 secret_state->sam_ldb = talloc_reference(secret_state,
3272 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3273 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3275 /* search for the secret record */
3276 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3277 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3279 "(&(cn=%s)(objectclass=secret))",
3280 ldb_binary_encode_string(mem_ctx, name));
3282 return NT_STATUS_OBJECT_NAME_COLLISION;
3286 DEBUG(0,("Failure searching for CN=%s: %s\n",
3287 name, ldb_errstring(secret_state->sam_ldb)));
3288 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3291 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3292 "cn=%s,cn=LSA Secrets", name);
3293 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3294 ret = ldb_msg_add_string(msg, "cn", name);
3295 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3298 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3299 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3301 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3302 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3304 /* create the secret */
3305 ret = ldb_add(secret_state->sam_ldb, msg);
3306 if (ret != LDB_SUCCESS) {
3307 DEBUG(0,("Failed to create secret record %s: %s\n",
3308 ldb_dn_get_linearized(msg->dn),
3309 ldb_errstring(secret_state->sam_ldb)));
3310 return NT_STATUS_ACCESS_DENIED;
3313 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3314 NT_STATUS_HAVE_NO_MEMORY(handle);
3316 handle->data = talloc_steal(handle, secret_state);
3318 secret_state->access_mask = r->in.access_mask;
3319 secret_state->policy = talloc_reference(secret_state, policy_state);
3320 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3322 *r->out.sec_handle = handle->wire_handle;
3324 return NT_STATUS_OK;
3331 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3332 struct lsa_OpenSecret *r)
3334 struct dcesrv_handle *policy_handle;
3336 struct lsa_policy_state *policy_state;
3337 struct lsa_secret_state *secret_state;
3338 struct dcesrv_handle *handle;
3339 struct ldb_message **msgs;
3340 const char *attrs[] = {
3348 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3349 ZERO_STRUCTP(r->out.sec_handle);
3350 policy_state = policy_handle->data;
3352 if (!r->in.name.string) {
3353 return NT_STATUS_INVALID_PARAMETER;
3356 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3358 case SECURITY_SYSTEM:
3359 case SECURITY_ADMINISTRATOR:
3362 /* Users and annonymous are not allowed to access secrets */
3363 return NT_STATUS_ACCESS_DENIED;
3366 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3367 if (!secret_state) {
3368 return NT_STATUS_NO_MEMORY;
3370 secret_state->policy = policy_state;
3372 if (strncmp("G$", r->in.name.string, 2) == 0) {
3373 name = &r->in.name.string[2];
3374 /* 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) */
3375 secret_state->sam_ldb = talloc_reference(secret_state,
3376 samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
3377 secret_state->global = true;
3379 if (strlen(name) < 1) {
3380 return NT_STATUS_INVALID_PARAMETER;
3383 /* search for the secret record */
3384 ret = gendb_search(secret_state->sam_ldb,
3385 mem_ctx, policy_state->system_dn, &msgs, attrs,
3386 "(&(cn=%s Secret)(objectclass=secret))",
3387 ldb_binary_encode_string(mem_ctx, name));
3389 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3393 DEBUG(0,("Found %d records matching DN %s\n", ret,
3394 ldb_dn_get_linearized(policy_state->system_dn)));
3395 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3398 secret_state->global = false;
3399 secret_state->sam_ldb = talloc_reference(secret_state,
3400 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3402 name = r->in.name.string;
3403 if (strlen(name) < 1) {
3404 return NT_STATUS_INVALID_PARAMETER;
3407 /* search for the secret record */
3408 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3409 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3411 "(&(cn=%s)(objectclass=secret))",
3412 ldb_binary_encode_string(mem_ctx, name));
3414 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3418 DEBUG(0,("Found %d records matching CN=%s\n",
3419 ret, ldb_binary_encode_string(mem_ctx, name)));
3420 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3424 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3426 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3428 return NT_STATUS_NO_MEMORY;
3431 handle->data = talloc_steal(handle, secret_state);
3433 secret_state->access_mask = r->in.access_mask;
3434 secret_state->policy = talloc_reference(secret_state, policy_state);
3436 *r->out.sec_handle = handle->wire_handle;
3438 return NT_STATUS_OK;
3445 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3446 struct lsa_SetSecret *r)
3449 struct dcesrv_handle *h;
3450 struct lsa_secret_state *secret_state;
3451 struct ldb_message *msg;
3452 DATA_BLOB session_key;
3453 DATA_BLOB crypt_secret, secret;
3456 NTSTATUS status = NT_STATUS_OK;
3458 struct timeval now = timeval_current();
3459 NTTIME nt_now = timeval_to_nttime(&now);
3461 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3463 secret_state = h->data;
3465 msg = ldb_msg_new(mem_ctx);
3467 return NT_STATUS_NO_MEMORY;
3470 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3472 return NT_STATUS_NO_MEMORY;
3474 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3475 if (!NT_STATUS_IS_OK(status)) {
3479 if (r->in.old_val) {
3481 crypt_secret.data = r->in.old_val->data;
3482 crypt_secret.length = r->in.old_val->size;
3484 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3485 if (!NT_STATUS_IS_OK(status)) {
3489 val.data = secret.data;
3490 val.length = secret.length;
3493 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3494 return NT_STATUS_NO_MEMORY;
3497 /* set old value mtime */
3498 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3499 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3500 return NT_STATUS_NO_MEMORY;
3504 /* If the old value is not set, then migrate the
3505 * current value to the old value */
3506 const struct ldb_val *old_val;
3507 NTTIME last_set_time;
3508 struct ldb_message **res;
3509 const char *attrs[] = {
3515 /* search for the secret record */
3516 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3517 secret_state->secret_dn, &res, attrs);
3519 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3523 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3524 ldb_dn_get_linearized(secret_state->secret_dn)));
3525 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3528 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3529 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3533 if (ldb_msg_add_value(msg, "priorValue",
3534 old_val, NULL) != LDB_SUCCESS) {
3535 return NT_STATUS_NO_MEMORY;
3538 if (samdb_msg_add_delete(secret_state->sam_ldb,
3539 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3540 return NT_STATUS_NO_MEMORY;
3544 /* set old value mtime */
3545 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3546 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3547 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3548 return NT_STATUS_NO_MEMORY;
3551 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3552 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3553 return NT_STATUS_NO_MEMORY;
3558 if (r->in.new_val) {
3560 crypt_secret.data = r->in.new_val->data;
3561 crypt_secret.length = r->in.new_val->size;
3563 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3564 if (!NT_STATUS_IS_OK(status)) {
3568 val.data = secret.data;
3569 val.length = secret.length;
3572 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3573 return NT_STATUS_NO_MEMORY;
3576 /* set new value mtime */
3577 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3578 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3579 return NT_STATUS_NO_MEMORY;
3582 /* NULL out the NEW value */
3583 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3584 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3585 return NT_STATUS_NO_MEMORY;
3587 if (samdb_msg_add_delete(secret_state->sam_ldb,
3588 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3589 return NT_STATUS_NO_MEMORY;
3593 /* modify the samdb record */
3594 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3595 if (ret != LDB_SUCCESS) {
3596 return dsdb_ldb_err_to_ntstatus(ret);
3599 return NT_STATUS_OK;
3606 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3607 struct lsa_QuerySecret *r)
3609 struct dcesrv_handle *h;
3610 struct lsa_secret_state *secret_state;
3611 struct ldb_message *msg;
3612 DATA_BLOB session_key;
3613 DATA_BLOB crypt_secret, secret;
3615 struct ldb_message **res;
3616 const char *attrs[] = {
3626 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3628 /* Ensure user is permitted to read this... */
3629 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3631 case SECURITY_SYSTEM:
3632 case SECURITY_ADMINISTRATOR:
3635 /* Users and annonymous are not allowed to read secrets */
3636 return NT_STATUS_ACCESS_DENIED;
3639 secret_state = h->data;
3641 /* pull all the user attributes */
3642 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3643 secret_state->secret_dn, &res, attrs);
3645 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3649 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3650 if (!NT_STATUS_IS_OK(nt_status)) {
3654 if (r->in.old_val) {
3655 const struct ldb_val *prior_val;
3656 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3657 if (!r->out.old_val) {
3658 return NT_STATUS_NO_MEMORY;
3660 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3662 if (prior_val && prior_val->length) {
3663 secret.data = prior_val->data;
3664 secret.length = prior_val->length;
3667 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3668 if (!crypt_secret.length) {
3669 return NT_STATUS_NO_MEMORY;
3671 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3672 if (!r->out.old_val->buf) {
3673 return NT_STATUS_NO_MEMORY;
3675 r->out.old_val->buf->size = crypt_secret.length;
3676 r->out.old_val->buf->length = crypt_secret.length;
3677 r->out.old_val->buf->data = crypt_secret.data;
3681 if (r->in.old_mtime) {
3682 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3683 if (!r->out.old_mtime) {
3684 return NT_STATUS_NO_MEMORY;
3686 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3689 if (r->in.new_val) {
3690 const struct ldb_val *new_val;
3691 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3692 if (!r->out.new_val) {
3693 return NT_STATUS_NO_MEMORY;
3696 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3698 if (new_val && new_val->length) {
3699 secret.data = new_val->data;
3700 secret.length = new_val->length;
3703 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3704 if (!crypt_secret.length) {
3705 return NT_STATUS_NO_MEMORY;
3707 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3708 if (!r->out.new_val->buf) {
3709 return NT_STATUS_NO_MEMORY;
3711 r->out.new_val->buf->length = crypt_secret.length;
3712 r->out.new_val->buf->size = crypt_secret.length;
3713 r->out.new_val->buf->data = crypt_secret.data;
3717 if (r->in.new_mtime) {
3718 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3719 if (!r->out.new_mtime) {
3720 return NT_STATUS_NO_MEMORY;
3722 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3725 return NT_STATUS_OK;
3732 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3733 TALLOC_CTX *mem_ctx,
3734 struct lsa_LookupPrivValue *r)
3736 struct dcesrv_handle *h;
3739 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3741 id = sec_privilege_id(r->in.name->string);
3742 if (id == SEC_PRIV_INVALID) {
3743 return NT_STATUS_NO_SUCH_PRIVILEGE;
3746 r->out.luid->low = id;
3747 r->out.luid->high = 0;
3749 return NT_STATUS_OK;
3756 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3757 TALLOC_CTX *mem_ctx,
3758 struct lsa_LookupPrivName *r)
3760 struct dcesrv_handle *h;
3761 struct lsa_StringLarge *name;
3762 const char *privname;
3764 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3766 if (r->in.luid->high != 0) {
3767 return NT_STATUS_NO_SUCH_PRIVILEGE;
3770 privname = sec_privilege_name(r->in.luid->low);
3771 if (privname == NULL) {
3772 return NT_STATUS_NO_SUCH_PRIVILEGE;
3775 name = talloc(mem_ctx, struct lsa_StringLarge);
3777 return NT_STATUS_NO_MEMORY;
3780 name->string = privname;
3782 *r->out.name = name;
3784 return NT_STATUS_OK;
3789 lsa_LookupPrivDisplayName
3791 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3792 TALLOC_CTX *mem_ctx,
3793 struct lsa_LookupPrivDisplayName *r)
3795 struct dcesrv_handle *h;
3796 struct lsa_StringLarge *disp_name = NULL;
3797 enum sec_privilege id;
3799 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3801 id = sec_privilege_id(r->in.name->string);
3802 if (id == SEC_PRIV_INVALID) {
3803 return NT_STATUS_NO_SUCH_PRIVILEGE;
3806 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3807 if (disp_name == NULL) {
3808 return NT_STATUS_NO_MEMORY;
3811 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3812 if (disp_name->string == NULL) {
3813 return NT_STATUS_INTERNAL_ERROR;
3816 *r->out.disp_name = disp_name;
3817 *r->out.returned_language_id = 0;
3819 return NT_STATUS_OK;
3824 lsa_EnumAccountsWithUserRight
3826 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3827 TALLOC_CTX *mem_ctx,
3828 struct lsa_EnumAccountsWithUserRight *r)
3830 struct dcesrv_handle *h;
3831 struct lsa_policy_state *state;
3833 struct ldb_message **res;
3834 const char * const attrs[] = { "objectSid", NULL};
3835 const char *privname;
3838 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3842 if (r->in.name == NULL) {
3843 return NT_STATUS_NO_SUCH_PRIVILEGE;
3846 privname = r->in.name->string;
3848 ok = dcesrc_lsa_valid_AccountRight(privname);
3850 return NT_STATUS_NO_SUCH_PRIVILEGE;
3853 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3854 "privilege=%s", privname);
3856 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3859 return NT_STATUS_NO_MORE_ENTRIES;
3862 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3863 if (r->out.sids->sids == NULL) {
3864 return NT_STATUS_NO_MEMORY;
3866 for (i=0;i<ret;i++) {
3867 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3868 res[i], "objectSid");
3869 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3871 r->out.sids->num_sids = ret;
3873 return NT_STATUS_OK;
3878 lsa_AddAccountRights
3880 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3881 TALLOC_CTX *mem_ctx,
3882 struct lsa_AddAccountRights *r)
3884 struct dcesrv_handle *h;
3885 struct lsa_policy_state *state;
3887 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3891 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3893 r->in.sid, r->in.rights);
3898 lsa_RemoveAccountRights
3900 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3901 TALLOC_CTX *mem_ctx,
3902 struct lsa_RemoveAccountRights *r)
3904 struct dcesrv_handle *h;
3905 struct lsa_policy_state *state;
3907 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3911 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3912 LDB_FLAG_MOD_DELETE,
3913 r->in.sid, r->in.rights);
3918 lsa_StorePrivateData
3920 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3921 struct lsa_StorePrivateData *r)
3923 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3928 lsa_RetrievePrivateData
3930 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3931 struct lsa_RetrievePrivateData *r)
3933 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3940 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3941 struct lsa_GetUserName *r)
3943 enum dcerpc_transport_t transport =
3944 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3945 NTSTATUS status = NT_STATUS_OK;
3946 const char *account_name;
3947 const char *authority_name;
3948 struct lsa_String *_account_name;
3949 struct lsa_String *_authority_name = NULL;
3951 if (transport != NCACN_NP && transport != NCALRPC) {
3952 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3955 /* this is what w2k3 does */
3956 r->out.account_name = r->in.account_name;
3957 r->out.authority_name = r->in.authority_name;
3959 if (r->in.account_name
3960 && *r->in.account_name
3961 /* && *(*r->in.account_name)->string */
3963 return NT_STATUS_INVALID_PARAMETER;
3966 if (r->in.authority_name
3967 && *r->in.authority_name
3968 /* && *(*r->in.authority_name)->string */
3970 return NT_STATUS_INVALID_PARAMETER;
3973 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3974 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3976 _account_name = talloc(mem_ctx, struct lsa_String);
3977 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3978 _account_name->string = account_name;
3980 if (r->in.authority_name) {
3981 _authority_name = talloc(mem_ctx, struct lsa_String);
3982 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3983 _authority_name->string = authority_name;
3986 *r->out.account_name = _account_name;
3987 if (r->out.authority_name) {
3988 *r->out.authority_name = _authority_name;
3997 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3998 TALLOC_CTX *mem_ctx,
3999 struct lsa_SetInfoPolicy2 *r)
4001 /* need to support these */
4002 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4005 static void kdc_get_policy(TALLOC_CTX *mem_ctx,
4006 struct loadparm_context *lp_ctx,
4007 struct smb_krb5_context *smb_krb5_context,
4008 struct lsa_DomainInfoKerberos *k)
4010 time_t svc_tkt_lifetime;
4011 time_t usr_tkt_lifetime;
4012 time_t renewal_lifetime;
4014 /* Our KDC always re-validates the client */
4015 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
4017 lpcfg_default_kdc_policy(mem_ctx, lp_ctx, &svc_tkt_lifetime,
4018 &usr_tkt_lifetime, &renewal_lifetime);
4020 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
4021 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
4022 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
4023 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
4024 However in the parent function we basically just did a full
4025 krb5_context init with the only purpose of getting a global
4026 config option (the max skew), it would probably make more sense
4027 to have a lp_ or ldb global option as the samba default */
4028 if (smb_krb5_context) {
4029 unix_to_nt_time(&k->clock_skew,
4030 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
4036 lsa_QueryDomainInformationPolicy
4038 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4039 TALLOC_CTX *mem_ctx,
4040 struct lsa_QueryDomainInformationPolicy *r)
4042 union lsa_DomainInformationPolicy *info;
4044 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
4046 return NT_STATUS_NO_MEMORY;
4049 switch (r->in.level) {
4050 case LSA_DOMAIN_INFO_POLICY_EFS:
4052 *r->out.info = NULL;
4053 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4054 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
4056 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
4057 struct smb_krb5_context *smb_krb5_context;
4058 int ret = smb_krb5_init_context(mem_ctx,
4059 dce_call->conn->dce_ctx->lp_ctx,
4063 *r->out.info = NULL;
4064 return NT_STATUS_INTERNAL_ERROR;
4066 kdc_get_policy(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
4069 talloc_free(smb_krb5_context);
4070 *r->out.info = info;
4071 return NT_STATUS_OK;
4075 *r->out.info = NULL;
4076 return NT_STATUS_INVALID_INFO_CLASS;
4081 lsa_SetDomInfoPolicy
4083 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4084 TALLOC_CTX *mem_ctx,
4085 struct lsa_SetDomainInformationPolicy *r)
4087 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4093 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
4094 TALLOC_CTX *mem_ctx,
4095 struct lsa_TestCall *r)
4097 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4103 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4104 struct lsa_CREDRWRITE *r)
4106 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4113 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4114 struct lsa_CREDRREAD *r)
4116 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4123 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4124 struct lsa_CREDRENUMERATE *r)
4126 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4131 lsa_CREDRWRITEDOMAINCREDENTIALS
4133 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4134 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
4136 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4141 lsa_CREDRREADDOMAINCREDENTIALS
4143 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4144 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
4146 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4153 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4154 struct lsa_CREDRDELETE *r)
4156 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4161 lsa_CREDRGETTARGETINFO
4163 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4164 struct lsa_CREDRGETTARGETINFO *r)
4166 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4171 lsa_CREDRPROFILELOADED
4173 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4174 struct lsa_CREDRPROFILELOADED *r)
4176 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4181 lsa_CREDRGETSESSIONTYPES
4183 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4184 struct lsa_CREDRGETSESSIONTYPES *r)
4186 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4191 lsa_LSARREGISTERAUDITEVENT
4193 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4194 struct lsa_LSARREGISTERAUDITEVENT *r)
4196 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4201 lsa_LSARGENAUDITEVENT
4203 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4204 struct lsa_LSARGENAUDITEVENT *r)
4206 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4211 lsa_LSARUNREGISTERAUDITEVENT
4213 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4214 struct lsa_LSARUNREGISTERAUDITEVENT *r)
4216 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4221 lsa_lsaRQueryForestTrustInformation
4223 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4224 struct lsa_lsaRQueryForestTrustInformation *r)
4226 struct dcesrv_handle *h = NULL;
4227 struct lsa_policy_state *p_state = NULL;
4228 int forest_level = DS_DOMAIN_FUNCTION_2000;
4229 const char * const trust_attrs[] = {
4230 "securityIdentifier",
4236 "msDS-TrustForestTrustInfo",
4239 struct ldb_message *trust_tdo_msg = NULL;
4240 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4241 struct ForestTrustInfo *trust_fti = NULL;
4242 struct lsa_ForestTrustInformation *trust_lfti = NULL;
4245 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4249 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4250 return NT_STATUS_INVALID_DOMAIN_STATE;
4253 forest_level = dsdb_forest_functional_level(p_state->sam_ldb);
4254 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4255 return NT_STATUS_INVALID_DOMAIN_STATE;
4258 if (r->in.trusted_domain_name->string == NULL) {
4259 return NT_STATUS_NO_SUCH_DOMAIN;
4262 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4263 r->in.trusted_domain_name->string,
4264 r->in.trusted_domain_name->string,
4265 trust_attrs, mem_ctx, &trust_tdo_msg);
4266 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4267 return NT_STATUS_NO_SUCH_DOMAIN;
4269 if (!NT_STATUS_IS_OK(status)) {
4273 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4274 if (!NT_STATUS_IS_OK(status)) {
4278 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4279 return NT_STATUS_INVALID_PARAMETER;
4282 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4283 return NT_STATUS_INVALID_PARAMETER;
4286 status = dsdb_trust_parse_forest_info(mem_ctx,
4289 if (!NT_STATUS_IS_OK(status)) {
4293 status = dsdb_trust_forest_info_to_lsa(mem_ctx, trust_fti,
4295 if (!NT_STATUS_IS_OK(status)) {
4299 *r->out.forest_trust_info = trust_lfti;
4300 return NT_STATUS_OK;
4304 lsa_lsaRSetForestTrustInformation
4306 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4307 TALLOC_CTX *mem_ctx,
4308 struct lsa_lsaRSetForestTrustInformation *r)
4310 struct dcesrv_handle *h;
4311 struct lsa_policy_state *p_state;
4312 const char * const trust_attrs[] = {
4313 "securityIdentifier",
4319 "msDS-TrustForestTrustInfo",
4322 struct ldb_message *trust_tdo_msg = NULL;
4323 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4324 struct lsa_ForestTrustInformation *step1_lfti = NULL;
4325 struct lsa_ForestTrustInformation *step2_lfti = NULL;
4326 struct ForestTrustInfo *trust_fti = NULL;
4327 struct ldb_result *trusts_res = NULL;
4329 struct lsa_TrustDomainInfoInfoEx *xref_tdo = NULL;
4330 struct lsa_ForestTrustInformation *xref_lfti = NULL;
4331 struct lsa_ForestTrustCollisionInfo *c_info = NULL;
4332 DATA_BLOB ft_blob = {};
4333 struct ldb_message *msg = NULL;
4334 struct server_id *server_ids = NULL;
4335 uint32_t num_server_ids = 0;
4337 enum ndr_err_code ndr_err;
4339 bool in_transaction = false;
4341 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4345 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4346 return NT_STATUS_INVALID_DOMAIN_STATE;
4349 if (r->in.check_only == 0) {
4350 ret = ldb_transaction_start(p_state->sam_ldb);
4351 if (ret != LDB_SUCCESS) {
4352 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4354 in_transaction = true;
4358 * abort if we are not a PDC
4360 * In future we should use a function like IsEffectiveRoleOwner()
4362 if (!samdb_is_pdc(p_state->sam_ldb)) {
4363 status = NT_STATUS_INVALID_DOMAIN_ROLE;
4367 if (r->in.trusted_domain_name->string == NULL) {
4368 status = NT_STATUS_NO_SUCH_DOMAIN;
4372 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4373 r->in.trusted_domain_name->string,
4374 r->in.trusted_domain_name->string,
4375 trust_attrs, mem_ctx, &trust_tdo_msg);
4376 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4377 status = NT_STATUS_NO_SUCH_DOMAIN;
4380 if (!NT_STATUS_IS_OK(status)) {
4384 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4385 if (!NT_STATUS_IS_OK(status)) {
4389 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4390 status = NT_STATUS_INVALID_PARAMETER;
4394 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4395 status = NT_STATUS_INVALID_PARAMETER;
4400 * verify and normalize the given forest trust info.
4402 * Step1: doesn't reorder yet, so step1_lfti might contain
4403 * NULL entries. This means dsdb_trust_verify_forest_info()
4404 * can generate collision entries with the callers index.
4406 status = dsdb_trust_normalize_forest_info_step1(mem_ctx,
4407 r->in.forest_trust_info,
4409 if (!NT_STATUS_IS_OK(status)) {
4413 c_info = talloc_zero(r->out.collision_info,
4414 struct lsa_ForestTrustCollisionInfo);
4415 if (c_info == NULL) {
4416 status = NT_STATUS_NO_MEMORY;
4421 * First check our own forest, then other domains/forests
4424 status = dsdb_trust_xref_tdo_info(mem_ctx, p_state->sam_ldb,
4426 if (!NT_STATUS_IS_OK(status)) {
4429 status = dsdb_trust_xref_forest_info(mem_ctx, p_state->sam_ldb,
4431 if (!NT_STATUS_IS_OK(status)) {
4436 * The documentation proposed to generate
4437 * LSA_FOREST_TRUST_COLLISION_XREF collisions.
4438 * But Windows always uses LSA_FOREST_TRUST_COLLISION_TDO.
4440 status = dsdb_trust_verify_forest_info(xref_tdo, xref_lfti,
4441 LSA_FOREST_TRUST_COLLISION_TDO,
4442 c_info, step1_lfti);
4443 if (!NT_STATUS_IS_OK(status)) {
4447 /* fetch all other trusted domain objects */
4448 status = dsdb_trust_search_tdos(p_state->sam_ldb,
4449 trust_tdo->domain_name.string,
4451 mem_ctx, &trusts_res);
4452 if (!NT_STATUS_IS_OK(status)) {
4457 * now check against the other domains.
4458 * and generate LSA_FOREST_TRUST_COLLISION_TDO collisions.
4460 for (i = 0; i < trusts_res->count; i++) {
4461 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
4462 struct ForestTrustInfo *fti = NULL;
4463 struct lsa_ForestTrustInformation *lfti = NULL;
4465 status = dsdb_trust_parse_tdo_info(mem_ctx,
4466 trusts_res->msgs[i],
4468 if (!NT_STATUS_IS_OK(status)) {
4472 status = dsdb_trust_parse_forest_info(tdo,
4473 trusts_res->msgs[i],
4475 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
4478 if (!NT_STATUS_IS_OK(status)) {
4482 status = dsdb_trust_forest_info_to_lsa(tdo, fti, &lfti);
4483 if (!NT_STATUS_IS_OK(status)) {
4487 status = dsdb_trust_verify_forest_info(tdo, lfti,
4488 LSA_FOREST_TRUST_COLLISION_TDO,
4489 c_info, step1_lfti);
4490 if (!NT_STATUS_IS_OK(status)) {
4497 if (r->in.check_only != 0) {
4498 status = NT_STATUS_OK;
4503 * not just a check, write info back
4507 * normalize the given forest trust info.
4509 * Step2: adds TOP_LEVEL_NAME[_EX] in reverse order,
4510 * followed by DOMAIN_INFO in reverse order. It also removes
4511 * possible NULL entries from Step1.
4513 status = dsdb_trust_normalize_forest_info_step2(mem_ctx, step1_lfti,
4515 if (!NT_STATUS_IS_OK(status)) {
4519 status = dsdb_trust_forest_info_from_lsa(mem_ctx, step2_lfti,
4521 if (!NT_STATUS_IS_OK(status)) {
4525 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, trust_fti,
4526 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4527 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4528 status = NT_STATUS_INVALID_PARAMETER;
4532 msg = ldb_msg_new(mem_ctx);
4534 status = NT_STATUS_NO_MEMORY;
4538 msg->dn = ldb_dn_copy(mem_ctx, trust_tdo_msg->dn);
4540 status = NT_STATUS_NO_MEMORY;
4544 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4545 LDB_FLAG_MOD_REPLACE, NULL);
4546 if (ret != LDB_SUCCESS) {
4547 status = NT_STATUS_NO_MEMORY;
4550 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4552 if (ret != LDB_SUCCESS) {
4553 status = NT_STATUS_NO_MEMORY;
4557 ret = ldb_modify(p_state->sam_ldb, msg);
4558 if (ret != LDB_SUCCESS) {
4559 status = dsdb_ldb_err_to_ntstatus(ret);
4561 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4562 ldb_errstring(p_state->sam_ldb)));
4567 /* ok, all fine, commit transaction and return */
4568 in_transaction = false;
4569 ret = ldb_transaction_commit(p_state->sam_ldb);
4570 if (ret != LDB_SUCCESS) {
4571 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4576 * Notify winbindd that we have a acquired forest trust info
4578 status = irpc_servers_byname(dce_call->msg_ctx,
4581 &num_server_ids, &server_ids);
4582 if (!NT_STATUS_IS_OK(status)) {
4583 DBG_ERR("irpc_servers_byname failed\n");
4587 imessaging_send(dce_call->msg_ctx, server_ids[0],
4588 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS, NULL);
4590 status = NT_STATUS_OK;
4593 if (NT_STATUS_IS_OK(status) && c_info->count != 0) {
4594 *r->out.collision_info = c_info;
4597 if (in_transaction) {
4598 ldb_transaction_cancel(p_state->sam_ldb);
4607 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4608 struct lsa_CREDRRENAME *r)
4610 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4616 lsa_LSAROPENPOLICYSCE
4618 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4619 struct lsa_LSAROPENPOLICYSCE *r)
4621 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4626 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4628 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4629 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4631 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4636 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4638 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4639 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4641 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4646 lsa_LSARADTREPORTSECURITYEVENT
4648 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4649 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4651 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4655 /* include the generated boilerplate */
4656 #include "librpc/gen_ndr/ndr_lsa_s.c"
4660 /*****************************************
4661 NOTE! The remaining calls below were
4662 removed in w2k3, so the DCESRV_FAULT()
4663 replies are the correct implementation. Do
4664 not try and fill these in with anything else
4665 ******************************************/
4668 dssetup_DsRoleDnsNameToFlatName
4670 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4671 struct dssetup_DsRoleDnsNameToFlatName *r)
4673 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4678 dssetup_DsRoleDcAsDc
4680 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4681 struct dssetup_DsRoleDcAsDc *r)
4683 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4688 dssetup_DsRoleDcAsReplica
4690 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4691 struct dssetup_DsRoleDcAsReplica *r)
4693 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4698 dssetup_DsRoleDemoteDc
4700 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4701 struct dssetup_DsRoleDemoteDc *r)
4703 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4708 dssetup_DsRoleGetDcOperationProgress
4710 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4711 struct dssetup_DsRoleGetDcOperationProgress *r)
4713 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4718 dssetup_DsRoleGetDcOperationResults
4720 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4721 struct dssetup_DsRoleGetDcOperationResults *r)
4723 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4728 dssetup_DsRoleCancel
4730 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4731 struct dssetup_DsRoleCancel *r)
4733 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4738 dssetup_DsRoleServerSaveStateForUpgrade
4740 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4741 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4743 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4748 dssetup_DsRoleUpgradeDownlevelServer
4750 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4751 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4753 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4758 dssetup_DsRoleAbortDownlevelServerUpgrade
4760 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4761 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4763 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4767 /* include the generated boilerplate */
4768 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4770 NTSTATUS dcerpc_server_lsa_init(TALLOC_CTX *ctx)
4774 ret = dcerpc_server_dssetup_init(ctx);
4775 if (!NT_STATUS_IS_OK(ret)) {
4778 ret = dcerpc_server_lsarpc_init(ctx);
4779 if (!NT_STATUS_IS_OK(ret)) {