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"
37 this type allows us to distinguish handle types
41 state associated with a lsa_OpenAccount() operation
43 struct lsa_account_state
{
44 struct lsa_policy_state
*policy
;
46 struct dom_sid
*account_sid
;
51 state associated with a lsa_OpenSecret() operation
53 struct lsa_secret_state
{
54 struct lsa_policy_state
*policy
;
56 struct ldb_dn
*secret_dn
;
57 struct ldb_context
*sam_ldb
;
62 state associated with a lsa_OpenTrustedDomain() operation
64 struct lsa_trusted_domain_state
{
65 struct lsa_policy_state
*policy
;
67 struct ldb_dn
*trusted_domain_dn
;
68 struct ldb_dn
*trusted_domain_user_dn
;
72 this is based on the samba3 function make_lsa_object_sd()
73 It uses the same logic, but with samba4 helper functions
75 static NTSTATUS
dcesrv_build_lsa_sd(TALLOC_CTX
*mem_ctx
,
76 struct security_descriptor
**sd
,
82 struct dom_sid
*domain_sid
, *domain_admins_sid
;
83 const char *domain_admins_sid_str
, *sidstr
;
84 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
86 status
= dom_sid_split_rid(tmp_ctx
, sid
, &domain_sid
, &rid
);
87 NT_STATUS_NOT_OK_RETURN_AND_FREE(status
, tmp_ctx
);
89 domain_admins_sid
= dom_sid_add_rid(tmp_ctx
, domain_sid
, DOMAIN_RID_ADMINS
);
90 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid
, tmp_ctx
);
92 domain_admins_sid_str
= dom_sid_string(tmp_ctx
, domain_admins_sid
);
93 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid_str
, tmp_ctx
);
95 sidstr
= dom_sid_string(tmp_ctx
, sid
);
96 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr
, tmp_ctx
);
98 *sd
= security_descriptor_dacl_create(mem_ctx
,
102 SEC_ACE_TYPE_ACCESS_ALLOWED
,
103 SEC_GENERIC_EXECUTE
| SEC_GENERIC_READ
, 0,
105 SID_BUILTIN_ADMINISTRATORS
,
106 SEC_ACE_TYPE_ACCESS_ALLOWED
,
109 SID_BUILTIN_ACCOUNT_OPERATORS
,
110 SEC_ACE_TYPE_ACCESS_ALLOWED
,
113 domain_admins_sid_str
,
114 SEC_ACE_TYPE_ACCESS_ALLOWED
,
118 SEC_ACE_TYPE_ACCESS_ALLOWED
,
122 talloc_free(tmp_ctx
);
124 NT_STATUS_HAVE_NO_MEMORY(*sd
);
130 static NTSTATUS
dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state
*dce_call
,
132 struct lsa_EnumAccountRights
*r
);
134 static NTSTATUS
dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state
*dce_call
,
136 struct lsa_policy_state
*state
,
139 const struct lsa_RightSet
*rights
);
144 static NTSTATUS
dcesrv_lsa_Close(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
147 enum dcerpc_transport_t transport
= dce_call
->conn
->endpoint
->ep_description
->transport
;
148 struct dcesrv_handle
*h
;
150 if (transport
!= NCACN_NP
&& transport
!= NCALRPC
) {
151 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED
);
154 *r
->out
.handle
= *r
->in
.handle
;
156 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, DCESRV_HANDLE_ANY
);
160 ZERO_STRUCTP(r
->out
.handle
);
169 static NTSTATUS
dcesrv_lsa_Delete(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
170 struct lsa_Delete
*r
)
172 return NT_STATUS_NOT_SUPPORTED
;
179 static NTSTATUS
dcesrv_lsa_DeleteObject(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
180 struct lsa_DeleteObject
*r
)
182 struct dcesrv_handle
*h
;
185 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, DCESRV_HANDLE_ANY
);
187 if (h
->wire_handle
.handle_type
== LSA_HANDLE_SECRET
) {
188 struct lsa_secret_state
*secret_state
= h
->data
;
190 /* Ensure user is permitted to delete this... */
191 switch (security_session_user_level(dce_call
->conn
->auth_state
.session_info
, NULL
))
193 case SECURITY_SYSTEM
:
194 case SECURITY_ADMINISTRATOR
:
197 /* Users and anonymous are not allowed to delete things */
198 return NT_STATUS_ACCESS_DENIED
;
201 ret
= ldb_delete(secret_state
->sam_ldb
,
202 secret_state
->secret_dn
);
203 if (ret
!= LDB_SUCCESS
) {
204 return NT_STATUS_INVALID_HANDLE
;
207 ZERO_STRUCTP(r
->out
.handle
);
211 } else if (h
->wire_handle
.handle_type
== LSA_HANDLE_TRUSTED_DOMAIN
) {
212 struct lsa_trusted_domain_state
*trusted_domain_state
=
213 talloc_get_type(h
->data
, struct lsa_trusted_domain_state
);
214 ret
= ldb_transaction_start(trusted_domain_state
->policy
->sam_ldb
);
215 if (ret
!= LDB_SUCCESS
) {
216 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
219 ret
= ldb_delete(trusted_domain_state
->policy
->sam_ldb
,
220 trusted_domain_state
->trusted_domain_dn
);
221 if (ret
!= LDB_SUCCESS
) {
222 ldb_transaction_cancel(trusted_domain_state
->policy
->sam_ldb
);
223 return NT_STATUS_INVALID_HANDLE
;
226 if (trusted_domain_state
->trusted_domain_user_dn
) {
227 ret
= ldb_delete(trusted_domain_state
->policy
->sam_ldb
,
228 trusted_domain_state
->trusted_domain_user_dn
);
229 if (ret
!= LDB_SUCCESS
) {
230 ldb_transaction_cancel(trusted_domain_state
->policy
->sam_ldb
);
231 return NT_STATUS_INVALID_HANDLE
;
235 ret
= ldb_transaction_commit(trusted_domain_state
->policy
->sam_ldb
);
236 if (ret
!= LDB_SUCCESS
) {
237 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
240 ZERO_STRUCTP(r
->out
.handle
);
244 } else if (h
->wire_handle
.handle_type
== LSA_HANDLE_ACCOUNT
) {
245 struct lsa_RightSet
*rights
;
246 struct lsa_account_state
*astate
;
247 struct lsa_EnumAccountRights r2
;
250 rights
= talloc(mem_ctx
, struct lsa_RightSet
);
252 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_ACCOUNT
);
256 r2
.in
.handle
= &astate
->policy
->handle
->wire_handle
;
257 r2
.in
.sid
= astate
->account_sid
;
258 r2
.out
.rights
= rights
;
260 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
261 but we have a LSA_HANDLE_ACCOUNT here, so this call
263 status
= dcesrv_lsa_EnumAccountRights(dce_call
, mem_ctx
, &r2
);
264 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
268 if (!NT_STATUS_IS_OK(status
)) {
272 status
= dcesrv_lsa_AddRemoveAccountRights(dce_call
, mem_ctx
, astate
->policy
,
273 LDB_FLAG_MOD_DELETE
, astate
->account_sid
,
275 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
279 if (!NT_STATUS_IS_OK(status
)) {
283 ZERO_STRUCTP(r
->out
.handle
);
288 return NT_STATUS_INVALID_HANDLE
;
295 static NTSTATUS
dcesrv_lsa_EnumPrivs(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
296 struct lsa_EnumPrivs
*r
)
298 struct dcesrv_handle
*h
;
299 struct lsa_policy_state
*state
;
301 enum sec_privilege priv
;
302 const char *privname
;
304 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
308 i
= *r
->in
.resume_handle
;
310 while (((priv
= sec_privilege_from_index(i
)) != SEC_PRIV_INVALID
) &&
311 r
->out
.privs
->count
< r
->in
.max_count
) {
312 struct lsa_PrivEntry
*e
;
313 privname
= sec_privilege_name(priv
);
314 r
->out
.privs
->privs
= talloc_realloc(r
->out
.privs
,
316 struct lsa_PrivEntry
,
317 r
->out
.privs
->count
+1);
318 if (r
->out
.privs
->privs
== NULL
) {
319 return NT_STATUS_NO_MEMORY
;
321 e
= &r
->out
.privs
->privs
[r
->out
.privs
->count
];
324 e
->name
.string
= privname
;
325 r
->out
.privs
->count
++;
329 *r
->out
.resume_handle
= i
;
338 static NTSTATUS
dcesrv_lsa_QuerySecurity(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
339 struct lsa_QuerySecurity
*r
)
341 struct dcesrv_handle
*h
;
342 struct security_descriptor
*sd
;
346 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, DCESRV_HANDLE_ANY
);
348 sid
= &dce_call
->conn
->auth_state
.session_info
->security_token
->sids
[PRIMARY_USER_SID_INDEX
];
350 if (h
->wire_handle
.handle_type
== LSA_HANDLE_POLICY
) {
351 status
= dcesrv_build_lsa_sd(mem_ctx
, &sd
, sid
, 0);
352 } else if (h
->wire_handle
.handle_type
== LSA_HANDLE_ACCOUNT
) {
353 status
= dcesrv_build_lsa_sd(mem_ctx
, &sd
, sid
,
354 LSA_ACCOUNT_ALL_ACCESS
);
356 return NT_STATUS_INVALID_HANDLE
;
358 NT_STATUS_NOT_OK_RETURN(status
);
360 (*r
->out
.sdbuf
) = talloc(mem_ctx
, struct sec_desc_buf
);
361 NT_STATUS_HAVE_NO_MEMORY(*r
->out
.sdbuf
);
363 (*r
->out
.sdbuf
)->sd
= sd
;
372 static NTSTATUS
dcesrv_lsa_SetSecObj(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
373 struct lsa_SetSecObj
*r
)
375 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
382 static NTSTATUS
dcesrv_lsa_ChangePassword(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
383 struct lsa_ChangePassword
*r
)
385 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
389 dssetup_DsRoleGetPrimaryDomainInformation
391 This is not an LSA call, but is the only call left on the DSSETUP
392 pipe (after the pipe was truncated), and needs lsa_get_policy_state
394 static WERROR
dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state
*dce_call
,
396 struct dssetup_DsRoleGetPrimaryDomainInformation
*r
)
398 union dssetup_DsRoleInfo
*info
;
400 info
= talloc_zero(mem_ctx
, union dssetup_DsRoleInfo
);
401 W_ERROR_HAVE_NO_MEMORY(info
);
403 switch (r
->in
.level
) {
404 case DS_ROLE_BASIC_INFORMATION
:
406 enum dssetup_DsRole role
= DS_ROLE_STANDALONE_SERVER
;
408 const char *domain
= NULL
;
409 const char *dns_domain
= NULL
;
410 const char *forest
= NULL
;
411 struct GUID domain_guid
;
412 struct lsa_policy_state
*state
;
414 NTSTATUS status
= dcesrv_lsa_get_policy_state(dce_call
, mem_ctx
, &state
);
415 if (!NT_STATUS_IS_OK(status
)) {
416 return ntstatus_to_werror(status
);
419 ZERO_STRUCT(domain_guid
);
421 switch (lpcfg_server_role(dce_call
->conn
->dce_ctx
->lp_ctx
)) {
422 case ROLE_STANDALONE
:
423 role
= DS_ROLE_STANDALONE_SERVER
;
425 case ROLE_DOMAIN_MEMBER
:
426 role
= DS_ROLE_MEMBER_SERVER
;
428 case ROLE_ACTIVE_DIRECTORY_DC
:
429 if (samdb_is_pdc(state
->sam_ldb
)) {
430 role
= DS_ROLE_PRIMARY_DC
;
432 role
= DS_ROLE_BACKUP_DC
;
437 switch (lpcfg_server_role(dce_call
->conn
->dce_ctx
->lp_ctx
)) {
438 case ROLE_STANDALONE
:
439 domain
= talloc_strdup(mem_ctx
, lpcfg_workgroup(dce_call
->conn
->dce_ctx
->lp_ctx
));
440 W_ERROR_HAVE_NO_MEMORY(domain
);
442 case ROLE_DOMAIN_MEMBER
:
443 domain
= talloc_strdup(mem_ctx
, lpcfg_workgroup(dce_call
->conn
->dce_ctx
->lp_ctx
));
444 W_ERROR_HAVE_NO_MEMORY(domain
);
445 /* TODO: what is with dns_domain and forest and guid? */
447 case ROLE_ACTIVE_DIRECTORY_DC
:
448 flags
= DS_ROLE_PRIMARY_DS_RUNNING
;
450 if (state
->mixed_domain
== 1) {
451 flags
|= DS_ROLE_PRIMARY_DS_MIXED_MODE
;
454 domain
= state
->domain_name
;
455 dns_domain
= state
->domain_dns
;
456 forest
= state
->forest_dns
;
458 domain_guid
= state
->domain_guid
;
459 flags
|= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT
;
463 info
->basic
.role
= role
;
464 info
->basic
.flags
= flags
;
465 info
->basic
.domain
= domain
;
466 info
->basic
.dns_domain
= dns_domain
;
467 info
->basic
.forest
= forest
;
468 info
->basic
.domain_guid
= domain_guid
;
473 case DS_ROLE_UPGRADE_STATUS
:
475 info
->upgrade
.upgrading
= DS_ROLE_NOT_UPGRADING
;
476 info
->upgrade
.previous_role
= DS_ROLE_PREVIOUS_UNKNOWN
;
481 case DS_ROLE_OP_STATUS
:
483 info
->opstatus
.status
= DS_ROLE_OP_IDLE
;
489 return WERR_INVALID_PARAM
;
494 fill in the AccountDomain info
496 static NTSTATUS
dcesrv_lsa_info_AccountDomain(struct lsa_policy_state
*state
, TALLOC_CTX
*mem_ctx
,
497 struct lsa_DomainInfo
*info
)
499 info
->name
.string
= state
->domain_name
;
500 info
->sid
= state
->domain_sid
;
506 fill in the DNS domain info
508 static NTSTATUS
dcesrv_lsa_info_DNS(struct lsa_policy_state
*state
, TALLOC_CTX
*mem_ctx
,
509 struct lsa_DnsDomainInfo
*info
)
511 info
->name
.string
= state
->domain_name
;
512 info
->sid
= state
->domain_sid
;
513 info
->dns_domain
.string
= state
->domain_dns
;
514 info
->dns_forest
.string
= state
->forest_dns
;
515 info
->domain_guid
= state
->domain_guid
;
523 static NTSTATUS
dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
524 struct lsa_QueryInfoPolicy2
*r
)
526 struct lsa_policy_state
*state
;
527 struct dcesrv_handle
*h
;
528 union lsa_PolicyInformation
*info
;
532 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
536 info
= talloc_zero(mem_ctx
, union lsa_PolicyInformation
);
538 return NT_STATUS_NO_MEMORY
;
542 switch (r
->in
.level
) {
543 case LSA_POLICY_INFO_AUDIT_LOG
:
544 /* we don't need to fill in any of this */
545 ZERO_STRUCT(info
->audit_log
);
547 case LSA_POLICY_INFO_AUDIT_EVENTS
:
548 /* we don't need to fill in any of this */
549 ZERO_STRUCT(info
->audit_events
);
551 case LSA_POLICY_INFO_PD
:
552 /* we don't need to fill in any of this */
553 ZERO_STRUCT(info
->pd
);
556 case LSA_POLICY_INFO_DOMAIN
:
557 return dcesrv_lsa_info_AccountDomain(state
, mem_ctx
, &info
->domain
);
558 case LSA_POLICY_INFO_ACCOUNT_DOMAIN
:
559 return dcesrv_lsa_info_AccountDomain(state
, mem_ctx
, &info
->account_domain
);
560 case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN
:
561 return dcesrv_lsa_info_AccountDomain(state
, mem_ctx
, &info
->l_account_domain
);
563 case LSA_POLICY_INFO_ROLE
:
564 info
->role
.role
= LSA_ROLE_PRIMARY
;
567 case LSA_POLICY_INFO_DNS
:
568 case LSA_POLICY_INFO_DNS_INT
:
569 return dcesrv_lsa_info_DNS(state
, mem_ctx
, &info
->dns
);
571 case LSA_POLICY_INFO_REPLICA
:
572 ZERO_STRUCT(info
->replica
);
575 case LSA_POLICY_INFO_QUOTA
:
576 ZERO_STRUCT(info
->quota
);
579 case LSA_POLICY_INFO_MOD
:
580 case LSA_POLICY_INFO_AUDIT_FULL_SET
:
581 case LSA_POLICY_INFO_AUDIT_FULL_QUERY
:
582 /* windows gives INVALID_PARAMETER */
584 return NT_STATUS_INVALID_PARAMETER
;
588 return NT_STATUS_INVALID_INFO_CLASS
;
594 static NTSTATUS
dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
595 struct lsa_QueryInfoPolicy
*r
)
597 struct lsa_QueryInfoPolicy2 r2
;
602 r2
.in
.handle
= r
->in
.handle
;
603 r2
.in
.level
= r
->in
.level
;
604 r2
.out
.info
= r
->out
.info
;
606 status
= dcesrv_lsa_QueryInfoPolicy2(dce_call
, mem_ctx
, &r2
);
614 static NTSTATUS
dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
615 struct lsa_SetInfoPolicy
*r
)
617 /* need to support this */
618 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
625 static NTSTATUS
dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
626 struct lsa_ClearAuditLog
*r
)
628 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
635 This call does not seem to have any long-term effects, hence no database operations
637 we need to talk to the MS product group to find out what this account database means!
639 answer is that the lsa database is totally separate from the SAM and
640 ldap databases. We are going to need a separate ldb to store these
641 accounts. The SIDs on this account bear no relation to the SIDs in
644 static NTSTATUS
dcesrv_lsa_CreateAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
645 struct lsa_CreateAccount
*r
)
647 struct lsa_account_state
*astate
;
649 struct lsa_policy_state
*state
;
650 struct dcesrv_handle
*h
, *ah
;
652 ZERO_STRUCTP(r
->out
.acct_handle
);
654 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
658 astate
= talloc(dce_call
->conn
, struct lsa_account_state
);
659 if (astate
== NULL
) {
660 return NT_STATUS_NO_MEMORY
;
663 astate
->account_sid
= dom_sid_dup(astate
, r
->in
.sid
);
664 if (astate
->account_sid
== NULL
) {
666 return NT_STATUS_NO_MEMORY
;
669 astate
->policy
= talloc_reference(astate
, state
);
670 astate
->access_mask
= r
->in
.access_mask
;
672 ah
= dcesrv_handle_new(dce_call
->context
, LSA_HANDLE_ACCOUNT
);
675 return NT_STATUS_NO_MEMORY
;
678 ah
->data
= talloc_steal(ah
, astate
);
680 *r
->out
.acct_handle
= ah
->wire_handle
;
689 static NTSTATUS
dcesrv_lsa_EnumAccounts(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
690 struct lsa_EnumAccounts
*r
)
692 struct dcesrv_handle
*h
;
693 struct lsa_policy_state
*state
;
695 struct ldb_message
**res
;
696 const char * const attrs
[] = { "objectSid", NULL
};
699 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
703 /* NOTE: This call must only return accounts that have at least
706 ret
= gendb_search(state
->pdb
, mem_ctx
, NULL
, &res
, attrs
,
707 "(&(objectSid=*)(privilege=*))");
709 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
712 if (*r
->in
.resume_handle
>= ret
) {
713 return NT_STATUS_NO_MORE_ENTRIES
;
716 count
= ret
- *r
->in
.resume_handle
;
717 if (count
> r
->in
.num_entries
) {
718 count
= r
->in
.num_entries
;
722 return NT_STATUS_NO_MORE_ENTRIES
;
725 r
->out
.sids
->sids
= talloc_array(r
->out
.sids
, struct lsa_SidPtr
, count
);
726 if (r
->out
.sids
->sids
== NULL
) {
727 return NT_STATUS_NO_MEMORY
;
730 for (i
=0;i
<count
;i
++) {
731 r
->out
.sids
->sids
[i
].sid
=
732 samdb_result_dom_sid(r
->out
.sids
->sids
,
733 res
[i
+ *r
->in
.resume_handle
],
735 NT_STATUS_HAVE_NO_MEMORY(r
->out
.sids
->sids
[i
].sid
);
738 r
->out
.sids
->num_sids
= count
;
739 *r
->out
.resume_handle
= count
+ *r
->in
.resume_handle
;
745 /* This decrypts and returns Trusted Domain Auth Information Internal data */
746 static NTSTATUS
get_trustdom_auth_blob(struct dcesrv_call_state
*dce_call
,
747 TALLOC_CTX
*mem_ctx
, DATA_BLOB
*auth_blob
,
748 struct trustDomainPasswords
*auth_struct
)
750 DATA_BLOB session_key
= data_blob(NULL
, 0);
751 enum ndr_err_code ndr_err
;
754 nt_status
= dcesrv_fetch_session_key(dce_call
->conn
, &session_key
);
755 if (!NT_STATUS_IS_OK(nt_status
)) {
759 arcfour_crypt_blob(auth_blob
->data
, auth_blob
->length
, &session_key
);
760 ndr_err
= ndr_pull_struct_blob(auth_blob
, mem_ctx
,
762 (ndr_pull_flags_fn_t
)ndr_pull_trustDomainPasswords
);
763 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
764 return NT_STATUS_INVALID_PARAMETER
;
770 static NTSTATUS
get_trustauth_inout_blob(struct dcesrv_call_state
*dce_call
,
772 struct trustAuthInOutBlob
*iopw
,
773 DATA_BLOB
*trustauth_blob
)
775 enum ndr_err_code ndr_err
;
777 ndr_err
= ndr_push_struct_blob(trustauth_blob
, mem_ctx
,
779 (ndr_push_flags_fn_t
)ndr_push_trustAuthInOutBlob
);
780 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
781 return NT_STATUS_INVALID_PARAMETER
;
787 static NTSTATUS
add_trust_user(TALLOC_CTX
*mem_ctx
,
788 struct ldb_context
*sam_ldb
,
789 struct ldb_dn
*base_dn
,
790 const char *netbios_name
,
791 struct trustAuthInOutBlob
*in
,
792 struct ldb_dn
**user_dn
)
794 struct ldb_message
*msg
;
799 dn
= ldb_dn_copy(mem_ctx
, base_dn
);
801 return NT_STATUS_NO_MEMORY
;
803 if (!ldb_dn_add_child_fmt(dn
, "cn=%s$,cn=users", netbios_name
)) {
804 return NT_STATUS_NO_MEMORY
;
807 msg
= ldb_msg_new(mem_ctx
);
809 return NT_STATUS_NO_MEMORY
;
813 ret
= ldb_msg_add_string(msg
, "objectClass", "user");
814 if (ret
!= LDB_SUCCESS
) {
815 return NT_STATUS_NO_MEMORY
;
818 ret
= ldb_msg_add_fmt(msg
, "samAccountName", "%s$", netbios_name
);
819 if (ret
!= LDB_SUCCESS
) {
820 return NT_STATUS_NO_MEMORY
;
823 ret
= samdb_msg_add_uint(sam_ldb
, msg
, msg
, "userAccountControl",
824 UF_INTERDOMAIN_TRUST_ACCOUNT
);
825 if (ret
!= LDB_SUCCESS
) {
826 return NT_STATUS_NO_MEMORY
;
829 for (i
= 0; i
< in
->count
; i
++) {
830 const char *attribute
;
832 switch (in
->current
.array
[i
].AuthType
) {
833 case TRUST_AUTH_TYPE_NT4OWF
:
834 attribute
= "unicodePwd";
835 v
.data
= (uint8_t *)&in
->current
.array
[i
].AuthInfo
.nt4owf
.password
;
838 case TRUST_AUTH_TYPE_CLEAR
:
839 attribute
= "clearTextPassword";
840 v
.data
= in
->current
.array
[i
].AuthInfo
.clear
.password
;
841 v
.length
= in
->current
.array
[i
].AuthInfo
.clear
.size
;
847 ret
= ldb_msg_add_value(msg
, attribute
, &v
, NULL
);
848 if (ret
!= LDB_SUCCESS
) {
849 return NT_STATUS_NO_MEMORY
;
853 /* create the trusted_domain user account */
854 ret
= ldb_add(sam_ldb
, msg
);
855 if (ret
!= LDB_SUCCESS
) {
856 DEBUG(0,("Failed to create user record %s: %s\n",
857 ldb_dn_get_linearized(msg
->dn
),
858 ldb_errstring(sam_ldb
)));
861 case LDB_ERR_ENTRY_ALREADY_EXISTS
:
862 return NT_STATUS_DOMAIN_EXISTS
;
863 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
:
864 return NT_STATUS_ACCESS_DENIED
;
866 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
877 lsa_CreateTrustedDomainEx2
879 static NTSTATUS
dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state
*dce_call
,
881 struct lsa_CreateTrustedDomainEx2
*r
,
883 struct lsa_TrustDomainInfoAuthInfo
*unencrypted_auth_info
)
885 struct dcesrv_handle
*policy_handle
;
886 struct lsa_policy_state
*policy_state
;
887 struct lsa_trusted_domain_state
*trusted_domain_state
;
888 struct dcesrv_handle
*handle
;
889 struct ldb_message
**msgs
, *msg
;
890 const char *attrs
[] = {
893 const char *netbios_name
;
894 const char *dns_name
;
896 DATA_BLOB trustAuthIncoming
, trustAuthOutgoing
, auth_blob
;
897 struct trustDomainPasswords auth_struct
;
900 struct ldb_context
*sam_ldb
;
902 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.policy_handle
, LSA_HANDLE_POLICY
);
903 ZERO_STRUCTP(r
->out
.trustdom_handle
);
905 policy_state
= policy_handle
->data
;
906 sam_ldb
= policy_state
->sam_ldb
;
908 netbios_name
= r
->in
.info
->netbios_name
.string
;
910 return NT_STATUS_INVALID_PARAMETER
;
913 dns_name
= r
->in
.info
->domain_name
.string
;
915 trusted_domain_state
= talloc_zero(mem_ctx
, struct lsa_trusted_domain_state
);
916 if (!trusted_domain_state
) {
917 return NT_STATUS_NO_MEMORY
;
919 trusted_domain_state
->policy
= policy_state
;
921 if (strcasecmp(netbios_name
, "BUILTIN") == 0
922 || (dns_name
&& strcasecmp(dns_name
, "BUILTIN") == 0)
923 || (dom_sid_in_domain(policy_state
->builtin_sid
, r
->in
.info
->sid
))) {
924 return NT_STATUS_INVALID_PARAMETER
;
927 if (strcasecmp(netbios_name
, policy_state
->domain_name
) == 0
928 || strcasecmp(netbios_name
, policy_state
->domain_dns
) == 0
929 || (dns_name
&& strcasecmp(dns_name
, policy_state
->domain_dns
) == 0)
930 || (dns_name
&& strcasecmp(dns_name
, policy_state
->domain_name
) == 0)
931 || (dom_sid_equal(policy_state
->domain_sid
, r
->in
.info
->sid
))) {
932 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED
;
935 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
936 if (op
== NDR_LSA_CREATETRUSTEDDOMAIN
) {
937 /* No secrets are created at this time, for this function */
938 auth_struct
.outgoing
.count
= 0;
939 auth_struct
.incoming
.count
= 0;
940 } else if (op
== NDR_LSA_CREATETRUSTEDDOMAINEX2
) {
941 auth_blob
= data_blob_const(r
->in
.auth_info_internal
->auth_blob
.data
,
942 r
->in
.auth_info_internal
->auth_blob
.size
);
943 nt_status
= get_trustdom_auth_blob(dce_call
, mem_ctx
,
944 &auth_blob
, &auth_struct
);
945 if (!NT_STATUS_IS_OK(nt_status
)) {
948 } else if (op
== NDR_LSA_CREATETRUSTEDDOMAINEX
) {
950 if (unencrypted_auth_info
->incoming_count
> 1) {
951 return NT_STATUS_INVALID_PARAMETER
;
954 /* more investigation required here, do not create secrets for
956 auth_struct
.outgoing
.count
= 0;
957 auth_struct
.incoming
.count
= 0;
959 return NT_STATUS_INVALID_PARAMETER
;
962 if (auth_struct
.incoming
.count
) {
963 nt_status
= get_trustauth_inout_blob(dce_call
, mem_ctx
,
964 &auth_struct
.incoming
,
966 if (!NT_STATUS_IS_OK(nt_status
)) {
970 trustAuthIncoming
= data_blob(NULL
, 0);
973 if (auth_struct
.outgoing
.count
) {
974 nt_status
= get_trustauth_inout_blob(dce_call
, mem_ctx
,
975 &auth_struct
.outgoing
,
977 if (!NT_STATUS_IS_OK(nt_status
)) {
981 trustAuthOutgoing
= data_blob(NULL
, 0);
984 ret
= ldb_transaction_start(sam_ldb
);
985 if (ret
!= LDB_SUCCESS
) {
986 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
990 char *dns_encoded
= ldb_binary_encode_string(mem_ctx
, dns_name
);
991 char *netbios_encoded
= ldb_binary_encode_string(mem_ctx
, netbios_name
);
992 /* search for the trusted_domain record */
993 ret
= gendb_search(sam_ldb
,
994 mem_ctx
, policy_state
->system_dn
, &msgs
, attrs
,
995 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
996 dns_encoded
, dns_encoded
, dns_encoded
, netbios_encoded
, netbios_encoded
, netbios_encoded
);
998 ldb_transaction_cancel(sam_ldb
);
999 return NT_STATUS_OBJECT_NAME_COLLISION
;
1002 char *netbios_encoded
= ldb_binary_encode_string(mem_ctx
, netbios_name
);
1003 /* search for the trusted_domain record */
1004 ret
= gendb_search(sam_ldb
,
1005 mem_ctx
, policy_state
->system_dn
, &msgs
, attrs
,
1006 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1007 netbios_encoded
, netbios_encoded
, netbios_encoded
);
1009 ldb_transaction_cancel(sam_ldb
);
1010 return NT_STATUS_OBJECT_NAME_COLLISION
;
1015 ldb_transaction_cancel(sam_ldb
);
1016 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1019 name
= dns_name
? dns_name
: netbios_name
;
1021 msg
= ldb_msg_new(mem_ctx
);
1023 return NT_STATUS_NO_MEMORY
;
1026 msg
->dn
= ldb_dn_copy(mem_ctx
, policy_state
->system_dn
);
1027 if ( ! ldb_dn_add_child_fmt(msg
->dn
, "cn=%s", name
)) {
1028 ldb_transaction_cancel(sam_ldb
);
1029 return NT_STATUS_NO_MEMORY
;
1032 ldb_msg_add_string(msg
, "flatname", netbios_name
);
1034 if (r
->in
.info
->sid
) {
1035 ret
= samdb_msg_add_dom_sid(sam_ldb
, mem_ctx
, msg
, "securityIdentifier", r
->in
.info
->sid
);
1036 if (ret
!= LDB_SUCCESS
) {
1037 ldb_transaction_cancel(sam_ldb
);
1038 return NT_STATUS_INVALID_PARAMETER
;
1042 ldb_msg_add_string(msg
, "objectClass", "trustedDomain");
1044 samdb_msg_add_int(sam_ldb
, mem_ctx
, msg
, "trustType", r
->in
.info
->trust_type
);
1046 samdb_msg_add_int(sam_ldb
, mem_ctx
, msg
, "trustAttributes", r
->in
.info
->trust_attributes
);
1048 samdb_msg_add_int(sam_ldb
, mem_ctx
, msg
, "trustDirection", r
->in
.info
->trust_direction
);
1051 ldb_msg_add_string(msg
, "trustPartner", dns_name
);
1054 if (trustAuthIncoming
.data
) {
1055 ret
= ldb_msg_add_value(msg
, "trustAuthIncoming", &trustAuthIncoming
, NULL
);
1056 if (ret
!= LDB_SUCCESS
) {
1057 ldb_transaction_cancel(sam_ldb
);
1058 return NT_STATUS_NO_MEMORY
;
1061 if (trustAuthOutgoing
.data
) {
1062 ret
= ldb_msg_add_value(msg
, "trustAuthOutgoing", &trustAuthOutgoing
, NULL
);
1063 if (ret
!= LDB_SUCCESS
) {
1064 ldb_transaction_cancel(sam_ldb
);
1065 return NT_STATUS_NO_MEMORY
;
1069 trusted_domain_state
->trusted_domain_dn
= talloc_reference(trusted_domain_state
, msg
->dn
);
1071 /* create the trusted_domain */
1072 ret
= ldb_add(sam_ldb
, msg
);
1076 case LDB_ERR_ENTRY_ALREADY_EXISTS
:
1077 ldb_transaction_cancel(sam_ldb
);
1078 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1079 ldb_dn_get_linearized(msg
->dn
),
1080 ldb_errstring(sam_ldb
)));
1081 return NT_STATUS_DOMAIN_EXISTS
;
1082 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
:
1083 ldb_transaction_cancel(sam_ldb
);
1084 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1085 ldb_dn_get_linearized(msg
->dn
),
1086 ldb_errstring(sam_ldb
)));
1087 return NT_STATUS_ACCESS_DENIED
;
1089 ldb_transaction_cancel(sam_ldb
);
1090 DEBUG(0,("Failed to create user record %s: %s\n",
1091 ldb_dn_get_linearized(msg
->dn
),
1092 ldb_errstring(sam_ldb
)));
1093 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1096 if (r
->in
.info
->trust_direction
& LSA_TRUST_DIRECTION_INBOUND
) {
1097 struct ldb_dn
*user_dn
;
1098 /* Inbound trusts must also create a cn=users object to match */
1099 nt_status
= add_trust_user(mem_ctx
, sam_ldb
,
1100 policy_state
->domain_dn
,
1102 &auth_struct
.incoming
,
1104 if (!NT_STATUS_IS_OK(nt_status
)) {
1105 ldb_transaction_cancel(sam_ldb
);
1109 /* save the trust user dn */
1110 trusted_domain_state
->trusted_domain_user_dn
1111 = talloc_steal(trusted_domain_state
, user_dn
);
1114 ret
= ldb_transaction_commit(sam_ldb
);
1115 if (ret
!= LDB_SUCCESS
) {
1116 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1119 handle
= dcesrv_handle_new(dce_call
->context
, LSA_HANDLE_TRUSTED_DOMAIN
);
1121 return NT_STATUS_NO_MEMORY
;
1124 handle
->data
= talloc_steal(handle
, trusted_domain_state
);
1126 trusted_domain_state
->access_mask
= r
->in
.access_mask
;
1127 trusted_domain_state
->policy
= talloc_reference(trusted_domain_state
, policy_state
);
1129 *r
->out
.trustdom_handle
= handle
->wire_handle
;
1131 return NT_STATUS_OK
;
1135 lsa_CreateTrustedDomainEx2
1137 static NTSTATUS
dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state
*dce_call
,
1138 TALLOC_CTX
*mem_ctx
,
1139 struct lsa_CreateTrustedDomainEx2
*r
)
1141 return dcesrv_lsa_CreateTrustedDomain_base(dce_call
, mem_ctx
, r
, NDR_LSA_CREATETRUSTEDDOMAINEX2
, NULL
);
1144 lsa_CreateTrustedDomainEx
1146 static NTSTATUS
dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state
*dce_call
,
1147 TALLOC_CTX
*mem_ctx
,
1148 struct lsa_CreateTrustedDomainEx
*r
)
1150 struct lsa_CreateTrustedDomainEx2 r2
;
1152 r2
.in
.policy_handle
= r
->in
.policy_handle
;
1153 r2
.in
.info
= r
->in
.info
;
1154 r2
.out
.trustdom_handle
= r
->out
.trustdom_handle
;
1155 return dcesrv_lsa_CreateTrustedDomain_base(dce_call
, mem_ctx
, &r2
, NDR_LSA_CREATETRUSTEDDOMAINEX
, r
->in
.auth_info
);
1159 lsa_CreateTrustedDomain
1161 static NTSTATUS
dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1162 struct lsa_CreateTrustedDomain
*r
)
1164 struct lsa_CreateTrustedDomainEx2 r2
;
1166 r2
.in
.policy_handle
= r
->in
.policy_handle
;
1167 r2
.in
.info
= talloc(mem_ctx
, struct lsa_TrustDomainInfoInfoEx
);
1169 return NT_STATUS_NO_MEMORY
;
1172 r2
.in
.info
->domain_name
.string
= NULL
;
1173 r2
.in
.info
->netbios_name
= r
->in
.info
->name
;
1174 r2
.in
.info
->sid
= r
->in
.info
->sid
;
1175 r2
.in
.info
->trust_direction
= LSA_TRUST_DIRECTION_OUTBOUND
;
1176 r2
.in
.info
->trust_type
= LSA_TRUST_TYPE_DOWNLEVEL
;
1177 r2
.in
.info
->trust_attributes
= 0;
1179 r2
.in
.access_mask
= r
->in
.access_mask
;
1180 r2
.out
.trustdom_handle
= r
->out
.trustdom_handle
;
1182 return dcesrv_lsa_CreateTrustedDomain_base(dce_call
, mem_ctx
, &r2
, NDR_LSA_CREATETRUSTEDDOMAIN
, NULL
);
1187 lsa_OpenTrustedDomain
1189 static NTSTATUS
dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1190 struct lsa_OpenTrustedDomain
*r
)
1192 struct dcesrv_handle
*policy_handle
;
1194 struct lsa_policy_state
*policy_state
;
1195 struct lsa_trusted_domain_state
*trusted_domain_state
;
1196 struct dcesrv_handle
*handle
;
1197 struct ldb_message
**msgs
;
1198 const char *attrs
[] = {
1204 const char *sid_string
;
1207 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
1208 ZERO_STRUCTP(r
->out
.trustdom_handle
);
1209 policy_state
= policy_handle
->data
;
1211 trusted_domain_state
= talloc_zero(mem_ctx
, struct lsa_trusted_domain_state
);
1212 if (!trusted_domain_state
) {
1213 return NT_STATUS_NO_MEMORY
;
1215 trusted_domain_state
->policy
= policy_state
;
1217 sid_string
= dom_sid_string(mem_ctx
, r
->in
.sid
);
1219 return NT_STATUS_NO_MEMORY
;
1222 /* search for the trusted_domain record */
1223 ret
= gendb_search(trusted_domain_state
->policy
->sam_ldb
,
1224 mem_ctx
, policy_state
->system_dn
, &msgs
, attrs
,
1225 "(&(securityIdentifier=%s)(objectclass=trustedDomain))",
1228 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1232 DEBUG(0,("Found %d records matching DN %s\n", ret
,
1233 ldb_dn_get_linearized(policy_state
->system_dn
)));
1234 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1237 trusted_domain_state
->trusted_domain_dn
= talloc_reference(trusted_domain_state
, msgs
[0]->dn
);
1239 trusted_domain_state
->trusted_domain_user_dn
= NULL
;
1241 if (ldb_msg_find_attr_as_int(msgs
[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND
) {
1242 const char *flatname
= ldb_binary_encode_string(mem_ctx
, ldb_msg_find_attr_as_string(msgs
[0], "flatname", NULL
));
1243 /* search for the trusted_domain record */
1244 ret
= gendb_search(trusted_domain_state
->policy
->sam_ldb
,
1245 mem_ctx
, policy_state
->domain_dn
, &msgs
, attrs
,
1246 "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%u))",
1247 flatname
, UF_INTERDOMAIN_TRUST_ACCOUNT
);
1249 trusted_domain_state
->trusted_domain_user_dn
= talloc_steal(trusted_domain_state
, msgs
[0]->dn
);
1252 handle
= dcesrv_handle_new(dce_call
->context
, LSA_HANDLE_TRUSTED_DOMAIN
);
1254 return NT_STATUS_NO_MEMORY
;
1257 handle
->data
= talloc_steal(handle
, trusted_domain_state
);
1259 trusted_domain_state
->access_mask
= r
->in
.access_mask
;
1260 trusted_domain_state
->policy
= talloc_reference(trusted_domain_state
, policy_state
);
1262 *r
->out
.trustdom_handle
= handle
->wire_handle
;
1264 return NT_STATUS_OK
;
1269 lsa_OpenTrustedDomainByName
1271 static NTSTATUS
dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state
*dce_call
,
1272 TALLOC_CTX
*mem_ctx
,
1273 struct lsa_OpenTrustedDomainByName
*r
)
1275 struct dcesrv_handle
*policy_handle
;
1277 struct lsa_policy_state
*policy_state
;
1278 struct lsa_trusted_domain_state
*trusted_domain_state
;
1279 struct dcesrv_handle
*handle
;
1280 struct ldb_message
**msgs
;
1281 const char *attrs
[] = {
1287 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
1288 ZERO_STRUCTP(r
->out
.trustdom_handle
);
1289 policy_state
= policy_handle
->data
;
1291 if (!r
->in
.name
.string
) {
1292 return NT_STATUS_INVALID_PARAMETER
;
1295 trusted_domain_state
= talloc_zero(mem_ctx
, struct lsa_trusted_domain_state
);
1296 if (!trusted_domain_state
) {
1297 return NT_STATUS_NO_MEMORY
;
1299 trusted_domain_state
->policy
= policy_state
;
1301 /* search for the trusted_domain record */
1302 td_name
= ldb_binary_encode_string(mem_ctx
, r
->in
.name
.string
);
1303 ret
= gendb_search(trusted_domain_state
->policy
->sam_ldb
,
1304 mem_ctx
, policy_state
->system_dn
, &msgs
, attrs
,
1305 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1306 "(objectclass=trustedDomain))",
1307 td_name
, td_name
, td_name
);
1309 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1313 DEBUG(0,("Found %d records matching DN %s\n", ret
,
1314 ldb_dn_get_linearized(policy_state
->system_dn
)));
1315 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1318 /* TODO: perform access checks */
1320 trusted_domain_state
->trusted_domain_dn
= talloc_reference(trusted_domain_state
, msgs
[0]->dn
);
1322 handle
= dcesrv_handle_new(dce_call
->context
, LSA_HANDLE_TRUSTED_DOMAIN
);
1324 return NT_STATUS_NO_MEMORY
;
1327 handle
->data
= talloc_steal(handle
, trusted_domain_state
);
1329 trusted_domain_state
->access_mask
= r
->in
.access_mask
;
1330 trusted_domain_state
->policy
= talloc_reference(trusted_domain_state
, policy_state
);
1332 *r
->out
.trustdom_handle
= handle
->wire_handle
;
1334 return NT_STATUS_OK
;
1340 lsa_SetTrustedDomainInfo
1342 static NTSTATUS
dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1343 struct lsa_SetTrustedDomainInfo
*r
)
1345 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1350 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1351 * otherwise at least one must be provided */
1352 static NTSTATUS
get_tdo(struct ldb_context
*sam
, TALLOC_CTX
*mem_ctx
,
1353 struct ldb_dn
*basedn
, const char *dns_domain
,
1354 const char *netbios
, struct dom_sid2
*sid
,
1355 struct ldb_message
***msgs
)
1357 const char *attrs
[] = { "flatname", "trustPartner",
1358 "securityIdentifier", "trustDirection",
1359 "trustType", "trustAttributes",
1361 "msDs-supportedEncryptionTypes", NULL
};
1364 char *sidstr
= NULL
;
1369 if (dns_domain
|| netbios
|| sid
) {
1370 filter
= talloc_strdup(mem_ctx
,
1371 "(&(objectclass=trustedDomain)(|");
1373 filter
= talloc_strdup(mem_ctx
,
1374 "(objectclass=trustedDomain)");
1377 return NT_STATUS_NO_MEMORY
;
1381 dns
= ldb_binary_encode_string(mem_ctx
, dns_domain
);
1383 return NT_STATUS_NO_MEMORY
;
1385 filter
= talloc_asprintf_append(filter
,
1386 "(trustPartner=%s)", dns
);
1388 return NT_STATUS_NO_MEMORY
;
1392 nbn
= ldb_binary_encode_string(mem_ctx
, netbios
);
1394 return NT_STATUS_NO_MEMORY
;
1396 filter
= talloc_asprintf_append(filter
,
1397 "(flatname=%s)", nbn
);
1399 return NT_STATUS_NO_MEMORY
;
1403 sidstr
= dom_sid_string(mem_ctx
, sid
);
1405 return NT_STATUS_INVALID_PARAMETER
;
1407 filter
= talloc_asprintf_append(filter
,
1408 "(securityIdentifier=%s)",
1411 return NT_STATUS_NO_MEMORY
;
1414 if (dns_domain
|| netbios
|| sid
) {
1415 filter
= talloc_asprintf_append(filter
, "))");
1417 return NT_STATUS_NO_MEMORY
;
1421 ret
= gendb_search(sam
, mem_ctx
, basedn
, msgs
, attrs
, "%s", filter
);
1423 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1427 return NT_STATUS_OBJECT_NAME_COLLISION
;
1430 return NT_STATUS_OK
;
1433 static NTSTATUS
update_uint32_t_value(TALLOC_CTX
*mem_ctx
,
1434 struct ldb_context
*sam_ldb
,
1435 struct ldb_message
*orig
,
1436 struct ldb_message
*dest
,
1437 const char *attribute
,
1439 uint32_t *orig_value
)
1441 const struct ldb_val
*orig_val
;
1442 uint32_t orig_uint
= 0;
1443 unsigned int flags
= 0;
1446 orig_val
= ldb_msg_find_ldb_val(orig
, attribute
);
1447 if (!orig_val
|| !orig_val
->data
) {
1448 /* add new attribute */
1449 flags
= LDB_FLAG_MOD_ADD
;
1453 orig_uint
= strtoul((const char *)orig_val
->data
, NULL
, 0);
1454 if (errno
!= 0 || orig_uint
!= value
) {
1455 /* replace also if can't get value */
1456 flags
= LDB_FLAG_MOD_REPLACE
;
1461 /* stored value is identical, nothing to change */
1465 ret
= ldb_msg_add_empty(dest
, attribute
, flags
, NULL
);
1466 if (ret
!= LDB_SUCCESS
) {
1467 return NT_STATUS_NO_MEMORY
;
1470 ret
= samdb_msg_add_uint(sam_ldb
, dest
, dest
, attribute
, value
);
1471 if (ret
!= LDB_SUCCESS
) {
1472 return NT_STATUS_NO_MEMORY
;
1477 *orig_value
= orig_uint
;
1479 return NT_STATUS_OK
;
1482 static NTSTATUS
update_trust_user(TALLOC_CTX
*mem_ctx
,
1483 struct ldb_context
*sam_ldb
,
1484 struct ldb_dn
*base_dn
,
1486 const char *netbios_name
,
1487 struct trustAuthInOutBlob
*in
)
1489 const char *attrs
[] = { "userAccountControl", NULL
};
1490 struct ldb_message
**msgs
;
1491 struct ldb_message
*msg
;
1496 ret
= gendb_search(sam_ldb
, mem_ctx
,
1497 base_dn
, &msgs
, attrs
,
1498 "samAccountName=%s$", netbios_name
);
1500 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1505 return NT_STATUS_OK
;
1508 /* ok no existing user, add it from scratch */
1509 return add_trust_user(mem_ctx
, sam_ldb
, base_dn
,
1510 netbios_name
, in
, NULL
);
1513 /* check user is what we are looking for */
1514 uac
= ldb_msg_find_attr_as_uint(msgs
[0],
1515 "userAccountControl", 0);
1516 if (!(uac
& UF_INTERDOMAIN_TRUST_ACCOUNT
)) {
1517 return NT_STATUS_OBJECT_NAME_COLLISION
;
1521 ret
= ldb_delete(sam_ldb
, msgs
[0]->dn
);
1524 return NT_STATUS_OK
;
1525 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
:
1526 return NT_STATUS_ACCESS_DENIED
;
1528 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1532 /* entry exists, just modify secret if any */
1533 if (in
== NULL
|| in
->count
== 0) {
1534 return NT_STATUS_OK
;
1537 msg
= ldb_msg_new(mem_ctx
);
1539 return NT_STATUS_NO_MEMORY
;
1541 msg
->dn
= msgs
[0]->dn
;
1543 for (i
= 0; i
< in
->count
; i
++) {
1544 const char *attribute
;
1546 switch (in
->current
.array
[i
].AuthType
) {
1547 case TRUST_AUTH_TYPE_NT4OWF
:
1548 attribute
= "unicodePwd";
1549 v
.data
= (uint8_t *)&in
->current
.array
[i
].AuthInfo
.nt4owf
.password
;
1552 case TRUST_AUTH_TYPE_CLEAR
:
1553 attribute
= "clearTextPassword";
1554 v
.data
= in
->current
.array
[i
].AuthInfo
.clear
.password
;
1555 v
.length
= in
->current
.array
[i
].AuthInfo
.clear
.size
;
1561 ret
= ldb_msg_add_empty(msg
, attribute
,
1562 LDB_FLAG_MOD_REPLACE
, NULL
);
1563 if (ret
!= LDB_SUCCESS
) {
1564 return NT_STATUS_NO_MEMORY
;
1567 ret
= ldb_msg_add_value(msg
, attribute
, &v
, NULL
);
1568 if (ret
!= LDB_SUCCESS
) {
1569 return NT_STATUS_NO_MEMORY
;
1573 /* create the trusted_domain user account */
1574 ret
= ldb_modify(sam_ldb
, msg
);
1575 if (ret
!= LDB_SUCCESS
) {
1576 DEBUG(0,("Failed to create user record %s: %s\n",
1577 ldb_dn_get_linearized(msg
->dn
),
1578 ldb_errstring(sam_ldb
)));
1581 case LDB_ERR_ENTRY_ALREADY_EXISTS
:
1582 return NT_STATUS_DOMAIN_EXISTS
;
1583 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
:
1584 return NT_STATUS_ACCESS_DENIED
;
1586 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1590 return NT_STATUS_OK
;
1594 static NTSTATUS
setInfoTrustedDomain_base(struct dcesrv_call_state
*dce_call
,
1595 struct dcesrv_handle
*p_handle
,
1596 TALLOC_CTX
*mem_ctx
,
1597 struct ldb_message
*dom_msg
,
1598 enum lsa_TrustDomInfoEnum level
,
1599 union lsa_TrustedDomainInfo
*info
)
1601 struct lsa_policy_state
*p_state
= p_handle
->data
;
1602 uint32_t *posix_offset
= NULL
;
1603 struct lsa_TrustDomainInfoInfoEx
*info_ex
= NULL
;
1604 struct lsa_TrustDomainInfoAuthInfo
*auth_info
= NULL
;
1605 struct lsa_TrustDomainInfoAuthInfoInternal
*auth_info_int
= NULL
;
1606 uint32_t *enc_types
= NULL
;
1607 DATA_BLOB trustAuthIncoming
, trustAuthOutgoing
, auth_blob
;
1608 struct trustDomainPasswords auth_struct
;
1609 struct trustAuthInOutBlob
*current_passwords
= NULL
;
1611 struct ldb_message
**msgs
;
1612 struct ldb_message
*msg
;
1613 bool add_outgoing
= false;
1614 bool add_incoming
= false;
1615 bool del_outgoing
= false;
1616 bool del_incoming
= false;
1617 bool in_transaction
= false;
1622 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET
:
1623 posix_offset
= &info
->posix_offset
.posix_offset
;
1625 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX
:
1626 info_ex
= &info
->info_ex
;
1628 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO
:
1629 auth_info
= &info
->auth_info
;
1631 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO
:
1632 posix_offset
= &info
->full_info
.posix_offset
.posix_offset
;
1633 info_ex
= &info
->full_info
.info_ex
;
1634 auth_info
= &info
->full_info
.auth_info
;
1636 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL
:
1637 auth_info_int
= &info
->auth_info_internal
;
1639 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL
:
1640 posix_offset
= &info
->full_info_internal
.posix_offset
.posix_offset
;
1641 info_ex
= &info
->full_info_internal
.info_ex
;
1642 auth_info_int
= &info
->full_info_internal
.auth_info
;
1644 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES
:
1645 enc_types
= &info
->enc_types
.enc_types
;
1648 return NT_STATUS_INVALID_PARAMETER
;
1652 nt_status
= auth_info_2_auth_blob(mem_ctx
, auth_info
,
1654 &trustAuthOutgoing
);
1655 if (!NT_STATUS_IS_OK(nt_status
)) {
1658 if (trustAuthIncoming
.data
) {
1659 /* This does the decode of some of this twice, but it is easier that way */
1660 nt_status
= auth_info_2_trustauth_inout(mem_ctx
,
1661 auth_info
->incoming_count
,
1662 auth_info
->incoming_current_auth_info
,
1664 ¤t_passwords
);
1665 if (!NT_STATUS_IS_OK(nt_status
)) {
1671 /* decode auth_info_int if set */
1672 if (auth_info_int
) {
1674 /* now decrypt blob */
1675 auth_blob
= data_blob_const(auth_info_int
->auth_blob
.data
,
1676 auth_info_int
->auth_blob
.size
);
1678 nt_status
= get_trustdom_auth_blob(dce_call
, mem_ctx
,
1679 &auth_blob
, &auth_struct
);
1680 if (!NT_STATUS_IS_OK(nt_status
)) {
1686 /* verify data matches */
1687 if (info_ex
->trust_attributes
&
1688 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
) {
1689 /* TODO: check what behavior level we have */
1690 if (strcasecmp_m(p_state
->domain_dns
,
1691 p_state
->forest_dns
) != 0) {
1692 return NT_STATUS_INVALID_DOMAIN_STATE
;
1696 ret
= samdb_rodc(p_state
->sam_ldb
, &am_rodc
);
1697 if (ret
== LDB_SUCCESS
&& am_rodc
) {
1698 return NT_STATUS_NO_SUCH_DOMAIN
;
1701 /* verify only one object matches the dns/netbios/sid
1702 * triplet and that this is the one we already have */
1703 nt_status
= get_tdo(p_state
->sam_ldb
, mem_ctx
,
1705 info_ex
->domain_name
.string
,
1706 info_ex
->netbios_name
.string
,
1707 info_ex
->sid
, &msgs
);
1708 if (!NT_STATUS_IS_OK(nt_status
)) {
1711 if (ldb_dn_compare(dom_msg
->dn
, msgs
[0]->dn
) != 0) {
1712 return NT_STATUS_OBJECT_NAME_COLLISION
;
1717 /* TODO: should we fetch previous values from the existing entry
1718 * and append them ? */
1719 if (auth_info_int
&& auth_struct
.incoming
.count
) {
1720 nt_status
= get_trustauth_inout_blob(dce_call
, mem_ctx
,
1721 &auth_struct
.incoming
,
1722 &trustAuthIncoming
);
1723 if (!NT_STATUS_IS_OK(nt_status
)) {
1727 current_passwords
= &auth_struct
.incoming
;
1730 trustAuthIncoming
= data_blob(NULL
, 0);
1733 if (auth_info_int
&& auth_struct
.outgoing
.count
) {
1734 nt_status
= get_trustauth_inout_blob(dce_call
, mem_ctx
,
1735 &auth_struct
.outgoing
,
1736 &trustAuthOutgoing
);
1737 if (!NT_STATUS_IS_OK(nt_status
)) {
1741 trustAuthOutgoing
= data_blob(NULL
, 0);
1744 msg
= ldb_msg_new(mem_ctx
);
1746 return NT_STATUS_NO_MEMORY
;
1748 msg
->dn
= dom_msg
->dn
;
1751 nt_status
= update_uint32_t_value(mem_ctx
, p_state
->sam_ldb
,
1754 *posix_offset
, NULL
);
1755 if (!NT_STATUS_IS_OK(nt_status
)) {
1765 nt_status
= update_uint32_t_value(mem_ctx
, p_state
->sam_ldb
,
1768 info_ex
->trust_direction
,
1770 if (!NT_STATUS_IS_OK(nt_status
)) {
1774 if (info_ex
->trust_direction
& LSA_TRUST_DIRECTION_INBOUND
) {
1775 add_incoming
= true;
1777 if (info_ex
->trust_direction
& LSA_TRUST_DIRECTION_OUTBOUND
) {
1778 add_outgoing
= true;
1781 if ((origdir
& LSA_TRUST_DIRECTION_INBOUND
) &&
1782 !(info_ex
->trust_direction
& LSA_TRUST_DIRECTION_INBOUND
)) {
1783 del_incoming
= true;
1785 if ((origdir
& LSA_TRUST_DIRECTION_OUTBOUND
) &&
1786 !(info_ex
->trust_direction
& LSA_TRUST_DIRECTION_OUTBOUND
)) {
1787 del_outgoing
= true;
1790 origtype
= ldb_msg_find_attr_as_int(dom_msg
, "trustType", -1);
1791 if (origtype
== -1 || origtype
!= info_ex
->trust_type
) {
1792 DEBUG(1, ("Attempted to change trust type! "
1793 "Operation not handled\n"));
1794 return NT_STATUS_INVALID_PARAMETER
;
1797 nt_status
= update_uint32_t_value(mem_ctx
, p_state
->sam_ldb
,
1800 info_ex
->trust_attributes
,
1802 if (!NT_STATUS_IS_OK(nt_status
)) {
1805 /* TODO: check forestFunctionality from ldb opaque */
1806 /* TODO: check what is set makes sense */
1807 /* for now refuse changes */
1808 if (origattrs
== -1 ||
1809 origattrs
!= info_ex
->trust_attributes
) {
1810 DEBUG(1, ("Attempted to change trust attributes! "
1811 "Operation not handled\n"));
1812 return NT_STATUS_INVALID_PARAMETER
;
1817 nt_status
= update_uint32_t_value(mem_ctx
, p_state
->sam_ldb
,
1819 "msDS-SupportedEncryptionTypes",
1821 if (!NT_STATUS_IS_OK(nt_status
)) {
1826 if (add_incoming
&& trustAuthIncoming
.data
) {
1827 ret
= ldb_msg_add_empty(msg
, "trustAuthIncoming",
1828 LDB_FLAG_MOD_REPLACE
, NULL
);
1829 if (ret
!= LDB_SUCCESS
) {
1830 return NT_STATUS_NO_MEMORY
;
1832 ret
= ldb_msg_add_value(msg
, "trustAuthIncoming",
1833 &trustAuthIncoming
, NULL
);
1834 if (ret
!= LDB_SUCCESS
) {
1835 return NT_STATUS_NO_MEMORY
;
1838 if (add_outgoing
&& trustAuthOutgoing
.data
) {
1839 ret
= ldb_msg_add_empty(msg
, "trustAuthOutgoing",
1840 LDB_FLAG_MOD_REPLACE
, NULL
);
1841 if (ret
!= LDB_SUCCESS
) {
1842 return NT_STATUS_NO_MEMORY
;
1844 ret
= ldb_msg_add_value(msg
, "trustAuthOutgoing",
1845 &trustAuthOutgoing
, NULL
);
1846 if (ret
!= LDB_SUCCESS
) {
1847 return NT_STATUS_NO_MEMORY
;
1851 /* start transaction */
1852 ret
= ldb_transaction_start(p_state
->sam_ldb
);
1853 if (ret
!= LDB_SUCCESS
) {
1854 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1856 in_transaction
= true;
1858 if (msg
->num_elements
) {
1859 ret
= ldb_modify(p_state
->sam_ldb
, msg
);
1860 if (ret
!= LDB_SUCCESS
) {
1861 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1862 ldb_dn_get_linearized(msg
->dn
),
1863 ldb_errstring(p_state
->sam_ldb
)));
1864 nt_status
= dsdb_ldb_err_to_ntstatus(ret
);
1869 if (add_incoming
|| del_incoming
) {
1870 const char *netbios_name
;
1872 netbios_name
= ldb_msg_find_attr_as_string(dom_msg
,
1874 if (!netbios_name
) {
1875 nt_status
= NT_STATUS_INVALID_DOMAIN_STATE
;
1879 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
1880 nt_status
= update_trust_user(mem_ctx
,
1886 if (!NT_STATUS_IS_OK(nt_status
)) {
1891 /* ok, all fine, commit transaction and return */
1892 ret
= ldb_transaction_commit(p_state
->sam_ldb
);
1893 if (ret
!= LDB_SUCCESS
) {
1894 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1896 in_transaction
= false;
1898 nt_status
= NT_STATUS_OK
;
1901 if (in_transaction
) {
1902 ldb_transaction_cancel(p_state
->sam_ldb
);
1908 lsa_SetInfomrationTrustedDomain
1910 static NTSTATUS
dcesrv_lsa_SetInformationTrustedDomain(
1911 struct dcesrv_call_state
*dce_call
,
1912 TALLOC_CTX
*mem_ctx
,
1913 struct lsa_SetInformationTrustedDomain
*r
)
1915 struct dcesrv_handle
*h
;
1916 struct lsa_trusted_domain_state
*td_state
;
1917 struct ldb_message
**msgs
;
1920 DCESRV_PULL_HANDLE(h
, r
->in
.trustdom_handle
,
1921 LSA_HANDLE_TRUSTED_DOMAIN
);
1923 td_state
= talloc_get_type(h
->data
, struct lsa_trusted_domain_state
);
1925 /* get the trusted domain object */
1926 nt_status
= get_tdo(td_state
->policy
->sam_ldb
, mem_ctx
,
1927 td_state
->trusted_domain_dn
,
1928 NULL
, NULL
, NULL
, &msgs
);
1929 if (!NT_STATUS_IS_OK(nt_status
)) {
1930 if (NT_STATUS_EQUAL(nt_status
,
1931 NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1934 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1937 return setInfoTrustedDomain_base(dce_call
, h
, mem_ctx
,
1938 msgs
[0], r
->in
.level
, r
->in
.info
);
1943 lsa_DeleteTrustedDomain
1945 static NTSTATUS
dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1946 struct lsa_DeleteTrustedDomain
*r
)
1949 struct lsa_OpenTrustedDomain opn
;
1950 struct lsa_DeleteObject del
;
1951 struct dcesrv_handle
*h
;
1953 opn
.in
.handle
= r
->in
.handle
;
1954 opn
.in
.sid
= r
->in
.dom_sid
;
1955 opn
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
1956 opn
.out
.trustdom_handle
= talloc(mem_ctx
, struct policy_handle
);
1957 if (!opn
.out
.trustdom_handle
) {
1958 return NT_STATUS_NO_MEMORY
;
1960 status
= dcesrv_lsa_OpenTrustedDomain(dce_call
, mem_ctx
, &opn
);
1961 if (!NT_STATUS_IS_OK(status
)) {
1965 DCESRV_PULL_HANDLE(h
, opn
.out
.trustdom_handle
, DCESRV_HANDLE_ANY
);
1966 talloc_steal(mem_ctx
, h
);
1968 del
.in
.handle
= opn
.out
.trustdom_handle
;
1969 del
.out
.handle
= opn
.out
.trustdom_handle
;
1970 status
= dcesrv_lsa_DeleteObject(dce_call
, mem_ctx
, &del
);
1971 if (!NT_STATUS_IS_OK(status
)) {
1974 return NT_STATUS_OK
;
1977 static NTSTATUS
fill_trust_domain_ex(TALLOC_CTX
*mem_ctx
,
1978 struct ldb_message
*msg
,
1979 struct lsa_TrustDomainInfoInfoEx
*info_ex
)
1981 info_ex
->domain_name
.string
1982 = ldb_msg_find_attr_as_string(msg
, "trustPartner", NULL
);
1983 info_ex
->netbios_name
.string
1984 = ldb_msg_find_attr_as_string(msg
, "flatname", NULL
);
1986 = samdb_result_dom_sid(mem_ctx
, msg
, "securityIdentifier");
1987 info_ex
->trust_direction
1988 = ldb_msg_find_attr_as_int(msg
, "trustDirection", 0);
1990 = ldb_msg_find_attr_as_int(msg
, "trustType", 0);
1991 info_ex
->trust_attributes
1992 = ldb_msg_find_attr_as_int(msg
, "trustAttributes", 0);
1993 return NT_STATUS_OK
;
1997 lsa_QueryTrustedDomainInfo
1999 static NTSTATUS
dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2000 struct lsa_QueryTrustedDomainInfo
*r
)
2002 union lsa_TrustedDomainInfo
*info
= NULL
;
2003 struct dcesrv_handle
*h
;
2004 struct lsa_trusted_domain_state
*trusted_domain_state
;
2005 struct ldb_message
*msg
;
2007 struct ldb_message
**res
;
2008 const char *attrs
[] = {
2011 "securityIdentifier",
2015 "msDs-supportedEncryptionTypes",
2019 DCESRV_PULL_HANDLE(h
, r
->in
.trustdom_handle
, LSA_HANDLE_TRUSTED_DOMAIN
);
2021 trusted_domain_state
= talloc_get_type(h
->data
, struct lsa_trusted_domain_state
);
2023 /* pull all the user attributes */
2024 ret
= gendb_search_dn(trusted_domain_state
->policy
->sam_ldb
, mem_ctx
,
2025 trusted_domain_state
->trusted_domain_dn
, &res
, attrs
);
2027 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2031 info
= talloc_zero(mem_ctx
, union lsa_TrustedDomainInfo
);
2033 return NT_STATUS_NO_MEMORY
;
2035 *r
->out
.info
= info
;
2037 switch (r
->in
.level
) {
2038 case LSA_TRUSTED_DOMAIN_INFO_NAME
:
2039 info
->name
.netbios_name
.string
2040 = ldb_msg_find_attr_as_string(msg
, "flatname", NULL
);
2042 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET
:
2043 info
->posix_offset
.posix_offset
2044 = ldb_msg_find_attr_as_uint(msg
, "posixOffset", 0);
2046 #if 0 /* Win2k3 doesn't implement this */
2047 case LSA_TRUSTED_DOMAIN_INFO_BASIC
:
2048 r
->out
.info
->info_basic
.netbios_name
.string
2049 = ldb_msg_find_attr_as_string(msg
, "flatname", NULL
);
2050 r
->out
.info
->info_basic
.sid
2051 = samdb_result_dom_sid(mem_ctx
, msg
, "securityIdentifier");
2054 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX
:
2055 return fill_trust_domain_ex(mem_ctx
, msg
, &info
->info_ex
);
2057 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO
:
2058 ZERO_STRUCT(info
->full_info
);
2059 return fill_trust_domain_ex(mem_ctx
, msg
, &info
->full_info
.info_ex
);
2060 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL
:
2061 ZERO_STRUCT(info
->full_info2_internal
);
2062 info
->full_info2_internal
.posix_offset
.posix_offset
2063 = ldb_msg_find_attr_as_uint(msg
, "posixOffset", 0);
2064 return fill_trust_domain_ex(mem_ctx
, msg
, &info
->full_info2_internal
.info
.info_ex
);
2066 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES
:
2067 info
->enc_types
.enc_types
2068 = ldb_msg_find_attr_as_uint(msg
, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5
);
2071 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS
:
2072 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL
:
2073 /* oops, we don't want to return the info after all */
2075 *r
->out
.info
= NULL
;
2076 return NT_STATUS_INVALID_PARAMETER
;
2078 /* oops, we don't want to return the info after all */
2080 *r
->out
.info
= NULL
;
2081 return NT_STATUS_INVALID_INFO_CLASS
;
2084 return NT_STATUS_OK
;
2089 lsa_QueryTrustedDomainInfoBySid
2091 static NTSTATUS
dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2092 struct lsa_QueryTrustedDomainInfoBySid
*r
)
2095 struct lsa_OpenTrustedDomain opn
;
2096 struct lsa_QueryTrustedDomainInfo query
;
2097 struct dcesrv_handle
*h
;
2099 opn
.in
.handle
= r
->in
.handle
;
2100 opn
.in
.sid
= r
->in
.dom_sid
;
2101 opn
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2102 opn
.out
.trustdom_handle
= talloc(mem_ctx
, struct policy_handle
);
2103 if (!opn
.out
.trustdom_handle
) {
2104 return NT_STATUS_NO_MEMORY
;
2106 status
= dcesrv_lsa_OpenTrustedDomain(dce_call
, mem_ctx
, &opn
);
2107 if (!NT_STATUS_IS_OK(status
)) {
2111 /* Ensure this handle goes away at the end of this call */
2112 DCESRV_PULL_HANDLE(h
, opn
.out
.trustdom_handle
, DCESRV_HANDLE_ANY
);
2113 talloc_steal(mem_ctx
, h
);
2115 query
.in
.trustdom_handle
= opn
.out
.trustdom_handle
;
2116 query
.in
.level
= r
->in
.level
;
2117 query
.out
.info
= r
->out
.info
;
2118 status
= dcesrv_lsa_QueryTrustedDomainInfo(dce_call
, mem_ctx
, &query
);
2119 if (!NT_STATUS_IS_OK(status
)) {
2123 return NT_STATUS_OK
;
2127 lsa_SetTrustedDomainInfoByName
2129 static NTSTATUS
dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state
*dce_call
,
2130 TALLOC_CTX
*mem_ctx
,
2131 struct lsa_SetTrustedDomainInfoByName
*r
)
2133 struct dcesrv_handle
*policy_handle
;
2134 struct lsa_policy_state
*policy_state
;
2135 struct ldb_message
**msgs
;
2138 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
2139 policy_state
= policy_handle
->data
;
2141 /* get the trusted domain object */
2142 nt_status
= get_tdo(policy_state
->sam_ldb
, mem_ctx
,
2143 policy_state
->domain_dn
,
2144 r
->in
.trusted_domain
->string
,
2145 r
->in
.trusted_domain
->string
,
2147 if (!NT_STATUS_IS_OK(nt_status
)) {
2148 if (NT_STATUS_EQUAL(nt_status
,
2149 NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
2152 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2155 return setInfoTrustedDomain_base(dce_call
, policy_handle
, mem_ctx
,
2156 msgs
[0], r
->in
.level
, r
->in
.info
);
2160 lsa_QueryTrustedDomainInfoByName
2162 static NTSTATUS
dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state
*dce_call
,
2163 TALLOC_CTX
*mem_ctx
,
2164 struct lsa_QueryTrustedDomainInfoByName
*r
)
2167 struct lsa_OpenTrustedDomainByName opn
;
2168 struct lsa_QueryTrustedDomainInfo query
;
2169 struct dcesrv_handle
*h
;
2171 opn
.in
.handle
= r
->in
.handle
;
2172 opn
.in
.name
= *r
->in
.trusted_domain
;
2173 opn
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2174 opn
.out
.trustdom_handle
= talloc(mem_ctx
, struct policy_handle
);
2175 if (!opn
.out
.trustdom_handle
) {
2176 return NT_STATUS_NO_MEMORY
;
2178 status
= dcesrv_lsa_OpenTrustedDomainByName(dce_call
, mem_ctx
, &opn
);
2179 if (!NT_STATUS_IS_OK(status
)) {
2183 /* Ensure this handle goes away at the end of this call */
2184 DCESRV_PULL_HANDLE(h
, opn
.out
.trustdom_handle
, DCESRV_HANDLE_ANY
);
2185 talloc_steal(mem_ctx
, h
);
2187 query
.in
.trustdom_handle
= opn
.out
.trustdom_handle
;
2188 query
.in
.level
= r
->in
.level
;
2189 query
.out
.info
= r
->out
.info
;
2190 status
= dcesrv_lsa_QueryTrustedDomainInfo(dce_call
, mem_ctx
, &query
);
2191 if (!NT_STATUS_IS_OK(status
)) {
2195 return NT_STATUS_OK
;
2199 lsa_CloseTrustedDomainEx
2201 static NTSTATUS
dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state
*dce_call
,
2202 TALLOC_CTX
*mem_ctx
,
2203 struct lsa_CloseTrustedDomainEx
*r
)
2205 /* The result of a bad hair day from an IDL programmer? Not
2206 * implmented in Win2k3. You should always just lsa_Close
2208 return NT_STATUS_NOT_IMPLEMENTED
;
2213 comparison function for sorting lsa_DomainInformation array
2215 static int compare_DomainInfo(struct lsa_DomainInfo
*e1
, struct lsa_DomainInfo
*e2
)
2217 return strcasecmp_m(e1
->name
.string
, e2
->name
.string
);
2223 static NTSTATUS
dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2224 struct lsa_EnumTrustDom
*r
)
2226 struct dcesrv_handle
*policy_handle
;
2227 struct lsa_DomainInfo
*entries
;
2228 struct lsa_policy_state
*policy_state
;
2229 struct ldb_message
**domains
;
2230 const char *attrs
[] = {
2232 "securityIdentifier",
2239 *r
->out
.resume_handle
= 0;
2241 r
->out
.domains
->domains
= NULL
;
2242 r
->out
.domains
->count
= 0;
2244 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
2246 policy_state
= policy_handle
->data
;
2248 /* search for all users in this domain. This could possibly be cached and
2249 resumed based on resume_key */
2250 count
= gendb_search(policy_state
->sam_ldb
, mem_ctx
, policy_state
->system_dn
, &domains
, attrs
,
2251 "objectclass=trustedDomain");
2253 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2256 /* convert to lsa_TrustInformation format */
2257 entries
= talloc_array(mem_ctx
, struct lsa_DomainInfo
, count
);
2259 return NT_STATUS_NO_MEMORY
;
2261 for (i
=0;i
<count
;i
++) {
2262 entries
[i
].sid
= samdb_result_dom_sid(mem_ctx
, domains
[i
], "securityIdentifier");
2263 entries
[i
].name
.string
= ldb_msg_find_attr_as_string(domains
[i
], "flatname", NULL
);
2266 /* sort the results by name */
2267 TYPESAFE_QSORT(entries
, count
, compare_DomainInfo
);
2269 if (*r
->in
.resume_handle
>= count
) {
2270 *r
->out
.resume_handle
= -1;
2272 return NT_STATUS_NO_MORE_ENTRIES
;
2275 /* return the rest, limit by max_size. Note that we
2276 use the w2k3 element size value of 60 */
2277 r
->out
.domains
->count
= count
- *r
->in
.resume_handle
;
2278 r
->out
.domains
->count
= MIN(r
->out
.domains
->count
,
2279 1+(r
->in
.max_size
/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER
));
2281 r
->out
.domains
->domains
= entries
+ *r
->in
.resume_handle
;
2282 r
->out
.domains
->count
= r
->out
.domains
->count
;
2284 if (r
->out
.domains
->count
< count
- *r
->in
.resume_handle
) {
2285 *r
->out
.resume_handle
= *r
->in
.resume_handle
+ r
->out
.domains
->count
;
2286 return STATUS_MORE_ENTRIES
;
2289 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2290 * always be larger than the previous input resume handle, in
2291 * particular when hitting the last query it is vital to set the
2292 * resume handle correctly to avoid infinite client loops, as
2293 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2294 * status is NT_STATUS_OK - gd */
2296 *r
->out
.resume_handle
= (uint32_t)-1;
2298 return NT_STATUS_OK
;
2302 comparison function for sorting lsa_DomainInformation array
2304 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx
*e1
, struct lsa_TrustDomainInfoInfoEx
*e2
)
2306 return strcasecmp_m(e1
->netbios_name
.string
, e2
->netbios_name
.string
);
2310 lsa_EnumTrustedDomainsEx
2312 static NTSTATUS
dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2313 struct lsa_EnumTrustedDomainsEx
*r
)
2315 struct dcesrv_handle
*policy_handle
;
2316 struct lsa_TrustDomainInfoInfoEx
*entries
;
2317 struct lsa_policy_state
*policy_state
;
2318 struct ldb_message
**domains
;
2319 const char *attrs
[] = {
2322 "securityIdentifier",
2332 *r
->out
.resume_handle
= 0;
2334 r
->out
.domains
->domains
= NULL
;
2335 r
->out
.domains
->count
= 0;
2337 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
2339 policy_state
= policy_handle
->data
;
2341 /* search for all users in this domain. This could possibly be cached and
2342 resumed based on resume_key */
2343 count
= gendb_search(policy_state
->sam_ldb
, mem_ctx
, policy_state
->system_dn
, &domains
, attrs
,
2344 "objectclass=trustedDomain");
2346 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2349 /* convert to lsa_DomainInformation format */
2350 entries
= talloc_array(mem_ctx
, struct lsa_TrustDomainInfoInfoEx
, count
);
2352 return NT_STATUS_NO_MEMORY
;
2354 for (i
=0;i
<count
;i
++) {
2355 nt_status
= fill_trust_domain_ex(mem_ctx
, domains
[i
], &entries
[i
]);
2356 if (!NT_STATUS_IS_OK(nt_status
)) {
2361 /* sort the results by name */
2362 TYPESAFE_QSORT(entries
, count
, compare_TrustDomainInfoInfoEx
);
2364 if (*r
->in
.resume_handle
>= count
) {
2365 *r
->out
.resume_handle
= -1;
2367 return NT_STATUS_NO_MORE_ENTRIES
;
2370 /* return the rest, limit by max_size. Note that we
2371 use the w2k3 element size value of 60 */
2372 r
->out
.domains
->count
= count
- *r
->in
.resume_handle
;
2373 r
->out
.domains
->count
= MIN(r
->out
.domains
->count
,
2374 1+(r
->in
.max_size
/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER
));
2376 r
->out
.domains
->domains
= entries
+ *r
->in
.resume_handle
;
2377 r
->out
.domains
->count
= r
->out
.domains
->count
;
2379 if (r
->out
.domains
->count
< count
- *r
->in
.resume_handle
) {
2380 *r
->out
.resume_handle
= *r
->in
.resume_handle
+ r
->out
.domains
->count
;
2381 return STATUS_MORE_ENTRIES
;
2384 return NT_STATUS_OK
;
2391 static NTSTATUS
dcesrv_lsa_OpenAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2392 struct lsa_OpenAccount
*r
)
2394 struct dcesrv_handle
*h
, *ah
;
2395 struct lsa_policy_state
*state
;
2396 struct lsa_account_state
*astate
;
2398 ZERO_STRUCTP(r
->out
.acct_handle
);
2400 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
2404 astate
= talloc(dce_call
->conn
, struct lsa_account_state
);
2405 if (astate
== NULL
) {
2406 return NT_STATUS_NO_MEMORY
;
2409 astate
->account_sid
= dom_sid_dup(astate
, r
->in
.sid
);
2410 if (astate
->account_sid
== NULL
) {
2411 talloc_free(astate
);
2412 return NT_STATUS_NO_MEMORY
;
2415 astate
->policy
= talloc_reference(astate
, state
);
2416 astate
->access_mask
= r
->in
.access_mask
;
2418 ah
= dcesrv_handle_new(dce_call
->context
, LSA_HANDLE_ACCOUNT
);
2420 talloc_free(astate
);
2421 return NT_STATUS_NO_MEMORY
;
2424 ah
->data
= talloc_steal(ah
, astate
);
2426 *r
->out
.acct_handle
= ah
->wire_handle
;
2428 return NT_STATUS_OK
;
2433 lsa_EnumPrivsAccount
2435 static NTSTATUS
dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state
*dce_call
,
2436 TALLOC_CTX
*mem_ctx
,
2437 struct lsa_EnumPrivsAccount
*r
)
2439 struct dcesrv_handle
*h
;
2440 struct lsa_account_state
*astate
;
2443 struct ldb_message
**res
;
2444 const char * const attrs
[] = { "privilege", NULL
};
2445 struct ldb_message_element
*el
;
2447 struct lsa_PrivilegeSet
*privs
;
2449 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_ACCOUNT
);
2453 privs
= talloc(mem_ctx
, struct lsa_PrivilegeSet
);
2454 if (privs
== NULL
) {
2455 return NT_STATUS_NO_MEMORY
;
2461 *r
->out
.privs
= privs
;
2463 sidstr
= ldap_encode_ndr_dom_sid(mem_ctx
, astate
->account_sid
);
2464 if (sidstr
== NULL
) {
2465 return NT_STATUS_NO_MEMORY
;
2468 ret
= gendb_search(astate
->policy
->pdb
, mem_ctx
, NULL
, &res
, attrs
,
2469 "objectSid=%s", sidstr
);
2471 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2474 return NT_STATUS_OK
;
2477 el
= ldb_msg_find_element(res
[0], "privilege");
2478 if (el
== NULL
|| el
->num_values
== 0) {
2479 return NT_STATUS_OK
;
2482 privs
->set
= talloc_array(privs
,
2483 struct lsa_LUIDAttribute
, el
->num_values
);
2484 if (privs
->set
== NULL
) {
2485 return NT_STATUS_NO_MEMORY
;
2489 for (i
=0;i
<el
->num_values
;i
++) {
2490 int id
= sec_privilege_id((const char *)el
->values
[i
].data
);
2491 if (id
== SEC_PRIV_INVALID
) {
2492 /* Perhaps an account right, not a privilege */
2495 privs
->set
[j
].attribute
= 0;
2496 privs
->set
[j
].luid
.low
= id
;
2497 privs
->set
[j
].luid
.high
= 0;
2503 return NT_STATUS_OK
;
2507 lsa_EnumAccountRights
2509 static NTSTATUS
dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state
*dce_call
,
2510 TALLOC_CTX
*mem_ctx
,
2511 struct lsa_EnumAccountRights
*r
)
2513 struct dcesrv_handle
*h
;
2514 struct lsa_policy_state
*state
;
2517 struct ldb_message
**res
;
2518 const char * const attrs
[] = { "privilege", NULL
};
2520 struct ldb_message_element
*el
;
2522 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
2526 sidstr
= ldap_encode_ndr_dom_sid(mem_ctx
, r
->in
.sid
);
2527 if (sidstr
== NULL
) {
2528 return NT_STATUS_NO_MEMORY
;
2531 ret
= gendb_search(state
->pdb
, mem_ctx
, NULL
, &res
, attrs
,
2532 "(&(objectSid=%s)(privilege=*))", sidstr
);
2534 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
2537 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2538 dom_sid_string(mem_ctx
, r
->in
.sid
),
2539 ldb_errstring(state
->pdb
)));
2540 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2543 el
= ldb_msg_find_element(res
[0], "privilege");
2544 if (el
== NULL
|| el
->num_values
== 0) {
2545 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
2548 r
->out
.rights
->count
= el
->num_values
;
2549 r
->out
.rights
->names
= talloc_array(r
->out
.rights
,
2550 struct lsa_StringLarge
, r
->out
.rights
->count
);
2551 if (r
->out
.rights
->names
== NULL
) {
2552 return NT_STATUS_NO_MEMORY
;
2555 for (i
=0;i
<el
->num_values
;i
++) {
2556 r
->out
.rights
->names
[i
].string
= (const char *)el
->values
[i
].data
;
2559 return NT_STATUS_OK
;
2565 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2567 static NTSTATUS
dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state
*dce_call
,
2568 TALLOC_CTX
*mem_ctx
,
2569 struct lsa_policy_state
*state
,
2571 struct dom_sid
*sid
,
2572 const struct lsa_RightSet
*rights
)
2574 const char *sidstr
, *sidndrstr
;
2575 struct ldb_message
*msg
;
2576 struct ldb_message_element
*el
;
2579 struct lsa_EnumAccountRights r2
;
2582 if (security_session_user_level(dce_call
->conn
->auth_state
.session_info
, NULL
) <
2583 SECURITY_ADMINISTRATOR
) {
2584 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2585 return NT_STATUS_ACCESS_DENIED
;
2588 msg
= ldb_msg_new(mem_ctx
);
2590 return NT_STATUS_NO_MEMORY
;
2593 sidndrstr
= ldap_encode_ndr_dom_sid(msg
, sid
);
2594 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr
, msg
);
2596 sidstr
= dom_sid_string(msg
, sid
);
2597 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr
, msg
);
2599 dnstr
= talloc_asprintf(msg
, "sid=%s", sidstr
);
2600 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr
, msg
);
2602 msg
->dn
= ldb_dn_new(msg
, state
->pdb
, dnstr
);
2603 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg
->dn
, msg
);
2605 if (LDB_FLAG_MOD_TYPE(ldb_flag
) == LDB_FLAG_MOD_ADD
) {
2608 r2
.in
.handle
= &state
->handle
->wire_handle
;
2610 r2
.out
.rights
= talloc(mem_ctx
, struct lsa_RightSet
);
2612 status
= dcesrv_lsa_EnumAccountRights(dce_call
, mem_ctx
, &r2
);
2613 if (!NT_STATUS_IS_OK(status
)) {
2614 ZERO_STRUCTP(r2
.out
.rights
);
2618 for (i
=0;i
<rights
->count
;i
++) {
2619 if (sec_privilege_id(rights
->names
[i
].string
) == SEC_PRIV_INVALID
) {
2620 if (sec_right_bit(rights
->names
[i
].string
) == 0) {
2622 return NT_STATUS_NO_SUCH_PRIVILEGE
;
2626 return NT_STATUS_NO_SUCH_PRIVILEGE
;
2629 if (LDB_FLAG_MOD_TYPE(ldb_flag
) == LDB_FLAG_MOD_ADD
) {
2631 for (j
=0;j
<r2
.out
.rights
->count
;j
++) {
2632 if (strcasecmp_m(r2
.out
.rights
->names
[j
].string
,
2633 rights
->names
[i
].string
) == 0) {
2637 if (j
!= r2
.out
.rights
->count
) continue;
2640 ret
= ldb_msg_add_string(msg
, "privilege", rights
->names
[i
].string
);
2641 if (ret
!= LDB_SUCCESS
) {
2643 return NT_STATUS_NO_MEMORY
;
2647 el
= ldb_msg_find_element(msg
, "privilege");
2650 return NT_STATUS_OK
;
2653 el
->flags
= ldb_flag
;
2655 ret
= ldb_modify(state
->pdb
, msg
);
2656 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
2657 if (samdb_msg_add_dom_sid(state
->pdb
, msg
, msg
, "objectSid", sid
) != LDB_SUCCESS
) {
2659 return NT_STATUS_NO_MEMORY
;
2661 ldb_msg_add_string(msg
, "comment", "added via LSA");
2662 ret
= ldb_add(state
->pdb
, msg
);
2664 if (ret
!= LDB_SUCCESS
) {
2665 if (LDB_FLAG_MOD_TYPE(ldb_flag
) == LDB_FLAG_MOD_DELETE
&& ret
== LDB_ERR_NO_SUCH_ATTRIBUTE
) {
2667 return NT_STATUS_OK
;
2669 DEBUG(3, ("Could not %s attributes from %s: %s",
2670 LDB_FLAG_MOD_TYPE(ldb_flag
) == LDB_FLAG_MOD_DELETE
? "delete" : "add",
2671 ldb_dn_get_linearized(msg
->dn
), ldb_errstring(state
->pdb
)));
2673 return NT_STATUS_UNEXPECTED_IO_ERROR
;
2677 return NT_STATUS_OK
;
2681 lsa_AddPrivilegesToAccount
2683 static NTSTATUS
dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2684 struct lsa_AddPrivilegesToAccount
*r
)
2686 struct lsa_RightSet rights
;
2687 struct dcesrv_handle
*h
;
2688 struct lsa_account_state
*astate
;
2691 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_ACCOUNT
);
2695 rights
.count
= r
->in
.privs
->count
;
2696 rights
.names
= talloc_array(mem_ctx
, struct lsa_StringLarge
, rights
.count
);
2697 if (rights
.names
== NULL
) {
2698 return NT_STATUS_NO_MEMORY
;
2700 for (i
=0;i
<rights
.count
;i
++) {
2701 int id
= r
->in
.privs
->set
[i
].luid
.low
;
2702 if (r
->in
.privs
->set
[i
].luid
.high
) {
2703 return NT_STATUS_NO_SUCH_PRIVILEGE
;
2705 rights
.names
[i
].string
= sec_privilege_name(id
);
2706 if (rights
.names
[i
].string
== NULL
) {
2707 return NT_STATUS_NO_SUCH_PRIVILEGE
;
2711 return dcesrv_lsa_AddRemoveAccountRights(dce_call
, mem_ctx
, astate
->policy
,
2712 LDB_FLAG_MOD_ADD
, astate
->account_sid
,
2718 lsa_RemovePrivilegesFromAccount
2720 static NTSTATUS
dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2721 struct lsa_RemovePrivilegesFromAccount
*r
)
2723 struct lsa_RightSet
*rights
;
2724 struct dcesrv_handle
*h
;
2725 struct lsa_account_state
*astate
;
2728 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_ACCOUNT
);
2732 rights
= talloc(mem_ctx
, struct lsa_RightSet
);
2734 if (r
->in
.remove_all
== 1 &&
2735 r
->in
.privs
== NULL
) {
2736 struct lsa_EnumAccountRights r2
;
2739 r2
.in
.handle
= &astate
->policy
->handle
->wire_handle
;
2740 r2
.in
.sid
= astate
->account_sid
;
2741 r2
.out
.rights
= rights
;
2743 status
= dcesrv_lsa_EnumAccountRights(dce_call
, mem_ctx
, &r2
);
2744 if (!NT_STATUS_IS_OK(status
)) {
2748 return dcesrv_lsa_AddRemoveAccountRights(dce_call
, mem_ctx
, astate
->policy
,
2749 LDB_FLAG_MOD_DELETE
, astate
->account_sid
,
2753 if (r
->in
.remove_all
!= 0) {
2754 return NT_STATUS_INVALID_PARAMETER
;
2757 rights
->count
= r
->in
.privs
->count
;
2758 rights
->names
= talloc_array(mem_ctx
, struct lsa_StringLarge
, rights
->count
);
2759 if (rights
->names
== NULL
) {
2760 return NT_STATUS_NO_MEMORY
;
2762 for (i
=0;i
<rights
->count
;i
++) {
2763 int id
= r
->in
.privs
->set
[i
].luid
.low
;
2764 if (r
->in
.privs
->set
[i
].luid
.high
) {
2765 return NT_STATUS_NO_SUCH_PRIVILEGE
;
2767 rights
->names
[i
].string
= sec_privilege_name(id
);
2768 if (rights
->names
[i
].string
== NULL
) {
2769 return NT_STATUS_NO_SUCH_PRIVILEGE
;
2773 return dcesrv_lsa_AddRemoveAccountRights(dce_call
, mem_ctx
, astate
->policy
,
2774 LDB_FLAG_MOD_DELETE
, astate
->account_sid
,
2780 lsa_GetQuotasForAccount
2782 static NTSTATUS
dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2783 struct lsa_GetQuotasForAccount
*r
)
2785 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
2790 lsa_SetQuotasForAccount
2792 static NTSTATUS
dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2793 struct lsa_SetQuotasForAccount
*r
)
2795 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
2800 lsa_GetSystemAccessAccount
2802 static NTSTATUS
dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2803 struct lsa_GetSystemAccessAccount
*r
)
2805 struct dcesrv_handle
*h
;
2806 struct lsa_account_state
*astate
;
2809 struct ldb_message
**res
;
2810 const char * const attrs
[] = { "privilege", NULL
};
2811 struct ldb_message_element
*el
;
2814 *(r
->out
.access_mask
) = 0x00000000;
2816 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_ACCOUNT
);
2820 sidstr
= ldap_encode_ndr_dom_sid(mem_ctx
, astate
->account_sid
);
2821 if (sidstr
== NULL
) {
2822 return NT_STATUS_NO_MEMORY
;
2825 ret
= gendb_search(astate
->policy
->pdb
, mem_ctx
, NULL
, &res
, attrs
,
2826 "objectSid=%s", sidstr
);
2828 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2831 return NT_STATUS_OK
;
2834 el
= ldb_msg_find_element(res
[0], "privilege");
2835 if (el
== NULL
|| el
->num_values
== 0) {
2836 return NT_STATUS_OK
;
2839 for (i
=0;i
<el
->num_values
;i
++) {
2840 uint32_t right_bit
= sec_right_bit((const char *)el
->values
[i
].data
);
2841 if (right_bit
== 0) {
2842 /* Perhaps an privilege, not a right */
2845 *(r
->out
.access_mask
) |= right_bit
;
2848 return NT_STATUS_OK
;
2853 lsa_SetSystemAccessAccount
2855 static NTSTATUS
dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2856 struct lsa_SetSystemAccessAccount
*r
)
2858 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
2865 static NTSTATUS
dcesrv_lsa_CreateSecret(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2866 struct lsa_CreateSecret
*r
)
2868 struct dcesrv_handle
*policy_handle
;
2869 struct lsa_policy_state
*policy_state
;
2870 struct lsa_secret_state
*secret_state
;
2871 struct dcesrv_handle
*handle
;
2872 struct ldb_message
**msgs
, *msg
;
2873 const char *attrs
[] = {
2881 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
2882 ZERO_STRUCTP(r
->out
.sec_handle
);
2884 switch (security_session_user_level(dce_call
->conn
->auth_state
.session_info
, NULL
))
2886 case SECURITY_SYSTEM
:
2887 case SECURITY_ADMINISTRATOR
:
2890 /* Users and annonymous are not allowed create secrets */
2891 return NT_STATUS_ACCESS_DENIED
;
2894 policy_state
= policy_handle
->data
;
2896 if (!r
->in
.name
.string
) {
2897 return NT_STATUS_INVALID_PARAMETER
;
2900 secret_state
= talloc(mem_ctx
, struct lsa_secret_state
);
2901 NT_STATUS_HAVE_NO_MEMORY(secret_state
);
2902 secret_state
->policy
= policy_state
;
2904 msg
= ldb_msg_new(mem_ctx
);
2906 return NT_STATUS_NO_MEMORY
;
2909 if (strncmp("G$", r
->in
.name
.string
, 2) == 0) {
2912 secret_state
->global
= true;
2914 name
= &r
->in
.name
.string
[2];
2915 if (strlen(name
) == 0) {
2916 return NT_STATUS_INVALID_PARAMETER
;
2919 name2
= talloc_asprintf(mem_ctx
, "%s Secret",
2920 ldb_binary_encode_string(mem_ctx
, name
));
2921 NT_STATUS_HAVE_NO_MEMORY(name2
);
2923 /* We need to connect to the database as system, as this is one
2924 * of the rare RPC calls that must read the secrets (and this
2925 * is denied otherwise) */
2926 secret_state
->sam_ldb
= talloc_reference(secret_state
,
2927 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));
2928 NT_STATUS_HAVE_NO_MEMORY(secret_state
->sam_ldb
);
2930 /* search for the secret record */
2931 ret
= gendb_search(secret_state
->sam_ldb
,
2932 mem_ctx
, policy_state
->system_dn
, &msgs
, attrs
,
2933 "(&(cn=%s)(objectclass=secret))",
2936 return NT_STATUS_OBJECT_NAME_COLLISION
;
2940 DEBUG(0,("Failure searching for CN=%s: %s\n",
2941 name2
, ldb_errstring(secret_state
->sam_ldb
)));
2942 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2945 msg
->dn
= ldb_dn_copy(mem_ctx
, policy_state
->system_dn
);
2946 NT_STATUS_HAVE_NO_MEMORY(msg
->dn
);
2947 if (!ldb_dn_add_child_fmt(msg
->dn
, "cn=%s", name2
)) {
2948 return NT_STATUS_NO_MEMORY
;
2951 ret
= ldb_msg_add_string(msg
, "cn", name2
);
2952 if (ret
!= LDB_SUCCESS
) return NT_STATUS_NO_MEMORY
;
2954 secret_state
->global
= false;
2956 name
= r
->in
.name
.string
;
2957 if (strlen(name
) == 0) {
2958 return NT_STATUS_INVALID_PARAMETER
;
2961 secret_state
->sam_ldb
= talloc_reference(secret_state
,
2962 secrets_db_connect(mem_ctx
, dce_call
->conn
->dce_ctx
->lp_ctx
));
2963 NT_STATUS_HAVE_NO_MEMORY(secret_state
->sam_ldb
);
2965 /* search for the secret record */
2966 ret
= gendb_search(secret_state
->sam_ldb
, mem_ctx
,
2967 ldb_dn_new(mem_ctx
, secret_state
->sam_ldb
, "cn=LSA Secrets"),
2969 "(&(cn=%s)(objectclass=secret))",
2970 ldb_binary_encode_string(mem_ctx
, name
));
2972 return NT_STATUS_OBJECT_NAME_COLLISION
;
2976 DEBUG(0,("Failure searching for CN=%s: %s\n",
2977 name
, ldb_errstring(secret_state
->sam_ldb
)));
2978 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2981 msg
->dn
= ldb_dn_new_fmt(mem_ctx
, secret_state
->sam_ldb
,
2982 "cn=%s,cn=LSA Secrets", name
);
2983 NT_STATUS_HAVE_NO_MEMORY(msg
->dn
);
2984 ret
= ldb_msg_add_string(msg
, "cn", name
);
2985 if (ret
!= LDB_SUCCESS
) return NT_STATUS_NO_MEMORY
;
2988 ret
= ldb_msg_add_string(msg
, "objectClass", "secret");
2989 if (ret
!= LDB_SUCCESS
) return NT_STATUS_NO_MEMORY
;
2991 secret_state
->secret_dn
= talloc_reference(secret_state
, msg
->dn
);
2992 NT_STATUS_HAVE_NO_MEMORY(secret_state
->secret_dn
);
2994 /* create the secret */
2995 ret
= ldb_add(secret_state
->sam_ldb
, msg
);
2996 if (ret
!= LDB_SUCCESS
) {
2997 DEBUG(0,("Failed to create secret record %s: %s\n",
2998 ldb_dn_get_linearized(msg
->dn
),
2999 ldb_errstring(secret_state
->sam_ldb
)));
3000 return NT_STATUS_ACCESS_DENIED
;
3003 handle
= dcesrv_handle_new(dce_call
->context
, LSA_HANDLE_SECRET
);
3004 NT_STATUS_HAVE_NO_MEMORY(handle
);
3006 handle
->data
= talloc_steal(handle
, secret_state
);
3008 secret_state
->access_mask
= r
->in
.access_mask
;
3009 secret_state
->policy
= talloc_reference(secret_state
, policy_state
);
3010 NT_STATUS_HAVE_NO_MEMORY(secret_state
->policy
);
3012 *r
->out
.sec_handle
= handle
->wire_handle
;
3014 return NT_STATUS_OK
;
3021 static NTSTATUS
dcesrv_lsa_OpenSecret(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3022 struct lsa_OpenSecret
*r
)
3024 struct dcesrv_handle
*policy_handle
;
3026 struct lsa_policy_state
*policy_state
;
3027 struct lsa_secret_state
*secret_state
;
3028 struct dcesrv_handle
*handle
;
3029 struct ldb_message
**msgs
;
3030 const char *attrs
[] = {
3038 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3039 ZERO_STRUCTP(r
->out
.sec_handle
);
3040 policy_state
= policy_handle
->data
;
3042 if (!r
->in
.name
.string
) {
3043 return NT_STATUS_INVALID_PARAMETER
;
3046 switch (security_session_user_level(dce_call
->conn
->auth_state
.session_info
, NULL
))
3048 case SECURITY_SYSTEM
:
3049 case SECURITY_ADMINISTRATOR
:
3052 /* Users and annonymous are not allowed to access secrets */
3053 return NT_STATUS_ACCESS_DENIED
;
3056 secret_state
= talloc(mem_ctx
, struct lsa_secret_state
);
3057 if (!secret_state
) {
3058 return NT_STATUS_NO_MEMORY
;
3060 secret_state
->policy
= policy_state
;
3062 if (strncmp("G$", r
->in
.name
.string
, 2) == 0) {
3063 name
= &r
->in
.name
.string
[2];
3064 /* 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) */
3065 secret_state
->sam_ldb
= talloc_reference(secret_state
,
3066 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));
3067 secret_state
->global
= true;
3069 if (strlen(name
) < 1) {
3070 return NT_STATUS_INVALID_PARAMETER
;
3073 /* search for the secret record */
3074 ret
= gendb_search(secret_state
->sam_ldb
,
3075 mem_ctx
, policy_state
->system_dn
, &msgs
, attrs
,
3076 "(&(cn=%s Secret)(objectclass=secret))",
3077 ldb_binary_encode_string(mem_ctx
, name
));
3079 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3083 DEBUG(0,("Found %d records matching DN %s\n", ret
,
3084 ldb_dn_get_linearized(policy_state
->system_dn
)));
3085 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
3089 secret_state
->global
= false;
3090 secret_state
->sam_ldb
= talloc_reference(secret_state
,
3091 secrets_db_connect(mem_ctx
, dce_call
->conn
->dce_ctx
->lp_ctx
));
3093 name
= r
->in
.name
.string
;
3094 if (strlen(name
) < 1) {
3095 return NT_STATUS_INVALID_PARAMETER
;
3098 /* search for the secret record */
3099 ret
= gendb_search(secret_state
->sam_ldb
, mem_ctx
,
3100 ldb_dn_new(mem_ctx
, secret_state
->sam_ldb
, "cn=LSA Secrets"),
3102 "(&(cn=%s)(objectclass=secret))",
3103 ldb_binary_encode_string(mem_ctx
, name
));
3105 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3109 DEBUG(0,("Found %d records matching CN=%s\n",
3110 ret
, ldb_binary_encode_string(mem_ctx
, name
)));
3111 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
3115 secret_state
->secret_dn
= talloc_reference(secret_state
, msgs
[0]->dn
);
3117 handle
= dcesrv_handle_new(dce_call
->context
, LSA_HANDLE_SECRET
);
3119 return NT_STATUS_NO_MEMORY
;
3122 handle
->data
= talloc_steal(handle
, secret_state
);
3124 secret_state
->access_mask
= r
->in
.access_mask
;
3125 secret_state
->policy
= talloc_reference(secret_state
, policy_state
);
3127 *r
->out
.sec_handle
= handle
->wire_handle
;
3129 return NT_STATUS_OK
;
3136 static NTSTATUS
dcesrv_lsa_SetSecret(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3137 struct lsa_SetSecret
*r
)
3140 struct dcesrv_handle
*h
;
3141 struct lsa_secret_state
*secret_state
;
3142 struct ldb_message
*msg
;
3143 DATA_BLOB session_key
;
3144 DATA_BLOB crypt_secret
, secret
;
3147 NTSTATUS status
= NT_STATUS_OK
;
3149 struct timeval now
= timeval_current();
3150 NTTIME nt_now
= timeval_to_nttime(&now
);
3152 DCESRV_PULL_HANDLE(h
, r
->in
.sec_handle
, LSA_HANDLE_SECRET
);
3154 secret_state
= h
->data
;
3156 msg
= ldb_msg_new(mem_ctx
);
3158 return NT_STATUS_NO_MEMORY
;
3161 msg
->dn
= talloc_reference(mem_ctx
, secret_state
->secret_dn
);
3163 return NT_STATUS_NO_MEMORY
;
3165 status
= dcesrv_fetch_session_key(dce_call
->conn
, &session_key
);
3166 if (!NT_STATUS_IS_OK(status
)) {
3170 if (r
->in
.old_val
) {
3172 crypt_secret
.data
= r
->in
.old_val
->data
;
3173 crypt_secret
.length
= r
->in
.old_val
->size
;
3175 status
= sess_decrypt_blob(mem_ctx
, &crypt_secret
, &session_key
, &secret
);
3176 if (!NT_STATUS_IS_OK(status
)) {
3180 val
.data
= secret
.data
;
3181 val
.length
= secret
.length
;
3184 if (ldb_msg_add_value(msg
, "priorValue", &val
, NULL
) != LDB_SUCCESS
) {
3185 return NT_STATUS_NO_MEMORY
;
3188 /* set old value mtime */
3189 if (samdb_msg_add_uint64(secret_state
->sam_ldb
,
3190 mem_ctx
, msg
, "priorSetTime", nt_now
) != LDB_SUCCESS
) {
3191 return NT_STATUS_NO_MEMORY
;
3195 /* If the old value is not set, then migrate the
3196 * current value to the old value */
3197 const struct ldb_val
*old_val
;
3198 NTTIME last_set_time
;
3199 struct ldb_message
**res
;
3200 const char *attrs
[] = {
3206 /* search for the secret record */
3207 ret
= gendb_search_dn(secret_state
->sam_ldb
,mem_ctx
,
3208 secret_state
->secret_dn
, &res
, attrs
);
3210 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3214 DEBUG(0,("Found %d records matching dn=%s\n", ret
,
3215 ldb_dn_get_linearized(secret_state
->secret_dn
)));
3216 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
3219 old_val
= ldb_msg_find_ldb_val(res
[0], "currentValue");
3220 last_set_time
= ldb_msg_find_attr_as_uint64(res
[0], "lastSetTime", 0);
3224 if (ldb_msg_add_value(msg
, "priorValue",
3225 old_val
, NULL
) != LDB_SUCCESS
) {
3226 return NT_STATUS_NO_MEMORY
;
3229 if (samdb_msg_add_delete(secret_state
->sam_ldb
,
3230 mem_ctx
, msg
, "priorValue") != LDB_SUCCESS
) {
3231 return NT_STATUS_NO_MEMORY
;
3236 /* set old value mtime */
3237 if (ldb_msg_find_ldb_val(res
[0], "lastSetTime")) {
3238 if (samdb_msg_add_uint64(secret_state
->sam_ldb
,
3239 mem_ctx
, msg
, "priorSetTime", last_set_time
) != LDB_SUCCESS
) {
3240 return NT_STATUS_NO_MEMORY
;
3243 if (samdb_msg_add_uint64(secret_state
->sam_ldb
,
3244 mem_ctx
, msg
, "priorSetTime", nt_now
) != LDB_SUCCESS
) {
3245 return NT_STATUS_NO_MEMORY
;
3250 if (r
->in
.new_val
) {
3252 crypt_secret
.data
= r
->in
.new_val
->data
;
3253 crypt_secret
.length
= r
->in
.new_val
->size
;
3255 status
= sess_decrypt_blob(mem_ctx
, &crypt_secret
, &session_key
, &secret
);
3256 if (!NT_STATUS_IS_OK(status
)) {
3260 val
.data
= secret
.data
;
3261 val
.length
= secret
.length
;
3264 if (ldb_msg_add_value(msg
, "currentValue", &val
, NULL
) != LDB_SUCCESS
) {
3265 return NT_STATUS_NO_MEMORY
;
3268 /* set new value mtime */
3269 if (samdb_msg_add_uint64(secret_state
->sam_ldb
,
3270 mem_ctx
, msg
, "lastSetTime", nt_now
) != LDB_SUCCESS
) {
3271 return NT_STATUS_NO_MEMORY
;
3275 /* NULL out the NEW value */
3276 if (samdb_msg_add_uint64(secret_state
->sam_ldb
,
3277 mem_ctx
, msg
, "lastSetTime", nt_now
) != LDB_SUCCESS
) {
3278 return NT_STATUS_NO_MEMORY
;
3280 if (samdb_msg_add_delete(secret_state
->sam_ldb
,
3281 mem_ctx
, msg
, "currentValue") != LDB_SUCCESS
) {
3282 return NT_STATUS_NO_MEMORY
;
3286 /* modify the samdb record */
3287 ret
= dsdb_replace(secret_state
->sam_ldb
, msg
, 0);
3288 if (ret
!= LDB_SUCCESS
) {
3289 return dsdb_ldb_err_to_ntstatus(ret
);
3292 return NT_STATUS_OK
;
3299 static NTSTATUS
dcesrv_lsa_QuerySecret(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3300 struct lsa_QuerySecret
*r
)
3302 struct dcesrv_handle
*h
;
3303 struct lsa_secret_state
*secret_state
;
3304 struct ldb_message
*msg
;
3305 DATA_BLOB session_key
;
3306 DATA_BLOB crypt_secret
, secret
;
3308 struct ldb_message
**res
;
3309 const char *attrs
[] = {
3319 DCESRV_PULL_HANDLE(h
, r
->in
.sec_handle
, LSA_HANDLE_SECRET
);
3321 /* Ensure user is permitted to read this... */
3322 switch (security_session_user_level(dce_call
->conn
->auth_state
.session_info
, NULL
))
3324 case SECURITY_SYSTEM
:
3325 case SECURITY_ADMINISTRATOR
:
3328 /* Users and annonymous are not allowed to read secrets */
3329 return NT_STATUS_ACCESS_DENIED
;
3332 secret_state
= h
->data
;
3334 /* pull all the user attributes */
3335 ret
= gendb_search_dn(secret_state
->sam_ldb
, mem_ctx
,
3336 secret_state
->secret_dn
, &res
, attrs
);
3338 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
3342 nt_status
= dcesrv_fetch_session_key(dce_call
->conn
, &session_key
);
3343 if (!NT_STATUS_IS_OK(nt_status
)) {
3347 if (r
->in
.old_val
) {
3348 const struct ldb_val
*prior_val
;
3349 r
->out
.old_val
= talloc_zero(mem_ctx
, struct lsa_DATA_BUF_PTR
);
3350 if (!r
->out
.old_val
) {
3351 return NT_STATUS_NO_MEMORY
;
3353 prior_val
= ldb_msg_find_ldb_val(res
[0], "priorValue");
3355 if (prior_val
&& prior_val
->length
) {
3356 secret
.data
= prior_val
->data
;
3357 secret
.length
= prior_val
->length
;
3360 crypt_secret
= sess_encrypt_blob(mem_ctx
, &secret
, &session_key
);
3361 if (!crypt_secret
.length
) {
3362 return NT_STATUS_NO_MEMORY
;
3364 r
->out
.old_val
->buf
= talloc(mem_ctx
, struct lsa_DATA_BUF
);
3365 if (!r
->out
.old_val
->buf
) {
3366 return NT_STATUS_NO_MEMORY
;
3368 r
->out
.old_val
->buf
->size
= crypt_secret
.length
;
3369 r
->out
.old_val
->buf
->length
= crypt_secret
.length
;
3370 r
->out
.old_val
->buf
->data
= crypt_secret
.data
;
3374 if (r
->in
.old_mtime
) {
3375 r
->out
.old_mtime
= talloc(mem_ctx
, NTTIME
);
3376 if (!r
->out
.old_mtime
) {
3377 return NT_STATUS_NO_MEMORY
;
3379 *r
->out
.old_mtime
= ldb_msg_find_attr_as_uint64(res
[0], "priorSetTime", 0);
3382 if (r
->in
.new_val
) {
3383 const struct ldb_val
*new_val
;
3384 r
->out
.new_val
= talloc_zero(mem_ctx
, struct lsa_DATA_BUF_PTR
);
3385 if (!r
->out
.new_val
) {
3386 return NT_STATUS_NO_MEMORY
;
3389 new_val
= ldb_msg_find_ldb_val(res
[0], "currentValue");
3391 if (new_val
&& new_val
->length
) {
3392 secret
.data
= new_val
->data
;
3393 secret
.length
= new_val
->length
;
3396 crypt_secret
= sess_encrypt_blob(mem_ctx
, &secret
, &session_key
);
3397 if (!crypt_secret
.length
) {
3398 return NT_STATUS_NO_MEMORY
;
3400 r
->out
.new_val
->buf
= talloc(mem_ctx
, struct lsa_DATA_BUF
);
3401 if (!r
->out
.new_val
->buf
) {
3402 return NT_STATUS_NO_MEMORY
;
3404 r
->out
.new_val
->buf
->length
= crypt_secret
.length
;
3405 r
->out
.new_val
->buf
->size
= crypt_secret
.length
;
3406 r
->out
.new_val
->buf
->data
= crypt_secret
.data
;
3410 if (r
->in
.new_mtime
) {
3411 r
->out
.new_mtime
= talloc(mem_ctx
, NTTIME
);
3412 if (!r
->out
.new_mtime
) {
3413 return NT_STATUS_NO_MEMORY
;
3415 *r
->out
.new_mtime
= ldb_msg_find_attr_as_uint64(res
[0], "lastSetTime", 0);
3418 return NT_STATUS_OK
;
3425 static NTSTATUS
dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state
*dce_call
,
3426 TALLOC_CTX
*mem_ctx
,
3427 struct lsa_LookupPrivValue
*r
)
3429 struct dcesrv_handle
*h
;
3430 struct lsa_policy_state
*state
;
3433 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3437 id
= sec_privilege_id(r
->in
.name
->string
);
3438 if (id
== SEC_PRIV_INVALID
) {
3439 return NT_STATUS_NO_SUCH_PRIVILEGE
;
3442 r
->out
.luid
->low
= id
;
3443 r
->out
.luid
->high
= 0;
3445 return NT_STATUS_OK
;
3452 static NTSTATUS
dcesrv_lsa_LookupPrivName(struct dcesrv_call_state
*dce_call
,
3453 TALLOC_CTX
*mem_ctx
,
3454 struct lsa_LookupPrivName
*r
)
3456 struct dcesrv_handle
*h
;
3457 struct lsa_policy_state
*state
;
3458 struct lsa_StringLarge
*name
;
3459 const char *privname
;
3461 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3465 if (r
->in
.luid
->high
!= 0) {
3466 return NT_STATUS_NO_SUCH_PRIVILEGE
;
3469 privname
= sec_privilege_name(r
->in
.luid
->low
);
3470 if (privname
== NULL
) {
3471 return NT_STATUS_NO_SUCH_PRIVILEGE
;
3474 name
= talloc(mem_ctx
, struct lsa_StringLarge
);
3476 return NT_STATUS_NO_MEMORY
;
3479 name
->string
= privname
;
3481 *r
->out
.name
= name
;
3483 return NT_STATUS_OK
;
3488 lsa_LookupPrivDisplayName
3490 static NTSTATUS
dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state
*dce_call
,
3491 TALLOC_CTX
*mem_ctx
,
3492 struct lsa_LookupPrivDisplayName
*r
)
3494 struct dcesrv_handle
*h
;
3495 struct lsa_policy_state
*state
;
3496 struct lsa_StringLarge
*disp_name
= NULL
;
3497 enum sec_privilege id
;
3499 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3503 id
= sec_privilege_id(r
->in
.name
->string
);
3504 if (id
== SEC_PRIV_INVALID
) {
3505 return NT_STATUS_NO_SUCH_PRIVILEGE
;
3508 disp_name
= talloc(mem_ctx
, struct lsa_StringLarge
);
3509 if (disp_name
== NULL
) {
3510 return NT_STATUS_NO_MEMORY
;
3513 disp_name
->string
= sec_privilege_display_name(id
, &r
->in
.language_id
);
3514 if (disp_name
->string
== NULL
) {
3515 return NT_STATUS_INTERNAL_ERROR
;
3518 *r
->out
.disp_name
= disp_name
;
3519 *r
->out
.returned_language_id
= 0;
3521 return NT_STATUS_OK
;
3526 lsa_EnumAccountsWithUserRight
3528 static NTSTATUS
dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state
*dce_call
,
3529 TALLOC_CTX
*mem_ctx
,
3530 struct lsa_EnumAccountsWithUserRight
*r
)
3532 struct dcesrv_handle
*h
;
3533 struct lsa_policy_state
*state
;
3535 struct ldb_message
**res
;
3536 const char * const attrs
[] = { "objectSid", NULL
};
3537 const char *privname
;
3539 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3543 if (r
->in
.name
== NULL
) {
3544 return NT_STATUS_NO_SUCH_PRIVILEGE
;
3547 privname
= r
->in
.name
->string
;
3548 if (sec_privilege_id(privname
) == SEC_PRIV_INVALID
&& sec_right_bit(privname
) == 0) {
3549 return NT_STATUS_NO_SUCH_PRIVILEGE
;
3552 ret
= gendb_search(state
->pdb
, mem_ctx
, NULL
, &res
, attrs
,
3553 "privilege=%s", privname
);
3555 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
3558 return NT_STATUS_NO_MORE_ENTRIES
;
3561 r
->out
.sids
->sids
= talloc_array(r
->out
.sids
, struct lsa_SidPtr
, ret
);
3562 if (r
->out
.sids
->sids
== NULL
) {
3563 return NT_STATUS_NO_MEMORY
;
3565 for (i
=0;i
<ret
;i
++) {
3566 r
->out
.sids
->sids
[i
].sid
= samdb_result_dom_sid(r
->out
.sids
->sids
,
3567 res
[i
], "objectSid");
3568 NT_STATUS_HAVE_NO_MEMORY(r
->out
.sids
->sids
[i
].sid
);
3570 r
->out
.sids
->num_sids
= ret
;
3572 return NT_STATUS_OK
;
3577 lsa_AddAccountRights
3579 static NTSTATUS
dcesrv_lsa_AddAccountRights(struct dcesrv_call_state
*dce_call
,
3580 TALLOC_CTX
*mem_ctx
,
3581 struct lsa_AddAccountRights
*r
)
3583 struct dcesrv_handle
*h
;
3584 struct lsa_policy_state
*state
;
3586 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3590 return dcesrv_lsa_AddRemoveAccountRights(dce_call
, mem_ctx
, state
,
3592 r
->in
.sid
, r
->in
.rights
);
3597 lsa_RemoveAccountRights
3599 static NTSTATUS
dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state
*dce_call
,
3600 TALLOC_CTX
*mem_ctx
,
3601 struct lsa_RemoveAccountRights
*r
)
3603 struct dcesrv_handle
*h
;
3604 struct lsa_policy_state
*state
;
3606 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3610 return dcesrv_lsa_AddRemoveAccountRights(dce_call
, mem_ctx
, state
,
3611 LDB_FLAG_MOD_DELETE
,
3612 r
->in
.sid
, r
->in
.rights
);
3617 lsa_StorePrivateData
3619 static NTSTATUS
dcesrv_lsa_StorePrivateData(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3620 struct lsa_StorePrivateData
*r
)
3622 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3627 lsa_RetrievePrivateData
3629 static NTSTATUS
dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3630 struct lsa_RetrievePrivateData
*r
)
3632 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3639 static NTSTATUS
dcesrv_lsa_GetUserName(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3640 struct lsa_GetUserName
*r
)
3642 enum dcerpc_transport_t transport
= dce_call
->conn
->endpoint
->ep_description
->transport
;
3643 NTSTATUS status
= NT_STATUS_OK
;
3644 const char *account_name
;
3645 const char *authority_name
;
3646 struct lsa_String
*_account_name
;
3647 struct lsa_String
*_authority_name
= NULL
;
3649 if (transport
!= NCACN_NP
&& transport
!= NCALRPC
) {
3650 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED
);
3653 /* this is what w2k3 does */
3654 r
->out
.account_name
= r
->in
.account_name
;
3655 r
->out
.authority_name
= r
->in
.authority_name
;
3657 if (r
->in
.account_name
3658 && *r
->in
.account_name
3659 /* && *(*r->in.account_name)->string */
3661 return NT_STATUS_INVALID_PARAMETER
;
3664 if (r
->in
.authority_name
3665 && *r
->in
.authority_name
3666 /* && *(*r->in.authority_name)->string */
3668 return NT_STATUS_INVALID_PARAMETER
;
3671 account_name
= talloc_reference(mem_ctx
, dce_call
->conn
->auth_state
.session_info
->info
->account_name
);
3672 authority_name
= talloc_reference(mem_ctx
, dce_call
->conn
->auth_state
.session_info
->info
->domain_name
);
3674 _account_name
= talloc(mem_ctx
, struct lsa_String
);
3675 NT_STATUS_HAVE_NO_MEMORY(_account_name
);
3676 _account_name
->string
= account_name
;
3678 if (r
->in
.authority_name
) {
3679 _authority_name
= talloc(mem_ctx
, struct lsa_String
);
3680 NT_STATUS_HAVE_NO_MEMORY(_authority_name
);
3681 _authority_name
->string
= authority_name
;
3684 *r
->out
.account_name
= _account_name
;
3685 if (r
->out
.authority_name
) {
3686 *r
->out
.authority_name
= _authority_name
;
3695 static NTSTATUS
dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state
*dce_call
,
3696 TALLOC_CTX
*mem_ctx
,
3697 struct lsa_SetInfoPolicy2
*r
)
3699 /* need to support these */
3700 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3703 static void kdc_get_policy(struct loadparm_context
*lp_ctx
,
3704 struct smb_krb5_context
*smb_krb5_context
,
3705 struct lsa_DomainInfoKerberos
*k
)
3707 time_t svc_tkt_lifetime
;
3708 time_t usr_tkt_lifetime
;
3709 time_t renewal_lifetime
;
3711 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
3713 /* Our KDC always re-validates the client */
3714 k
->authentication_options
= LSA_POLICY_KERBEROS_VALIDATE_CLIENT
;
3716 lpcfg_default_kdc_policy(lp_ctx
, &svc_tkt_lifetime
,
3717 &usr_tkt_lifetime
, &renewal_lifetime
);
3719 unix_to_nt_time(&k
->service_tkt_lifetime
, svc_tkt_lifetime
);
3720 unix_to_nt_time(&k
->user_tkt_lifetime
, usr_tkt_lifetime
);
3721 unix_to_nt_time(&k
->user_tkt_renewaltime
, renewal_lifetime
);
3722 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
3723 However in the parent function we basically just did a full
3724 krb5_context init with the only purpose of getting a global
3725 config option (the max skew), it would probably make more sense
3726 to have a lp_ or ldb global option as the samba default */
3727 if (smb_krb5_context
) {
3728 unix_to_nt_time(&k
->clock_skew
,
3729 krb5_get_max_time_skew(smb_krb5_context
->krb5_context
));
3735 lsa_QueryDomainInformationPolicy
3737 static NTSTATUS
dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state
*dce_call
,
3738 TALLOC_CTX
*mem_ctx
,
3739 struct lsa_QueryDomainInformationPolicy
*r
)
3741 union lsa_DomainInformationPolicy
*info
;
3743 info
= talloc_zero(r
->out
.info
, union lsa_DomainInformationPolicy
);
3745 return NT_STATUS_NO_MEMORY
;
3748 switch (r
->in
.level
) {
3749 case LSA_DOMAIN_INFO_POLICY_EFS
:
3751 *r
->out
.info
= NULL
;
3752 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3753 case LSA_DOMAIN_INFO_POLICY_KERBEROS
:
3755 struct lsa_DomainInfoKerberos
*k
= &info
->kerberos_info
;
3756 struct smb_krb5_context
*smb_krb5_context
;
3757 int ret
= smb_krb5_init_context(mem_ctx
,
3758 dce_call
->event_ctx
,
3759 dce_call
->conn
->dce_ctx
->lp_ctx
,
3763 *r
->out
.info
= NULL
;
3764 return NT_STATUS_INTERNAL_ERROR
;
3766 kdc_get_policy(dce_call
->conn
->dce_ctx
->lp_ctx
,
3769 talloc_free(smb_krb5_context
);
3770 *r
->out
.info
= info
;
3771 return NT_STATUS_OK
;
3775 *r
->out
.info
= NULL
;
3776 return NT_STATUS_INVALID_INFO_CLASS
;
3781 lsa_SetDomInfoPolicy
3783 static NTSTATUS
dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state
*dce_call
,
3784 TALLOC_CTX
*mem_ctx
,
3785 struct lsa_SetDomainInformationPolicy
*r
)
3787 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3793 static NTSTATUS
dcesrv_lsa_TestCall(struct dcesrv_call_state
*dce_call
,
3794 TALLOC_CTX
*mem_ctx
,
3795 struct lsa_TestCall
*r
)
3797 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3803 static NTSTATUS
dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3804 struct lsa_CREDRWRITE
*r
)
3806 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3813 static NTSTATUS
dcesrv_lsa_CREDRREAD(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3814 struct lsa_CREDRREAD
*r
)
3816 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3823 static NTSTATUS
dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3824 struct lsa_CREDRENUMERATE
*r
)
3826 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3831 lsa_CREDRWRITEDOMAINCREDENTIALS
3833 static NTSTATUS
dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3834 struct lsa_CREDRWRITEDOMAINCREDENTIALS
*r
)
3836 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3841 lsa_CREDRREADDOMAINCREDENTIALS
3843 static NTSTATUS
dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3844 struct lsa_CREDRREADDOMAINCREDENTIALS
*r
)
3846 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3853 static NTSTATUS
dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3854 struct lsa_CREDRDELETE
*r
)
3856 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3861 lsa_CREDRGETTARGETINFO
3863 static NTSTATUS
dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3864 struct lsa_CREDRGETTARGETINFO
*r
)
3866 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3871 lsa_CREDRPROFILELOADED
3873 static NTSTATUS
dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3874 struct lsa_CREDRPROFILELOADED
*r
)
3876 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3881 lsa_CREDRGETSESSIONTYPES
3883 static NTSTATUS
dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3884 struct lsa_CREDRGETSESSIONTYPES
*r
)
3886 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3891 lsa_LSARREGISTERAUDITEVENT
3893 static NTSTATUS
dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3894 struct lsa_LSARREGISTERAUDITEVENT
*r
)
3896 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3901 lsa_LSARGENAUDITEVENT
3903 static NTSTATUS
dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3904 struct lsa_LSARGENAUDITEVENT
*r
)
3906 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3911 lsa_LSARUNREGISTERAUDITEVENT
3913 static NTSTATUS
dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3914 struct lsa_LSARUNREGISTERAUDITEVENT
*r
)
3916 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3921 lsa_lsaRQueryForestTrustInformation
3923 static NTSTATUS
dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3924 struct lsa_lsaRQueryForestTrustInformation
*r
)
3926 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3929 #define DNS_CMP_MATCH 0
3930 #define DNS_CMP_FIRST_IS_CHILD 1
3931 #define DNS_CMP_SECOND_IS_CHILD 2
3932 #define DNS_CMP_NO_MATCH 3
3934 /* this function assumes names are well formed DNS names.
3935 * it doesn't validate them */
3936 static int dns_cmp(const char *s1
, size_t l1
,
3937 const char *s2
, size_t l2
)
3939 const char *p1
, *p2
;
3944 if (strcasecmp_m(s1
, s2
) == 0) {
3945 return DNS_CMP_MATCH
;
3947 return DNS_CMP_NO_MATCH
;
3955 cret
= DNS_CMP_FIRST_IS_CHILD
;
3961 cret
= DNS_CMP_SECOND_IS_CHILD
;
3964 if (p1
[t1
- t2
- 1] != '.') {
3965 return DNS_CMP_NO_MATCH
;
3968 if (strcasecmp_m(&p1
[t1
- t2
], p2
) == 0) {
3972 return DNS_CMP_NO_MATCH
;
3975 /* decode all TDOs forest trust info blobs */
3976 static NTSTATUS
get_ft_info(TALLOC_CTX
*mem_ctx
,
3977 struct ldb_message
*msg
,
3978 struct ForestTrustInfo
*info
)
3980 const struct ldb_val
*ft_blob
;
3981 enum ndr_err_code ndr_err
;
3983 ft_blob
= ldb_msg_find_ldb_val(msg
, "msDS-TrustForestTrustInfo");
3984 if (!ft_blob
|| !ft_blob
->data
) {
3985 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3987 /* ldb_val is equivalent to DATA_BLOB */
3988 ndr_err
= ndr_pull_struct_blob_all(ft_blob
, mem_ctx
, info
,
3989 (ndr_pull_flags_fn_t
)ndr_pull_ForestTrustInfo
);
3990 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
3991 return NT_STATUS_INVALID_DOMAIN_STATE
;
3994 return NT_STATUS_OK
;
3997 static NTSTATUS
own_ft_info(struct lsa_policy_state
*ps
,
3998 struct ForestTrustInfo
*fti
)
4000 struct ForestTrustDataDomainInfo
*info
;
4001 struct ForestTrustInfoRecord
*rec
;
4005 fti
->records
= talloc_array(fti
,
4006 struct ForestTrustInfoRecordArmor
, 2);
4007 if (!fti
->records
) {
4008 return NT_STATUS_NO_MEMORY
;
4012 rec
= &fti
->records
[0].record
;
4016 rec
->type
= LSA_FOREST_TRUST_TOP_LEVEL_NAME
;
4018 rec
->data
.name
.string
= talloc_strdup(fti
, ps
->forest_dns
);
4019 if (!rec
->data
.name
.string
) {
4020 return NT_STATUS_NO_MEMORY
;
4022 rec
->data
.name
.size
= strlen(rec
->data
.name
.string
);
4025 rec
= &fti
->records
[1].record
;
4029 rec
->type
= LSA_FOREST_TRUST_DOMAIN_INFO
;
4031 info
= &rec
->data
.info
;
4033 info
->sid
= *ps
->domain_sid
;
4034 info
->dns_name
.string
= talloc_strdup(fti
, ps
->domain_dns
);
4035 if (!info
->dns_name
.string
) {
4036 return NT_STATUS_NO_MEMORY
;
4038 info
->dns_name
.size
= strlen(info
->dns_name
.string
);
4039 info
->netbios_name
.string
= talloc_strdup(fti
, ps
->domain_name
);
4040 if (!info
->netbios_name
.string
) {
4041 return NT_STATUS_NO_MEMORY
;
4043 info
->netbios_name
.size
= strlen(info
->netbios_name
.string
);
4045 return NT_STATUS_OK
;
4048 static NTSTATUS
make_ft_info(TALLOC_CTX
*mem_ctx
,
4049 struct lsa_ForestTrustInformation
*lfti
,
4050 struct ForestTrustInfo
*fti
)
4052 struct lsa_ForestTrustRecord
*lrec
;
4053 struct ForestTrustInfoRecord
*rec
;
4054 struct lsa_StringLarge
*tln
;
4055 struct lsa_ForestTrustDomainInfo
*info
;
4059 fti
->count
= lfti
->count
;
4060 fti
->records
= talloc_array(mem_ctx
,
4061 struct ForestTrustInfoRecordArmor
,
4063 if (!fti
->records
) {
4064 return NT_STATUS_NO_MEMORY
;
4066 for (i
= 0; i
< fti
->count
; i
++) {
4067 lrec
= lfti
->entries
[i
];
4068 rec
= &fti
->records
[i
].record
;
4070 rec
->flags
= lrec
->flags
;
4071 rec
->timestamp
= lrec
->time
;
4072 rec
->type
= lrec
->type
;
4074 switch (lrec
->type
) {
4075 case LSA_FOREST_TRUST_TOP_LEVEL_NAME
:
4076 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
:
4077 tln
= &lrec
->forest_trust_data
.top_level_name
;
4078 rec
->data
.name
.string
=
4079 talloc_strdup(mem_ctx
, tln
->string
);
4080 if (!rec
->data
.name
.string
) {
4081 return NT_STATUS_NO_MEMORY
;
4083 rec
->data
.name
.size
= strlen(rec
->data
.name
.string
);
4085 case LSA_FOREST_TRUST_DOMAIN_INFO
:
4086 info
= &lrec
->forest_trust_data
.domain_info
;
4087 rec
->data
.info
.sid
= *info
->domain_sid
;
4088 rec
->data
.info
.dns_name
.string
=
4089 talloc_strdup(mem_ctx
,
4090 info
->dns_domain_name
.string
);
4091 if (!rec
->data
.info
.dns_name
.string
) {
4092 return NT_STATUS_NO_MEMORY
;
4094 rec
->data
.info
.dns_name
.size
=
4095 strlen(rec
->data
.info
.dns_name
.string
);
4096 rec
->data
.info
.netbios_name
.string
=
4097 talloc_strdup(mem_ctx
,
4098 info
->netbios_domain_name
.string
);
4099 if (!rec
->data
.info
.netbios_name
.string
) {
4100 return NT_STATUS_NO_MEMORY
;
4102 rec
->data
.info
.netbios_name
.size
=
4103 strlen(rec
->data
.info
.netbios_name
.string
);
4106 return NT_STATUS_INVALID_DOMAIN_STATE
;
4110 return NT_STATUS_OK
;
4113 static NTSTATUS
add_collision(struct lsa_ForestTrustCollisionInfo
*c_info
,
4114 uint32_t idx
, uint32_t collision_type
,
4115 uint32_t conflict_type
, const char *tdo_name
);
4117 static NTSTATUS
check_ft_info(TALLOC_CTX
*mem_ctx
,
4118 const char *tdo_name
,
4119 struct ForestTrustInfo
*tdo_fti
,
4120 struct ForestTrustInfo
*new_fti
,
4121 struct lsa_ForestTrustCollisionInfo
*c_info
)
4123 struct ForestTrustInfoRecord
*nrec
;
4124 struct ForestTrustInfoRecord
*trec
;
4125 const char *dns_name
;
4126 const char *nb_name
;
4127 struct dom_sid
*sid
;
4133 uint32_t new_fti_idx
;
4135 /* use always TDO type, until we understand when Xref can be used */
4136 uint32_t collision_type
= LSA_FOREST_TRUST_COLLISION_TDO
;
4144 for (new_fti_idx
= 0; new_fti_idx
< new_fti
->count
; new_fti_idx
++) {
4146 nrec
= &new_fti
->records
[new_fti_idx
].record
;
4148 tln_conflict
= false;
4149 sid_conflict
= false;
4150 nb_conflict
= false;
4153 switch (nrec
->type
) {
4154 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
:
4155 /* exclusions do not conflict by definition */
4158 case FOREST_TRUST_TOP_LEVEL_NAME
:
4159 dns_name
= nrec
->data
.name
.string
;
4160 dns_len
= nrec
->data
.name
.size
;
4163 case LSA_FOREST_TRUST_DOMAIN_INFO
:
4164 dns_name
= nrec
->data
.info
.dns_name
.string
;
4165 dns_len
= nrec
->data
.info
.dns_name
.size
;
4166 nb_name
= nrec
->data
.info
.netbios_name
.string
;
4167 nb_len
= nrec
->data
.info
.netbios_name
.size
;
4168 sid
= &nrec
->data
.info
.sid
;
4172 if (!dns_name
) continue;
4174 /* check if this is already taken and not excluded */
4175 for (i
= 0; i
< tdo_fti
->count
; i
++) {
4176 trec
= &tdo_fti
->records
[i
].record
;
4178 switch (trec
->type
) {
4179 case FOREST_TRUST_TOP_LEVEL_NAME
:
4181 tname
= trec
->data
.name
.string
;
4182 tlen
= trec
->data
.name
.size
;
4184 case FOREST_TRUST_TOP_LEVEL_NAME_EX
:
4186 tname
= trec
->data
.name
.string
;
4187 tlen
= trec
->data
.name
.size
;
4189 case FOREST_TRUST_DOMAIN_INFO
:
4191 tname
= trec
->data
.info
.dns_name
.string
;
4192 tlen
= trec
->data
.info
.dns_name
.size
;
4194 ret
= dns_cmp(dns_name
, dns_len
, tname
, tlen
);
4197 /* if it matches exclusion,
4198 * it doesn't conflict */
4204 case DNS_CMP_FIRST_IS_CHILD
:
4205 case DNS_CMP_SECOND_IS_CHILD
:
4206 tln_conflict
= true;
4212 /* explicit exclusion, no dns name conflict here */
4214 tln_conflict
= false;
4217 if (trec
->type
!= FOREST_TRUST_DOMAIN_INFO
) {
4221 /* also test for domain info */
4222 if (!(trec
->flags
& LSA_SID_DISABLED_ADMIN
) &&
4223 dom_sid_compare(&trec
->data
.info
.sid
, sid
) == 0) {
4224 sid_conflict
= true;
4226 if (!(trec
->flags
& LSA_NB_DISABLED_ADMIN
) &&
4227 strcasecmp_m(trec
->data
.info
.netbios_name
.string
,
4234 nt_status
= add_collision(c_info
, new_fti_idx
,
4236 LSA_TLN_DISABLED_CONFLICT
,
4240 nt_status
= add_collision(c_info
, new_fti_idx
,
4242 LSA_SID_DISABLED_CONFLICT
,
4246 nt_status
= add_collision(c_info
, new_fti_idx
,
4248 LSA_NB_DISABLED_CONFLICT
,
4253 return NT_STATUS_OK
;
4256 static NTSTATUS
add_collision(struct lsa_ForestTrustCollisionInfo
*c_info
,
4257 uint32_t idx
, uint32_t collision_type
,
4258 uint32_t conflict_type
, const char *tdo_name
)
4260 struct lsa_ForestTrustCollisionRecord
**es
;
4261 uint32_t i
= c_info
->count
;
4263 es
= talloc_realloc(c_info
, c_info
->entries
,
4264 struct lsa_ForestTrustCollisionRecord
*, i
+ 1);
4266 return NT_STATUS_NO_MEMORY
;
4268 c_info
->entries
= es
;
4269 c_info
->count
= i
+ 1;
4271 es
[i
] = talloc(es
, struct lsa_ForestTrustCollisionRecord
);
4273 return NT_STATUS_NO_MEMORY
;
4277 es
[i
]->type
= collision_type
;
4278 es
[i
]->flags
.flags
= conflict_type
;
4279 es
[i
]->name
.string
= talloc_strdup(es
[i
], tdo_name
);
4280 if (!es
[i
]->name
.string
) {
4281 return NT_STATUS_NO_MEMORY
;
4283 es
[i
]->name
.size
= strlen(es
[i
]->name
.string
);
4285 return NT_STATUS_OK
;
4289 lsa_lsaRSetForestTrustInformation
4291 static NTSTATUS
dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state
*dce_call
,
4292 TALLOC_CTX
*mem_ctx
,
4293 struct lsa_lsaRSetForestTrustInformation
*r
)
4295 struct dcesrv_handle
*h
;
4296 struct lsa_policy_state
*p_state
;
4297 const char *trust_attrs
[] = { "trustPartner", "trustAttributes",
4298 "msDS-TrustForestTrustInfo", NULL
};
4299 struct ldb_message
**dom_res
= NULL
;
4300 struct ldb_dn
*tdo_dn
;
4301 struct ldb_message
*msg
;
4303 const char *td_name
;
4304 uint32_t trust_attributes
;
4305 struct lsa_ForestTrustCollisionInfo
*c_info
;
4306 struct ForestTrustInfo
*nfti
;
4307 struct ForestTrustInfo
*fti
;
4309 enum ndr_err_code ndr_err
;
4314 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
4318 if (strcmp(p_state
->domain_dns
, p_state
->forest_dns
)) {
4319 return NT_STATUS_INVALID_DOMAIN_STATE
;
4322 /* abort if we are not a PDC */
4323 if (!samdb_is_pdc(p_state
->sam_ldb
)) {
4324 return NT_STATUS_INVALID_DOMAIN_ROLE
;
4327 ret
= samdb_rodc(p_state
->sam_ldb
, &am_rodc
);
4328 if (ret
== LDB_SUCCESS
&& am_rodc
) {
4329 return NT_STATUS_NO_SUCH_DOMAIN
;
4332 /* check caller has TRUSTED_SET_AUTH */
4334 /* fetch all trusted domain objects */
4335 num_res
= gendb_search(p_state
->sam_ldb
, mem_ctx
,
4337 &dom_res
, trust_attrs
,
4338 "(objectclass=trustedDomain)");
4340 return NT_STATUS_NO_SUCH_DOMAIN
;
4343 for (i
= 0; i
< num_res
; i
++) {
4344 td_name
= ldb_msg_find_attr_as_string(dom_res
[i
],
4345 "trustPartner", NULL
);
4347 return NT_STATUS_INVALID_DOMAIN_STATE
;
4349 if (strcasecmp_m(td_name
,
4350 r
->in
.trusted_domain_name
->string
) == 0) {
4355 return NT_STATUS_NO_SUCH_DOMAIN
;
4358 tdo_dn
= dom_res
[i
]->dn
;
4360 trust_attributes
= ldb_msg_find_attr_as_uint(dom_res
[i
],
4361 "trustAttributes", 0);
4362 if (!(trust_attributes
& NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
)) {
4363 return NT_STATUS_INVALID_PARAMETER
;
4366 if (r
->in
.highest_record_type
>= LSA_FOREST_TRUST_RECORD_TYPE_LAST
) {
4367 return NT_STATUS_INVALID_PARAMETER
;
4370 nfti
= talloc(mem_ctx
, struct ForestTrustInfo
);
4372 return NT_STATUS_NO_MEMORY
;
4375 nt_status
= make_ft_info(nfti
, r
->in
.forest_trust_info
, nfti
);
4376 if (!NT_STATUS_IS_OK(nt_status
)) {
4380 c_info
= talloc_zero(r
->out
.collision_info
,
4381 struct lsa_ForestTrustCollisionInfo
);
4383 return NT_STATUS_NO_MEMORY
;
4386 /* first check own info, then other domains */
4387 fti
= talloc(mem_ctx
, struct ForestTrustInfo
);
4389 return NT_STATUS_NO_MEMORY
;
4392 nt_status
= own_ft_info(p_state
, fti
);
4393 if (!NT_STATUS_IS_OK(nt_status
)) {
4397 nt_status
= check_ft_info(c_info
, p_state
->domain_dns
,
4399 if (!NT_STATUS_IS_OK(nt_status
)) {
4403 for (i
= 0; i
< num_res
; i
++) {
4404 fti
= talloc(mem_ctx
, struct ForestTrustInfo
);
4406 return NT_STATUS_NO_MEMORY
;
4409 nt_status
= get_ft_info(mem_ctx
, dom_res
[i
], fti
);
4410 if (!NT_STATUS_IS_OK(nt_status
)) {
4411 if (NT_STATUS_EQUAL(nt_status
,
4412 NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
4418 td_name
= ldb_msg_find_attr_as_string(dom_res
[i
],
4419 "trustPartner", NULL
);
4421 return NT_STATUS_INVALID_DOMAIN_STATE
;
4424 nt_status
= check_ft_info(c_info
, td_name
, fti
, nfti
, c_info
);
4425 if (!NT_STATUS_IS_OK(nt_status
)) {
4430 *r
->out
.collision_info
= c_info
;
4432 if (r
->in
.check_only
!= 0) {
4433 return NT_STATUS_OK
;
4436 /* not just a check, write info back */
4438 ndr_err
= ndr_push_struct_blob(&ft_blob
, mem_ctx
, nfti
,
4439 (ndr_push_flags_fn_t
)ndr_push_ForestTrustInfo
);
4440 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
4441 return NT_STATUS_INVALID_PARAMETER
;
4444 msg
= ldb_msg_new(mem_ctx
);
4446 return NT_STATUS_NO_MEMORY
;
4449 msg
->dn
= ldb_dn_copy(mem_ctx
, tdo_dn
);
4451 return NT_STATUS_NO_MEMORY
;
4454 ret
= ldb_msg_add_empty(msg
, "msDS-TrustForestTrustInfo",
4455 LDB_FLAG_MOD_REPLACE
, NULL
);
4456 if (ret
!= LDB_SUCCESS
) {
4457 return NT_STATUS_NO_MEMORY
;
4459 ret
= ldb_msg_add_value(msg
, "msDS-TrustForestTrustInfo",
4461 if (ret
!= LDB_SUCCESS
) {
4462 return NT_STATUS_NO_MEMORY
;
4465 ret
= ldb_modify(p_state
->sam_ldb
, msg
);
4466 if (ret
!= LDB_SUCCESS
) {
4467 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4468 ldb_errstring(p_state
->sam_ldb
)));
4471 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
:
4472 return NT_STATUS_ACCESS_DENIED
;
4474 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
4478 return NT_STATUS_OK
;
4484 static NTSTATUS
dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4485 struct lsa_CREDRRENAME
*r
)
4487 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4493 lsa_LSAROPENPOLICYSCE
4495 static NTSTATUS
dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4496 struct lsa_LSAROPENPOLICYSCE
*r
)
4498 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4503 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4505 static NTSTATUS
dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4506 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE
*r
)
4508 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4513 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4515 static NTSTATUS
dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4516 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
*r
)
4518 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4523 lsa_LSARADTREPORTSECURITYEVENT
4525 static NTSTATUS
dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4526 struct lsa_LSARADTREPORTSECURITYEVENT
*r
)
4528 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4532 /* include the generated boilerplate */
4533 #include "librpc/gen_ndr/ndr_lsa_s.c"
4537 /*****************************************
4538 NOTE! The remaining calls below were
4539 removed in w2k3, so the DCESRV_FAULT()
4540 replies are the correct implementation. Do
4541 not try and fill these in with anything else
4542 ******************************************/
4545 dssetup_DsRoleDnsNameToFlatName
4547 static WERROR
dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4548 struct dssetup_DsRoleDnsNameToFlatName
*r
)
4550 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4555 dssetup_DsRoleDcAsDc
4557 static WERROR
dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4558 struct dssetup_DsRoleDcAsDc
*r
)
4560 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4565 dssetup_DsRoleDcAsReplica
4567 static WERROR
dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4568 struct dssetup_DsRoleDcAsReplica
*r
)
4570 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4575 dssetup_DsRoleDemoteDc
4577 static WERROR
dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4578 struct dssetup_DsRoleDemoteDc
*r
)
4580 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4585 dssetup_DsRoleGetDcOperationProgress
4587 static WERROR
dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4588 struct dssetup_DsRoleGetDcOperationProgress
*r
)
4590 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4595 dssetup_DsRoleGetDcOperationResults
4597 static WERROR
dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4598 struct dssetup_DsRoleGetDcOperationResults
*r
)
4600 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4605 dssetup_DsRoleCancel
4607 static WERROR
dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4608 struct dssetup_DsRoleCancel
*r
)
4610 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4615 dssetup_DsRoleServerSaveStateForUpgrade
4617 static WERROR
dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4618 struct dssetup_DsRoleServerSaveStateForUpgrade
*r
)
4620 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4625 dssetup_DsRoleUpgradeDownlevelServer
4627 static WERROR
dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4628 struct dssetup_DsRoleUpgradeDownlevelServer
*r
)
4630 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4635 dssetup_DsRoleAbortDownlevelServerUpgrade
4637 static WERROR
dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4638 struct dssetup_DsRoleAbortDownlevelServerUpgrade
*r
)
4640 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4644 /* include the generated boilerplate */
4645 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4647 NTSTATUS
dcerpc_server_lsa_init(void)
4651 ret
= dcerpc_server_dssetup_init();
4652 if (!NT_STATUS_IS_OK(ret
)) {
4655 ret
= dcerpc_server_lsarpc_init();
4656 if (!NT_STATUS_IS_OK(ret
)) {