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;
1065 struct dom_sid *tmp_sid1;
1066 struct dom_sid *tmp_sid2;
1069 char *dns_encoded = NULL;
1070 char *netbios_encoded = NULL;
1071 char *sid_encoded = NULL;
1073 DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
1074 ZERO_STRUCTP(r->out.trustdom_handle);
1076 policy_state = policy_handle->data;
1077 sam_ldb = policy_state->sam_ldb;
1079 netbios_name = r->in.info->netbios_name.string;
1080 if (!netbios_name) {
1081 return NT_STATUS_INVALID_PARAMETER;
1084 dns_name = r->in.info->domain_name.string;
1085 if (dns_name == NULL) {
1086 return NT_STATUS_INVALID_PARAMETER;
1089 if (r->in.info->sid == NULL) {
1090 return NT_STATUS_INVALID_SID;
1094 * We expect S-1-5-21-A-B-C, but we don't
1095 * allow S-1-5-21-0-0-0 as this is used
1096 * for claims and compound identities.
1098 * So we call dom_sid_split_rid() 3 times
1099 * and compare the result to S-1-5-21
1101 status = dom_sid_split_rid(mem_ctx, r->in.info->sid, &tmp_sid1, &tmp_rid);
1102 if (!NT_STATUS_IS_OK(status)) {
1105 status = dom_sid_split_rid(mem_ctx, tmp_sid1, &tmp_sid2, &tmp_rid);
1106 if (!NT_STATUS_IS_OK(status)) {
1109 status = dom_sid_split_rid(mem_ctx, tmp_sid2, &tmp_sid1, &tmp_rid);
1110 if (!NT_STATUS_IS_OK(status)) {
1113 ok = dom_sid_parse("S-1-5-21", tmp_sid2);
1115 return NT_STATUS_INTERNAL_ERROR;
1117 ok = dom_sid_equal(tmp_sid1, tmp_sid2);
1119 return NT_STATUS_INVALID_PARAMETER;
1121 ok = dom_sid_parse("S-1-5-21-0-0-0", tmp_sid2);
1123 return NT_STATUS_INTERNAL_ERROR;
1125 ok = !dom_sid_equal(r->in.info->sid, tmp_sid2);
1127 return NT_STATUS_INVALID_PARAMETER;
1130 dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1131 if (dns_encoded == NULL) {
1132 return NT_STATUS_NO_MEMORY;
1134 netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1135 if (netbios_encoded == NULL) {
1136 return NT_STATUS_NO_MEMORY;
1138 sid_encoded = ldap_encode_ndr_dom_sid(mem_ctx, r->in.info->sid);
1139 if (sid_encoded == NULL) {
1140 return NT_STATUS_NO_MEMORY;
1143 trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1144 if (!trusted_domain_state) {
1145 return NT_STATUS_NO_MEMORY;
1147 trusted_domain_state->policy = policy_state;
1149 if (strcasecmp(netbios_name, "BUILTIN") == 0
1150 || (strcasecmp(dns_name, "BUILTIN") == 0)
1151 || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
1152 return NT_STATUS_INVALID_PARAMETER;
1155 if (strcasecmp(netbios_name, policy_state->domain_name) == 0
1156 || strcasecmp(netbios_name, policy_state->domain_dns) == 0
1157 || strcasecmp(dns_name, policy_state->domain_dns) == 0
1158 || strcasecmp(dns_name, policy_state->domain_name) == 0
1159 || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
1160 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
1163 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
1164 if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
1165 /* No secrets are created at this time, for this function */
1166 auth_struct.outgoing.count = 0;
1167 auth_struct.incoming.count = 0;
1168 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
1169 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
1170 r->in.auth_info_internal->auth_blob.size);
1171 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1172 &auth_blob, &auth_struct);
1173 if (!NT_STATUS_IS_OK(nt_status)) {
1176 } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
1178 if (unencrypted_auth_info->incoming_count > 1) {
1179 return NT_STATUS_INVALID_PARAMETER;
1182 /* more investigation required here, do not create secrets for
1184 auth_struct.outgoing.count = 0;
1185 auth_struct.incoming.count = 0;
1187 return NT_STATUS_INVALID_PARAMETER;
1190 if (auth_struct.incoming.count) {
1191 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1192 &auth_struct.incoming,
1193 &trustAuthIncoming);
1194 if (!NT_STATUS_IS_OK(nt_status)) {
1198 trustAuthIncoming = data_blob(NULL, 0);
1201 if (auth_struct.outgoing.count) {
1202 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1203 &auth_struct.outgoing,
1204 &trustAuthOutgoing);
1205 if (!NT_STATUS_IS_OK(nt_status)) {
1209 trustAuthOutgoing = data_blob(NULL, 0);
1212 ret = ldb_transaction_start(sam_ldb);
1213 if (ret != LDB_SUCCESS) {
1214 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1217 /* search for the trusted_domain record */
1218 ret = gendb_search(sam_ldb,
1219 mem_ctx, policy_state->system_dn, &msgs, attrs,
1220 "(&(objectClass=trustedDomain)(|"
1221 "(flatname=%s)(trustPartner=%s)"
1222 "(flatname=%s)(trustPartner=%s)"
1223 "(securityIdentifier=%s)))",
1224 dns_encoded, dns_encoded,
1225 netbios_encoded, netbios_encoded,
1228 ldb_transaction_cancel(sam_ldb);
1229 return NT_STATUS_OBJECT_NAME_COLLISION;
1232 ldb_transaction_cancel(sam_ldb);
1233 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1236 msg = ldb_msg_new(mem_ctx);
1238 return NT_STATUS_NO_MEMORY;
1241 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1242 if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", dns_name)) {
1243 ldb_transaction_cancel(sam_ldb);
1244 return NT_STATUS_NO_MEMORY;
1247 ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1248 if (ret != LDB_SUCCESS) {
1249 ldb_transaction_cancel(sam_ldb);
1250 return NT_STATUS_NO_MEMORY;;
1253 ret = ldb_msg_add_string(msg, "flatname", netbios_name);
1254 if (ret != LDB_SUCCESS) {
1255 ldb_transaction_cancel(sam_ldb);
1256 return NT_STATUS_NO_MEMORY;
1259 ret = ldb_msg_add_string(msg, "trustPartner", dns_name);
1260 if (ret != LDB_SUCCESS) {
1261 ldb_transaction_cancel(sam_ldb);
1262 return NT_STATUS_NO_MEMORY;;
1265 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier",
1267 if (ret != LDB_SUCCESS) {
1268 ldb_transaction_cancel(sam_ldb);
1269 return NT_STATUS_NO_MEMORY;;
1272 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1273 if (ret != LDB_SUCCESS) {
1274 ldb_transaction_cancel(sam_ldb);
1275 return NT_STATUS_NO_MEMORY;;
1278 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1279 if (ret != LDB_SUCCESS) {
1280 ldb_transaction_cancel(sam_ldb);
1281 return NT_STATUS_NO_MEMORY;;
1284 ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1285 if (ret != LDB_SUCCESS) {
1286 ldb_transaction_cancel(sam_ldb);
1287 return NT_STATUS_NO_MEMORY;;
1290 if (trustAuthIncoming.data) {
1291 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1292 if (ret != LDB_SUCCESS) {
1293 ldb_transaction_cancel(sam_ldb);
1294 return NT_STATUS_NO_MEMORY;
1297 if (trustAuthOutgoing.data) {
1298 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1299 if (ret != LDB_SUCCESS) {
1300 ldb_transaction_cancel(sam_ldb);
1301 return NT_STATUS_NO_MEMORY;
1305 trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1307 /* create the trusted_domain */
1308 ret = ldb_add(sam_ldb, msg);
1312 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1313 ldb_transaction_cancel(sam_ldb);
1314 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1315 ldb_dn_get_linearized(msg->dn),
1316 ldb_errstring(sam_ldb)));
1317 return NT_STATUS_DOMAIN_EXISTS;
1318 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1319 ldb_transaction_cancel(sam_ldb);
1320 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1321 ldb_dn_get_linearized(msg->dn),
1322 ldb_errstring(sam_ldb)));
1323 return NT_STATUS_ACCESS_DENIED;
1325 ldb_transaction_cancel(sam_ldb);
1326 DEBUG(0,("Failed to create user record %s: %s\n",
1327 ldb_dn_get_linearized(msg->dn),
1328 ldb_errstring(sam_ldb)));
1329 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1332 if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1333 struct ldb_dn *user_dn;
1334 /* Inbound trusts must also create a cn=users object to match */
1335 nt_status = add_trust_user(mem_ctx, sam_ldb,
1336 policy_state->domain_dn,
1338 &auth_struct.incoming,
1340 if (!NT_STATUS_IS_OK(nt_status)) {
1341 ldb_transaction_cancel(sam_ldb);
1345 /* save the trust user dn */
1346 trusted_domain_state->trusted_domain_user_dn
1347 = talloc_steal(trusted_domain_state, user_dn);
1350 ret = ldb_transaction_commit(sam_ldb);
1351 if (ret != LDB_SUCCESS) {
1352 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1356 * Notify winbindd that we have a new trust
1358 status = irpc_servers_byname(dce_call->msg_ctx,
1361 &num_server_ids, &server_ids);
1362 if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
1363 imessaging_send(dce_call->msg_ctx, server_ids[0],
1364 MSG_WINBIND_NEW_TRUSTED_DOMAIN, NULL);
1366 TALLOC_FREE(server_ids);
1368 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1370 return NT_STATUS_NO_MEMORY;
1373 handle->data = talloc_steal(handle, trusted_domain_state);
1375 trusted_domain_state->access_mask = r->in.access_mask;
1376 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1378 *r->out.trustdom_handle = handle->wire_handle;
1380 return NT_STATUS_OK;
1384 lsa_CreateTrustedDomainEx2
1386 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1387 TALLOC_CTX *mem_ctx,
1388 struct lsa_CreateTrustedDomainEx2 *r)
1390 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1393 lsa_CreateTrustedDomainEx
1395 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1396 TALLOC_CTX *mem_ctx,
1397 struct lsa_CreateTrustedDomainEx *r)
1399 struct lsa_CreateTrustedDomainEx2 r2;
1401 r2.in.policy_handle = r->in.policy_handle;
1402 r2.in.info = r->in.info;
1403 r2.out.trustdom_handle = r->out.trustdom_handle;
1404 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1408 lsa_CreateTrustedDomain
1410 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1411 struct lsa_CreateTrustedDomain *r)
1413 struct lsa_CreateTrustedDomainEx2 r2;
1415 r2.in.policy_handle = r->in.policy_handle;
1416 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1418 return NT_STATUS_NO_MEMORY;
1421 r2.in.info->domain_name = r->in.info->name;
1422 r2.in.info->netbios_name = r->in.info->name;
1423 r2.in.info->sid = r->in.info->sid;
1424 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1425 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1426 r2.in.info->trust_attributes = 0;
1428 r2.in.access_mask = r->in.access_mask;
1429 r2.out.trustdom_handle = r->out.trustdom_handle;
1431 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1434 static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
1435 struct dcesrv_call_state *dce_call,
1436 TALLOC_CTX *tmp_mem,
1437 struct lsa_policy_state *policy_state,
1439 uint32_t access_mask,
1440 struct dcesrv_handle **_handle)
1442 struct lsa_trusted_domain_state *trusted_domain_state;
1443 struct dcesrv_handle *handle;
1444 struct ldb_message **msgs;
1445 const char *attrs[] = {
1453 /* TODO: perform access checks */
1455 /* search for the trusted_domain record */
1456 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1457 policy_state->system_dn,
1458 &msgs, attrs, "%s", filter);
1460 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1464 DEBUG(0,("Found %d records matching %s under %s\n", ret,
1466 ldb_dn_get_linearized(policy_state->system_dn)));
1467 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1470 trusted_domain_state = talloc_zero(tmp_mem,
1471 struct lsa_trusted_domain_state);
1472 if (!trusted_domain_state) {
1473 return NT_STATUS_NO_MEMORY;
1475 trusted_domain_state->policy = policy_state;
1477 trusted_domain_state->trusted_domain_dn =
1478 talloc_steal(trusted_domain_state, msgs[0]->dn);
1480 direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1481 if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1482 const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1485 /* search for the trusted_domain account */
1486 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1487 policy_state->domain_dn,
1489 "(&(samaccountname=%s$)(objectclass=user)"
1490 "(userAccountControl:%s:=%u))",
1492 LDB_OID_COMPARATOR_AND,
1493 UF_INTERDOMAIN_TRUST_ACCOUNT);
1495 trusted_domain_state->trusted_domain_user_dn =
1496 talloc_steal(trusted_domain_state, msgs[0]->dn);
1500 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1502 return NT_STATUS_NO_MEMORY;
1505 handle->data = talloc_steal(handle, trusted_domain_state);
1507 trusted_domain_state->access_mask = access_mask;
1508 trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1513 return NT_STATUS_OK;
1517 lsa_OpenTrustedDomain
1519 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1520 struct lsa_OpenTrustedDomain *r)
1522 struct dcesrv_handle *policy_handle;
1523 struct lsa_policy_state *policy_state;
1524 struct dcesrv_handle *handle;
1525 const char *sid_string;
1529 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1530 ZERO_STRUCTP(r->out.trustdom_handle);
1531 policy_state = policy_handle->data;
1533 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1535 return NT_STATUS_NO_MEMORY;
1538 filter = talloc_asprintf(mem_ctx,
1539 "(&(securityIdentifier=%s)"
1540 "(objectclass=trustedDomain))",
1542 if (filter == NULL) {
1543 return NT_STATUS_NO_MEMORY;
1546 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1551 if (!NT_STATUS_IS_OK(status)) {
1555 *r->out.trustdom_handle = handle->wire_handle;
1557 return NT_STATUS_OK;
1562 lsa_OpenTrustedDomainByName
1564 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1565 TALLOC_CTX *mem_ctx,
1566 struct lsa_OpenTrustedDomainByName *r)
1568 struct dcesrv_handle *policy_handle;
1569 struct lsa_policy_state *policy_state;
1570 struct dcesrv_handle *handle;
1575 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1576 ZERO_STRUCTP(r->out.trustdom_handle);
1577 policy_state = policy_handle->data;
1579 if (!r->in.name.string) {
1580 return NT_STATUS_INVALID_PARAMETER;
1583 /* search for the trusted_domain record */
1584 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1585 if (td_name == NULL) {
1586 return NT_STATUS_NO_MEMORY;
1589 filter = talloc_asprintf(mem_ctx,
1590 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1591 "(objectclass=trustedDomain))",
1592 td_name, td_name, td_name);
1593 if (filter == NULL) {
1594 return NT_STATUS_NO_MEMORY;
1597 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1602 if (!NT_STATUS_IS_OK(status)) {
1606 *r->out.trustdom_handle = handle->wire_handle;
1608 return NT_STATUS_OK;
1614 lsa_SetTrustedDomainInfo
1616 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1617 struct lsa_SetTrustedDomainInfo *r)
1619 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1624 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1625 * otherwise at least one must be provided */
1626 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1627 struct ldb_dn *basedn, const char *dns_domain,
1628 const char *netbios, struct dom_sid2 *sid,
1629 struct ldb_message ***msgs)
1631 const char *attrs[] = { "flatname", "trustPartner",
1632 "securityIdentifier", "trustDirection",
1633 "trustType", "trustAttributes",
1635 "msDs-supportedEncryptionTypes",
1636 "msDS-TrustForestTrustInfo",
1641 char *sidstr = NULL;
1646 if (dns_domain || netbios || sid) {
1647 filter = talloc_strdup(mem_ctx,
1648 "(&(objectclass=trustedDomain)(|");
1650 filter = talloc_strdup(mem_ctx,
1651 "(objectclass=trustedDomain)");
1654 return NT_STATUS_NO_MEMORY;
1658 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1660 return NT_STATUS_NO_MEMORY;
1662 filter = talloc_asprintf_append(filter,
1663 "(trustPartner=%s)", dns);
1665 return NT_STATUS_NO_MEMORY;
1669 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1671 return NT_STATUS_NO_MEMORY;
1673 filter = talloc_asprintf_append(filter,
1674 "(flatname=%s)", nbn);
1676 return NT_STATUS_NO_MEMORY;
1680 sidstr = dom_sid_string(mem_ctx, sid);
1682 return NT_STATUS_INVALID_PARAMETER;
1684 filter = talloc_asprintf_append(filter,
1685 "(securityIdentifier=%s)",
1688 return NT_STATUS_NO_MEMORY;
1691 if (dns_domain || netbios || sid) {
1692 filter = talloc_asprintf_append(filter, "))");
1694 return NT_STATUS_NO_MEMORY;
1698 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1700 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1704 return NT_STATUS_OBJECT_NAME_COLLISION;
1707 return NT_STATUS_OK;
1710 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1711 struct ldb_context *sam_ldb,
1712 struct ldb_message *orig,
1713 struct ldb_message *dest,
1714 const char *attribute,
1716 uint32_t *orig_value)
1718 const struct ldb_val *orig_val;
1719 uint32_t orig_uint = 0;
1720 unsigned int flags = 0;
1723 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1724 if (!orig_val || !orig_val->data) {
1725 /* add new attribute */
1726 flags = LDB_FLAG_MOD_ADD;
1730 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1731 if (errno != 0 || orig_uint != value) {
1732 /* replace also if can't get value */
1733 flags = LDB_FLAG_MOD_REPLACE;
1738 /* stored value is identical, nothing to change */
1742 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1743 if (ret != LDB_SUCCESS) {
1744 return NT_STATUS_NO_MEMORY;
1747 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1748 if (ret != LDB_SUCCESS) {
1749 return NT_STATUS_NO_MEMORY;
1754 *orig_value = orig_uint;
1756 return NT_STATUS_OK;
1759 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1760 struct ldb_context *sam_ldb,
1761 struct ldb_dn *base_dn,
1763 const char *netbios_name,
1764 struct trustAuthInOutBlob *in)
1766 const char *attrs[] = { "userAccountControl", NULL };
1767 struct ldb_message **msgs;
1768 struct ldb_message *msg;
1773 ret = gendb_search(sam_ldb, mem_ctx,
1774 base_dn, &msgs, attrs,
1775 "samAccountName=%s$", netbios_name);
1777 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1782 return NT_STATUS_OK;
1785 /* ok no existing user, add it from scratch */
1786 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1787 netbios_name, in, NULL);
1790 /* check user is what we are looking for */
1791 uac = ldb_msg_find_attr_as_uint(msgs[0],
1792 "userAccountControl", 0);
1793 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1794 return NT_STATUS_OBJECT_NAME_COLLISION;
1798 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1801 return NT_STATUS_OK;
1802 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1803 return NT_STATUS_ACCESS_DENIED;
1805 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1809 /* entry exists, just modify secret if any */
1810 if (in == NULL || in->count == 0) {
1811 return NT_STATUS_OK;
1814 msg = ldb_msg_new(mem_ctx);
1816 return NT_STATUS_NO_MEMORY;
1818 msg->dn = msgs[0]->dn;
1820 for (i = 0; i < in->count; i++) {
1821 const char *attribute;
1823 switch (in->current.array[i].AuthType) {
1824 case TRUST_AUTH_TYPE_NT4OWF:
1825 attribute = "unicodePwd";
1826 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1829 case TRUST_AUTH_TYPE_CLEAR:
1830 attribute = "clearTextPassword";
1831 v.data = in->current.array[i].AuthInfo.clear.password;
1832 v.length = in->current.array[i].AuthInfo.clear.size;
1838 ret = ldb_msg_add_empty(msg, attribute,
1839 LDB_FLAG_MOD_REPLACE, NULL);
1840 if (ret != LDB_SUCCESS) {
1841 return NT_STATUS_NO_MEMORY;
1844 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1845 if (ret != LDB_SUCCESS) {
1846 return NT_STATUS_NO_MEMORY;
1850 /* create the trusted_domain user account */
1851 ret = ldb_modify(sam_ldb, msg);
1852 if (ret != LDB_SUCCESS) {
1853 DEBUG(0,("Failed to create user record %s: %s\n",
1854 ldb_dn_get_linearized(msg->dn),
1855 ldb_errstring(sam_ldb)));
1858 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1859 return NT_STATUS_DOMAIN_EXISTS;
1860 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1861 return NT_STATUS_ACCESS_DENIED;
1863 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1867 return NT_STATUS_OK;
1871 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1872 struct lsa_policy_state *p_state,
1873 TALLOC_CTX *mem_ctx,
1874 struct ldb_message *dom_msg,
1875 enum lsa_TrustDomInfoEnum level,
1876 union lsa_TrustedDomainInfo *info)
1878 uint32_t *posix_offset = NULL;
1879 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1880 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1881 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1882 uint32_t *enc_types = NULL;
1883 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1884 struct trustDomainPasswords auth_struct;
1885 struct trustAuthInOutBlob *current_passwords = NULL;
1887 struct ldb_message **msgs;
1888 struct ldb_message *msg;
1889 bool add_outgoing = false;
1890 bool add_incoming = false;
1891 bool del_outgoing = false;
1892 bool del_incoming = false;
1893 bool del_forest_info = false;
1894 bool in_transaction = false;
1899 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1900 posix_offset = &info->posix_offset.posix_offset;
1902 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1903 info_ex = &info->info_ex;
1905 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1906 auth_info = &info->auth_info;
1908 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1909 posix_offset = &info->full_info.posix_offset.posix_offset;
1910 info_ex = &info->full_info.info_ex;
1911 auth_info = &info->full_info.auth_info;
1913 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1914 auth_info_int = &info->auth_info_internal;
1916 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1917 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1918 info_ex = &info->full_info_internal.info_ex;
1919 auth_info_int = &info->full_info_internal.auth_info;
1921 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1922 enc_types = &info->enc_types.enc_types;
1925 return NT_STATUS_INVALID_PARAMETER;
1929 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1931 &trustAuthOutgoing);
1932 if (!NT_STATUS_IS_OK(nt_status)) {
1935 if (trustAuthIncoming.data) {
1936 /* This does the decode of some of this twice, but it is easier that way */
1937 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1938 auth_info->incoming_count,
1939 auth_info->incoming_current_auth_info,
1941 ¤t_passwords);
1942 if (!NT_STATUS_IS_OK(nt_status)) {
1948 /* decode auth_info_int if set */
1949 if (auth_info_int) {
1951 /* now decrypt blob */
1952 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1953 auth_info_int->auth_blob.size);
1955 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1956 &auth_blob, &auth_struct);
1957 if (!NT_STATUS_IS_OK(nt_status)) {
1963 /* verify data matches */
1964 if (info_ex->trust_attributes &
1965 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1966 /* TODO: check what behavior level we have */
1967 if (strcasecmp_m(p_state->domain_dns,
1968 p_state->forest_dns) != 0) {
1969 return NT_STATUS_INVALID_DOMAIN_STATE;
1973 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1974 if (ret == LDB_SUCCESS && am_rodc) {
1975 return NT_STATUS_NO_SUCH_DOMAIN;
1978 /* verify only one object matches the dns/netbios/sid
1979 * triplet and that this is the one we already have */
1980 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1982 info_ex->domain_name.string,
1983 info_ex->netbios_name.string,
1984 info_ex->sid, &msgs);
1985 if (!NT_STATUS_IS_OK(nt_status)) {
1988 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1989 return NT_STATUS_OBJECT_NAME_COLLISION;
1994 /* TODO: should we fetch previous values from the existing entry
1995 * and append them ? */
1996 if (auth_info_int && auth_struct.incoming.count) {
1997 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1998 &auth_struct.incoming,
1999 &trustAuthIncoming);
2000 if (!NT_STATUS_IS_OK(nt_status)) {
2004 current_passwords = &auth_struct.incoming;
2007 trustAuthIncoming = data_blob(NULL, 0);
2010 if (auth_info_int && auth_struct.outgoing.count) {
2011 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
2012 &auth_struct.outgoing,
2013 &trustAuthOutgoing);
2014 if (!NT_STATUS_IS_OK(nt_status)) {
2018 trustAuthOutgoing = data_blob(NULL, 0);
2021 msg = ldb_msg_new(mem_ctx);
2023 return NT_STATUS_NO_MEMORY;
2025 msg->dn = dom_msg->dn;
2028 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2031 *posix_offset, NULL);
2032 if (!NT_STATUS_IS_OK(nt_status)) {
2039 uint32_t changed_attrs;
2043 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2046 info_ex->trust_direction,
2048 if (!NT_STATUS_IS_OK(nt_status)) {
2052 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2053 if (auth_info != NULL && trustAuthIncoming.length > 0) {
2054 add_incoming = true;
2057 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2058 if (auth_info != NULL && trustAuthOutgoing.length > 0) {
2059 add_outgoing = true;
2063 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
2064 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
2065 del_incoming = true;
2067 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
2068 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2069 del_outgoing = true;
2072 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
2073 if (origtype == -1 || origtype != info_ex->trust_type) {
2074 DEBUG(1, ("Attempted to change trust type! "
2075 "Operation not handled\n"));
2076 return NT_STATUS_INVALID_PARAMETER;
2079 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2082 info_ex->trust_attributes,
2084 if (!NT_STATUS_IS_OK(nt_status)) {
2087 /* TODO: check forestFunctionality from ldb opaque */
2088 /* TODO: check what is set makes sense */
2090 changed_attrs = origattrs ^ info_ex->trust_attributes;
2091 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2093 * For now we only allow
2094 * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
2096 * TODO: we may need to support more attribute changes
2098 DEBUG(1, ("Attempted to change trust attributes "
2099 "(0x%08x != 0x%08x)! "
2100 "Operation not handled yet...\n",
2101 (unsigned)origattrs,
2102 (unsigned)info_ex->trust_attributes));
2103 return NT_STATUS_INVALID_PARAMETER;
2106 if (!(info_ex->trust_attributes &
2107 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
2109 struct ldb_message_element *orig_forest_el = NULL;
2111 orig_forest_el = ldb_msg_find_element(dom_msg,
2112 "msDS-TrustForestTrustInfo");
2113 if (orig_forest_el != NULL) {
2114 del_forest_info = true;
2120 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2122 "msDS-SupportedEncryptionTypes",
2124 if (!NT_STATUS_IS_OK(nt_status)) {
2129 if (add_incoming || del_incoming) {
2130 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
2131 LDB_FLAG_MOD_REPLACE, NULL);
2132 if (ret != LDB_SUCCESS) {
2133 return NT_STATUS_NO_MEMORY;
2136 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
2137 &trustAuthIncoming, NULL);
2138 if (ret != LDB_SUCCESS) {
2139 return NT_STATUS_NO_MEMORY;
2143 if (add_outgoing || del_outgoing) {
2144 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2145 LDB_FLAG_MOD_REPLACE, NULL);
2146 if (ret != LDB_SUCCESS) {
2147 return NT_STATUS_NO_MEMORY;
2150 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
2151 &trustAuthOutgoing, NULL);
2152 if (ret != LDB_SUCCESS) {
2153 return NT_STATUS_NO_MEMORY;
2157 if (del_forest_info) {
2158 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
2159 LDB_FLAG_MOD_REPLACE, NULL);
2160 if (ret != LDB_SUCCESS) {
2161 return NT_STATUS_NO_MEMORY;
2165 /* start transaction */
2166 ret = ldb_transaction_start(p_state->sam_ldb);
2167 if (ret != LDB_SUCCESS) {
2168 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2170 in_transaction = true;
2172 if (msg->num_elements) {
2173 ret = ldb_modify(p_state->sam_ldb, msg);
2174 if (ret != LDB_SUCCESS) {
2175 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
2176 ldb_dn_get_linearized(msg->dn),
2177 ldb_errstring(p_state->sam_ldb)));
2178 nt_status = dsdb_ldb_err_to_ntstatus(ret);
2183 if (add_incoming || del_incoming) {
2184 const char *netbios_name;
2186 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
2188 if (!netbios_name) {
2189 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
2193 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
2194 nt_status = update_trust_user(mem_ctx,
2200 if (!NT_STATUS_IS_OK(nt_status)) {
2205 /* ok, all fine, commit transaction and return */
2206 ret = ldb_transaction_commit(p_state->sam_ldb);
2207 if (ret != LDB_SUCCESS) {
2208 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2210 in_transaction = false;
2212 nt_status = NT_STATUS_OK;
2215 if (in_transaction) {
2216 ldb_transaction_cancel(p_state->sam_ldb);
2222 lsa_SetInfomrationTrustedDomain
2224 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
2225 struct dcesrv_call_state *dce_call,
2226 TALLOC_CTX *mem_ctx,
2227 struct lsa_SetInformationTrustedDomain *r)
2229 struct dcesrv_handle *h;
2230 struct lsa_trusted_domain_state *td_state;
2231 struct ldb_message **msgs;
2234 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
2235 LSA_HANDLE_TRUSTED_DOMAIN);
2237 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2239 /* get the trusted domain object */
2240 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
2241 td_state->trusted_domain_dn,
2242 NULL, NULL, NULL, &msgs);
2243 if (!NT_STATUS_IS_OK(nt_status)) {
2244 if (NT_STATUS_EQUAL(nt_status,
2245 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2248 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2251 return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
2252 msgs[0], r->in.level, r->in.info);
2257 lsa_DeleteTrustedDomain
2259 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2260 struct lsa_DeleteTrustedDomain *r)
2263 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2264 struct lsa_DeleteObject del;
2265 struct dcesrv_handle *h;
2267 opn.in.handle = r->in.handle;
2268 opn.in.sid = r->in.dom_sid;
2269 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2270 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2271 if (!opn.out.trustdom_handle) {
2272 return NT_STATUS_NO_MEMORY;
2274 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2275 if (!NT_STATUS_IS_OK(status)) {
2279 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2280 talloc_steal(mem_ctx, h);
2282 del.in.handle = opn.out.trustdom_handle;
2283 del.out.handle = opn.out.trustdom_handle;
2284 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2285 if (!NT_STATUS_IS_OK(status)) {
2288 return NT_STATUS_OK;
2291 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2292 struct ldb_message *msg,
2293 struct lsa_TrustDomainInfoInfoEx *info_ex)
2295 info_ex->domain_name.string
2296 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2297 info_ex->netbios_name.string
2298 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2300 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2301 info_ex->trust_direction
2302 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2304 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2305 info_ex->trust_attributes
2306 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2307 return NT_STATUS_OK;
2311 lsa_QueryTrustedDomainInfo
2313 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2314 struct lsa_QueryTrustedDomainInfo *r)
2316 union lsa_TrustedDomainInfo *info = NULL;
2317 struct dcesrv_handle *h;
2318 struct lsa_trusted_domain_state *trusted_domain_state;
2319 struct ldb_message *msg;
2321 struct ldb_message **res;
2322 const char *attrs[] = {
2325 "securityIdentifier",
2329 "msDs-supportedEncryptionTypes",
2333 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2335 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2337 /* pull all the user attributes */
2338 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2339 trusted_domain_state->trusted_domain_dn, &res, attrs);
2341 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2345 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2347 return NT_STATUS_NO_MEMORY;
2349 *r->out.info = info;
2351 switch (r->in.level) {
2352 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2353 info->name.netbios_name.string
2354 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2356 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2357 info->posix_offset.posix_offset
2358 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2360 #if 0 /* Win2k3 doesn't implement this */
2361 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2362 r->out.info->info_basic.netbios_name.string
2363 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2364 r->out.info->info_basic.sid
2365 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2368 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2369 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2371 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2372 ZERO_STRUCT(info->full_info);
2373 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2374 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2375 ZERO_STRUCT(info->full_info2_internal);
2376 info->full_info2_internal.posix_offset.posix_offset
2377 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2378 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2380 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2381 info->enc_types.enc_types
2382 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2385 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2386 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2387 /* oops, we don't want to return the info after all */
2389 *r->out.info = NULL;
2390 return NT_STATUS_INVALID_PARAMETER;
2392 /* oops, we don't want to return the info after all */
2394 *r->out.info = NULL;
2395 return NT_STATUS_INVALID_INFO_CLASS;
2398 return NT_STATUS_OK;
2403 lsa_QueryTrustedDomainInfoBySid
2405 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2406 struct lsa_QueryTrustedDomainInfoBySid *r)
2409 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2410 struct lsa_QueryTrustedDomainInfo query;
2411 struct dcesrv_handle *h;
2413 opn.in.handle = r->in.handle;
2414 opn.in.sid = r->in.dom_sid;
2415 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2416 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2417 if (!opn.out.trustdom_handle) {
2418 return NT_STATUS_NO_MEMORY;
2420 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2421 if (!NT_STATUS_IS_OK(status)) {
2425 /* Ensure this handle goes away at the end of this call */
2426 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2427 talloc_steal(mem_ctx, h);
2429 query.in.trustdom_handle = opn.out.trustdom_handle;
2430 query.in.level = r->in.level;
2431 query.out.info = r->out.info;
2432 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2433 if (!NT_STATUS_IS_OK(status)) {
2437 return NT_STATUS_OK;
2441 lsa_SetTrustedDomainInfoByName
2443 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2444 TALLOC_CTX *mem_ctx,
2445 struct lsa_SetTrustedDomainInfoByName *r)
2447 struct dcesrv_handle *policy_handle;
2448 struct lsa_policy_state *policy_state;
2449 struct ldb_message **msgs;
2452 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2453 policy_state = policy_handle->data;
2455 /* get the trusted domain object */
2456 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2457 policy_state->domain_dn,
2458 r->in.trusted_domain->string,
2459 r->in.trusted_domain->string,
2461 if (!NT_STATUS_IS_OK(nt_status)) {
2462 if (NT_STATUS_EQUAL(nt_status,
2463 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2466 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2469 return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2470 msgs[0], r->in.level, r->in.info);
2474 lsa_QueryTrustedDomainInfoByName
2476 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2477 TALLOC_CTX *mem_ctx,
2478 struct lsa_QueryTrustedDomainInfoByName *r)
2481 struct lsa_OpenTrustedDomainByName opn = {{0},{0}};
2482 struct lsa_QueryTrustedDomainInfo query;
2483 struct dcesrv_handle *h;
2485 opn.in.handle = r->in.handle;
2486 opn.in.name = *r->in.trusted_domain;
2487 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2488 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2489 if (!opn.out.trustdom_handle) {
2490 return NT_STATUS_NO_MEMORY;
2492 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2493 if (!NT_STATUS_IS_OK(status)) {
2497 /* Ensure this handle goes away at the end of this call */
2498 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2499 talloc_steal(mem_ctx, h);
2501 query.in.trustdom_handle = opn.out.trustdom_handle;
2502 query.in.level = r->in.level;
2503 query.out.info = r->out.info;
2504 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2505 if (!NT_STATUS_IS_OK(status)) {
2509 return NT_STATUS_OK;
2513 lsa_CloseTrustedDomainEx
2515 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2516 TALLOC_CTX *mem_ctx,
2517 struct lsa_CloseTrustedDomainEx *r)
2519 /* The result of a bad hair day from an IDL programmer? Not
2520 * implmented in Win2k3. You should always just lsa_Close
2522 return NT_STATUS_NOT_IMPLEMENTED;
2527 comparison function for sorting lsa_DomainInformation array
2529 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2531 return strcasecmp_m(e1->name.string, e2->name.string);
2537 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2538 struct lsa_EnumTrustDom *r)
2540 struct dcesrv_handle *policy_handle;
2541 struct lsa_DomainInfo *entries;
2542 struct lsa_policy_state *policy_state;
2543 struct ldb_message **domains;
2544 const char *attrs[] = {
2546 "securityIdentifier",
2553 *r->out.resume_handle = 0;
2555 r->out.domains->domains = NULL;
2556 r->out.domains->count = 0;
2558 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2560 policy_state = policy_handle->data;
2562 /* search for all users in this domain. This could possibly be cached and
2563 resumed based on resume_key */
2564 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2565 "objectclass=trustedDomain");
2567 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2570 /* convert to lsa_TrustInformation format */
2571 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2573 return NT_STATUS_NO_MEMORY;
2575 for (i=0;i<count;i++) {
2576 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2577 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2580 /* sort the results by name */
2581 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2583 if (*r->in.resume_handle >= count) {
2584 *r->out.resume_handle = -1;
2586 return NT_STATUS_NO_MORE_ENTRIES;
2589 /* return the rest, limit by max_size. Note that we
2590 use the w2k3 element size value of 60 */
2591 r->out.domains->count = count - *r->in.resume_handle;
2592 r->out.domains->count = MIN(r->out.domains->count,
2593 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2595 r->out.domains->domains = entries + *r->in.resume_handle;
2596 r->out.domains->count = r->out.domains->count;
2598 if (r->out.domains->count < count - *r->in.resume_handle) {
2599 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2600 return STATUS_MORE_ENTRIES;
2603 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2604 * always be larger than the previous input resume handle, in
2605 * particular when hitting the last query it is vital to set the
2606 * resume handle correctly to avoid infinite client loops, as
2607 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2608 * status is NT_STATUS_OK - gd */
2610 *r->out.resume_handle = (uint32_t)-1;
2612 return NT_STATUS_OK;
2616 comparison function for sorting lsa_DomainInformation array
2618 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2620 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2624 lsa_EnumTrustedDomainsEx
2626 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2627 struct lsa_EnumTrustedDomainsEx *r)
2629 struct dcesrv_handle *policy_handle;
2630 struct lsa_TrustDomainInfoInfoEx *entries;
2631 struct lsa_policy_state *policy_state;
2632 struct ldb_message **domains;
2633 const char *attrs[] = {
2636 "securityIdentifier",
2646 *r->out.resume_handle = 0;
2648 r->out.domains->domains = NULL;
2649 r->out.domains->count = 0;
2651 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2653 policy_state = policy_handle->data;
2655 /* search for all users in this domain. This could possibly be cached and
2656 resumed based on resume_key */
2657 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2658 "objectclass=trustedDomain");
2660 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2663 /* convert to lsa_DomainInformation format */
2664 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2666 return NT_STATUS_NO_MEMORY;
2668 for (i=0;i<count;i++) {
2669 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2670 if (!NT_STATUS_IS_OK(nt_status)) {
2675 /* sort the results by name */
2676 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2678 if (*r->in.resume_handle >= count) {
2679 *r->out.resume_handle = -1;
2681 return NT_STATUS_NO_MORE_ENTRIES;
2684 /* return the rest, limit by max_size. Note that we
2685 use the w2k3 element size value of 60 */
2686 r->out.domains->count = count - *r->in.resume_handle;
2687 r->out.domains->count = MIN(r->out.domains->count,
2688 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2690 r->out.domains->domains = entries + *r->in.resume_handle;
2691 r->out.domains->count = r->out.domains->count;
2693 if (r->out.domains->count < count - *r->in.resume_handle) {
2694 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2695 return STATUS_MORE_ENTRIES;
2698 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2700 return NT_STATUS_OK;
2707 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2708 struct lsa_OpenAccount *r)
2710 struct dcesrv_handle *h, *ah;
2711 struct lsa_policy_state *state;
2712 struct lsa_account_state *astate;
2714 ZERO_STRUCTP(r->out.acct_handle);
2716 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2720 astate = talloc(dce_call->conn, struct lsa_account_state);
2721 if (astate == NULL) {
2722 return NT_STATUS_NO_MEMORY;
2725 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2726 if (astate->account_sid == NULL) {
2727 talloc_free(astate);
2728 return NT_STATUS_NO_MEMORY;
2731 astate->policy = talloc_reference(astate, state);
2732 astate->access_mask = r->in.access_mask;
2735 * For now we grant all requested access.
2737 * We will fail at the ldb layer later.
2739 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2740 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2741 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2743 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2745 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2746 __func__, dom_sid_string(mem_ctx, astate->account_sid),
2747 (unsigned)r->in.access_mask,
2748 (unsigned)astate->access_mask));
2750 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2752 talloc_free(astate);
2753 return NT_STATUS_NO_MEMORY;
2756 ah->data = talloc_steal(ah, astate);
2758 *r->out.acct_handle = ah->wire_handle;
2760 return NT_STATUS_OK;
2765 lsa_EnumPrivsAccount
2767 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2768 TALLOC_CTX *mem_ctx,
2769 struct lsa_EnumPrivsAccount *r)
2771 struct dcesrv_handle *h;
2772 struct lsa_account_state *astate;
2775 struct ldb_message **res;
2776 const char * const attrs[] = { "privilege", NULL};
2777 struct ldb_message_element *el;
2779 struct lsa_PrivilegeSet *privs;
2781 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2785 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2786 if (privs == NULL) {
2787 return NT_STATUS_NO_MEMORY;
2793 *r->out.privs = privs;
2795 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2796 if (sidstr == NULL) {
2797 return NT_STATUS_NO_MEMORY;
2800 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2801 "objectSid=%s", sidstr);
2803 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2806 return NT_STATUS_OK;
2809 el = ldb_msg_find_element(res[0], "privilege");
2810 if (el == NULL || el->num_values == 0) {
2811 return NT_STATUS_OK;
2814 privs->set = talloc_array(privs,
2815 struct lsa_LUIDAttribute, el->num_values);
2816 if (privs->set == NULL) {
2817 return NT_STATUS_NO_MEMORY;
2821 for (i=0;i<el->num_values;i++) {
2822 int id = sec_privilege_id((const char *)el->values[i].data);
2823 if (id == SEC_PRIV_INVALID) {
2824 /* Perhaps an account right, not a privilege */
2827 privs->set[j].attribute = 0;
2828 privs->set[j].luid.low = id;
2829 privs->set[j].luid.high = 0;
2835 return NT_STATUS_OK;
2839 lsa_EnumAccountRights
2841 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2842 TALLOC_CTX *mem_ctx,
2843 struct lsa_EnumAccountRights *r)
2845 struct dcesrv_handle *h;
2846 struct lsa_policy_state *state;
2849 struct ldb_message **res;
2850 const char * const attrs[] = { "privilege", NULL};
2852 struct ldb_message_element *el;
2854 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2858 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2859 if (sidstr == NULL) {
2860 return NT_STATUS_NO_MEMORY;
2863 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2864 "(&(objectSid=%s)(privilege=*))", sidstr);
2866 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2869 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2870 dom_sid_string(mem_ctx, r->in.sid),
2871 ldb_errstring(state->pdb)));
2872 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2875 el = ldb_msg_find_element(res[0], "privilege");
2876 if (el == NULL || el->num_values == 0) {
2877 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2880 r->out.rights->count = el->num_values;
2881 r->out.rights->names = talloc_array(r->out.rights,
2882 struct lsa_StringLarge, r->out.rights->count);
2883 if (r->out.rights->names == NULL) {
2884 return NT_STATUS_NO_MEMORY;
2887 for (i=0;i<el->num_values;i++) {
2888 r->out.rights->names[i].string = (const char *)el->values[i].data;
2891 return NT_STATUS_OK;
2897 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2899 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2900 TALLOC_CTX *mem_ctx,
2901 struct lsa_policy_state *state,
2903 struct dom_sid *sid,
2904 const struct lsa_RightSet *rights)
2906 const char *sidstr, *sidndrstr;
2907 struct ldb_message *msg;
2908 struct ldb_message_element *el;
2911 struct lsa_EnumAccountRights r2;
2914 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2915 SECURITY_ADMINISTRATOR) {
2916 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2917 return NT_STATUS_ACCESS_DENIED;
2920 msg = ldb_msg_new(mem_ctx);
2922 return NT_STATUS_NO_MEMORY;
2925 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2926 if (sidndrstr == NULL) {
2928 return NT_STATUS_NO_MEMORY;
2931 sidstr = dom_sid_string(msg, sid);
2932 if (sidstr == NULL) {
2934 return NT_STATUS_NO_MEMORY;
2937 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2938 if (dnstr == NULL) {
2940 return NT_STATUS_NO_MEMORY;
2943 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2944 if (msg->dn == NULL) {
2946 return NT_STATUS_NO_MEMORY;
2949 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2952 r2.in.handle = &state->handle->wire_handle;
2954 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2956 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2957 if (!NT_STATUS_IS_OK(status)) {
2958 ZERO_STRUCTP(r2.out.rights);
2962 for (i=0;i<rights->count;i++) {
2965 ok = dcesrc_lsa_valid_AccountRight(rights->names[i].string);
2968 return NT_STATUS_NO_SUCH_PRIVILEGE;
2971 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2973 for (j=0;j<r2.out.rights->count;j++) {
2974 if (strcasecmp_m(r2.out.rights->names[j].string,
2975 rights->names[i].string) == 0) {
2979 if (j != r2.out.rights->count) continue;
2982 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2983 if (ret != LDB_SUCCESS) {
2985 return NT_STATUS_NO_MEMORY;
2989 el = ldb_msg_find_element(msg, "privilege");
2992 return NT_STATUS_OK;
2995 el->flags = ldb_flag;
2997 ret = ldb_modify(state->pdb, msg);
2998 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2999 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
3001 return NT_STATUS_NO_MEMORY;
3003 ldb_msg_add_string(msg, "comment", "added via LSA");
3004 ret = ldb_add(state->pdb, msg);
3006 if (ret != LDB_SUCCESS) {
3007 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
3009 return NT_STATUS_OK;
3011 DEBUG(3, ("Could not %s attributes from %s: %s",
3012 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
3013 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
3015 return NT_STATUS_UNEXPECTED_IO_ERROR;
3019 return NT_STATUS_OK;
3023 lsa_AddPrivilegesToAccount
3025 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3026 struct lsa_AddPrivilegesToAccount *r)
3028 struct lsa_RightSet rights;
3029 struct dcesrv_handle *h;
3030 struct lsa_account_state *astate;
3033 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3037 rights.count = r->in.privs->count;
3038 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
3039 if (rights.names == NULL) {
3040 return NT_STATUS_NO_MEMORY;
3042 for (i=0;i<rights.count;i++) {
3043 int id = r->in.privs->set[i].luid.low;
3044 if (r->in.privs->set[i].luid.high) {
3045 return NT_STATUS_NO_SUCH_PRIVILEGE;
3047 rights.names[i].string = sec_privilege_name(id);
3048 if (rights.names[i].string == NULL) {
3049 return NT_STATUS_NO_SUCH_PRIVILEGE;
3053 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3054 LDB_FLAG_MOD_ADD, astate->account_sid,
3060 lsa_RemovePrivilegesFromAccount
3062 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3063 struct lsa_RemovePrivilegesFromAccount *r)
3065 struct lsa_RightSet *rights;
3066 struct dcesrv_handle *h;
3067 struct lsa_account_state *astate;
3070 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3074 rights = talloc(mem_ctx, struct lsa_RightSet);
3076 if (r->in.remove_all == 1 &&
3077 r->in.privs == NULL) {
3078 struct lsa_EnumAccountRights r2;
3081 r2.in.handle = &astate->policy->handle->wire_handle;
3082 r2.in.sid = astate->account_sid;
3083 r2.out.rights = rights;
3085 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
3086 if (!NT_STATUS_IS_OK(status)) {
3090 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3091 LDB_FLAG_MOD_DELETE, astate->account_sid,
3095 if (r->in.remove_all != 0) {
3096 return NT_STATUS_INVALID_PARAMETER;
3099 rights->count = r->in.privs->count;
3100 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
3101 if (rights->names == NULL) {
3102 return NT_STATUS_NO_MEMORY;
3104 for (i=0;i<rights->count;i++) {
3105 int id = r->in.privs->set[i].luid.low;
3106 if (r->in.privs->set[i].luid.high) {
3107 return NT_STATUS_NO_SUCH_PRIVILEGE;
3109 rights->names[i].string = sec_privilege_name(id);
3110 if (rights->names[i].string == NULL) {
3111 return NT_STATUS_NO_SUCH_PRIVILEGE;
3115 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3116 LDB_FLAG_MOD_DELETE, astate->account_sid,
3122 lsa_GetQuotasForAccount
3124 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3125 struct lsa_GetQuotasForAccount *r)
3127 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3132 lsa_SetQuotasForAccount
3134 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3135 struct lsa_SetQuotasForAccount *r)
3137 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3142 lsa_GetSystemAccessAccount
3144 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3145 struct lsa_GetSystemAccessAccount *r)
3147 struct dcesrv_handle *h;
3148 struct lsa_account_state *astate;
3151 struct ldb_message **res;
3152 const char * const attrs[] = { "privilege", NULL};
3153 struct ldb_message_element *el;
3156 *(r->out.access_mask) = 0x00000000;
3158 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3162 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
3163 if (sidstr == NULL) {
3164 return NT_STATUS_NO_MEMORY;
3167 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
3168 "objectSid=%s", sidstr);
3170 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3173 return NT_STATUS_OK;
3176 el = ldb_msg_find_element(res[0], "privilege");
3177 if (el == NULL || el->num_values == 0) {
3178 return NT_STATUS_OK;
3181 for (i=0;i<el->num_values;i++) {
3182 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
3183 if (right_bit == 0) {
3184 /* Perhaps an privilege, not a right */
3187 *(r->out.access_mask) |= right_bit;
3190 return NT_STATUS_OK;
3195 lsa_SetSystemAccessAccount
3197 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3198 struct lsa_SetSystemAccessAccount *r)
3200 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3207 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3208 struct lsa_CreateSecret *r)
3210 struct dcesrv_handle *policy_handle;
3211 struct lsa_policy_state *policy_state;
3212 struct lsa_secret_state *secret_state;
3213 struct dcesrv_handle *handle;
3214 struct ldb_message **msgs, *msg;
3215 const char *attrs[] = {
3223 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3224 ZERO_STRUCTP(r->out.sec_handle);
3226 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3228 case SECURITY_SYSTEM:
3229 case SECURITY_ADMINISTRATOR:
3232 /* Users and annonymous are not allowed create secrets */
3233 return NT_STATUS_ACCESS_DENIED;
3236 policy_state = policy_handle->data;
3238 if (!r->in.name.string) {
3239 return NT_STATUS_INVALID_PARAMETER;
3242 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3243 NT_STATUS_HAVE_NO_MEMORY(secret_state);
3244 secret_state->policy = policy_state;
3246 msg = ldb_msg_new(mem_ctx);
3248 return NT_STATUS_NO_MEMORY;
3251 if (strncmp("G$", r->in.name.string, 2) == 0) {
3254 secret_state->global = true;
3256 name = &r->in.name.string[2];
3257 if (strlen(name) == 0) {
3258 return NT_STATUS_INVALID_PARAMETER;
3261 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3262 ldb_binary_encode_string(mem_ctx, name));
3263 NT_STATUS_HAVE_NO_MEMORY(name2);
3265 /* We need to connect to the database as system, as this is one
3266 * of the rare RPC calls that must read the secrets (and this
3267 * is denied otherwise) */
3268 secret_state->sam_ldb = talloc_reference(secret_state,
3269 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));
3270 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3272 /* search for the secret record */
3273 ret = gendb_search(secret_state->sam_ldb,
3274 mem_ctx, policy_state->system_dn, &msgs, attrs,
3275 "(&(cn=%s)(objectclass=secret))",
3278 return NT_STATUS_OBJECT_NAME_COLLISION;
3282 DEBUG(0,("Failure searching for CN=%s: %s\n",
3283 name2, ldb_errstring(secret_state->sam_ldb)));
3284 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3287 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3288 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3289 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3290 return NT_STATUS_NO_MEMORY;
3293 ret = ldb_msg_add_string(msg, "cn", name2);
3294 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3296 secret_state->global = false;
3298 name = r->in.name.string;
3299 if (strlen(name) == 0) {
3300 return NT_STATUS_INVALID_PARAMETER;
3303 secret_state->sam_ldb = talloc_reference(secret_state,
3304 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3305 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3307 /* search for the secret record */
3308 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3309 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3311 "(&(cn=%s)(objectclass=secret))",
3312 ldb_binary_encode_string(mem_ctx, name));
3314 return NT_STATUS_OBJECT_NAME_COLLISION;
3318 DEBUG(0,("Failure searching for CN=%s: %s\n",
3319 name, ldb_errstring(secret_state->sam_ldb)));
3320 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3323 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3324 "cn=%s,cn=LSA Secrets", name);
3325 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3326 ret = ldb_msg_add_string(msg, "cn", name);
3327 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3330 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3331 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3333 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3334 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3336 /* create the secret */
3337 ret = ldb_add(secret_state->sam_ldb, msg);
3338 if (ret != LDB_SUCCESS) {
3339 DEBUG(0,("Failed to create secret record %s: %s\n",
3340 ldb_dn_get_linearized(msg->dn),
3341 ldb_errstring(secret_state->sam_ldb)));
3342 return NT_STATUS_ACCESS_DENIED;
3345 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3346 NT_STATUS_HAVE_NO_MEMORY(handle);
3348 handle->data = talloc_steal(handle, secret_state);
3350 secret_state->access_mask = r->in.access_mask;
3351 secret_state->policy = talloc_reference(secret_state, policy_state);
3352 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3354 *r->out.sec_handle = handle->wire_handle;
3356 return NT_STATUS_OK;
3363 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3364 struct lsa_OpenSecret *r)
3366 struct dcesrv_handle *policy_handle;
3368 struct lsa_policy_state *policy_state;
3369 struct lsa_secret_state *secret_state;
3370 struct dcesrv_handle *handle;
3371 struct ldb_message **msgs;
3372 const char *attrs[] = {
3380 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3381 ZERO_STRUCTP(r->out.sec_handle);
3382 policy_state = policy_handle->data;
3384 if (!r->in.name.string) {
3385 return NT_STATUS_INVALID_PARAMETER;
3388 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3390 case SECURITY_SYSTEM:
3391 case SECURITY_ADMINISTRATOR:
3394 /* Users and annonymous are not allowed to access secrets */
3395 return NT_STATUS_ACCESS_DENIED;
3398 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3399 if (!secret_state) {
3400 return NT_STATUS_NO_MEMORY;
3402 secret_state->policy = policy_state;
3404 if (strncmp("G$", r->in.name.string, 2) == 0) {
3405 name = &r->in.name.string[2];
3406 /* 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) */
3407 secret_state->sam_ldb = talloc_reference(secret_state,
3408 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));
3409 secret_state->global = true;
3411 if (strlen(name) < 1) {
3412 return NT_STATUS_INVALID_PARAMETER;
3415 /* search for the secret record */
3416 ret = gendb_search(secret_state->sam_ldb,
3417 mem_ctx, policy_state->system_dn, &msgs, attrs,
3418 "(&(cn=%s Secret)(objectclass=secret))",
3419 ldb_binary_encode_string(mem_ctx, name));
3421 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3425 DEBUG(0,("Found %d records matching DN %s\n", ret,
3426 ldb_dn_get_linearized(policy_state->system_dn)));
3427 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3430 secret_state->global = false;
3431 secret_state->sam_ldb = talloc_reference(secret_state,
3432 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3434 name = r->in.name.string;
3435 if (strlen(name) < 1) {
3436 return NT_STATUS_INVALID_PARAMETER;
3439 /* search for the secret record */
3440 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3441 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3443 "(&(cn=%s)(objectclass=secret))",
3444 ldb_binary_encode_string(mem_ctx, name));
3446 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3450 DEBUG(0,("Found %d records matching CN=%s\n",
3451 ret, ldb_binary_encode_string(mem_ctx, name)));
3452 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3456 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3458 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3460 return NT_STATUS_NO_MEMORY;
3463 handle->data = talloc_steal(handle, secret_state);
3465 secret_state->access_mask = r->in.access_mask;
3466 secret_state->policy = talloc_reference(secret_state, policy_state);
3468 *r->out.sec_handle = handle->wire_handle;
3470 return NT_STATUS_OK;
3477 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3478 struct lsa_SetSecret *r)
3481 struct dcesrv_handle *h;
3482 struct lsa_secret_state *secret_state;
3483 struct ldb_message *msg;
3484 DATA_BLOB session_key;
3485 DATA_BLOB crypt_secret, secret;
3488 NTSTATUS status = NT_STATUS_OK;
3490 struct timeval now = timeval_current();
3491 NTTIME nt_now = timeval_to_nttime(&now);
3493 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3495 secret_state = h->data;
3497 msg = ldb_msg_new(mem_ctx);
3499 return NT_STATUS_NO_MEMORY;
3502 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3504 return NT_STATUS_NO_MEMORY;
3506 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3507 if (!NT_STATUS_IS_OK(status)) {
3511 if (r->in.old_val) {
3513 crypt_secret.data = r->in.old_val->data;
3514 crypt_secret.length = r->in.old_val->size;
3516 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3517 if (!NT_STATUS_IS_OK(status)) {
3521 val.data = secret.data;
3522 val.length = secret.length;
3525 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3526 return NT_STATUS_NO_MEMORY;
3529 /* set old value mtime */
3530 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3531 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3532 return NT_STATUS_NO_MEMORY;
3536 /* If the old value is not set, then migrate the
3537 * current value to the old value */
3538 const struct ldb_val *old_val;
3539 NTTIME last_set_time;
3540 struct ldb_message **res;
3541 const char *attrs[] = {
3547 /* search for the secret record */
3548 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3549 secret_state->secret_dn, &res, attrs);
3551 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3555 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3556 ldb_dn_get_linearized(secret_state->secret_dn)));
3557 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3560 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3561 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3565 if (ldb_msg_add_value(msg, "priorValue",
3566 old_val, NULL) != LDB_SUCCESS) {
3567 return NT_STATUS_NO_MEMORY;
3570 if (samdb_msg_add_delete(secret_state->sam_ldb,
3571 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3572 return NT_STATUS_NO_MEMORY;
3576 /* set old value mtime */
3577 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3578 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3579 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3580 return NT_STATUS_NO_MEMORY;
3583 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3584 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3585 return NT_STATUS_NO_MEMORY;
3590 if (r->in.new_val) {
3592 crypt_secret.data = r->in.new_val->data;
3593 crypt_secret.length = r->in.new_val->size;
3595 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3596 if (!NT_STATUS_IS_OK(status)) {
3600 val.data = secret.data;
3601 val.length = secret.length;
3604 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3605 return NT_STATUS_NO_MEMORY;
3608 /* set new value mtime */
3609 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3610 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3611 return NT_STATUS_NO_MEMORY;
3614 /* NULL out the NEW value */
3615 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3616 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3617 return NT_STATUS_NO_MEMORY;
3619 if (samdb_msg_add_delete(secret_state->sam_ldb,
3620 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3621 return NT_STATUS_NO_MEMORY;
3625 /* modify the samdb record */
3626 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3627 if (ret != LDB_SUCCESS) {
3628 return dsdb_ldb_err_to_ntstatus(ret);
3631 return NT_STATUS_OK;
3638 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3639 struct lsa_QuerySecret *r)
3641 struct dcesrv_handle *h;
3642 struct lsa_secret_state *secret_state;
3643 struct ldb_message *msg;
3644 DATA_BLOB session_key;
3645 DATA_BLOB crypt_secret, secret;
3647 struct ldb_message **res;
3648 const char *attrs[] = {
3658 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3660 /* Ensure user is permitted to read this... */
3661 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3663 case SECURITY_SYSTEM:
3664 case SECURITY_ADMINISTRATOR:
3667 /* Users and annonymous are not allowed to read secrets */
3668 return NT_STATUS_ACCESS_DENIED;
3671 secret_state = h->data;
3673 /* pull all the user attributes */
3674 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3675 secret_state->secret_dn, &res, attrs);
3677 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3681 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3682 if (!NT_STATUS_IS_OK(nt_status)) {
3686 if (r->in.old_val) {
3687 const struct ldb_val *prior_val;
3688 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3689 if (!r->out.old_val) {
3690 return NT_STATUS_NO_MEMORY;
3692 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3694 if (prior_val && prior_val->length) {
3695 secret.data = prior_val->data;
3696 secret.length = prior_val->length;
3699 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3700 if (!crypt_secret.length) {
3701 return NT_STATUS_NO_MEMORY;
3703 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3704 if (!r->out.old_val->buf) {
3705 return NT_STATUS_NO_MEMORY;
3707 r->out.old_val->buf->size = crypt_secret.length;
3708 r->out.old_val->buf->length = crypt_secret.length;
3709 r->out.old_val->buf->data = crypt_secret.data;
3713 if (r->in.old_mtime) {
3714 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3715 if (!r->out.old_mtime) {
3716 return NT_STATUS_NO_MEMORY;
3718 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3721 if (r->in.new_val) {
3722 const struct ldb_val *new_val;
3723 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3724 if (!r->out.new_val) {
3725 return NT_STATUS_NO_MEMORY;
3728 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3730 if (new_val && new_val->length) {
3731 secret.data = new_val->data;
3732 secret.length = new_val->length;
3735 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3736 if (!crypt_secret.length) {
3737 return NT_STATUS_NO_MEMORY;
3739 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3740 if (!r->out.new_val->buf) {
3741 return NT_STATUS_NO_MEMORY;
3743 r->out.new_val->buf->length = crypt_secret.length;
3744 r->out.new_val->buf->size = crypt_secret.length;
3745 r->out.new_val->buf->data = crypt_secret.data;
3749 if (r->in.new_mtime) {
3750 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3751 if (!r->out.new_mtime) {
3752 return NT_STATUS_NO_MEMORY;
3754 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3757 return NT_STATUS_OK;
3764 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3765 TALLOC_CTX *mem_ctx,
3766 struct lsa_LookupPrivValue *r)
3768 struct dcesrv_handle *h;
3771 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3773 id = sec_privilege_id(r->in.name->string);
3774 if (id == SEC_PRIV_INVALID) {
3775 return NT_STATUS_NO_SUCH_PRIVILEGE;
3778 r->out.luid->low = id;
3779 r->out.luid->high = 0;
3781 return NT_STATUS_OK;
3788 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3789 TALLOC_CTX *mem_ctx,
3790 struct lsa_LookupPrivName *r)
3792 struct dcesrv_handle *h;
3793 struct lsa_StringLarge *name;
3794 const char *privname;
3796 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3798 if (r->in.luid->high != 0) {
3799 return NT_STATUS_NO_SUCH_PRIVILEGE;
3802 privname = sec_privilege_name(r->in.luid->low);
3803 if (privname == NULL) {
3804 return NT_STATUS_NO_SUCH_PRIVILEGE;
3807 name = talloc(mem_ctx, struct lsa_StringLarge);
3809 return NT_STATUS_NO_MEMORY;
3812 name->string = privname;
3814 *r->out.name = name;
3816 return NT_STATUS_OK;
3821 lsa_LookupPrivDisplayName
3823 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3824 TALLOC_CTX *mem_ctx,
3825 struct lsa_LookupPrivDisplayName *r)
3827 struct dcesrv_handle *h;
3828 struct lsa_StringLarge *disp_name = NULL;
3829 enum sec_privilege id;
3831 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3833 id = sec_privilege_id(r->in.name->string);
3834 if (id == SEC_PRIV_INVALID) {
3835 return NT_STATUS_NO_SUCH_PRIVILEGE;
3838 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3839 if (disp_name == NULL) {
3840 return NT_STATUS_NO_MEMORY;
3843 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3844 if (disp_name->string == NULL) {
3845 return NT_STATUS_INTERNAL_ERROR;
3848 *r->out.disp_name = disp_name;
3849 *r->out.returned_language_id = 0;
3851 return NT_STATUS_OK;
3856 lsa_EnumAccountsWithUserRight
3858 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3859 TALLOC_CTX *mem_ctx,
3860 struct lsa_EnumAccountsWithUserRight *r)
3862 struct dcesrv_handle *h;
3863 struct lsa_policy_state *state;
3865 struct ldb_message **res;
3866 const char * const attrs[] = { "objectSid", NULL};
3867 const char *privname;
3870 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3874 if (r->in.name == NULL) {
3875 return NT_STATUS_NO_SUCH_PRIVILEGE;
3878 privname = r->in.name->string;
3880 ok = dcesrc_lsa_valid_AccountRight(privname);
3882 return NT_STATUS_NO_SUCH_PRIVILEGE;
3885 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3886 "privilege=%s", privname);
3888 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3891 return NT_STATUS_NO_MORE_ENTRIES;
3894 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3895 if (r->out.sids->sids == NULL) {
3896 return NT_STATUS_NO_MEMORY;
3898 for (i=0;i<ret;i++) {
3899 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3900 res[i], "objectSid");
3901 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3903 r->out.sids->num_sids = ret;
3905 return NT_STATUS_OK;
3910 lsa_AddAccountRights
3912 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3913 TALLOC_CTX *mem_ctx,
3914 struct lsa_AddAccountRights *r)
3916 struct dcesrv_handle *h;
3917 struct lsa_policy_state *state;
3919 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3923 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3925 r->in.sid, r->in.rights);
3930 lsa_RemoveAccountRights
3932 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3933 TALLOC_CTX *mem_ctx,
3934 struct lsa_RemoveAccountRights *r)
3936 struct dcesrv_handle *h;
3937 struct lsa_policy_state *state;
3939 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3943 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3944 LDB_FLAG_MOD_DELETE,
3945 r->in.sid, r->in.rights);
3950 lsa_StorePrivateData
3952 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3953 struct lsa_StorePrivateData *r)
3955 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3960 lsa_RetrievePrivateData
3962 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3963 struct lsa_RetrievePrivateData *r)
3965 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3972 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3973 struct lsa_GetUserName *r)
3975 enum dcerpc_transport_t transport =
3976 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3977 NTSTATUS status = NT_STATUS_OK;
3978 const char *account_name;
3979 const char *authority_name;
3980 struct lsa_String *_account_name;
3981 struct lsa_String *_authority_name = NULL;
3983 if (transport != NCACN_NP && transport != NCALRPC) {
3984 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3987 /* this is what w2k3 does */
3988 r->out.account_name = r->in.account_name;
3989 r->out.authority_name = r->in.authority_name;
3991 if (r->in.account_name
3992 && *r->in.account_name
3993 /* && *(*r->in.account_name)->string */
3995 return NT_STATUS_INVALID_PARAMETER;
3998 if (r->in.authority_name
3999 && *r->in.authority_name
4000 /* && *(*r->in.authority_name)->string */
4002 return NT_STATUS_INVALID_PARAMETER;
4005 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
4006 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
4008 _account_name = talloc(mem_ctx, struct lsa_String);
4009 NT_STATUS_HAVE_NO_MEMORY(_account_name);
4010 _account_name->string = account_name;
4012 if (r->in.authority_name) {
4013 _authority_name = talloc(mem_ctx, struct lsa_String);
4014 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
4015 _authority_name->string = authority_name;
4018 *r->out.account_name = _account_name;
4019 if (r->out.authority_name) {
4020 *r->out.authority_name = _authority_name;
4029 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
4030 TALLOC_CTX *mem_ctx,
4031 struct lsa_SetInfoPolicy2 *r)
4033 /* need to support these */
4034 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4037 static void kdc_get_policy(TALLOC_CTX *mem_ctx,
4038 struct loadparm_context *lp_ctx,
4039 struct smb_krb5_context *smb_krb5_context,
4040 struct lsa_DomainInfoKerberos *k)
4042 time_t svc_tkt_lifetime;
4043 time_t usr_tkt_lifetime;
4044 time_t renewal_lifetime;
4046 /* Our KDC always re-validates the client */
4047 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
4049 lpcfg_default_kdc_policy(mem_ctx, lp_ctx, &svc_tkt_lifetime,
4050 &usr_tkt_lifetime, &renewal_lifetime);
4052 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
4053 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
4054 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
4055 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
4056 However in the parent function we basically just did a full
4057 krb5_context init with the only purpose of getting a global
4058 config option (the max skew), it would probably make more sense
4059 to have a lp_ or ldb global option as the samba default */
4060 if (smb_krb5_context) {
4061 unix_to_nt_time(&k->clock_skew,
4062 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
4068 lsa_QueryDomainInformationPolicy
4070 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4071 TALLOC_CTX *mem_ctx,
4072 struct lsa_QueryDomainInformationPolicy *r)
4074 union lsa_DomainInformationPolicy *info;
4076 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
4078 return NT_STATUS_NO_MEMORY;
4081 switch (r->in.level) {
4082 case LSA_DOMAIN_INFO_POLICY_EFS:
4084 *r->out.info = NULL;
4085 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4086 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
4088 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
4089 struct smb_krb5_context *smb_krb5_context;
4090 int ret = smb_krb5_init_context(mem_ctx,
4091 dce_call->conn->dce_ctx->lp_ctx,
4095 *r->out.info = NULL;
4096 return NT_STATUS_INTERNAL_ERROR;
4098 kdc_get_policy(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
4101 talloc_free(smb_krb5_context);
4102 *r->out.info = info;
4103 return NT_STATUS_OK;
4107 *r->out.info = NULL;
4108 return NT_STATUS_INVALID_INFO_CLASS;
4113 lsa_SetDomInfoPolicy
4115 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4116 TALLOC_CTX *mem_ctx,
4117 struct lsa_SetDomainInformationPolicy *r)
4119 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4125 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
4126 TALLOC_CTX *mem_ctx,
4127 struct lsa_TestCall *r)
4129 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4135 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4136 struct lsa_CREDRWRITE *r)
4138 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4145 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4146 struct lsa_CREDRREAD *r)
4148 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4155 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4156 struct lsa_CREDRENUMERATE *r)
4158 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4163 lsa_CREDRWRITEDOMAINCREDENTIALS
4165 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4166 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
4168 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4173 lsa_CREDRREADDOMAINCREDENTIALS
4175 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4176 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
4178 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4185 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4186 struct lsa_CREDRDELETE *r)
4188 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4193 lsa_CREDRGETTARGETINFO
4195 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4196 struct lsa_CREDRGETTARGETINFO *r)
4198 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4203 lsa_CREDRPROFILELOADED
4205 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4206 struct lsa_CREDRPROFILELOADED *r)
4208 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4213 lsa_CREDRGETSESSIONTYPES
4215 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4216 struct lsa_CREDRGETSESSIONTYPES *r)
4218 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4223 lsa_LSARREGISTERAUDITEVENT
4225 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4226 struct lsa_LSARREGISTERAUDITEVENT *r)
4228 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4233 lsa_LSARGENAUDITEVENT
4235 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4236 struct lsa_LSARGENAUDITEVENT *r)
4238 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4243 lsa_LSARUNREGISTERAUDITEVENT
4245 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4246 struct lsa_LSARUNREGISTERAUDITEVENT *r)
4248 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4253 lsa_lsaRQueryForestTrustInformation
4255 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4256 struct lsa_lsaRQueryForestTrustInformation *r)
4258 struct dcesrv_handle *h = NULL;
4259 struct lsa_policy_state *p_state = NULL;
4260 int forest_level = DS_DOMAIN_FUNCTION_2000;
4261 const char * const trust_attrs[] = {
4262 "securityIdentifier",
4268 "msDS-TrustForestTrustInfo",
4271 struct ldb_message *trust_tdo_msg = NULL;
4272 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4273 struct ForestTrustInfo *trust_fti = NULL;
4274 struct lsa_ForestTrustInformation *trust_lfti = NULL;
4277 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4281 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4282 return NT_STATUS_INVALID_DOMAIN_STATE;
4285 forest_level = dsdb_forest_functional_level(p_state->sam_ldb);
4286 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4287 return NT_STATUS_INVALID_DOMAIN_STATE;
4290 if (r->in.trusted_domain_name->string == NULL) {
4291 return NT_STATUS_NO_SUCH_DOMAIN;
4294 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4295 r->in.trusted_domain_name->string,
4296 r->in.trusted_domain_name->string,
4297 trust_attrs, mem_ctx, &trust_tdo_msg);
4298 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4299 return NT_STATUS_NO_SUCH_DOMAIN;
4301 if (!NT_STATUS_IS_OK(status)) {
4305 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4306 if (!NT_STATUS_IS_OK(status)) {
4310 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4311 return NT_STATUS_INVALID_PARAMETER;
4314 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4315 return NT_STATUS_INVALID_PARAMETER;
4318 status = dsdb_trust_parse_forest_info(mem_ctx,
4321 if (!NT_STATUS_IS_OK(status)) {
4325 status = dsdb_trust_forest_info_to_lsa(mem_ctx, trust_fti,
4327 if (!NT_STATUS_IS_OK(status)) {
4331 *r->out.forest_trust_info = trust_lfti;
4332 return NT_STATUS_OK;
4336 lsa_lsaRSetForestTrustInformation
4338 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4339 TALLOC_CTX *mem_ctx,
4340 struct lsa_lsaRSetForestTrustInformation *r)
4342 struct dcesrv_handle *h;
4343 struct lsa_policy_state *p_state;
4344 const char * const trust_attrs[] = {
4345 "securityIdentifier",
4351 "msDS-TrustForestTrustInfo",
4354 struct ldb_message *trust_tdo_msg = NULL;
4355 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4356 struct lsa_ForestTrustInformation *step1_lfti = NULL;
4357 struct lsa_ForestTrustInformation *step2_lfti = NULL;
4358 struct ForestTrustInfo *trust_fti = NULL;
4359 struct ldb_result *trusts_res = NULL;
4361 struct lsa_TrustDomainInfoInfoEx *xref_tdo = NULL;
4362 struct lsa_ForestTrustInformation *xref_lfti = NULL;
4363 struct lsa_ForestTrustCollisionInfo *c_info = NULL;
4364 DATA_BLOB ft_blob = {};
4365 struct ldb_message *msg = NULL;
4367 enum ndr_err_code ndr_err;
4369 bool in_transaction = false;
4371 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4375 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4376 return NT_STATUS_INVALID_DOMAIN_STATE;
4379 if (r->in.check_only == 0) {
4380 ret = ldb_transaction_start(p_state->sam_ldb);
4381 if (ret != LDB_SUCCESS) {
4382 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4384 in_transaction = true;
4388 * abort if we are not a PDC
4390 * In future we should use a function like IsEffectiveRoleOwner()
4392 if (!samdb_is_pdc(p_state->sam_ldb)) {
4393 status = NT_STATUS_INVALID_DOMAIN_ROLE;
4397 if (r->in.trusted_domain_name->string == NULL) {
4398 status = NT_STATUS_NO_SUCH_DOMAIN;
4402 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4403 r->in.trusted_domain_name->string,
4404 r->in.trusted_domain_name->string,
4405 trust_attrs, mem_ctx, &trust_tdo_msg);
4406 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4407 status = NT_STATUS_NO_SUCH_DOMAIN;
4410 if (!NT_STATUS_IS_OK(status)) {
4414 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4415 if (!NT_STATUS_IS_OK(status)) {
4419 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4420 status = NT_STATUS_INVALID_PARAMETER;
4424 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4425 status = NT_STATUS_INVALID_PARAMETER;
4430 * verify and normalize the given forest trust info.
4432 * Step1: doesn't reorder yet, so step1_lfti might contain
4433 * NULL entries. This means dsdb_trust_verify_forest_info()
4434 * can generate collision entries with the callers index.
4436 status = dsdb_trust_normalize_forest_info_step1(mem_ctx,
4437 r->in.forest_trust_info,
4439 if (!NT_STATUS_IS_OK(status)) {
4443 c_info = talloc_zero(r->out.collision_info,
4444 struct lsa_ForestTrustCollisionInfo);
4445 if (c_info == NULL) {
4446 status = NT_STATUS_NO_MEMORY;
4451 * First check our own forest, then other domains/forests
4454 status = dsdb_trust_xref_tdo_info(mem_ctx, p_state->sam_ldb,
4456 if (!NT_STATUS_IS_OK(status)) {
4459 status = dsdb_trust_xref_forest_info(mem_ctx, p_state->sam_ldb,
4461 if (!NT_STATUS_IS_OK(status)) {
4466 * The documentation proposed to generate
4467 * LSA_FOREST_TRUST_COLLISION_XREF collisions.
4468 * But Windows always uses LSA_FOREST_TRUST_COLLISION_TDO.
4470 status = dsdb_trust_verify_forest_info(xref_tdo, xref_lfti,
4471 LSA_FOREST_TRUST_COLLISION_TDO,
4472 c_info, step1_lfti);
4473 if (!NT_STATUS_IS_OK(status)) {
4477 /* fetch all other trusted domain objects */
4478 status = dsdb_trust_search_tdos(p_state->sam_ldb,
4479 trust_tdo->domain_name.string,
4481 mem_ctx, &trusts_res);
4482 if (!NT_STATUS_IS_OK(status)) {
4487 * now check against the other domains.
4488 * and generate LSA_FOREST_TRUST_COLLISION_TDO collisions.
4490 for (i = 0; i < trusts_res->count; i++) {
4491 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
4492 struct ForestTrustInfo *fti = NULL;
4493 struct lsa_ForestTrustInformation *lfti = NULL;
4495 status = dsdb_trust_parse_tdo_info(mem_ctx,
4496 trusts_res->msgs[i],
4498 if (!NT_STATUS_IS_OK(status)) {
4502 status = dsdb_trust_parse_forest_info(tdo,
4503 trusts_res->msgs[i],
4505 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
4508 if (!NT_STATUS_IS_OK(status)) {
4512 status = dsdb_trust_forest_info_to_lsa(tdo, fti, &lfti);
4513 if (!NT_STATUS_IS_OK(status)) {
4517 status = dsdb_trust_verify_forest_info(tdo, lfti,
4518 LSA_FOREST_TRUST_COLLISION_TDO,
4519 c_info, step1_lfti);
4520 if (!NT_STATUS_IS_OK(status)) {
4527 if (r->in.check_only != 0) {
4528 status = NT_STATUS_OK;
4533 * not just a check, write info back
4537 * normalize the given forest trust info.
4539 * Step2: adds TOP_LEVEL_NAME[_EX] in reverse order,
4540 * followed by DOMAIN_INFO in reverse order. It also removes
4541 * possible NULL entries from Step1.
4543 status = dsdb_trust_normalize_forest_info_step2(mem_ctx, step1_lfti,
4545 if (!NT_STATUS_IS_OK(status)) {
4549 status = dsdb_trust_forest_info_from_lsa(mem_ctx, step2_lfti,
4551 if (!NT_STATUS_IS_OK(status)) {
4555 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, trust_fti,
4556 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4557 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4558 status = NT_STATUS_INVALID_PARAMETER;
4562 msg = ldb_msg_new(mem_ctx);
4564 status = NT_STATUS_NO_MEMORY;
4568 msg->dn = ldb_dn_copy(mem_ctx, trust_tdo_msg->dn);
4570 status = NT_STATUS_NO_MEMORY;
4574 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4575 LDB_FLAG_MOD_REPLACE, NULL);
4576 if (ret != LDB_SUCCESS) {
4577 status = NT_STATUS_NO_MEMORY;
4580 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4582 if (ret != LDB_SUCCESS) {
4583 status = NT_STATUS_NO_MEMORY;
4587 ret = ldb_modify(p_state->sam_ldb, msg);
4588 if (ret != LDB_SUCCESS) {
4589 status = dsdb_ldb_err_to_ntstatus(ret);
4591 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4592 ldb_errstring(p_state->sam_ldb)));
4597 /* ok, all fine, commit transaction and return */
4598 in_transaction = false;
4599 ret = ldb_transaction_commit(p_state->sam_ldb);
4600 if (ret != LDB_SUCCESS) {
4601 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4605 status = NT_STATUS_OK;
4608 if (NT_STATUS_IS_OK(status) && c_info->count != 0) {
4609 *r->out.collision_info = c_info;
4612 if (in_transaction) {
4613 ldb_transaction_cancel(p_state->sam_ldb);
4622 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4623 struct lsa_CREDRRENAME *r)
4625 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4631 lsa_LSAROPENPOLICYSCE
4633 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4634 struct lsa_LSAROPENPOLICYSCE *r)
4636 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4641 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4643 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4644 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4646 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4651 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4653 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4654 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4656 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4661 lsa_LSARADTREPORTSECURITYEVENT
4663 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4664 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4666 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4670 /* include the generated boilerplate */
4671 #include "librpc/gen_ndr/ndr_lsa_s.c"
4675 /*****************************************
4676 NOTE! The remaining calls below were
4677 removed in w2k3, so the DCESRV_FAULT()
4678 replies are the correct implementation. Do
4679 not try and fill these in with anything else
4680 ******************************************/
4683 dssetup_DsRoleDnsNameToFlatName
4685 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4686 struct dssetup_DsRoleDnsNameToFlatName *r)
4688 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4693 dssetup_DsRoleDcAsDc
4695 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4696 struct dssetup_DsRoleDcAsDc *r)
4698 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4703 dssetup_DsRoleDcAsReplica
4705 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4706 struct dssetup_DsRoleDcAsReplica *r)
4708 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4713 dssetup_DsRoleDemoteDc
4715 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4716 struct dssetup_DsRoleDemoteDc *r)
4718 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4723 dssetup_DsRoleGetDcOperationProgress
4725 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4726 struct dssetup_DsRoleGetDcOperationProgress *r)
4728 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4733 dssetup_DsRoleGetDcOperationResults
4735 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4736 struct dssetup_DsRoleGetDcOperationResults *r)
4738 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4743 dssetup_DsRoleCancel
4745 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4746 struct dssetup_DsRoleCancel *r)
4748 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4753 dssetup_DsRoleServerSaveStateForUpgrade
4755 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4756 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4758 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4763 dssetup_DsRoleUpgradeDownlevelServer
4765 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4766 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4768 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4773 dssetup_DsRoleAbortDownlevelServerUpgrade
4775 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4776 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4778 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4782 /* include the generated boilerplate */
4783 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4785 NTSTATUS dcerpc_server_lsa_init(TALLOC_CTX *ctx)
4789 ret = dcerpc_server_dssetup_init(ctx);
4790 if (!NT_STATUS_IS_OK(ret)) {
4793 ret = dcerpc_server_lsarpc_init(ctx);
4794 if (!NT_STATUS_IS_OK(ret)) {