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"
38 this type allows us to distinguish handle types
42 state associated with a lsa_OpenAccount() operation
44 struct lsa_account_state
{
45 struct lsa_policy_state
*policy
;
47 struct dom_sid
*account_sid
;
52 state associated with a lsa_OpenSecret() operation
54 struct lsa_secret_state
{
55 struct lsa_policy_state
*policy
;
57 struct ldb_dn
*secret_dn
;
58 struct ldb_context
*sam_ldb
;
63 state associated with a lsa_OpenTrustedDomain() operation
65 struct lsa_trusted_domain_state
{
66 struct lsa_policy_state
*policy
;
68 struct ldb_dn
*trusted_domain_dn
;
69 struct ldb_dn
*trusted_domain_user_dn
;
73 this is based on the samba3 function make_lsa_object_sd()
74 It uses the same logic, but with samba4 helper functions
76 static NTSTATUS
dcesrv_build_lsa_sd(TALLOC_CTX
*mem_ctx
,
77 struct security_descriptor
**sd
,
83 struct dom_sid
*domain_sid
, *domain_admins_sid
;
84 const char *domain_admins_sid_str
, *sidstr
;
85 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
87 status
= dom_sid_split_rid(tmp_ctx
, sid
, &domain_sid
, &rid
);
88 if (!NT_STATUS_IS_OK(status
)) {
93 domain_admins_sid
= dom_sid_add_rid(tmp_ctx
, domain_sid
, DOMAIN_RID_ADMINS
);
94 if (domain_admins_sid
== NULL
) {
96 return NT_STATUS_NO_MEMORY
;
99 domain_admins_sid_str
= dom_sid_string(tmp_ctx
, domain_admins_sid
);
100 if (domain_admins_sid_str
== NULL
) {
101 TALLOC_FREE(tmp_ctx
);
102 return NT_STATUS_NO_MEMORY
;
105 sidstr
= dom_sid_string(tmp_ctx
, sid
);
106 if (sidstr
== NULL
) {
107 TALLOC_FREE(tmp_ctx
);
108 return NT_STATUS_NO_MEMORY
;
111 *sd
= security_descriptor_dacl_create(mem_ctx
,
115 SEC_ACE_TYPE_ACCESS_ALLOWED
,
116 SEC_GENERIC_EXECUTE
| SEC_GENERIC_READ
, 0,
118 SID_BUILTIN_ADMINISTRATORS
,
119 SEC_ACE_TYPE_ACCESS_ALLOWED
,
122 SID_BUILTIN_ACCOUNT_OPERATORS
,
123 SEC_ACE_TYPE_ACCESS_ALLOWED
,
126 domain_admins_sid_str
,
127 SEC_ACE_TYPE_ACCESS_ALLOWED
,
131 SEC_ACE_TYPE_ACCESS_ALLOWED
,
135 talloc_free(tmp_ctx
);
137 NT_STATUS_HAVE_NO_MEMORY(*sd
);
143 static NTSTATUS
dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state
*dce_call
,
145 struct lsa_EnumAccountRights
*r
);
147 static NTSTATUS
dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state
*dce_call
,
149 struct lsa_policy_state
*state
,
152 const struct lsa_RightSet
*rights
);
157 static NTSTATUS
dcesrv_lsa_Close(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
160 enum dcerpc_transport_t transport
=
161 dcerpc_binding_get_transport(dce_call
->conn
->endpoint
->ep_description
);
162 struct dcesrv_handle
*h
;
164 if (transport
!= NCACN_NP
&& transport
!= NCALRPC
) {
165 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED
);
168 *r
->out
.handle
= *r
->in
.handle
;
170 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, DCESRV_HANDLE_ANY
);
174 ZERO_STRUCTP(r
->out
.handle
);
183 static NTSTATUS
dcesrv_lsa_Delete(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
184 struct lsa_Delete
*r
)
186 return NT_STATUS_NOT_SUPPORTED
;
193 static NTSTATUS
dcesrv_lsa_DeleteObject(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
194 struct lsa_DeleteObject
*r
)
196 struct dcesrv_handle
*h
;
199 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, DCESRV_HANDLE_ANY
);
201 if (h
->wire_handle
.handle_type
== LSA_HANDLE_SECRET
) {
202 struct lsa_secret_state
*secret_state
= h
->data
;
204 /* Ensure user is permitted to delete this... */
205 switch (security_session_user_level(dce_call
->conn
->auth_state
.session_info
, NULL
))
207 case SECURITY_SYSTEM
:
208 case SECURITY_ADMINISTRATOR
:
211 /* Users and anonymous are not allowed to delete things */
212 return NT_STATUS_ACCESS_DENIED
;
215 ret
= ldb_delete(secret_state
->sam_ldb
,
216 secret_state
->secret_dn
);
217 if (ret
!= LDB_SUCCESS
) {
218 return NT_STATUS_INVALID_HANDLE
;
221 ZERO_STRUCTP(r
->out
.handle
);
225 } else if (h
->wire_handle
.handle_type
== LSA_HANDLE_TRUSTED_DOMAIN
) {
226 struct lsa_trusted_domain_state
*trusted_domain_state
=
227 talloc_get_type(h
->data
, struct lsa_trusted_domain_state
);
228 ret
= ldb_transaction_start(trusted_domain_state
->policy
->sam_ldb
);
229 if (ret
!= LDB_SUCCESS
) {
230 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
233 ret
= ldb_delete(trusted_domain_state
->policy
->sam_ldb
,
234 trusted_domain_state
->trusted_domain_dn
);
235 if (ret
!= LDB_SUCCESS
) {
236 ldb_transaction_cancel(trusted_domain_state
->policy
->sam_ldb
);
237 return NT_STATUS_INVALID_HANDLE
;
240 if (trusted_domain_state
->trusted_domain_user_dn
) {
241 ret
= ldb_delete(trusted_domain_state
->policy
->sam_ldb
,
242 trusted_domain_state
->trusted_domain_user_dn
);
243 if (ret
!= LDB_SUCCESS
) {
244 ldb_transaction_cancel(trusted_domain_state
->policy
->sam_ldb
);
245 return NT_STATUS_INVALID_HANDLE
;
249 ret
= ldb_transaction_commit(trusted_domain_state
->policy
->sam_ldb
);
250 if (ret
!= LDB_SUCCESS
) {
251 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
254 ZERO_STRUCTP(r
->out
.handle
);
258 } else if (h
->wire_handle
.handle_type
== LSA_HANDLE_ACCOUNT
) {
259 struct lsa_RightSet
*rights
;
260 struct lsa_account_state
*astate
;
261 struct lsa_EnumAccountRights r2
;
264 rights
= talloc(mem_ctx
, struct lsa_RightSet
);
266 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_ACCOUNT
);
270 r2
.in
.handle
= &astate
->policy
->handle
->wire_handle
;
271 r2
.in
.sid
= astate
->account_sid
;
272 r2
.out
.rights
= rights
;
274 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
275 but we have a LSA_HANDLE_ACCOUNT here, so this call
277 status
= dcesrv_lsa_EnumAccountRights(dce_call
, mem_ctx
, &r2
);
278 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
282 if (!NT_STATUS_IS_OK(status
)) {
286 status
= dcesrv_lsa_AddRemoveAccountRights(dce_call
, mem_ctx
, astate
->policy
,
287 LDB_FLAG_MOD_DELETE
, astate
->account_sid
,
289 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
293 if (!NT_STATUS_IS_OK(status
)) {
297 ZERO_STRUCTP(r
->out
.handle
);
302 return NT_STATUS_INVALID_HANDLE
;
309 static NTSTATUS
dcesrv_lsa_EnumPrivs(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
310 struct lsa_EnumPrivs
*r
)
312 struct dcesrv_handle
*h
;
314 enum sec_privilege priv
;
315 const char *privname
;
317 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
319 i
= *r
->in
.resume_handle
;
321 while (((priv
= sec_privilege_from_index(i
)) != SEC_PRIV_INVALID
) &&
322 r
->out
.privs
->count
< r
->in
.max_count
) {
323 struct lsa_PrivEntry
*e
;
324 privname
= sec_privilege_name(priv
);
325 r
->out
.privs
->privs
= talloc_realloc(r
->out
.privs
,
327 struct lsa_PrivEntry
,
328 r
->out
.privs
->count
+1);
329 if (r
->out
.privs
->privs
== NULL
) {
330 return NT_STATUS_NO_MEMORY
;
332 e
= &r
->out
.privs
->privs
[r
->out
.privs
->count
];
335 e
->name
.string
= privname
;
336 r
->out
.privs
->count
++;
340 *r
->out
.resume_handle
= i
;
349 static NTSTATUS
dcesrv_lsa_QuerySecurity(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
350 struct lsa_QuerySecurity
*r
)
352 struct dcesrv_handle
*h
;
353 const struct security_descriptor
*sd
= NULL
;
354 uint32_t access_granted
= 0;
355 struct sec_desc_buf
*sdbuf
= NULL
;
359 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, DCESRV_HANDLE_ANY
);
361 sid
= &dce_call
->conn
->auth_state
.session_info
->security_token
->sids
[PRIMARY_USER_SID_INDEX
];
363 if (h
->wire_handle
.handle_type
== LSA_HANDLE_POLICY
) {
364 struct lsa_policy_state
*pstate
= h
->data
;
367 access_granted
= pstate
->access_mask
;
369 } else if (h
->wire_handle
.handle_type
== LSA_HANDLE_ACCOUNT
) {
370 struct lsa_account_state
*astate
= h
->data
;
371 struct security_descriptor
*_sd
= NULL
;
373 status
= dcesrv_build_lsa_sd(mem_ctx
, &_sd
, sid
,
374 LSA_ACCOUNT_ALL_ACCESS
);
375 if (!NT_STATUS_IS_OK(status
)) {
379 access_granted
= astate
->access_mask
;
381 return NT_STATUS_INVALID_HANDLE
;
384 sdbuf
= talloc_zero(mem_ctx
, struct sec_desc_buf
);
386 return NT_STATUS_NO_MEMORY
;
389 status
= security_descriptor_for_client(sdbuf
, sd
, r
->in
.sec_info
,
390 access_granted
, &sdbuf
->sd
);
391 if (!NT_STATUS_IS_OK(status
)) {
395 *r
->out
.sdbuf
= sdbuf
;
404 static NTSTATUS
dcesrv_lsa_SetSecObj(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
405 struct lsa_SetSecObj
*r
)
407 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
414 static NTSTATUS
dcesrv_lsa_ChangePassword(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
415 struct lsa_ChangePassword
*r
)
417 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
421 dssetup_DsRoleGetPrimaryDomainInformation
423 This is not an LSA call, but is the only call left on the DSSETUP
424 pipe (after the pipe was truncated), and needs lsa_get_policy_state
426 static WERROR
dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state
*dce_call
,
428 struct dssetup_DsRoleGetPrimaryDomainInformation
*r
)
430 union dssetup_DsRoleInfo
*info
;
432 info
= talloc_zero(mem_ctx
, union dssetup_DsRoleInfo
);
433 W_ERROR_HAVE_NO_MEMORY(info
);
435 switch (r
->in
.level
) {
436 case DS_ROLE_BASIC_INFORMATION
:
438 enum dssetup_DsRole role
= DS_ROLE_STANDALONE_SERVER
;
440 const char *domain
= NULL
;
441 const char *dns_domain
= NULL
;
442 const char *forest
= NULL
;
443 struct GUID domain_guid
;
444 struct lsa_policy_state
*state
;
446 NTSTATUS status
= dcesrv_lsa_get_policy_state(dce_call
, mem_ctx
,
447 0, /* we skip access checks */
449 if (!NT_STATUS_IS_OK(status
)) {
450 return ntstatus_to_werror(status
);
453 ZERO_STRUCT(domain_guid
);
455 switch (lpcfg_server_role(dce_call
->conn
->dce_ctx
->lp_ctx
)) {
456 case ROLE_STANDALONE
:
457 role
= DS_ROLE_STANDALONE_SERVER
;
459 case ROLE_DOMAIN_MEMBER
:
460 role
= DS_ROLE_MEMBER_SERVER
;
462 case ROLE_ACTIVE_DIRECTORY_DC
:
463 if (samdb_is_pdc(state
->sam_ldb
)) {
464 role
= DS_ROLE_PRIMARY_DC
;
466 role
= DS_ROLE_BACKUP_DC
;
471 switch (lpcfg_server_role(dce_call
->conn
->dce_ctx
->lp_ctx
)) {
472 case ROLE_STANDALONE
:
473 domain
= talloc_strdup(mem_ctx
, lpcfg_workgroup(dce_call
->conn
->dce_ctx
->lp_ctx
));
474 W_ERROR_HAVE_NO_MEMORY(domain
);
476 case ROLE_DOMAIN_MEMBER
:
477 domain
= talloc_strdup(mem_ctx
, lpcfg_workgroup(dce_call
->conn
->dce_ctx
->lp_ctx
));
478 W_ERROR_HAVE_NO_MEMORY(domain
);
479 /* TODO: what is with dns_domain and forest and guid? */
481 case ROLE_ACTIVE_DIRECTORY_DC
:
482 flags
= DS_ROLE_PRIMARY_DS_RUNNING
;
484 if (state
->mixed_domain
== 1) {
485 flags
|= DS_ROLE_PRIMARY_DS_MIXED_MODE
;
488 domain
= state
->domain_name
;
489 dns_domain
= state
->domain_dns
;
490 forest
= state
->forest_dns
;
492 domain_guid
= state
->domain_guid
;
493 flags
|= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT
;
497 info
->basic
.role
= role
;
498 info
->basic
.flags
= flags
;
499 info
->basic
.domain
= domain
;
500 info
->basic
.dns_domain
= dns_domain
;
501 info
->basic
.forest
= forest
;
502 info
->basic
.domain_guid
= domain_guid
;
507 case DS_ROLE_UPGRADE_STATUS
:
509 info
->upgrade
.upgrading
= DS_ROLE_NOT_UPGRADING
;
510 info
->upgrade
.previous_role
= DS_ROLE_PREVIOUS_UNKNOWN
;
515 case DS_ROLE_OP_STATUS
:
517 info
->opstatus
.status
= DS_ROLE_OP_IDLE
;
523 return WERR_INVALID_PARAM
;
528 fill in the AccountDomain info
530 static NTSTATUS
dcesrv_lsa_info_AccountDomain(struct lsa_policy_state
*state
, TALLOC_CTX
*mem_ctx
,
531 struct lsa_DomainInfo
*info
)
533 info
->name
.string
= state
->domain_name
;
534 info
->sid
= state
->domain_sid
;
540 fill in the DNS domain info
542 static NTSTATUS
dcesrv_lsa_info_DNS(struct lsa_policy_state
*state
, TALLOC_CTX
*mem_ctx
,
543 struct lsa_DnsDomainInfo
*info
)
545 info
->name
.string
= state
->domain_name
;
546 info
->sid
= state
->domain_sid
;
547 info
->dns_domain
.string
= state
->domain_dns
;
548 info
->dns_forest
.string
= state
->forest_dns
;
549 info
->domain_guid
= state
->domain_guid
;
557 static NTSTATUS
dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
558 struct lsa_QueryInfoPolicy2
*r
)
560 struct lsa_policy_state
*state
;
561 struct dcesrv_handle
*h
;
562 union lsa_PolicyInformation
*info
;
566 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
570 info
= talloc_zero(mem_ctx
, union lsa_PolicyInformation
);
572 return NT_STATUS_NO_MEMORY
;
576 switch (r
->in
.level
) {
577 case LSA_POLICY_INFO_AUDIT_LOG
:
578 /* we don't need to fill in any of this */
579 ZERO_STRUCT(info
->audit_log
);
581 case LSA_POLICY_INFO_AUDIT_EVENTS
:
582 /* we don't need to fill in any of this */
583 ZERO_STRUCT(info
->audit_events
);
585 case LSA_POLICY_INFO_PD
:
586 /* we don't need to fill in any of this */
587 ZERO_STRUCT(info
->pd
);
590 case LSA_POLICY_INFO_DOMAIN
:
591 return dcesrv_lsa_info_AccountDomain(state
, mem_ctx
, &info
->domain
);
592 case LSA_POLICY_INFO_ACCOUNT_DOMAIN
:
593 return dcesrv_lsa_info_AccountDomain(state
, mem_ctx
, &info
->account_domain
);
594 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN
:
595 return dcesrv_lsa_info_AccountDomain(state
, mem_ctx
, &info
->l_account_domain
);
597 case LSA_POLICY_INFO_ROLE
:
598 info
->role
.role
= LSA_ROLE_PRIMARY
;
601 case LSA_POLICY_INFO_DNS
:
602 case LSA_POLICY_INFO_DNS_INT
:
603 return dcesrv_lsa_info_DNS(state
, mem_ctx
, &info
->dns
);
605 case LSA_POLICY_INFO_REPLICA
:
606 ZERO_STRUCT(info
->replica
);
609 case LSA_POLICY_INFO_QUOTA
:
610 ZERO_STRUCT(info
->quota
);
613 case LSA_POLICY_INFO_MOD
:
614 case LSA_POLICY_INFO_AUDIT_FULL_SET
:
615 case LSA_POLICY_INFO_AUDIT_FULL_QUERY
:
616 /* windows gives INVALID_PARAMETER */
618 return NT_STATUS_INVALID_PARAMETER
;
622 return NT_STATUS_INVALID_INFO_CLASS
;
628 static NTSTATUS
dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
629 struct lsa_QueryInfoPolicy
*r
)
631 struct lsa_QueryInfoPolicy2 r2
;
636 r2
.in
.handle
= r
->in
.handle
;
637 r2
.in
.level
= r
->in
.level
;
638 r2
.out
.info
= r
->out
.info
;
640 status
= dcesrv_lsa_QueryInfoPolicy2(dce_call
, mem_ctx
, &r2
);
648 static NTSTATUS
dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
649 struct lsa_SetInfoPolicy
*r
)
651 /* need to support this */
652 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
659 static NTSTATUS
dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
660 struct lsa_ClearAuditLog
*r
)
662 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
666 static const struct generic_mapping dcesrv_lsa_account_mapping
= {
670 LSA_ACCOUNT_ALL_ACCESS
676 This call does not seem to have any long-term effects, hence no database operations
678 we need to talk to the MS product group to find out what this account database means!
680 answer is that the lsa database is totally separate from the SAM and
681 ldap databases. We are going to need a separate ldb to store these
682 accounts. The SIDs on this account bear no relation to the SIDs in
685 static NTSTATUS
dcesrv_lsa_CreateAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
686 struct lsa_CreateAccount
*r
)
688 struct lsa_account_state
*astate
;
690 struct lsa_policy_state
*state
;
691 struct dcesrv_handle
*h
, *ah
;
693 ZERO_STRUCTP(r
->out
.acct_handle
);
695 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
699 astate
= talloc(dce_call
->conn
, struct lsa_account_state
);
700 if (astate
== NULL
) {
701 return NT_STATUS_NO_MEMORY
;
704 astate
->account_sid
= dom_sid_dup(astate
, r
->in
.sid
);
705 if (astate
->account_sid
== NULL
) {
707 return NT_STATUS_NO_MEMORY
;
710 astate
->policy
= talloc_reference(astate
, state
);
711 astate
->access_mask
= r
->in
.access_mask
;
714 * For now we grant all requested access.
716 * We will fail at the ldb layer later.
718 if (astate
->access_mask
& SEC_FLAG_MAXIMUM_ALLOWED
) {
719 astate
->access_mask
&= ~SEC_FLAG_MAXIMUM_ALLOWED
;
720 astate
->access_mask
|= LSA_ACCOUNT_ALL_ACCESS
;
722 se_map_generic(&astate
->access_mask
, &dcesrv_lsa_account_mapping
);
724 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X].\n",
725 __func__
, dom_sid_string(mem_ctx
, astate
->account_sid
),
726 (unsigned)r
->in
.access_mask
,
727 (unsigned)astate
->access_mask
));
729 ah
= dcesrv_handle_new(dce_call
->context
, LSA_HANDLE_ACCOUNT
);
732 return NT_STATUS_NO_MEMORY
;
735 ah
->data
= talloc_steal(ah
, astate
);
737 *r
->out
.acct_handle
= ah
->wire_handle
;
746 static NTSTATUS
dcesrv_lsa_EnumAccounts(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
747 struct lsa_EnumAccounts
*r
)
749 struct dcesrv_handle
*h
;
750 struct lsa_policy_state
*state
;
752 struct ldb_message
**res
;
753 const char * const attrs
[] = { "objectSid", NULL
};
756 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
760 /* NOTE: This call must only return accounts that have at least
763 ret
= gendb_search(state
->pdb
, mem_ctx
, NULL
, &res
, attrs
,
764 "(&(objectSid=*)(privilege=*))");
766 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
769 if (*r
->in
.resume_handle
>= ret
) {
770 return NT_STATUS_NO_MORE_ENTRIES
;
773 count
= ret
- *r
->in
.resume_handle
;
774 if (count
> r
->in
.num_entries
) {
775 count
= r
->in
.num_entries
;
779 return NT_STATUS_NO_MORE_ENTRIES
;
782 r
->out
.sids
->sids
= talloc_array(r
->out
.sids
, struct lsa_SidPtr
, count
);
783 if (r
->out
.sids
->sids
== NULL
) {
784 return NT_STATUS_NO_MEMORY
;
787 for (i
=0;i
<count
;i
++) {
788 r
->out
.sids
->sids
[i
].sid
=
789 samdb_result_dom_sid(r
->out
.sids
->sids
,
790 res
[i
+ *r
->in
.resume_handle
],
792 NT_STATUS_HAVE_NO_MEMORY(r
->out
.sids
->sids
[i
].sid
);
795 r
->out
.sids
->num_sids
= count
;
796 *r
->out
.resume_handle
= count
+ *r
->in
.resume_handle
;
801 /* This decrypts and returns Trusted Domain Auth Information Internal data */
802 static NTSTATUS
get_trustdom_auth_blob(struct dcesrv_call_state
*dce_call
,
803 TALLOC_CTX
*mem_ctx
, DATA_BLOB
*auth_blob
,
804 struct trustDomainPasswords
*auth_struct
)
806 DATA_BLOB session_key
= data_blob(NULL
, 0);
807 enum ndr_err_code ndr_err
;
810 nt_status
= dcesrv_fetch_session_key(dce_call
->conn
, &session_key
);
811 if (!NT_STATUS_IS_OK(nt_status
)) {
815 arcfour_crypt_blob(auth_blob
->data
, auth_blob
->length
, &session_key
);
816 ndr_err
= ndr_pull_struct_blob(auth_blob
, mem_ctx
,
818 (ndr_pull_flags_fn_t
)ndr_pull_trustDomainPasswords
);
819 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
820 return NT_STATUS_INVALID_PARAMETER
;
826 static NTSTATUS
get_trustauth_inout_blob(struct dcesrv_call_state
*dce_call
,
828 struct trustAuthInOutBlob
*iopw
,
829 DATA_BLOB
*trustauth_blob
)
831 enum ndr_err_code ndr_err
;
833 if (iopw
->current
.count
!= iopw
->count
) {
834 return NT_STATUS_INVALID_PARAMETER
;
837 if (iopw
->previous
.count
> iopw
->current
.count
) {
838 return NT_STATUS_INVALID_PARAMETER
;
841 if (iopw
->previous
.count
== 0) {
843 * If the previous credentials are not present
844 * we need to make a copy.
846 iopw
->previous
= iopw
->current
;
849 if (iopw
->previous
.count
< iopw
->current
.count
) {
850 struct AuthenticationInformationArray
*c
= &iopw
->current
;
851 struct AuthenticationInformationArray
*p
= &iopw
->previous
;
854 * The previous array needs to have the same size
855 * as the current one.
857 * We may have to fill with TRUST_AUTH_TYPE_NONE
860 p
->array
= talloc_realloc(mem_ctx
, p
->array
,
861 struct AuthenticationInformation
,
863 if (p
->array
== NULL
) {
864 return NT_STATUS_NO_MEMORY
;
867 while (p
->count
< c
->count
) {
868 struct AuthenticationInformation
*a
=
869 &p
->array
[p
->count
++];
871 *a
= (struct AuthenticationInformation
) {
872 .LastUpdateTime
= p
->array
[0].LastUpdateTime
,
873 .AuthType
= TRUST_AUTH_TYPE_NONE
,
878 ndr_err
= ndr_push_struct_blob(trustauth_blob
, mem_ctx
,
880 (ndr_push_flags_fn_t
)ndr_push_trustAuthInOutBlob
);
881 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
882 return NT_STATUS_INVALID_PARAMETER
;
888 static NTSTATUS
add_trust_user(TALLOC_CTX
*mem_ctx
,
889 struct ldb_context
*sam_ldb
,
890 struct ldb_dn
*base_dn
,
891 const char *netbios_name
,
892 struct trustAuthInOutBlob
*in
,
893 struct ldb_dn
**user_dn
)
895 struct ldb_request
*req
;
896 struct ldb_message
*msg
;
901 dn
= ldb_dn_copy(mem_ctx
, base_dn
);
903 return NT_STATUS_NO_MEMORY
;
905 if (!ldb_dn_add_child_fmt(dn
, "cn=%s$,cn=users", netbios_name
)) {
906 return NT_STATUS_NO_MEMORY
;
909 msg
= ldb_msg_new(mem_ctx
);
911 return NT_STATUS_NO_MEMORY
;
915 ret
= ldb_msg_add_string(msg
, "objectClass", "user");
916 if (ret
!= LDB_SUCCESS
) {
917 return NT_STATUS_NO_MEMORY
;
920 ret
= ldb_msg_add_fmt(msg
, "samAccountName", "%s$", netbios_name
);
921 if (ret
!= LDB_SUCCESS
) {
922 return NT_STATUS_NO_MEMORY
;
925 ret
= samdb_msg_add_uint(sam_ldb
, msg
, msg
, "userAccountControl",
926 UF_INTERDOMAIN_TRUST_ACCOUNT
);
927 if (ret
!= LDB_SUCCESS
) {
928 return NT_STATUS_NO_MEMORY
;
931 for (i
= 0; i
< in
->count
; i
++) {
932 const char *attribute
;
934 switch (in
->current
.array
[i
].AuthType
) {
935 case TRUST_AUTH_TYPE_NT4OWF
:
936 attribute
= "unicodePwd";
937 v
.data
= (uint8_t *)&in
->current
.array
[i
].AuthInfo
.nt4owf
.password
;
940 case TRUST_AUTH_TYPE_CLEAR
:
941 attribute
= "clearTextPassword";
942 v
.data
= in
->current
.array
[i
].AuthInfo
.clear
.password
;
943 v
.length
= in
->current
.array
[i
].AuthInfo
.clear
.size
;
949 ret
= ldb_msg_add_value(msg
, attribute
, &v
, NULL
);
950 if (ret
!= LDB_SUCCESS
) {
951 return NT_STATUS_NO_MEMORY
;
955 /* create the trusted_domain user account */
956 ret
= ldb_build_add_req(&req
, sam_ldb
, mem_ctx
, msg
, NULL
, NULL
,
957 ldb_op_default_callback
, NULL
);
958 if (ret
!= LDB_SUCCESS
) {
959 return NT_STATUS_NO_MEMORY
;
962 ret
= ldb_request_add_control(req
, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID
,
964 if (ret
!= LDB_SUCCESS
) {
965 return NT_STATUS_NO_MEMORY
;
968 ret
= dsdb_autotransaction_request(sam_ldb
, req
);
969 if (ret
!= LDB_SUCCESS
) {
970 DEBUG(0,("Failed to create user record %s: %s\n",
971 ldb_dn_get_linearized(msg
->dn
),
972 ldb_errstring(sam_ldb
)));
975 case LDB_ERR_ENTRY_ALREADY_EXISTS
:
976 return NT_STATUS_DOMAIN_EXISTS
;
977 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
:
978 return NT_STATUS_ACCESS_DENIED
;
980 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
991 lsa_CreateTrustedDomainEx2
993 static NTSTATUS
dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state
*dce_call
,
995 struct lsa_CreateTrustedDomainEx2
*r
,
997 struct lsa_TrustDomainInfoAuthInfo
*unencrypted_auth_info
)
999 struct dcesrv_handle
*policy_handle
;
1000 struct lsa_policy_state
*policy_state
;
1001 struct lsa_trusted_domain_state
*trusted_domain_state
;
1002 struct dcesrv_handle
*handle
;
1003 struct ldb_message
**msgs
, *msg
;
1004 const char *attrs
[] = {
1007 const char *netbios_name
;
1008 const char *dns_name
;
1010 DATA_BLOB trustAuthIncoming
, trustAuthOutgoing
, auth_blob
;
1011 struct trustDomainPasswords auth_struct
;
1014 struct ldb_context
*sam_ldb
;
1015 struct server_id
*server_ids
= NULL
;
1016 uint32_t num_server_ids
= 0;
1019 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.policy_handle
, LSA_HANDLE_POLICY
);
1020 ZERO_STRUCTP(r
->out
.trustdom_handle
);
1022 policy_state
= policy_handle
->data
;
1023 sam_ldb
= policy_state
->sam_ldb
;
1025 netbios_name
= r
->in
.info
->netbios_name
.string
;
1026 if (!netbios_name
) {
1027 return NT_STATUS_INVALID_PARAMETER
;
1030 dns_name
= r
->in
.info
->domain_name
.string
;
1032 trusted_domain_state
= talloc_zero(mem_ctx
, struct lsa_trusted_domain_state
);
1033 if (!trusted_domain_state
) {
1034 return NT_STATUS_NO_MEMORY
;
1036 trusted_domain_state
->policy
= policy_state
;
1038 if (strcasecmp(netbios_name
, "BUILTIN") == 0
1039 || (dns_name
&& strcasecmp(dns_name
, "BUILTIN") == 0)
1040 || (dom_sid_in_domain(policy_state
->builtin_sid
, r
->in
.info
->sid
))) {
1041 return NT_STATUS_INVALID_PARAMETER
;
1044 if (strcasecmp(netbios_name
, policy_state
->domain_name
) == 0
1045 || strcasecmp(netbios_name
, policy_state
->domain_dns
) == 0
1046 || (dns_name
&& strcasecmp(dns_name
, policy_state
->domain_dns
) == 0)
1047 || (dns_name
&& strcasecmp(dns_name
, policy_state
->domain_name
) == 0)
1048 || (dom_sid_equal(policy_state
->domain_sid
, r
->in
.info
->sid
))) {
1049 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED
;
1052 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
1053 if (op
== NDR_LSA_CREATETRUSTEDDOMAIN
) {
1054 /* No secrets are created at this time, for this function */
1055 auth_struct
.outgoing
.count
= 0;
1056 auth_struct
.incoming
.count
= 0;
1057 } else if (op
== NDR_LSA_CREATETRUSTEDDOMAINEX2
) {
1058 auth_blob
= data_blob_const(r
->in
.auth_info_internal
->auth_blob
.data
,
1059 r
->in
.auth_info_internal
->auth_blob
.size
);
1060 nt_status
= get_trustdom_auth_blob(dce_call
, mem_ctx
,
1061 &auth_blob
, &auth_struct
);
1062 if (!NT_STATUS_IS_OK(nt_status
)) {
1065 } else if (op
== NDR_LSA_CREATETRUSTEDDOMAINEX
) {
1067 if (unencrypted_auth_info
->incoming_count
> 1) {
1068 return NT_STATUS_INVALID_PARAMETER
;
1071 /* more investigation required here, do not create secrets for
1073 auth_struct
.outgoing
.count
= 0;
1074 auth_struct
.incoming
.count
= 0;
1076 return NT_STATUS_INVALID_PARAMETER
;
1079 if (auth_struct
.incoming
.count
) {
1080 nt_status
= get_trustauth_inout_blob(dce_call
, mem_ctx
,
1081 &auth_struct
.incoming
,
1082 &trustAuthIncoming
);
1083 if (!NT_STATUS_IS_OK(nt_status
)) {
1087 trustAuthIncoming
= data_blob(NULL
, 0);
1090 if (auth_struct
.outgoing
.count
) {
1091 nt_status
= get_trustauth_inout_blob(dce_call
, mem_ctx
,
1092 &auth_struct
.outgoing
,
1093 &trustAuthOutgoing
);
1094 if (!NT_STATUS_IS_OK(nt_status
)) {
1098 trustAuthOutgoing
= data_blob(NULL
, 0);
1101 ret
= ldb_transaction_start(sam_ldb
);
1102 if (ret
!= LDB_SUCCESS
) {
1103 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1107 char *dns_encoded
= ldb_binary_encode_string(mem_ctx
, dns_name
);
1108 char *netbios_encoded
= ldb_binary_encode_string(mem_ctx
, netbios_name
);
1109 /* search for the trusted_domain record */
1110 ret
= gendb_search(sam_ldb
,
1111 mem_ctx
, policy_state
->system_dn
, &msgs
, attrs
,
1112 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1113 dns_encoded
, dns_encoded
, dns_encoded
, netbios_encoded
, netbios_encoded
, netbios_encoded
);
1115 ldb_transaction_cancel(sam_ldb
);
1116 return NT_STATUS_OBJECT_NAME_COLLISION
;
1119 char *netbios_encoded
= ldb_binary_encode_string(mem_ctx
, netbios_name
);
1120 /* search for the trusted_domain record */
1121 ret
= gendb_search(sam_ldb
,
1122 mem_ctx
, policy_state
->system_dn
, &msgs
, attrs
,
1123 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1124 netbios_encoded
, netbios_encoded
, netbios_encoded
);
1126 ldb_transaction_cancel(sam_ldb
);
1127 return NT_STATUS_OBJECT_NAME_COLLISION
;
1132 ldb_transaction_cancel(sam_ldb
);
1133 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1136 name
= dns_name
? dns_name
: netbios_name
;
1138 msg
= ldb_msg_new(mem_ctx
);
1140 return NT_STATUS_NO_MEMORY
;
1143 msg
->dn
= ldb_dn_copy(mem_ctx
, policy_state
->system_dn
);
1144 if ( ! ldb_dn_add_child_fmt(msg
->dn
, "cn=%s", name
)) {
1145 ldb_transaction_cancel(sam_ldb
);
1146 return NT_STATUS_NO_MEMORY
;
1149 ldb_msg_add_string(msg
, "flatname", netbios_name
);
1151 if (r
->in
.info
->sid
) {
1152 ret
= samdb_msg_add_dom_sid(sam_ldb
, mem_ctx
, msg
, "securityIdentifier", r
->in
.info
->sid
);
1153 if (ret
!= LDB_SUCCESS
) {
1154 ldb_transaction_cancel(sam_ldb
);
1155 return NT_STATUS_INVALID_PARAMETER
;
1159 ldb_msg_add_string(msg
, "objectClass", "trustedDomain");
1161 samdb_msg_add_int(sam_ldb
, mem_ctx
, msg
, "trustType", r
->in
.info
->trust_type
);
1163 samdb_msg_add_int(sam_ldb
, mem_ctx
, msg
, "trustAttributes", r
->in
.info
->trust_attributes
);
1165 samdb_msg_add_int(sam_ldb
, mem_ctx
, msg
, "trustDirection", r
->in
.info
->trust_direction
);
1168 ldb_msg_add_string(msg
, "trustPartner", dns_name
);
1171 if (trustAuthIncoming
.data
) {
1172 ret
= ldb_msg_add_value(msg
, "trustAuthIncoming", &trustAuthIncoming
, NULL
);
1173 if (ret
!= LDB_SUCCESS
) {
1174 ldb_transaction_cancel(sam_ldb
);
1175 return NT_STATUS_NO_MEMORY
;
1178 if (trustAuthOutgoing
.data
) {
1179 ret
= ldb_msg_add_value(msg
, "trustAuthOutgoing", &trustAuthOutgoing
, NULL
);
1180 if (ret
!= LDB_SUCCESS
) {
1181 ldb_transaction_cancel(sam_ldb
);
1182 return NT_STATUS_NO_MEMORY
;
1186 trusted_domain_state
->trusted_domain_dn
= talloc_reference(trusted_domain_state
, msg
->dn
);
1188 /* create the trusted_domain */
1189 ret
= ldb_add(sam_ldb
, msg
);
1193 case LDB_ERR_ENTRY_ALREADY_EXISTS
:
1194 ldb_transaction_cancel(sam_ldb
);
1195 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1196 ldb_dn_get_linearized(msg
->dn
),
1197 ldb_errstring(sam_ldb
)));
1198 return NT_STATUS_DOMAIN_EXISTS
;
1199 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
:
1200 ldb_transaction_cancel(sam_ldb
);
1201 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1202 ldb_dn_get_linearized(msg
->dn
),
1203 ldb_errstring(sam_ldb
)));
1204 return NT_STATUS_ACCESS_DENIED
;
1206 ldb_transaction_cancel(sam_ldb
);
1207 DEBUG(0,("Failed to create user record %s: %s\n",
1208 ldb_dn_get_linearized(msg
->dn
),
1209 ldb_errstring(sam_ldb
)));
1210 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1213 if (r
->in
.info
->trust_direction
& LSA_TRUST_DIRECTION_INBOUND
) {
1214 struct ldb_dn
*user_dn
;
1215 /* Inbound trusts must also create a cn=users object to match */
1216 nt_status
= add_trust_user(mem_ctx
, sam_ldb
,
1217 policy_state
->domain_dn
,
1219 &auth_struct
.incoming
,
1221 if (!NT_STATUS_IS_OK(nt_status
)) {
1222 ldb_transaction_cancel(sam_ldb
);
1226 /* save the trust user dn */
1227 trusted_domain_state
->trusted_domain_user_dn
1228 = talloc_steal(trusted_domain_state
, user_dn
);
1231 ret
= ldb_transaction_commit(sam_ldb
);
1232 if (ret
!= LDB_SUCCESS
) {
1233 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1237 * Notify winbindd that we have a new trust
1239 status
= irpc_servers_byname(dce_call
->msg_ctx
,
1242 &num_server_ids
, &server_ids
);
1243 if (NT_STATUS_IS_OK(status
) && num_server_ids
>= 1) {
1244 enum ndr_err_code ndr_err
;
1247 ndr_err
= ndr_push_struct_blob(&b
, mem_ctx
, r
->in
.info
,
1248 (ndr_push_flags_fn_t
)ndr_push_lsa_TrustDomainInfoInfoEx
);
1249 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1250 imessaging_send(dce_call
->msg_ctx
, server_ids
[0],
1251 MSG_WINBIND_NEW_TRUSTED_DOMAIN
, &b
);
1254 TALLOC_FREE(server_ids
);
1256 handle
= dcesrv_handle_new(dce_call
->context
, LSA_HANDLE_TRUSTED_DOMAIN
);
1258 return NT_STATUS_NO_MEMORY
;
1261 handle
->data
= talloc_steal(handle
, trusted_domain_state
);
1263 trusted_domain_state
->access_mask
= r
->in
.access_mask
;
1264 trusted_domain_state
->policy
= talloc_reference(trusted_domain_state
, policy_state
);
1266 *r
->out
.trustdom_handle
= handle
->wire_handle
;
1268 return NT_STATUS_OK
;
1272 lsa_CreateTrustedDomainEx2
1274 static NTSTATUS
dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state
*dce_call
,
1275 TALLOC_CTX
*mem_ctx
,
1276 struct lsa_CreateTrustedDomainEx2
*r
)
1278 return dcesrv_lsa_CreateTrustedDomain_base(dce_call
, mem_ctx
, r
, NDR_LSA_CREATETRUSTEDDOMAINEX2
, NULL
);
1281 lsa_CreateTrustedDomainEx
1283 static NTSTATUS
dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state
*dce_call
,
1284 TALLOC_CTX
*mem_ctx
,
1285 struct lsa_CreateTrustedDomainEx
*r
)
1287 struct lsa_CreateTrustedDomainEx2 r2
;
1289 r2
.in
.policy_handle
= r
->in
.policy_handle
;
1290 r2
.in
.info
= r
->in
.info
;
1291 r2
.out
.trustdom_handle
= r
->out
.trustdom_handle
;
1292 return dcesrv_lsa_CreateTrustedDomain_base(dce_call
, mem_ctx
, &r2
, NDR_LSA_CREATETRUSTEDDOMAINEX
, r
->in
.auth_info
);
1296 lsa_CreateTrustedDomain
1298 static NTSTATUS
dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1299 struct lsa_CreateTrustedDomain
*r
)
1301 struct lsa_CreateTrustedDomainEx2 r2
;
1303 r2
.in
.policy_handle
= r
->in
.policy_handle
;
1304 r2
.in
.info
= talloc(mem_ctx
, struct lsa_TrustDomainInfoInfoEx
);
1306 return NT_STATUS_NO_MEMORY
;
1309 r2
.in
.info
->domain_name
.string
= NULL
;
1310 r2
.in
.info
->netbios_name
= r
->in
.info
->name
;
1311 r2
.in
.info
->sid
= r
->in
.info
->sid
;
1312 r2
.in
.info
->trust_direction
= LSA_TRUST_DIRECTION_OUTBOUND
;
1313 r2
.in
.info
->trust_type
= LSA_TRUST_TYPE_DOWNLEVEL
;
1314 r2
.in
.info
->trust_attributes
= 0;
1316 r2
.in
.access_mask
= r
->in
.access_mask
;
1317 r2
.out
.trustdom_handle
= r
->out
.trustdom_handle
;
1319 return dcesrv_lsa_CreateTrustedDomain_base(dce_call
, mem_ctx
, &r2
, NDR_LSA_CREATETRUSTEDDOMAIN
, NULL
);
1322 static NTSTATUS
dcesrv_lsa_OpenTrustedDomain_common(
1323 struct dcesrv_call_state
*dce_call
,
1324 TALLOC_CTX
*tmp_mem
,
1325 struct lsa_policy_state
*policy_state
,
1327 uint32_t access_mask
,
1328 struct dcesrv_handle
**_handle
)
1330 struct lsa_trusted_domain_state
*trusted_domain_state
;
1331 struct dcesrv_handle
*handle
;
1332 struct ldb_message
**msgs
;
1333 const char *attrs
[] = {
1341 /* TODO: perform access checks */
1343 /* search for the trusted_domain record */
1344 ret
= gendb_search(policy_state
->sam_ldb
, tmp_mem
,
1345 policy_state
->system_dn
,
1346 &msgs
, attrs
, "%s", filter
);
1348 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1352 DEBUG(0,("Found %d records matching %s under %s\n", ret
,
1354 ldb_dn_get_linearized(policy_state
->system_dn
)));
1355 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1358 trusted_domain_state
= talloc_zero(tmp_mem
,
1359 struct lsa_trusted_domain_state
);
1360 if (!trusted_domain_state
) {
1361 return NT_STATUS_NO_MEMORY
;
1363 trusted_domain_state
->policy
= policy_state
;
1365 trusted_domain_state
->trusted_domain_dn
=
1366 talloc_steal(trusted_domain_state
, msgs
[0]->dn
);
1368 direction
= ldb_msg_find_attr_as_int(msgs
[0], "trustDirection", 0);
1369 if (direction
& LSA_TRUST_DIRECTION_INBOUND
) {
1370 const char *flatname
= ldb_msg_find_attr_as_string(msgs
[0],
1373 /* search for the trusted_domain account */
1374 ret
= gendb_search(policy_state
->sam_ldb
, tmp_mem
,
1375 policy_state
->domain_dn
,
1377 "(&(samaccountname=%s$)(objectclass=user)"
1378 "(userAccountControl:%s:=%u))",
1380 LDB_OID_COMPARATOR_AND
,
1381 UF_INTERDOMAIN_TRUST_ACCOUNT
);
1383 trusted_domain_state
->trusted_domain_user_dn
=
1384 talloc_steal(trusted_domain_state
, msgs
[0]->dn
);
1388 handle
= dcesrv_handle_new(dce_call
->context
, LSA_HANDLE_TRUSTED_DOMAIN
);
1390 return NT_STATUS_NO_MEMORY
;
1393 handle
->data
= talloc_steal(handle
, trusted_domain_state
);
1395 trusted_domain_state
->access_mask
= access_mask
;
1396 trusted_domain_state
->policy
= talloc_reference(trusted_domain_state
,
1401 return NT_STATUS_OK
;
1405 lsa_OpenTrustedDomain
1407 static NTSTATUS
dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1408 struct lsa_OpenTrustedDomain
*r
)
1410 struct dcesrv_handle
*policy_handle
;
1411 struct lsa_policy_state
*policy_state
;
1412 struct dcesrv_handle
*handle
;
1413 const char *sid_string
;
1417 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
1418 ZERO_STRUCTP(r
->out
.trustdom_handle
);
1419 policy_state
= policy_handle
->data
;
1421 sid_string
= dom_sid_string(mem_ctx
, r
->in
.sid
);
1423 return NT_STATUS_NO_MEMORY
;
1426 filter
= talloc_asprintf(mem_ctx
,
1427 "(&(securityIdentifier=%s)"
1428 "(objectclass=trustedDomain))",
1430 if (filter
== NULL
) {
1431 return NT_STATUS_NO_MEMORY
;
1434 status
= dcesrv_lsa_OpenTrustedDomain_common(dce_call
, mem_ctx
,
1439 if (!NT_STATUS_IS_OK(status
)) {
1443 *r
->out
.trustdom_handle
= handle
->wire_handle
;
1445 return NT_STATUS_OK
;
1450 lsa_OpenTrustedDomainByName
1452 static NTSTATUS
dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state
*dce_call
,
1453 TALLOC_CTX
*mem_ctx
,
1454 struct lsa_OpenTrustedDomainByName
*r
)
1456 struct dcesrv_handle
*policy_handle
;
1457 struct lsa_policy_state
*policy_state
;
1458 struct dcesrv_handle
*handle
;
1463 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
1464 ZERO_STRUCTP(r
->out
.trustdom_handle
);
1465 policy_state
= policy_handle
->data
;
1467 if (!r
->in
.name
.string
) {
1468 return NT_STATUS_INVALID_PARAMETER
;
1471 /* search for the trusted_domain record */
1472 td_name
= ldb_binary_encode_string(mem_ctx
, r
->in
.name
.string
);
1473 if (td_name
== NULL
) {
1474 return NT_STATUS_NO_MEMORY
;
1477 filter
= talloc_asprintf(mem_ctx
,
1478 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1479 "(objectclass=trustedDomain))",
1480 td_name
, td_name
, td_name
);
1481 if (filter
== NULL
) {
1482 return NT_STATUS_NO_MEMORY
;
1485 status
= dcesrv_lsa_OpenTrustedDomain_common(dce_call
, mem_ctx
,
1490 if (!NT_STATUS_IS_OK(status
)) {
1494 *r
->out
.trustdom_handle
= handle
->wire_handle
;
1496 return NT_STATUS_OK
;
1502 lsa_SetTrustedDomainInfo
1504 static NTSTATUS
dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1505 struct lsa_SetTrustedDomainInfo
*r
)
1507 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1512 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1513 * otherwise at least one must be provided */
1514 static NTSTATUS
get_tdo(struct ldb_context
*sam
, TALLOC_CTX
*mem_ctx
,
1515 struct ldb_dn
*basedn
, const char *dns_domain
,
1516 const char *netbios
, struct dom_sid2
*sid
,
1517 struct ldb_message
***msgs
)
1519 const char *attrs
[] = { "flatname", "trustPartner",
1520 "securityIdentifier", "trustDirection",
1521 "trustType", "trustAttributes",
1523 "msDs-supportedEncryptionTypes",
1524 "msDS-TrustForestTrustInfo",
1529 char *sidstr
= NULL
;
1534 if (dns_domain
|| netbios
|| sid
) {
1535 filter
= talloc_strdup(mem_ctx
,
1536 "(&(objectclass=trustedDomain)(|");
1538 filter
= talloc_strdup(mem_ctx
,
1539 "(objectclass=trustedDomain)");
1542 return NT_STATUS_NO_MEMORY
;
1546 dns
= ldb_binary_encode_string(mem_ctx
, dns_domain
);
1548 return NT_STATUS_NO_MEMORY
;
1550 filter
= talloc_asprintf_append(filter
,
1551 "(trustPartner=%s)", dns
);
1553 return NT_STATUS_NO_MEMORY
;
1557 nbn
= ldb_binary_encode_string(mem_ctx
, netbios
);
1559 return NT_STATUS_NO_MEMORY
;
1561 filter
= talloc_asprintf_append(filter
,
1562 "(flatname=%s)", nbn
);
1564 return NT_STATUS_NO_MEMORY
;
1568 sidstr
= dom_sid_string(mem_ctx
, sid
);
1570 return NT_STATUS_INVALID_PARAMETER
;
1572 filter
= talloc_asprintf_append(filter
,
1573 "(securityIdentifier=%s)",
1576 return NT_STATUS_NO_MEMORY
;
1579 if (dns_domain
|| netbios
|| sid
) {
1580 filter
= talloc_asprintf_append(filter
, "))");
1582 return NT_STATUS_NO_MEMORY
;
1586 ret
= gendb_search(sam
, mem_ctx
, basedn
, msgs
, attrs
, "%s", filter
);
1588 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1592 return NT_STATUS_OBJECT_NAME_COLLISION
;
1595 return NT_STATUS_OK
;
1598 static NTSTATUS
update_uint32_t_value(TALLOC_CTX
*mem_ctx
,
1599 struct ldb_context
*sam_ldb
,
1600 struct ldb_message
*orig
,
1601 struct ldb_message
*dest
,
1602 const char *attribute
,
1604 uint32_t *orig_value
)
1606 const struct ldb_val
*orig_val
;
1607 uint32_t orig_uint
= 0;
1608 unsigned int flags
= 0;
1611 orig_val
= ldb_msg_find_ldb_val(orig
, attribute
);
1612 if (!orig_val
|| !orig_val
->data
) {
1613 /* add new attribute */
1614 flags
= LDB_FLAG_MOD_ADD
;
1618 orig_uint
= strtoul((const char *)orig_val
->data
, NULL
, 0);
1619 if (errno
!= 0 || orig_uint
!= value
) {
1620 /* replace also if can't get value */
1621 flags
= LDB_FLAG_MOD_REPLACE
;
1626 /* stored value is identical, nothing to change */
1630 ret
= ldb_msg_add_empty(dest
, attribute
, flags
, NULL
);
1631 if (ret
!= LDB_SUCCESS
) {
1632 return NT_STATUS_NO_MEMORY
;
1635 ret
= samdb_msg_add_uint(sam_ldb
, dest
, dest
, attribute
, value
);
1636 if (ret
!= LDB_SUCCESS
) {
1637 return NT_STATUS_NO_MEMORY
;
1642 *orig_value
= orig_uint
;
1644 return NT_STATUS_OK
;
1647 static NTSTATUS
update_trust_user(TALLOC_CTX
*mem_ctx
,
1648 struct ldb_context
*sam_ldb
,
1649 struct ldb_dn
*base_dn
,
1651 const char *netbios_name
,
1652 struct trustAuthInOutBlob
*in
)
1654 const char *attrs
[] = { "userAccountControl", NULL
};
1655 struct ldb_message
**msgs
;
1656 struct ldb_message
*msg
;
1661 ret
= gendb_search(sam_ldb
, mem_ctx
,
1662 base_dn
, &msgs
, attrs
,
1663 "samAccountName=%s$", netbios_name
);
1665 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1670 return NT_STATUS_OK
;
1673 /* ok no existing user, add it from scratch */
1674 return add_trust_user(mem_ctx
, sam_ldb
, base_dn
,
1675 netbios_name
, in
, NULL
);
1678 /* check user is what we are looking for */
1679 uac
= ldb_msg_find_attr_as_uint(msgs
[0],
1680 "userAccountControl", 0);
1681 if (!(uac
& UF_INTERDOMAIN_TRUST_ACCOUNT
)) {
1682 return NT_STATUS_OBJECT_NAME_COLLISION
;
1686 ret
= ldb_delete(sam_ldb
, msgs
[0]->dn
);
1689 return NT_STATUS_OK
;
1690 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
:
1691 return NT_STATUS_ACCESS_DENIED
;
1693 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1697 /* entry exists, just modify secret if any */
1698 if (in
== NULL
|| in
->count
== 0) {
1699 return NT_STATUS_OK
;
1702 msg
= ldb_msg_new(mem_ctx
);
1704 return NT_STATUS_NO_MEMORY
;
1706 msg
->dn
= msgs
[0]->dn
;
1708 for (i
= 0; i
< in
->count
; i
++) {
1709 const char *attribute
;
1711 switch (in
->current
.array
[i
].AuthType
) {
1712 case TRUST_AUTH_TYPE_NT4OWF
:
1713 attribute
= "unicodePwd";
1714 v
.data
= (uint8_t *)&in
->current
.array
[i
].AuthInfo
.nt4owf
.password
;
1717 case TRUST_AUTH_TYPE_CLEAR
:
1718 attribute
= "clearTextPassword";
1719 v
.data
= in
->current
.array
[i
].AuthInfo
.clear
.password
;
1720 v
.length
= in
->current
.array
[i
].AuthInfo
.clear
.size
;
1726 ret
= ldb_msg_add_empty(msg
, attribute
,
1727 LDB_FLAG_MOD_REPLACE
, NULL
);
1728 if (ret
!= LDB_SUCCESS
) {
1729 return NT_STATUS_NO_MEMORY
;
1732 ret
= ldb_msg_add_value(msg
, attribute
, &v
, NULL
);
1733 if (ret
!= LDB_SUCCESS
) {
1734 return NT_STATUS_NO_MEMORY
;
1738 /* create the trusted_domain user account */
1739 ret
= ldb_modify(sam_ldb
, msg
);
1740 if (ret
!= LDB_SUCCESS
) {
1741 DEBUG(0,("Failed to create user record %s: %s\n",
1742 ldb_dn_get_linearized(msg
->dn
),
1743 ldb_errstring(sam_ldb
)));
1746 case LDB_ERR_ENTRY_ALREADY_EXISTS
:
1747 return NT_STATUS_DOMAIN_EXISTS
;
1748 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
:
1749 return NT_STATUS_ACCESS_DENIED
;
1751 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1755 return NT_STATUS_OK
;
1759 static NTSTATUS
setInfoTrustedDomain_base(struct dcesrv_call_state
*dce_call
,
1760 struct lsa_policy_state
*p_state
,
1761 TALLOC_CTX
*mem_ctx
,
1762 struct ldb_message
*dom_msg
,
1763 enum lsa_TrustDomInfoEnum level
,
1764 union lsa_TrustedDomainInfo
*info
)
1766 uint32_t *posix_offset
= NULL
;
1767 struct lsa_TrustDomainInfoInfoEx
*info_ex
= NULL
;
1768 struct lsa_TrustDomainInfoAuthInfo
*auth_info
= NULL
;
1769 struct lsa_TrustDomainInfoAuthInfoInternal
*auth_info_int
= NULL
;
1770 uint32_t *enc_types
= NULL
;
1771 DATA_BLOB trustAuthIncoming
, trustAuthOutgoing
, auth_blob
;
1772 struct trustDomainPasswords auth_struct
;
1773 struct trustAuthInOutBlob
*current_passwords
= NULL
;
1775 struct ldb_message
**msgs
;
1776 struct ldb_message
*msg
;
1777 bool add_outgoing
= false;
1778 bool add_incoming
= false;
1779 bool del_outgoing
= false;
1780 bool del_incoming
= false;
1781 bool del_forest_info
= false;
1782 bool in_transaction
= false;
1787 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET
:
1788 posix_offset
= &info
->posix_offset
.posix_offset
;
1790 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX
:
1791 info_ex
= &info
->info_ex
;
1793 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO
:
1794 auth_info
= &info
->auth_info
;
1796 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO
:
1797 posix_offset
= &info
->full_info
.posix_offset
.posix_offset
;
1798 info_ex
= &info
->full_info
.info_ex
;
1799 auth_info
= &info
->full_info
.auth_info
;
1801 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL
:
1802 auth_info_int
= &info
->auth_info_internal
;
1804 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL
:
1805 posix_offset
= &info
->full_info_internal
.posix_offset
.posix_offset
;
1806 info_ex
= &info
->full_info_internal
.info_ex
;
1807 auth_info_int
= &info
->full_info_internal
.auth_info
;
1809 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES
:
1810 enc_types
= &info
->enc_types
.enc_types
;
1813 return NT_STATUS_INVALID_PARAMETER
;
1817 nt_status
= auth_info_2_auth_blob(mem_ctx
, auth_info
,
1819 &trustAuthOutgoing
);
1820 if (!NT_STATUS_IS_OK(nt_status
)) {
1823 if (trustAuthIncoming
.data
) {
1824 /* This does the decode of some of this twice, but it is easier that way */
1825 nt_status
= auth_info_2_trustauth_inout(mem_ctx
,
1826 auth_info
->incoming_count
,
1827 auth_info
->incoming_current_auth_info
,
1829 ¤t_passwords
);
1830 if (!NT_STATUS_IS_OK(nt_status
)) {
1836 /* decode auth_info_int if set */
1837 if (auth_info_int
) {
1839 /* now decrypt blob */
1840 auth_blob
= data_blob_const(auth_info_int
->auth_blob
.data
,
1841 auth_info_int
->auth_blob
.size
);
1843 nt_status
= get_trustdom_auth_blob(dce_call
, mem_ctx
,
1844 &auth_blob
, &auth_struct
);
1845 if (!NT_STATUS_IS_OK(nt_status
)) {
1851 /* verify data matches */
1852 if (info_ex
->trust_attributes
&
1853 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
) {
1854 /* TODO: check what behavior level we have */
1855 if (strcasecmp_m(p_state
->domain_dns
,
1856 p_state
->forest_dns
) != 0) {
1857 return NT_STATUS_INVALID_DOMAIN_STATE
;
1861 ret
= samdb_rodc(p_state
->sam_ldb
, &am_rodc
);
1862 if (ret
== LDB_SUCCESS
&& am_rodc
) {
1863 return NT_STATUS_NO_SUCH_DOMAIN
;
1866 /* verify only one object matches the dns/netbios/sid
1867 * triplet and that this is the one we already have */
1868 nt_status
= get_tdo(p_state
->sam_ldb
, mem_ctx
,
1870 info_ex
->domain_name
.string
,
1871 info_ex
->netbios_name
.string
,
1872 info_ex
->sid
, &msgs
);
1873 if (!NT_STATUS_IS_OK(nt_status
)) {
1876 if (ldb_dn_compare(dom_msg
->dn
, msgs
[0]->dn
) != 0) {
1877 return NT_STATUS_OBJECT_NAME_COLLISION
;
1882 /* TODO: should we fetch previous values from the existing entry
1883 * and append them ? */
1884 if (auth_info_int
&& auth_struct
.incoming
.count
) {
1885 nt_status
= get_trustauth_inout_blob(dce_call
, mem_ctx
,
1886 &auth_struct
.incoming
,
1887 &trustAuthIncoming
);
1888 if (!NT_STATUS_IS_OK(nt_status
)) {
1892 current_passwords
= &auth_struct
.incoming
;
1895 trustAuthIncoming
= data_blob(NULL
, 0);
1898 if (auth_info_int
&& auth_struct
.outgoing
.count
) {
1899 nt_status
= get_trustauth_inout_blob(dce_call
, mem_ctx
,
1900 &auth_struct
.outgoing
,
1901 &trustAuthOutgoing
);
1902 if (!NT_STATUS_IS_OK(nt_status
)) {
1906 trustAuthOutgoing
= data_blob(NULL
, 0);
1909 msg
= ldb_msg_new(mem_ctx
);
1911 return NT_STATUS_NO_MEMORY
;
1913 msg
->dn
= dom_msg
->dn
;
1916 nt_status
= update_uint32_t_value(mem_ctx
, p_state
->sam_ldb
,
1919 *posix_offset
, NULL
);
1920 if (!NT_STATUS_IS_OK(nt_status
)) {
1927 uint32_t changed_attrs
;
1931 nt_status
= update_uint32_t_value(mem_ctx
, p_state
->sam_ldb
,
1934 info_ex
->trust_direction
,
1936 if (!NT_STATUS_IS_OK(nt_status
)) {
1940 if (info_ex
->trust_direction
& LSA_TRUST_DIRECTION_INBOUND
) {
1941 if (auth_info
!= NULL
&& trustAuthIncoming
.length
> 0) {
1942 add_incoming
= true;
1945 if (info_ex
->trust_direction
& LSA_TRUST_DIRECTION_OUTBOUND
) {
1946 if (auth_info
!= NULL
&& trustAuthOutgoing
.length
> 0) {
1947 add_outgoing
= true;
1951 if ((origdir
& LSA_TRUST_DIRECTION_INBOUND
) &&
1952 !(info_ex
->trust_direction
& LSA_TRUST_DIRECTION_INBOUND
)) {
1953 del_incoming
= true;
1955 if ((origdir
& LSA_TRUST_DIRECTION_OUTBOUND
) &&
1956 !(info_ex
->trust_direction
& LSA_TRUST_DIRECTION_OUTBOUND
)) {
1957 del_outgoing
= true;
1960 origtype
= ldb_msg_find_attr_as_int(dom_msg
, "trustType", -1);
1961 if (origtype
== -1 || origtype
!= info_ex
->trust_type
) {
1962 DEBUG(1, ("Attempted to change trust type! "
1963 "Operation not handled\n"));
1964 return NT_STATUS_INVALID_PARAMETER
;
1967 nt_status
= update_uint32_t_value(mem_ctx
, p_state
->sam_ldb
,
1970 info_ex
->trust_attributes
,
1972 if (!NT_STATUS_IS_OK(nt_status
)) {
1975 /* TODO: check forestFunctionality from ldb opaque */
1976 /* TODO: check what is set makes sense */
1978 changed_attrs
= origattrs
^ info_ex
->trust_attributes
;
1979 if (changed_attrs
& ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
) {
1981 * For now we only allow
1982 * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
1984 * TODO: we may need to support more attribute changes
1986 DEBUG(1, ("Attempted to change trust attributes "
1987 "(0x%08x != 0x%08x)! "
1988 "Operation not handled yet...\n",
1989 (unsigned)origattrs
,
1990 (unsigned)info_ex
->trust_attributes
));
1991 return NT_STATUS_INVALID_PARAMETER
;
1994 if (!(info_ex
->trust_attributes
&
1995 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
))
1997 struct ldb_message_element
*orig_forest_el
= NULL
;
1999 orig_forest_el
= ldb_msg_find_element(dom_msg
,
2000 "msDS-TrustForestTrustInfo");
2001 if (orig_forest_el
!= NULL
) {
2002 del_forest_info
= true;
2008 nt_status
= update_uint32_t_value(mem_ctx
, p_state
->sam_ldb
,
2010 "msDS-SupportedEncryptionTypes",
2012 if (!NT_STATUS_IS_OK(nt_status
)) {
2017 if (add_incoming
|| del_incoming
) {
2018 ret
= ldb_msg_add_empty(msg
, "trustAuthIncoming",
2019 LDB_FLAG_MOD_REPLACE
, NULL
);
2020 if (ret
!= LDB_SUCCESS
) {
2021 return NT_STATUS_NO_MEMORY
;
2024 ret
= ldb_msg_add_value(msg
, "trustAuthIncoming",
2025 &trustAuthIncoming
, NULL
);
2026 if (ret
!= LDB_SUCCESS
) {
2027 return NT_STATUS_NO_MEMORY
;
2031 if (add_outgoing
|| del_outgoing
) {
2032 ret
= ldb_msg_add_empty(msg
, "trustAuthOutgoing",
2033 LDB_FLAG_MOD_REPLACE
, NULL
);
2034 if (ret
!= LDB_SUCCESS
) {
2035 return NT_STATUS_NO_MEMORY
;
2038 ret
= ldb_msg_add_value(msg
, "trustAuthOutgoing",
2039 &trustAuthOutgoing
, NULL
);
2040 if (ret
!= LDB_SUCCESS
) {
2041 return NT_STATUS_NO_MEMORY
;
2045 if (del_forest_info
) {
2046 ret
= ldb_msg_add_empty(msg
, "msDS-TrustForestTrustInfo",
2047 LDB_FLAG_MOD_REPLACE
, NULL
);
2048 if (ret
!= LDB_SUCCESS
) {
2049 return NT_STATUS_NO_MEMORY
;
2053 /* start transaction */
2054 ret
= ldb_transaction_start(p_state
->sam_ldb
);
2055 if (ret
!= LDB_SUCCESS
) {
2056 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2058 in_transaction
= true;
2060 if (msg
->num_elements
) {
2061 ret
= ldb_modify(p_state
->sam_ldb
, msg
);
2062 if (ret
!= LDB_SUCCESS
) {
2063 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
2064 ldb_dn_get_linearized(msg
->dn
),
2065 ldb_errstring(p_state
->sam_ldb
)));
2066 nt_status
= dsdb_ldb_err_to_ntstatus(ret
);
2071 if (add_incoming
|| del_incoming
) {
2072 const char *netbios_name
;
2074 netbios_name
= ldb_msg_find_attr_as_string(dom_msg
,
2076 if (!netbios_name
) {
2077 nt_status
= NT_STATUS_INVALID_DOMAIN_STATE
;
2081 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
2082 nt_status
= update_trust_user(mem_ctx
,
2088 if (!NT_STATUS_IS_OK(nt_status
)) {
2093 /* ok, all fine, commit transaction and return */
2094 ret
= ldb_transaction_commit(p_state
->sam_ldb
);
2095 if (ret
!= LDB_SUCCESS
) {
2096 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2098 in_transaction
= false;
2100 nt_status
= NT_STATUS_OK
;
2103 if (in_transaction
) {
2104 ldb_transaction_cancel(p_state
->sam_ldb
);
2110 lsa_SetInfomrationTrustedDomain
2112 static NTSTATUS
dcesrv_lsa_SetInformationTrustedDomain(
2113 struct dcesrv_call_state
*dce_call
,
2114 TALLOC_CTX
*mem_ctx
,
2115 struct lsa_SetInformationTrustedDomain
*r
)
2117 struct dcesrv_handle
*h
;
2118 struct lsa_trusted_domain_state
*td_state
;
2119 struct ldb_message
**msgs
;
2122 DCESRV_PULL_HANDLE(h
, r
->in
.trustdom_handle
,
2123 LSA_HANDLE_TRUSTED_DOMAIN
);
2125 td_state
= talloc_get_type(h
->data
, struct lsa_trusted_domain_state
);
2127 /* get the trusted domain object */
2128 nt_status
= get_tdo(td_state
->policy
->sam_ldb
, mem_ctx
,
2129 td_state
->trusted_domain_dn
,
2130 NULL
, NULL
, NULL
, &msgs
);
2131 if (!NT_STATUS_IS_OK(nt_status
)) {
2132 if (NT_STATUS_EQUAL(nt_status
,
2133 NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
2136 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2139 return setInfoTrustedDomain_base(dce_call
, td_state
->policy
, mem_ctx
,
2140 msgs
[0], r
->in
.level
, r
->in
.info
);
2145 lsa_DeleteTrustedDomain
2147 static NTSTATUS
dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2148 struct lsa_DeleteTrustedDomain
*r
)
2151 struct lsa_OpenTrustedDomain opn
= {{0},{0}};
2152 struct lsa_DeleteObject del
;
2153 struct dcesrv_handle
*h
;
2155 opn
.in
.handle
= r
->in
.handle
;
2156 opn
.in
.sid
= r
->in
.dom_sid
;
2157 opn
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2158 opn
.out
.trustdom_handle
= talloc(mem_ctx
, struct policy_handle
);
2159 if (!opn
.out
.trustdom_handle
) {
2160 return NT_STATUS_NO_MEMORY
;
2162 status
= dcesrv_lsa_OpenTrustedDomain(dce_call
, mem_ctx
, &opn
);
2163 if (!NT_STATUS_IS_OK(status
)) {
2167 DCESRV_PULL_HANDLE(h
, opn
.out
.trustdom_handle
, DCESRV_HANDLE_ANY
);
2168 talloc_steal(mem_ctx
, h
);
2170 del
.in
.handle
= opn
.out
.trustdom_handle
;
2171 del
.out
.handle
= opn
.out
.trustdom_handle
;
2172 status
= dcesrv_lsa_DeleteObject(dce_call
, mem_ctx
, &del
);
2173 if (!NT_STATUS_IS_OK(status
)) {
2176 return NT_STATUS_OK
;
2179 static NTSTATUS
fill_trust_domain_ex(TALLOC_CTX
*mem_ctx
,
2180 struct ldb_message
*msg
,
2181 struct lsa_TrustDomainInfoInfoEx
*info_ex
)
2183 info_ex
->domain_name
.string
2184 = ldb_msg_find_attr_as_string(msg
, "trustPartner", NULL
);
2185 info_ex
->netbios_name
.string
2186 = ldb_msg_find_attr_as_string(msg
, "flatname", NULL
);
2188 = samdb_result_dom_sid(mem_ctx
, msg
, "securityIdentifier");
2189 info_ex
->trust_direction
2190 = ldb_msg_find_attr_as_int(msg
, "trustDirection", 0);
2192 = ldb_msg_find_attr_as_int(msg
, "trustType", 0);
2193 info_ex
->trust_attributes
2194 = ldb_msg_find_attr_as_int(msg
, "trustAttributes", 0);
2195 return NT_STATUS_OK
;
2199 lsa_QueryTrustedDomainInfo
2201 static NTSTATUS
dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2202 struct lsa_QueryTrustedDomainInfo
*r
)
2204 union lsa_TrustedDomainInfo
*info
= NULL
;
2205 struct dcesrv_handle
*h
;
2206 struct lsa_trusted_domain_state
*trusted_domain_state
;
2207 struct ldb_message
*msg
;
2209 struct ldb_message
**res
;
2210 const char *attrs
[] = {
2213 "securityIdentifier",
2217 "msDs-supportedEncryptionTypes",
2221 DCESRV_PULL_HANDLE(h
, r
->in
.trustdom_handle
, LSA_HANDLE_TRUSTED_DOMAIN
);
2223 trusted_domain_state
= talloc_get_type(h
->data
, struct lsa_trusted_domain_state
);
2225 /* pull all the user attributes */
2226 ret
= gendb_search_dn(trusted_domain_state
->policy
->sam_ldb
, mem_ctx
,
2227 trusted_domain_state
->trusted_domain_dn
, &res
, attrs
);
2229 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2233 info
= talloc_zero(mem_ctx
, union lsa_TrustedDomainInfo
);
2235 return NT_STATUS_NO_MEMORY
;
2237 *r
->out
.info
= info
;
2239 switch (r
->in
.level
) {
2240 case LSA_TRUSTED_DOMAIN_INFO_NAME
:
2241 info
->name
.netbios_name
.string
2242 = ldb_msg_find_attr_as_string(msg
, "flatname", NULL
);
2244 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET
:
2245 info
->posix_offset
.posix_offset
2246 = ldb_msg_find_attr_as_uint(msg
, "posixOffset", 0);
2248 #if 0 /* Win2k3 doesn't implement this */
2249 case LSA_TRUSTED_DOMAIN_INFO_BASIC
:
2250 r
->out
.info
->info_basic
.netbios_name
.string
2251 = ldb_msg_find_attr_as_string(msg
, "flatname", NULL
);
2252 r
->out
.info
->info_basic
.sid
2253 = samdb_result_dom_sid(mem_ctx
, msg
, "securityIdentifier");
2256 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX
:
2257 return fill_trust_domain_ex(mem_ctx
, msg
, &info
->info_ex
);
2259 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO
:
2260 ZERO_STRUCT(info
->full_info
);
2261 return fill_trust_domain_ex(mem_ctx
, msg
, &info
->full_info
.info_ex
);
2262 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL
:
2263 ZERO_STRUCT(info
->full_info2_internal
);
2264 info
->full_info2_internal
.posix_offset
.posix_offset
2265 = ldb_msg_find_attr_as_uint(msg
, "posixOffset", 0);
2266 return fill_trust_domain_ex(mem_ctx
, msg
, &info
->full_info2_internal
.info
.info_ex
);
2268 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES
:
2269 info
->enc_types
.enc_types
2270 = ldb_msg_find_attr_as_uint(msg
, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5
);
2273 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS
:
2274 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL
:
2275 /* oops, we don't want to return the info after all */
2277 *r
->out
.info
= NULL
;
2278 return NT_STATUS_INVALID_PARAMETER
;
2280 /* oops, we don't want to return the info after all */
2282 *r
->out
.info
= NULL
;
2283 return NT_STATUS_INVALID_INFO_CLASS
;
2286 return NT_STATUS_OK
;
2291 lsa_QueryTrustedDomainInfoBySid
2293 static NTSTATUS
dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2294 struct lsa_QueryTrustedDomainInfoBySid
*r
)
2297 struct lsa_OpenTrustedDomain opn
= {{0},{0}};
2298 struct lsa_QueryTrustedDomainInfo query
;
2299 struct dcesrv_handle
*h
;
2301 opn
.in
.handle
= r
->in
.handle
;
2302 opn
.in
.sid
= r
->in
.dom_sid
;
2303 opn
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2304 opn
.out
.trustdom_handle
= talloc(mem_ctx
, struct policy_handle
);
2305 if (!opn
.out
.trustdom_handle
) {
2306 return NT_STATUS_NO_MEMORY
;
2308 status
= dcesrv_lsa_OpenTrustedDomain(dce_call
, mem_ctx
, &opn
);
2309 if (!NT_STATUS_IS_OK(status
)) {
2313 /* Ensure this handle goes away at the end of this call */
2314 DCESRV_PULL_HANDLE(h
, opn
.out
.trustdom_handle
, DCESRV_HANDLE_ANY
);
2315 talloc_steal(mem_ctx
, h
);
2317 query
.in
.trustdom_handle
= opn
.out
.trustdom_handle
;
2318 query
.in
.level
= r
->in
.level
;
2319 query
.out
.info
= r
->out
.info
;
2320 status
= dcesrv_lsa_QueryTrustedDomainInfo(dce_call
, mem_ctx
, &query
);
2321 if (!NT_STATUS_IS_OK(status
)) {
2325 return NT_STATUS_OK
;
2329 lsa_SetTrustedDomainInfoByName
2331 static NTSTATUS
dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state
*dce_call
,
2332 TALLOC_CTX
*mem_ctx
,
2333 struct lsa_SetTrustedDomainInfoByName
*r
)
2335 struct dcesrv_handle
*policy_handle
;
2336 struct lsa_policy_state
*policy_state
;
2337 struct ldb_message
**msgs
;
2340 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
2341 policy_state
= policy_handle
->data
;
2343 /* get the trusted domain object */
2344 nt_status
= get_tdo(policy_state
->sam_ldb
, mem_ctx
,
2345 policy_state
->domain_dn
,
2346 r
->in
.trusted_domain
->string
,
2347 r
->in
.trusted_domain
->string
,
2349 if (!NT_STATUS_IS_OK(nt_status
)) {
2350 if (NT_STATUS_EQUAL(nt_status
,
2351 NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
2354 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2357 return setInfoTrustedDomain_base(dce_call
, policy_state
, mem_ctx
,
2358 msgs
[0], r
->in
.level
, r
->in
.info
);
2362 lsa_QueryTrustedDomainInfoByName
2364 static NTSTATUS
dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state
*dce_call
,
2365 TALLOC_CTX
*mem_ctx
,
2366 struct lsa_QueryTrustedDomainInfoByName
*r
)
2369 struct lsa_OpenTrustedDomainByName opn
= {{0},{0}};
2370 struct lsa_QueryTrustedDomainInfo query
;
2371 struct dcesrv_handle
*h
;
2373 opn
.in
.handle
= r
->in
.handle
;
2374 opn
.in
.name
= *r
->in
.trusted_domain
;
2375 opn
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2376 opn
.out
.trustdom_handle
= talloc(mem_ctx
, struct policy_handle
);
2377 if (!opn
.out
.trustdom_handle
) {
2378 return NT_STATUS_NO_MEMORY
;
2380 status
= dcesrv_lsa_OpenTrustedDomainByName(dce_call
, mem_ctx
, &opn
);
2381 if (!NT_STATUS_IS_OK(status
)) {
2385 /* Ensure this handle goes away at the end of this call */
2386 DCESRV_PULL_HANDLE(h
, opn
.out
.trustdom_handle
, DCESRV_HANDLE_ANY
);
2387 talloc_steal(mem_ctx
, h
);
2389 query
.in
.trustdom_handle
= opn
.out
.trustdom_handle
;
2390 query
.in
.level
= r
->in
.level
;
2391 query
.out
.info
= r
->out
.info
;
2392 status
= dcesrv_lsa_QueryTrustedDomainInfo(dce_call
, mem_ctx
, &query
);
2393 if (!NT_STATUS_IS_OK(status
)) {
2397 return NT_STATUS_OK
;
2401 lsa_CloseTrustedDomainEx
2403 static NTSTATUS
dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state
*dce_call
,
2404 TALLOC_CTX
*mem_ctx
,
2405 struct lsa_CloseTrustedDomainEx
*r
)
2407 /* The result of a bad hair day from an IDL programmer? Not
2408 * implmented in Win2k3. You should always just lsa_Close
2410 return NT_STATUS_NOT_IMPLEMENTED
;
2415 comparison function for sorting lsa_DomainInformation array
2417 static int compare_DomainInfo(struct lsa_DomainInfo
*e1
, struct lsa_DomainInfo
*e2
)
2419 return strcasecmp_m(e1
->name
.string
, e2
->name
.string
);
2425 static NTSTATUS
dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2426 struct lsa_EnumTrustDom
*r
)
2428 struct dcesrv_handle
*policy_handle
;
2429 struct lsa_DomainInfo
*entries
;
2430 struct lsa_policy_state
*policy_state
;
2431 struct ldb_message
**domains
;
2432 const char *attrs
[] = {
2434 "securityIdentifier",
2441 *r
->out
.resume_handle
= 0;
2443 r
->out
.domains
->domains
= NULL
;
2444 r
->out
.domains
->count
= 0;
2446 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
2448 policy_state
= policy_handle
->data
;
2450 /* search for all users in this domain. This could possibly be cached and
2451 resumed based on resume_key */
2452 count
= gendb_search(policy_state
->sam_ldb
, mem_ctx
, policy_state
->system_dn
, &domains
, attrs
,
2453 "objectclass=trustedDomain");
2455 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2458 /* convert to lsa_TrustInformation format */
2459 entries
= talloc_array(mem_ctx
, struct lsa_DomainInfo
, count
);
2461 return NT_STATUS_NO_MEMORY
;
2463 for (i
=0;i
<count
;i
++) {
2464 entries
[i
].sid
= samdb_result_dom_sid(mem_ctx
, domains
[i
], "securityIdentifier");
2465 entries
[i
].name
.string
= ldb_msg_find_attr_as_string(domains
[i
], "flatname", NULL
);
2468 /* sort the results by name */
2469 TYPESAFE_QSORT(entries
, count
, compare_DomainInfo
);
2471 if (*r
->in
.resume_handle
>= count
) {
2472 *r
->out
.resume_handle
= -1;
2474 return NT_STATUS_NO_MORE_ENTRIES
;
2477 /* return the rest, limit by max_size. Note that we
2478 use the w2k3 element size value of 60 */
2479 r
->out
.domains
->count
= count
- *r
->in
.resume_handle
;
2480 r
->out
.domains
->count
= MIN(r
->out
.domains
->count
,
2481 1+(r
->in
.max_size
/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER
));
2483 r
->out
.domains
->domains
= entries
+ *r
->in
.resume_handle
;
2484 r
->out
.domains
->count
= r
->out
.domains
->count
;
2486 if (r
->out
.domains
->count
< count
- *r
->in
.resume_handle
) {
2487 *r
->out
.resume_handle
= *r
->in
.resume_handle
+ r
->out
.domains
->count
;
2488 return STATUS_MORE_ENTRIES
;
2491 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2492 * always be larger than the previous input resume handle, in
2493 * particular when hitting the last query it is vital to set the
2494 * resume handle correctly to avoid infinite client loops, as
2495 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2496 * status is NT_STATUS_OK - gd */
2498 *r
->out
.resume_handle
= (uint32_t)-1;
2500 return NT_STATUS_OK
;
2504 comparison function for sorting lsa_DomainInformation array
2506 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx
*e1
, struct lsa_TrustDomainInfoInfoEx
*e2
)
2508 return strcasecmp_m(e1
->netbios_name
.string
, e2
->netbios_name
.string
);
2512 lsa_EnumTrustedDomainsEx
2514 static NTSTATUS
dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2515 struct lsa_EnumTrustedDomainsEx
*r
)
2517 struct dcesrv_handle
*policy_handle
;
2518 struct lsa_TrustDomainInfoInfoEx
*entries
;
2519 struct lsa_policy_state
*policy_state
;
2520 struct ldb_message
**domains
;
2521 const char *attrs
[] = {
2524 "securityIdentifier",
2534 *r
->out
.resume_handle
= 0;
2536 r
->out
.domains
->domains
= NULL
;
2537 r
->out
.domains
->count
= 0;
2539 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
2541 policy_state
= policy_handle
->data
;
2543 /* search for all users in this domain. This could possibly be cached and
2544 resumed based on resume_key */
2545 count
= gendb_search(policy_state
->sam_ldb
, mem_ctx
, policy_state
->system_dn
, &domains
, attrs
,
2546 "objectclass=trustedDomain");
2548 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2551 /* convert to lsa_DomainInformation format */
2552 entries
= talloc_array(mem_ctx
, struct lsa_TrustDomainInfoInfoEx
, count
);
2554 return NT_STATUS_NO_MEMORY
;
2556 for (i
=0;i
<count
;i
++) {
2557 nt_status
= fill_trust_domain_ex(mem_ctx
, domains
[i
], &entries
[i
]);
2558 if (!NT_STATUS_IS_OK(nt_status
)) {
2563 /* sort the results by name */
2564 TYPESAFE_QSORT(entries
, count
, compare_TrustDomainInfoInfoEx
);
2566 if (*r
->in
.resume_handle
>= count
) {
2567 *r
->out
.resume_handle
= -1;
2569 return NT_STATUS_NO_MORE_ENTRIES
;
2572 /* return the rest, limit by max_size. Note that we
2573 use the w2k3 element size value of 60 */
2574 r
->out
.domains
->count
= count
- *r
->in
.resume_handle
;
2575 r
->out
.domains
->count
= MIN(r
->out
.domains
->count
,
2576 1+(r
->in
.max_size
/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER
));
2578 r
->out
.domains
->domains
= entries
+ *r
->in
.resume_handle
;
2579 r
->out
.domains
->count
= r
->out
.domains
->count
;
2581 if (r
->out
.domains
->count
< count
- *r
->in
.resume_handle
) {
2582 *r
->out
.resume_handle
= *r
->in
.resume_handle
+ r
->out
.domains
->count
;
2583 return STATUS_MORE_ENTRIES
;
2586 *r
->out
.resume_handle
= *r
->in
.resume_handle
+ r
->out
.domains
->count
;
2588 return NT_STATUS_OK
;
2595 static NTSTATUS
dcesrv_lsa_OpenAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2596 struct lsa_OpenAccount
*r
)
2598 struct dcesrv_handle
*h
, *ah
;
2599 struct lsa_policy_state
*state
;
2600 struct lsa_account_state
*astate
;
2602 ZERO_STRUCTP(r
->out
.acct_handle
);
2604 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
2608 astate
= talloc(dce_call
->conn
, struct lsa_account_state
);
2609 if (astate
== NULL
) {
2610 return NT_STATUS_NO_MEMORY
;
2613 astate
->account_sid
= dom_sid_dup(astate
, r
->in
.sid
);
2614 if (astate
->account_sid
== NULL
) {
2615 talloc_free(astate
);
2616 return NT_STATUS_NO_MEMORY
;
2619 astate
->policy
= talloc_reference(astate
, state
);
2620 astate
->access_mask
= r
->in
.access_mask
;
2623 * For now we grant all requested access.
2625 * We will fail at the ldb layer later.
2627 if (astate
->access_mask
& SEC_FLAG_MAXIMUM_ALLOWED
) {
2628 astate
->access_mask
&= ~SEC_FLAG_MAXIMUM_ALLOWED
;
2629 astate
->access_mask
|= LSA_ACCOUNT_ALL_ACCESS
;
2631 se_map_generic(&astate
->access_mask
, &dcesrv_lsa_account_mapping
);
2633 DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2634 __func__
, dom_sid_string(mem_ctx
, astate
->account_sid
),
2635 (unsigned)r
->in
.access_mask
,
2636 (unsigned)astate
->access_mask
));
2638 ah
= dcesrv_handle_new(dce_call
->context
, LSA_HANDLE_ACCOUNT
);
2640 talloc_free(astate
);
2641 return NT_STATUS_NO_MEMORY
;
2644 ah
->data
= talloc_steal(ah
, astate
);
2646 *r
->out
.acct_handle
= ah
->wire_handle
;
2648 return NT_STATUS_OK
;
2653 lsa_EnumPrivsAccount
2655 static NTSTATUS
dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state
*dce_call
,
2656 TALLOC_CTX
*mem_ctx
,
2657 struct lsa_EnumPrivsAccount
*r
)
2659 struct dcesrv_handle
*h
;
2660 struct lsa_account_state
*astate
;
2663 struct ldb_message
**res
;
2664 const char * const attrs
[] = { "privilege", NULL
};
2665 struct ldb_message_element
*el
;
2667 struct lsa_PrivilegeSet
*privs
;
2669 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_ACCOUNT
);
2673 privs
= talloc(mem_ctx
, struct lsa_PrivilegeSet
);
2674 if (privs
== NULL
) {
2675 return NT_STATUS_NO_MEMORY
;
2681 *r
->out
.privs
= privs
;
2683 sidstr
= ldap_encode_ndr_dom_sid(mem_ctx
, astate
->account_sid
);
2684 if (sidstr
== NULL
) {
2685 return NT_STATUS_NO_MEMORY
;
2688 ret
= gendb_search(astate
->policy
->pdb
, mem_ctx
, NULL
, &res
, attrs
,
2689 "objectSid=%s", sidstr
);
2691 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2694 return NT_STATUS_OK
;
2697 el
= ldb_msg_find_element(res
[0], "privilege");
2698 if (el
== NULL
|| el
->num_values
== 0) {
2699 return NT_STATUS_OK
;
2702 privs
->set
= talloc_array(privs
,
2703 struct lsa_LUIDAttribute
, el
->num_values
);
2704 if (privs
->set
== NULL
) {
2705 return NT_STATUS_NO_MEMORY
;
2709 for (i
=0;i
<el
->num_values
;i
++) {
2710 int id
= sec_privilege_id((const char *)el
->values
[i
].data
);
2711 if (id
== SEC_PRIV_INVALID
) {
2712 /* Perhaps an account right, not a privilege */
2715 privs
->set
[j
].attribute
= 0;
2716 privs
->set
[j
].luid
.low
= id
;
2717 privs
->set
[j
].luid
.high
= 0;
2723 return NT_STATUS_OK
;
2727 lsa_EnumAccountRights
2729 static NTSTATUS
dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state
*dce_call
,
2730 TALLOC_CTX
*mem_ctx
,
2731 struct lsa_EnumAccountRights
*r
)
2733 struct dcesrv_handle
*h
;
2734 struct lsa_policy_state
*state
;
2737 struct ldb_message
**res
;
2738 const char * const attrs
[] = { "privilege", NULL
};
2740 struct ldb_message_element
*el
;
2742 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
2746 sidstr
= ldap_encode_ndr_dom_sid(mem_ctx
, r
->in
.sid
);
2747 if (sidstr
== NULL
) {
2748 return NT_STATUS_NO_MEMORY
;
2751 ret
= gendb_search(state
->pdb
, mem_ctx
, NULL
, &res
, attrs
,
2752 "(&(objectSid=%s)(privilege=*))", sidstr
);
2754 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
2757 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2758 dom_sid_string(mem_ctx
, r
->in
.sid
),
2759 ldb_errstring(state
->pdb
)));
2760 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2763 el
= ldb_msg_find_element(res
[0], "privilege");
2764 if (el
== NULL
|| el
->num_values
== 0) {
2765 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
2768 r
->out
.rights
->count
= el
->num_values
;
2769 r
->out
.rights
->names
= talloc_array(r
->out
.rights
,
2770 struct lsa_StringLarge
, r
->out
.rights
->count
);
2771 if (r
->out
.rights
->names
== NULL
) {
2772 return NT_STATUS_NO_MEMORY
;
2775 for (i
=0;i
<el
->num_values
;i
++) {
2776 r
->out
.rights
->names
[i
].string
= (const char *)el
->values
[i
].data
;
2779 return NT_STATUS_OK
;
2785 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2787 static NTSTATUS
dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state
*dce_call
,
2788 TALLOC_CTX
*mem_ctx
,
2789 struct lsa_policy_state
*state
,
2791 struct dom_sid
*sid
,
2792 const struct lsa_RightSet
*rights
)
2794 const char *sidstr
, *sidndrstr
;
2795 struct ldb_message
*msg
;
2796 struct ldb_message_element
*el
;
2799 struct lsa_EnumAccountRights r2
;
2802 if (security_session_user_level(dce_call
->conn
->auth_state
.session_info
, NULL
) <
2803 SECURITY_ADMINISTRATOR
) {
2804 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2805 return NT_STATUS_ACCESS_DENIED
;
2808 msg
= ldb_msg_new(mem_ctx
);
2810 return NT_STATUS_NO_MEMORY
;
2813 sidndrstr
= ldap_encode_ndr_dom_sid(msg
, sid
);
2814 if (sidndrstr
== NULL
) {
2816 return NT_STATUS_NO_MEMORY
;
2819 sidstr
= dom_sid_string(msg
, sid
);
2820 if (sidstr
== NULL
) {
2822 return NT_STATUS_NO_MEMORY
;
2825 dnstr
= talloc_asprintf(msg
, "sid=%s", sidstr
);
2826 if (dnstr
== NULL
) {
2828 return NT_STATUS_NO_MEMORY
;
2831 msg
->dn
= ldb_dn_new(msg
, state
->pdb
, dnstr
);
2832 if (msg
->dn
== NULL
) {
2834 return NT_STATUS_NO_MEMORY
;
2837 if (LDB_FLAG_MOD_TYPE(ldb_flag
) == LDB_FLAG_MOD_ADD
) {
2840 r2
.in
.handle
= &state
->handle
->wire_handle
;
2842 r2
.out
.rights
= talloc(mem_ctx
, struct lsa_RightSet
);
2844 status
= dcesrv_lsa_EnumAccountRights(dce_call
, mem_ctx
, &r2
);
2845 if (!NT_STATUS_IS_OK(status
)) {
2846 ZERO_STRUCTP(r2
.out
.rights
);
2850 for (i
=0;i
<rights
->count
;i
++) {
2851 if (sec_privilege_id(rights
->names
[i
].string
) == SEC_PRIV_INVALID
) {
2852 if (sec_right_bit(rights
->names
[i
].string
) == 0) {
2854 return NT_STATUS_NO_SUCH_PRIVILEGE
;
2858 return NT_STATUS_NO_SUCH_PRIVILEGE
;
2861 if (LDB_FLAG_MOD_TYPE(ldb_flag
) == LDB_FLAG_MOD_ADD
) {
2863 for (j
=0;j
<r2
.out
.rights
->count
;j
++) {
2864 if (strcasecmp_m(r2
.out
.rights
->names
[j
].string
,
2865 rights
->names
[i
].string
) == 0) {
2869 if (j
!= r2
.out
.rights
->count
) continue;
2872 ret
= ldb_msg_add_string(msg
, "privilege", rights
->names
[i
].string
);
2873 if (ret
!= LDB_SUCCESS
) {
2875 return NT_STATUS_NO_MEMORY
;
2879 el
= ldb_msg_find_element(msg
, "privilege");
2882 return NT_STATUS_OK
;
2885 el
->flags
= ldb_flag
;
2887 ret
= ldb_modify(state
->pdb
, msg
);
2888 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
2889 if (samdb_msg_add_dom_sid(state
->pdb
, msg
, msg
, "objectSid", sid
) != LDB_SUCCESS
) {
2891 return NT_STATUS_NO_MEMORY
;
2893 ldb_msg_add_string(msg
, "comment", "added via LSA");
2894 ret
= ldb_add(state
->pdb
, msg
);
2896 if (ret
!= LDB_SUCCESS
) {
2897 if (LDB_FLAG_MOD_TYPE(ldb_flag
) == LDB_FLAG_MOD_DELETE
&& ret
== LDB_ERR_NO_SUCH_ATTRIBUTE
) {
2899 return NT_STATUS_OK
;
2901 DEBUG(3, ("Could not %s attributes from %s: %s",
2902 LDB_FLAG_MOD_TYPE(ldb_flag
) == LDB_FLAG_MOD_DELETE
? "delete" : "add",
2903 ldb_dn_get_linearized(msg
->dn
), ldb_errstring(state
->pdb
)));
2905 return NT_STATUS_UNEXPECTED_IO_ERROR
;
2909 return NT_STATUS_OK
;
2913 lsa_AddPrivilegesToAccount
2915 static NTSTATUS
dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2916 struct lsa_AddPrivilegesToAccount
*r
)
2918 struct lsa_RightSet rights
;
2919 struct dcesrv_handle
*h
;
2920 struct lsa_account_state
*astate
;
2923 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_ACCOUNT
);
2927 rights
.count
= r
->in
.privs
->count
;
2928 rights
.names
= talloc_array(mem_ctx
, struct lsa_StringLarge
, rights
.count
);
2929 if (rights
.names
== NULL
) {
2930 return NT_STATUS_NO_MEMORY
;
2932 for (i
=0;i
<rights
.count
;i
++) {
2933 int id
= r
->in
.privs
->set
[i
].luid
.low
;
2934 if (r
->in
.privs
->set
[i
].luid
.high
) {
2935 return NT_STATUS_NO_SUCH_PRIVILEGE
;
2937 rights
.names
[i
].string
= sec_privilege_name(id
);
2938 if (rights
.names
[i
].string
== NULL
) {
2939 return NT_STATUS_NO_SUCH_PRIVILEGE
;
2943 return dcesrv_lsa_AddRemoveAccountRights(dce_call
, mem_ctx
, astate
->policy
,
2944 LDB_FLAG_MOD_ADD
, astate
->account_sid
,
2950 lsa_RemovePrivilegesFromAccount
2952 static NTSTATUS
dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2953 struct lsa_RemovePrivilegesFromAccount
*r
)
2955 struct lsa_RightSet
*rights
;
2956 struct dcesrv_handle
*h
;
2957 struct lsa_account_state
*astate
;
2960 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_ACCOUNT
);
2964 rights
= talloc(mem_ctx
, struct lsa_RightSet
);
2966 if (r
->in
.remove_all
== 1 &&
2967 r
->in
.privs
== NULL
) {
2968 struct lsa_EnumAccountRights r2
;
2971 r2
.in
.handle
= &astate
->policy
->handle
->wire_handle
;
2972 r2
.in
.sid
= astate
->account_sid
;
2973 r2
.out
.rights
= rights
;
2975 status
= dcesrv_lsa_EnumAccountRights(dce_call
, mem_ctx
, &r2
);
2976 if (!NT_STATUS_IS_OK(status
)) {
2980 return dcesrv_lsa_AddRemoveAccountRights(dce_call
, mem_ctx
, astate
->policy
,
2981 LDB_FLAG_MOD_DELETE
, astate
->account_sid
,
2985 if (r
->in
.remove_all
!= 0) {
2986 return NT_STATUS_INVALID_PARAMETER
;
2989 rights
->count
= r
->in
.privs
->count
;
2990 rights
->names
= talloc_array(mem_ctx
, struct lsa_StringLarge
, rights
->count
);
2991 if (rights
->names
== NULL
) {
2992 return NT_STATUS_NO_MEMORY
;
2994 for (i
=0;i
<rights
->count
;i
++) {
2995 int id
= r
->in
.privs
->set
[i
].luid
.low
;
2996 if (r
->in
.privs
->set
[i
].luid
.high
) {
2997 return NT_STATUS_NO_SUCH_PRIVILEGE
;
2999 rights
->names
[i
].string
= sec_privilege_name(id
);
3000 if (rights
->names
[i
].string
== NULL
) {
3001 return NT_STATUS_NO_SUCH_PRIVILEGE
;
3005 return dcesrv_lsa_AddRemoveAccountRights(dce_call
, mem_ctx
, astate
->policy
,
3006 LDB_FLAG_MOD_DELETE
, astate
->account_sid
,
3012 lsa_GetQuotasForAccount
3014 static NTSTATUS
dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3015 struct lsa_GetQuotasForAccount
*r
)
3017 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3022 lsa_SetQuotasForAccount
3024 static NTSTATUS
dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3025 struct lsa_SetQuotasForAccount
*r
)
3027 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3032 lsa_GetSystemAccessAccount
3034 static NTSTATUS
dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3035 struct lsa_GetSystemAccessAccount
*r
)
3037 struct dcesrv_handle
*h
;
3038 struct lsa_account_state
*astate
;
3041 struct ldb_message
**res
;
3042 const char * const attrs
[] = { "privilege", NULL
};
3043 struct ldb_message_element
*el
;
3046 *(r
->out
.access_mask
) = 0x00000000;
3048 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_ACCOUNT
);
3052 sidstr
= ldap_encode_ndr_dom_sid(mem_ctx
, astate
->account_sid
);
3053 if (sidstr
== NULL
) {
3054 return NT_STATUS_NO_MEMORY
;
3057 ret
= gendb_search(astate
->policy
->pdb
, mem_ctx
, NULL
, &res
, attrs
,
3058 "objectSid=%s", sidstr
);
3060 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
3063 return NT_STATUS_OK
;
3066 el
= ldb_msg_find_element(res
[0], "privilege");
3067 if (el
== NULL
|| el
->num_values
== 0) {
3068 return NT_STATUS_OK
;
3071 for (i
=0;i
<el
->num_values
;i
++) {
3072 uint32_t right_bit
= sec_right_bit((const char *)el
->values
[i
].data
);
3073 if (right_bit
== 0) {
3074 /* Perhaps an privilege, not a right */
3077 *(r
->out
.access_mask
) |= right_bit
;
3080 return NT_STATUS_OK
;
3085 lsa_SetSystemAccessAccount
3087 static NTSTATUS
dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3088 struct lsa_SetSystemAccessAccount
*r
)
3090 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3097 static NTSTATUS
dcesrv_lsa_CreateSecret(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3098 struct lsa_CreateSecret
*r
)
3100 struct dcesrv_handle
*policy_handle
;
3101 struct lsa_policy_state
*policy_state
;
3102 struct lsa_secret_state
*secret_state
;
3103 struct dcesrv_handle
*handle
;
3104 struct ldb_message
**msgs
, *msg
;
3105 const char *attrs
[] = {
3113 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3114 ZERO_STRUCTP(r
->out
.sec_handle
);
3116 switch (security_session_user_level(dce_call
->conn
->auth_state
.session_info
, NULL
))
3118 case SECURITY_SYSTEM
:
3119 case SECURITY_ADMINISTRATOR
:
3122 /* Users and annonymous are not allowed create secrets */
3123 return NT_STATUS_ACCESS_DENIED
;
3126 policy_state
= policy_handle
->data
;
3128 if (!r
->in
.name
.string
) {
3129 return NT_STATUS_INVALID_PARAMETER
;
3132 secret_state
= talloc(mem_ctx
, struct lsa_secret_state
);
3133 NT_STATUS_HAVE_NO_MEMORY(secret_state
);
3134 secret_state
->policy
= policy_state
;
3136 msg
= ldb_msg_new(mem_ctx
);
3138 return NT_STATUS_NO_MEMORY
;
3141 if (strncmp("G$", r
->in
.name
.string
, 2) == 0) {
3144 secret_state
->global
= true;
3146 name
= &r
->in
.name
.string
[2];
3147 if (strlen(name
) == 0) {
3148 return NT_STATUS_INVALID_PARAMETER
;
3151 name2
= talloc_asprintf(mem_ctx
, "%s Secret",
3152 ldb_binary_encode_string(mem_ctx
, name
));
3153 NT_STATUS_HAVE_NO_MEMORY(name2
);
3155 /* We need to connect to the database as system, as this is one
3156 * of the rare RPC calls that must read the secrets (and this
3157 * is denied otherwise) */
3158 secret_state
->sam_ldb
= talloc_reference(secret_state
,
3159 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));
3160 NT_STATUS_HAVE_NO_MEMORY(secret_state
->sam_ldb
);
3162 /* search for the secret record */
3163 ret
= gendb_search(secret_state
->sam_ldb
,
3164 mem_ctx
, policy_state
->system_dn
, &msgs
, attrs
,
3165 "(&(cn=%s)(objectclass=secret))",
3168 return NT_STATUS_OBJECT_NAME_COLLISION
;
3172 DEBUG(0,("Failure searching for CN=%s: %s\n",
3173 name2
, ldb_errstring(secret_state
->sam_ldb
)));
3174 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
3177 msg
->dn
= ldb_dn_copy(mem_ctx
, policy_state
->system_dn
);
3178 NT_STATUS_HAVE_NO_MEMORY(msg
->dn
);
3179 if (!ldb_dn_add_child_fmt(msg
->dn
, "cn=%s", name2
)) {
3180 return NT_STATUS_NO_MEMORY
;
3183 ret
= ldb_msg_add_string(msg
, "cn", name2
);
3184 if (ret
!= LDB_SUCCESS
) return NT_STATUS_NO_MEMORY
;
3186 secret_state
->global
= false;
3188 name
= r
->in
.name
.string
;
3189 if (strlen(name
) == 0) {
3190 return NT_STATUS_INVALID_PARAMETER
;
3193 secret_state
->sam_ldb
= talloc_reference(secret_state
,
3194 secrets_db_connect(mem_ctx
, dce_call
->conn
->dce_ctx
->lp_ctx
));
3195 NT_STATUS_HAVE_NO_MEMORY(secret_state
->sam_ldb
);
3197 /* search for the secret record */
3198 ret
= gendb_search(secret_state
->sam_ldb
, mem_ctx
,
3199 ldb_dn_new(mem_ctx
, secret_state
->sam_ldb
, "cn=LSA Secrets"),
3201 "(&(cn=%s)(objectclass=secret))",
3202 ldb_binary_encode_string(mem_ctx
, name
));
3204 return NT_STATUS_OBJECT_NAME_COLLISION
;
3208 DEBUG(0,("Failure searching for CN=%s: %s\n",
3209 name
, ldb_errstring(secret_state
->sam_ldb
)));
3210 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
3213 msg
->dn
= ldb_dn_new_fmt(mem_ctx
, secret_state
->sam_ldb
,
3214 "cn=%s,cn=LSA Secrets", name
);
3215 NT_STATUS_HAVE_NO_MEMORY(msg
->dn
);
3216 ret
= ldb_msg_add_string(msg
, "cn", name
);
3217 if (ret
!= LDB_SUCCESS
) return NT_STATUS_NO_MEMORY
;
3220 ret
= ldb_msg_add_string(msg
, "objectClass", "secret");
3221 if (ret
!= LDB_SUCCESS
) return NT_STATUS_NO_MEMORY
;
3223 secret_state
->secret_dn
= talloc_reference(secret_state
, msg
->dn
);
3224 NT_STATUS_HAVE_NO_MEMORY(secret_state
->secret_dn
);
3226 /* create the secret */
3227 ret
= ldb_add(secret_state
->sam_ldb
, msg
);
3228 if (ret
!= LDB_SUCCESS
) {
3229 DEBUG(0,("Failed to create secret record %s: %s\n",
3230 ldb_dn_get_linearized(msg
->dn
),
3231 ldb_errstring(secret_state
->sam_ldb
)));
3232 return NT_STATUS_ACCESS_DENIED
;
3235 handle
= dcesrv_handle_new(dce_call
->context
, LSA_HANDLE_SECRET
);
3236 NT_STATUS_HAVE_NO_MEMORY(handle
);
3238 handle
->data
= talloc_steal(handle
, secret_state
);
3240 secret_state
->access_mask
= r
->in
.access_mask
;
3241 secret_state
->policy
= talloc_reference(secret_state
, policy_state
);
3242 NT_STATUS_HAVE_NO_MEMORY(secret_state
->policy
);
3244 *r
->out
.sec_handle
= handle
->wire_handle
;
3246 return NT_STATUS_OK
;
3253 static NTSTATUS
dcesrv_lsa_OpenSecret(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3254 struct lsa_OpenSecret
*r
)
3256 struct dcesrv_handle
*policy_handle
;
3258 struct lsa_policy_state
*policy_state
;
3259 struct lsa_secret_state
*secret_state
;
3260 struct dcesrv_handle
*handle
;
3261 struct ldb_message
**msgs
;
3262 const char *attrs
[] = {
3270 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3271 ZERO_STRUCTP(r
->out
.sec_handle
);
3272 policy_state
= policy_handle
->data
;
3274 if (!r
->in
.name
.string
) {
3275 return NT_STATUS_INVALID_PARAMETER
;
3278 switch (security_session_user_level(dce_call
->conn
->auth_state
.session_info
, NULL
))
3280 case SECURITY_SYSTEM
:
3281 case SECURITY_ADMINISTRATOR
:
3284 /* Users and annonymous are not allowed to access secrets */
3285 return NT_STATUS_ACCESS_DENIED
;
3288 secret_state
= talloc(mem_ctx
, struct lsa_secret_state
);
3289 if (!secret_state
) {
3290 return NT_STATUS_NO_MEMORY
;
3292 secret_state
->policy
= policy_state
;
3294 if (strncmp("G$", r
->in
.name
.string
, 2) == 0) {
3295 name
= &r
->in
.name
.string
[2];
3296 /* 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) */
3297 secret_state
->sam_ldb
= talloc_reference(secret_state
,
3298 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));
3299 secret_state
->global
= true;
3301 if (strlen(name
) < 1) {
3302 return NT_STATUS_INVALID_PARAMETER
;
3305 /* search for the secret record */
3306 ret
= gendb_search(secret_state
->sam_ldb
,
3307 mem_ctx
, policy_state
->system_dn
, &msgs
, attrs
,
3308 "(&(cn=%s Secret)(objectclass=secret))",
3309 ldb_binary_encode_string(mem_ctx
, name
));
3311 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3315 DEBUG(0,("Found %d records matching DN %s\n", ret
,
3316 ldb_dn_get_linearized(policy_state
->system_dn
)));
3317 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
3320 secret_state
->global
= false;
3321 secret_state
->sam_ldb
= talloc_reference(secret_state
,
3322 secrets_db_connect(mem_ctx
, dce_call
->conn
->dce_ctx
->lp_ctx
));
3324 name
= r
->in
.name
.string
;
3325 if (strlen(name
) < 1) {
3326 return NT_STATUS_INVALID_PARAMETER
;
3329 /* search for the secret record */
3330 ret
= gendb_search(secret_state
->sam_ldb
, mem_ctx
,
3331 ldb_dn_new(mem_ctx
, secret_state
->sam_ldb
, "cn=LSA Secrets"),
3333 "(&(cn=%s)(objectclass=secret))",
3334 ldb_binary_encode_string(mem_ctx
, name
));
3336 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3340 DEBUG(0,("Found %d records matching CN=%s\n",
3341 ret
, ldb_binary_encode_string(mem_ctx
, name
)));
3342 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
3346 secret_state
->secret_dn
= talloc_reference(secret_state
, msgs
[0]->dn
);
3348 handle
= dcesrv_handle_new(dce_call
->context
, LSA_HANDLE_SECRET
);
3350 return NT_STATUS_NO_MEMORY
;
3353 handle
->data
= talloc_steal(handle
, secret_state
);
3355 secret_state
->access_mask
= r
->in
.access_mask
;
3356 secret_state
->policy
= talloc_reference(secret_state
, policy_state
);
3358 *r
->out
.sec_handle
= handle
->wire_handle
;
3360 return NT_STATUS_OK
;
3367 static NTSTATUS
dcesrv_lsa_SetSecret(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3368 struct lsa_SetSecret
*r
)
3371 struct dcesrv_handle
*h
;
3372 struct lsa_secret_state
*secret_state
;
3373 struct ldb_message
*msg
;
3374 DATA_BLOB session_key
;
3375 DATA_BLOB crypt_secret
, secret
;
3378 NTSTATUS status
= NT_STATUS_OK
;
3380 struct timeval now
= timeval_current();
3381 NTTIME nt_now
= timeval_to_nttime(&now
);
3383 DCESRV_PULL_HANDLE(h
, r
->in
.sec_handle
, LSA_HANDLE_SECRET
);
3385 secret_state
= h
->data
;
3387 msg
= ldb_msg_new(mem_ctx
);
3389 return NT_STATUS_NO_MEMORY
;
3392 msg
->dn
= talloc_reference(mem_ctx
, secret_state
->secret_dn
);
3394 return NT_STATUS_NO_MEMORY
;
3396 status
= dcesrv_fetch_session_key(dce_call
->conn
, &session_key
);
3397 if (!NT_STATUS_IS_OK(status
)) {
3401 if (r
->in
.old_val
) {
3403 crypt_secret
.data
= r
->in
.old_val
->data
;
3404 crypt_secret
.length
= r
->in
.old_val
->size
;
3406 status
= sess_decrypt_blob(mem_ctx
, &crypt_secret
, &session_key
, &secret
);
3407 if (!NT_STATUS_IS_OK(status
)) {
3411 val
.data
= secret
.data
;
3412 val
.length
= secret
.length
;
3415 if (ldb_msg_add_value(msg
, "priorValue", &val
, NULL
) != LDB_SUCCESS
) {
3416 return NT_STATUS_NO_MEMORY
;
3419 /* set old value mtime */
3420 if (samdb_msg_add_uint64(secret_state
->sam_ldb
,
3421 mem_ctx
, msg
, "priorSetTime", nt_now
) != LDB_SUCCESS
) {
3422 return NT_STATUS_NO_MEMORY
;
3426 /* If the old value is not set, then migrate the
3427 * current value to the old value */
3428 const struct ldb_val
*old_val
;
3429 NTTIME last_set_time
;
3430 struct ldb_message
**res
;
3431 const char *attrs
[] = {
3437 /* search for the secret record */
3438 ret
= gendb_search_dn(secret_state
->sam_ldb
,mem_ctx
,
3439 secret_state
->secret_dn
, &res
, attrs
);
3441 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3445 DEBUG(0,("Found %d records matching dn=%s\n", ret
,
3446 ldb_dn_get_linearized(secret_state
->secret_dn
)));
3447 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
3450 old_val
= ldb_msg_find_ldb_val(res
[0], "currentValue");
3451 last_set_time
= ldb_msg_find_attr_as_uint64(res
[0], "lastSetTime", 0);
3455 if (ldb_msg_add_value(msg
, "priorValue",
3456 old_val
, NULL
) != LDB_SUCCESS
) {
3457 return NT_STATUS_NO_MEMORY
;
3460 if (samdb_msg_add_delete(secret_state
->sam_ldb
,
3461 mem_ctx
, msg
, "priorValue") != LDB_SUCCESS
) {
3462 return NT_STATUS_NO_MEMORY
;
3466 /* set old value mtime */
3467 if (ldb_msg_find_ldb_val(res
[0], "lastSetTime")) {
3468 if (samdb_msg_add_uint64(secret_state
->sam_ldb
,
3469 mem_ctx
, msg
, "priorSetTime", last_set_time
) != LDB_SUCCESS
) {
3470 return NT_STATUS_NO_MEMORY
;
3473 if (samdb_msg_add_uint64(secret_state
->sam_ldb
,
3474 mem_ctx
, msg
, "priorSetTime", nt_now
) != LDB_SUCCESS
) {
3475 return NT_STATUS_NO_MEMORY
;
3480 if (r
->in
.new_val
) {
3482 crypt_secret
.data
= r
->in
.new_val
->data
;
3483 crypt_secret
.length
= r
->in
.new_val
->size
;
3485 status
= sess_decrypt_blob(mem_ctx
, &crypt_secret
, &session_key
, &secret
);
3486 if (!NT_STATUS_IS_OK(status
)) {
3490 val
.data
= secret
.data
;
3491 val
.length
= secret
.length
;
3494 if (ldb_msg_add_value(msg
, "currentValue", &val
, NULL
) != LDB_SUCCESS
) {
3495 return NT_STATUS_NO_MEMORY
;
3498 /* set new value mtime */
3499 if (samdb_msg_add_uint64(secret_state
->sam_ldb
,
3500 mem_ctx
, msg
, "lastSetTime", nt_now
) != LDB_SUCCESS
) {
3501 return NT_STATUS_NO_MEMORY
;
3504 /* NULL out the NEW value */
3505 if (samdb_msg_add_uint64(secret_state
->sam_ldb
,
3506 mem_ctx
, msg
, "lastSetTime", nt_now
) != LDB_SUCCESS
) {
3507 return NT_STATUS_NO_MEMORY
;
3509 if (samdb_msg_add_delete(secret_state
->sam_ldb
,
3510 mem_ctx
, msg
, "currentValue") != LDB_SUCCESS
) {
3511 return NT_STATUS_NO_MEMORY
;
3515 /* modify the samdb record */
3516 ret
= dsdb_replace(secret_state
->sam_ldb
, msg
, 0);
3517 if (ret
!= LDB_SUCCESS
) {
3518 return dsdb_ldb_err_to_ntstatus(ret
);
3521 return NT_STATUS_OK
;
3528 static NTSTATUS
dcesrv_lsa_QuerySecret(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3529 struct lsa_QuerySecret
*r
)
3531 struct dcesrv_handle
*h
;
3532 struct lsa_secret_state
*secret_state
;
3533 struct ldb_message
*msg
;
3534 DATA_BLOB session_key
;
3535 DATA_BLOB crypt_secret
, secret
;
3537 struct ldb_message
**res
;
3538 const char *attrs
[] = {
3548 DCESRV_PULL_HANDLE(h
, r
->in
.sec_handle
, LSA_HANDLE_SECRET
);
3550 /* Ensure user is permitted to read this... */
3551 switch (security_session_user_level(dce_call
->conn
->auth_state
.session_info
, NULL
))
3553 case SECURITY_SYSTEM
:
3554 case SECURITY_ADMINISTRATOR
:
3557 /* Users and annonymous are not allowed to read secrets */
3558 return NT_STATUS_ACCESS_DENIED
;
3561 secret_state
= h
->data
;
3563 /* pull all the user attributes */
3564 ret
= gendb_search_dn(secret_state
->sam_ldb
, mem_ctx
,
3565 secret_state
->secret_dn
, &res
, attrs
);
3567 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
3571 nt_status
= dcesrv_fetch_session_key(dce_call
->conn
, &session_key
);
3572 if (!NT_STATUS_IS_OK(nt_status
)) {
3576 if (r
->in
.old_val
) {
3577 const struct ldb_val
*prior_val
;
3578 r
->out
.old_val
= talloc_zero(mem_ctx
, struct lsa_DATA_BUF_PTR
);
3579 if (!r
->out
.old_val
) {
3580 return NT_STATUS_NO_MEMORY
;
3582 prior_val
= ldb_msg_find_ldb_val(msg
, "priorValue");
3584 if (prior_val
&& prior_val
->length
) {
3585 secret
.data
= prior_val
->data
;
3586 secret
.length
= prior_val
->length
;
3589 crypt_secret
= sess_encrypt_blob(mem_ctx
, &secret
, &session_key
);
3590 if (!crypt_secret
.length
) {
3591 return NT_STATUS_NO_MEMORY
;
3593 r
->out
.old_val
->buf
= talloc(mem_ctx
, struct lsa_DATA_BUF
);
3594 if (!r
->out
.old_val
->buf
) {
3595 return NT_STATUS_NO_MEMORY
;
3597 r
->out
.old_val
->buf
->size
= crypt_secret
.length
;
3598 r
->out
.old_val
->buf
->length
= crypt_secret
.length
;
3599 r
->out
.old_val
->buf
->data
= crypt_secret
.data
;
3603 if (r
->in
.old_mtime
) {
3604 r
->out
.old_mtime
= talloc(mem_ctx
, NTTIME
);
3605 if (!r
->out
.old_mtime
) {
3606 return NT_STATUS_NO_MEMORY
;
3608 *r
->out
.old_mtime
= ldb_msg_find_attr_as_uint64(msg
, "priorSetTime", 0);
3611 if (r
->in
.new_val
) {
3612 const struct ldb_val
*new_val
;
3613 r
->out
.new_val
= talloc_zero(mem_ctx
, struct lsa_DATA_BUF_PTR
);
3614 if (!r
->out
.new_val
) {
3615 return NT_STATUS_NO_MEMORY
;
3618 new_val
= ldb_msg_find_ldb_val(msg
, "currentValue");
3620 if (new_val
&& new_val
->length
) {
3621 secret
.data
= new_val
->data
;
3622 secret
.length
= new_val
->length
;
3625 crypt_secret
= sess_encrypt_blob(mem_ctx
, &secret
, &session_key
);
3626 if (!crypt_secret
.length
) {
3627 return NT_STATUS_NO_MEMORY
;
3629 r
->out
.new_val
->buf
= talloc(mem_ctx
, struct lsa_DATA_BUF
);
3630 if (!r
->out
.new_val
->buf
) {
3631 return NT_STATUS_NO_MEMORY
;
3633 r
->out
.new_val
->buf
->length
= crypt_secret
.length
;
3634 r
->out
.new_val
->buf
->size
= crypt_secret
.length
;
3635 r
->out
.new_val
->buf
->data
= crypt_secret
.data
;
3639 if (r
->in
.new_mtime
) {
3640 r
->out
.new_mtime
= talloc(mem_ctx
, NTTIME
);
3641 if (!r
->out
.new_mtime
) {
3642 return NT_STATUS_NO_MEMORY
;
3644 *r
->out
.new_mtime
= ldb_msg_find_attr_as_uint64(msg
, "lastSetTime", 0);
3647 return NT_STATUS_OK
;
3654 static NTSTATUS
dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state
*dce_call
,
3655 TALLOC_CTX
*mem_ctx
,
3656 struct lsa_LookupPrivValue
*r
)
3658 struct dcesrv_handle
*h
;
3661 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3663 id
= sec_privilege_id(r
->in
.name
->string
);
3664 if (id
== SEC_PRIV_INVALID
) {
3665 return NT_STATUS_NO_SUCH_PRIVILEGE
;
3668 r
->out
.luid
->low
= id
;
3669 r
->out
.luid
->high
= 0;
3671 return NT_STATUS_OK
;
3678 static NTSTATUS
dcesrv_lsa_LookupPrivName(struct dcesrv_call_state
*dce_call
,
3679 TALLOC_CTX
*mem_ctx
,
3680 struct lsa_LookupPrivName
*r
)
3682 struct dcesrv_handle
*h
;
3683 struct lsa_StringLarge
*name
;
3684 const char *privname
;
3686 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3688 if (r
->in
.luid
->high
!= 0) {
3689 return NT_STATUS_NO_SUCH_PRIVILEGE
;
3692 privname
= sec_privilege_name(r
->in
.luid
->low
);
3693 if (privname
== NULL
) {
3694 return NT_STATUS_NO_SUCH_PRIVILEGE
;
3697 name
= talloc(mem_ctx
, struct lsa_StringLarge
);
3699 return NT_STATUS_NO_MEMORY
;
3702 name
->string
= privname
;
3704 *r
->out
.name
= name
;
3706 return NT_STATUS_OK
;
3711 lsa_LookupPrivDisplayName
3713 static NTSTATUS
dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state
*dce_call
,
3714 TALLOC_CTX
*mem_ctx
,
3715 struct lsa_LookupPrivDisplayName
*r
)
3717 struct dcesrv_handle
*h
;
3718 struct lsa_StringLarge
*disp_name
= NULL
;
3719 enum sec_privilege id
;
3721 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3723 id
= sec_privilege_id(r
->in
.name
->string
);
3724 if (id
== SEC_PRIV_INVALID
) {
3725 return NT_STATUS_NO_SUCH_PRIVILEGE
;
3728 disp_name
= talloc(mem_ctx
, struct lsa_StringLarge
);
3729 if (disp_name
== NULL
) {
3730 return NT_STATUS_NO_MEMORY
;
3733 disp_name
->string
= sec_privilege_display_name(id
, &r
->in
.language_id
);
3734 if (disp_name
->string
== NULL
) {
3735 return NT_STATUS_INTERNAL_ERROR
;
3738 *r
->out
.disp_name
= disp_name
;
3739 *r
->out
.returned_language_id
= 0;
3741 return NT_STATUS_OK
;
3746 lsa_EnumAccountsWithUserRight
3748 static NTSTATUS
dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state
*dce_call
,
3749 TALLOC_CTX
*mem_ctx
,
3750 struct lsa_EnumAccountsWithUserRight
*r
)
3752 struct dcesrv_handle
*h
;
3753 struct lsa_policy_state
*state
;
3755 struct ldb_message
**res
;
3756 const char * const attrs
[] = { "objectSid", NULL
};
3757 const char *privname
;
3759 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3763 if (r
->in
.name
== NULL
) {
3764 return NT_STATUS_NO_SUCH_PRIVILEGE
;
3767 privname
= r
->in
.name
->string
;
3768 if (sec_privilege_id(privname
) == SEC_PRIV_INVALID
&& sec_right_bit(privname
) == 0) {
3769 return NT_STATUS_NO_SUCH_PRIVILEGE
;
3772 ret
= gendb_search(state
->pdb
, mem_ctx
, NULL
, &res
, attrs
,
3773 "privilege=%s", privname
);
3775 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
3778 return NT_STATUS_NO_MORE_ENTRIES
;
3781 r
->out
.sids
->sids
= talloc_array(r
->out
.sids
, struct lsa_SidPtr
, ret
);
3782 if (r
->out
.sids
->sids
== NULL
) {
3783 return NT_STATUS_NO_MEMORY
;
3785 for (i
=0;i
<ret
;i
++) {
3786 r
->out
.sids
->sids
[i
].sid
= samdb_result_dom_sid(r
->out
.sids
->sids
,
3787 res
[i
], "objectSid");
3788 NT_STATUS_HAVE_NO_MEMORY(r
->out
.sids
->sids
[i
].sid
);
3790 r
->out
.sids
->num_sids
= ret
;
3792 return NT_STATUS_OK
;
3797 lsa_AddAccountRights
3799 static NTSTATUS
dcesrv_lsa_AddAccountRights(struct dcesrv_call_state
*dce_call
,
3800 TALLOC_CTX
*mem_ctx
,
3801 struct lsa_AddAccountRights
*r
)
3803 struct dcesrv_handle
*h
;
3804 struct lsa_policy_state
*state
;
3806 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3810 return dcesrv_lsa_AddRemoveAccountRights(dce_call
, mem_ctx
, state
,
3812 r
->in
.sid
, r
->in
.rights
);
3817 lsa_RemoveAccountRights
3819 static NTSTATUS
dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state
*dce_call
,
3820 TALLOC_CTX
*mem_ctx
,
3821 struct lsa_RemoveAccountRights
*r
)
3823 struct dcesrv_handle
*h
;
3824 struct lsa_policy_state
*state
;
3826 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3830 return dcesrv_lsa_AddRemoveAccountRights(dce_call
, mem_ctx
, state
,
3831 LDB_FLAG_MOD_DELETE
,
3832 r
->in
.sid
, r
->in
.rights
);
3837 lsa_StorePrivateData
3839 static NTSTATUS
dcesrv_lsa_StorePrivateData(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3840 struct lsa_StorePrivateData
*r
)
3842 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3847 lsa_RetrievePrivateData
3849 static NTSTATUS
dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3850 struct lsa_RetrievePrivateData
*r
)
3852 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3859 static NTSTATUS
dcesrv_lsa_GetUserName(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3860 struct lsa_GetUserName
*r
)
3862 enum dcerpc_transport_t transport
=
3863 dcerpc_binding_get_transport(dce_call
->conn
->endpoint
->ep_description
);
3864 NTSTATUS status
= NT_STATUS_OK
;
3865 const char *account_name
;
3866 const char *authority_name
;
3867 struct lsa_String
*_account_name
;
3868 struct lsa_String
*_authority_name
= NULL
;
3870 if (transport
!= NCACN_NP
&& transport
!= NCALRPC
) {
3871 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED
);
3874 /* this is what w2k3 does */
3875 r
->out
.account_name
= r
->in
.account_name
;
3876 r
->out
.authority_name
= r
->in
.authority_name
;
3878 if (r
->in
.account_name
3879 && *r
->in
.account_name
3880 /* && *(*r->in.account_name)->string */
3882 return NT_STATUS_INVALID_PARAMETER
;
3885 if (r
->in
.authority_name
3886 && *r
->in
.authority_name
3887 /* && *(*r->in.authority_name)->string */
3889 return NT_STATUS_INVALID_PARAMETER
;
3892 account_name
= talloc_reference(mem_ctx
, dce_call
->conn
->auth_state
.session_info
->info
->account_name
);
3893 authority_name
= talloc_reference(mem_ctx
, dce_call
->conn
->auth_state
.session_info
->info
->domain_name
);
3895 _account_name
= talloc(mem_ctx
, struct lsa_String
);
3896 NT_STATUS_HAVE_NO_MEMORY(_account_name
);
3897 _account_name
->string
= account_name
;
3899 if (r
->in
.authority_name
) {
3900 _authority_name
= talloc(mem_ctx
, struct lsa_String
);
3901 NT_STATUS_HAVE_NO_MEMORY(_authority_name
);
3902 _authority_name
->string
= authority_name
;
3905 *r
->out
.account_name
= _account_name
;
3906 if (r
->out
.authority_name
) {
3907 *r
->out
.authority_name
= _authority_name
;
3916 static NTSTATUS
dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state
*dce_call
,
3917 TALLOC_CTX
*mem_ctx
,
3918 struct lsa_SetInfoPolicy2
*r
)
3920 /* need to support these */
3921 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3924 static void kdc_get_policy(struct loadparm_context
*lp_ctx
,
3925 struct smb_krb5_context
*smb_krb5_context
,
3926 struct lsa_DomainInfoKerberos
*k
)
3928 time_t svc_tkt_lifetime
;
3929 time_t usr_tkt_lifetime
;
3930 time_t renewal_lifetime
;
3932 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
3934 /* Our KDC always re-validates the client */
3935 k
->authentication_options
= LSA_POLICY_KERBEROS_VALIDATE_CLIENT
;
3937 lpcfg_default_kdc_policy(lp_ctx
, &svc_tkt_lifetime
,
3938 &usr_tkt_lifetime
, &renewal_lifetime
);
3940 unix_to_nt_time(&k
->service_tkt_lifetime
, svc_tkt_lifetime
);
3941 unix_to_nt_time(&k
->user_tkt_lifetime
, usr_tkt_lifetime
);
3942 unix_to_nt_time(&k
->user_tkt_renewaltime
, renewal_lifetime
);
3943 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
3944 However in the parent function we basically just did a full
3945 krb5_context init with the only purpose of getting a global
3946 config option (the max skew), it would probably make more sense
3947 to have a lp_ or ldb global option as the samba default */
3948 if (smb_krb5_context
) {
3949 unix_to_nt_time(&k
->clock_skew
,
3950 krb5_get_max_time_skew(smb_krb5_context
->krb5_context
));
3956 lsa_QueryDomainInformationPolicy
3958 static NTSTATUS
dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state
*dce_call
,
3959 TALLOC_CTX
*mem_ctx
,
3960 struct lsa_QueryDomainInformationPolicy
*r
)
3962 union lsa_DomainInformationPolicy
*info
;
3964 info
= talloc_zero(r
->out
.info
, union lsa_DomainInformationPolicy
);
3966 return NT_STATUS_NO_MEMORY
;
3969 switch (r
->in
.level
) {
3970 case LSA_DOMAIN_INFO_POLICY_EFS
:
3972 *r
->out
.info
= NULL
;
3973 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3974 case LSA_DOMAIN_INFO_POLICY_KERBEROS
:
3976 struct lsa_DomainInfoKerberos
*k
= &info
->kerberos_info
;
3977 struct smb_krb5_context
*smb_krb5_context
;
3978 int ret
= smb_krb5_init_context(mem_ctx
,
3979 dce_call
->conn
->dce_ctx
->lp_ctx
,
3983 *r
->out
.info
= NULL
;
3984 return NT_STATUS_INTERNAL_ERROR
;
3986 kdc_get_policy(dce_call
->conn
->dce_ctx
->lp_ctx
,
3989 talloc_free(smb_krb5_context
);
3990 *r
->out
.info
= info
;
3991 return NT_STATUS_OK
;
3995 *r
->out
.info
= NULL
;
3996 return NT_STATUS_INVALID_INFO_CLASS
;
4001 lsa_SetDomInfoPolicy
4003 static NTSTATUS
dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state
*dce_call
,
4004 TALLOC_CTX
*mem_ctx
,
4005 struct lsa_SetDomainInformationPolicy
*r
)
4007 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4013 static NTSTATUS
dcesrv_lsa_TestCall(struct dcesrv_call_state
*dce_call
,
4014 TALLOC_CTX
*mem_ctx
,
4015 struct lsa_TestCall
*r
)
4017 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4023 static NTSTATUS
dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4024 struct lsa_CREDRWRITE
*r
)
4026 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4033 static NTSTATUS
dcesrv_lsa_CREDRREAD(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4034 struct lsa_CREDRREAD
*r
)
4036 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4043 static NTSTATUS
dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4044 struct lsa_CREDRENUMERATE
*r
)
4046 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4051 lsa_CREDRWRITEDOMAINCREDENTIALS
4053 static NTSTATUS
dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4054 struct lsa_CREDRWRITEDOMAINCREDENTIALS
*r
)
4056 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4061 lsa_CREDRREADDOMAINCREDENTIALS
4063 static NTSTATUS
dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4064 struct lsa_CREDRREADDOMAINCREDENTIALS
*r
)
4066 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4073 static NTSTATUS
dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4074 struct lsa_CREDRDELETE
*r
)
4076 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4081 lsa_CREDRGETTARGETINFO
4083 static NTSTATUS
dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4084 struct lsa_CREDRGETTARGETINFO
*r
)
4086 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4091 lsa_CREDRPROFILELOADED
4093 static NTSTATUS
dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4094 struct lsa_CREDRPROFILELOADED
*r
)
4096 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4101 lsa_CREDRGETSESSIONTYPES
4103 static NTSTATUS
dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4104 struct lsa_CREDRGETSESSIONTYPES
*r
)
4106 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4111 lsa_LSARREGISTERAUDITEVENT
4113 static NTSTATUS
dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4114 struct lsa_LSARREGISTERAUDITEVENT
*r
)
4116 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4121 lsa_LSARGENAUDITEVENT
4123 static NTSTATUS
dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4124 struct lsa_LSARGENAUDITEVENT
*r
)
4126 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4131 lsa_LSARUNREGISTERAUDITEVENT
4133 static NTSTATUS
dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4134 struct lsa_LSARUNREGISTERAUDITEVENT
*r
)
4136 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4141 lsa_lsaRQueryForestTrustInformation
4143 static NTSTATUS
dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4144 struct lsa_lsaRQueryForestTrustInformation
*r
)
4146 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4149 #define DNS_CMP_MATCH 0
4150 #define DNS_CMP_FIRST_IS_CHILD 1
4151 #define DNS_CMP_SECOND_IS_CHILD 2
4152 #define DNS_CMP_NO_MATCH 3
4154 /* this function assumes names are well formed DNS names.
4155 * it doesn't validate them */
4156 static int dns_cmp(const char *s1
, size_t l1
,
4157 const char *s2
, size_t l2
)
4159 const char *p1
, *p2
;
4164 if (strcasecmp_m(s1
, s2
) == 0) {
4165 return DNS_CMP_MATCH
;
4167 return DNS_CMP_NO_MATCH
;
4175 cret
= DNS_CMP_FIRST_IS_CHILD
;
4181 cret
= DNS_CMP_SECOND_IS_CHILD
;
4184 if (p1
[t1
- t2
- 1] != '.') {
4185 return DNS_CMP_NO_MATCH
;
4188 if (strcasecmp_m(&p1
[t1
- t2
], p2
) == 0) {
4192 return DNS_CMP_NO_MATCH
;
4195 /* decode all TDOs forest trust info blobs */
4196 static NTSTATUS
get_ft_info(TALLOC_CTX
*mem_ctx
,
4197 struct ldb_message
*msg
,
4198 struct ForestTrustInfo
*info
)
4200 const struct ldb_val
*ft_blob
;
4201 enum ndr_err_code ndr_err
;
4203 ft_blob
= ldb_msg_find_ldb_val(msg
, "msDS-TrustForestTrustInfo");
4204 if (!ft_blob
|| !ft_blob
->data
) {
4205 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4207 /* ldb_val is equivalent to DATA_BLOB */
4208 ndr_err
= ndr_pull_struct_blob_all(ft_blob
, mem_ctx
, info
,
4209 (ndr_pull_flags_fn_t
)ndr_pull_ForestTrustInfo
);
4210 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
4211 return NT_STATUS_INVALID_DOMAIN_STATE
;
4214 return NT_STATUS_OK
;
4217 static NTSTATUS
own_ft_info(struct lsa_policy_state
*ps
,
4218 struct ForestTrustInfo
*fti
)
4220 struct ForestTrustDataDomainInfo
*info
;
4221 struct ForestTrustInfoRecord
*rec
;
4225 fti
->records
= talloc_array(fti
,
4226 struct ForestTrustInfoRecordArmor
, 2);
4227 if (!fti
->records
) {
4228 return NT_STATUS_NO_MEMORY
;
4232 rec
= &fti
->records
[0].record
;
4236 rec
->type
= LSA_FOREST_TRUST_TOP_LEVEL_NAME
;
4238 rec
->data
.name
.string
= talloc_strdup(fti
, ps
->forest_dns
);
4239 if (!rec
->data
.name
.string
) {
4240 return NT_STATUS_NO_MEMORY
;
4242 rec
->data
.name
.size
= strlen(rec
->data
.name
.string
);
4245 rec
= &fti
->records
[1].record
;
4249 rec
->type
= LSA_FOREST_TRUST_DOMAIN_INFO
;
4251 info
= &rec
->data
.info
;
4253 info
->sid
= *ps
->domain_sid
;
4254 info
->dns_name
.string
= talloc_strdup(fti
, ps
->domain_dns
);
4255 if (!info
->dns_name
.string
) {
4256 return NT_STATUS_NO_MEMORY
;
4258 info
->dns_name
.size
= strlen(info
->dns_name
.string
);
4259 info
->netbios_name
.string
= talloc_strdup(fti
, ps
->domain_name
);
4260 if (!info
->netbios_name
.string
) {
4261 return NT_STATUS_NO_MEMORY
;
4263 info
->netbios_name
.size
= strlen(info
->netbios_name
.string
);
4265 return NT_STATUS_OK
;
4268 static NTSTATUS
make_ft_info(TALLOC_CTX
*mem_ctx
,
4269 struct lsa_ForestTrustInformation
*lfti
,
4270 struct ForestTrustInfo
*fti
)
4272 struct lsa_ForestTrustRecord
*lrec
;
4273 struct ForestTrustInfoRecord
*rec
;
4274 struct lsa_StringLarge
*tln
;
4275 struct lsa_ForestTrustDomainInfo
*info
;
4279 fti
->count
= lfti
->count
;
4280 fti
->records
= talloc_array(mem_ctx
,
4281 struct ForestTrustInfoRecordArmor
,
4283 if (!fti
->records
) {
4284 return NT_STATUS_NO_MEMORY
;
4286 for (i
= 0; i
< fti
->count
; i
++) {
4287 lrec
= lfti
->entries
[i
];
4288 rec
= &fti
->records
[i
].record
;
4290 rec
->flags
= lrec
->flags
;
4291 rec
->timestamp
= lrec
->time
;
4292 rec
->type
= lrec
->type
;
4294 switch (lrec
->type
) {
4295 case LSA_FOREST_TRUST_TOP_LEVEL_NAME
:
4296 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
:
4297 tln
= &lrec
->forest_trust_data
.top_level_name
;
4298 rec
->data
.name
.string
=
4299 talloc_strdup(mem_ctx
, tln
->string
);
4300 if (!rec
->data
.name
.string
) {
4301 return NT_STATUS_NO_MEMORY
;
4303 rec
->data
.name
.size
= strlen(rec
->data
.name
.string
);
4305 case LSA_FOREST_TRUST_DOMAIN_INFO
:
4306 info
= &lrec
->forest_trust_data
.domain_info
;
4307 rec
->data
.info
.sid
= *info
->domain_sid
;
4308 rec
->data
.info
.dns_name
.string
=
4309 talloc_strdup(mem_ctx
,
4310 info
->dns_domain_name
.string
);
4311 if (!rec
->data
.info
.dns_name
.string
) {
4312 return NT_STATUS_NO_MEMORY
;
4314 rec
->data
.info
.dns_name
.size
=
4315 strlen(rec
->data
.info
.dns_name
.string
);
4316 rec
->data
.info
.netbios_name
.string
=
4317 talloc_strdup(mem_ctx
,
4318 info
->netbios_domain_name
.string
);
4319 if (!rec
->data
.info
.netbios_name
.string
) {
4320 return NT_STATUS_NO_MEMORY
;
4322 rec
->data
.info
.netbios_name
.size
=
4323 strlen(rec
->data
.info
.netbios_name
.string
);
4326 return NT_STATUS_INVALID_DOMAIN_STATE
;
4330 return NT_STATUS_OK
;
4333 static NTSTATUS
add_collision(struct lsa_ForestTrustCollisionInfo
*c_info
,
4334 uint32_t idx
, uint32_t collision_type
,
4335 uint32_t conflict_type
, const char *tdo_name
);
4337 static NTSTATUS
check_ft_info(TALLOC_CTX
*mem_ctx
,
4338 const char *tdo_name
,
4339 struct ForestTrustInfo
*tdo_fti
,
4340 struct ForestTrustInfo
*new_fti
,
4341 struct lsa_ForestTrustCollisionInfo
*c_info
)
4343 struct ForestTrustInfoRecord
*nrec
;
4344 struct ForestTrustInfoRecord
*trec
;
4345 const char *dns_name
;
4346 const char *nb_name
;
4347 struct dom_sid
*sid
= NULL
;
4348 const char *tname
= NULL
;
4351 NTSTATUS nt_status
= NT_STATUS_OK
;
4352 uint32_t new_fti_idx
;
4354 /* use always TDO type, until we understand when Xref can be used */
4355 uint32_t collision_type
= LSA_FOREST_TRUST_COLLISION_TDO
;
4360 bool ex_rule
= false;
4363 for (new_fti_idx
= 0; new_fti_idx
< new_fti
->count
; new_fti_idx
++) {
4365 nrec
= &new_fti
->records
[new_fti_idx
].record
;
4368 tln_conflict
= false;
4369 sid_conflict
= false;
4370 nb_conflict
= false;
4373 switch (nrec
->type
) {
4374 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
:
4375 /* exclusions do not conflict by definition */
4378 case FOREST_TRUST_TOP_LEVEL_NAME
:
4379 dns_name
= nrec
->data
.name
.string
;
4380 dns_len
= nrec
->data
.name
.size
;
4383 case LSA_FOREST_TRUST_DOMAIN_INFO
:
4384 dns_name
= nrec
->data
.info
.dns_name
.string
;
4385 dns_len
= nrec
->data
.info
.dns_name
.size
;
4386 nb_name
= nrec
->data
.info
.netbios_name
.string
;
4387 sid
= &nrec
->data
.info
.sid
;
4391 if (!dns_name
) continue;
4393 /* check if this is already taken and not excluded */
4394 for (i
= 0; i
< tdo_fti
->count
; i
++) {
4395 trec
= &tdo_fti
->records
[i
].record
;
4397 switch (trec
->type
) {
4398 case FOREST_TRUST_TOP_LEVEL_NAME
:
4400 tname
= trec
->data
.name
.string
;
4401 tlen
= trec
->data
.name
.size
;
4403 case FOREST_TRUST_TOP_LEVEL_NAME_EX
:
4405 tname
= trec
->data
.name
.string
;
4406 tlen
= trec
->data
.name
.size
;
4408 case FOREST_TRUST_DOMAIN_INFO
:
4410 tname
= trec
->data
.info
.dns_name
.string
;
4411 tlen
= trec
->data
.info
.dns_name
.size
;
4413 ret
= dns_cmp(dns_name
, dns_len
, tname
, tlen
);
4416 /* if it matches exclusion,
4417 * it doesn't conflict */
4423 case DNS_CMP_FIRST_IS_CHILD
:
4424 case DNS_CMP_SECOND_IS_CHILD
:
4425 tln_conflict
= true;
4431 /* explicit exclusion, no dns name conflict here */
4433 tln_conflict
= false;
4436 if (trec
->type
!= FOREST_TRUST_DOMAIN_INFO
) {
4440 /* also test for domain info */
4441 if (!(trec
->flags
& LSA_SID_DISABLED_ADMIN
) &&
4442 dom_sid_compare(&trec
->data
.info
.sid
, sid
) == 0) {
4443 sid_conflict
= true;
4445 if (!(trec
->flags
& LSA_NB_DISABLED_ADMIN
) &&
4446 (nb_name
!= NULL
) &&
4447 strcasecmp_m(trec
->data
.info
.netbios_name
.string
,
4454 nt_status
= add_collision(c_info
, new_fti_idx
,
4456 LSA_TLN_DISABLED_CONFLICT
,
4458 if (!NT_STATUS_IS_OK(nt_status
)) {
4463 nt_status
= add_collision(c_info
, new_fti_idx
,
4465 LSA_SID_DISABLED_CONFLICT
,
4467 if (!NT_STATUS_IS_OK(nt_status
)) {
4472 nt_status
= add_collision(c_info
, new_fti_idx
,
4474 LSA_NB_DISABLED_CONFLICT
,
4476 if (!NT_STATUS_IS_OK(nt_status
)) {
4486 static NTSTATUS
add_collision(struct lsa_ForestTrustCollisionInfo
*c_info
,
4487 uint32_t idx
, uint32_t collision_type
,
4488 uint32_t conflict_type
, const char *tdo_name
)
4490 struct lsa_ForestTrustCollisionRecord
**es
;
4491 uint32_t i
= c_info
->count
;
4493 es
= talloc_realloc(c_info
, c_info
->entries
,
4494 struct lsa_ForestTrustCollisionRecord
*, i
+ 1);
4496 return NT_STATUS_NO_MEMORY
;
4498 c_info
->entries
= es
;
4499 c_info
->count
= i
+ 1;
4501 es
[i
] = talloc(es
, struct lsa_ForestTrustCollisionRecord
);
4503 return NT_STATUS_NO_MEMORY
;
4507 es
[i
]->type
= collision_type
;
4508 es
[i
]->flags
= conflict_type
;
4509 es
[i
]->name
.string
= talloc_strdup(es
[i
], tdo_name
);
4510 if (!es
[i
]->name
.string
) {
4511 return NT_STATUS_NO_MEMORY
;
4513 es
[i
]->name
.size
= strlen(es
[i
]->name
.string
);
4515 return NT_STATUS_OK
;
4519 lsa_lsaRSetForestTrustInformation
4521 static NTSTATUS
dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state
*dce_call
,
4522 TALLOC_CTX
*mem_ctx
,
4523 struct lsa_lsaRSetForestTrustInformation
*r
)
4525 struct dcesrv_handle
*h
;
4526 struct lsa_policy_state
*p_state
;
4527 const char *trust_attrs
[] = { "trustPartner", "trustAttributes",
4528 "msDS-TrustForestTrustInfo", NULL
};
4529 struct ldb_message
**dom_res
= NULL
;
4530 struct ldb_dn
*tdo_dn
;
4531 struct ldb_message
*msg
;
4533 const char *td_name
;
4534 uint32_t trust_attributes
;
4535 struct lsa_ForestTrustCollisionInfo
*c_info
;
4536 struct ForestTrustInfo
*nfti
;
4537 struct ForestTrustInfo
*fti
;
4539 enum ndr_err_code ndr_err
;
4544 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
4548 if (strcmp(p_state
->domain_dns
, p_state
->forest_dns
)) {
4549 return NT_STATUS_INVALID_DOMAIN_STATE
;
4552 /* abort if we are not a PDC */
4553 if (!samdb_is_pdc(p_state
->sam_ldb
)) {
4554 return NT_STATUS_INVALID_DOMAIN_ROLE
;
4557 ret
= samdb_rodc(p_state
->sam_ldb
, &am_rodc
);
4558 if (ret
== LDB_SUCCESS
&& am_rodc
) {
4559 return NT_STATUS_NO_SUCH_DOMAIN
;
4562 /* check caller has TRUSTED_SET_AUTH */
4564 /* fetch all trusted domain objects */
4565 num_res
= gendb_search(p_state
->sam_ldb
, mem_ctx
,
4567 &dom_res
, trust_attrs
,
4568 "(objectclass=trustedDomain)");
4570 return NT_STATUS_NO_SUCH_DOMAIN
;
4573 for (i
= 0; i
< num_res
; i
++) {
4574 td_name
= ldb_msg_find_attr_as_string(dom_res
[i
],
4575 "trustPartner", NULL
);
4577 return NT_STATUS_INVALID_DOMAIN_STATE
;
4579 if (strcasecmp_m(td_name
,
4580 r
->in
.trusted_domain_name
->string
) == 0) {
4585 return NT_STATUS_NO_SUCH_DOMAIN
;
4588 tdo_dn
= dom_res
[i
]->dn
;
4590 trust_attributes
= ldb_msg_find_attr_as_uint(dom_res
[i
],
4591 "trustAttributes", 0);
4592 if (!(trust_attributes
& LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
)) {
4593 return NT_STATUS_INVALID_PARAMETER
;
4596 if (r
->in
.highest_record_type
>= LSA_FOREST_TRUST_RECORD_TYPE_LAST
) {
4597 return NT_STATUS_INVALID_PARAMETER
;
4600 nfti
= talloc(mem_ctx
, struct ForestTrustInfo
);
4602 return NT_STATUS_NO_MEMORY
;
4605 nt_status
= make_ft_info(nfti
, r
->in
.forest_trust_info
, nfti
);
4606 if (!NT_STATUS_IS_OK(nt_status
)) {
4610 c_info
= talloc_zero(r
->out
.collision_info
,
4611 struct lsa_ForestTrustCollisionInfo
);
4613 return NT_STATUS_NO_MEMORY
;
4616 /* first check own info, then other domains */
4617 fti
= talloc(mem_ctx
, struct ForestTrustInfo
);
4619 return NT_STATUS_NO_MEMORY
;
4622 nt_status
= own_ft_info(p_state
, fti
);
4623 if (!NT_STATUS_IS_OK(nt_status
)) {
4627 nt_status
= check_ft_info(c_info
, p_state
->domain_dns
,
4629 if (!NT_STATUS_IS_OK(nt_status
)) {
4633 for (i
= 0; i
< num_res
; i
++) {
4634 fti
= talloc(mem_ctx
, struct ForestTrustInfo
);
4636 return NT_STATUS_NO_MEMORY
;
4639 nt_status
= get_ft_info(mem_ctx
, dom_res
[i
], fti
);
4640 if (!NT_STATUS_IS_OK(nt_status
)) {
4641 if (NT_STATUS_EQUAL(nt_status
,
4642 NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
4648 td_name
= ldb_msg_find_attr_as_string(dom_res
[i
],
4649 "trustPartner", NULL
);
4651 return NT_STATUS_INVALID_DOMAIN_STATE
;
4654 nt_status
= check_ft_info(c_info
, td_name
, fti
, nfti
, c_info
);
4655 if (!NT_STATUS_IS_OK(nt_status
)) {
4660 if (c_info
->count
!= 0) {
4661 *r
->out
.collision_info
= c_info
;
4664 if (r
->in
.check_only
!= 0) {
4665 return NT_STATUS_OK
;
4668 /* not just a check, write info back */
4670 ndr_err
= ndr_push_struct_blob(&ft_blob
, mem_ctx
, nfti
,
4671 (ndr_push_flags_fn_t
)ndr_push_ForestTrustInfo
);
4672 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
4673 return NT_STATUS_INVALID_PARAMETER
;
4676 msg
= ldb_msg_new(mem_ctx
);
4678 return NT_STATUS_NO_MEMORY
;
4681 msg
->dn
= ldb_dn_copy(mem_ctx
, tdo_dn
);
4683 return NT_STATUS_NO_MEMORY
;
4686 ret
= ldb_msg_add_empty(msg
, "msDS-TrustForestTrustInfo",
4687 LDB_FLAG_MOD_REPLACE
, NULL
);
4688 if (ret
!= LDB_SUCCESS
) {
4689 return NT_STATUS_NO_MEMORY
;
4691 ret
= ldb_msg_add_value(msg
, "msDS-TrustForestTrustInfo",
4693 if (ret
!= LDB_SUCCESS
) {
4694 return NT_STATUS_NO_MEMORY
;
4697 ret
= ldb_modify(p_state
->sam_ldb
, msg
);
4698 if (ret
!= LDB_SUCCESS
) {
4699 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4700 ldb_errstring(p_state
->sam_ldb
)));
4703 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
:
4704 return NT_STATUS_ACCESS_DENIED
;
4706 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
4710 return NT_STATUS_OK
;
4716 static NTSTATUS
dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4717 struct lsa_CREDRRENAME
*r
)
4719 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4725 lsa_LSAROPENPOLICYSCE
4727 static NTSTATUS
dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4728 struct lsa_LSAROPENPOLICYSCE
*r
)
4730 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4735 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4737 static NTSTATUS
dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4738 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE
*r
)
4740 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4745 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4747 static NTSTATUS
dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4748 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
*r
)
4750 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4755 lsa_LSARADTREPORTSECURITYEVENT
4757 static NTSTATUS
dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4758 struct lsa_LSARADTREPORTSECURITYEVENT
*r
)
4760 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4764 /* include the generated boilerplate */
4765 #include "librpc/gen_ndr/ndr_lsa_s.c"
4769 /*****************************************
4770 NOTE! The remaining calls below were
4771 removed in w2k3, so the DCESRV_FAULT()
4772 replies are the correct implementation. Do
4773 not try and fill these in with anything else
4774 ******************************************/
4777 dssetup_DsRoleDnsNameToFlatName
4779 static WERROR
dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4780 struct dssetup_DsRoleDnsNameToFlatName
*r
)
4782 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4787 dssetup_DsRoleDcAsDc
4789 static WERROR
dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4790 struct dssetup_DsRoleDcAsDc
*r
)
4792 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4797 dssetup_DsRoleDcAsReplica
4799 static WERROR
dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4800 struct dssetup_DsRoleDcAsReplica
*r
)
4802 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4807 dssetup_DsRoleDemoteDc
4809 static WERROR
dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4810 struct dssetup_DsRoleDemoteDc
*r
)
4812 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4817 dssetup_DsRoleGetDcOperationProgress
4819 static WERROR
dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4820 struct dssetup_DsRoleGetDcOperationProgress
*r
)
4822 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4827 dssetup_DsRoleGetDcOperationResults
4829 static WERROR
dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4830 struct dssetup_DsRoleGetDcOperationResults
*r
)
4832 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4837 dssetup_DsRoleCancel
4839 static WERROR
dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4840 struct dssetup_DsRoleCancel
*r
)
4842 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4847 dssetup_DsRoleServerSaveStateForUpgrade
4849 static WERROR
dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4850 struct dssetup_DsRoleServerSaveStateForUpgrade
*r
)
4852 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4857 dssetup_DsRoleUpgradeDownlevelServer
4859 static WERROR
dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4860 struct dssetup_DsRoleUpgradeDownlevelServer
*r
)
4862 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4867 dssetup_DsRoleAbortDownlevelServerUpgrade
4869 static WERROR
dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4870 struct dssetup_DsRoleAbortDownlevelServerUpgrade
*r
)
4872 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4876 /* include the generated boilerplate */
4877 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4879 NTSTATUS
dcerpc_server_lsa_init(void)
4883 ret
= dcerpc_server_dssetup_init();
4884 if (!NT_STATUS_IS_OK(ret
)) {
4887 ret
= dcerpc_server_lsarpc_init();
4888 if (!NT_STATUS_IS_OK(ret
)) {