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
;
744 /* This decrypts and returns Trusted Domain Auth Information Internal data */
745 static NTSTATUS
get_trustdom_auth_blob(struct dcesrv_call_state
*dce_call
,
746 TALLOC_CTX
*mem_ctx
, DATA_BLOB
*auth_blob
,
747 struct trustDomainPasswords
*auth_struct
)
749 DATA_BLOB session_key
= data_blob(NULL
, 0);
750 enum ndr_err_code ndr_err
;
753 nt_status
= dcesrv_fetch_session_key(dce_call
->conn
, &session_key
);
754 if (!NT_STATUS_IS_OK(nt_status
)) {
758 arcfour_crypt_blob(auth_blob
->data
, auth_blob
->length
, &session_key
);
759 ndr_err
= ndr_pull_struct_blob(auth_blob
, mem_ctx
,
761 (ndr_pull_flags_fn_t
)ndr_pull_trustDomainPasswords
);
762 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
763 return NT_STATUS_INVALID_PARAMETER
;
769 static NTSTATUS
get_trustauth_inout_blob(struct dcesrv_call_state
*dce_call
,
771 struct trustAuthInOutBlob
*iopw
,
772 DATA_BLOB
*trustauth_blob
)
774 enum ndr_err_code ndr_err
;
776 ndr_err
= ndr_push_struct_blob(trustauth_blob
, mem_ctx
,
778 (ndr_push_flags_fn_t
)ndr_push_trustAuthInOutBlob
);
779 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
780 return NT_STATUS_INVALID_PARAMETER
;
786 static NTSTATUS
add_trust_user(TALLOC_CTX
*mem_ctx
,
787 struct ldb_context
*sam_ldb
,
788 struct ldb_dn
*base_dn
,
789 const char *netbios_name
,
790 struct trustAuthInOutBlob
*in
,
791 struct ldb_dn
**user_dn
)
793 struct ldb_message
*msg
;
798 dn
= ldb_dn_copy(mem_ctx
, base_dn
);
800 return NT_STATUS_NO_MEMORY
;
802 if (!ldb_dn_add_child_fmt(dn
, "cn=%s$,cn=users", netbios_name
)) {
803 return NT_STATUS_NO_MEMORY
;
806 msg
= ldb_msg_new(mem_ctx
);
808 return NT_STATUS_NO_MEMORY
;
812 ret
= ldb_msg_add_string(msg
, "objectClass", "user");
813 if (ret
!= LDB_SUCCESS
) {
814 return NT_STATUS_NO_MEMORY
;
817 ret
= ldb_msg_add_fmt(msg
, "samAccountName", "%s$", netbios_name
);
818 if (ret
!= LDB_SUCCESS
) {
819 return NT_STATUS_NO_MEMORY
;
822 ret
= samdb_msg_add_uint(sam_ldb
, msg
, msg
, "userAccountControl",
823 UF_INTERDOMAIN_TRUST_ACCOUNT
);
824 if (ret
!= LDB_SUCCESS
) {
825 return NT_STATUS_NO_MEMORY
;
828 for (i
= 0; i
< in
->count
; i
++) {
829 const char *attribute
;
831 switch (in
->current
.array
[i
].AuthType
) {
832 case TRUST_AUTH_TYPE_NT4OWF
:
833 attribute
= "unicodePwd";
834 v
.data
= (uint8_t *)&in
->current
.array
[i
].AuthInfo
.nt4owf
.password
;
837 case TRUST_AUTH_TYPE_CLEAR
:
838 attribute
= "clearTextPassword";
839 v
.data
= in
->current
.array
[i
].AuthInfo
.clear
.password
;
840 v
.length
= in
->current
.array
[i
].AuthInfo
.clear
.size
;
846 ret
= ldb_msg_add_value(msg
, attribute
, &v
, NULL
);
847 if (ret
!= LDB_SUCCESS
) {
848 return NT_STATUS_NO_MEMORY
;
852 /* create the trusted_domain user account */
853 ret
= ldb_add(sam_ldb
, msg
);
854 if (ret
!= LDB_SUCCESS
) {
855 DEBUG(0,("Failed to create user record %s: %s\n",
856 ldb_dn_get_linearized(msg
->dn
),
857 ldb_errstring(sam_ldb
)));
860 case LDB_ERR_ENTRY_ALREADY_EXISTS
:
861 return NT_STATUS_DOMAIN_EXISTS
;
862 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
:
863 return NT_STATUS_ACCESS_DENIED
;
865 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
876 lsa_CreateTrustedDomainEx2
878 static NTSTATUS
dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state
*dce_call
,
880 struct lsa_CreateTrustedDomainEx2
*r
,
882 struct lsa_TrustDomainInfoAuthInfo
*unencrypted_auth_info
)
884 struct dcesrv_handle
*policy_handle
;
885 struct lsa_policy_state
*policy_state
;
886 struct lsa_trusted_domain_state
*trusted_domain_state
;
887 struct dcesrv_handle
*handle
;
888 struct ldb_message
**msgs
, *msg
;
889 const char *attrs
[] = {
892 const char *netbios_name
;
893 const char *dns_name
;
895 DATA_BLOB trustAuthIncoming
, trustAuthOutgoing
, auth_blob
;
896 struct trustDomainPasswords auth_struct
;
899 struct ldb_context
*sam_ldb
;
901 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.policy_handle
, LSA_HANDLE_POLICY
);
902 ZERO_STRUCTP(r
->out
.trustdom_handle
);
904 policy_state
= policy_handle
->data
;
905 sam_ldb
= policy_state
->sam_ldb
;
907 netbios_name
= r
->in
.info
->netbios_name
.string
;
909 return NT_STATUS_INVALID_PARAMETER
;
912 dns_name
= r
->in
.info
->domain_name
.string
;
914 trusted_domain_state
= talloc_zero(mem_ctx
, struct lsa_trusted_domain_state
);
915 if (!trusted_domain_state
) {
916 return NT_STATUS_NO_MEMORY
;
918 trusted_domain_state
->policy
= policy_state
;
920 if (strcasecmp(netbios_name
, "BUILTIN") == 0
921 || (dns_name
&& strcasecmp(dns_name
, "BUILTIN") == 0)
922 || (dom_sid_in_domain(policy_state
->builtin_sid
, r
->in
.info
->sid
))) {
923 return NT_STATUS_INVALID_PARAMETER
;
926 if (strcasecmp(netbios_name
, policy_state
->domain_name
) == 0
927 || strcasecmp(netbios_name
, policy_state
->domain_dns
) == 0
928 || (dns_name
&& strcasecmp(dns_name
, policy_state
->domain_dns
) == 0)
929 || (dns_name
&& strcasecmp(dns_name
, policy_state
->domain_name
) == 0)
930 || (dom_sid_equal(policy_state
->domain_sid
, r
->in
.info
->sid
))) {
931 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED
;
934 /* While this is a REF pointer, some of the functions that wrap this don't provide this */
935 if (op
== NDR_LSA_CREATETRUSTEDDOMAIN
) {
936 /* No secrets are created at this time, for this function */
937 auth_struct
.outgoing
.count
= 0;
938 auth_struct
.incoming
.count
= 0;
939 } else if (op
== NDR_LSA_CREATETRUSTEDDOMAINEX2
) {
940 auth_blob
= data_blob_const(r
->in
.auth_info_internal
->auth_blob
.data
,
941 r
->in
.auth_info_internal
->auth_blob
.size
);
942 nt_status
= get_trustdom_auth_blob(dce_call
, mem_ctx
,
943 &auth_blob
, &auth_struct
);
944 if (!NT_STATUS_IS_OK(nt_status
)) {
947 } else if (op
== NDR_LSA_CREATETRUSTEDDOMAINEX
) {
949 if (unencrypted_auth_info
->incoming_count
> 1) {
950 return NT_STATUS_INVALID_PARAMETER
;
953 /* more investigation required here, do not create secrets for
955 auth_struct
.outgoing
.count
= 0;
956 auth_struct
.incoming
.count
= 0;
958 return NT_STATUS_INVALID_PARAMETER
;
961 if (auth_struct
.incoming
.count
) {
962 nt_status
= get_trustauth_inout_blob(dce_call
, mem_ctx
,
963 &auth_struct
.incoming
,
965 if (!NT_STATUS_IS_OK(nt_status
)) {
969 trustAuthIncoming
= data_blob(NULL
, 0);
972 if (auth_struct
.outgoing
.count
) {
973 nt_status
= get_trustauth_inout_blob(dce_call
, mem_ctx
,
974 &auth_struct
.outgoing
,
976 if (!NT_STATUS_IS_OK(nt_status
)) {
980 trustAuthOutgoing
= data_blob(NULL
, 0);
983 ret
= ldb_transaction_start(sam_ldb
);
984 if (ret
!= LDB_SUCCESS
) {
985 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
989 char *dns_encoded
= ldb_binary_encode_string(mem_ctx
, dns_name
);
990 char *netbios_encoded
= ldb_binary_encode_string(mem_ctx
, netbios_name
);
991 /* search for the trusted_domain record */
992 ret
= gendb_search(sam_ldb
,
993 mem_ctx
, policy_state
->system_dn
, &msgs
, attrs
,
994 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
995 dns_encoded
, dns_encoded
, dns_encoded
, netbios_encoded
, netbios_encoded
, netbios_encoded
);
997 ldb_transaction_cancel(sam_ldb
);
998 return NT_STATUS_OBJECT_NAME_COLLISION
;
1001 char *netbios_encoded
= ldb_binary_encode_string(mem_ctx
, netbios_name
);
1002 /* search for the trusted_domain record */
1003 ret
= gendb_search(sam_ldb
,
1004 mem_ctx
, policy_state
->system_dn
, &msgs
, attrs
,
1005 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1006 netbios_encoded
, netbios_encoded
, netbios_encoded
);
1008 ldb_transaction_cancel(sam_ldb
);
1009 return NT_STATUS_OBJECT_NAME_COLLISION
;
1014 ldb_transaction_cancel(sam_ldb
);
1015 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1018 name
= dns_name
? dns_name
: netbios_name
;
1020 msg
= ldb_msg_new(mem_ctx
);
1022 return NT_STATUS_NO_MEMORY
;
1025 msg
->dn
= ldb_dn_copy(mem_ctx
, policy_state
->system_dn
);
1026 if ( ! ldb_dn_add_child_fmt(msg
->dn
, "cn=%s", name
)) {
1027 ldb_transaction_cancel(sam_ldb
);
1028 return NT_STATUS_NO_MEMORY
;
1031 ldb_msg_add_string(msg
, "flatname", netbios_name
);
1033 if (r
->in
.info
->sid
) {
1034 ret
= samdb_msg_add_dom_sid(sam_ldb
, mem_ctx
, msg
, "securityIdentifier", r
->in
.info
->sid
);
1035 if (ret
!= LDB_SUCCESS
) {
1036 ldb_transaction_cancel(sam_ldb
);
1037 return NT_STATUS_INVALID_PARAMETER
;
1041 ldb_msg_add_string(msg
, "objectClass", "trustedDomain");
1043 samdb_msg_add_int(sam_ldb
, mem_ctx
, msg
, "trustType", r
->in
.info
->trust_type
);
1045 samdb_msg_add_int(sam_ldb
, mem_ctx
, msg
, "trustAttributes", r
->in
.info
->trust_attributes
);
1047 samdb_msg_add_int(sam_ldb
, mem_ctx
, msg
, "trustDirection", r
->in
.info
->trust_direction
);
1050 ldb_msg_add_string(msg
, "trustPartner", dns_name
);
1053 if (trustAuthIncoming
.data
) {
1054 ret
= ldb_msg_add_value(msg
, "trustAuthIncoming", &trustAuthIncoming
, NULL
);
1055 if (ret
!= LDB_SUCCESS
) {
1056 ldb_transaction_cancel(sam_ldb
);
1057 return NT_STATUS_NO_MEMORY
;
1060 if (trustAuthOutgoing
.data
) {
1061 ret
= ldb_msg_add_value(msg
, "trustAuthOutgoing", &trustAuthOutgoing
, NULL
);
1062 if (ret
!= LDB_SUCCESS
) {
1063 ldb_transaction_cancel(sam_ldb
);
1064 return NT_STATUS_NO_MEMORY
;
1068 trusted_domain_state
->trusted_domain_dn
= talloc_reference(trusted_domain_state
, msg
->dn
);
1070 /* create the trusted_domain */
1071 ret
= ldb_add(sam_ldb
, msg
);
1075 case LDB_ERR_ENTRY_ALREADY_EXISTS
:
1076 ldb_transaction_cancel(sam_ldb
);
1077 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1078 ldb_dn_get_linearized(msg
->dn
),
1079 ldb_errstring(sam_ldb
)));
1080 return NT_STATUS_DOMAIN_EXISTS
;
1081 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
:
1082 ldb_transaction_cancel(sam_ldb
);
1083 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1084 ldb_dn_get_linearized(msg
->dn
),
1085 ldb_errstring(sam_ldb
)));
1086 return NT_STATUS_ACCESS_DENIED
;
1088 ldb_transaction_cancel(sam_ldb
);
1089 DEBUG(0,("Failed to create user record %s: %s\n",
1090 ldb_dn_get_linearized(msg
->dn
),
1091 ldb_errstring(sam_ldb
)));
1092 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1095 if (r
->in
.info
->trust_direction
& LSA_TRUST_DIRECTION_INBOUND
) {
1096 struct ldb_dn
*user_dn
;
1097 /* Inbound trusts must also create a cn=users object to match */
1098 nt_status
= add_trust_user(mem_ctx
, sam_ldb
,
1099 policy_state
->domain_dn
,
1101 &auth_struct
.incoming
,
1103 if (!NT_STATUS_IS_OK(nt_status
)) {
1104 ldb_transaction_cancel(sam_ldb
);
1108 /* save the trust user dn */
1109 trusted_domain_state
->trusted_domain_user_dn
1110 = talloc_steal(trusted_domain_state
, user_dn
);
1113 ret
= ldb_transaction_commit(sam_ldb
);
1114 if (ret
!= LDB_SUCCESS
) {
1115 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1118 handle
= dcesrv_handle_new(dce_call
->context
, LSA_HANDLE_TRUSTED_DOMAIN
);
1120 return NT_STATUS_NO_MEMORY
;
1123 handle
->data
= talloc_steal(handle
, trusted_domain_state
);
1125 trusted_domain_state
->access_mask
= r
->in
.access_mask
;
1126 trusted_domain_state
->policy
= talloc_reference(trusted_domain_state
, policy_state
);
1128 *r
->out
.trustdom_handle
= handle
->wire_handle
;
1130 return NT_STATUS_OK
;
1134 lsa_CreateTrustedDomainEx2
1136 static NTSTATUS
dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state
*dce_call
,
1137 TALLOC_CTX
*mem_ctx
,
1138 struct lsa_CreateTrustedDomainEx2
*r
)
1140 return dcesrv_lsa_CreateTrustedDomain_base(dce_call
, mem_ctx
, r
, NDR_LSA_CREATETRUSTEDDOMAINEX2
, NULL
);
1143 lsa_CreateTrustedDomainEx
1145 static NTSTATUS
dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state
*dce_call
,
1146 TALLOC_CTX
*mem_ctx
,
1147 struct lsa_CreateTrustedDomainEx
*r
)
1149 struct lsa_CreateTrustedDomainEx2 r2
;
1151 r2
.in
.policy_handle
= r
->in
.policy_handle
;
1152 r2
.in
.info
= r
->in
.info
;
1153 r2
.out
.trustdom_handle
= r
->out
.trustdom_handle
;
1154 return dcesrv_lsa_CreateTrustedDomain_base(dce_call
, mem_ctx
, &r2
, NDR_LSA_CREATETRUSTEDDOMAINEX
, r
->in
.auth_info
);
1158 lsa_CreateTrustedDomain
1160 static NTSTATUS
dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1161 struct lsa_CreateTrustedDomain
*r
)
1163 struct lsa_CreateTrustedDomainEx2 r2
;
1165 r2
.in
.policy_handle
= r
->in
.policy_handle
;
1166 r2
.in
.info
= talloc(mem_ctx
, struct lsa_TrustDomainInfoInfoEx
);
1168 return NT_STATUS_NO_MEMORY
;
1171 r2
.in
.info
->domain_name
.string
= NULL
;
1172 r2
.in
.info
->netbios_name
= r
->in
.info
->name
;
1173 r2
.in
.info
->sid
= r
->in
.info
->sid
;
1174 r2
.in
.info
->trust_direction
= LSA_TRUST_DIRECTION_OUTBOUND
;
1175 r2
.in
.info
->trust_type
= LSA_TRUST_TYPE_DOWNLEVEL
;
1176 r2
.in
.info
->trust_attributes
= 0;
1178 r2
.in
.access_mask
= r
->in
.access_mask
;
1179 r2
.out
.trustdom_handle
= r
->out
.trustdom_handle
;
1181 return dcesrv_lsa_CreateTrustedDomain_base(dce_call
, mem_ctx
, &r2
, NDR_LSA_CREATETRUSTEDDOMAIN
, NULL
);
1185 lsa_OpenTrustedDomain
1187 static NTSTATUS
dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1188 struct lsa_OpenTrustedDomain
*r
)
1190 struct dcesrv_handle
*policy_handle
;
1192 struct lsa_policy_state
*policy_state
;
1193 struct lsa_trusted_domain_state
*trusted_domain_state
;
1194 struct dcesrv_handle
*handle
;
1195 struct ldb_message
**msgs
;
1196 const char *attrs
[] = {
1202 const char *sid_string
;
1205 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
1206 ZERO_STRUCTP(r
->out
.trustdom_handle
);
1207 policy_state
= policy_handle
->data
;
1209 trusted_domain_state
= talloc_zero(mem_ctx
, struct lsa_trusted_domain_state
);
1210 if (!trusted_domain_state
) {
1211 return NT_STATUS_NO_MEMORY
;
1213 trusted_domain_state
->policy
= policy_state
;
1215 sid_string
= dom_sid_string(mem_ctx
, r
->in
.sid
);
1217 return NT_STATUS_NO_MEMORY
;
1220 /* search for the trusted_domain record */
1221 ret
= gendb_search(trusted_domain_state
->policy
->sam_ldb
,
1222 mem_ctx
, policy_state
->system_dn
, &msgs
, attrs
,
1223 "(&(securityIdentifier=%s)(objectclass=trustedDomain))",
1226 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1230 DEBUG(0,("Found %d records matching DN %s\n", ret
,
1231 ldb_dn_get_linearized(policy_state
->system_dn
)));
1232 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1235 trusted_domain_state
->trusted_domain_dn
= talloc_reference(trusted_domain_state
, msgs
[0]->dn
);
1237 trusted_domain_state
->trusted_domain_user_dn
= NULL
;
1239 if (ldb_msg_find_attr_as_int(msgs
[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND
) {
1240 const char *flatname
= ldb_binary_encode_string(mem_ctx
, ldb_msg_find_attr_as_string(msgs
[0], "flatname", NULL
));
1241 /* search for the trusted_domain record */
1242 ret
= gendb_search(trusted_domain_state
->policy
->sam_ldb
,
1243 mem_ctx
, policy_state
->domain_dn
, &msgs
, attrs
,
1244 "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%u))",
1245 flatname
, UF_INTERDOMAIN_TRUST_ACCOUNT
);
1247 trusted_domain_state
->trusted_domain_user_dn
= talloc_steal(trusted_domain_state
, msgs
[0]->dn
);
1250 handle
= dcesrv_handle_new(dce_call
->context
, LSA_HANDLE_TRUSTED_DOMAIN
);
1252 return NT_STATUS_NO_MEMORY
;
1255 handle
->data
= talloc_steal(handle
, trusted_domain_state
);
1257 trusted_domain_state
->access_mask
= r
->in
.access_mask
;
1258 trusted_domain_state
->policy
= talloc_reference(trusted_domain_state
, policy_state
);
1260 *r
->out
.trustdom_handle
= handle
->wire_handle
;
1262 return NT_STATUS_OK
;
1267 lsa_OpenTrustedDomainByName
1269 static NTSTATUS
dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state
*dce_call
,
1270 TALLOC_CTX
*mem_ctx
,
1271 struct lsa_OpenTrustedDomainByName
*r
)
1273 struct dcesrv_handle
*policy_handle
;
1275 struct lsa_policy_state
*policy_state
;
1276 struct lsa_trusted_domain_state
*trusted_domain_state
;
1277 struct dcesrv_handle
*handle
;
1278 struct ldb_message
**msgs
;
1279 const char *attrs
[] = {
1285 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
1286 ZERO_STRUCTP(r
->out
.trustdom_handle
);
1287 policy_state
= policy_handle
->data
;
1289 if (!r
->in
.name
.string
) {
1290 return NT_STATUS_INVALID_PARAMETER
;
1293 trusted_domain_state
= talloc_zero(mem_ctx
, struct lsa_trusted_domain_state
);
1294 if (!trusted_domain_state
) {
1295 return NT_STATUS_NO_MEMORY
;
1297 trusted_domain_state
->policy
= policy_state
;
1299 /* search for the trusted_domain record */
1300 td_name
= ldb_binary_encode_string(mem_ctx
, r
->in
.name
.string
);
1301 ret
= gendb_search(trusted_domain_state
->policy
->sam_ldb
,
1302 mem_ctx
, policy_state
->system_dn
, &msgs
, attrs
,
1303 "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1304 "(objectclass=trustedDomain))",
1305 td_name
, td_name
, td_name
);
1307 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1311 DEBUG(0,("Found %d records matching DN %s\n", ret
,
1312 ldb_dn_get_linearized(policy_state
->system_dn
)));
1313 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1316 /* TODO: perform access checks */
1318 trusted_domain_state
->trusted_domain_dn
= talloc_reference(trusted_domain_state
, msgs
[0]->dn
);
1320 handle
= dcesrv_handle_new(dce_call
->context
, LSA_HANDLE_TRUSTED_DOMAIN
);
1322 return NT_STATUS_NO_MEMORY
;
1325 handle
->data
= talloc_steal(handle
, trusted_domain_state
);
1327 trusted_domain_state
->access_mask
= r
->in
.access_mask
;
1328 trusted_domain_state
->policy
= talloc_reference(trusted_domain_state
, policy_state
);
1330 *r
->out
.trustdom_handle
= handle
->wire_handle
;
1332 return NT_STATUS_OK
;
1338 lsa_SetTrustedDomainInfo
1340 static NTSTATUS
dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1341 struct lsa_SetTrustedDomainInfo
*r
)
1343 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1348 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1349 * otherwise at least one must be provided */
1350 static NTSTATUS
get_tdo(struct ldb_context
*sam
, TALLOC_CTX
*mem_ctx
,
1351 struct ldb_dn
*basedn
, const char *dns_domain
,
1352 const char *netbios
, struct dom_sid2
*sid
,
1353 struct ldb_message
***msgs
)
1355 const char *attrs
[] = { "flatname", "trustPartner",
1356 "securityIdentifier", "trustDirection",
1357 "trustType", "trustAttributes",
1359 "msDs-supportedEncryptionTypes", NULL
};
1362 char *sidstr
= NULL
;
1367 if (dns_domain
|| netbios
|| sid
) {
1368 filter
= talloc_strdup(mem_ctx
,
1369 "(&(objectclass=trustedDomain)(|");
1371 filter
= talloc_strdup(mem_ctx
,
1372 "(objectclass=trustedDomain)");
1375 return NT_STATUS_NO_MEMORY
;
1379 dns
= ldb_binary_encode_string(mem_ctx
, dns_domain
);
1381 return NT_STATUS_NO_MEMORY
;
1383 filter
= talloc_asprintf_append(filter
,
1384 "(trustPartner=%s)", dns
);
1386 return NT_STATUS_NO_MEMORY
;
1390 nbn
= ldb_binary_encode_string(mem_ctx
, netbios
);
1392 return NT_STATUS_NO_MEMORY
;
1394 filter
= talloc_asprintf_append(filter
,
1395 "(flatname=%s)", nbn
);
1397 return NT_STATUS_NO_MEMORY
;
1401 sidstr
= dom_sid_string(mem_ctx
, sid
);
1403 return NT_STATUS_INVALID_PARAMETER
;
1405 filter
= talloc_asprintf_append(filter
,
1406 "(securityIdentifier=%s)",
1409 return NT_STATUS_NO_MEMORY
;
1412 if (dns_domain
|| netbios
|| sid
) {
1413 filter
= talloc_asprintf_append(filter
, "))");
1415 return NT_STATUS_NO_MEMORY
;
1419 ret
= gendb_search(sam
, mem_ctx
, basedn
, msgs
, attrs
, "%s", filter
);
1421 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1425 return NT_STATUS_OBJECT_NAME_COLLISION
;
1428 return NT_STATUS_OK
;
1431 static NTSTATUS
update_uint32_t_value(TALLOC_CTX
*mem_ctx
,
1432 struct ldb_context
*sam_ldb
,
1433 struct ldb_message
*orig
,
1434 struct ldb_message
*dest
,
1435 const char *attribute
,
1437 uint32_t *orig_value
)
1439 const struct ldb_val
*orig_val
;
1440 uint32_t orig_uint
= 0;
1441 unsigned int flags
= 0;
1444 orig_val
= ldb_msg_find_ldb_val(orig
, attribute
);
1445 if (!orig_val
|| !orig_val
->data
) {
1446 /* add new attribute */
1447 flags
= LDB_FLAG_MOD_ADD
;
1451 orig_uint
= strtoul((const char *)orig_val
->data
, NULL
, 0);
1452 if (errno
!= 0 || orig_uint
!= value
) {
1453 /* replace also if can't get value */
1454 flags
= LDB_FLAG_MOD_REPLACE
;
1459 /* stored value is identical, nothing to change */
1463 ret
= ldb_msg_add_empty(dest
, attribute
, flags
, NULL
);
1464 if (ret
!= LDB_SUCCESS
) {
1465 return NT_STATUS_NO_MEMORY
;
1468 ret
= samdb_msg_add_uint(sam_ldb
, dest
, dest
, attribute
, value
);
1469 if (ret
!= LDB_SUCCESS
) {
1470 return NT_STATUS_NO_MEMORY
;
1475 *orig_value
= orig_uint
;
1477 return NT_STATUS_OK
;
1480 static NTSTATUS
update_trust_user(TALLOC_CTX
*mem_ctx
,
1481 struct ldb_context
*sam_ldb
,
1482 struct ldb_dn
*base_dn
,
1484 const char *netbios_name
,
1485 struct trustAuthInOutBlob
*in
)
1487 const char *attrs
[] = { "userAccountControl", NULL
};
1488 struct ldb_message
**msgs
;
1489 struct ldb_message
*msg
;
1494 ret
= gendb_search(sam_ldb
, mem_ctx
,
1495 base_dn
, &msgs
, attrs
,
1496 "samAccountName=%s$", netbios_name
);
1498 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1503 return NT_STATUS_OK
;
1506 /* ok no existing user, add it from scratch */
1507 return add_trust_user(mem_ctx
, sam_ldb
, base_dn
,
1508 netbios_name
, in
, NULL
);
1511 /* check user is what we are looking for */
1512 uac
= ldb_msg_find_attr_as_uint(msgs
[0],
1513 "userAccountControl", 0);
1514 if (!(uac
& UF_INTERDOMAIN_TRUST_ACCOUNT
)) {
1515 return NT_STATUS_OBJECT_NAME_COLLISION
;
1519 ret
= ldb_delete(sam_ldb
, msgs
[0]->dn
);
1522 return NT_STATUS_OK
;
1523 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
:
1524 return NT_STATUS_ACCESS_DENIED
;
1526 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1530 /* entry exists, just modify secret if any */
1531 if (in
== NULL
|| in
->count
== 0) {
1532 return NT_STATUS_OK
;
1535 msg
= ldb_msg_new(mem_ctx
);
1537 return NT_STATUS_NO_MEMORY
;
1539 msg
->dn
= msgs
[0]->dn
;
1541 for (i
= 0; i
< in
->count
; i
++) {
1542 const char *attribute
;
1544 switch (in
->current
.array
[i
].AuthType
) {
1545 case TRUST_AUTH_TYPE_NT4OWF
:
1546 attribute
= "unicodePwd";
1547 v
.data
= (uint8_t *)&in
->current
.array
[i
].AuthInfo
.nt4owf
.password
;
1550 case TRUST_AUTH_TYPE_CLEAR
:
1551 attribute
= "clearTextPassword";
1552 v
.data
= in
->current
.array
[i
].AuthInfo
.clear
.password
;
1553 v
.length
= in
->current
.array
[i
].AuthInfo
.clear
.size
;
1559 ret
= ldb_msg_add_empty(msg
, attribute
,
1560 LDB_FLAG_MOD_REPLACE
, NULL
);
1561 if (ret
!= LDB_SUCCESS
) {
1562 return NT_STATUS_NO_MEMORY
;
1565 ret
= ldb_msg_add_value(msg
, attribute
, &v
, NULL
);
1566 if (ret
!= LDB_SUCCESS
) {
1567 return NT_STATUS_NO_MEMORY
;
1571 /* create the trusted_domain user account */
1572 ret
= ldb_modify(sam_ldb
, msg
);
1573 if (ret
!= LDB_SUCCESS
) {
1574 DEBUG(0,("Failed to create user record %s: %s\n",
1575 ldb_dn_get_linearized(msg
->dn
),
1576 ldb_errstring(sam_ldb
)));
1579 case LDB_ERR_ENTRY_ALREADY_EXISTS
:
1580 return NT_STATUS_DOMAIN_EXISTS
;
1581 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
:
1582 return NT_STATUS_ACCESS_DENIED
;
1584 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1588 return NT_STATUS_OK
;
1592 static NTSTATUS
setInfoTrustedDomain_base(struct dcesrv_call_state
*dce_call
,
1593 struct dcesrv_handle
*p_handle
,
1594 TALLOC_CTX
*mem_ctx
,
1595 struct ldb_message
*dom_msg
,
1596 enum lsa_TrustDomInfoEnum level
,
1597 union lsa_TrustedDomainInfo
*info
)
1599 struct lsa_policy_state
*p_state
= p_handle
->data
;
1600 uint32_t *posix_offset
= NULL
;
1601 struct lsa_TrustDomainInfoInfoEx
*info_ex
= NULL
;
1602 struct lsa_TrustDomainInfoAuthInfo
*auth_info
= NULL
;
1603 struct lsa_TrustDomainInfoAuthInfoInternal
*auth_info_int
= NULL
;
1604 uint32_t *enc_types
= NULL
;
1605 DATA_BLOB trustAuthIncoming
, trustAuthOutgoing
, auth_blob
;
1606 struct trustDomainPasswords auth_struct
;
1607 struct trustAuthInOutBlob
*current_passwords
= NULL
;
1609 struct ldb_message
**msgs
;
1610 struct ldb_message
*msg
;
1611 bool add_outgoing
= false;
1612 bool add_incoming
= false;
1613 bool del_outgoing
= false;
1614 bool del_incoming
= false;
1615 bool in_transaction
= false;
1620 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET
:
1621 posix_offset
= &info
->posix_offset
.posix_offset
;
1623 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX
:
1624 info_ex
= &info
->info_ex
;
1626 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO
:
1627 auth_info
= &info
->auth_info
;
1629 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO
:
1630 posix_offset
= &info
->full_info
.posix_offset
.posix_offset
;
1631 info_ex
= &info
->full_info
.info_ex
;
1632 auth_info
= &info
->full_info
.auth_info
;
1634 case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL
:
1635 auth_info_int
= &info
->auth_info_internal
;
1637 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL
:
1638 posix_offset
= &info
->full_info_internal
.posix_offset
.posix_offset
;
1639 info_ex
= &info
->full_info_internal
.info_ex
;
1640 auth_info_int
= &info
->full_info_internal
.auth_info
;
1642 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES
:
1643 enc_types
= &info
->enc_types
.enc_types
;
1646 return NT_STATUS_INVALID_PARAMETER
;
1650 nt_status
= auth_info_2_auth_blob(mem_ctx
, auth_info
,
1652 &trustAuthOutgoing
);
1653 if (!NT_STATUS_IS_OK(nt_status
)) {
1656 if (trustAuthIncoming
.data
) {
1657 /* This does the decode of some of this twice, but it is easier that way */
1658 nt_status
= auth_info_2_trustauth_inout(mem_ctx
,
1659 auth_info
->incoming_count
,
1660 auth_info
->incoming_current_auth_info
,
1662 ¤t_passwords
);
1663 if (!NT_STATUS_IS_OK(nt_status
)) {
1669 /* decode auth_info_int if set */
1670 if (auth_info_int
) {
1672 /* now decrypt blob */
1673 auth_blob
= data_blob_const(auth_info_int
->auth_blob
.data
,
1674 auth_info_int
->auth_blob
.size
);
1676 nt_status
= get_trustdom_auth_blob(dce_call
, mem_ctx
,
1677 &auth_blob
, &auth_struct
);
1678 if (!NT_STATUS_IS_OK(nt_status
)) {
1684 /* verify data matches */
1685 if (info_ex
->trust_attributes
&
1686 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
) {
1687 /* TODO: check what behavior level we have */
1688 if (strcasecmp_m(p_state
->domain_dns
,
1689 p_state
->forest_dns
) != 0) {
1690 return NT_STATUS_INVALID_DOMAIN_STATE
;
1694 ret
= samdb_rodc(p_state
->sam_ldb
, &am_rodc
);
1695 if (ret
== LDB_SUCCESS
&& am_rodc
) {
1696 return NT_STATUS_NO_SUCH_DOMAIN
;
1699 /* verify only one object matches the dns/netbios/sid
1700 * triplet and that this is the one we already have */
1701 nt_status
= get_tdo(p_state
->sam_ldb
, mem_ctx
,
1703 info_ex
->domain_name
.string
,
1704 info_ex
->netbios_name
.string
,
1705 info_ex
->sid
, &msgs
);
1706 if (!NT_STATUS_IS_OK(nt_status
)) {
1709 if (ldb_dn_compare(dom_msg
->dn
, msgs
[0]->dn
) != 0) {
1710 return NT_STATUS_OBJECT_NAME_COLLISION
;
1715 /* TODO: should we fetch previous values from the existing entry
1716 * and append them ? */
1717 if (auth_info_int
&& auth_struct
.incoming
.count
) {
1718 nt_status
= get_trustauth_inout_blob(dce_call
, mem_ctx
,
1719 &auth_struct
.incoming
,
1720 &trustAuthIncoming
);
1721 if (!NT_STATUS_IS_OK(nt_status
)) {
1725 current_passwords
= &auth_struct
.incoming
;
1728 trustAuthIncoming
= data_blob(NULL
, 0);
1731 if (auth_info_int
&& auth_struct
.outgoing
.count
) {
1732 nt_status
= get_trustauth_inout_blob(dce_call
, mem_ctx
,
1733 &auth_struct
.outgoing
,
1734 &trustAuthOutgoing
);
1735 if (!NT_STATUS_IS_OK(nt_status
)) {
1739 trustAuthOutgoing
= data_blob(NULL
, 0);
1742 msg
= ldb_msg_new(mem_ctx
);
1744 return NT_STATUS_NO_MEMORY
;
1746 msg
->dn
= dom_msg
->dn
;
1749 nt_status
= update_uint32_t_value(mem_ctx
, p_state
->sam_ldb
,
1752 *posix_offset
, NULL
);
1753 if (!NT_STATUS_IS_OK(nt_status
)) {
1763 nt_status
= update_uint32_t_value(mem_ctx
, p_state
->sam_ldb
,
1766 info_ex
->trust_direction
,
1768 if (!NT_STATUS_IS_OK(nt_status
)) {
1772 if (info_ex
->trust_direction
& LSA_TRUST_DIRECTION_INBOUND
) {
1773 add_incoming
= true;
1775 if (info_ex
->trust_direction
& LSA_TRUST_DIRECTION_OUTBOUND
) {
1776 add_outgoing
= true;
1779 if ((origdir
& LSA_TRUST_DIRECTION_INBOUND
) &&
1780 !(info_ex
->trust_direction
& LSA_TRUST_DIRECTION_INBOUND
)) {
1781 del_incoming
= true;
1783 if ((origdir
& LSA_TRUST_DIRECTION_OUTBOUND
) &&
1784 !(info_ex
->trust_direction
& LSA_TRUST_DIRECTION_OUTBOUND
)) {
1785 del_outgoing
= true;
1788 origtype
= ldb_msg_find_attr_as_int(dom_msg
, "trustType", -1);
1789 if (origtype
== -1 || origtype
!= info_ex
->trust_type
) {
1790 DEBUG(1, ("Attempted to change trust type! "
1791 "Operation not handled\n"));
1792 return NT_STATUS_INVALID_PARAMETER
;
1795 nt_status
= update_uint32_t_value(mem_ctx
, p_state
->sam_ldb
,
1798 info_ex
->trust_attributes
,
1800 if (!NT_STATUS_IS_OK(nt_status
)) {
1803 /* TODO: check forestFunctionality from ldb opaque */
1804 /* TODO: check what is set makes sense */
1805 /* for now refuse changes */
1806 if (origattrs
== -1 ||
1807 origattrs
!= info_ex
->trust_attributes
) {
1808 DEBUG(1, ("Attempted to change trust attributes! "
1809 "Operation not handled\n"));
1810 return NT_STATUS_INVALID_PARAMETER
;
1815 nt_status
= update_uint32_t_value(mem_ctx
, p_state
->sam_ldb
,
1817 "msDS-SupportedEncryptionTypes",
1819 if (!NT_STATUS_IS_OK(nt_status
)) {
1824 if (add_incoming
&& trustAuthIncoming
.data
) {
1825 ret
= ldb_msg_add_empty(msg
, "trustAuthIncoming",
1826 LDB_FLAG_MOD_REPLACE
, NULL
);
1827 if (ret
!= LDB_SUCCESS
) {
1828 return NT_STATUS_NO_MEMORY
;
1830 ret
= ldb_msg_add_value(msg
, "trustAuthIncoming",
1831 &trustAuthIncoming
, NULL
);
1832 if (ret
!= LDB_SUCCESS
) {
1833 return NT_STATUS_NO_MEMORY
;
1836 if (add_outgoing
&& trustAuthOutgoing
.data
) {
1837 ret
= ldb_msg_add_empty(msg
, "trustAuthOutgoing",
1838 LDB_FLAG_MOD_REPLACE
, NULL
);
1839 if (ret
!= LDB_SUCCESS
) {
1840 return NT_STATUS_NO_MEMORY
;
1842 ret
= ldb_msg_add_value(msg
, "trustAuthOutgoing",
1843 &trustAuthOutgoing
, NULL
);
1844 if (ret
!= LDB_SUCCESS
) {
1845 return NT_STATUS_NO_MEMORY
;
1849 /* start transaction */
1850 ret
= ldb_transaction_start(p_state
->sam_ldb
);
1851 if (ret
!= LDB_SUCCESS
) {
1852 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1854 in_transaction
= true;
1856 if (msg
->num_elements
) {
1857 ret
= ldb_modify(p_state
->sam_ldb
, msg
);
1858 if (ret
!= LDB_SUCCESS
) {
1859 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1860 ldb_dn_get_linearized(msg
->dn
),
1861 ldb_errstring(p_state
->sam_ldb
)));
1862 nt_status
= dsdb_ldb_err_to_ntstatus(ret
);
1867 if (add_incoming
|| del_incoming
) {
1868 const char *netbios_name
;
1870 netbios_name
= ldb_msg_find_attr_as_string(dom_msg
,
1872 if (!netbios_name
) {
1873 nt_status
= NT_STATUS_INVALID_DOMAIN_STATE
;
1877 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
1878 nt_status
= update_trust_user(mem_ctx
,
1884 if (!NT_STATUS_IS_OK(nt_status
)) {
1889 /* ok, all fine, commit transaction and return */
1890 ret
= ldb_transaction_commit(p_state
->sam_ldb
);
1891 if (ret
!= LDB_SUCCESS
) {
1892 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1894 in_transaction
= false;
1896 nt_status
= NT_STATUS_OK
;
1899 if (in_transaction
) {
1900 ldb_transaction_cancel(p_state
->sam_ldb
);
1906 lsa_SetInfomrationTrustedDomain
1908 static NTSTATUS
dcesrv_lsa_SetInformationTrustedDomain(
1909 struct dcesrv_call_state
*dce_call
,
1910 TALLOC_CTX
*mem_ctx
,
1911 struct lsa_SetInformationTrustedDomain
*r
)
1913 struct dcesrv_handle
*h
;
1914 struct lsa_trusted_domain_state
*td_state
;
1915 struct ldb_message
**msgs
;
1918 DCESRV_PULL_HANDLE(h
, r
->in
.trustdom_handle
,
1919 LSA_HANDLE_TRUSTED_DOMAIN
);
1921 td_state
= talloc_get_type(h
->data
, struct lsa_trusted_domain_state
);
1923 /* get the trusted domain object */
1924 nt_status
= get_tdo(td_state
->policy
->sam_ldb
, mem_ctx
,
1925 td_state
->trusted_domain_dn
,
1926 NULL
, NULL
, NULL
, &msgs
);
1927 if (!NT_STATUS_IS_OK(nt_status
)) {
1928 if (NT_STATUS_EQUAL(nt_status
,
1929 NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1932 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1935 return setInfoTrustedDomain_base(dce_call
, h
, mem_ctx
,
1936 msgs
[0], r
->in
.level
, r
->in
.info
);
1941 lsa_DeleteTrustedDomain
1943 static NTSTATUS
dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1944 struct lsa_DeleteTrustedDomain
*r
)
1947 struct lsa_OpenTrustedDomain opn
;
1948 struct lsa_DeleteObject del
;
1949 struct dcesrv_handle
*h
;
1951 opn
.in
.handle
= r
->in
.handle
;
1952 opn
.in
.sid
= r
->in
.dom_sid
;
1953 opn
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
1954 opn
.out
.trustdom_handle
= talloc(mem_ctx
, struct policy_handle
);
1955 if (!opn
.out
.trustdom_handle
) {
1956 return NT_STATUS_NO_MEMORY
;
1958 status
= dcesrv_lsa_OpenTrustedDomain(dce_call
, mem_ctx
, &opn
);
1959 if (!NT_STATUS_IS_OK(status
)) {
1963 DCESRV_PULL_HANDLE(h
, opn
.out
.trustdom_handle
, DCESRV_HANDLE_ANY
);
1964 talloc_steal(mem_ctx
, h
);
1966 del
.in
.handle
= opn
.out
.trustdom_handle
;
1967 del
.out
.handle
= opn
.out
.trustdom_handle
;
1968 status
= dcesrv_lsa_DeleteObject(dce_call
, mem_ctx
, &del
);
1969 if (!NT_STATUS_IS_OK(status
)) {
1972 return NT_STATUS_OK
;
1975 static NTSTATUS
fill_trust_domain_ex(TALLOC_CTX
*mem_ctx
,
1976 struct ldb_message
*msg
,
1977 struct lsa_TrustDomainInfoInfoEx
*info_ex
)
1979 info_ex
->domain_name
.string
1980 = ldb_msg_find_attr_as_string(msg
, "trustPartner", NULL
);
1981 info_ex
->netbios_name
.string
1982 = ldb_msg_find_attr_as_string(msg
, "flatname", NULL
);
1984 = samdb_result_dom_sid(mem_ctx
, msg
, "securityIdentifier");
1985 info_ex
->trust_direction
1986 = ldb_msg_find_attr_as_int(msg
, "trustDirection", 0);
1988 = ldb_msg_find_attr_as_int(msg
, "trustType", 0);
1989 info_ex
->trust_attributes
1990 = ldb_msg_find_attr_as_int(msg
, "trustAttributes", 0);
1991 return NT_STATUS_OK
;
1995 lsa_QueryTrustedDomainInfo
1997 static NTSTATUS
dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1998 struct lsa_QueryTrustedDomainInfo
*r
)
2000 union lsa_TrustedDomainInfo
*info
= NULL
;
2001 struct dcesrv_handle
*h
;
2002 struct lsa_trusted_domain_state
*trusted_domain_state
;
2003 struct ldb_message
*msg
;
2005 struct ldb_message
**res
;
2006 const char *attrs
[] = {
2009 "securityIdentifier",
2013 "msDs-supportedEncryptionTypes",
2017 DCESRV_PULL_HANDLE(h
, r
->in
.trustdom_handle
, LSA_HANDLE_TRUSTED_DOMAIN
);
2019 trusted_domain_state
= talloc_get_type(h
->data
, struct lsa_trusted_domain_state
);
2021 /* pull all the user attributes */
2022 ret
= gendb_search_dn(trusted_domain_state
->policy
->sam_ldb
, mem_ctx
,
2023 trusted_domain_state
->trusted_domain_dn
, &res
, attrs
);
2025 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2029 info
= talloc_zero(mem_ctx
, union lsa_TrustedDomainInfo
);
2031 return NT_STATUS_NO_MEMORY
;
2033 *r
->out
.info
= info
;
2035 switch (r
->in
.level
) {
2036 case LSA_TRUSTED_DOMAIN_INFO_NAME
:
2037 info
->name
.netbios_name
.string
2038 = ldb_msg_find_attr_as_string(msg
, "flatname", NULL
);
2040 case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET
:
2041 info
->posix_offset
.posix_offset
2042 = ldb_msg_find_attr_as_uint(msg
, "posixOffset", 0);
2044 #if 0 /* Win2k3 doesn't implement this */
2045 case LSA_TRUSTED_DOMAIN_INFO_BASIC
:
2046 r
->out
.info
->info_basic
.netbios_name
.string
2047 = ldb_msg_find_attr_as_string(msg
, "flatname", NULL
);
2048 r
->out
.info
->info_basic
.sid
2049 = samdb_result_dom_sid(mem_ctx
, msg
, "securityIdentifier");
2052 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX
:
2053 return fill_trust_domain_ex(mem_ctx
, msg
, &info
->info_ex
);
2055 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO
:
2056 ZERO_STRUCT(info
->full_info
);
2057 return fill_trust_domain_ex(mem_ctx
, msg
, &info
->full_info
.info_ex
);
2058 case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL
:
2059 ZERO_STRUCT(info
->full_info2_internal
);
2060 info
->full_info2_internal
.posix_offset
.posix_offset
2061 = ldb_msg_find_attr_as_uint(msg
, "posixOffset", 0);
2062 return fill_trust_domain_ex(mem_ctx
, msg
, &info
->full_info2_internal
.info
.info_ex
);
2064 case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES
:
2065 info
->enc_types
.enc_types
2066 = ldb_msg_find_attr_as_uint(msg
, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5
);
2069 case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS
:
2070 case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL
:
2071 /* oops, we don't want to return the info after all */
2073 *r
->out
.info
= NULL
;
2074 return NT_STATUS_INVALID_PARAMETER
;
2076 /* oops, we don't want to return the info after all */
2078 *r
->out
.info
= NULL
;
2079 return NT_STATUS_INVALID_INFO_CLASS
;
2082 return NT_STATUS_OK
;
2087 lsa_QueryTrustedDomainInfoBySid
2089 static NTSTATUS
dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2090 struct lsa_QueryTrustedDomainInfoBySid
*r
)
2093 struct lsa_OpenTrustedDomain opn
;
2094 struct lsa_QueryTrustedDomainInfo query
;
2095 struct dcesrv_handle
*h
;
2097 opn
.in
.handle
= r
->in
.handle
;
2098 opn
.in
.sid
= r
->in
.dom_sid
;
2099 opn
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2100 opn
.out
.trustdom_handle
= talloc(mem_ctx
, struct policy_handle
);
2101 if (!opn
.out
.trustdom_handle
) {
2102 return NT_STATUS_NO_MEMORY
;
2104 status
= dcesrv_lsa_OpenTrustedDomain(dce_call
, mem_ctx
, &opn
);
2105 if (!NT_STATUS_IS_OK(status
)) {
2109 /* Ensure this handle goes away at the end of this call */
2110 DCESRV_PULL_HANDLE(h
, opn
.out
.trustdom_handle
, DCESRV_HANDLE_ANY
);
2111 talloc_steal(mem_ctx
, h
);
2113 query
.in
.trustdom_handle
= opn
.out
.trustdom_handle
;
2114 query
.in
.level
= r
->in
.level
;
2115 query
.out
.info
= r
->out
.info
;
2116 status
= dcesrv_lsa_QueryTrustedDomainInfo(dce_call
, mem_ctx
, &query
);
2117 if (!NT_STATUS_IS_OK(status
)) {
2121 return NT_STATUS_OK
;
2125 lsa_SetTrustedDomainInfoByName
2127 static NTSTATUS
dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state
*dce_call
,
2128 TALLOC_CTX
*mem_ctx
,
2129 struct lsa_SetTrustedDomainInfoByName
*r
)
2131 struct dcesrv_handle
*policy_handle
;
2132 struct lsa_policy_state
*policy_state
;
2133 struct ldb_message
**msgs
;
2136 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
2137 policy_state
= policy_handle
->data
;
2139 /* get the trusted domain object */
2140 nt_status
= get_tdo(policy_state
->sam_ldb
, mem_ctx
,
2141 policy_state
->domain_dn
,
2142 r
->in
.trusted_domain
->string
,
2143 r
->in
.trusted_domain
->string
,
2145 if (!NT_STATUS_IS_OK(nt_status
)) {
2146 if (NT_STATUS_EQUAL(nt_status
,
2147 NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
2150 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2153 return setInfoTrustedDomain_base(dce_call
, policy_handle
, mem_ctx
,
2154 msgs
[0], r
->in
.level
, r
->in
.info
);
2158 lsa_QueryTrustedDomainInfoByName
2160 static NTSTATUS
dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state
*dce_call
,
2161 TALLOC_CTX
*mem_ctx
,
2162 struct lsa_QueryTrustedDomainInfoByName
*r
)
2165 struct lsa_OpenTrustedDomainByName opn
;
2166 struct lsa_QueryTrustedDomainInfo query
;
2167 struct dcesrv_handle
*h
;
2169 opn
.in
.handle
= r
->in
.handle
;
2170 opn
.in
.name
= *r
->in
.trusted_domain
;
2171 opn
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2172 opn
.out
.trustdom_handle
= talloc(mem_ctx
, struct policy_handle
);
2173 if (!opn
.out
.trustdom_handle
) {
2174 return NT_STATUS_NO_MEMORY
;
2176 status
= dcesrv_lsa_OpenTrustedDomainByName(dce_call
, mem_ctx
, &opn
);
2177 if (!NT_STATUS_IS_OK(status
)) {
2181 /* Ensure this handle goes away at the end of this call */
2182 DCESRV_PULL_HANDLE(h
, opn
.out
.trustdom_handle
, DCESRV_HANDLE_ANY
);
2183 talloc_steal(mem_ctx
, h
);
2185 query
.in
.trustdom_handle
= opn
.out
.trustdom_handle
;
2186 query
.in
.level
= r
->in
.level
;
2187 query
.out
.info
= r
->out
.info
;
2188 status
= dcesrv_lsa_QueryTrustedDomainInfo(dce_call
, mem_ctx
, &query
);
2189 if (!NT_STATUS_IS_OK(status
)) {
2193 return NT_STATUS_OK
;
2197 lsa_CloseTrustedDomainEx
2199 static NTSTATUS
dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state
*dce_call
,
2200 TALLOC_CTX
*mem_ctx
,
2201 struct lsa_CloseTrustedDomainEx
*r
)
2203 /* The result of a bad hair day from an IDL programmer? Not
2204 * implmented in Win2k3. You should always just lsa_Close
2206 return NT_STATUS_NOT_IMPLEMENTED
;
2211 comparison function for sorting lsa_DomainInformation array
2213 static int compare_DomainInfo(struct lsa_DomainInfo
*e1
, struct lsa_DomainInfo
*e2
)
2215 return strcasecmp_m(e1
->name
.string
, e2
->name
.string
);
2221 static NTSTATUS
dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2222 struct lsa_EnumTrustDom
*r
)
2224 struct dcesrv_handle
*policy_handle
;
2225 struct lsa_DomainInfo
*entries
;
2226 struct lsa_policy_state
*policy_state
;
2227 struct ldb_message
**domains
;
2228 const char *attrs
[] = {
2230 "securityIdentifier",
2237 *r
->out
.resume_handle
= 0;
2239 r
->out
.domains
->domains
= NULL
;
2240 r
->out
.domains
->count
= 0;
2242 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
2244 policy_state
= policy_handle
->data
;
2246 /* search for all users in this domain. This could possibly be cached and
2247 resumed based on resume_key */
2248 count
= gendb_search(policy_state
->sam_ldb
, mem_ctx
, policy_state
->system_dn
, &domains
, attrs
,
2249 "objectclass=trustedDomain");
2251 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2254 /* convert to lsa_TrustInformation format */
2255 entries
= talloc_array(mem_ctx
, struct lsa_DomainInfo
, count
);
2257 return NT_STATUS_NO_MEMORY
;
2259 for (i
=0;i
<count
;i
++) {
2260 entries
[i
].sid
= samdb_result_dom_sid(mem_ctx
, domains
[i
], "securityIdentifier");
2261 entries
[i
].name
.string
= ldb_msg_find_attr_as_string(domains
[i
], "flatname", NULL
);
2264 /* sort the results by name */
2265 TYPESAFE_QSORT(entries
, count
, compare_DomainInfo
);
2267 if (*r
->in
.resume_handle
>= count
) {
2268 *r
->out
.resume_handle
= -1;
2270 return NT_STATUS_NO_MORE_ENTRIES
;
2273 /* return the rest, limit by max_size. Note that we
2274 use the w2k3 element size value of 60 */
2275 r
->out
.domains
->count
= count
- *r
->in
.resume_handle
;
2276 r
->out
.domains
->count
= MIN(r
->out
.domains
->count
,
2277 1+(r
->in
.max_size
/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER
));
2279 r
->out
.domains
->domains
= entries
+ *r
->in
.resume_handle
;
2280 r
->out
.domains
->count
= r
->out
.domains
->count
;
2282 if (r
->out
.domains
->count
< count
- *r
->in
.resume_handle
) {
2283 *r
->out
.resume_handle
= *r
->in
.resume_handle
+ r
->out
.domains
->count
;
2284 return STATUS_MORE_ENTRIES
;
2287 /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2288 * always be larger than the previous input resume handle, in
2289 * particular when hitting the last query it is vital to set the
2290 * resume handle correctly to avoid infinite client loops, as
2291 * seen e.g. with Windows XP SP3 when resume handle is 0 and
2292 * status is NT_STATUS_OK - gd */
2294 *r
->out
.resume_handle
= (uint32_t)-1;
2296 return NT_STATUS_OK
;
2300 comparison function for sorting lsa_DomainInformation array
2302 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx
*e1
, struct lsa_TrustDomainInfoInfoEx
*e2
)
2304 return strcasecmp_m(e1
->netbios_name
.string
, e2
->netbios_name
.string
);
2308 lsa_EnumTrustedDomainsEx
2310 static NTSTATUS
dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2311 struct lsa_EnumTrustedDomainsEx
*r
)
2313 struct dcesrv_handle
*policy_handle
;
2314 struct lsa_TrustDomainInfoInfoEx
*entries
;
2315 struct lsa_policy_state
*policy_state
;
2316 struct ldb_message
**domains
;
2317 const char *attrs
[] = {
2320 "securityIdentifier",
2330 *r
->out
.resume_handle
= 0;
2332 r
->out
.domains
->domains
= NULL
;
2333 r
->out
.domains
->count
= 0;
2335 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
2337 policy_state
= policy_handle
->data
;
2339 /* search for all users in this domain. This could possibly be cached and
2340 resumed based on resume_key */
2341 count
= gendb_search(policy_state
->sam_ldb
, mem_ctx
, policy_state
->system_dn
, &domains
, attrs
,
2342 "objectclass=trustedDomain");
2344 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2347 /* convert to lsa_DomainInformation format */
2348 entries
= talloc_array(mem_ctx
, struct lsa_TrustDomainInfoInfoEx
, count
);
2350 return NT_STATUS_NO_MEMORY
;
2352 for (i
=0;i
<count
;i
++) {
2353 nt_status
= fill_trust_domain_ex(mem_ctx
, domains
[i
], &entries
[i
]);
2354 if (!NT_STATUS_IS_OK(nt_status
)) {
2359 /* sort the results by name */
2360 TYPESAFE_QSORT(entries
, count
, compare_TrustDomainInfoInfoEx
);
2362 if (*r
->in
.resume_handle
>= count
) {
2363 *r
->out
.resume_handle
= -1;
2365 return NT_STATUS_NO_MORE_ENTRIES
;
2368 /* return the rest, limit by max_size. Note that we
2369 use the w2k3 element size value of 60 */
2370 r
->out
.domains
->count
= count
- *r
->in
.resume_handle
;
2371 r
->out
.domains
->count
= MIN(r
->out
.domains
->count
,
2372 1+(r
->in
.max_size
/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER
));
2374 r
->out
.domains
->domains
= entries
+ *r
->in
.resume_handle
;
2375 r
->out
.domains
->count
= r
->out
.domains
->count
;
2377 if (r
->out
.domains
->count
< count
- *r
->in
.resume_handle
) {
2378 *r
->out
.resume_handle
= *r
->in
.resume_handle
+ r
->out
.domains
->count
;
2379 return STATUS_MORE_ENTRIES
;
2382 return NT_STATUS_OK
;
2389 static NTSTATUS
dcesrv_lsa_OpenAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2390 struct lsa_OpenAccount
*r
)
2392 struct dcesrv_handle
*h
, *ah
;
2393 struct lsa_policy_state
*state
;
2394 struct lsa_account_state
*astate
;
2396 ZERO_STRUCTP(r
->out
.acct_handle
);
2398 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
2402 astate
= talloc(dce_call
->conn
, struct lsa_account_state
);
2403 if (astate
== NULL
) {
2404 return NT_STATUS_NO_MEMORY
;
2407 astate
->account_sid
= dom_sid_dup(astate
, r
->in
.sid
);
2408 if (astate
->account_sid
== NULL
) {
2409 talloc_free(astate
);
2410 return NT_STATUS_NO_MEMORY
;
2413 astate
->policy
= talloc_reference(astate
, state
);
2414 astate
->access_mask
= r
->in
.access_mask
;
2416 ah
= dcesrv_handle_new(dce_call
->context
, LSA_HANDLE_ACCOUNT
);
2418 talloc_free(astate
);
2419 return NT_STATUS_NO_MEMORY
;
2422 ah
->data
= talloc_steal(ah
, astate
);
2424 *r
->out
.acct_handle
= ah
->wire_handle
;
2426 return NT_STATUS_OK
;
2431 lsa_EnumPrivsAccount
2433 static NTSTATUS
dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state
*dce_call
,
2434 TALLOC_CTX
*mem_ctx
,
2435 struct lsa_EnumPrivsAccount
*r
)
2437 struct dcesrv_handle
*h
;
2438 struct lsa_account_state
*astate
;
2441 struct ldb_message
**res
;
2442 const char * const attrs
[] = { "privilege", NULL
};
2443 struct ldb_message_element
*el
;
2445 struct lsa_PrivilegeSet
*privs
;
2447 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_ACCOUNT
);
2451 privs
= talloc(mem_ctx
, struct lsa_PrivilegeSet
);
2452 if (privs
== NULL
) {
2453 return NT_STATUS_NO_MEMORY
;
2459 *r
->out
.privs
= privs
;
2461 sidstr
= ldap_encode_ndr_dom_sid(mem_ctx
, astate
->account_sid
);
2462 if (sidstr
== NULL
) {
2463 return NT_STATUS_NO_MEMORY
;
2466 ret
= gendb_search(astate
->policy
->pdb
, mem_ctx
, NULL
, &res
, attrs
,
2467 "objectSid=%s", sidstr
);
2469 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2472 return NT_STATUS_OK
;
2475 el
= ldb_msg_find_element(res
[0], "privilege");
2476 if (el
== NULL
|| el
->num_values
== 0) {
2477 return NT_STATUS_OK
;
2480 privs
->set
= talloc_array(privs
,
2481 struct lsa_LUIDAttribute
, el
->num_values
);
2482 if (privs
->set
== NULL
) {
2483 return NT_STATUS_NO_MEMORY
;
2487 for (i
=0;i
<el
->num_values
;i
++) {
2488 int id
= sec_privilege_id((const char *)el
->values
[i
].data
);
2489 if (id
== SEC_PRIV_INVALID
) {
2490 /* Perhaps an account right, not a privilege */
2493 privs
->set
[j
].attribute
= 0;
2494 privs
->set
[j
].luid
.low
= id
;
2495 privs
->set
[j
].luid
.high
= 0;
2501 return NT_STATUS_OK
;
2505 lsa_EnumAccountRights
2507 static NTSTATUS
dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state
*dce_call
,
2508 TALLOC_CTX
*mem_ctx
,
2509 struct lsa_EnumAccountRights
*r
)
2511 struct dcesrv_handle
*h
;
2512 struct lsa_policy_state
*state
;
2515 struct ldb_message
**res
;
2516 const char * const attrs
[] = { "privilege", NULL
};
2518 struct ldb_message_element
*el
;
2520 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
2524 sidstr
= ldap_encode_ndr_dom_sid(mem_ctx
, r
->in
.sid
);
2525 if (sidstr
== NULL
) {
2526 return NT_STATUS_NO_MEMORY
;
2529 ret
= gendb_search(state
->pdb
, mem_ctx
, NULL
, &res
, attrs
,
2530 "(&(objectSid=%s)(privilege=*))", sidstr
);
2532 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
2535 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2536 dom_sid_string(mem_ctx
, r
->in
.sid
),
2537 ldb_errstring(state
->pdb
)));
2538 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2541 el
= ldb_msg_find_element(res
[0], "privilege");
2542 if (el
== NULL
|| el
->num_values
== 0) {
2543 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
2546 r
->out
.rights
->count
= el
->num_values
;
2547 r
->out
.rights
->names
= talloc_array(r
->out
.rights
,
2548 struct lsa_StringLarge
, r
->out
.rights
->count
);
2549 if (r
->out
.rights
->names
== NULL
) {
2550 return NT_STATUS_NO_MEMORY
;
2553 for (i
=0;i
<el
->num_values
;i
++) {
2554 r
->out
.rights
->names
[i
].string
= (const char *)el
->values
[i
].data
;
2557 return NT_STATUS_OK
;
2563 helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2565 static NTSTATUS
dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state
*dce_call
,
2566 TALLOC_CTX
*mem_ctx
,
2567 struct lsa_policy_state
*state
,
2569 struct dom_sid
*sid
,
2570 const struct lsa_RightSet
*rights
)
2572 const char *sidstr
, *sidndrstr
;
2573 struct ldb_message
*msg
;
2574 struct ldb_message_element
*el
;
2577 struct lsa_EnumAccountRights r2
;
2580 if (security_session_user_level(dce_call
->conn
->auth_state
.session_info
, NULL
) <
2581 SECURITY_ADMINISTRATOR
) {
2582 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2583 return NT_STATUS_ACCESS_DENIED
;
2586 msg
= ldb_msg_new(mem_ctx
);
2588 return NT_STATUS_NO_MEMORY
;
2591 sidndrstr
= ldap_encode_ndr_dom_sid(msg
, sid
);
2592 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr
, msg
);
2594 sidstr
= dom_sid_string(msg
, sid
);
2595 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr
, msg
);
2597 dnstr
= talloc_asprintf(msg
, "sid=%s", sidstr
);
2598 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr
, msg
);
2600 msg
->dn
= ldb_dn_new(msg
, state
->pdb
, dnstr
);
2601 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg
->dn
, msg
);
2603 if (LDB_FLAG_MOD_TYPE(ldb_flag
) == LDB_FLAG_MOD_ADD
) {
2606 r2
.in
.handle
= &state
->handle
->wire_handle
;
2608 r2
.out
.rights
= talloc(mem_ctx
, struct lsa_RightSet
);
2610 status
= dcesrv_lsa_EnumAccountRights(dce_call
, mem_ctx
, &r2
);
2611 if (!NT_STATUS_IS_OK(status
)) {
2612 ZERO_STRUCTP(r2
.out
.rights
);
2616 for (i
=0;i
<rights
->count
;i
++) {
2617 if (sec_privilege_id(rights
->names
[i
].string
) == SEC_PRIV_INVALID
) {
2618 if (sec_right_bit(rights
->names
[i
].string
) == 0) {
2620 return NT_STATUS_NO_SUCH_PRIVILEGE
;
2624 return NT_STATUS_NO_SUCH_PRIVILEGE
;
2627 if (LDB_FLAG_MOD_TYPE(ldb_flag
) == LDB_FLAG_MOD_ADD
) {
2629 for (j
=0;j
<r2
.out
.rights
->count
;j
++) {
2630 if (strcasecmp_m(r2
.out
.rights
->names
[j
].string
,
2631 rights
->names
[i
].string
) == 0) {
2635 if (j
!= r2
.out
.rights
->count
) continue;
2638 ret
= ldb_msg_add_string(msg
, "privilege", rights
->names
[i
].string
);
2639 if (ret
!= LDB_SUCCESS
) {
2641 return NT_STATUS_NO_MEMORY
;
2645 el
= ldb_msg_find_element(msg
, "privilege");
2648 return NT_STATUS_OK
;
2651 el
->flags
= ldb_flag
;
2653 ret
= ldb_modify(state
->pdb
, msg
);
2654 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
2655 if (samdb_msg_add_dom_sid(state
->pdb
, msg
, msg
, "objectSid", sid
) != LDB_SUCCESS
) {
2657 return NT_STATUS_NO_MEMORY
;
2659 ldb_msg_add_string(msg
, "comment", "added via LSA");
2660 ret
= ldb_add(state
->pdb
, msg
);
2662 if (ret
!= LDB_SUCCESS
) {
2663 if (LDB_FLAG_MOD_TYPE(ldb_flag
) == LDB_FLAG_MOD_DELETE
&& ret
== LDB_ERR_NO_SUCH_ATTRIBUTE
) {
2665 return NT_STATUS_OK
;
2667 DEBUG(3, ("Could not %s attributes from %s: %s",
2668 LDB_FLAG_MOD_TYPE(ldb_flag
) == LDB_FLAG_MOD_DELETE
? "delete" : "add",
2669 ldb_dn_get_linearized(msg
->dn
), ldb_errstring(state
->pdb
)));
2671 return NT_STATUS_UNEXPECTED_IO_ERROR
;
2675 return NT_STATUS_OK
;
2679 lsa_AddPrivilegesToAccount
2681 static NTSTATUS
dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2682 struct lsa_AddPrivilegesToAccount
*r
)
2684 struct lsa_RightSet rights
;
2685 struct dcesrv_handle
*h
;
2686 struct lsa_account_state
*astate
;
2689 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_ACCOUNT
);
2693 rights
.count
= r
->in
.privs
->count
;
2694 rights
.names
= talloc_array(mem_ctx
, struct lsa_StringLarge
, rights
.count
);
2695 if (rights
.names
== NULL
) {
2696 return NT_STATUS_NO_MEMORY
;
2698 for (i
=0;i
<rights
.count
;i
++) {
2699 int id
= r
->in
.privs
->set
[i
].luid
.low
;
2700 if (r
->in
.privs
->set
[i
].luid
.high
) {
2701 return NT_STATUS_NO_SUCH_PRIVILEGE
;
2703 rights
.names
[i
].string
= sec_privilege_name(id
);
2704 if (rights
.names
[i
].string
== NULL
) {
2705 return NT_STATUS_NO_SUCH_PRIVILEGE
;
2709 return dcesrv_lsa_AddRemoveAccountRights(dce_call
, mem_ctx
, astate
->policy
,
2710 LDB_FLAG_MOD_ADD
, astate
->account_sid
,
2716 lsa_RemovePrivilegesFromAccount
2718 static NTSTATUS
dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2719 struct lsa_RemovePrivilegesFromAccount
*r
)
2721 struct lsa_RightSet
*rights
;
2722 struct dcesrv_handle
*h
;
2723 struct lsa_account_state
*astate
;
2726 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_ACCOUNT
);
2730 rights
= talloc(mem_ctx
, struct lsa_RightSet
);
2732 if (r
->in
.remove_all
== 1 &&
2733 r
->in
.privs
== NULL
) {
2734 struct lsa_EnumAccountRights r2
;
2737 r2
.in
.handle
= &astate
->policy
->handle
->wire_handle
;
2738 r2
.in
.sid
= astate
->account_sid
;
2739 r2
.out
.rights
= rights
;
2741 status
= dcesrv_lsa_EnumAccountRights(dce_call
, mem_ctx
, &r2
);
2742 if (!NT_STATUS_IS_OK(status
)) {
2746 return dcesrv_lsa_AddRemoveAccountRights(dce_call
, mem_ctx
, astate
->policy
,
2747 LDB_FLAG_MOD_DELETE
, astate
->account_sid
,
2751 if (r
->in
.remove_all
!= 0) {
2752 return NT_STATUS_INVALID_PARAMETER
;
2755 rights
->count
= r
->in
.privs
->count
;
2756 rights
->names
= talloc_array(mem_ctx
, struct lsa_StringLarge
, rights
->count
);
2757 if (rights
->names
== NULL
) {
2758 return NT_STATUS_NO_MEMORY
;
2760 for (i
=0;i
<rights
->count
;i
++) {
2761 int id
= r
->in
.privs
->set
[i
].luid
.low
;
2762 if (r
->in
.privs
->set
[i
].luid
.high
) {
2763 return NT_STATUS_NO_SUCH_PRIVILEGE
;
2765 rights
->names
[i
].string
= sec_privilege_name(id
);
2766 if (rights
->names
[i
].string
== NULL
) {
2767 return NT_STATUS_NO_SUCH_PRIVILEGE
;
2771 return dcesrv_lsa_AddRemoveAccountRights(dce_call
, mem_ctx
, astate
->policy
,
2772 LDB_FLAG_MOD_DELETE
, astate
->account_sid
,
2778 lsa_GetQuotasForAccount
2780 static NTSTATUS
dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2781 struct lsa_GetQuotasForAccount
*r
)
2783 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
2788 lsa_SetQuotasForAccount
2790 static NTSTATUS
dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2791 struct lsa_SetQuotasForAccount
*r
)
2793 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
2798 lsa_GetSystemAccessAccount
2800 static NTSTATUS
dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2801 struct lsa_GetSystemAccessAccount
*r
)
2803 struct dcesrv_handle
*h
;
2804 struct lsa_account_state
*astate
;
2807 struct ldb_message
**res
;
2808 const char * const attrs
[] = { "privilege", NULL
};
2809 struct ldb_message_element
*el
;
2812 *(r
->out
.access_mask
) = 0x00000000;
2814 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_ACCOUNT
);
2818 sidstr
= ldap_encode_ndr_dom_sid(mem_ctx
, astate
->account_sid
);
2819 if (sidstr
== NULL
) {
2820 return NT_STATUS_NO_MEMORY
;
2823 ret
= gendb_search(astate
->policy
->pdb
, mem_ctx
, NULL
, &res
, attrs
,
2824 "objectSid=%s", sidstr
);
2826 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2829 return NT_STATUS_OK
;
2832 el
= ldb_msg_find_element(res
[0], "privilege");
2833 if (el
== NULL
|| el
->num_values
== 0) {
2834 return NT_STATUS_OK
;
2837 for (i
=0;i
<el
->num_values
;i
++) {
2838 uint32_t right_bit
= sec_right_bit((const char *)el
->values
[i
].data
);
2839 if (right_bit
== 0) {
2840 /* Perhaps an privilege, not a right */
2843 *(r
->out
.access_mask
) |= right_bit
;
2846 return NT_STATUS_OK
;
2851 lsa_SetSystemAccessAccount
2853 static NTSTATUS
dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2854 struct lsa_SetSystemAccessAccount
*r
)
2856 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
2863 static NTSTATUS
dcesrv_lsa_CreateSecret(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2864 struct lsa_CreateSecret
*r
)
2866 struct dcesrv_handle
*policy_handle
;
2867 struct lsa_policy_state
*policy_state
;
2868 struct lsa_secret_state
*secret_state
;
2869 struct dcesrv_handle
*handle
;
2870 struct ldb_message
**msgs
, *msg
;
2871 const char *attrs
[] = {
2879 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
2880 ZERO_STRUCTP(r
->out
.sec_handle
);
2882 switch (security_session_user_level(dce_call
->conn
->auth_state
.session_info
, NULL
))
2884 case SECURITY_SYSTEM
:
2885 case SECURITY_ADMINISTRATOR
:
2888 /* Users and annonymous are not allowed create secrets */
2889 return NT_STATUS_ACCESS_DENIED
;
2892 policy_state
= policy_handle
->data
;
2894 if (!r
->in
.name
.string
) {
2895 return NT_STATUS_INVALID_PARAMETER
;
2898 secret_state
= talloc(mem_ctx
, struct lsa_secret_state
);
2899 NT_STATUS_HAVE_NO_MEMORY(secret_state
);
2900 secret_state
->policy
= policy_state
;
2902 msg
= ldb_msg_new(mem_ctx
);
2904 return NT_STATUS_NO_MEMORY
;
2907 if (strncmp("G$", r
->in
.name
.string
, 2) == 0) {
2910 secret_state
->global
= true;
2912 name
= &r
->in
.name
.string
[2];
2913 if (strlen(name
) == 0) {
2914 return NT_STATUS_INVALID_PARAMETER
;
2917 name2
= talloc_asprintf(mem_ctx
, "%s Secret",
2918 ldb_binary_encode_string(mem_ctx
, name
));
2919 NT_STATUS_HAVE_NO_MEMORY(name2
);
2921 /* We need to connect to the database as system, as this is one
2922 * of the rare RPC calls that must read the secrets (and this
2923 * is denied otherwise) */
2924 secret_state
->sam_ldb
= talloc_reference(secret_state
,
2925 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));
2926 NT_STATUS_HAVE_NO_MEMORY(secret_state
->sam_ldb
);
2928 /* search for the secret record */
2929 ret
= gendb_search(secret_state
->sam_ldb
,
2930 mem_ctx
, policy_state
->system_dn
, &msgs
, attrs
,
2931 "(&(cn=%s)(objectclass=secret))",
2934 return NT_STATUS_OBJECT_NAME_COLLISION
;
2938 DEBUG(0,("Failure searching for CN=%s: %s\n",
2939 name2
, ldb_errstring(secret_state
->sam_ldb
)));
2940 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2943 msg
->dn
= ldb_dn_copy(mem_ctx
, policy_state
->system_dn
);
2944 NT_STATUS_HAVE_NO_MEMORY(msg
->dn
);
2945 if (!ldb_dn_add_child_fmt(msg
->dn
, "cn=%s", name2
)) {
2946 return NT_STATUS_NO_MEMORY
;
2949 ret
= ldb_msg_add_string(msg
, "cn", name2
);
2950 if (ret
!= LDB_SUCCESS
) return NT_STATUS_NO_MEMORY
;
2952 secret_state
->global
= false;
2954 name
= r
->in
.name
.string
;
2955 if (strlen(name
) == 0) {
2956 return NT_STATUS_INVALID_PARAMETER
;
2959 secret_state
->sam_ldb
= talloc_reference(secret_state
,
2960 secrets_db_connect(mem_ctx
, dce_call
->conn
->dce_ctx
->lp_ctx
));
2961 NT_STATUS_HAVE_NO_MEMORY(secret_state
->sam_ldb
);
2963 /* search for the secret record */
2964 ret
= gendb_search(secret_state
->sam_ldb
, mem_ctx
,
2965 ldb_dn_new(mem_ctx
, secret_state
->sam_ldb
, "cn=LSA Secrets"),
2967 "(&(cn=%s)(objectclass=secret))",
2968 ldb_binary_encode_string(mem_ctx
, name
));
2970 return NT_STATUS_OBJECT_NAME_COLLISION
;
2974 DEBUG(0,("Failure searching for CN=%s: %s\n",
2975 name
, ldb_errstring(secret_state
->sam_ldb
)));
2976 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2979 msg
->dn
= ldb_dn_new_fmt(mem_ctx
, secret_state
->sam_ldb
,
2980 "cn=%s,cn=LSA Secrets", name
);
2981 NT_STATUS_HAVE_NO_MEMORY(msg
->dn
);
2982 ret
= ldb_msg_add_string(msg
, "cn", name
);
2983 if (ret
!= LDB_SUCCESS
) return NT_STATUS_NO_MEMORY
;
2986 ret
= ldb_msg_add_string(msg
, "objectClass", "secret");
2987 if (ret
!= LDB_SUCCESS
) return NT_STATUS_NO_MEMORY
;
2989 secret_state
->secret_dn
= talloc_reference(secret_state
, msg
->dn
);
2990 NT_STATUS_HAVE_NO_MEMORY(secret_state
->secret_dn
);
2992 /* create the secret */
2993 ret
= ldb_add(secret_state
->sam_ldb
, msg
);
2994 if (ret
!= LDB_SUCCESS
) {
2995 DEBUG(0,("Failed to create secret record %s: %s\n",
2996 ldb_dn_get_linearized(msg
->dn
),
2997 ldb_errstring(secret_state
->sam_ldb
)));
2998 return NT_STATUS_ACCESS_DENIED
;
3001 handle
= dcesrv_handle_new(dce_call
->context
, LSA_HANDLE_SECRET
);
3002 NT_STATUS_HAVE_NO_MEMORY(handle
);
3004 handle
->data
= talloc_steal(handle
, secret_state
);
3006 secret_state
->access_mask
= r
->in
.access_mask
;
3007 secret_state
->policy
= talloc_reference(secret_state
, policy_state
);
3008 NT_STATUS_HAVE_NO_MEMORY(secret_state
->policy
);
3010 *r
->out
.sec_handle
= handle
->wire_handle
;
3012 return NT_STATUS_OK
;
3019 static NTSTATUS
dcesrv_lsa_OpenSecret(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3020 struct lsa_OpenSecret
*r
)
3022 struct dcesrv_handle
*policy_handle
;
3024 struct lsa_policy_state
*policy_state
;
3025 struct lsa_secret_state
*secret_state
;
3026 struct dcesrv_handle
*handle
;
3027 struct ldb_message
**msgs
;
3028 const char *attrs
[] = {
3036 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3037 ZERO_STRUCTP(r
->out
.sec_handle
);
3038 policy_state
= policy_handle
->data
;
3040 if (!r
->in
.name
.string
) {
3041 return NT_STATUS_INVALID_PARAMETER
;
3044 switch (security_session_user_level(dce_call
->conn
->auth_state
.session_info
, NULL
))
3046 case SECURITY_SYSTEM
:
3047 case SECURITY_ADMINISTRATOR
:
3050 /* Users and annonymous are not allowed to access secrets */
3051 return NT_STATUS_ACCESS_DENIED
;
3054 secret_state
= talloc(mem_ctx
, struct lsa_secret_state
);
3055 if (!secret_state
) {
3056 return NT_STATUS_NO_MEMORY
;
3058 secret_state
->policy
= policy_state
;
3060 if (strncmp("G$", r
->in
.name
.string
, 2) == 0) {
3061 name
= &r
->in
.name
.string
[2];
3062 /* 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) */
3063 secret_state
->sam_ldb
= talloc_reference(secret_state
,
3064 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));
3065 secret_state
->global
= true;
3067 if (strlen(name
) < 1) {
3068 return NT_STATUS_INVALID_PARAMETER
;
3071 /* search for the secret record */
3072 ret
= gendb_search(secret_state
->sam_ldb
,
3073 mem_ctx
, policy_state
->system_dn
, &msgs
, attrs
,
3074 "(&(cn=%s Secret)(objectclass=secret))",
3075 ldb_binary_encode_string(mem_ctx
, name
));
3077 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3081 DEBUG(0,("Found %d records matching DN %s\n", ret
,
3082 ldb_dn_get_linearized(policy_state
->system_dn
)));
3083 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
3086 secret_state
->global
= false;
3087 secret_state
->sam_ldb
= talloc_reference(secret_state
,
3088 secrets_db_connect(mem_ctx
, dce_call
->conn
->dce_ctx
->lp_ctx
));
3090 name
= r
->in
.name
.string
;
3091 if (strlen(name
) < 1) {
3092 return NT_STATUS_INVALID_PARAMETER
;
3095 /* search for the secret record */
3096 ret
= gendb_search(secret_state
->sam_ldb
, mem_ctx
,
3097 ldb_dn_new(mem_ctx
, secret_state
->sam_ldb
, "cn=LSA Secrets"),
3099 "(&(cn=%s)(objectclass=secret))",
3100 ldb_binary_encode_string(mem_ctx
, name
));
3102 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3106 DEBUG(0,("Found %d records matching CN=%s\n",
3107 ret
, ldb_binary_encode_string(mem_ctx
, name
)));
3108 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
3112 secret_state
->secret_dn
= talloc_reference(secret_state
, msgs
[0]->dn
);
3114 handle
= dcesrv_handle_new(dce_call
->context
, LSA_HANDLE_SECRET
);
3116 return NT_STATUS_NO_MEMORY
;
3119 handle
->data
= talloc_steal(handle
, secret_state
);
3121 secret_state
->access_mask
= r
->in
.access_mask
;
3122 secret_state
->policy
= talloc_reference(secret_state
, policy_state
);
3124 *r
->out
.sec_handle
= handle
->wire_handle
;
3126 return NT_STATUS_OK
;
3133 static NTSTATUS
dcesrv_lsa_SetSecret(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3134 struct lsa_SetSecret
*r
)
3137 struct dcesrv_handle
*h
;
3138 struct lsa_secret_state
*secret_state
;
3139 struct ldb_message
*msg
;
3140 DATA_BLOB session_key
;
3141 DATA_BLOB crypt_secret
, secret
;
3144 NTSTATUS status
= NT_STATUS_OK
;
3146 struct timeval now
= timeval_current();
3147 NTTIME nt_now
= timeval_to_nttime(&now
);
3149 DCESRV_PULL_HANDLE(h
, r
->in
.sec_handle
, LSA_HANDLE_SECRET
);
3151 secret_state
= h
->data
;
3153 msg
= ldb_msg_new(mem_ctx
);
3155 return NT_STATUS_NO_MEMORY
;
3158 msg
->dn
= talloc_reference(mem_ctx
, secret_state
->secret_dn
);
3160 return NT_STATUS_NO_MEMORY
;
3162 status
= dcesrv_fetch_session_key(dce_call
->conn
, &session_key
);
3163 if (!NT_STATUS_IS_OK(status
)) {
3167 if (r
->in
.old_val
) {
3169 crypt_secret
.data
= r
->in
.old_val
->data
;
3170 crypt_secret
.length
= r
->in
.old_val
->size
;
3172 status
= sess_decrypt_blob(mem_ctx
, &crypt_secret
, &session_key
, &secret
);
3173 if (!NT_STATUS_IS_OK(status
)) {
3177 val
.data
= secret
.data
;
3178 val
.length
= secret
.length
;
3181 if (ldb_msg_add_value(msg
, "priorValue", &val
, NULL
) != LDB_SUCCESS
) {
3182 return NT_STATUS_NO_MEMORY
;
3185 /* set old value mtime */
3186 if (samdb_msg_add_uint64(secret_state
->sam_ldb
,
3187 mem_ctx
, msg
, "priorSetTime", nt_now
) != LDB_SUCCESS
) {
3188 return NT_STATUS_NO_MEMORY
;
3192 /* If the old value is not set, then migrate the
3193 * current value to the old value */
3194 const struct ldb_val
*old_val
;
3195 NTTIME last_set_time
;
3196 struct ldb_message
**res
;
3197 const char *attrs
[] = {
3203 /* search for the secret record */
3204 ret
= gendb_search_dn(secret_state
->sam_ldb
,mem_ctx
,
3205 secret_state
->secret_dn
, &res
, attrs
);
3207 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3211 DEBUG(0,("Found %d records matching dn=%s\n", ret
,
3212 ldb_dn_get_linearized(secret_state
->secret_dn
)));
3213 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
3216 old_val
= ldb_msg_find_ldb_val(res
[0], "currentValue");
3217 last_set_time
= ldb_msg_find_attr_as_uint64(res
[0], "lastSetTime", 0);
3221 if (ldb_msg_add_value(msg
, "priorValue",
3222 old_val
, NULL
) != LDB_SUCCESS
) {
3223 return NT_STATUS_NO_MEMORY
;
3226 if (samdb_msg_add_delete(secret_state
->sam_ldb
,
3227 mem_ctx
, msg
, "priorValue") != LDB_SUCCESS
) {
3228 return NT_STATUS_NO_MEMORY
;
3232 /* set old value mtime */
3233 if (ldb_msg_find_ldb_val(res
[0], "lastSetTime")) {
3234 if (samdb_msg_add_uint64(secret_state
->sam_ldb
,
3235 mem_ctx
, msg
, "priorSetTime", last_set_time
) != LDB_SUCCESS
) {
3236 return NT_STATUS_NO_MEMORY
;
3239 if (samdb_msg_add_uint64(secret_state
->sam_ldb
,
3240 mem_ctx
, msg
, "priorSetTime", nt_now
) != LDB_SUCCESS
) {
3241 return NT_STATUS_NO_MEMORY
;
3246 if (r
->in
.new_val
) {
3248 crypt_secret
.data
= r
->in
.new_val
->data
;
3249 crypt_secret
.length
= r
->in
.new_val
->size
;
3251 status
= sess_decrypt_blob(mem_ctx
, &crypt_secret
, &session_key
, &secret
);
3252 if (!NT_STATUS_IS_OK(status
)) {
3256 val
.data
= secret
.data
;
3257 val
.length
= secret
.length
;
3260 if (ldb_msg_add_value(msg
, "currentValue", &val
, NULL
) != LDB_SUCCESS
) {
3261 return NT_STATUS_NO_MEMORY
;
3264 /* set new value mtime */
3265 if (samdb_msg_add_uint64(secret_state
->sam_ldb
,
3266 mem_ctx
, msg
, "lastSetTime", nt_now
) != LDB_SUCCESS
) {
3267 return NT_STATUS_NO_MEMORY
;
3270 /* NULL out the NEW value */
3271 if (samdb_msg_add_uint64(secret_state
->sam_ldb
,
3272 mem_ctx
, msg
, "lastSetTime", nt_now
) != LDB_SUCCESS
) {
3273 return NT_STATUS_NO_MEMORY
;
3275 if (samdb_msg_add_delete(secret_state
->sam_ldb
,
3276 mem_ctx
, msg
, "currentValue") != LDB_SUCCESS
) {
3277 return NT_STATUS_NO_MEMORY
;
3281 /* modify the samdb record */
3282 ret
= dsdb_replace(secret_state
->sam_ldb
, msg
, 0);
3283 if (ret
!= LDB_SUCCESS
) {
3284 return dsdb_ldb_err_to_ntstatus(ret
);
3287 return NT_STATUS_OK
;
3294 static NTSTATUS
dcesrv_lsa_QuerySecret(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3295 struct lsa_QuerySecret
*r
)
3297 struct dcesrv_handle
*h
;
3298 struct lsa_secret_state
*secret_state
;
3299 struct ldb_message
*msg
;
3300 DATA_BLOB session_key
;
3301 DATA_BLOB crypt_secret
, secret
;
3303 struct ldb_message
**res
;
3304 const char *attrs
[] = {
3314 DCESRV_PULL_HANDLE(h
, r
->in
.sec_handle
, LSA_HANDLE_SECRET
);
3316 /* Ensure user is permitted to read this... */
3317 switch (security_session_user_level(dce_call
->conn
->auth_state
.session_info
, NULL
))
3319 case SECURITY_SYSTEM
:
3320 case SECURITY_ADMINISTRATOR
:
3323 /* Users and annonymous are not allowed to read secrets */
3324 return NT_STATUS_ACCESS_DENIED
;
3327 secret_state
= h
->data
;
3329 /* pull all the user attributes */
3330 ret
= gendb_search_dn(secret_state
->sam_ldb
, mem_ctx
,
3331 secret_state
->secret_dn
, &res
, attrs
);
3333 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
3337 nt_status
= dcesrv_fetch_session_key(dce_call
->conn
, &session_key
);
3338 if (!NT_STATUS_IS_OK(nt_status
)) {
3342 if (r
->in
.old_val
) {
3343 const struct ldb_val
*prior_val
;
3344 r
->out
.old_val
= talloc_zero(mem_ctx
, struct lsa_DATA_BUF_PTR
);
3345 if (!r
->out
.old_val
) {
3346 return NT_STATUS_NO_MEMORY
;
3348 prior_val
= ldb_msg_find_ldb_val(res
[0], "priorValue");
3350 if (prior_val
&& prior_val
->length
) {
3351 secret
.data
= prior_val
->data
;
3352 secret
.length
= prior_val
->length
;
3355 crypt_secret
= sess_encrypt_blob(mem_ctx
, &secret
, &session_key
);
3356 if (!crypt_secret
.length
) {
3357 return NT_STATUS_NO_MEMORY
;
3359 r
->out
.old_val
->buf
= talloc(mem_ctx
, struct lsa_DATA_BUF
);
3360 if (!r
->out
.old_val
->buf
) {
3361 return NT_STATUS_NO_MEMORY
;
3363 r
->out
.old_val
->buf
->size
= crypt_secret
.length
;
3364 r
->out
.old_val
->buf
->length
= crypt_secret
.length
;
3365 r
->out
.old_val
->buf
->data
= crypt_secret
.data
;
3369 if (r
->in
.old_mtime
) {
3370 r
->out
.old_mtime
= talloc(mem_ctx
, NTTIME
);
3371 if (!r
->out
.old_mtime
) {
3372 return NT_STATUS_NO_MEMORY
;
3374 *r
->out
.old_mtime
= ldb_msg_find_attr_as_uint64(res
[0], "priorSetTime", 0);
3377 if (r
->in
.new_val
) {
3378 const struct ldb_val
*new_val
;
3379 r
->out
.new_val
= talloc_zero(mem_ctx
, struct lsa_DATA_BUF_PTR
);
3380 if (!r
->out
.new_val
) {
3381 return NT_STATUS_NO_MEMORY
;
3384 new_val
= ldb_msg_find_ldb_val(res
[0], "currentValue");
3386 if (new_val
&& new_val
->length
) {
3387 secret
.data
= new_val
->data
;
3388 secret
.length
= new_val
->length
;
3391 crypt_secret
= sess_encrypt_blob(mem_ctx
, &secret
, &session_key
);
3392 if (!crypt_secret
.length
) {
3393 return NT_STATUS_NO_MEMORY
;
3395 r
->out
.new_val
->buf
= talloc(mem_ctx
, struct lsa_DATA_BUF
);
3396 if (!r
->out
.new_val
->buf
) {
3397 return NT_STATUS_NO_MEMORY
;
3399 r
->out
.new_val
->buf
->length
= crypt_secret
.length
;
3400 r
->out
.new_val
->buf
->size
= crypt_secret
.length
;
3401 r
->out
.new_val
->buf
->data
= crypt_secret
.data
;
3405 if (r
->in
.new_mtime
) {
3406 r
->out
.new_mtime
= talloc(mem_ctx
, NTTIME
);
3407 if (!r
->out
.new_mtime
) {
3408 return NT_STATUS_NO_MEMORY
;
3410 *r
->out
.new_mtime
= ldb_msg_find_attr_as_uint64(res
[0], "lastSetTime", 0);
3413 return NT_STATUS_OK
;
3420 static NTSTATUS
dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state
*dce_call
,
3421 TALLOC_CTX
*mem_ctx
,
3422 struct lsa_LookupPrivValue
*r
)
3424 struct dcesrv_handle
*h
;
3427 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3429 id
= sec_privilege_id(r
->in
.name
->string
);
3430 if (id
== SEC_PRIV_INVALID
) {
3431 return NT_STATUS_NO_SUCH_PRIVILEGE
;
3434 r
->out
.luid
->low
= id
;
3435 r
->out
.luid
->high
= 0;
3437 return NT_STATUS_OK
;
3444 static NTSTATUS
dcesrv_lsa_LookupPrivName(struct dcesrv_call_state
*dce_call
,
3445 TALLOC_CTX
*mem_ctx
,
3446 struct lsa_LookupPrivName
*r
)
3448 struct dcesrv_handle
*h
;
3449 struct lsa_StringLarge
*name
;
3450 const char *privname
;
3452 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3454 if (r
->in
.luid
->high
!= 0) {
3455 return NT_STATUS_NO_SUCH_PRIVILEGE
;
3458 privname
= sec_privilege_name(r
->in
.luid
->low
);
3459 if (privname
== NULL
) {
3460 return NT_STATUS_NO_SUCH_PRIVILEGE
;
3463 name
= talloc(mem_ctx
, struct lsa_StringLarge
);
3465 return NT_STATUS_NO_MEMORY
;
3468 name
->string
= privname
;
3470 *r
->out
.name
= name
;
3472 return NT_STATUS_OK
;
3477 lsa_LookupPrivDisplayName
3479 static NTSTATUS
dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state
*dce_call
,
3480 TALLOC_CTX
*mem_ctx
,
3481 struct lsa_LookupPrivDisplayName
*r
)
3483 struct dcesrv_handle
*h
;
3484 struct lsa_StringLarge
*disp_name
= NULL
;
3485 enum sec_privilege id
;
3487 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3489 id
= sec_privilege_id(r
->in
.name
->string
);
3490 if (id
== SEC_PRIV_INVALID
) {
3491 return NT_STATUS_NO_SUCH_PRIVILEGE
;
3494 disp_name
= talloc(mem_ctx
, struct lsa_StringLarge
);
3495 if (disp_name
== NULL
) {
3496 return NT_STATUS_NO_MEMORY
;
3499 disp_name
->string
= sec_privilege_display_name(id
, &r
->in
.language_id
);
3500 if (disp_name
->string
== NULL
) {
3501 return NT_STATUS_INTERNAL_ERROR
;
3504 *r
->out
.disp_name
= disp_name
;
3505 *r
->out
.returned_language_id
= 0;
3507 return NT_STATUS_OK
;
3512 lsa_EnumAccountsWithUserRight
3514 static NTSTATUS
dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state
*dce_call
,
3515 TALLOC_CTX
*mem_ctx
,
3516 struct lsa_EnumAccountsWithUserRight
*r
)
3518 struct dcesrv_handle
*h
;
3519 struct lsa_policy_state
*state
;
3521 struct ldb_message
**res
;
3522 const char * const attrs
[] = { "objectSid", NULL
};
3523 const char *privname
;
3525 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3529 if (r
->in
.name
== NULL
) {
3530 return NT_STATUS_NO_SUCH_PRIVILEGE
;
3533 privname
= r
->in
.name
->string
;
3534 if (sec_privilege_id(privname
) == SEC_PRIV_INVALID
&& sec_right_bit(privname
) == 0) {
3535 return NT_STATUS_NO_SUCH_PRIVILEGE
;
3538 ret
= gendb_search(state
->pdb
, mem_ctx
, NULL
, &res
, attrs
,
3539 "privilege=%s", privname
);
3541 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
3544 return NT_STATUS_NO_MORE_ENTRIES
;
3547 r
->out
.sids
->sids
= talloc_array(r
->out
.sids
, struct lsa_SidPtr
, ret
);
3548 if (r
->out
.sids
->sids
== NULL
) {
3549 return NT_STATUS_NO_MEMORY
;
3551 for (i
=0;i
<ret
;i
++) {
3552 r
->out
.sids
->sids
[i
].sid
= samdb_result_dom_sid(r
->out
.sids
->sids
,
3553 res
[i
], "objectSid");
3554 NT_STATUS_HAVE_NO_MEMORY(r
->out
.sids
->sids
[i
].sid
);
3556 r
->out
.sids
->num_sids
= ret
;
3558 return NT_STATUS_OK
;
3563 lsa_AddAccountRights
3565 static NTSTATUS
dcesrv_lsa_AddAccountRights(struct dcesrv_call_state
*dce_call
,
3566 TALLOC_CTX
*mem_ctx
,
3567 struct lsa_AddAccountRights
*r
)
3569 struct dcesrv_handle
*h
;
3570 struct lsa_policy_state
*state
;
3572 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3576 return dcesrv_lsa_AddRemoveAccountRights(dce_call
, mem_ctx
, state
,
3578 r
->in
.sid
, r
->in
.rights
);
3583 lsa_RemoveAccountRights
3585 static NTSTATUS
dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state
*dce_call
,
3586 TALLOC_CTX
*mem_ctx
,
3587 struct lsa_RemoveAccountRights
*r
)
3589 struct dcesrv_handle
*h
;
3590 struct lsa_policy_state
*state
;
3592 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
3596 return dcesrv_lsa_AddRemoveAccountRights(dce_call
, mem_ctx
, state
,
3597 LDB_FLAG_MOD_DELETE
,
3598 r
->in
.sid
, r
->in
.rights
);
3603 lsa_StorePrivateData
3605 static NTSTATUS
dcesrv_lsa_StorePrivateData(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3606 struct lsa_StorePrivateData
*r
)
3608 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3613 lsa_RetrievePrivateData
3615 static NTSTATUS
dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3616 struct lsa_RetrievePrivateData
*r
)
3618 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3625 static NTSTATUS
dcesrv_lsa_GetUserName(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3626 struct lsa_GetUserName
*r
)
3628 enum dcerpc_transport_t transport
= dce_call
->conn
->endpoint
->ep_description
->transport
;
3629 NTSTATUS status
= NT_STATUS_OK
;
3630 const char *account_name
;
3631 const char *authority_name
;
3632 struct lsa_String
*_account_name
;
3633 struct lsa_String
*_authority_name
= NULL
;
3635 if (transport
!= NCACN_NP
&& transport
!= NCALRPC
) {
3636 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED
);
3639 /* this is what w2k3 does */
3640 r
->out
.account_name
= r
->in
.account_name
;
3641 r
->out
.authority_name
= r
->in
.authority_name
;
3643 if (r
->in
.account_name
3644 && *r
->in
.account_name
3645 /* && *(*r->in.account_name)->string */
3647 return NT_STATUS_INVALID_PARAMETER
;
3650 if (r
->in
.authority_name
3651 && *r
->in
.authority_name
3652 /* && *(*r->in.authority_name)->string */
3654 return NT_STATUS_INVALID_PARAMETER
;
3657 account_name
= talloc_reference(mem_ctx
, dce_call
->conn
->auth_state
.session_info
->info
->account_name
);
3658 authority_name
= talloc_reference(mem_ctx
, dce_call
->conn
->auth_state
.session_info
->info
->domain_name
);
3660 _account_name
= talloc(mem_ctx
, struct lsa_String
);
3661 NT_STATUS_HAVE_NO_MEMORY(_account_name
);
3662 _account_name
->string
= account_name
;
3664 if (r
->in
.authority_name
) {
3665 _authority_name
= talloc(mem_ctx
, struct lsa_String
);
3666 NT_STATUS_HAVE_NO_MEMORY(_authority_name
);
3667 _authority_name
->string
= authority_name
;
3670 *r
->out
.account_name
= _account_name
;
3671 if (r
->out
.authority_name
) {
3672 *r
->out
.authority_name
= _authority_name
;
3681 static NTSTATUS
dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state
*dce_call
,
3682 TALLOC_CTX
*mem_ctx
,
3683 struct lsa_SetInfoPolicy2
*r
)
3685 /* need to support these */
3686 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3689 static void kdc_get_policy(struct loadparm_context
*lp_ctx
,
3690 struct smb_krb5_context
*smb_krb5_context
,
3691 struct lsa_DomainInfoKerberos
*k
)
3693 time_t svc_tkt_lifetime
;
3694 time_t usr_tkt_lifetime
;
3695 time_t renewal_lifetime
;
3697 /* These should be set and stored via Group Policy, but until then, some defaults are in order */
3699 /* Our KDC always re-validates the client */
3700 k
->authentication_options
= LSA_POLICY_KERBEROS_VALIDATE_CLIENT
;
3702 lpcfg_default_kdc_policy(lp_ctx
, &svc_tkt_lifetime
,
3703 &usr_tkt_lifetime
, &renewal_lifetime
);
3705 unix_to_nt_time(&k
->service_tkt_lifetime
, svc_tkt_lifetime
);
3706 unix_to_nt_time(&k
->user_tkt_lifetime
, usr_tkt_lifetime
);
3707 unix_to_nt_time(&k
->user_tkt_renewaltime
, renewal_lifetime
);
3708 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
3709 However in the parent function we basically just did a full
3710 krb5_context init with the only purpose of getting a global
3711 config option (the max skew), it would probably make more sense
3712 to have a lp_ or ldb global option as the samba default */
3713 if (smb_krb5_context
) {
3714 unix_to_nt_time(&k
->clock_skew
,
3715 krb5_get_max_time_skew(smb_krb5_context
->krb5_context
));
3721 lsa_QueryDomainInformationPolicy
3723 static NTSTATUS
dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state
*dce_call
,
3724 TALLOC_CTX
*mem_ctx
,
3725 struct lsa_QueryDomainInformationPolicy
*r
)
3727 union lsa_DomainInformationPolicy
*info
;
3729 info
= talloc_zero(r
->out
.info
, union lsa_DomainInformationPolicy
);
3731 return NT_STATUS_NO_MEMORY
;
3734 switch (r
->in
.level
) {
3735 case LSA_DOMAIN_INFO_POLICY_EFS
:
3737 *r
->out
.info
= NULL
;
3738 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3739 case LSA_DOMAIN_INFO_POLICY_KERBEROS
:
3741 struct lsa_DomainInfoKerberos
*k
= &info
->kerberos_info
;
3742 struct smb_krb5_context
*smb_krb5_context
;
3743 int ret
= smb_krb5_init_context(mem_ctx
,
3744 dce_call
->event_ctx
,
3745 dce_call
->conn
->dce_ctx
->lp_ctx
,
3749 *r
->out
.info
= NULL
;
3750 return NT_STATUS_INTERNAL_ERROR
;
3752 kdc_get_policy(dce_call
->conn
->dce_ctx
->lp_ctx
,
3755 talloc_free(smb_krb5_context
);
3756 *r
->out
.info
= info
;
3757 return NT_STATUS_OK
;
3761 *r
->out
.info
= NULL
;
3762 return NT_STATUS_INVALID_INFO_CLASS
;
3767 lsa_SetDomInfoPolicy
3769 static NTSTATUS
dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state
*dce_call
,
3770 TALLOC_CTX
*mem_ctx
,
3771 struct lsa_SetDomainInformationPolicy
*r
)
3773 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3779 static NTSTATUS
dcesrv_lsa_TestCall(struct dcesrv_call_state
*dce_call
,
3780 TALLOC_CTX
*mem_ctx
,
3781 struct lsa_TestCall
*r
)
3783 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3789 static NTSTATUS
dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3790 struct lsa_CREDRWRITE
*r
)
3792 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3799 static NTSTATUS
dcesrv_lsa_CREDRREAD(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3800 struct lsa_CREDRREAD
*r
)
3802 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3809 static NTSTATUS
dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3810 struct lsa_CREDRENUMERATE
*r
)
3812 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3817 lsa_CREDRWRITEDOMAINCREDENTIALS
3819 static NTSTATUS
dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3820 struct lsa_CREDRWRITEDOMAINCREDENTIALS
*r
)
3822 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3827 lsa_CREDRREADDOMAINCREDENTIALS
3829 static NTSTATUS
dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3830 struct lsa_CREDRREADDOMAINCREDENTIALS
*r
)
3832 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3839 static NTSTATUS
dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3840 struct lsa_CREDRDELETE
*r
)
3842 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3847 lsa_CREDRGETTARGETINFO
3849 static NTSTATUS
dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3850 struct lsa_CREDRGETTARGETINFO
*r
)
3852 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3857 lsa_CREDRPROFILELOADED
3859 static NTSTATUS
dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3860 struct lsa_CREDRPROFILELOADED
*r
)
3862 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3867 lsa_CREDRGETSESSIONTYPES
3869 static NTSTATUS
dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3870 struct lsa_CREDRGETSESSIONTYPES
*r
)
3872 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3877 lsa_LSARREGISTERAUDITEVENT
3879 static NTSTATUS
dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3880 struct lsa_LSARREGISTERAUDITEVENT
*r
)
3882 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3887 lsa_LSARGENAUDITEVENT
3889 static NTSTATUS
dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3890 struct lsa_LSARGENAUDITEVENT
*r
)
3892 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3897 lsa_LSARUNREGISTERAUDITEVENT
3899 static NTSTATUS
dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3900 struct lsa_LSARUNREGISTERAUDITEVENT
*r
)
3902 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3907 lsa_lsaRQueryForestTrustInformation
3909 static NTSTATUS
dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
3910 struct lsa_lsaRQueryForestTrustInformation
*r
)
3912 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
3915 #define DNS_CMP_MATCH 0
3916 #define DNS_CMP_FIRST_IS_CHILD 1
3917 #define DNS_CMP_SECOND_IS_CHILD 2
3918 #define DNS_CMP_NO_MATCH 3
3920 /* this function assumes names are well formed DNS names.
3921 * it doesn't validate them */
3922 static int dns_cmp(const char *s1
, size_t l1
,
3923 const char *s2
, size_t l2
)
3925 const char *p1
, *p2
;
3930 if (strcasecmp_m(s1
, s2
) == 0) {
3931 return DNS_CMP_MATCH
;
3933 return DNS_CMP_NO_MATCH
;
3941 cret
= DNS_CMP_FIRST_IS_CHILD
;
3947 cret
= DNS_CMP_SECOND_IS_CHILD
;
3950 if (p1
[t1
- t2
- 1] != '.') {
3951 return DNS_CMP_NO_MATCH
;
3954 if (strcasecmp_m(&p1
[t1
- t2
], p2
) == 0) {
3958 return DNS_CMP_NO_MATCH
;
3961 /* decode all TDOs forest trust info blobs */
3962 static NTSTATUS
get_ft_info(TALLOC_CTX
*mem_ctx
,
3963 struct ldb_message
*msg
,
3964 struct ForestTrustInfo
*info
)
3966 const struct ldb_val
*ft_blob
;
3967 enum ndr_err_code ndr_err
;
3969 ft_blob
= ldb_msg_find_ldb_val(msg
, "msDS-TrustForestTrustInfo");
3970 if (!ft_blob
|| !ft_blob
->data
) {
3971 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3973 /* ldb_val is equivalent to DATA_BLOB */
3974 ndr_err
= ndr_pull_struct_blob_all(ft_blob
, mem_ctx
, info
,
3975 (ndr_pull_flags_fn_t
)ndr_pull_ForestTrustInfo
);
3976 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
3977 return NT_STATUS_INVALID_DOMAIN_STATE
;
3980 return NT_STATUS_OK
;
3983 static NTSTATUS
own_ft_info(struct lsa_policy_state
*ps
,
3984 struct ForestTrustInfo
*fti
)
3986 struct ForestTrustDataDomainInfo
*info
;
3987 struct ForestTrustInfoRecord
*rec
;
3991 fti
->records
= talloc_array(fti
,
3992 struct ForestTrustInfoRecordArmor
, 2);
3993 if (!fti
->records
) {
3994 return NT_STATUS_NO_MEMORY
;
3998 rec
= &fti
->records
[0].record
;
4002 rec
->type
= LSA_FOREST_TRUST_TOP_LEVEL_NAME
;
4004 rec
->data
.name
.string
= talloc_strdup(fti
, ps
->forest_dns
);
4005 if (!rec
->data
.name
.string
) {
4006 return NT_STATUS_NO_MEMORY
;
4008 rec
->data
.name
.size
= strlen(rec
->data
.name
.string
);
4011 rec
= &fti
->records
[1].record
;
4015 rec
->type
= LSA_FOREST_TRUST_DOMAIN_INFO
;
4017 info
= &rec
->data
.info
;
4019 info
->sid
= *ps
->domain_sid
;
4020 info
->dns_name
.string
= talloc_strdup(fti
, ps
->domain_dns
);
4021 if (!info
->dns_name
.string
) {
4022 return NT_STATUS_NO_MEMORY
;
4024 info
->dns_name
.size
= strlen(info
->dns_name
.string
);
4025 info
->netbios_name
.string
= talloc_strdup(fti
, ps
->domain_name
);
4026 if (!info
->netbios_name
.string
) {
4027 return NT_STATUS_NO_MEMORY
;
4029 info
->netbios_name
.size
= strlen(info
->netbios_name
.string
);
4031 return NT_STATUS_OK
;
4034 static NTSTATUS
make_ft_info(TALLOC_CTX
*mem_ctx
,
4035 struct lsa_ForestTrustInformation
*lfti
,
4036 struct ForestTrustInfo
*fti
)
4038 struct lsa_ForestTrustRecord
*lrec
;
4039 struct ForestTrustInfoRecord
*rec
;
4040 struct lsa_StringLarge
*tln
;
4041 struct lsa_ForestTrustDomainInfo
*info
;
4045 fti
->count
= lfti
->count
;
4046 fti
->records
= talloc_array(mem_ctx
,
4047 struct ForestTrustInfoRecordArmor
,
4049 if (!fti
->records
) {
4050 return NT_STATUS_NO_MEMORY
;
4052 for (i
= 0; i
< fti
->count
; i
++) {
4053 lrec
= lfti
->entries
[i
];
4054 rec
= &fti
->records
[i
].record
;
4056 rec
->flags
= lrec
->flags
;
4057 rec
->timestamp
= lrec
->time
;
4058 rec
->type
= lrec
->type
;
4060 switch (lrec
->type
) {
4061 case LSA_FOREST_TRUST_TOP_LEVEL_NAME
:
4062 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
:
4063 tln
= &lrec
->forest_trust_data
.top_level_name
;
4064 rec
->data
.name
.string
=
4065 talloc_strdup(mem_ctx
, tln
->string
);
4066 if (!rec
->data
.name
.string
) {
4067 return NT_STATUS_NO_MEMORY
;
4069 rec
->data
.name
.size
= strlen(rec
->data
.name
.string
);
4071 case LSA_FOREST_TRUST_DOMAIN_INFO
:
4072 info
= &lrec
->forest_trust_data
.domain_info
;
4073 rec
->data
.info
.sid
= *info
->domain_sid
;
4074 rec
->data
.info
.dns_name
.string
=
4075 talloc_strdup(mem_ctx
,
4076 info
->dns_domain_name
.string
);
4077 if (!rec
->data
.info
.dns_name
.string
) {
4078 return NT_STATUS_NO_MEMORY
;
4080 rec
->data
.info
.dns_name
.size
=
4081 strlen(rec
->data
.info
.dns_name
.string
);
4082 rec
->data
.info
.netbios_name
.string
=
4083 talloc_strdup(mem_ctx
,
4084 info
->netbios_domain_name
.string
);
4085 if (!rec
->data
.info
.netbios_name
.string
) {
4086 return NT_STATUS_NO_MEMORY
;
4088 rec
->data
.info
.netbios_name
.size
=
4089 strlen(rec
->data
.info
.netbios_name
.string
);
4092 return NT_STATUS_INVALID_DOMAIN_STATE
;
4096 return NT_STATUS_OK
;
4099 static NTSTATUS
add_collision(struct lsa_ForestTrustCollisionInfo
*c_info
,
4100 uint32_t idx
, uint32_t collision_type
,
4101 uint32_t conflict_type
, const char *tdo_name
);
4103 static NTSTATUS
check_ft_info(TALLOC_CTX
*mem_ctx
,
4104 const char *tdo_name
,
4105 struct ForestTrustInfo
*tdo_fti
,
4106 struct ForestTrustInfo
*new_fti
,
4107 struct lsa_ForestTrustCollisionInfo
*c_info
)
4109 struct ForestTrustInfoRecord
*nrec
;
4110 struct ForestTrustInfoRecord
*trec
;
4111 const char *dns_name
;
4112 const char *nb_name
;
4113 struct dom_sid
*sid
;
4118 uint32_t new_fti_idx
;
4120 /* use always TDO type, until we understand when Xref can be used */
4121 uint32_t collision_type
= LSA_FOREST_TRUST_COLLISION_TDO
;
4129 for (new_fti_idx
= 0; new_fti_idx
< new_fti
->count
; new_fti_idx
++) {
4131 nrec
= &new_fti
->records
[new_fti_idx
].record
;
4133 tln_conflict
= false;
4134 sid_conflict
= false;
4135 nb_conflict
= false;
4138 switch (nrec
->type
) {
4139 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
:
4140 /* exclusions do not conflict by definition */
4143 case FOREST_TRUST_TOP_LEVEL_NAME
:
4144 dns_name
= nrec
->data
.name
.string
;
4145 dns_len
= nrec
->data
.name
.size
;
4148 case LSA_FOREST_TRUST_DOMAIN_INFO
:
4149 dns_name
= nrec
->data
.info
.dns_name
.string
;
4150 dns_len
= nrec
->data
.info
.dns_name
.size
;
4151 nb_name
= nrec
->data
.info
.netbios_name
.string
;
4152 sid
= &nrec
->data
.info
.sid
;
4156 if (!dns_name
) continue;
4158 /* check if this is already taken and not excluded */
4159 for (i
= 0; i
< tdo_fti
->count
; i
++) {
4160 trec
= &tdo_fti
->records
[i
].record
;
4162 switch (trec
->type
) {
4163 case FOREST_TRUST_TOP_LEVEL_NAME
:
4165 tname
= trec
->data
.name
.string
;
4166 tlen
= trec
->data
.name
.size
;
4168 case FOREST_TRUST_TOP_LEVEL_NAME_EX
:
4170 tname
= trec
->data
.name
.string
;
4171 tlen
= trec
->data
.name
.size
;
4173 case FOREST_TRUST_DOMAIN_INFO
:
4175 tname
= trec
->data
.info
.dns_name
.string
;
4176 tlen
= trec
->data
.info
.dns_name
.size
;
4178 ret
= dns_cmp(dns_name
, dns_len
, tname
, tlen
);
4181 /* if it matches exclusion,
4182 * it doesn't conflict */
4188 case DNS_CMP_FIRST_IS_CHILD
:
4189 case DNS_CMP_SECOND_IS_CHILD
:
4190 tln_conflict
= true;
4196 /* explicit exclusion, no dns name conflict here */
4198 tln_conflict
= false;
4201 if (trec
->type
!= FOREST_TRUST_DOMAIN_INFO
) {
4205 /* also test for domain info */
4206 if (!(trec
->flags
& LSA_SID_DISABLED_ADMIN
) &&
4207 dom_sid_compare(&trec
->data
.info
.sid
, sid
) == 0) {
4208 sid_conflict
= true;
4210 if (!(trec
->flags
& LSA_NB_DISABLED_ADMIN
) &&
4211 strcasecmp_m(trec
->data
.info
.netbios_name
.string
,
4218 nt_status
= add_collision(c_info
, new_fti_idx
,
4220 LSA_TLN_DISABLED_CONFLICT
,
4224 nt_status
= add_collision(c_info
, new_fti_idx
,
4226 LSA_SID_DISABLED_CONFLICT
,
4230 nt_status
= add_collision(c_info
, new_fti_idx
,
4232 LSA_NB_DISABLED_CONFLICT
,
4237 return NT_STATUS_OK
;
4240 static NTSTATUS
add_collision(struct lsa_ForestTrustCollisionInfo
*c_info
,
4241 uint32_t idx
, uint32_t collision_type
,
4242 uint32_t conflict_type
, const char *tdo_name
)
4244 struct lsa_ForestTrustCollisionRecord
**es
;
4245 uint32_t i
= c_info
->count
;
4247 es
= talloc_realloc(c_info
, c_info
->entries
,
4248 struct lsa_ForestTrustCollisionRecord
*, i
+ 1);
4250 return NT_STATUS_NO_MEMORY
;
4252 c_info
->entries
= es
;
4253 c_info
->count
= i
+ 1;
4255 es
[i
] = talloc(es
, struct lsa_ForestTrustCollisionRecord
);
4257 return NT_STATUS_NO_MEMORY
;
4261 es
[i
]->type
= collision_type
;
4262 es
[i
]->flags
.flags
= conflict_type
;
4263 es
[i
]->name
.string
= talloc_strdup(es
[i
], tdo_name
);
4264 if (!es
[i
]->name
.string
) {
4265 return NT_STATUS_NO_MEMORY
;
4267 es
[i
]->name
.size
= strlen(es
[i
]->name
.string
);
4269 return NT_STATUS_OK
;
4273 lsa_lsaRSetForestTrustInformation
4275 static NTSTATUS
dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state
*dce_call
,
4276 TALLOC_CTX
*mem_ctx
,
4277 struct lsa_lsaRSetForestTrustInformation
*r
)
4279 struct dcesrv_handle
*h
;
4280 struct lsa_policy_state
*p_state
;
4281 const char *trust_attrs
[] = { "trustPartner", "trustAttributes",
4282 "msDS-TrustForestTrustInfo", NULL
};
4283 struct ldb_message
**dom_res
= NULL
;
4284 struct ldb_dn
*tdo_dn
;
4285 struct ldb_message
*msg
;
4287 const char *td_name
;
4288 uint32_t trust_attributes
;
4289 struct lsa_ForestTrustCollisionInfo
*c_info
;
4290 struct ForestTrustInfo
*nfti
;
4291 struct ForestTrustInfo
*fti
;
4293 enum ndr_err_code ndr_err
;
4298 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
4302 if (strcmp(p_state
->domain_dns
, p_state
->forest_dns
)) {
4303 return NT_STATUS_INVALID_DOMAIN_STATE
;
4306 /* abort if we are not a PDC */
4307 if (!samdb_is_pdc(p_state
->sam_ldb
)) {
4308 return NT_STATUS_INVALID_DOMAIN_ROLE
;
4311 ret
= samdb_rodc(p_state
->sam_ldb
, &am_rodc
);
4312 if (ret
== LDB_SUCCESS
&& am_rodc
) {
4313 return NT_STATUS_NO_SUCH_DOMAIN
;
4316 /* check caller has TRUSTED_SET_AUTH */
4318 /* fetch all trusted domain objects */
4319 num_res
= gendb_search(p_state
->sam_ldb
, mem_ctx
,
4321 &dom_res
, trust_attrs
,
4322 "(objectclass=trustedDomain)");
4324 return NT_STATUS_NO_SUCH_DOMAIN
;
4327 for (i
= 0; i
< num_res
; i
++) {
4328 td_name
= ldb_msg_find_attr_as_string(dom_res
[i
],
4329 "trustPartner", NULL
);
4331 return NT_STATUS_INVALID_DOMAIN_STATE
;
4333 if (strcasecmp_m(td_name
,
4334 r
->in
.trusted_domain_name
->string
) == 0) {
4339 return NT_STATUS_NO_SUCH_DOMAIN
;
4342 tdo_dn
= dom_res
[i
]->dn
;
4344 trust_attributes
= ldb_msg_find_attr_as_uint(dom_res
[i
],
4345 "trustAttributes", 0);
4346 if (!(trust_attributes
& NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
)) {
4347 return NT_STATUS_INVALID_PARAMETER
;
4350 if (r
->in
.highest_record_type
>= LSA_FOREST_TRUST_RECORD_TYPE_LAST
) {
4351 return NT_STATUS_INVALID_PARAMETER
;
4354 nfti
= talloc(mem_ctx
, struct ForestTrustInfo
);
4356 return NT_STATUS_NO_MEMORY
;
4359 nt_status
= make_ft_info(nfti
, r
->in
.forest_trust_info
, nfti
);
4360 if (!NT_STATUS_IS_OK(nt_status
)) {
4364 c_info
= talloc_zero(r
->out
.collision_info
,
4365 struct lsa_ForestTrustCollisionInfo
);
4367 return NT_STATUS_NO_MEMORY
;
4370 /* first check own info, then other domains */
4371 fti
= talloc(mem_ctx
, struct ForestTrustInfo
);
4373 return NT_STATUS_NO_MEMORY
;
4376 nt_status
= own_ft_info(p_state
, fti
);
4377 if (!NT_STATUS_IS_OK(nt_status
)) {
4381 nt_status
= check_ft_info(c_info
, p_state
->domain_dns
,
4383 if (!NT_STATUS_IS_OK(nt_status
)) {
4387 for (i
= 0; i
< num_res
; i
++) {
4388 fti
= talloc(mem_ctx
, struct ForestTrustInfo
);
4390 return NT_STATUS_NO_MEMORY
;
4393 nt_status
= get_ft_info(mem_ctx
, dom_res
[i
], fti
);
4394 if (!NT_STATUS_IS_OK(nt_status
)) {
4395 if (NT_STATUS_EQUAL(nt_status
,
4396 NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
4402 td_name
= ldb_msg_find_attr_as_string(dom_res
[i
],
4403 "trustPartner", NULL
);
4405 return NT_STATUS_INVALID_DOMAIN_STATE
;
4408 nt_status
= check_ft_info(c_info
, td_name
, fti
, nfti
, c_info
);
4409 if (!NT_STATUS_IS_OK(nt_status
)) {
4414 *r
->out
.collision_info
= c_info
;
4416 if (r
->in
.check_only
!= 0) {
4417 return NT_STATUS_OK
;
4420 /* not just a check, write info back */
4422 ndr_err
= ndr_push_struct_blob(&ft_blob
, mem_ctx
, nfti
,
4423 (ndr_push_flags_fn_t
)ndr_push_ForestTrustInfo
);
4424 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
4425 return NT_STATUS_INVALID_PARAMETER
;
4428 msg
= ldb_msg_new(mem_ctx
);
4430 return NT_STATUS_NO_MEMORY
;
4433 msg
->dn
= ldb_dn_copy(mem_ctx
, tdo_dn
);
4435 return NT_STATUS_NO_MEMORY
;
4438 ret
= ldb_msg_add_empty(msg
, "msDS-TrustForestTrustInfo",
4439 LDB_FLAG_MOD_REPLACE
, NULL
);
4440 if (ret
!= LDB_SUCCESS
) {
4441 return NT_STATUS_NO_MEMORY
;
4443 ret
= ldb_msg_add_value(msg
, "msDS-TrustForestTrustInfo",
4445 if (ret
!= LDB_SUCCESS
) {
4446 return NT_STATUS_NO_MEMORY
;
4449 ret
= ldb_modify(p_state
->sam_ldb
, msg
);
4450 if (ret
!= LDB_SUCCESS
) {
4451 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4452 ldb_errstring(p_state
->sam_ldb
)));
4455 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
:
4456 return NT_STATUS_ACCESS_DENIED
;
4458 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
4462 return NT_STATUS_OK
;
4468 static NTSTATUS
dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4469 struct lsa_CREDRRENAME
*r
)
4471 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4477 lsa_LSAROPENPOLICYSCE
4479 static NTSTATUS
dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4480 struct lsa_LSAROPENPOLICYSCE
*r
)
4482 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4487 lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4489 static NTSTATUS
dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4490 struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE
*r
)
4492 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4497 lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4499 static NTSTATUS
dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4500 struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
*r
)
4502 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4507 lsa_LSARADTREPORTSECURITYEVENT
4509 static NTSTATUS
dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4510 struct lsa_LSARADTREPORTSECURITYEVENT
*r
)
4512 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4516 /* include the generated boilerplate */
4517 #include "librpc/gen_ndr/ndr_lsa_s.c"
4521 /*****************************************
4522 NOTE! The remaining calls below were
4523 removed in w2k3, so the DCESRV_FAULT()
4524 replies are the correct implementation. Do
4525 not try and fill these in with anything else
4526 ******************************************/
4529 dssetup_DsRoleDnsNameToFlatName
4531 static WERROR
dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4532 struct dssetup_DsRoleDnsNameToFlatName
*r
)
4534 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4539 dssetup_DsRoleDcAsDc
4541 static WERROR
dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4542 struct dssetup_DsRoleDcAsDc
*r
)
4544 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4549 dssetup_DsRoleDcAsReplica
4551 static WERROR
dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4552 struct dssetup_DsRoleDcAsReplica
*r
)
4554 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4559 dssetup_DsRoleDemoteDc
4561 static WERROR
dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4562 struct dssetup_DsRoleDemoteDc
*r
)
4564 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4569 dssetup_DsRoleGetDcOperationProgress
4571 static WERROR
dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4572 struct dssetup_DsRoleGetDcOperationProgress
*r
)
4574 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4579 dssetup_DsRoleGetDcOperationResults
4581 static WERROR
dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4582 struct dssetup_DsRoleGetDcOperationResults
*r
)
4584 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4589 dssetup_DsRoleCancel
4591 static WERROR
dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4592 struct dssetup_DsRoleCancel
*r
)
4594 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4599 dssetup_DsRoleServerSaveStateForUpgrade
4601 static WERROR
dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4602 struct dssetup_DsRoleServerSaveStateForUpgrade
*r
)
4604 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4609 dssetup_DsRoleUpgradeDownlevelServer
4611 static WERROR
dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4612 struct dssetup_DsRoleUpgradeDownlevelServer
*r
)
4614 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4619 dssetup_DsRoleAbortDownlevelServerUpgrade
4621 static WERROR
dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
4622 struct dssetup_DsRoleAbortDownlevelServerUpgrade
*r
)
4624 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
4628 /* include the generated boilerplate */
4629 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4631 NTSTATUS
dcerpc_server_lsa_init(void)
4635 ret
= dcerpc_server_dssetup_init();
4636 if (!NT_STATUS_IS_OK(ret
)) {
4639 ret
= dcerpc_server_lsarpc_init();
4640 if (!NT_STATUS_IS_OK(ret
)) {