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 enum ndr_err_code ndr_err;
1366 ndr_err = ndr_push_struct_blob(&b, mem_ctx, r->in.info,
1367 (ndr_push_flags_fn_t)ndr_push_lsa_TrustDomainInfoInfoEx);
1368 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1369 imessaging_send(dce_call->msg_ctx, server_ids[0],
1370 MSG_WINBIND_NEW_TRUSTED_DOMAIN, &b);
1373 TALLOC_FREE(server_ids);
1375 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1377 return NT_STATUS_NO_MEMORY;
1380 handle->data = talloc_steal(handle, trusted_domain_state);
1382 trusted_domain_state->access_mask = r->in.access_mask;
1383 trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1385 *r->out.trustdom_handle = handle->wire_handle;
1387 return NT_STATUS_OK;
1391 lsa_CreateTrustedDomainEx2
1393 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1394 TALLOC_CTX *mem_ctx,
1395 struct lsa_CreateTrustedDomainEx2 *r)
1397 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1400 lsa_CreateTrustedDomainEx
1402 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1403 TALLOC_CTX *mem_ctx,
1404 struct lsa_CreateTrustedDomainEx *r)
1406 struct lsa_CreateTrustedDomainEx2 r2;
1408 r2.in.policy_handle = r->in.policy_handle;
1409 r2.in.info = r->in.info;
1410 r2.out.trustdom_handle = r->out.trustdom_handle;
1411 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1415 lsa_CreateTrustedDomain
1417 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1418 struct lsa_CreateTrustedDomain *r)
1420 struct lsa_CreateTrustedDomainEx2 r2;
1422 r2.in.policy_handle = r->in.policy_handle;
1423 r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1425 return NT_STATUS_NO_MEMORY;
1428 r2.in.info->domain_name = r->in.info->name;
1429 r2.in.info->netbios_name = r->in.info->name;
1430 r2.in.info->sid = r->in.info->sid;
1431 r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1432 r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1433 r2.in.info->trust_attributes = 0;
1435 r2.in.access_mask = r->in.access_mask;
1436 r2.out.trustdom_handle = r->out.trustdom_handle;
1438 return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1441 static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
1442 struct dcesrv_call_state *dce_call,
1443 TALLOC_CTX *tmp_mem,
1444 struct lsa_policy_state *policy_state,
1446 uint32_t access_mask,
1447 struct dcesrv_handle **_handle)
1449 struct lsa_trusted_domain_state *trusted_domain_state;
1450 struct dcesrv_handle *handle;
1451 struct ldb_message **msgs;
1452 const char *attrs[] = {
1460 /* TODO: perform access checks */
1462 /* search for the trusted_domain record */
1463 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1464 policy_state->system_dn,
1465 &msgs, attrs, "%s", filter);
1467 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1471 DEBUG(0,("Found %d records matching %s under %s\n", ret,
1473 ldb_dn_get_linearized(policy_state->system_dn)));
1474 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1477 trusted_domain_state = talloc_zero(tmp_mem,
1478 struct lsa_trusted_domain_state);
1479 if (!trusted_domain_state) {
1480 return NT_STATUS_NO_MEMORY;
1482 trusted_domain_state->policy = policy_state;
1484 trusted_domain_state->trusted_domain_dn =
1485 talloc_steal(trusted_domain_state, msgs[0]->dn);
1487 direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1488 if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1489 const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1492 /* search for the trusted_domain account */
1493 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1494 policy_state->domain_dn,
1496 "(&(samaccountname=%s$)(objectclass=user)"
1497 "(userAccountControl:%s:=%u))",
1499 LDB_OID_COMPARATOR_AND,
1500 UF_INTERDOMAIN_TRUST_ACCOUNT);
1502 trusted_domain_state->trusted_domain_user_dn =
1503 talloc_steal(trusted_domain_state, msgs[0]->dn);
1507 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1509 return NT_STATUS_NO_MEMORY;
1512 handle->data = talloc_steal(handle, trusted_domain_state);
1514 trusted_domain_state->access_mask = access_mask;
1515 trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1520 return NT_STATUS_OK;
1524 lsa_OpenTrustedDomain
1526 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1527 struct lsa_OpenTrustedDomain *r)
1529 struct dcesrv_handle *policy_handle;
1530 struct lsa_policy_state *policy_state;
1531 struct dcesrv_handle *handle;
1532 const char *sid_string;
1536 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1537 ZERO_STRUCTP(r->out.trustdom_handle);
1538 policy_state = policy_handle->data;
1540 sid_string = dom_sid_string(mem_ctx, r->in.sid);
1542 return NT_STATUS_NO_MEMORY;
1545 filter = talloc_asprintf(mem_ctx,
1546 "(&(securityIdentifier=%s)"
1547 "(objectclass=trustedDomain))",
1549 if (filter == NULL) {
1550 return NT_STATUS_NO_MEMORY;
1553 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1558 if (!NT_STATUS_IS_OK(status)) {
1562 *r->out.trustdom_handle = handle->wire_handle;
1564 return NT_STATUS_OK;
1569 lsa_OpenTrustedDomainByName
1571 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1572 TALLOC_CTX *mem_ctx,
1573 struct lsa_OpenTrustedDomainByName *r)
1575 struct dcesrv_handle *policy_handle;
1576 struct lsa_policy_state *policy_state;
1577 struct dcesrv_handle *handle;
1582 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1583 ZERO_STRUCTP(r->out.trustdom_handle);
1584 policy_state = policy_handle->data;
1586 if (!r->in.name.string) {
1587 return NT_STATUS_INVALID_PARAMETER;
1590 /* search for the trusted_domain record */
1591 td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1592 if (td_name == NULL) {
1593 return NT_STATUS_NO_MEMORY;
1596 filter = talloc_asprintf(mem_ctx,
1597 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1598 "(objectclass=trustedDomain))",
1599 td_name, td_name, td_name);
1600 if (filter == NULL) {
1601 return NT_STATUS_NO_MEMORY;
1604 status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1609 if (!NT_STATUS_IS_OK(status)) {
1613 *r->out.trustdom_handle = handle->wire_handle;
1615 return NT_STATUS_OK;
1621 lsa_SetTrustedDomainInfo
1623 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1624 struct lsa_SetTrustedDomainInfo *r)
1626 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1631 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1632 * otherwise at least one must be provided */
1633 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1634 struct ldb_dn *basedn, const char *dns_domain,
1635 const char *netbios, struct dom_sid2 *sid,
1636 struct ldb_message ***msgs)
1638 const char *attrs[] = { "flatname", "trustPartner",
1639 "securityIdentifier", "trustDirection",
1640 "trustType", "trustAttributes",
1642 "msDs-supportedEncryptionTypes",
1643 "msDS-TrustForestTrustInfo",
1648 char *sidstr = NULL;
1653 if (dns_domain || netbios || sid) {
1654 filter = talloc_strdup(mem_ctx,
1655 "(&(objectclass=trustedDomain)(|");
1657 filter = talloc_strdup(mem_ctx,
1658 "(objectclass=trustedDomain)");
1661 return NT_STATUS_NO_MEMORY;
1665 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1667 return NT_STATUS_NO_MEMORY;
1669 filter = talloc_asprintf_append(filter,
1670 "(trustPartner=%s)", dns);
1672 return NT_STATUS_NO_MEMORY;
1676 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1678 return NT_STATUS_NO_MEMORY;
1680 filter = talloc_asprintf_append(filter,
1681 "(flatname=%s)", nbn);
1683 return NT_STATUS_NO_MEMORY;
1687 sidstr = dom_sid_string(mem_ctx, sid);
1689 return NT_STATUS_INVALID_PARAMETER;
1691 filter = talloc_asprintf_append(filter,
1692 "(securityIdentifier=%s)",
1695 return NT_STATUS_NO_MEMORY;
1698 if (dns_domain || netbios || sid) {
1699 filter = talloc_asprintf_append(filter, "))");
1701 return NT_STATUS_NO_MEMORY;
1705 ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1707 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1711 return NT_STATUS_OBJECT_NAME_COLLISION;
1714 return NT_STATUS_OK;
1717 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1718 struct ldb_context *sam_ldb,
1719 struct ldb_message *orig,
1720 struct ldb_message *dest,
1721 const char *attribute,
1723 uint32_t *orig_value)
1725 const struct ldb_val *orig_val;
1726 uint32_t orig_uint = 0;
1727 unsigned int flags = 0;
1730 orig_val = ldb_msg_find_ldb_val(orig, attribute);
1731 if (!orig_val || !orig_val->data) {
1732 /* add new attribute */
1733 flags = LDB_FLAG_MOD_ADD;
1737 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1738 if (errno != 0 || orig_uint != value) {
1739 /* replace also if can't get value */
1740 flags = LDB_FLAG_MOD_REPLACE;
1745 /* stored value is identical, nothing to change */
1749 ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1750 if (ret != LDB_SUCCESS) {
1751 return NT_STATUS_NO_MEMORY;
1754 ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1755 if (ret != LDB_SUCCESS) {
1756 return NT_STATUS_NO_MEMORY;
1761 *orig_value = orig_uint;
1763 return NT_STATUS_OK;
1766 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1767 struct ldb_context *sam_ldb,
1768 struct ldb_dn *base_dn,
1770 const char *netbios_name,
1771 struct trustAuthInOutBlob *in)
1773 const char *attrs[] = { "userAccountControl", NULL };
1774 struct ldb_message **msgs;
1775 struct ldb_message *msg;
1780 ret = gendb_search(sam_ldb, mem_ctx,
1781 base_dn, &msgs, attrs,
1782 "samAccountName=%s$", netbios_name);
1784 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1789 return NT_STATUS_OK;
1792 /* ok no existing user, add it from scratch */
1793 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1794 netbios_name, in, NULL);
1797 /* check user is what we are looking for */
1798 uac = ldb_msg_find_attr_as_uint(msgs[0],
1799 "userAccountControl", 0);
1800 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1801 return NT_STATUS_OBJECT_NAME_COLLISION;
1805 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1808 return NT_STATUS_OK;
1809 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1810 return NT_STATUS_ACCESS_DENIED;
1812 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1816 /* entry exists, just modify secret if any */
1817 if (in == NULL || in->count == 0) {
1818 return NT_STATUS_OK;
1821 msg = ldb_msg_new(mem_ctx);
1823 return NT_STATUS_NO_MEMORY;
1825 msg->dn = msgs[0]->dn;
1827 for (i = 0; i < in->count; i++) {
1828 const char *attribute;
1830 switch (in->current.array[i].AuthType) {
1831 case TRUST_AUTH_TYPE_NT4OWF:
1832 attribute = "unicodePwd";
1833 v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1836 case TRUST_AUTH_TYPE_CLEAR:
1837 attribute = "clearTextPassword";
1838 v.data = in->current.array[i].AuthInfo.clear.password;
1839 v.length = in->current.array[i].AuthInfo.clear.size;
1845 ret = ldb_msg_add_empty(msg, attribute,
1846 LDB_FLAG_MOD_REPLACE, NULL);
1847 if (ret != LDB_SUCCESS) {
1848 return NT_STATUS_NO_MEMORY;
1851 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1852 if (ret != LDB_SUCCESS) {
1853 return NT_STATUS_NO_MEMORY;
1857 /* create the trusted_domain user account */
1858 ret = ldb_modify(sam_ldb, msg);
1859 if (ret != LDB_SUCCESS) {
1860 DEBUG(0,("Failed to create user record %s: %s\n",
1861 ldb_dn_get_linearized(msg->dn),
1862 ldb_errstring(sam_ldb)));
1865 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1866 return NT_STATUS_DOMAIN_EXISTS;
1867 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1868 return NT_STATUS_ACCESS_DENIED;
1870 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1874 return NT_STATUS_OK;
1878 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1879 struct lsa_policy_state *p_state,
1880 TALLOC_CTX *mem_ctx,
1881 struct ldb_message *dom_msg,
1882 enum lsa_TrustDomInfoEnum level,
1883 union lsa_TrustedDomainInfo *info)
1885 uint32_t *posix_offset = NULL;
1886 struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1887 struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1888 struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1889 uint32_t *enc_types = NULL;
1890 DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1891 struct trustDomainPasswords auth_struct;
1892 struct trustAuthInOutBlob *current_passwords = NULL;
1894 struct ldb_message **msgs;
1895 struct ldb_message *msg;
1896 bool add_outgoing = false;
1897 bool add_incoming = false;
1898 bool del_outgoing = false;
1899 bool del_incoming = false;
1900 bool del_forest_info = false;
1901 bool in_transaction = false;
1906 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1907 posix_offset = &info->posix_offset.posix_offset;
1909 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1910 info_ex = &info->info_ex;
1912 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1913 auth_info = &info->auth_info;
1915 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1916 posix_offset = &info->full_info.posix_offset.posix_offset;
1917 info_ex = &info->full_info.info_ex;
1918 auth_info = &info->full_info.auth_info;
1920 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1921 auth_info_int = &info->auth_info_internal;
1923 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1924 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1925 info_ex = &info->full_info_internal.info_ex;
1926 auth_info_int = &info->full_info_internal.auth_info;
1928 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1929 enc_types = &info->enc_types.enc_types;
1932 return NT_STATUS_INVALID_PARAMETER;
1936 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1938 &trustAuthOutgoing);
1939 if (!NT_STATUS_IS_OK(nt_status)) {
1942 if (trustAuthIncoming.data) {
1943 /* This does the decode of some of this twice, but it is easier that way */
1944 nt_status = auth_info_2_trustauth_inout(mem_ctx,
1945 auth_info->incoming_count,
1946 auth_info->incoming_current_auth_info,
1948 ¤t_passwords);
1949 if (!NT_STATUS_IS_OK(nt_status)) {
1955 /* decode auth_info_int if set */
1956 if (auth_info_int) {
1958 /* now decrypt blob */
1959 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1960 auth_info_int->auth_blob.size);
1962 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1963 &auth_blob, &auth_struct);
1964 if (!NT_STATUS_IS_OK(nt_status)) {
1970 /* verify data matches */
1971 if (info_ex->trust_attributes &
1972 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1973 /* TODO: check what behavior level we have */
1974 if (strcasecmp_m(p_state->domain_dns,
1975 p_state->forest_dns) != 0) {
1976 return NT_STATUS_INVALID_DOMAIN_STATE;
1980 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1981 if (ret == LDB_SUCCESS && am_rodc) {
1982 return NT_STATUS_NO_SUCH_DOMAIN;
1985 /* verify only one object matches the dns/netbios/sid
1986 * triplet and that this is the one we already have */
1987 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1989 info_ex->domain_name.string,
1990 info_ex->netbios_name.string,
1991 info_ex->sid, &msgs);
1992 if (!NT_STATUS_IS_OK(nt_status)) {
1995 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1996 return NT_STATUS_OBJECT_NAME_COLLISION;
2001 /* TODO: should we fetch previous values from the existing entry
2002 * and append them ? */
2003 if (auth_info_int && auth_struct.incoming.count) {
2004 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
2005 &auth_struct.incoming,
2006 &trustAuthIncoming);
2007 if (!NT_STATUS_IS_OK(nt_status)) {
2011 current_passwords = &auth_struct.incoming;
2014 trustAuthIncoming = data_blob(NULL, 0);
2017 if (auth_info_int && auth_struct.outgoing.count) {
2018 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
2019 &auth_struct.outgoing,
2020 &trustAuthOutgoing);
2021 if (!NT_STATUS_IS_OK(nt_status)) {
2025 trustAuthOutgoing = data_blob(NULL, 0);
2028 msg = ldb_msg_new(mem_ctx);
2030 return NT_STATUS_NO_MEMORY;
2032 msg->dn = dom_msg->dn;
2035 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2038 *posix_offset, NULL);
2039 if (!NT_STATUS_IS_OK(nt_status)) {
2046 uint32_t changed_attrs;
2050 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2053 info_ex->trust_direction,
2055 if (!NT_STATUS_IS_OK(nt_status)) {
2059 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2060 if (auth_info != NULL && trustAuthIncoming.length > 0) {
2061 add_incoming = true;
2064 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2065 if (auth_info != NULL && trustAuthOutgoing.length > 0) {
2066 add_outgoing = true;
2070 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
2071 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
2072 del_incoming = true;
2074 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
2075 !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2076 del_outgoing = true;
2079 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
2080 if (origtype == -1 || origtype != info_ex->trust_type) {
2081 DEBUG(1, ("Attempted to change trust type! "
2082 "Operation not handled\n"));
2083 return NT_STATUS_INVALID_PARAMETER;
2086 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2089 info_ex->trust_attributes,
2091 if (!NT_STATUS_IS_OK(nt_status)) {
2094 /* TODO: check forestFunctionality from ldb opaque */
2095 /* TODO: check what is set makes sense */
2097 changed_attrs = origattrs ^ info_ex->trust_attributes;
2098 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2100 * For now we only allow
2101 * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
2103 * TODO: we may need to support more attribute changes
2105 DEBUG(1, ("Attempted to change trust attributes "
2106 "(0x%08x != 0x%08x)! "
2107 "Operation not handled yet...\n",
2108 (unsigned)origattrs,
2109 (unsigned)info_ex->trust_attributes));
2110 return NT_STATUS_INVALID_PARAMETER;
2113 if (!(info_ex->trust_attributes &
2114 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
2116 struct ldb_message_element *orig_forest_el = NULL;
2118 orig_forest_el = ldb_msg_find_element(dom_msg,
2119 "msDS-TrustForestTrustInfo");
2120 if (orig_forest_el != NULL) {
2121 del_forest_info = true;
2127 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2129 "msDS-SupportedEncryptionTypes",
2131 if (!NT_STATUS_IS_OK(nt_status)) {
2136 if (add_incoming || del_incoming) {
2137 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
2138 LDB_FLAG_MOD_REPLACE, NULL);
2139 if (ret != LDB_SUCCESS) {
2140 return NT_STATUS_NO_MEMORY;
2143 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
2144 &trustAuthIncoming, NULL);
2145 if (ret != LDB_SUCCESS) {
2146 return NT_STATUS_NO_MEMORY;
2150 if (add_outgoing || del_outgoing) {
2151 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2152 LDB_FLAG_MOD_REPLACE, NULL);
2153 if (ret != LDB_SUCCESS) {
2154 return NT_STATUS_NO_MEMORY;
2157 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
2158 &trustAuthOutgoing, NULL);
2159 if (ret != LDB_SUCCESS) {
2160 return NT_STATUS_NO_MEMORY;
2164 if (del_forest_info) {
2165 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
2166 LDB_FLAG_MOD_REPLACE, NULL);
2167 if (ret != LDB_SUCCESS) {
2168 return NT_STATUS_NO_MEMORY;
2172 /* start transaction */
2173 ret = ldb_transaction_start(p_state->sam_ldb);
2174 if (ret != LDB_SUCCESS) {
2175 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2177 in_transaction = true;
2179 if (msg->num_elements) {
2180 ret = ldb_modify(p_state->sam_ldb, msg);
2181 if (ret != LDB_SUCCESS) {
2182 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
2183 ldb_dn_get_linearized(msg->dn),
2184 ldb_errstring(p_state->sam_ldb)));
2185 nt_status = dsdb_ldb_err_to_ntstatus(ret);
2190 if (add_incoming || del_incoming) {
2191 const char *netbios_name;
2193 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
2195 if (!netbios_name) {
2196 nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
2200 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
2201 nt_status = update_trust_user(mem_ctx,
2207 if (!NT_STATUS_IS_OK(nt_status)) {
2212 /* ok, all fine, commit transaction and return */
2213 ret = ldb_transaction_commit(p_state->sam_ldb);
2214 if (ret != LDB_SUCCESS) {
2215 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2217 in_transaction = false;
2219 nt_status = NT_STATUS_OK;
2222 if (in_transaction) {
2223 ldb_transaction_cancel(p_state->sam_ldb);
2229 lsa_SetInfomrationTrustedDomain
2231 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
2232 struct dcesrv_call_state *dce_call,
2233 TALLOC_CTX *mem_ctx,
2234 struct lsa_SetInformationTrustedDomain *r)
2236 struct dcesrv_handle *h;
2237 struct lsa_trusted_domain_state *td_state;
2238 struct ldb_message **msgs;
2241 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
2242 LSA_HANDLE_TRUSTED_DOMAIN);
2244 td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2246 /* get the trusted domain object */
2247 nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
2248 td_state->trusted_domain_dn,
2249 NULL, NULL, NULL, &msgs);
2250 if (!NT_STATUS_IS_OK(nt_status)) {
2251 if (NT_STATUS_EQUAL(nt_status,
2252 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2255 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2258 return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
2259 msgs[0], r->in.level, r->in.info);
2264 lsa_DeleteTrustedDomain
2266 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2267 struct lsa_DeleteTrustedDomain *r)
2270 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2271 struct lsa_DeleteObject del;
2272 struct dcesrv_handle *h;
2274 opn.in.handle = r->in.handle;
2275 opn.in.sid = r->in.dom_sid;
2276 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2277 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2278 if (!opn.out.trustdom_handle) {
2279 return NT_STATUS_NO_MEMORY;
2281 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2282 if (!NT_STATUS_IS_OK(status)) {
2286 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2287 talloc_steal(mem_ctx, h);
2289 del.in.handle = opn.out.trustdom_handle;
2290 del.out.handle = opn.out.trustdom_handle;
2291 status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2292 if (!NT_STATUS_IS_OK(status)) {
2295 return NT_STATUS_OK;
2298 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2299 struct ldb_message *msg,
2300 struct lsa_TrustDomainInfoInfoEx *info_ex)
2302 info_ex->domain_name.string
2303 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2304 info_ex->netbios_name.string
2305 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2307 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2308 info_ex->trust_direction
2309 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2311 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2312 info_ex->trust_attributes
2313 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2314 return NT_STATUS_OK;
2318 lsa_QueryTrustedDomainInfo
2320 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2321 struct lsa_QueryTrustedDomainInfo *r)
2323 union lsa_TrustedDomainInfo *info = NULL;
2324 struct dcesrv_handle *h;
2325 struct lsa_trusted_domain_state *trusted_domain_state;
2326 struct ldb_message *msg;
2328 struct ldb_message **res;
2329 const char *attrs[] = {
2332 "securityIdentifier",
2336 "msDs-supportedEncryptionTypes",
2340 DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2342 trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2344 /* pull all the user attributes */
2345 ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2346 trusted_domain_state->trusted_domain_dn, &res, attrs);
2348 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2352 info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2354 return NT_STATUS_NO_MEMORY;
2356 *r->out.info = info;
2358 switch (r->in.level) {
2359 case LSA_TRUSTED_DOMAIN_INFO_NAME:
2360 info->name.netbios_name.string
2361 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2363 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2364 info->posix_offset.posix_offset
2365 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2367 #if 0 /* Win2k3 doesn't implement this */
2368 case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2369 r->out.info->info_basic.netbios_name.string
2370 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2371 r->out.info->info_basic.sid
2372 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2375 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2376 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2378 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2379 ZERO_STRUCT(info->full_info);
2380 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2381 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2382 ZERO_STRUCT(info->full_info2_internal);
2383 info->full_info2_internal.posix_offset.posix_offset
2384 = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2385 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2387 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2388 info->enc_types.enc_types
2389 = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2392 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2393 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2394 /* oops, we don't want to return the info after all */
2396 *r->out.info = NULL;
2397 return NT_STATUS_INVALID_PARAMETER;
2399 /* oops, we don't want to return the info after all */
2401 *r->out.info = NULL;
2402 return NT_STATUS_INVALID_INFO_CLASS;
2405 return NT_STATUS_OK;
2410 lsa_QueryTrustedDomainInfoBySid
2412 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2413 struct lsa_QueryTrustedDomainInfoBySid *r)
2416 struct lsa_OpenTrustedDomain opn = {{0},{0}};
2417 struct lsa_QueryTrustedDomainInfo query;
2418 struct dcesrv_handle *h;
2420 opn.in.handle = r->in.handle;
2421 opn.in.sid = r->in.dom_sid;
2422 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2423 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2424 if (!opn.out.trustdom_handle) {
2425 return NT_STATUS_NO_MEMORY;
2427 status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2428 if (!NT_STATUS_IS_OK(status)) {
2432 /* Ensure this handle goes away at the end of this call */
2433 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2434 talloc_steal(mem_ctx, h);
2436 query.in.trustdom_handle = opn.out.trustdom_handle;
2437 query.in.level = r->in.level;
2438 query.out.info = r->out.info;
2439 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2440 if (!NT_STATUS_IS_OK(status)) {
2444 return NT_STATUS_OK;
2448 lsa_SetTrustedDomainInfoByName
2450 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2451 TALLOC_CTX *mem_ctx,
2452 struct lsa_SetTrustedDomainInfoByName *r)
2454 struct dcesrv_handle *policy_handle;
2455 struct lsa_policy_state *policy_state;
2456 struct ldb_message **msgs;
2459 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2460 policy_state = policy_handle->data;
2462 /* get the trusted domain object */
2463 nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2464 policy_state->domain_dn,
2465 r->in.trusted_domain->string,
2466 r->in.trusted_domain->string,
2468 if (!NT_STATUS_IS_OK(nt_status)) {
2469 if (NT_STATUS_EQUAL(nt_status,
2470 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2473 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2476 return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2477 msgs[0], r->in.level, r->in.info);
2481 lsa_QueryTrustedDomainInfoByName
2483 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2484 TALLOC_CTX *mem_ctx,
2485 struct lsa_QueryTrustedDomainInfoByName *r)
2488 struct lsa_OpenTrustedDomainByName opn = {{0},{0}};
2489 struct lsa_QueryTrustedDomainInfo query;
2490 struct dcesrv_handle *h;
2492 opn.in.handle = r->in.handle;
2493 opn.in.name = *r->in.trusted_domain;
2494 opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2495 opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2496 if (!opn.out.trustdom_handle) {
2497 return NT_STATUS_NO_MEMORY;
2499 status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2500 if (!NT_STATUS_IS_OK(status)) {
2504 /* Ensure this handle goes away at the end of this call */
2505 DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2506 talloc_steal(mem_ctx, h);
2508 query.in.trustdom_handle = opn.out.trustdom_handle;
2509 query.in.level = r->in.level;
2510 query.out.info = r->out.info;
2511 status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2512 if (!NT_STATUS_IS_OK(status)) {
2516 return NT_STATUS_OK;
2520 lsa_CloseTrustedDomainEx
2522 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2523 TALLOC_CTX *mem_ctx,
2524 struct lsa_CloseTrustedDomainEx *r)
2526 /* The result of a bad hair day from an IDL programmer? Not
2527 * implmented in Win2k3. You should always just lsa_Close
2529 return NT_STATUS_NOT_IMPLEMENTED;
2534 comparison function for sorting lsa_DomainInformation array
2536 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2538 return strcasecmp_m(e1->name.string, e2->name.string);
2544 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2545 struct lsa_EnumTrustDom *r)
2547 struct dcesrv_handle *policy_handle;
2548 struct lsa_DomainInfo *entries;
2549 struct lsa_policy_state *policy_state;
2550 struct ldb_message **domains;
2551 const char *attrs[] = {
2553 "securityIdentifier",
2560 *r->out.resume_handle = 0;
2562 r->out.domains->domains = NULL;
2563 r->out.domains->count = 0;
2565 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2567 policy_state = policy_handle->data;
2569 /* search for all users in this domain. This could possibly be cached and
2570 resumed based on resume_key */
2571 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2572 "objectclass=trustedDomain");
2574 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2577 /* convert to lsa_TrustInformation format */
2578 entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2580 return NT_STATUS_NO_MEMORY;
2582 for (i=0;i<count;i++) {
2583 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2584 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2587 /* sort the results by name */
2588 TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2590 if (*r->in.resume_handle >= count) {
2591 *r->out.resume_handle = -1;
2593 return NT_STATUS_NO_MORE_ENTRIES;
2596 /* return the rest, limit by max_size. Note that we
2597 use the w2k3 element size value of 60 */
2598 r->out.domains->count = count - *r->in.resume_handle;
2599 r->out.domains->count = MIN(r->out.domains->count,
2600 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2602 r->out.domains->domains = entries + *r->in.resume_handle;
2603 r->out.domains->count = r->out.domains->count;
2605 if (r->out.domains->count < count - *r->in.resume_handle) {
2606 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2607 return STATUS_MORE_ENTRIES;
2610 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2611 * always be larger than the previous input resume handle, in
2612 * particular when hitting the last query it is vital to set the
2613 * resume handle correctly to avoid infinite client loops, as
2614 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2615 * status is NT_STATUS_OK - gd */
2617 *r->out.resume_handle = (uint32_t)-1;
2619 return NT_STATUS_OK;
2623 comparison function for sorting lsa_DomainInformation array
2625 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2627 return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2631 lsa_EnumTrustedDomainsEx
2633 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2634 struct lsa_EnumTrustedDomainsEx *r)
2636 struct dcesrv_handle *policy_handle;
2637 struct lsa_TrustDomainInfoInfoEx *entries;
2638 struct lsa_policy_state *policy_state;
2639 struct ldb_message **domains;
2640 const char *attrs[] = {
2643 "securityIdentifier",
2653 *r->out.resume_handle = 0;
2655 r->out.domains->domains = NULL;
2656 r->out.domains->count = 0;
2658 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2660 policy_state = policy_handle->data;
2662 /* search for all users in this domain. This could possibly be cached and
2663 resumed based on resume_key */
2664 count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2665 "objectclass=trustedDomain");
2667 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2670 /* convert to lsa_DomainInformation format */
2671 entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2673 return NT_STATUS_NO_MEMORY;
2675 for (i=0;i<count;i++) {
2676 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2677 if (!NT_STATUS_IS_OK(nt_status)) {
2682 /* sort the results by name */
2683 TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2685 if (*r->in.resume_handle >= count) {
2686 *r->out.resume_handle = -1;
2688 return NT_STATUS_NO_MORE_ENTRIES;
2691 /* return the rest, limit by max_size. Note that we
2692 use the w2k3 element size value of 60 */
2693 r->out.domains->count = count - *r->in.resume_handle;
2694 r->out.domains->count = MIN(r->out.domains->count,
2695 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2697 r->out.domains->domains = entries + *r->in.resume_handle;
2698 r->out.domains->count = r->out.domains->count;
2700 if (r->out.domains->count < count - *r->in.resume_handle) {
2701 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2702 return STATUS_MORE_ENTRIES;
2705 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2707 return NT_STATUS_OK;
2714 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2715 struct lsa_OpenAccount *r)
2717 struct dcesrv_handle *h, *ah;
2718 struct lsa_policy_state *state;
2719 struct lsa_account_state *astate;
2721 ZERO_STRUCTP(r->out.acct_handle);
2723 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2727 astate = talloc(dce_call->conn, struct lsa_account_state);
2728 if (astate == NULL) {
2729 return NT_STATUS_NO_MEMORY;
2732 astate->account_sid = dom_sid_dup(astate, r->in.sid);
2733 if (astate->account_sid == NULL) {
2734 talloc_free(astate);
2735 return NT_STATUS_NO_MEMORY;
2738 astate->policy = talloc_reference(astate, state);
2739 astate->access_mask = r->in.access_mask;
2742 * For now we grant all requested access.
2744 * We will fail at the ldb layer later.
2746 if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2747 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2748 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2750 se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2752 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2753 __func__, dom_sid_string(mem_ctx, astate->account_sid),
2754 (unsigned)r->in.access_mask,
2755 (unsigned)astate->access_mask));
2757 ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2759 talloc_free(astate);
2760 return NT_STATUS_NO_MEMORY;
2763 ah->data = talloc_steal(ah, astate);
2765 *r->out.acct_handle = ah->wire_handle;
2767 return NT_STATUS_OK;
2772 lsa_EnumPrivsAccount
2774 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2775 TALLOC_CTX *mem_ctx,
2776 struct lsa_EnumPrivsAccount *r)
2778 struct dcesrv_handle *h;
2779 struct lsa_account_state *astate;
2782 struct ldb_message **res;
2783 const char * const attrs[] = { "privilege", NULL};
2784 struct ldb_message_element *el;
2786 struct lsa_PrivilegeSet *privs;
2788 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2792 privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2793 if (privs == NULL) {
2794 return NT_STATUS_NO_MEMORY;
2800 *r->out.privs = privs;
2802 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2803 if (sidstr == NULL) {
2804 return NT_STATUS_NO_MEMORY;
2807 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2808 "objectSid=%s", sidstr);
2810 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2813 return NT_STATUS_OK;
2816 el = ldb_msg_find_element(res[0], "privilege");
2817 if (el == NULL || el->num_values == 0) {
2818 return NT_STATUS_OK;
2821 privs->set = talloc_array(privs,
2822 struct lsa_LUIDAttribute, el->num_values);
2823 if (privs->set == NULL) {
2824 return NT_STATUS_NO_MEMORY;
2828 for (i=0;i<el->num_values;i++) {
2829 int id = sec_privilege_id((const char *)el->values[i].data);
2830 if (id == SEC_PRIV_INVALID) {
2831 /* Perhaps an account right, not a privilege */
2834 privs->set[j].attribute = 0;
2835 privs->set[j].luid.low = id;
2836 privs->set[j].luid.high = 0;
2842 return NT_STATUS_OK;
2846 lsa_EnumAccountRights
2848 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2849 TALLOC_CTX *mem_ctx,
2850 struct lsa_EnumAccountRights *r)
2852 struct dcesrv_handle *h;
2853 struct lsa_policy_state *state;
2856 struct ldb_message **res;
2857 const char * const attrs[] = { "privilege", NULL};
2859 struct ldb_message_element *el;
2861 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2865 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2866 if (sidstr == NULL) {
2867 return NT_STATUS_NO_MEMORY;
2870 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2871 "(&(objectSid=%s)(privilege=*))", sidstr);
2873 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2876 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2877 dom_sid_string(mem_ctx, r->in.sid),
2878 ldb_errstring(state->pdb)));
2879 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2882 el = ldb_msg_find_element(res[0], "privilege");
2883 if (el == NULL || el->num_values == 0) {
2884 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2887 r->out.rights->count = el->num_values;
2888 r->out.rights->names = talloc_array(r->out.rights,
2889 struct lsa_StringLarge, r->out.rights->count);
2890 if (r->out.rights->names == NULL) {
2891 return NT_STATUS_NO_MEMORY;
2894 for (i=0;i<el->num_values;i++) {
2895 r->out.rights->names[i].string = (const char *)el->values[i].data;
2898 return NT_STATUS_OK;
2904 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2906 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2907 TALLOC_CTX *mem_ctx,
2908 struct lsa_policy_state *state,
2910 struct dom_sid *sid,
2911 const struct lsa_RightSet *rights)
2913 const char *sidstr, *sidndrstr;
2914 struct ldb_message *msg;
2915 struct ldb_message_element *el;
2918 struct lsa_EnumAccountRights r2;
2921 if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2922 SECURITY_ADMINISTRATOR) {
2923 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2924 return NT_STATUS_ACCESS_DENIED;
2927 msg = ldb_msg_new(mem_ctx);
2929 return NT_STATUS_NO_MEMORY;
2932 sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2933 if (sidndrstr == NULL) {
2935 return NT_STATUS_NO_MEMORY;
2938 sidstr = dom_sid_string(msg, sid);
2939 if (sidstr == NULL) {
2941 return NT_STATUS_NO_MEMORY;
2944 dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2945 if (dnstr == NULL) {
2947 return NT_STATUS_NO_MEMORY;
2950 msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2951 if (msg->dn == NULL) {
2953 return NT_STATUS_NO_MEMORY;
2956 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2959 r2.in.handle = &state->handle->wire_handle;
2961 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2963 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2964 if (!NT_STATUS_IS_OK(status)) {
2965 ZERO_STRUCTP(r2.out.rights);
2969 for (i=0;i<rights->count;i++) {
2972 ok = dcesrc_lsa_valid_AccountRight(rights->names[i].string);
2975 return NT_STATUS_NO_SUCH_PRIVILEGE;
2978 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2980 for (j=0;j<r2.out.rights->count;j++) {
2981 if (strcasecmp_m(r2.out.rights->names[j].string,
2982 rights->names[i].string) == 0) {
2986 if (j != r2.out.rights->count) continue;
2989 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2990 if (ret != LDB_SUCCESS) {
2992 return NT_STATUS_NO_MEMORY;
2996 el = ldb_msg_find_element(msg, "privilege");
2999 return NT_STATUS_OK;
3002 el->flags = ldb_flag;
3004 ret = ldb_modify(state->pdb, msg);
3005 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
3006 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
3008 return NT_STATUS_NO_MEMORY;
3010 ldb_msg_add_string(msg, "comment", "added via LSA");
3011 ret = ldb_add(state->pdb, msg);
3013 if (ret != LDB_SUCCESS) {
3014 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
3016 return NT_STATUS_OK;
3018 DEBUG(3, ("Could not %s attributes from %s: %s",
3019 LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
3020 ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
3022 return NT_STATUS_UNEXPECTED_IO_ERROR;
3026 return NT_STATUS_OK;
3030 lsa_AddPrivilegesToAccount
3032 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3033 struct lsa_AddPrivilegesToAccount *r)
3035 struct lsa_RightSet rights;
3036 struct dcesrv_handle *h;
3037 struct lsa_account_state *astate;
3040 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3044 rights.count = r->in.privs->count;
3045 rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
3046 if (rights.names == NULL) {
3047 return NT_STATUS_NO_MEMORY;
3049 for (i=0;i<rights.count;i++) {
3050 int id = r->in.privs->set[i].luid.low;
3051 if (r->in.privs->set[i].luid.high) {
3052 return NT_STATUS_NO_SUCH_PRIVILEGE;
3054 rights.names[i].string = sec_privilege_name(id);
3055 if (rights.names[i].string == NULL) {
3056 return NT_STATUS_NO_SUCH_PRIVILEGE;
3060 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3061 LDB_FLAG_MOD_ADD, astate->account_sid,
3067 lsa_RemovePrivilegesFromAccount
3069 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3070 struct lsa_RemovePrivilegesFromAccount *r)
3072 struct lsa_RightSet *rights;
3073 struct dcesrv_handle *h;
3074 struct lsa_account_state *astate;
3077 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3081 rights = talloc(mem_ctx, struct lsa_RightSet);
3083 if (r->in.remove_all == 1 &&
3084 r->in.privs == NULL) {
3085 struct lsa_EnumAccountRights r2;
3088 r2.in.handle = &astate->policy->handle->wire_handle;
3089 r2.in.sid = astate->account_sid;
3090 r2.out.rights = rights;
3092 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
3093 if (!NT_STATUS_IS_OK(status)) {
3097 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3098 LDB_FLAG_MOD_DELETE, astate->account_sid,
3102 if (r->in.remove_all != 0) {
3103 return NT_STATUS_INVALID_PARAMETER;
3106 rights->count = r->in.privs->count;
3107 rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
3108 if (rights->names == NULL) {
3109 return NT_STATUS_NO_MEMORY;
3111 for (i=0;i<rights->count;i++) {
3112 int id = r->in.privs->set[i].luid.low;
3113 if (r->in.privs->set[i].luid.high) {
3114 return NT_STATUS_NO_SUCH_PRIVILEGE;
3116 rights->names[i].string = sec_privilege_name(id);
3117 if (rights->names[i].string == NULL) {
3118 return NT_STATUS_NO_SUCH_PRIVILEGE;
3122 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3123 LDB_FLAG_MOD_DELETE, astate->account_sid,
3129 lsa_GetQuotasForAccount
3131 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3132 struct lsa_GetQuotasForAccount *r)
3134 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3139 lsa_SetQuotasForAccount
3141 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3142 struct lsa_SetQuotasForAccount *r)
3144 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3149 lsa_GetSystemAccessAccount
3151 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3152 struct lsa_GetSystemAccessAccount *r)
3154 struct dcesrv_handle *h;
3155 struct lsa_account_state *astate;
3158 struct ldb_message **res;
3159 const char * const attrs[] = { "privilege", NULL};
3160 struct ldb_message_element *el;
3163 *(r->out.access_mask) = 0x00000000;
3165 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3169 sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
3170 if (sidstr == NULL) {
3171 return NT_STATUS_NO_MEMORY;
3174 ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
3175 "objectSid=%s", sidstr);
3177 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3180 return NT_STATUS_OK;
3183 el = ldb_msg_find_element(res[0], "privilege");
3184 if (el == NULL || el->num_values == 0) {
3185 return NT_STATUS_OK;
3188 for (i=0;i<el->num_values;i++) {
3189 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
3190 if (right_bit == 0) {
3191 /* Perhaps an privilege, not a right */
3194 *(r->out.access_mask) |= right_bit;
3197 return NT_STATUS_OK;
3202 lsa_SetSystemAccessAccount
3204 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3205 struct lsa_SetSystemAccessAccount *r)
3207 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3214 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3215 struct lsa_CreateSecret *r)
3217 struct dcesrv_handle *policy_handle;
3218 struct lsa_policy_state *policy_state;
3219 struct lsa_secret_state *secret_state;
3220 struct dcesrv_handle *handle;
3221 struct ldb_message **msgs, *msg;
3222 const char *attrs[] = {
3230 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3231 ZERO_STRUCTP(r->out.sec_handle);
3233 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3235 case SECURITY_SYSTEM:
3236 case SECURITY_ADMINISTRATOR:
3239 /* Users and annonymous are not allowed create secrets */
3240 return NT_STATUS_ACCESS_DENIED;
3243 policy_state = policy_handle->data;
3245 if (!r->in.name.string) {
3246 return NT_STATUS_INVALID_PARAMETER;
3249 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3250 NT_STATUS_HAVE_NO_MEMORY(secret_state);
3251 secret_state->policy = policy_state;
3253 msg = ldb_msg_new(mem_ctx);
3255 return NT_STATUS_NO_MEMORY;
3258 if (strncmp("G$", r->in.name.string, 2) == 0) {
3261 secret_state->global = true;
3263 name = &r->in.name.string[2];
3264 if (strlen(name) == 0) {
3265 return NT_STATUS_INVALID_PARAMETER;
3268 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3269 ldb_binary_encode_string(mem_ctx, name));
3270 NT_STATUS_HAVE_NO_MEMORY(name2);
3272 /* We need to connect to the database as system, as this is one
3273 * of the rare RPC calls that must read the secrets (and this
3274 * is denied otherwise) */
3275 secret_state->sam_ldb = talloc_reference(secret_state,
3276 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));
3277 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3279 /* search for the secret record */
3280 ret = gendb_search(secret_state->sam_ldb,
3281 mem_ctx, policy_state->system_dn, &msgs, attrs,
3282 "(&(cn=%s)(objectclass=secret))",
3285 return NT_STATUS_OBJECT_NAME_COLLISION;
3289 DEBUG(0,("Failure searching for CN=%s: %s\n",
3290 name2, ldb_errstring(secret_state->sam_ldb)));
3291 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3294 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3295 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3296 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3297 return NT_STATUS_NO_MEMORY;
3300 ret = ldb_msg_add_string(msg, "cn", name2);
3301 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3303 secret_state->global = false;
3305 name = r->in.name.string;
3306 if (strlen(name) == 0) {
3307 return NT_STATUS_INVALID_PARAMETER;
3310 secret_state->sam_ldb = talloc_reference(secret_state,
3311 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3312 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3314 /* search for the secret record */
3315 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3316 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3318 "(&(cn=%s)(objectclass=secret))",
3319 ldb_binary_encode_string(mem_ctx, name));
3321 return NT_STATUS_OBJECT_NAME_COLLISION;
3325 DEBUG(0,("Failure searching for CN=%s: %s\n",
3326 name, ldb_errstring(secret_state->sam_ldb)));
3327 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3330 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3331 "cn=%s,cn=LSA Secrets", name);
3332 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3333 ret = ldb_msg_add_string(msg, "cn", name);
3334 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3337 ret = ldb_msg_add_string(msg, "objectClass", "secret");
3338 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3340 secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3341 NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3343 /* create the secret */
3344 ret = ldb_add(secret_state->sam_ldb, msg);
3345 if (ret != LDB_SUCCESS) {
3346 DEBUG(0,("Failed to create secret record %s: %s\n",
3347 ldb_dn_get_linearized(msg->dn),
3348 ldb_errstring(secret_state->sam_ldb)));
3349 return NT_STATUS_ACCESS_DENIED;
3352 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3353 NT_STATUS_HAVE_NO_MEMORY(handle);
3355 handle->data = talloc_steal(handle, secret_state);
3357 secret_state->access_mask = r->in.access_mask;
3358 secret_state->policy = talloc_reference(secret_state, policy_state);
3359 NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3361 *r->out.sec_handle = handle->wire_handle;
3363 return NT_STATUS_OK;
3370 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3371 struct lsa_OpenSecret *r)
3373 struct dcesrv_handle *policy_handle;
3375 struct lsa_policy_state *policy_state;
3376 struct lsa_secret_state *secret_state;
3377 struct dcesrv_handle *handle;
3378 struct ldb_message **msgs;
3379 const char *attrs[] = {
3387 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3388 ZERO_STRUCTP(r->out.sec_handle);
3389 policy_state = policy_handle->data;
3391 if (!r->in.name.string) {
3392 return NT_STATUS_INVALID_PARAMETER;
3395 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3397 case SECURITY_SYSTEM:
3398 case SECURITY_ADMINISTRATOR:
3401 /* Users and annonymous are not allowed to access secrets */
3402 return NT_STATUS_ACCESS_DENIED;
3405 secret_state = talloc(mem_ctx, struct lsa_secret_state);
3406 if (!secret_state) {
3407 return NT_STATUS_NO_MEMORY;
3409 secret_state->policy = policy_state;
3411 if (strncmp("G$", r->in.name.string, 2) == 0) {
3412 name = &r->in.name.string[2];
3413 /* 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) */
3414 secret_state->sam_ldb = talloc_reference(secret_state,
3415 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));
3416 secret_state->global = true;
3418 if (strlen(name) < 1) {
3419 return NT_STATUS_INVALID_PARAMETER;
3422 /* search for the secret record */
3423 ret = gendb_search(secret_state->sam_ldb,
3424 mem_ctx, policy_state->system_dn, &msgs, attrs,
3425 "(&(cn=%s Secret)(objectclass=secret))",
3426 ldb_binary_encode_string(mem_ctx, name));
3428 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3432 DEBUG(0,("Found %d records matching DN %s\n", ret,
3433 ldb_dn_get_linearized(policy_state->system_dn)));
3434 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3437 secret_state->global = false;
3438 secret_state->sam_ldb = talloc_reference(secret_state,
3439 secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3441 name = r->in.name.string;
3442 if (strlen(name) < 1) {
3443 return NT_STATUS_INVALID_PARAMETER;
3446 /* search for the secret record */
3447 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3448 ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3450 "(&(cn=%s)(objectclass=secret))",
3451 ldb_binary_encode_string(mem_ctx, name));
3453 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3457 DEBUG(0,("Found %d records matching CN=%s\n",
3458 ret, ldb_binary_encode_string(mem_ctx, name)));
3459 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3463 secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3465 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3467 return NT_STATUS_NO_MEMORY;
3470 handle->data = talloc_steal(handle, secret_state);
3472 secret_state->access_mask = r->in.access_mask;
3473 secret_state->policy = talloc_reference(secret_state, policy_state);
3475 *r->out.sec_handle = handle->wire_handle;
3477 return NT_STATUS_OK;
3484 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3485 struct lsa_SetSecret *r)
3488 struct dcesrv_handle *h;
3489 struct lsa_secret_state *secret_state;
3490 struct ldb_message *msg;
3491 DATA_BLOB session_key;
3492 DATA_BLOB crypt_secret, secret;
3495 NTSTATUS status = NT_STATUS_OK;
3497 struct timeval now = timeval_current();
3498 NTTIME nt_now = timeval_to_nttime(&now);
3500 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3502 secret_state = h->data;
3504 msg = ldb_msg_new(mem_ctx);
3506 return NT_STATUS_NO_MEMORY;
3509 msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3511 return NT_STATUS_NO_MEMORY;
3513 status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3514 if (!NT_STATUS_IS_OK(status)) {
3518 if (r->in.old_val) {
3520 crypt_secret.data = r->in.old_val->data;
3521 crypt_secret.length = r->in.old_val->size;
3523 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3524 if (!NT_STATUS_IS_OK(status)) {
3528 val.data = secret.data;
3529 val.length = secret.length;
3532 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3533 return NT_STATUS_NO_MEMORY;
3536 /* set old value mtime */
3537 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3538 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3539 return NT_STATUS_NO_MEMORY;
3543 /* If the old value is not set, then migrate the
3544 * current value to the old value */
3545 const struct ldb_val *old_val;
3546 NTTIME last_set_time;
3547 struct ldb_message **res;
3548 const char *attrs[] = {
3554 /* search for the secret record */
3555 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3556 secret_state->secret_dn, &res, attrs);
3558 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3562 DEBUG(0,("Found %d records matching dn=%s\n", ret,
3563 ldb_dn_get_linearized(secret_state->secret_dn)));
3564 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3567 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3568 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3572 if (ldb_msg_add_value(msg, "priorValue",
3573 old_val, NULL) != LDB_SUCCESS) {
3574 return NT_STATUS_NO_MEMORY;
3577 if (samdb_msg_add_delete(secret_state->sam_ldb,
3578 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3579 return NT_STATUS_NO_MEMORY;
3583 /* set old value mtime */
3584 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3585 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3586 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3587 return NT_STATUS_NO_MEMORY;
3590 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3591 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3592 return NT_STATUS_NO_MEMORY;
3597 if (r->in.new_val) {
3599 crypt_secret.data = r->in.new_val->data;
3600 crypt_secret.length = r->in.new_val->size;
3602 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3603 if (!NT_STATUS_IS_OK(status)) {
3607 val.data = secret.data;
3608 val.length = secret.length;
3611 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3612 return NT_STATUS_NO_MEMORY;
3615 /* set new value mtime */
3616 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3617 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3618 return NT_STATUS_NO_MEMORY;
3621 /* NULL out the NEW value */
3622 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3623 mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3624 return NT_STATUS_NO_MEMORY;
3626 if (samdb_msg_add_delete(secret_state->sam_ldb,
3627 mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3628 return NT_STATUS_NO_MEMORY;
3632 /* modify the samdb record */
3633 ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3634 if (ret != LDB_SUCCESS) {
3635 return dsdb_ldb_err_to_ntstatus(ret);
3638 return NT_STATUS_OK;
3645 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3646 struct lsa_QuerySecret *r)
3648 struct dcesrv_handle *h;
3649 struct lsa_secret_state *secret_state;
3650 struct ldb_message *msg;
3651 DATA_BLOB session_key;
3652 DATA_BLOB crypt_secret, secret;
3654 struct ldb_message **res;
3655 const char *attrs[] = {
3665 DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3667 /* Ensure user is permitted to read this... */
3668 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3670 case SECURITY_SYSTEM:
3671 case SECURITY_ADMINISTRATOR:
3674 /* Users and annonymous are not allowed to read secrets */
3675 return NT_STATUS_ACCESS_DENIED;
3678 secret_state = h->data;
3680 /* pull all the user attributes */
3681 ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3682 secret_state->secret_dn, &res, attrs);
3684 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3688 nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3689 if (!NT_STATUS_IS_OK(nt_status)) {
3693 if (r->in.old_val) {
3694 const struct ldb_val *prior_val;
3695 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3696 if (!r->out.old_val) {
3697 return NT_STATUS_NO_MEMORY;
3699 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3701 if (prior_val && prior_val->length) {
3702 secret.data = prior_val->data;
3703 secret.length = prior_val->length;
3706 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3707 if (!crypt_secret.length) {
3708 return NT_STATUS_NO_MEMORY;
3710 r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3711 if (!r->out.old_val->buf) {
3712 return NT_STATUS_NO_MEMORY;
3714 r->out.old_val->buf->size = crypt_secret.length;
3715 r->out.old_val->buf->length = crypt_secret.length;
3716 r->out.old_val->buf->data = crypt_secret.data;
3720 if (r->in.old_mtime) {
3721 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3722 if (!r->out.old_mtime) {
3723 return NT_STATUS_NO_MEMORY;
3725 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3728 if (r->in.new_val) {
3729 const struct ldb_val *new_val;
3730 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3731 if (!r->out.new_val) {
3732 return NT_STATUS_NO_MEMORY;
3735 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3737 if (new_val && new_val->length) {
3738 secret.data = new_val->data;
3739 secret.length = new_val->length;
3742 crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3743 if (!crypt_secret.length) {
3744 return NT_STATUS_NO_MEMORY;
3746 r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3747 if (!r->out.new_val->buf) {
3748 return NT_STATUS_NO_MEMORY;
3750 r->out.new_val->buf->length = crypt_secret.length;
3751 r->out.new_val->buf->size = crypt_secret.length;
3752 r->out.new_val->buf->data = crypt_secret.data;
3756 if (r->in.new_mtime) {
3757 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3758 if (!r->out.new_mtime) {
3759 return NT_STATUS_NO_MEMORY;
3761 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3764 return NT_STATUS_OK;
3771 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3772 TALLOC_CTX *mem_ctx,
3773 struct lsa_LookupPrivValue *r)
3775 struct dcesrv_handle *h;
3778 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3780 id = sec_privilege_id(r->in.name->string);
3781 if (id == SEC_PRIV_INVALID) {
3782 return NT_STATUS_NO_SUCH_PRIVILEGE;
3785 r->out.luid->low = id;
3786 r->out.luid->high = 0;
3788 return NT_STATUS_OK;
3795 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3796 TALLOC_CTX *mem_ctx,
3797 struct lsa_LookupPrivName *r)
3799 struct dcesrv_handle *h;
3800 struct lsa_StringLarge *name;
3801 const char *privname;
3803 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3805 if (r->in.luid->high != 0) {
3806 return NT_STATUS_NO_SUCH_PRIVILEGE;
3809 privname = sec_privilege_name(r->in.luid->low);
3810 if (privname == NULL) {
3811 return NT_STATUS_NO_SUCH_PRIVILEGE;
3814 name = talloc(mem_ctx, struct lsa_StringLarge);
3816 return NT_STATUS_NO_MEMORY;
3819 name->string = privname;
3821 *r->out.name = name;
3823 return NT_STATUS_OK;
3828 lsa_LookupPrivDisplayName
3830 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3831 TALLOC_CTX *mem_ctx,
3832 struct lsa_LookupPrivDisplayName *r)
3834 struct dcesrv_handle *h;
3835 struct lsa_StringLarge *disp_name = NULL;
3836 enum sec_privilege id;
3838 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3840 id = sec_privilege_id(r->in.name->string);
3841 if (id == SEC_PRIV_INVALID) {
3842 return NT_STATUS_NO_SUCH_PRIVILEGE;
3845 disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3846 if (disp_name == NULL) {
3847 return NT_STATUS_NO_MEMORY;
3850 disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3851 if (disp_name->string == NULL) {
3852 return NT_STATUS_INTERNAL_ERROR;
3855 *r->out.disp_name = disp_name;
3856 *r->out.returned_language_id = 0;
3858 return NT_STATUS_OK;
3863 lsa_EnumAccountsWithUserRight
3865 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3866 TALLOC_CTX *mem_ctx,
3867 struct lsa_EnumAccountsWithUserRight *r)
3869 struct dcesrv_handle *h;
3870 struct lsa_policy_state *state;
3872 struct ldb_message **res;
3873 const char * const attrs[] = { "objectSid", NULL};
3874 const char *privname;
3877 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3881 if (r->in.name == NULL) {
3882 return NT_STATUS_NO_SUCH_PRIVILEGE;
3885 privname = r->in.name->string;
3887 ok = dcesrc_lsa_valid_AccountRight(privname);
3889 return NT_STATUS_NO_SUCH_PRIVILEGE;
3892 ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3893 "privilege=%s", privname);
3895 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3898 return NT_STATUS_NO_MORE_ENTRIES;
3901 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3902 if (r->out.sids->sids == NULL) {
3903 return NT_STATUS_NO_MEMORY;
3905 for (i=0;i<ret;i++) {
3906 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3907 res[i], "objectSid");
3908 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3910 r->out.sids->num_sids = ret;
3912 return NT_STATUS_OK;
3917 lsa_AddAccountRights
3919 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3920 TALLOC_CTX *mem_ctx,
3921 struct lsa_AddAccountRights *r)
3923 struct dcesrv_handle *h;
3924 struct lsa_policy_state *state;
3926 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3930 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3932 r->in.sid, r->in.rights);
3937 lsa_RemoveAccountRights
3939 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3940 TALLOC_CTX *mem_ctx,
3941 struct lsa_RemoveAccountRights *r)
3943 struct dcesrv_handle *h;
3944 struct lsa_policy_state *state;
3946 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3950 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3951 LDB_FLAG_MOD_DELETE,
3952 r->in.sid, r->in.rights);
3957 lsa_StorePrivateData
3959 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3960 struct lsa_StorePrivateData *r)
3962 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3967 lsa_RetrievePrivateData
3969 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3970 struct lsa_RetrievePrivateData *r)
3972 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3979 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3980 struct lsa_GetUserName *r)
3982 enum dcerpc_transport_t transport =
3983 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3984 NTSTATUS status = NT_STATUS_OK;
3985 const char *account_name;
3986 const char *authority_name;
3987 struct lsa_String *_account_name;
3988 struct lsa_String *_authority_name = NULL;
3990 if (transport != NCACN_NP && transport != NCALRPC) {
3991 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3994 /* this is what w2k3 does */
3995 r->out.account_name = r->in.account_name;
3996 r->out.authority_name = r->in.authority_name;
3998 if (r->in.account_name
3999 && *r->in.account_name
4000 /* && *(*r->in.account_name)->string */
4002 return NT_STATUS_INVALID_PARAMETER;
4005 if (r->in.authority_name
4006 && *r->in.authority_name
4007 /* && *(*r->in.authority_name)->string */
4009 return NT_STATUS_INVALID_PARAMETER;
4012 account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
4013 authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
4015 _account_name = talloc(mem_ctx, struct lsa_String);
4016 NT_STATUS_HAVE_NO_MEMORY(_account_name);
4017 _account_name->string = account_name;
4019 if (r->in.authority_name) {
4020 _authority_name = talloc(mem_ctx, struct lsa_String);
4021 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
4022 _authority_name->string = authority_name;
4025 *r->out.account_name = _account_name;
4026 if (r->out.authority_name) {
4027 *r->out.authority_name = _authority_name;
4036 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
4037 TALLOC_CTX *mem_ctx,
4038 struct lsa_SetInfoPolicy2 *r)
4040 /* need to support these */
4041 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4044 static void kdc_get_policy(TALLOC_CTX *mem_ctx,
4045 struct loadparm_context *lp_ctx,
4046 struct smb_krb5_context *smb_krb5_context,
4047 struct lsa_DomainInfoKerberos *k)
4049 time_t svc_tkt_lifetime;
4050 time_t usr_tkt_lifetime;
4051 time_t renewal_lifetime;
4053 /* Our KDC always re-validates the client */
4054 k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
4056 lpcfg_default_kdc_policy(mem_ctx, lp_ctx, &svc_tkt_lifetime,
4057 &usr_tkt_lifetime, &renewal_lifetime);
4059 unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
4060 unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
4061 unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
4062 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
4063 However in the parent function we basically just did a full
4064 krb5_context init with the only purpose of getting a global
4065 config option (the max skew), it would probably make more sense
4066 to have a lp_ or ldb global option as the samba default */
4067 if (smb_krb5_context) {
4068 unix_to_nt_time(&k->clock_skew,
4069 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
4075 lsa_QueryDomainInformationPolicy
4077 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4078 TALLOC_CTX *mem_ctx,
4079 struct lsa_QueryDomainInformationPolicy *r)
4081 union lsa_DomainInformationPolicy *info;
4083 info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
4085 return NT_STATUS_NO_MEMORY;
4088 switch (r->in.level) {
4089 case LSA_DOMAIN_INFO_POLICY_EFS:
4091 *r->out.info = NULL;
4092 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4093 case LSA_DOMAIN_INFO_POLICY_KERBEROS:
4095 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
4096 struct smb_krb5_context *smb_krb5_context;
4097 int ret = smb_krb5_init_context(mem_ctx,
4098 dce_call->conn->dce_ctx->lp_ctx,
4102 *r->out.info = NULL;
4103 return NT_STATUS_INTERNAL_ERROR;
4105 kdc_get_policy(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
4108 talloc_free(smb_krb5_context);
4109 *r->out.info = info;
4110 return NT_STATUS_OK;
4114 *r->out.info = NULL;
4115 return NT_STATUS_INVALID_INFO_CLASS;
4120 lsa_SetDomInfoPolicy
4122 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4123 TALLOC_CTX *mem_ctx,
4124 struct lsa_SetDomainInformationPolicy *r)
4126 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4132 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
4133 TALLOC_CTX *mem_ctx,
4134 struct lsa_TestCall *r)
4136 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4142 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4143 struct lsa_CREDRWRITE *r)
4145 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4152 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4153 struct lsa_CREDRREAD *r)
4155 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4162 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4163 struct lsa_CREDRENUMERATE *r)
4165 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4170 lsa_CREDRWRITEDOMAINCREDENTIALS
4172 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4173 struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
4175 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4180 lsa_CREDRREADDOMAINCREDENTIALS
4182 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4183 struct lsa_CREDRREADDOMAINCREDENTIALS *r)
4185 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4192 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4193 struct lsa_CREDRDELETE *r)
4195 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4200 lsa_CREDRGETTARGETINFO
4202 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4203 struct lsa_CREDRGETTARGETINFO *r)
4205 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4210 lsa_CREDRPROFILELOADED
4212 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4213 struct lsa_CREDRPROFILELOADED *r)
4215 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4220 lsa_CREDRGETSESSIONTYPES
4222 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4223 struct lsa_CREDRGETSESSIONTYPES *r)
4225 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4230 lsa_LSARREGISTERAUDITEVENT
4232 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4233 struct lsa_LSARREGISTERAUDITEVENT *r)
4235 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4240 lsa_LSARGENAUDITEVENT
4242 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4243 struct lsa_LSARGENAUDITEVENT *r)
4245 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4250 lsa_LSARUNREGISTERAUDITEVENT
4252 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4253 struct lsa_LSARUNREGISTERAUDITEVENT *r)
4255 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4260 lsa_lsaRQueryForestTrustInformation
4262 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4263 struct lsa_lsaRQueryForestTrustInformation *r)
4265 struct dcesrv_handle *h = NULL;
4266 struct lsa_policy_state *p_state = NULL;
4267 int forest_level = DS_DOMAIN_FUNCTION_2000;
4268 const char * const trust_attrs[] = {
4269 "securityIdentifier",
4275 "msDS-TrustForestTrustInfo",
4278 struct ldb_message *trust_tdo_msg = NULL;
4279 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4280 struct ForestTrustInfo *trust_fti = NULL;
4281 struct lsa_ForestTrustInformation *trust_lfti = NULL;
4284 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4288 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4289 return NT_STATUS_INVALID_DOMAIN_STATE;
4292 forest_level = dsdb_forest_functional_level(p_state->sam_ldb);
4293 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4294 return NT_STATUS_INVALID_DOMAIN_STATE;
4297 if (r->in.trusted_domain_name->string == NULL) {
4298 return NT_STATUS_NO_SUCH_DOMAIN;
4301 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4302 r->in.trusted_domain_name->string,
4303 r->in.trusted_domain_name->string,
4304 trust_attrs, mem_ctx, &trust_tdo_msg);
4305 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4306 return NT_STATUS_NO_SUCH_DOMAIN;
4308 if (!NT_STATUS_IS_OK(status)) {
4312 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4313 if (!NT_STATUS_IS_OK(status)) {
4317 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4318 return NT_STATUS_INVALID_PARAMETER;
4321 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4322 return NT_STATUS_INVALID_PARAMETER;
4325 status = dsdb_trust_parse_forest_info(mem_ctx,
4328 if (!NT_STATUS_IS_OK(status)) {
4332 status = dsdb_trust_forest_info_to_lsa(mem_ctx, trust_fti,
4334 if (!NT_STATUS_IS_OK(status)) {
4338 *r->out.forest_trust_info = trust_lfti;
4339 return NT_STATUS_OK;
4343 lsa_lsaRSetForestTrustInformation
4345 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4346 TALLOC_CTX *mem_ctx,
4347 struct lsa_lsaRSetForestTrustInformation *r)
4349 struct dcesrv_handle *h;
4350 struct lsa_policy_state *p_state;
4351 const char * const trust_attrs[] = {
4352 "securityIdentifier",
4358 "msDS-TrustForestTrustInfo",
4361 struct ldb_message *trust_tdo_msg = NULL;
4362 struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4363 struct lsa_ForestTrustInformation *step1_lfti = NULL;
4364 struct lsa_ForestTrustInformation *step2_lfti = NULL;
4365 struct ForestTrustInfo *trust_fti = NULL;
4366 struct ldb_result *trusts_res = NULL;
4368 struct lsa_TrustDomainInfoInfoEx *xref_tdo = NULL;
4369 struct lsa_ForestTrustInformation *xref_lfti = NULL;
4370 struct lsa_ForestTrustCollisionInfo *c_info = NULL;
4371 DATA_BLOB ft_blob = {};
4372 struct ldb_message *msg = NULL;
4374 enum ndr_err_code ndr_err;
4376 bool in_transaction = false;
4378 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4382 if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4383 return NT_STATUS_INVALID_DOMAIN_STATE;
4386 if (r->in.check_only == 0) {
4387 ret = ldb_transaction_start(p_state->sam_ldb);
4388 if (ret != LDB_SUCCESS) {
4389 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4391 in_transaction = true;
4395 * abort if we are not a PDC
4397 * In future we should use a function like IsEffectiveRoleOwner()
4399 if (!samdb_is_pdc(p_state->sam_ldb)) {
4400 status = NT_STATUS_INVALID_DOMAIN_ROLE;
4404 if (r->in.trusted_domain_name->string == NULL) {
4405 status = NT_STATUS_NO_SUCH_DOMAIN;
4409 status = dsdb_trust_search_tdo(p_state->sam_ldb,
4410 r->in.trusted_domain_name->string,
4411 r->in.trusted_domain_name->string,
4412 trust_attrs, mem_ctx, &trust_tdo_msg);
4413 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4414 status = NT_STATUS_NO_SUCH_DOMAIN;
4417 if (!NT_STATUS_IS_OK(status)) {
4421 status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4422 if (!NT_STATUS_IS_OK(status)) {
4426 if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4427 status = NT_STATUS_INVALID_PARAMETER;
4431 if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4432 status = NT_STATUS_INVALID_PARAMETER;
4437 * verify and normalize the given forest trust info.
4439 * Step1: doesn't reorder yet, so step1_lfti might contain
4440 * NULL entries. This means dsdb_trust_verify_forest_info()
4441 * can generate collision entries with the callers index.
4443 status = dsdb_trust_normalize_forest_info_step1(mem_ctx,
4444 r->in.forest_trust_info,
4446 if (!NT_STATUS_IS_OK(status)) {
4450 c_info = talloc_zero(r->out.collision_info,
4451 struct lsa_ForestTrustCollisionInfo);
4452 if (c_info == NULL) {
4453 status = NT_STATUS_NO_MEMORY;
4458 * First check our own forest, then other domains/forests
4461 status = dsdb_trust_xref_tdo_info(mem_ctx, p_state->sam_ldb,
4463 if (!NT_STATUS_IS_OK(status)) {
4466 status = dsdb_trust_xref_forest_info(mem_ctx, p_state->sam_ldb,
4468 if (!NT_STATUS_IS_OK(status)) {
4473 * The documentation proposed to generate
4474 * LSA_FOREST_TRUST_COLLISION_XREF collisions.
4475 * But Windows always uses LSA_FOREST_TRUST_COLLISION_TDO.
4477 status = dsdb_trust_verify_forest_info(xref_tdo, xref_lfti,
4478 LSA_FOREST_TRUST_COLLISION_TDO,
4479 c_info, step1_lfti);
4480 if (!NT_STATUS_IS_OK(status)) {
4484 /* fetch all other trusted domain objects */
4485 status = dsdb_trust_search_tdos(p_state->sam_ldb,
4486 trust_tdo->domain_name.string,
4488 mem_ctx, &trusts_res);
4489 if (!NT_STATUS_IS_OK(status)) {
4494 * now check against the other domains.
4495 * and generate LSA_FOREST_TRUST_COLLISION_TDO collisions.
4497 for (i = 0; i < trusts_res->count; i++) {
4498 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
4499 struct ForestTrustInfo *fti = NULL;
4500 struct lsa_ForestTrustInformation *lfti = NULL;
4502 status = dsdb_trust_parse_tdo_info(mem_ctx,
4503 trusts_res->msgs[i],
4505 if (!NT_STATUS_IS_OK(status)) {
4509 status = dsdb_trust_parse_forest_info(tdo,
4510 trusts_res->msgs[i],
4512 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
4515 if (!NT_STATUS_IS_OK(status)) {
4519 status = dsdb_trust_forest_info_to_lsa(tdo, fti, &lfti);
4520 if (!NT_STATUS_IS_OK(status)) {
4524 status = dsdb_trust_verify_forest_info(tdo, lfti,
4525 LSA_FOREST_TRUST_COLLISION_TDO,
4526 c_info, step1_lfti);
4527 if (!NT_STATUS_IS_OK(status)) {
4534 if (r->in.check_only != 0) {
4535 status = NT_STATUS_OK;
4540 * not just a check, write info back
4544 * normalize the given forest trust info.
4546 * Step2: adds TOP_LEVEL_NAME[_EX] in reverse order,
4547 * followed by DOMAIN_INFO in reverse order. It also removes
4548 * possible NULL entries from Step1.
4550 status = dsdb_trust_normalize_forest_info_step2(mem_ctx, step1_lfti,
4552 if (!NT_STATUS_IS_OK(status)) {
4556 status = dsdb_trust_forest_info_from_lsa(mem_ctx, step2_lfti,
4558 if (!NT_STATUS_IS_OK(status)) {
4562 ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, trust_fti,
4563 (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4564 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4565 status = NT_STATUS_INVALID_PARAMETER;
4569 msg = ldb_msg_new(mem_ctx);
4571 status = NT_STATUS_NO_MEMORY;
4575 msg->dn = ldb_dn_copy(mem_ctx, trust_tdo_msg->dn);
4577 status = NT_STATUS_NO_MEMORY;
4581 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4582 LDB_FLAG_MOD_REPLACE, NULL);
4583 if (ret != LDB_SUCCESS) {
4584 status = NT_STATUS_NO_MEMORY;
4587 ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4589 if (ret != LDB_SUCCESS) {
4590 status = NT_STATUS_NO_MEMORY;
4594 ret = ldb_modify(p_state->sam_ldb, msg);
4595 if (ret != LDB_SUCCESS) {
4596 status = dsdb_ldb_err_to_ntstatus(ret);
4598 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4599 ldb_errstring(p_state->sam_ldb)));
4604 /* ok, all fine, commit transaction and return */
4605 in_transaction = false;
4606 ret = ldb_transaction_commit(p_state->sam_ldb);
4607 if (ret != LDB_SUCCESS) {
4608 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4612 status = NT_STATUS_OK;
4615 if (NT_STATUS_IS_OK(status) && c_info->count != 0) {
4616 *r->out.collision_info = c_info;
4619 if (in_transaction) {
4620 ldb_transaction_cancel(p_state->sam_ldb);
4629 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4630 struct lsa_CREDRRENAME *r)
4632 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4638 lsa_LSAROPENPOLICYSCE
4640 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4641 struct lsa_LSAROPENPOLICYSCE *r)
4643 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4648 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4650 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4651 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4653 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4658 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4660 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4661 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4663 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4668 lsa_LSARADTREPORTSECURITYEVENT
4670 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4671 struct lsa_LSARADTREPORTSECURITYEVENT *r)
4673 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4677 /* include the generated boilerplate */
4678 #include "librpc/gen_ndr/ndr_lsa_s.c"
4682 /*****************************************
4683 NOTE! The remaining calls below were
4684 removed in w2k3, so the DCESRV_FAULT()
4685 replies are the correct implementation. Do
4686 not try and fill these in with anything else
4687 ******************************************/
4690 dssetup_DsRoleDnsNameToFlatName
4692 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4693 struct dssetup_DsRoleDnsNameToFlatName *r)
4695 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4700 dssetup_DsRoleDcAsDc
4702 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4703 struct dssetup_DsRoleDcAsDc *r)
4705 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4710 dssetup_DsRoleDcAsReplica
4712 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4713 struct dssetup_DsRoleDcAsReplica *r)
4715 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4720 dssetup_DsRoleDemoteDc
4722 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4723 struct dssetup_DsRoleDemoteDc *r)
4725 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4730 dssetup_DsRoleGetDcOperationProgress
4732 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4733 struct dssetup_DsRoleGetDcOperationProgress *r)
4735 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4740 dssetup_DsRoleGetDcOperationResults
4742 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4743 struct dssetup_DsRoleGetDcOperationResults *r)
4745 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4750 dssetup_DsRoleCancel
4752 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4753 struct dssetup_DsRoleCancel *r)
4755 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4760 dssetup_DsRoleServerSaveStateForUpgrade
4762 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4763 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4765 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4770 dssetup_DsRoleUpgradeDownlevelServer
4772 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4773 struct dssetup_DsRoleUpgradeDownlevelServer *r)
4775 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4780 dssetup_DsRoleAbortDownlevelServerUpgrade
4782 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4783 struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4785 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4789 /* include the generated boilerplate */
4790 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4792 NTSTATUS dcerpc_server_lsa_init(TALLOC_CTX *ctx)
4796 ret = dcerpc_server_dssetup_init(ctx);
4797 if (!NT_STATUS_IS_OK(ret)) {
4800 ret = dcerpc_server_lsarpc_init(ctx);
4801 if (!NT_STATUS_IS_OK(ret)) {