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;
2660 r->out.domains->count = r->out.domains->count;
2662 if (r->out.domains->count < count - *r->in.resume_handle) {
2663 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2664 return STATUS_MORE_ENTRIES;
2667 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2669 return NT_STATUS_OK;
2676 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2677 struct lsa_OpenAccount *r)
2679 struct dcesrv_handle *h, *ah;
2680 struct lsa_policy_state *state;
2681 struct lsa_account_state *astate;
2683 ZERO_STRUCTP(r->out.acct_handle);
2685 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2689 astate = talloc(dce_call->conn, struct lsa_account_state);
2690 if (astate == NULL) {
2691 return NT_STATUS_NO_MEMORY;
2694 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2695 if (astate->account_sid == NULL) {
2696 talloc_free(astate);
2697 return NT_STATUS_NO_MEMORY;
2700 astate->policy = talloc_reference(astate, state);
2701 astate->access_mask = r->in.access_mask;
2704 * For now we grant all requested access.
2706 * We will fail at the ldb layer later.
2708 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2709 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2710 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2712 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2714 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2715 __func__, dom_sid_string(mem_ctx, astate->account_sid),
2716 (unsigned)r->in.access_mask,
2717 (unsigned)astate->access_mask));
2719 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2721 talloc_free(astate);
2722 return NT_STATUS_NO_MEMORY;
2725 ah->data = talloc_steal(ah, astate);
2727 *r->out.acct_handle = ah->wire_handle;
2729 return NT_STATUS_OK;
2734 lsa_EnumPrivsAccount
2736 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2737 TALLOC_CTX *mem_ctx,
2738 struct lsa_EnumPrivsAccount *r)
2740 struct dcesrv_handle *h;
2741 struct lsa_account_state *astate;
2744 struct ldb_message **res;
2745 const char * const attrs[] = { "privilege", NULL};
2746 struct ldb_message_element *el;
2748 struct lsa_PrivilegeSet *privs;
2750 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2754 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2755 if (privs == NULL) {
2756 return NT_STATUS_NO_MEMORY;
2762 *r->out.privs = privs;
2764 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2765 if (sidstr == NULL) {
2766 return NT_STATUS_NO_MEMORY;
2769 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2770 "objectSid=%s", sidstr);
2772 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2775 return NT_STATUS_OK;
2778 el = ldb_msg_find_element(res[0], "privilege");
2779 if (el == NULL || el->num_values == 0) {
2780 return NT_STATUS_OK;
2783 privs->set = talloc_array(privs,
2784 struct lsa_LUIDAttribute, el->num_values);
2785 if (privs->set == NULL) {
2786 return NT_STATUS_NO_MEMORY;
2790 for (i=0;i<el->num_values;i++) {
2791 int id = sec_privilege_id((const char *)el->values[i].data);
2792 if (id == SEC_PRIV_INVALID) {
2793 /* Perhaps an account right, not a privilege */
2796 privs->set[j].attribute = 0;
2797 privs->set[j].luid.low = id;
2798 privs->set[j].luid.high = 0;
2804 return NT_STATUS_OK;
2808 lsa_EnumAccountRights
2810 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2811 TALLOC_CTX *mem_ctx,
2812 struct lsa_EnumAccountRights *r)
2814 struct dcesrv_handle *h;
2815 struct lsa_policy_state *state;
2818 struct ldb_message **res;
2819 const char * const attrs[] = { "privilege", NULL};
2821 struct ldb_message_element *el;
2823 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2827 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2828 if (sidstr == NULL) {
2829 return NT_STATUS_NO_MEMORY;
2832 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2833 "(&(objectSid=%s)(privilege=*))", sidstr);
2835 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2838 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2839 dom_sid_string(mem_ctx, r->in.sid),
2840 ldb_errstring(state->pdb)));
2841 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2844 el = ldb_msg_find_element(res[0], "privilege");
2845 if (el == NULL || el->num_values == 0) {
2846 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2849 r->out.rights->count = el->num_values;
2850 r->out.rights->names = talloc_array(r->out.rights,
2851 struct lsa_StringLarge, r->out.rights->count);
2852 if (r->out.rights->names == NULL) {
2853 return NT_STATUS_NO_MEMORY;
2856 for (i=0;i<el->num_values;i++) {
2857 r->out.rights->names[i].string = (const char *)el->values[i].data;
2860 return NT_STATUS_OK;
2866 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2868 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2869 TALLOC_CTX *mem_ctx,
2870 struct lsa_policy_state *state,
2872 struct dom_sid *sid,
2873 const struct lsa_RightSet *rights)
2875 const char *sidstr, *sidndrstr;
2876 struct ldb_message *msg;
2877 struct ldb_message_element *el;
2880 struct lsa_EnumAccountRights r2;
2883 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2884 SECURITY_ADMINISTRATOR) {
2885 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2886 return NT_STATUS_ACCESS_DENIED;
2889 msg = ldb_msg_new(mem_ctx);
2891 return NT_STATUS_NO_MEMORY;
2894 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2895 if (sidndrstr == NULL) {
2897 return NT_STATUS_NO_MEMORY;
2900 sidstr = dom_sid_string(msg, sid);
2901 if (sidstr == NULL) {
2903 return NT_STATUS_NO_MEMORY;
2906 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2907 if (dnstr == NULL) {
2909 return NT_STATUS_NO_MEMORY;
2912 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2913 if (msg->dn == NULL) {
2915 return NT_STATUS_NO_MEMORY;
2918 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2921 r2.in.handle = &state->handle->wire_handle;
2923 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2925 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2926 if (!NT_STATUS_IS_OK(status)) {
2927 ZERO_STRUCTP(r2.out.rights);
2931 for (i=0;i<rights->count;i++) {
2934 ok = dcesrc_lsa_valid_AccountRight(rights->names[i].string);
2937 return NT_STATUS_NO_SUCH_PRIVILEGE;
2940 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2942 for (j=0;j<r2.out.rights->count;j++) {
2943 if (strcasecmp_m(r2.out.rights->names[j].string,
2944 rights->names[i].string) == 0) {
2948 if (j != r2.out.rights->count) continue;
2951 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2952 if (ret != LDB_SUCCESS) {
2954 return NT_STATUS_NO_MEMORY;
2958 el = ldb_msg_find_element(msg, "privilege");
2961 return NT_STATUS_OK;
2964 el->flags = ldb_flag;
2966 ret = ldb_modify(state->pdb, msg);
2967 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2968 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2970 return NT_STATUS_NO_MEMORY;
2972 ldb_msg_add_string(msg, "comment", "added via LSA");
2973 ret = ldb_add(state->pdb, msg);
2975 if (ret != LDB_SUCCESS) {
2976 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2978 return NT_STATUS_OK;
2980 DEBUG(3, ("Could not %s attributes from %s: %s",
2981 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2982 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2984 return NT_STATUS_UNEXPECTED_IO_ERROR;
2988 return NT_STATUS_OK;
2992 lsa_AddPrivilegesToAccount
2994 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2995 struct lsa_AddPrivilegesToAccount *r)
2997 struct lsa_RightSet rights;
2998 struct dcesrv_handle *h;
2999 struct lsa_account_state *astate;
3002 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3006 rights.count = r->in.privs->count;
3007 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
3008 if (rights.names == NULL) {
3009 return NT_STATUS_NO_MEMORY;
3011 for (i=0;i<rights.count;i++) {
3012 int id = r->in.privs->set[i].luid.low;
3013 if (r->in.privs->set[i].luid.high) {
3014 return NT_STATUS_NO_SUCH_PRIVILEGE;
3016 rights.names[i].string = sec_privilege_name(id);
3017 if (rights.names[i].string == NULL) {
3018 return NT_STATUS_NO_SUCH_PRIVILEGE;
3022 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3023 LDB_FLAG_MOD_ADD, astate->account_sid,
3029 lsa_RemovePrivilegesFromAccount
3031 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3032 struct lsa_RemovePrivilegesFromAccount *r)
3034 struct lsa_RightSet *rights;
3035 struct dcesrv_handle *h;
3036 struct lsa_account_state *astate;
3039 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3043 rights = talloc(mem_ctx, struct lsa_RightSet);
3045 if (r->in.remove_all == 1 &&
3046 r->in.privs == NULL) {
3047 struct lsa_EnumAccountRights r2;
3050 r2.in.handle = &astate->policy->handle->wire_handle;
3051 r2.in.sid = astate->account_sid;
3052 r2.out.rights = rights;
3054 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
3055 if (!NT_STATUS_IS_OK(status)) {
3059 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3060 LDB_FLAG_MOD_DELETE, astate->account_sid,
3064 if (r->in.remove_all != 0) {
3065 return NT_STATUS_INVALID_PARAMETER;
3068 rights->count = r->in.privs->count;
3069 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
3070 if (rights->names == NULL) {
3071 return NT_STATUS_NO_MEMORY;
3073 for (i=0;i<rights->count;i++) {
3074 int id = r->in.privs->set[i].luid.low;
3075 if (r->in.privs->set[i].luid.high) {
3076 return NT_STATUS_NO_SUCH_PRIVILEGE;
3078 rights->names[i].string = sec_privilege_name(id);
3079 if (rights->names[i].string == NULL) {
3080 return NT_STATUS_NO_SUCH_PRIVILEGE;
3084 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3085 LDB_FLAG_MOD_DELETE, astate->account_sid,
3091 lsa_GetQuotasForAccount
3093 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3094 struct lsa_GetQuotasForAccount *r)
3096 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3101 lsa_SetQuotasForAccount
3103 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3104 struct lsa_SetQuotasForAccount *r)
3106 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3111 lsa_GetSystemAccessAccount
3113 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3114 struct lsa_GetSystemAccessAccount *r)
3116 struct dcesrv_handle *h;
3117 struct lsa_account_state *astate;
3120 struct ldb_message **res;
3121 const char * const attrs[] = { "privilege", NULL};
3122 struct ldb_message_element *el;
3125 *(r->out.access_mask) = 0x00000000;
3127 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3131 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
3132 if (sidstr == NULL) {
3133 return NT_STATUS_NO_MEMORY;
3136 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
3137 "objectSid=%s", sidstr);
3139 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3142 return NT_STATUS_OK;
3145 el = ldb_msg_find_element(res[0], "privilege");
3146 if (el == NULL || el->num_values == 0) {
3147 return NT_STATUS_OK;
3150 for (i=0;i<el->num_values;i++) {
3151 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
3152 if (right_bit == 0) {
3153 /* Perhaps an privilege, not a right */
3156 *(r->out.access_mask) |= right_bit;
3159 return NT_STATUS_OK;
3164 lsa_SetSystemAccessAccount
3166 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3167 struct lsa_SetSystemAccessAccount *r)
3169 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3176 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3177 struct lsa_CreateSecret *r)
3179 struct dcesrv_handle *policy_handle;
3180 struct lsa_policy_state *policy_state;
3181 struct lsa_secret_state *secret_state;
3182 struct dcesrv_handle *handle;
3183 struct ldb_message **msgs, *msg;
3184 const char *attrs[] = {
3192 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3193 ZERO_STRUCTP(r->out.sec_handle);
3195 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3197 case SECURITY_SYSTEM:
3198 case SECURITY_ADMINISTRATOR:
3201 /* Users and annonymous are not allowed create secrets */
3202 return NT_STATUS_ACCESS_DENIED;
3205 policy_state = policy_handle->data;
3207 if (!r->in.name.string) {
3208 return NT_STATUS_INVALID_PARAMETER;
3211 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3212 NT_STATUS_HAVE_NO_MEMORY(secret_state);
3213 secret_state->policy = policy_state;
3215 msg = ldb_msg_new(mem_ctx);
3217 return NT_STATUS_NO_MEMORY;
3220 if (strncmp("G$", r->in.name.string, 2) == 0) {
3223 secret_state->global = true;
3225 name = &r->in.name.string[2];
3226 if (strlen(name) == 0) {
3227 return NT_STATUS_INVALID_PARAMETER;
3230 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3231 ldb_binary_encode_string(mem_ctx, name));
3232 NT_STATUS_HAVE_NO_MEMORY(name2);
3234 /* We need to connect to the database as system, as this is one
3235 * of the rare RPC calls that must read the secrets (and this
3236 * is denied otherwise) */
3237 secret_state->sam_ldb = talloc_reference(secret_state,
3238 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));
3239 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3241 /* search for the secret record */
3242 ret = gendb_search(secret_state->sam_ldb,
3243 mem_ctx, policy_state->system_dn, &msgs, attrs,
3244 "(&(cn=%s)(objectclass=secret))",
3247 return NT_STATUS_OBJECT_NAME_COLLISION;
3251 DEBUG(0,("Failure searching for CN=%s: %s\n",
3252 name2, ldb_errstring(secret_state->sam_ldb)));
3253 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3256 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3257 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3258 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3259 return NT_STATUS_NO_MEMORY;
3262 ret = ldb_msg_add_string(msg, "cn", name2);
3263 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3265 secret_state->global = false;
3267 name = r->in.name.string;
3268 if (strlen(name) == 0) {
3269 return NT_STATUS_INVALID_PARAMETER;
3272 secret_state->sam_ldb = talloc_reference(secret_state,
3273 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3274 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3276 /* search for the secret record */
3277 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3278 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3280 "(&(cn=%s)(objectclass=secret))",
3281 ldb_binary_encode_string(mem_ctx, name));
3283 return NT_STATUS_OBJECT_NAME_COLLISION;
3287 DEBUG(0,("Failure searching for CN=%s: %s\n",
3288 name, ldb_errstring(secret_state->sam_ldb)));
3289 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3292 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3293 "cn=%s,cn=LSA Secrets", name);
3294 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3295 ret = ldb_msg_add_string(msg, "cn", name);
3296 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3299 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3300 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3302 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3303 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3305 /* create the secret */
3306 ret = ldb_add(secret_state->sam_ldb, msg);
3307 if (ret != LDB_SUCCESS) {
3308 DEBUG(0,("Failed to create secret record %s: %s\n",
3309 ldb_dn_get_linearized(msg->dn),
3310 ldb_errstring(secret_state->sam_ldb)));
3311 return NT_STATUS_ACCESS_DENIED;
3314 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3315 NT_STATUS_HAVE_NO_MEMORY(handle);
3317 handle->data = talloc_steal(handle, secret_state);
3319 secret_state->access_mask = r->in.access_mask;
3320 secret_state->policy = talloc_reference(secret_state, policy_state);
3321 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3323 *r->out.sec_handle = handle->wire_handle;
3325 return NT_STATUS_OK;
3332 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3333 struct lsa_OpenSecret *r)
3335 struct dcesrv_handle *policy_handle;
3337 struct lsa_policy_state *policy_state;
3338 struct lsa_secret_state *secret_state;
3339 struct dcesrv_handle *handle;
3340 struct ldb_message **msgs;
3341 const char *attrs[] = {
3349 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3350 ZERO_STRUCTP(r->out.sec_handle);
3351 policy_state = policy_handle->data;
3353 if (!r->in.name.string) {
3354 return NT_STATUS_INVALID_PARAMETER;
3357 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3359 case SECURITY_SYSTEM:
3360 case SECURITY_ADMINISTRATOR:
3363 /* Users and annonymous are not allowed to access secrets */
3364 return NT_STATUS_ACCESS_DENIED;
3367 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3368 if (!secret_state) {
3369 return NT_STATUS_NO_MEMORY;
3371 secret_state->policy = policy_state;
3373 if (strncmp("G$", r->in.name.string, 2) == 0) {
3374 name = &r->in.name.string[2];
3375 /* 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) */
3376 secret_state->sam_ldb = talloc_reference(secret_state,
3377 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));
3378 secret_state->global = true;
3380 if (strlen(name) < 1) {
3381 return NT_STATUS_INVALID_PARAMETER;
3384 /* search for the secret record */
3385 ret = gendb_search(secret_state->sam_ldb,
3386 mem_ctx, policy_state->system_dn, &msgs, attrs,
3387 "(&(cn=%s Secret)(objectclass=secret))",
3388 ldb_binary_encode_string(mem_ctx, name));
3390 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3394 DEBUG(0,("Found %d records matching DN %s\n", ret,
3395 ldb_dn_get_linearized(policy_state->system_dn)));
3396 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3399 secret_state->global = false;
3400 secret_state->sam_ldb = talloc_reference(secret_state,
3401 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3403 name = r->in.name.string;
3404 if (strlen(name) < 1) {
3405 return NT_STATUS_INVALID_PARAMETER;
3408 /* search for the secret record */
3409 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3410 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3412 "(&(cn=%s)(objectclass=secret))",
3413 ldb_binary_encode_string(mem_ctx, name));
3415 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3419 DEBUG(0,("Found %d records matching CN=%s\n",
3420 ret, ldb_binary_encode_string(mem_ctx, name)));
3421 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3425 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3427 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3429 return NT_STATUS_NO_MEMORY;
3432 handle->data = talloc_steal(handle, secret_state);
3434 secret_state->access_mask = r->in.access_mask;
3435 secret_state->policy = talloc_reference(secret_state, policy_state);
3437 *r->out.sec_handle = handle->wire_handle;
3439 return NT_STATUS_OK;
3446 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3447 struct lsa_SetSecret *r)
3450 struct dcesrv_handle *h;
3451 struct lsa_secret_state *secret_state;
3452 struct ldb_message *msg;
3453 DATA_BLOB session_key;
3454 DATA_BLOB crypt_secret, secret;
3457 NTSTATUS status = NT_STATUS_OK;
3459 struct timeval now = timeval_current();
3460 NTTIME nt_now = timeval_to_nttime(&now);
3462 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3464 secret_state = h->data;
3466 msg = ldb_msg_new(mem_ctx);
3468 return NT_STATUS_NO_MEMORY;
3471 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3473 return NT_STATUS_NO_MEMORY;
3475 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3476 if (!NT_STATUS_IS_OK(status)) {
3480 if (r->in.old_val) {
3482 crypt_secret.data = r->in.old_val->data;
3483 crypt_secret.length = r->in.old_val->size;
3485 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3486 if (!NT_STATUS_IS_OK(status)) {
3490 val.data = secret.data;
3491 val.length = secret.length;
3494 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3495 return NT_STATUS_NO_MEMORY;
3498 /* set old value mtime */
3499 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3500 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3501 return NT_STATUS_NO_MEMORY;
3505 /* If the old value is not set, then migrate the
3506 * current value to the old value */
3507 const struct ldb_val *old_val;
3508 NTTIME last_set_time;
3509 struct ldb_message **res;
3510 const char *attrs[] = {
3516 /* search for the secret record */
3517 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3518 secret_state->secret_dn, &res, attrs);
3520 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3524 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3525 ldb_dn_get_linearized(secret_state->secret_dn)));
3526 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3529 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3530 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3534 if (ldb_msg_add_value(msg, "priorValue",
3535 old_val, NULL) != LDB_SUCCESS) {
3536 return NT_STATUS_NO_MEMORY;
3539 if (samdb_msg_add_delete(secret_state->sam_ldb,
3540 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3541 return NT_STATUS_NO_MEMORY;
3545 /* set old value mtime */
3546 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3547 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3548 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3549 return NT_STATUS_NO_MEMORY;
3552 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3553 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3554 return NT_STATUS_NO_MEMORY;
3559 if (r->in.new_val) {
3561 crypt_secret.data = r->in.new_val->data;
3562 crypt_secret.length = r->in.new_val->size;
3564 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3565 if (!NT_STATUS_IS_OK(status)) {
3569 val.data = secret.data;
3570 val.length = secret.length;
3573 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3574 return NT_STATUS_NO_MEMORY;
3577 /* set new value mtime */
3578 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3579 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3580 return NT_STATUS_NO_MEMORY;
3583 /* NULL out the NEW value */
3584 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3585 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3586 return NT_STATUS_NO_MEMORY;
3588 if (samdb_msg_add_delete(secret_state->sam_ldb,
3589 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3590 return NT_STATUS_NO_MEMORY;
3594 /* modify the samdb record */
3595 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3596 if (ret != LDB_SUCCESS) {
3597 return dsdb_ldb_err_to_ntstatus(ret);
3600 return NT_STATUS_OK;
3607 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3608 struct lsa_QuerySecret *r)
3610 struct dcesrv_handle *h;
3611 struct lsa_secret_state *secret_state;
3612 struct ldb_message *msg;
3613 DATA_BLOB session_key;
3614 DATA_BLOB crypt_secret, secret;
3616 struct ldb_message **res;
3617 const char *attrs[] = {
3627 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3629 /* Ensure user is permitted to read this... */
3630 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3632 case SECURITY_SYSTEM:
3633 case SECURITY_ADMINISTRATOR:
3636 /* Users and annonymous are not allowed to read secrets */
3637 return NT_STATUS_ACCESS_DENIED;
3640 secret_state = h->data;
3642 /* pull all the user attributes */
3643 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3644 secret_state->secret_dn, &res, attrs);
3646 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3650 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3651 if (!NT_STATUS_IS_OK(nt_status)) {
3655 if (r->in.old_val) {
3656 const struct ldb_val *prior_val;
3657 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3658 if (!r->out.old_val) {
3659 return NT_STATUS_NO_MEMORY;
3661 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3663 if (prior_val && prior_val->length) {
3664 secret.data = prior_val->data;
3665 secret.length = prior_val->length;
3668 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3669 if (!crypt_secret.length) {
3670 return NT_STATUS_NO_MEMORY;
3672 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3673 if (!r->out.old_val->buf) {
3674 return NT_STATUS_NO_MEMORY;
3676 r->out.old_val->buf->size = crypt_secret.length;
3677 r->out.old_val->buf->length = crypt_secret.length;
3678 r->out.old_val->buf->data = crypt_secret.data;
3682 if (r->in.old_mtime) {
3683 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3684 if (!r->out.old_mtime) {
3685 return NT_STATUS_NO_MEMORY;
3687 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3690 if (r->in.new_val) {
3691 const struct ldb_val *new_val;
3692 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3693 if (!r->out.new_val) {
3694 return NT_STATUS_NO_MEMORY;
3697 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3699 if (new_val && new_val->length) {
3700 secret.data = new_val->data;
3701 secret.length = new_val->length;
3704 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3705 if (!crypt_secret.length) {
3706 return NT_STATUS_NO_MEMORY;
3708 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3709 if (!r->out.new_val->buf) {
3710 return NT_STATUS_NO_MEMORY;
3712 r->out.new_val->buf->length = crypt_secret.length;
3713 r->out.new_val->buf->size = crypt_secret.length;
3714 r->out.new_val->buf->data = crypt_secret.data;
3718 if (r->in.new_mtime) {
3719 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3720 if (!r->out.new_mtime) {
3721 return NT_STATUS_NO_MEMORY;
3723 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3726 return NT_STATUS_OK;
3733 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3734 TALLOC_CTX *mem_ctx,
3735 struct lsa_LookupPrivValue *r)
3737 struct dcesrv_handle *h;
3740 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3742 id = sec_privilege_id(r->in.name->string);
3743 if (id == SEC_PRIV_INVALID) {
3744 return NT_STATUS_NO_SUCH_PRIVILEGE;
3747 r->out.luid->low = id;
3748 r->out.luid->high = 0;
3750 return NT_STATUS_OK;
3757 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3758 TALLOC_CTX *mem_ctx,
3759 struct lsa_LookupPrivName *r)
3761 struct dcesrv_handle *h;
3762 struct lsa_StringLarge *name;
3763 const char *privname;
3765 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3767 if (r->in.luid->high != 0) {
3768 return NT_STATUS_NO_SUCH_PRIVILEGE;
3771 privname = sec_privilege_name(r->in.luid->low);
3772 if (privname == NULL) {
3773 return NT_STATUS_NO_SUCH_PRIVILEGE;
3776 name = talloc(mem_ctx, struct lsa_StringLarge);
3778 return NT_STATUS_NO_MEMORY;
3781 name->string = privname;
3783 *r->out.name = name;
3785 return NT_STATUS_OK;
3790 lsa_LookupPrivDisplayName
3792 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3793 TALLOC_CTX *mem_ctx,
3794 struct lsa_LookupPrivDisplayName *r)
3796 struct dcesrv_handle *h;
3797 struct lsa_StringLarge *disp_name = NULL;
3798 enum sec_privilege id;
3800 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3802 id = sec_privilege_id(r->in.name->string);
3803 if (id == SEC_PRIV_INVALID) {
3804 return NT_STATUS_NO_SUCH_PRIVILEGE;
3807 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3808 if (disp_name == NULL) {
3809 return NT_STATUS_NO_MEMORY;
3812 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3813 if (disp_name->string == NULL) {
3814 return NT_STATUS_INTERNAL_ERROR;
3817 *r->out.disp_name = disp_name;
3818 *r->out.returned_language_id = 0;
3820 return NT_STATUS_OK;
3825 lsa_EnumAccountsWithUserRight
3827 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3828 TALLOC_CTX *mem_ctx,
3829 struct lsa_EnumAccountsWithUserRight *r)
3831 struct dcesrv_handle *h;
3832 struct lsa_policy_state *state;
3834 struct ldb_message **res;
3835 const char * const attrs[] = { "objectSid", NULL};
3836 const char *privname;
3839 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3843 if (r->in.name == NULL) {
3844 return NT_STATUS_NO_SUCH_PRIVILEGE;
3847 privname = r->in.name->string;
3849 ok = dcesrc_lsa_valid_AccountRight(privname);
3851 return NT_STATUS_NO_SUCH_PRIVILEGE;
3854 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3855 "privilege=%s", privname);
3857 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3860 return NT_STATUS_NO_MORE_ENTRIES;
3863 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3864 if (r->out.sids->sids == NULL) {
3865 return NT_STATUS_NO_MEMORY;
3867 for (i=0;i<ret;i++) {
3868 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3869 res[i], "objectSid");
3870 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3872 r->out.sids->num_sids = ret;
3874 return NT_STATUS_OK;
3879 lsa_AddAccountRights
3881 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3882 TALLOC_CTX *mem_ctx,
3883 struct lsa_AddAccountRights *r)
3885 struct dcesrv_handle *h;
3886 struct lsa_policy_state *state;
3888 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3892 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3894 r->in.sid, r->in.rights);
3899 lsa_RemoveAccountRights
3901 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3902 TALLOC_CTX *mem_ctx,
3903 struct lsa_RemoveAccountRights *r)
3905 struct dcesrv_handle *h;
3906 struct lsa_policy_state *state;
3908 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3912 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3913 LDB_FLAG_MOD_DELETE,
3914 r->in.sid, r->in.rights);
3919 lsa_StorePrivateData
3921 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3922 struct lsa_StorePrivateData *r)
3924 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3929 lsa_RetrievePrivateData
3931 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3932 struct lsa_RetrievePrivateData *r)
3934 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3941 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3942 struct lsa_GetUserName *r)
3944 enum dcerpc_transport_t transport =
3945 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3946 NTSTATUS status = NT_STATUS_OK;
3947 const char *account_name;
3948 const char *authority_name;
3949 struct lsa_String *_account_name;
3950 struct lsa_String *_authority_name = NULL;
3952 if (transport != NCACN_NP && transport != NCALRPC) {
3953 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3956 /* this is what w2k3 does */
3957 r->out.account_name = r->in.account_name;
3958 r->out.authority_name = r->in.authority_name;
3960 if (r->in.account_name
3961 && *r->in.account_name
3962 /* && *(*r->in.account_name)->string */
3964 return NT_STATUS_INVALID_PARAMETER;
3967 if (r->in.authority_name
3968 && *r->in.authority_name
3969 /* && *(*r->in.authority_name)->string */
3971 return NT_STATUS_INVALID_PARAMETER;
3974 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3975 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3977 _account_name = talloc(mem_ctx, struct lsa_String);
3978 NT_STATUS_HAVE_NO_MEMORY(_account_name);
3979 _account_name->string = account_name;
3981 if (r->in.authority_name) {
3982 _authority_name = talloc(mem_ctx, struct lsa_String);
3983 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3984 _authority_name->string = authority_name;
3987 *r->out.account_name = _account_name;
3988 if (r->out.authority_name) {
3989 *r->out.authority_name = _authority_name;
3998 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3999 TALLOC_CTX *mem_ctx,
4000 struct lsa_SetInfoPolicy2 *r)
4002 /* need to support these */
4003 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4006 static void kdc_get_policy(TALLOC_CTX *mem_ctx,
4007 struct loadparm_context *lp_ctx,
4008 struct smb_krb5_context *smb_krb5_context,
4009 struct lsa_DomainInfoKerberos *k)
4011 time_t svc_tkt_lifetime;
4012 time_t usr_tkt_lifetime;
4013 time_t renewal_lifetime;
4015 /* Our KDC always re-validates the client */
4016 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
4018 lpcfg_default_kdc_policy(mem_ctx, lp_ctx, &svc_tkt_lifetime,
4019 &usr_tkt_lifetime, &renewal_lifetime);
4021 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
4022 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
4023 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
4024 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
4025 However in the parent function we basically just did a full
4026 krb5_context init with the only purpose of getting a global
4027 config option (the max skew), it would probably make more sense
4028 to have a lp_ or ldb global option as the samba default */
4029 if (smb_krb5_context) {
4030 unix_to_nt_time(&k->clock_skew,
4031 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
4037 lsa_QueryDomainInformationPolicy
4039 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4040 TALLOC_CTX *mem_ctx,
4041 struct lsa_QueryDomainInformationPolicy *r)
4043 union lsa_DomainInformationPolicy *info;
4045 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
4047 return NT_STATUS_NO_MEMORY;
4050 switch (r->in.level) {
4051 case LSA_DOMAIN_INFO_POLICY_EFS:
4053 *r->out.info = NULL;
4054 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4055 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
4057 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
4058 struct smb_krb5_context *smb_krb5_context;
4059 int ret = smb_krb5_init_context(mem_ctx,
4060 dce_call->conn->dce_ctx->lp_ctx,
4064 *r->out.info = NULL;
4065 return NT_STATUS_INTERNAL_ERROR;
4067 kdc_get_policy(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
4070 talloc_free(smb_krb5_context);
4071 *r->out.info = info;
4072 return NT_STATUS_OK;
4076 *r->out.info = NULL;
4077 return NT_STATUS_INVALID_INFO_CLASS;
4082 lsa_SetDomInfoPolicy
4084 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4085 TALLOC_CTX *mem_ctx,
4086 struct lsa_SetDomainInformationPolicy *r)
4088 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4094 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
4095 TALLOC_CTX *mem_ctx,
4096 struct lsa_TestCall *r)
4098 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4104 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4105 struct lsa_CREDRWRITE *r)
4107 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4114 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4115 struct lsa_CREDRREAD *r)
4117 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4124 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4125 struct lsa_CREDRENUMERATE *r)
4127 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4132 lsa_CREDRWRITEDOMAINCREDENTIALS
4134 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4135 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
4137 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4142 lsa_CREDRREADDOMAINCREDENTIALS
4144 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4145 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
4147 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4154 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4155 struct lsa_CREDRDELETE *r)
4157 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4162 lsa_CREDRGETTARGETINFO
4164 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4165 struct lsa_CREDRGETTARGETINFO *r)
4167 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4172 lsa_CREDRPROFILELOADED
4174 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4175 struct lsa_CREDRPROFILELOADED *r)
4177 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4182 lsa_CREDRGETSESSIONTYPES
4184 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4185 struct lsa_CREDRGETSESSIONTYPES *r)
4187 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4192 lsa_LSARREGISTERAUDITEVENT
4194 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4195 struct lsa_LSARREGISTERAUDITEVENT *r)
4197 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4202 lsa_LSARGENAUDITEVENT
4204 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4205 struct lsa_LSARGENAUDITEVENT *r)
4207 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4212 lsa_LSARUNREGISTERAUDITEVENT
4214 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4215 struct lsa_LSARUNREGISTERAUDITEVENT *r)
4217 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4222 lsa_lsaRQueryForestTrustInformation
4224 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4225 struct lsa_lsaRQueryForestTrustInformation *r)
4227 struct dcesrv_handle *h = NULL;
4228 struct lsa_policy_state *p_state = NULL;
4229 int forest_level = DS_DOMAIN_FUNCTION_2000;
4230 const char * const trust_attrs[] = {
4231 "securityIdentifier",
4237 "msDS-TrustForestTrustInfo",
4240 struct ldb_message *trust_tdo_msg = NULL;
4241 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4242 struct ForestTrustInfo *trust_fti = NULL;
4243 struct lsa_ForestTrustInformation *trust_lfti = NULL;
4246 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4250 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4251 return NT_STATUS_INVALID_DOMAIN_STATE;
4254 forest_level = dsdb_forest_functional_level(p_state->sam_ldb);
4255 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4256 return NT_STATUS_INVALID_DOMAIN_STATE;
4259 if (r->in.trusted_domain_name->string == NULL) {
4260 return NT_STATUS_NO_SUCH_DOMAIN;
4263 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4264 r->in.trusted_domain_name->string,
4265 r->in.trusted_domain_name->string,
4266 trust_attrs, mem_ctx, &trust_tdo_msg);
4267 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4268 return NT_STATUS_NO_SUCH_DOMAIN;
4270 if (!NT_STATUS_IS_OK(status)) {
4274 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4275 if (!NT_STATUS_IS_OK(status)) {
4279 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4280 return NT_STATUS_INVALID_PARAMETER;
4283 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4284 return NT_STATUS_INVALID_PARAMETER;
4287 status = dsdb_trust_parse_forest_info(mem_ctx,
4290 if (!NT_STATUS_IS_OK(status)) {
4294 status = dsdb_trust_forest_info_to_lsa(mem_ctx, trust_fti,
4296 if (!NT_STATUS_IS_OK(status)) {
4300 *r->out.forest_trust_info = trust_lfti;
4301 return NT_STATUS_OK;
4305 lsa_lsaRSetForestTrustInformation
4307 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4308 TALLOC_CTX *mem_ctx,
4309 struct lsa_lsaRSetForestTrustInformation *r)
4311 struct dcesrv_handle *h;
4312 struct lsa_policy_state *p_state;
4313 const char * const trust_attrs[] = {
4314 "securityIdentifier",
4320 "msDS-TrustForestTrustInfo",
4323 struct ldb_message *trust_tdo_msg = NULL;
4324 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4325 struct lsa_ForestTrustInformation *step1_lfti = NULL;
4326 struct lsa_ForestTrustInformation *step2_lfti = NULL;
4327 struct ForestTrustInfo *trust_fti = NULL;
4328 struct ldb_result *trusts_res = NULL;
4330 struct lsa_TrustDomainInfoInfoEx *xref_tdo = NULL;
4331 struct lsa_ForestTrustInformation *xref_lfti = NULL;
4332 struct lsa_ForestTrustCollisionInfo *c_info = NULL;
4333 DATA_BLOB ft_blob = {};
4334 struct ldb_message *msg = NULL;
4335 struct server_id *server_ids = NULL;
4336 uint32_t num_server_ids = 0;
4338 enum ndr_err_code ndr_err;
4340 bool in_transaction = false;
4342 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4346 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4347 return NT_STATUS_INVALID_DOMAIN_STATE;
4350 if (r->in.check_only == 0) {
4351 ret = ldb_transaction_start(p_state->sam_ldb);
4352 if (ret != LDB_SUCCESS) {
4353 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4355 in_transaction = true;
4359 * abort if we are not a PDC
4361 * In future we should use a function like IsEffectiveRoleOwner()
4363 if (!samdb_is_pdc(p_state->sam_ldb)) {
4364 status = NT_STATUS_INVALID_DOMAIN_ROLE;
4368 if (r->in.trusted_domain_name->string == NULL) {
4369 status = NT_STATUS_NO_SUCH_DOMAIN;
4373 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4374 r->in.trusted_domain_name->string,
4375 r->in.trusted_domain_name->string,
4376 trust_attrs, mem_ctx, &trust_tdo_msg);
4377 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4378 status = NT_STATUS_NO_SUCH_DOMAIN;
4381 if (!NT_STATUS_IS_OK(status)) {
4385 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4386 if (!NT_STATUS_IS_OK(status)) {
4390 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4391 status = NT_STATUS_INVALID_PARAMETER;
4395 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4396 status = NT_STATUS_INVALID_PARAMETER;
4401 * verify and normalize the given forest trust info.
4403 * Step1: doesn't reorder yet, so step1_lfti might contain
4404 * NULL entries. This means dsdb_trust_verify_forest_info()
4405 * can generate collision entries with the callers index.
4407 status = dsdb_trust_normalize_forest_info_step1(mem_ctx,
4408 r->in.forest_trust_info,
4410 if (!NT_STATUS_IS_OK(status)) {
4414 c_info = talloc_zero(r->out.collision_info,
4415 struct lsa_ForestTrustCollisionInfo);
4416 if (c_info == NULL) {
4417 status = NT_STATUS_NO_MEMORY;
4422 * First check our own forest, then other domains/forests
4425 status = dsdb_trust_xref_tdo_info(mem_ctx, p_state->sam_ldb,
4427 if (!NT_STATUS_IS_OK(status)) {
4430 status = dsdb_trust_xref_forest_info(mem_ctx, p_state->sam_ldb,
4432 if (!NT_STATUS_IS_OK(status)) {
4437 * The documentation proposed to generate
4438 * LSA_FOREST_TRUST_COLLISION_XREF collisions.
4439 * But Windows always uses LSA_FOREST_TRUST_COLLISION_TDO.
4441 status = dsdb_trust_verify_forest_info(xref_tdo, xref_lfti,
4442 LSA_FOREST_TRUST_COLLISION_TDO,
4443 c_info, step1_lfti);
4444 if (!NT_STATUS_IS_OK(status)) {
4448 /* fetch all other trusted domain objects */
4449 status = dsdb_trust_search_tdos(p_state->sam_ldb,
4450 trust_tdo->domain_name.string,
4452 mem_ctx, &trusts_res);
4453 if (!NT_STATUS_IS_OK(status)) {
4458 * now check against the other domains.
4459 * and generate LSA_FOREST_TRUST_COLLISION_TDO collisions.
4461 for (i = 0; i < trusts_res->count; i++) {
4462 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
4463 struct ForestTrustInfo *fti = NULL;
4464 struct lsa_ForestTrustInformation *lfti = NULL;
4466 status = dsdb_trust_parse_tdo_info(mem_ctx,
4467 trusts_res->msgs[i],
4469 if (!NT_STATUS_IS_OK(status)) {
4473 status = dsdb_trust_parse_forest_info(tdo,
4474 trusts_res->msgs[i],
4476 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
4479 if (!NT_STATUS_IS_OK(status)) {
4483 status = dsdb_trust_forest_info_to_lsa(tdo, fti, &lfti);
4484 if (!NT_STATUS_IS_OK(status)) {
4488 status = dsdb_trust_verify_forest_info(tdo, lfti,
4489 LSA_FOREST_TRUST_COLLISION_TDO,
4490 c_info, step1_lfti);
4491 if (!NT_STATUS_IS_OK(status)) {
4498 if (r->in.check_only != 0) {
4499 status = NT_STATUS_OK;
4504 * not just a check, write info back
4508 * normalize the given forest trust info.
4510 * Step2: adds TOP_LEVEL_NAME[_EX] in reverse order,
4511 * followed by DOMAIN_INFO in reverse order. It also removes
4512 * possible NULL entries from Step1.
4514 status = dsdb_trust_normalize_forest_info_step2(mem_ctx, step1_lfti,
4516 if (!NT_STATUS_IS_OK(status)) {
4520 status = dsdb_trust_forest_info_from_lsa(mem_ctx, step2_lfti,
4522 if (!NT_STATUS_IS_OK(status)) {
4526 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, trust_fti,
4527 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4528 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4529 status = NT_STATUS_INVALID_PARAMETER;
4533 msg = ldb_msg_new(mem_ctx);
4535 status = NT_STATUS_NO_MEMORY;
4539 msg->dn = ldb_dn_copy(mem_ctx, trust_tdo_msg->dn);
4541 status = NT_STATUS_NO_MEMORY;
4545 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4546 LDB_FLAG_MOD_REPLACE, NULL);
4547 if (ret != LDB_SUCCESS) {
4548 status = NT_STATUS_NO_MEMORY;
4551 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4553 if (ret != LDB_SUCCESS) {
4554 status = NT_STATUS_NO_MEMORY;
4558 ret = ldb_modify(p_state->sam_ldb, msg);
4559 if (ret != LDB_SUCCESS) {
4560 status = dsdb_ldb_err_to_ntstatus(ret);
4562 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4563 ldb_errstring(p_state->sam_ldb)));
4568 /* ok, all fine, commit transaction and return */
4569 in_transaction = false;
4570 ret = ldb_transaction_commit(p_state->sam_ldb);
4571 if (ret != LDB_SUCCESS) {
4572 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4577 * Notify winbindd that we have a acquired forest trust info
4579 status = irpc_servers_byname(dce_call->msg_ctx,
4582 &num_server_ids, &server_ids);
4583 if (!NT_STATUS_IS_OK(status)) {
4584 DBG_ERR("irpc_servers_byname failed\n");
4588 imessaging_send(dce_call->msg_ctx, server_ids[0],
4589 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS, NULL);
4591 status = NT_STATUS_OK;
4594 if (NT_STATUS_IS_OK(status) && c_info->count != 0) {
4595 *r->out.collision_info = c_info;
4598 if (in_transaction) {
4599 ldb_transaction_cancel(p_state->sam_ldb);
4608 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4609 struct lsa_CREDRRENAME *r)
4611 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4617 lsa_LSAROPENPOLICYSCE
4619 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4620 struct lsa_LSAROPENPOLICYSCE *r)
4622 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4627 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4629 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4630 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4632 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4637 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4639 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4640 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4642 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4647 lsa_LSARADTREPORTSECURITYEVENT
4649 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4650 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4652 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4656 /* include the generated boilerplate */
4657 #include "librpc/gen_ndr/ndr_lsa_s.c"
4661 /*****************************************
4662 NOTE! The remaining calls below were
4663 removed in w2k3, so the DCESRV_FAULT()
4664 replies are the correct implementation. Do
4665 not try and fill these in with anything else
4666 ******************************************/
4669 dssetup_DsRoleDnsNameToFlatName
4671 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4672 struct dssetup_DsRoleDnsNameToFlatName *r)
4674 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4679 dssetup_DsRoleDcAsDc
4681 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4682 struct dssetup_DsRoleDcAsDc *r)
4684 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4689 dssetup_DsRoleDcAsReplica
4691 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4692 struct dssetup_DsRoleDcAsReplica *r)
4694 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4699 dssetup_DsRoleDemoteDc
4701 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4702 struct dssetup_DsRoleDemoteDc *r)
4704 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4709 dssetup_DsRoleGetDcOperationProgress
4711 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4712 struct dssetup_DsRoleGetDcOperationProgress *r)
4714 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4719 dssetup_DsRoleGetDcOperationResults
4721 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4722 struct dssetup_DsRoleGetDcOperationResults *r)
4724 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4729 dssetup_DsRoleCancel
4731 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4732 struct dssetup_DsRoleCancel *r)
4734 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4739 dssetup_DsRoleServerSaveStateForUpgrade
4741 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4742 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4744 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4749 dssetup_DsRoleUpgradeDownlevelServer
4751 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4752 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4754 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4759 dssetup_DsRoleAbortDownlevelServerUpgrade
4761 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4762 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4764 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4768 /* include the generated boilerplate */
4769 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4771 NTSTATUS dcerpc_server_lsa_init(TALLOC_CTX *ctx)
4775 ret = dcerpc_server_dssetup_init(ctx);
4776 if (!NT_STATUS_IS_OK(ret)) {
4779 ret = dcerpc_server_lsarpc_init(ctx);
4780 if (!NT_STATUS_IS_OK(ret)) {