2 Unix SMB/CIFS implementation.
4 In-Child server implementation of the routines defined in wbint.idl
6 Copyright (C) Volker Lendecke 2009
7 Copyright (C) Guenther Deschner 2009
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "winbindd/winbindd.h"
25 #include "winbindd/winbindd_proto.h"
26 #include "rpc_client/cli_pipe.h"
28 #include "librpc/rpc/dcesrv_core.h"
29 #include "librpc/gen_ndr/ndr_winbind.h"
30 #include "librpc/gen_ndr/ndr_winbind_scompat.h"
31 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
32 #include "../librpc/gen_ndr/ndr_lsa_c.h"
34 #include "../libcli/security/security.h"
35 #include "../libcli/auth/netlogon_creds_cli.h"
37 #include "../source4/dsdb/samdb/samdb.h"
38 #include "rpc_client/cli_netlogon.h"
39 #include "rpc_client/util_netlogon.h"
40 #include "libsmb/dsgetdcname.h"
41 #include "lib/global_contexts.h"
43 NTSTATUS
_wbint_Ping(struct pipes_struct
*p
, struct wbint_Ping
*r
)
45 *r
->out
.out_data
= r
->in
.in_data
;
49 bool reset_cm_connection_on_error(struct winbindd_domain
*domain
,
50 struct dcerpc_binding_handle
*b
,
53 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
) ||
54 NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
) ||
55 NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_ACCESS_DENIED
)) {
56 invalidate_cm_connection(domain
);
57 domain
->conn
.netlogon_force_reauth
= true;
61 if (NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
) ||
62 NT_STATUS_EQUAL(status
, NT_STATUS_IO_DEVICE_ERROR
))
64 invalidate_cm_connection(domain
);
65 /* We invalidated the connection. */
69 if (b
!= NULL
&& !dcerpc_binding_handle_is_connected(b
)) {
70 invalidate_cm_connection(domain
);
77 NTSTATUS
_wbint_LookupSid(struct pipes_struct
*p
, struct wbint_LookupSid
*r
)
79 struct winbindd_domain
*domain
= wb_child_domain();
82 enum lsa_SidType type
;
86 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
89 status
= wb_cache_sid_to_name(domain
, p
->mem_ctx
, r
->in
.sid
,
90 &dom_name
, &name
, &type
);
91 reset_cm_connection_on_error(domain
, NULL
, status
);
92 if (!NT_STATUS_IS_OK(status
)) {
96 *r
->out
.domain
= dom_name
;
102 NTSTATUS
_wbint_LookupSids(struct pipes_struct
*p
, struct wbint_LookupSids
*r
)
104 struct winbindd_domain
*domain
= wb_child_domain();
105 struct lsa_RefDomainList
*domains
= r
->out
.domains
;
109 if (domain
== NULL
) {
110 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
114 * This breaks the winbindd_domain->methods abstraction: This
115 * is only called for remote domains, and both winbindd_msrpc
116 * and winbindd_ad call into lsa_lookupsids anyway. Caching is
117 * done at the wbint RPC layer.
120 status
= rpc_lookup_sids(p
->mem_ctx
, domain
, r
->in
.sids
,
121 &domains
, &r
->out
.names
);
123 if (domains
!= NULL
) {
124 r
->out
.domains
= domains
;
127 if (!retry
&& reset_cm_connection_on_error(domain
, NULL
, status
)) {
135 NTSTATUS
_wbint_LookupName(struct pipes_struct
*p
, struct wbint_LookupName
*r
)
137 struct winbindd_domain
*domain
= wb_child_domain();
140 if (domain
== NULL
) {
141 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
144 status
= wb_cache_name_to_sid(domain
, p
->mem_ctx
, r
->in
.domain
,
145 r
->in
.name
, r
->in
.flags
,
146 r
->out
.sid
, r
->out
.type
);
147 reset_cm_connection_on_error(domain
, NULL
, status
);
151 NTSTATUS
_wbint_Sids2UnixIDs(struct pipes_struct
*p
,
152 struct wbint_Sids2UnixIDs
*r
)
156 struct lsa_DomainInfo
*d
;
157 struct wbint_TransID
*ids
;
160 struct id_map
**id_map_ptrs
= NULL
;
161 struct idmap_domain
*dom
;
162 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
164 if (r
->in
.domains
->count
!= 1) {
165 return NT_STATUS_INVALID_PARAMETER
;
168 d
= &r
->in
.domains
->domains
[0];
169 ids
= r
->in
.ids
->ids
;
170 num_ids
= r
->in
.ids
->num_ids
;
172 dom
= idmap_find_domain_with_sid(d
->name
.string
, d
->sid
);
174 struct dom_sid_buf buf
;
175 DEBUG(10, ("idmap domain %s:%s not found\n",
177 dom_sid_str_buf(d
->sid
, &buf
)));
179 for (i
=0; i
<num_ids
; i
++) {
181 ids
[i
].xid
= (struct unixid
) {
183 .type
= ID_TYPE_NOT_SPECIFIED
190 id_map_ptrs
= id_map_ptrs_init(talloc_tos(), num_ids
);
191 if (id_map_ptrs
== NULL
) {
196 * Convert the input data into a list of id_map structs
197 * suitable for handing in to the idmap sids_to_unixids
201 for (i
=0; i
<num_ids
; i
++) {
202 struct id_map
*m
= id_map_ptrs
[i
];
204 sid_compose(m
->sid
, d
->sid
, ids
[i
].rid
);
205 m
->status
= ID_UNKNOWN
;
206 m
->xid
= (struct unixid
) { .type
= ids
[i
].type_hint
};
209 status
= dom
->methods
->sids_to_unixids(dom
, id_map_ptrs
);
211 if (NT_STATUS_EQUAL(status
, STATUS_SOME_UNMAPPED
)) {
213 * This is okay. We need to transfer the mapped ones
214 * up to our caller. The individual mappings carry the
215 * information whether they are mapped or not.
217 status
= NT_STATUS_OK
;
220 if (!NT_STATUS_IS_OK(status
)) {
221 DEBUG(10, ("sids_to_unixids returned %s\n",
227 * Extract the results for handing them back to the caller.
230 for (i
=0; i
<num_ids
; i
++) {
231 struct id_map
*m
= id_map_ptrs
[i
];
233 if (m
->status
== ID_REQUIRE_TYPE
) {
234 ids
[i
].xid
.id
= UINT32_MAX
;
235 ids
[i
].xid
.type
= ID_TYPE_WB_REQUIRE_TYPE
;
239 if (!idmap_unix_id_is_in_range(m
->xid
.id
, dom
)) {
240 DBG_DEBUG("id %"PRIu32
" is out of range "
241 "%"PRIu32
"-%"PRIu32
" for domain %s\n",
242 m
->xid
.id
, dom
->low_id
, dom
->high_id
,
244 m
->status
= ID_UNMAPPED
;
247 if (m
->status
== ID_MAPPED
) {
250 ids
[i
].xid
.id
= UINT32_MAX
;
251 ids
[i
].xid
.type
= ID_TYPE_NOT_SPECIFIED
;
257 status
= NT_STATUS_NO_MEMORY
;
259 TALLOC_FREE(id_map_ptrs
);
263 NTSTATUS
_wbint_UnixIDs2Sids(struct pipes_struct
*p
,
264 struct wbint_UnixIDs2Sids
*r
)
266 struct id_map
**maps
;
270 maps
= id_map_ptrs_init(talloc_tos(), r
->in
.num_ids
);
272 return NT_STATUS_NO_MEMORY
;
275 for (i
=0; i
<r
->in
.num_ids
; i
++) {
276 maps
[i
]->status
= ID_UNKNOWN
;
277 maps
[i
]->xid
= r
->in
.xids
[i
];
280 status
= idmap_backend_unixids_to_sids(maps
, r
->in
.domain_name
,
282 if (!NT_STATUS_IS_OK(status
)) {
287 for (i
=0; i
<r
->in
.num_ids
; i
++) {
288 if (maps
[i
]->status
== ID_MAPPED
) {
289 r
->out
.xids
[i
] = maps
[i
]->xid
;
290 sid_copy(&r
->out
.sids
[i
], maps
[i
]->sid
);
292 r
->out
.sids
[i
] = (struct dom_sid
) { 0 };
301 NTSTATUS
_wbint_AllocateUid(struct pipes_struct
*p
, struct wbint_AllocateUid
*r
)
306 status
= idmap_allocate_uid(&xid
);
307 if (!NT_STATUS_IS_OK(status
)) {
310 *r
->out
.uid
= xid
.id
;
314 NTSTATUS
_wbint_AllocateGid(struct pipes_struct
*p
, struct wbint_AllocateGid
*r
)
319 status
= idmap_allocate_gid(&xid
);
320 if (!NT_STATUS_IS_OK(status
)) {
323 *r
->out
.gid
= xid
.id
;
327 NTSTATUS
_wbint_GetNssInfo(struct pipes_struct
*p
, struct wbint_GetNssInfo
*r
)
329 struct idmap_domain
*domain
;
332 domain
= idmap_find_domain(r
->in
.info
->domain_name
);
333 if ((domain
== NULL
) || (domain
->query_user
== NULL
)) {
334 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
337 status
= domain
->query_user(domain
, r
->in
.info
);
341 NTSTATUS
_wbint_LookupUserAliases(struct pipes_struct
*p
,
342 struct wbint_LookupUserAliases
*r
)
344 struct winbindd_domain
*domain
= wb_child_domain();
347 if (domain
== NULL
) {
348 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
351 status
= wb_cache_lookup_useraliases(domain
, p
->mem_ctx
,
352 r
->in
.sids
->num_sids
,
354 &r
->out
.rids
->num_rids
,
356 reset_cm_connection_on_error(domain
, NULL
, status
);
360 NTSTATUS
_wbint_LookupUserGroups(struct pipes_struct
*p
,
361 struct wbint_LookupUserGroups
*r
)
363 struct winbindd_domain
*domain
= wb_child_domain();
366 if (domain
== NULL
) {
367 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
370 status
= wb_cache_lookup_usergroups(domain
, p
->mem_ctx
, r
->in
.sid
,
371 &r
->out
.sids
->num_sids
,
373 reset_cm_connection_on_error(domain
, NULL
, status
);
377 NTSTATUS
_wbint_QuerySequenceNumber(struct pipes_struct
*p
,
378 struct wbint_QuerySequenceNumber
*r
)
380 struct winbindd_domain
*domain
= wb_child_domain();
383 if (domain
== NULL
) {
384 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
387 status
= wb_cache_sequence_number(domain
, r
->out
.sequence
);
388 reset_cm_connection_on_error(domain
, NULL
, status
);
392 NTSTATUS
_wbint_LookupGroupMembers(struct pipes_struct
*p
,
393 struct wbint_LookupGroupMembers
*r
)
395 struct winbindd_domain
*domain
= wb_child_domain();
396 uint32_t i
, num_names
;
397 struct dom_sid
*sid_mem
;
399 uint32_t *name_types
;
402 if (domain
== NULL
) {
403 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
406 status
= wb_cache_lookup_groupmem(domain
, p
->mem_ctx
, r
->in
.sid
,
407 r
->in
.type
, &num_names
, &sid_mem
,
408 &names
, &name_types
);
409 reset_cm_connection_on_error(domain
, NULL
, status
);
410 if (!NT_STATUS_IS_OK(status
)) {
414 r
->out
.members
->num_principals
= num_names
;
415 r
->out
.members
->principals
= talloc_array(
416 r
->out
.members
, struct wbint_Principal
, num_names
);
417 if (r
->out
.members
->principals
== NULL
) {
418 return NT_STATUS_NO_MEMORY
;
421 for (i
=0; i
<num_names
; i
++) {
422 struct wbint_Principal
*m
= &r
->out
.members
->principals
[i
];
423 sid_copy(&m
->sid
, &sid_mem
[i
]);
424 m
->name
= talloc_move(r
->out
.members
->principals
, &names
[i
]);
425 m
->type
= (enum lsa_SidType
)name_types
[i
];
431 NTSTATUS
_wbint_QueryGroupList(struct pipes_struct
*p
,
432 struct wbint_QueryGroupList
*r
)
434 TALLOC_CTX
*frame
= NULL
;
435 struct winbindd_domain
*domain
= wb_child_domain();
437 uint32_t num_local_groups
= 0;
438 struct wb_acct_info
*local_groups
= NULL
;
439 uint32_t num_dom_groups
= 0;
440 struct wb_acct_info
*dom_groups
= NULL
;
442 uint64_t num_total
= 0;
443 struct wbint_Principal
*result
;
444 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
445 bool include_local_groups
= false;
447 if (domain
== NULL
) {
448 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
451 frame
= talloc_stackframe();
453 switch (lp_server_role()) {
454 case ROLE_ACTIVE_DIRECTORY_DC
:
455 if (domain
->internal
) {
457 * we want to include local groups
458 * for BUILTIN and WORKGROUP
460 include_local_groups
= true;
465 * We might include local groups in more
466 * setups later, but that requires more work
472 if (include_local_groups
) {
473 status
= wb_cache_enum_local_groups(domain
, frame
,
476 reset_cm_connection_on_error(domain
, NULL
, status
);
477 if (!NT_STATUS_IS_OK(status
)) {
482 status
= wb_cache_enum_dom_groups(domain
, frame
,
485 reset_cm_connection_on_error(domain
, NULL
, status
);
486 if (!NT_STATUS_IS_OK(status
)) {
490 num_total
= num_local_groups
+ num_dom_groups
;
491 if (num_total
> UINT32_MAX
) {
492 status
= NT_STATUS_INTERNAL_ERROR
;
496 result
= talloc_array(frame
, struct wbint_Principal
, num_total
);
497 if (result
== NULL
) {
498 status
= NT_STATUS_NO_MEMORY
;
502 for (i
= 0; i
< num_local_groups
; i
++) {
503 struct wb_acct_info
*lg
= &local_groups
[i
];
504 struct wbint_Principal
*rg
= &result
[ti
++];
506 sid_compose(&rg
->sid
, &domain
->sid
, lg
->rid
);
507 rg
->type
= SID_NAME_ALIAS
;
508 rg
->name
= talloc_strdup(result
, lg
->acct_name
);
509 if (rg
->name
== NULL
) {
510 status
= NT_STATUS_NO_MEMORY
;
514 num_local_groups
= 0;
516 for (i
= 0; i
< num_dom_groups
; i
++) {
517 struct wb_acct_info
*dg
= &dom_groups
[i
];
518 struct wbint_Principal
*rg
= &result
[ti
++];
520 sid_compose(&rg
->sid
, &domain
->sid
, dg
->rid
);
521 rg
->type
= SID_NAME_DOM_GRP
;
522 rg
->name
= talloc_strdup(result
, dg
->acct_name
);
523 if (rg
->name
== NULL
) {
524 status
= NT_STATUS_NO_MEMORY
;
530 r
->out
.groups
->num_principals
= ti
;
531 r
->out
.groups
->principals
= talloc_move(r
->out
.groups
, &result
);
533 status
= NT_STATUS_OK
;
539 NTSTATUS
_wbint_QueryUserRidList(struct pipes_struct
*p
,
540 struct wbint_QueryUserRidList
*r
)
542 struct winbindd_domain
*domain
= wb_child_domain();
545 if (domain
== NULL
) {
546 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
550 * Right now this is overkill. We should add a backend call
551 * just querying the rids.
554 status
= wb_cache_query_user_list(domain
, p
->mem_ctx
,
556 reset_cm_connection_on_error(domain
, NULL
, status
);
558 if (!NT_STATUS_IS_OK(status
)) {
562 r
->out
.rids
->num_rids
= talloc_array_length(r
->out
.rids
->rids
);
567 NTSTATUS
_wbint_DsGetDcName(struct pipes_struct
*p
, struct wbint_DsGetDcName
*r
)
569 struct winbindd_domain
*domain
= wb_child_domain();
570 struct rpc_pipe_client
*netlogon_pipe
;
571 struct netr_DsRGetDCNameInfo
*dc_info
;
574 unsigned int orig_timeout
;
575 struct dcerpc_binding_handle
*b
;
577 bool try_dsrgetdcname
= false;
579 if (domain
== NULL
) {
580 return dsgetdcname(p
->mem_ctx
, global_messaging_context(),
581 r
->in
.domain_name
, r
->in
.domain_guid
,
582 r
->in
.site_name
? r
->in
.site_name
: "",
587 if (domain
->active_directory
) {
588 try_dsrgetdcname
= true;
592 status
= cm_connect_netlogon(domain
, &netlogon_pipe
);
594 reset_cm_connection_on_error(domain
, NULL
, status
);
595 if (!NT_STATUS_IS_OK(status
)) {
596 DEBUG(10, ("Can't contact the NETLOGON pipe\n"));
600 b
= netlogon_pipe
->binding_handle
;
602 /* This call can take a long time - allow the server to time out.
603 35 seconds should do it. */
605 orig_timeout
= rpccli_set_timeout(netlogon_pipe
, 35000);
607 if (try_dsrgetdcname
) {
608 status
= dcerpc_netr_DsRGetDCName(b
,
609 p
->mem_ctx
, domain
->dcname
,
610 r
->in
.domain_name
, NULL
, r
->in
.domain_guid
,
611 r
->in
.flags
, r
->out
.dc_info
, &werr
);
612 if (NT_STATUS_IS_OK(status
) && W_ERROR_IS_OK(werr
)) {
616 reset_cm_connection_on_error(domain
, NULL
, status
))
621 try_dsrgetdcname
= false;
626 * Fallback to less capable methods
629 dc_info
= talloc_zero(r
->out
.dc_info
, struct netr_DsRGetDCNameInfo
);
630 if (dc_info
== NULL
) {
631 status
= NT_STATUS_NO_MEMORY
;
635 if (r
->in
.flags
& DS_PDC_REQUIRED
) {
636 status
= dcerpc_netr_GetDcName(b
,
637 p
->mem_ctx
, domain
->dcname
,
638 r
->in
.domain_name
, &dc_info
->dc_unc
, &werr
);
640 status
= dcerpc_netr_GetAnyDCName(b
,
641 p
->mem_ctx
, domain
->dcname
,
642 r
->in
.domain_name
, &dc_info
->dc_unc
, &werr
);
645 if (!retry
&& reset_cm_connection_on_error(domain
, b
, status
)) {
649 if (!NT_STATUS_IS_OK(status
)) {
650 DEBUG(10, ("dcerpc_netr_Get[Any]DCName failed: %s\n",
654 if (!W_ERROR_IS_OK(werr
)) {
655 DEBUG(10, ("dcerpc_netr_Get[Any]DCName failed: %s\n",
657 status
= werror_to_ntstatus(werr
);
661 *r
->out
.dc_info
= dc_info
;
662 status
= NT_STATUS_OK
;
665 /* And restore our original timeout. */
666 rpccli_set_timeout(netlogon_pipe
, orig_timeout
);
671 NTSTATUS
_wbint_LookupRids(struct pipes_struct
*p
, struct wbint_LookupRids
*r
)
673 struct winbindd_domain
*domain
= wb_child_domain();
676 enum lsa_SidType
*types
;
677 struct wbint_Principal
*result
;
681 if (domain
== NULL
) {
682 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
685 status
= wb_cache_rids_to_names(domain
, talloc_tos(), r
->in
.domain_sid
,
686 r
->in
.rids
->rids
, r
->in
.rids
->num_rids
,
687 &domain_name
, &names
, &types
);
688 reset_cm_connection_on_error(domain
, NULL
, status
);
689 if (!NT_STATUS_IS_OK(status
) &&
690 !NT_STATUS_EQUAL(status
, STATUS_SOME_UNMAPPED
)) {
694 *r
->out
.domain_name
= talloc_move(r
->out
.domain_name
, &domain_name
);
696 result
= talloc_array(p
->mem_ctx
, struct wbint_Principal
,
697 r
->in
.rids
->num_rids
);
698 if (result
== NULL
) {
699 return NT_STATUS_NO_MEMORY
;
702 for (i
=0; i
<r
->in
.rids
->num_rids
; i
++) {
703 sid_compose(&result
[i
].sid
, r
->in
.domain_sid
,
704 r
->in
.rids
->rids
[i
]);
705 result
[i
].type
= types
[i
];
706 result
[i
].name
= talloc_move(result
, &names
[i
]);
711 r
->out
.names
->num_principals
= r
->in
.rids
->num_rids
;
712 r
->out
.names
->principals
= result
;
716 NTSTATUS
_wbint_CheckMachineAccount(struct pipes_struct
*p
,
717 struct wbint_CheckMachineAccount
*r
)
719 struct winbindd_domain
*domain
;
723 domain
= wb_child_domain();
724 if (domain
== NULL
) {
725 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
729 invalidate_cm_connection(domain
);
730 domain
->conn
.netlogon_force_reauth
= true;
733 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
734 struct netlogon_creds_cli_context
*netlogon_creds_ctx
= NULL
;
735 status
= cm_connect_netlogon_secure(domain
,
737 &netlogon_creds_ctx
);
740 /* There is a race condition between fetching the trust account
741 password and the periodic machine password change. So it's
742 possible that the trust account password has been changed on us.
743 We are returned NT_STATUS_ACCESS_DENIED if this happens. */
745 #define MAX_RETRIES 3
747 if ((num_retries
< MAX_RETRIES
)
748 && NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
753 if (!NT_STATUS_IS_OK(status
)) {
754 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
758 /* Pass back result code - zero for success, other values for
759 specific failures. */
761 DEBUG(3,("domain %s secret is %s\n", domain
->name
,
762 NT_STATUS_IS_OK(status
) ? "good" : "bad"));
765 DEBUG(NT_STATUS_IS_OK(status
) ? 5 : 2,
766 ("Checking the trust account password for domain %s returned %s\n",
767 domain
->name
, nt_errstr(status
)));
772 NTSTATUS
_wbint_ChangeMachineAccount(struct pipes_struct
*p
,
773 struct wbint_ChangeMachineAccount
*r
)
775 struct messaging_context
*msg_ctx
= global_messaging_context();
776 struct winbindd_domain
*domain
;
778 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
779 struct netlogon_creds_cli_context
*netlogon_creds_ctx
= NULL
;
781 domain
= wb_child_domain();
782 if (domain
== NULL
) {
783 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
786 status
= cm_connect_netlogon_secure(domain
,
788 &netlogon_creds_ctx
);
789 if (!NT_STATUS_IS_OK(status
)) {
790 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
794 status
= trust_pw_change(netlogon_creds_ctx
,
796 netlogon_pipe
->binding_handle
,
801 /* Pass back result code - zero for success, other values for
802 specific failures. */
804 DEBUG(3,("domain %s secret %s\n", domain
->name
,
805 NT_STATUS_IS_OK(status
) ? "changed" : "unchanged"));
808 DEBUG(NT_STATUS_IS_OK(status
) ? 5 : 2,
809 ("Changing the trust account password for domain %s returned %s\n",
810 domain
->name
, nt_errstr(status
)));
815 NTSTATUS
_wbint_PingDc(struct pipes_struct
*p
, struct wbint_PingDc
*r
)
818 struct winbindd_domain
*domain
;
819 struct rpc_pipe_client
*netlogon_pipe
;
820 union netr_CONTROL_QUERY_INFORMATION info
;
822 fstring logon_server
;
823 struct dcerpc_binding_handle
*b
;
826 domain
= wb_child_domain();
827 if (domain
== NULL
) {
828 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
832 status
= cm_connect_netlogon(domain
, &netlogon_pipe
);
833 reset_cm_connection_on_error(domain
, NULL
, status
);
834 if (!NT_STATUS_IS_OK(status
)) {
835 DEBUG(3, ("could not open handle to NETLOGON pipe: %s\n",
840 b
= netlogon_pipe
->binding_handle
;
842 fstr_sprintf(logon_server
, "\\\\%s", domain
->dcname
);
843 *r
->out
.dcname
= talloc_strdup(p
->mem_ctx
, domain
->dcname
);
844 if (*r
->out
.dcname
== NULL
) {
845 DEBUG(2, ("Could not allocate memory\n"));
846 return NT_STATUS_NO_MEMORY
;
850 * This provokes a WERR_NOT_SUPPORTED error message. This is
851 * documented in the wspp docs. I could not get a successful
852 * call to work, but the main point here is testing that the
853 * netlogon pipe works.
855 status
= dcerpc_netr_LogonControl(b
, p
->mem_ctx
,
856 logon_server
, NETLOGON_CONTROL_QUERY
,
859 if (!retry
&& reset_cm_connection_on_error(domain
, b
, status
)) {
864 if (!NT_STATUS_IS_OK(status
)) {
865 DEBUG(2, ("dcerpc_netr_LogonControl failed: %s\n",
870 if (!W_ERROR_EQUAL(werr
, WERR_NOT_SUPPORTED
)) {
871 DEBUG(2, ("dcerpc_netr_LogonControl returned %s, expected "
872 "WERR_NOT_SUPPORTED\n",
874 return werror_to_ntstatus(werr
);
877 DEBUG(5, ("winbindd_dual_ping_dc succeeded\n"));
881 NTSTATUS
_winbind_DsrUpdateReadOnlyServerDnsRecords(struct pipes_struct
*p
,
882 struct winbind_DsrUpdateReadOnlyServerDnsRecords
*r
)
884 struct winbindd_domain
*domain
;
886 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
887 struct netlogon_creds_cli_context
*netlogon_creds_ctx
= NULL
;
888 struct dcerpc_binding_handle
*b
= NULL
;
891 domain
= wb_child_domain();
892 if (domain
== NULL
) {
893 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
897 status
= cm_connect_netlogon_secure(domain
,
899 &netlogon_creds_ctx
);
900 if (!NT_STATUS_IS_OK(status
)) {
901 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
905 b
= netlogon_pipe
->binding_handle
;
907 status
= netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(netlogon_creds_ctx
,
908 netlogon_pipe
->binding_handle
,
913 if (!retry
&& reset_cm_connection_on_error(domain
, b
, status
)) {
918 /* Pass back result code - zero for success, other values for
919 specific failures. */
921 DEBUG(3,("DNS records for domain %s %s\n", domain
->name
,
922 NT_STATUS_IS_OK(status
) ? "changed" : "unchanged"));
925 DEBUG(NT_STATUS_IS_OK(status
) ? 5 : 2,
926 ("Update of DNS records via RW DC %s returned %s\n",
927 domain
->name
, nt_errstr(status
)));
932 NTSTATUS
_winbind_SamLogon(struct pipes_struct
*p
,
933 struct winbind_SamLogon
*r
)
935 struct dcesrv_call_state
*dce_call
= p
->dce_call
;
936 struct dcesrv_connection
*dcesrv_conn
= dce_call
->conn
;
937 const struct tsocket_address
*local_address
=
938 dcesrv_connection_get_local_address(dcesrv_conn
);
939 const struct tsocket_address
*remote_address
=
940 dcesrv_connection_get_remote_address(dcesrv_conn
);
941 struct winbindd_domain
*domain
;
943 struct netr_IdentityInfo
*identity_info
= NULL
;
944 DATA_BLOB lm_response
, nt_response
;
945 DATA_BLOB challenge
= data_blob_null
;
947 uint16_t validation_level
;
948 union netr_Validation
*validation
= NULL
;
949 bool interactive
= false;
952 * Make sure we start with authoritative=true,
953 * it will only set to false if we don't know the
956 r
->out
.authoritative
= true;
958 domain
= wb_child_domain();
959 if (domain
== NULL
) {
960 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
963 switch (r
->in
.validation_level
) {
968 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
971 switch (r
->in
.logon_level
) {
972 case NetlogonInteractiveInformation
:
973 case NetlogonServiceInformation
:
974 case NetlogonInteractiveTransitiveInformation
:
975 case NetlogonServiceTransitiveInformation
:
976 if (r
->in
.logon
.password
== NULL
) {
977 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
981 identity_info
= &r
->in
.logon
.password
->identity_info
;
983 challenge
= data_blob_null
;
984 lm_response
= data_blob_talloc(p
->mem_ctx
,
985 r
->in
.logon
.password
->lmpassword
.hash
,
986 sizeof(r
->in
.logon
.password
->lmpassword
.hash
));
987 nt_response
= data_blob_talloc(p
->mem_ctx
,
988 r
->in
.logon
.password
->ntpassword
.hash
,
989 sizeof(r
->in
.logon
.password
->ntpassword
.hash
));
992 case NetlogonNetworkInformation
:
993 case NetlogonNetworkTransitiveInformation
:
994 if (r
->in
.logon
.network
== NULL
) {
995 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
999 identity_info
= &r
->in
.logon
.network
->identity_info
;
1001 challenge
= data_blob_talloc(p
->mem_ctx
,
1002 r
->in
.logon
.network
->challenge
,
1004 lm_response
= data_blob_talloc(p
->mem_ctx
,
1005 r
->in
.logon
.network
->lm
.data
,
1006 r
->in
.logon
.network
->lm
.length
);
1007 nt_response
= data_blob_talloc(p
->mem_ctx
,
1008 r
->in
.logon
.network
->nt
.data
,
1009 r
->in
.logon
.network
->nt
.length
);
1012 case NetlogonGenericInformation
:
1013 if (r
->in
.logon
.generic
== NULL
) {
1014 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
1017 identity_info
= &r
->in
.logon
.generic
->identity_info
;
1019 * Not implemented here...
1021 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
1024 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
1027 status
= winbind_dual_SamLogon(domain
, p
->mem_ctx
,
1029 identity_info
->parameter_control
,
1030 identity_info
->account_name
.string
,
1031 identity_info
->domain_name
.string
,
1032 identity_info
->workstation
.string
,
1033 identity_info
->logon_id
,
1037 lm_response
, nt_response
,
1040 &r
->out
.authoritative
,
1041 true, /* skip_sam */
1045 if (!NT_STATUS_IS_OK(status
)) {
1048 switch (r
->in
.validation_level
) {
1050 status
= map_validation_to_info3(p
->mem_ctx
,
1053 &r
->out
.validation
.sam3
);
1054 TALLOC_FREE(validation
);
1055 if (!NT_STATUS_IS_OK(status
)) {
1058 return NT_STATUS_OK
;
1060 status
= map_validation_to_info6(p
->mem_ctx
,
1063 &r
->out
.validation
.sam6
);
1064 TALLOC_FREE(validation
);
1065 if (!NT_STATUS_IS_OK(status
)) {
1068 return NT_STATUS_OK
;
1071 smb_panic(__location__
);
1072 return NT_STATUS_INTERNAL_ERROR
;
1075 static WERROR
_winbind_LogonControl_REDISCOVER(struct pipes_struct
*p
,
1076 struct winbindd_domain
*domain
,
1077 struct winbind_LogonControl
*r
)
1080 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
1081 struct netlogon_creds_cli_context
*netlogon_creds_ctx
= NULL
;
1082 struct netr_NETLOGON_INFO_2
*info2
= NULL
;
1083 WERROR check_result
= WERR_INTERNAL_ERROR
;
1085 info2
= talloc_zero(p
->mem_ctx
, struct netr_NETLOGON_INFO_2
);
1086 if (info2
== NULL
) {
1087 return WERR_NOT_ENOUGH_MEMORY
;
1090 if (domain
->internal
) {
1091 check_result
= WERR_OK
;
1096 * For now we just force a reconnect
1098 * TODO: take care of the optional '\dcname'
1100 invalidate_cm_connection(domain
);
1101 domain
->conn
.netlogon_force_reauth
= true;
1102 status
= cm_connect_netlogon_secure(domain
,
1104 &netlogon_creds_ctx
);
1105 reset_cm_connection_on_error(domain
, NULL
, status
);
1106 if (NT_STATUS_EQUAL(status
, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
)) {
1107 status
= NT_STATUS_NO_LOGON_SERVERS
;
1109 if (!NT_STATUS_IS_OK(status
)) {
1110 DEBUG(2, ("%s: domain[%s/%s] cm_connect_netlogon() returned %s\n",
1111 __func__
, domain
->name
, domain
->alt_name
,
1112 nt_errstr(status
)));
1114 * Here we return a top level error!
1115 * This is different than TC_QUERY or TC_VERIFY.
1117 return ntstatus_to_werror(status
);
1119 check_result
= WERR_OK
;
1122 info2
->pdc_connection_status
= WERR_OK
;
1123 if (domain
->dcname
!= NULL
) {
1124 info2
->flags
|= NETLOGON_HAS_IP
;
1125 info2
->flags
|= NETLOGON_HAS_TIMESERV
;
1126 info2
->trusted_dc_name
= talloc_asprintf(info2
, "\\\\%s",
1128 if (info2
->trusted_dc_name
== NULL
) {
1129 return WERR_NOT_ENOUGH_MEMORY
;
1132 info2
->trusted_dc_name
= talloc_strdup(info2
, "");
1133 if (info2
->trusted_dc_name
== NULL
) {
1134 return WERR_NOT_ENOUGH_MEMORY
;
1137 info2
->tc_connection_status
= check_result
;
1139 if (!W_ERROR_IS_OK(info2
->pdc_connection_status
)) {
1140 DEBUG(2, ("%s: domain[%s/%s] dcname[%s] "
1141 "pdc_connection[%s] tc_connection[%s]\n",
1142 __func__
, domain
->name
, domain
->alt_name
,
1144 win_errstr(info2
->pdc_connection_status
),
1145 win_errstr(info2
->tc_connection_status
)));
1148 r
->out
.query
->info2
= info2
;
1150 DEBUG(5, ("%s: succeeded.\n", __func__
));
1154 static WERROR
_winbind_LogonControl_TC_QUERY(struct pipes_struct
*p
,
1155 struct winbindd_domain
*domain
,
1156 struct winbind_LogonControl
*r
)
1159 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
1160 struct netlogon_creds_cli_context
*netlogon_creds_ctx
= NULL
;
1161 struct netr_NETLOGON_INFO_2
*info2
= NULL
;
1162 WERROR check_result
= WERR_INTERNAL_ERROR
;
1164 info2
= talloc_zero(p
->mem_ctx
, struct netr_NETLOGON_INFO_2
);
1165 if (info2
== NULL
) {
1166 return WERR_NOT_ENOUGH_MEMORY
;
1169 if (domain
->internal
) {
1170 check_result
= WERR_OK
;
1174 status
= cm_connect_netlogon_secure(domain
,
1176 &netlogon_creds_ctx
);
1177 reset_cm_connection_on_error(domain
, NULL
, status
);
1178 if (NT_STATUS_EQUAL(status
, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
)) {
1179 status
= NT_STATUS_NO_LOGON_SERVERS
;
1181 if (!NT_STATUS_IS_OK(status
)) {
1182 DEBUG(3, ("could not open handle to NETLOGON pipe: %s\n",
1183 nt_errstr(status
)));
1184 check_result
= ntstatus_to_werror(status
);
1187 check_result
= WERR_OK
;
1190 info2
->pdc_connection_status
= WERR_OK
;
1191 if (domain
->dcname
!= NULL
) {
1192 info2
->flags
|= NETLOGON_HAS_IP
;
1193 info2
->flags
|= NETLOGON_HAS_TIMESERV
;
1194 info2
->trusted_dc_name
= talloc_asprintf(info2
, "\\\\%s",
1196 if (info2
->trusted_dc_name
== NULL
) {
1197 return WERR_NOT_ENOUGH_MEMORY
;
1200 info2
->trusted_dc_name
= talloc_strdup(info2
, "");
1201 if (info2
->trusted_dc_name
== NULL
) {
1202 return WERR_NOT_ENOUGH_MEMORY
;
1205 info2
->tc_connection_status
= check_result
;
1207 if (!W_ERROR_IS_OK(info2
->pdc_connection_status
)) {
1208 DEBUG(2, ("%s: domain[%s/%s] dcname[%s] "
1209 "pdc_connection[%s] tc_connection[%s]\n",
1210 __func__
, domain
->name
, domain
->alt_name
,
1212 win_errstr(info2
->pdc_connection_status
),
1213 win_errstr(info2
->tc_connection_status
)));
1216 r
->out
.query
->info2
= info2
;
1218 DEBUG(5, ("%s: succeeded.\n", __func__
));
1222 static WERROR
_winbind_LogonControl_TC_VERIFY(struct pipes_struct
*p
,
1223 struct winbindd_domain
*domain
,
1224 struct winbind_LogonControl
*r
)
1226 TALLOC_CTX
*frame
= talloc_stackframe();
1229 struct lsa_String trusted_domain_name
= {};
1230 struct lsa_StringLarge trusted_domain_name_l
= {};
1231 struct rpc_pipe_client
*local_lsa_pipe
= NULL
;
1232 struct policy_handle local_lsa_policy
= {};
1233 struct dcerpc_binding_handle
*local_lsa
= NULL
;
1234 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
1235 struct netlogon_creds_cli_context
*netlogon_creds_ctx
= NULL
;
1236 struct cli_credentials
*creds
= NULL
;
1237 struct samr_Password
*cur_nt_hash
= NULL
;
1238 uint32_t trust_attributes
= 0;
1239 struct samr_Password new_owf_password
= {};
1241 struct samr_Password old_owf_password
= {};
1243 const struct lsa_TrustDomainInfoInfoEx
*local_tdo
= NULL
;
1244 bool fetch_fti
= false;
1245 struct lsa_ForestTrustInformation
*new_fti
= NULL
;
1246 struct netr_TrustInfo
*trust_info
= NULL
;
1247 struct netr_NETLOGON_INFO_2
*info2
= NULL
;
1248 struct dcerpc_binding_handle
*b
= NULL
;
1249 WERROR check_result
= WERR_INTERNAL_ERROR
;
1250 WERROR verify_result
= WERR_INTERNAL_ERROR
;
1253 trusted_domain_name
.string
= domain
->name
;
1254 trusted_domain_name_l
.string
= domain
->name
;
1256 info2
= talloc_zero(p
->mem_ctx
, struct netr_NETLOGON_INFO_2
);
1257 if (info2
== NULL
) {
1259 return WERR_NOT_ENOUGH_MEMORY
;
1262 if (domain
->internal
) {
1263 check_result
= WERR_OK
;
1267 status
= pdb_get_trust_credentials(domain
->name
,
1271 if (NT_STATUS_IS_OK(status
)) {
1272 cur_nt_hash
= cli_credentials_get_nt_hash(creds
, frame
);
1276 if (!domain
->primary
) {
1277 union lsa_TrustedDomainInfo
*tdi
= NULL
;
1279 status
= open_internal_lsa_conn(frame
, &local_lsa_pipe
,
1281 if (!NT_STATUS_IS_OK(status
)) {
1282 DEBUG(0,("%s:%s: open_internal_lsa_conn() failed - %s\n",
1283 __location__
, __func__
, nt_errstr(status
)));
1285 return WERR_INTERNAL_ERROR
;
1287 local_lsa
= local_lsa_pipe
->binding_handle
;
1289 status
= dcerpc_lsa_QueryTrustedDomainInfoByName(local_lsa
, frame
,
1291 &trusted_domain_name
,
1292 LSA_TRUSTED_DOMAIN_INFO_INFO_EX
,
1294 if (!NT_STATUS_IS_OK(status
)) {
1295 DEBUG(0,("%s:%s: local_lsa.QueryTrustedDomainInfoByName(%s) failed - %s\n",
1296 __location__
, __func__
, domain
->name
, nt_errstr(status
)));
1298 return WERR_INTERNAL_ERROR
;
1300 if (NT_STATUS_EQUAL(result
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1301 DEBUG(1,("%s:%s: domain[%s] not found via LSA, might be removed already.\n",
1302 __location__
, __func__
, domain
->name
));
1304 return WERR_NO_SUCH_DOMAIN
;
1306 if (!NT_STATUS_IS_OK(result
)) {
1307 DEBUG(0,("%s:%s: local_lsa.QueryTrustedDomainInfoByName(%s) returned %s\n",
1308 __location__
, __func__
, domain
->name
, nt_errstr(result
)));
1310 return WERR_INTERNAL_ERROR
;
1313 DEBUG(0,("%s:%s: local_lsa.QueryTrustedDomainInfoByName() "
1314 "returned no trusted domain information\n",
1315 __location__
, __func__
));
1317 return WERR_INTERNAL_ERROR
;
1320 local_tdo
= &tdi
->info_ex
;
1321 trust_attributes
= local_tdo
->trust_attributes
;
1324 if (trust_attributes
& LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
) {
1325 struct lsa_ForestTrustInformation
*old_fti
= NULL
;
1327 status
= dcerpc_lsa_lsaRQueryForestTrustInformation(local_lsa
, frame
,
1329 &trusted_domain_name
,
1330 LSA_FOREST_TRUST_DOMAIN_INFO
,
1332 if (!NT_STATUS_IS_OK(status
)) {
1333 DEBUG(0,("%s:%s: local_lsa.lsaRQueryForestTrustInformation(%s) failed %s\n",
1334 __location__
, __func__
, domain
->name
, nt_errstr(status
)));
1336 return WERR_INTERNAL_ERROR
;
1338 if (NT_STATUS_EQUAL(result
, NT_STATUS_NOT_FOUND
)) {
1339 DEBUG(2,("%s: no forest trust information available for domain[%s] yet.\n",
1340 __func__
, domain
->name
));
1343 result
= NT_STATUS_OK
;
1345 if (!NT_STATUS_IS_OK(result
)) {
1346 DEBUG(0,("%s:%s: local_lsa.lsaRQueryForestTrustInformation(%s) returned %s\n",
1347 __location__
, __func__
, domain
->name
, nt_errstr(result
)));
1349 return WERR_INTERNAL_ERROR
;
1352 TALLOC_FREE(old_fti
);
1356 status
= cm_connect_netlogon_secure(domain
,
1358 &netlogon_creds_ctx
);
1359 reset_cm_connection_on_error(domain
, NULL
, status
);
1360 if (NT_STATUS_EQUAL(status
, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
)) {
1361 status
= NT_STATUS_NO_LOGON_SERVERS
;
1363 if (!NT_STATUS_IS_OK(status
)) {
1364 DEBUG(3, ("could not open handle to NETLOGON pipe: %s\n",
1365 nt_errstr(status
)));
1366 check_result
= ntstatus_to_werror(status
);
1369 check_result
= WERR_OK
;
1370 b
= netlogon_pipe
->binding_handle
;
1372 if (cur_nt_hash
== NULL
) {
1373 verify_result
= WERR_NO_TRUST_LSA_SECRET
;
1378 status
= netlogon_creds_cli_GetForestTrustInformation(netlogon_creds_ctx
,
1381 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1382 status
= NT_STATUS_NOT_SUPPORTED
;
1384 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_SUPPORTED
)) {
1386 status
= NT_STATUS_OK
;
1388 if (!NT_STATUS_IS_OK(status
)) {
1390 reset_cm_connection_on_error(domain
, b
, status
))
1395 DEBUG(2, ("netlogon_creds_cli_GetForestTrustInformation(%s)"
1397 domain
->name
, nt_errstr(status
)));
1398 check_result
= ntstatus_to_werror(status
);
1403 if (new_fti
!= NULL
) {
1404 struct lsa_ForestTrustInformation old_fti
= {};
1405 struct lsa_ForestTrustInformation
*merged_fti
= NULL
;
1406 struct lsa_ForestTrustCollisionInfo
*collision_info
= NULL
;
1408 status
= dsdb_trust_merge_forest_info(frame
, local_tdo
,
1411 if (!NT_STATUS_IS_OK(status
)) {
1412 DEBUG(0,("%s:%s: dsdb_trust_merge_forest_info(%s) failed %s\n",
1413 __location__
, __func__
,
1414 domain
->name
, nt_errstr(status
)));
1416 return ntstatus_to_werror(status
);
1419 status
= dcerpc_lsa_lsaRSetForestTrustInformation(local_lsa
, frame
,
1421 &trusted_domain_name_l
,
1422 LSA_FOREST_TRUST_DOMAIN_INFO
,
1424 0, /* check_only=0 => store it! */
1427 if (!NT_STATUS_IS_OK(status
)) {
1428 DEBUG(0,("%s:%s: local_lsa.lsaRSetForestTrustInformation(%s) failed %s\n",
1429 __location__
, __func__
, domain
->name
, nt_errstr(status
)));
1431 return WERR_INTERNAL_ERROR
;
1433 if (!NT_STATUS_IS_OK(result
)) {
1434 DEBUG(0,("%s:%s: local_lsa.lsaRSetForestTrustInformation(%s) returned %s\n",
1435 __location__
, __func__
, domain
->name
, nt_errstr(result
)));
1437 return ntstatus_to_werror(result
);
1441 status
= netlogon_creds_cli_ServerGetTrustInfo(netlogon_creds_ctx
,
1446 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
1447 status
= NT_STATUS_NOT_SUPPORTED
;
1449 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_SUPPORTED
)) {
1450 DEBUG(5, ("netlogon_creds_cli_ServerGetTrustInfo failed: %s\n",
1451 nt_errstr(status
)));
1452 verify_result
= WERR_OK
;
1455 if (!NT_STATUS_IS_OK(status
)) {
1456 if (!retry
&& reset_cm_connection_on_error(domain
, b
, status
)) {
1460 DEBUG(2, ("netlogon_creds_cli_ServerGetTrustInfo failed: %s\n",
1461 nt_errstr(status
)));
1463 if (!dcerpc_binding_handle_is_connected(b
)) {
1464 check_result
= ntstatus_to_werror(status
);
1467 verify_result
= ntstatus_to_werror(status
);
1472 if (trust_info
!= NULL
&& trust_info
->count
>= 1) {
1473 uint32_t diff
= trust_info
->data
[0] ^ trust_attributes
;
1475 if (diff
& LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
) {
1476 verify_result
= WERR_DOMAIN_TRUST_INCONSISTENT
;
1481 cmp_new
= memcmp(new_owf_password
.hash
,
1483 sizeof(cur_nt_hash
->hash
));
1484 cmp_old
= memcmp(old_owf_password
.hash
,
1486 sizeof(cur_nt_hash
->hash
));
1487 if (cmp_new
!= 0 && cmp_old
!= 0) {
1488 DEBUG(1,("%s:Error: credentials for domain[%s/%s] doesn't match "
1489 "any password known to dcname[%s]\n",
1490 __func__
, domain
->name
, domain
->alt_name
,
1492 verify_result
= WERR_WRONG_PASSWORD
;
1497 DEBUG(2,("%s:Warning: credentials for domain[%s/%s] only match "
1498 "against the old password known to dcname[%s]\n",
1499 __func__
, domain
->name
, domain
->alt_name
,
1503 verify_result
= WERR_OK
;
1507 verify_result
= check_result
;
1509 info2
->flags
|= NETLOGON_VERIFY_STATUS_RETURNED
;
1510 info2
->pdc_connection_status
= verify_result
;
1511 if (domain
->dcname
!= NULL
) {
1512 info2
->flags
|= NETLOGON_HAS_IP
;
1513 info2
->flags
|= NETLOGON_HAS_TIMESERV
;
1514 info2
->trusted_dc_name
= talloc_asprintf(info2
, "\\\\%s",
1516 if (info2
->trusted_dc_name
== NULL
) {
1518 return WERR_NOT_ENOUGH_MEMORY
;
1521 info2
->trusted_dc_name
= talloc_strdup(info2
, "");
1522 if (info2
->trusted_dc_name
== NULL
) {
1524 return WERR_NOT_ENOUGH_MEMORY
;
1527 info2
->tc_connection_status
= check_result
;
1529 if (!W_ERROR_IS_OK(info2
->pdc_connection_status
)) {
1530 DEBUG(2, ("%s: domain[%s/%s] dcname[%s] "
1531 "pdc_connection[%s] tc_connection[%s]\n",
1532 __func__
, domain
->name
, domain
->alt_name
,
1534 win_errstr(info2
->pdc_connection_status
),
1535 win_errstr(info2
->tc_connection_status
)));
1538 r
->out
.query
->info2
= info2
;
1540 DEBUG(5, ("%s: succeeded.\n", __func__
));
1545 static WERROR
_winbind_LogonControl_CHANGE_PASSWORD(struct pipes_struct
*p
,
1546 struct winbindd_domain
*domain
,
1547 struct winbind_LogonControl
*r
)
1549 struct messaging_context
*msg_ctx
= global_messaging_context();
1551 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
1552 struct netlogon_creds_cli_context
*netlogon_creds_ctx
= NULL
;
1553 struct cli_credentials
*creds
= NULL
;
1554 struct samr_Password
*cur_nt_hash
= NULL
;
1555 struct netr_NETLOGON_INFO_1
*info1
= NULL
;
1556 struct dcerpc_binding_handle
*b
;
1557 WERROR change_result
= WERR_OK
;
1560 info1
= talloc_zero(p
->mem_ctx
, struct netr_NETLOGON_INFO_1
);
1561 if (info1
== NULL
) {
1562 return WERR_NOT_ENOUGH_MEMORY
;
1565 if (domain
->internal
) {
1566 return WERR_NOT_SUPPORTED
;
1569 status
= pdb_get_trust_credentials(domain
->name
,
1573 if (NT_STATUS_IS_OK(status
)) {
1574 cur_nt_hash
= cli_credentials_get_nt_hash(creds
, p
->mem_ctx
);
1579 status
= cm_connect_netlogon_secure(domain
,
1581 &netlogon_creds_ctx
);
1582 reset_cm_connection_on_error(domain
, NULL
, status
);
1583 if (NT_STATUS_EQUAL(status
, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
)) {
1584 status
= NT_STATUS_NO_LOGON_SERVERS
;
1586 if (!NT_STATUS_IS_OK(status
)) {
1587 DEBUG(2, ("%s: domain[%s/%s] cm_connect_netlogon() returned %s\n",
1588 __func__
, domain
->name
, domain
->alt_name
,
1589 nt_errstr(status
)));
1591 * Here we return a top level error!
1592 * This is different than TC_QUERY or TC_VERIFY.
1594 return ntstatus_to_werror(status
);
1596 b
= netlogon_pipe
->binding_handle
;
1598 if (cur_nt_hash
== NULL
) {
1599 change_result
= WERR_NO_TRUST_LSA_SECRET
;
1602 TALLOC_FREE(cur_nt_hash
);
1604 status
= trust_pw_change(netlogon_creds_ctx
,
1605 msg_ctx
, b
, domain
->name
,
1608 if (!NT_STATUS_IS_OK(status
)) {
1609 if (!retry
&& reset_cm_connection_on_error(domain
, b
, status
)) {
1614 DEBUG(1, ("trust_pw_change(%s): %s\n",
1615 domain
->name
, nt_errstr(status
)));
1617 change_result
= ntstatus_to_werror(status
);
1621 change_result
= WERR_OK
;
1624 info1
->pdc_connection_status
= change_result
;
1626 if (!W_ERROR_IS_OK(info1
->pdc_connection_status
)) {
1627 DEBUG(2, ("%s: domain[%s/%s] dcname[%s] "
1628 "pdc_connection[%s]\n",
1629 __func__
, domain
->name
, domain
->alt_name
,
1631 win_errstr(info1
->pdc_connection_status
)));
1634 r
->out
.query
->info1
= info1
;
1636 DEBUG(5, ("%s: succeeded.\n", __func__
));
1640 WERROR
_winbind_LogonControl(struct pipes_struct
*p
,
1641 struct winbind_LogonControl
*r
)
1643 struct winbindd_domain
*domain
;
1645 domain
= wb_child_domain();
1646 if (domain
== NULL
) {
1647 return WERR_NO_SUCH_DOMAIN
;
1650 switch (r
->in
.function_code
) {
1651 case NETLOGON_CONTROL_REDISCOVER
:
1652 if (r
->in
.level
!= 2) {
1653 return WERR_INVALID_PARAMETER
;
1655 return _winbind_LogonControl_REDISCOVER(p
, domain
, r
);
1656 case NETLOGON_CONTROL_TC_QUERY
:
1657 if (r
->in
.level
!= 2) {
1658 return WERR_INVALID_PARAMETER
;
1660 return _winbind_LogonControl_TC_QUERY(p
, domain
, r
);
1661 case NETLOGON_CONTROL_TC_VERIFY
:
1662 if (r
->in
.level
!= 2) {
1663 return WERR_INVALID_PARAMETER
;
1665 return _winbind_LogonControl_TC_VERIFY(p
, domain
, r
);
1666 case NETLOGON_CONTROL_CHANGE_PASSWORD
:
1667 if (r
->in
.level
!= 1) {
1668 return WERR_INVALID_PARAMETER
;
1670 return _winbind_LogonControl_CHANGE_PASSWORD(p
, domain
, r
);
1675 DEBUG(4, ("%s: function_code[0x%x] not supported\n",
1676 __func__
, r
->in
.function_code
));
1677 return WERR_NOT_SUPPORTED
;
1680 WERROR
_winbind_GetForestTrustInformation(struct pipes_struct
*p
,
1681 struct winbind_GetForestTrustInformation
*r
)
1683 TALLOC_CTX
*frame
= talloc_stackframe();
1684 NTSTATUS status
, result
;
1685 struct winbindd_domain
*domain
;
1686 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
1687 struct netlogon_creds_cli_context
*netlogon_creds_ctx
= NULL
;
1688 struct dcerpc_binding_handle
*b
;
1690 struct lsa_String trusted_domain_name
= {};
1691 struct lsa_StringLarge trusted_domain_name_l
= {};
1692 union lsa_TrustedDomainInfo
*tdi
= NULL
;
1693 const struct lsa_TrustDomainInfoInfoEx
*tdo
= NULL
;
1694 struct lsa_ForestTrustInformation _old_fti
= {};
1695 struct lsa_ForestTrustInformation
*old_fti
= NULL
;
1696 struct lsa_ForestTrustInformation
*new_fti
= NULL
;
1697 struct lsa_ForestTrustInformation
*merged_fti
= NULL
;
1698 struct lsa_ForestTrustCollisionInfo
*collision_info
= NULL
;
1699 bool update_fti
= false;
1700 struct rpc_pipe_client
*local_lsa_pipe
;
1701 struct policy_handle local_lsa_policy
;
1702 struct dcerpc_binding_handle
*local_lsa
= NULL
;
1704 domain
= wb_child_domain();
1705 if (domain
== NULL
) {
1707 return WERR_NO_SUCH_DOMAIN
;
1711 * checking for domain->internal and domain->primary
1712 * makes sure we only do some work when running as DC.
1715 if (domain
->internal
) {
1717 return WERR_NO_SUCH_DOMAIN
;
1720 if (domain
->primary
) {
1722 return WERR_NO_SUCH_DOMAIN
;
1725 trusted_domain_name
.string
= domain
->name
;
1726 trusted_domain_name_l
.string
= domain
->name
;
1728 status
= open_internal_lsa_conn(frame
, &local_lsa_pipe
,
1730 if (!NT_STATUS_IS_OK(status
)) {
1731 DEBUG(0,("%s:%s: open_internal_lsa_conn() failed - %s\n",
1732 __location__
, __func__
, nt_errstr(status
)));
1734 return WERR_INTERNAL_ERROR
;
1736 local_lsa
= local_lsa_pipe
->binding_handle
;
1738 status
= dcerpc_lsa_QueryTrustedDomainInfoByName(local_lsa
, frame
,
1740 &trusted_domain_name
,
1741 LSA_TRUSTED_DOMAIN_INFO_INFO_EX
,
1743 if (!NT_STATUS_IS_OK(status
)) {
1744 DEBUG(0,("%s:%s: local_lsa.QueryTrustedDomainInfoByName(%s) failed - %s\n",
1745 __location__
, __func__
, domain
->name
, nt_errstr(status
)));
1747 return WERR_INTERNAL_ERROR
;
1749 if (NT_STATUS_EQUAL(result
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1750 DEBUG(1,("%s:%s: domain[%s] not found via LSA, might be removed already.\n",
1751 __location__
, __func__
, domain
->name
));
1753 return WERR_NO_SUCH_DOMAIN
;
1755 if (!NT_STATUS_IS_OK(result
)) {
1756 DEBUG(0,("%s:%s: local_lsa.QueryTrustedDomainInfoByName(%s) returned %s\n",
1757 __location__
, __func__
, domain
->name
, nt_errstr(result
)));
1759 return WERR_INTERNAL_ERROR
;
1762 DEBUG(0,("%s:%s: local_lsa.QueryTrustedDomainInfoByName() "
1763 "returned no trusted domain information\n",
1764 __location__
, __func__
));
1766 return WERR_INTERNAL_ERROR
;
1769 tdo
= &tdi
->info_ex
;
1771 if (!(tdo
->trust_attributes
& LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
)) {
1772 DEBUG(2,("%s: tdo[%s/%s] is no forest trust attributes[0x%08X]\n",
1773 __func__
, tdo
->netbios_name
.string
,
1774 tdo
->domain_name
.string
,
1775 (unsigned)tdo
->trust_attributes
));
1777 return WERR_NO_SUCH_DOMAIN
;
1780 if (r
->in
.flags
& ~DS_GFTI_UPDATE_TDO
) {
1782 return WERR_INVALID_FLAGS
;
1786 status
= cm_connect_netlogon_secure(domain
,
1788 &netlogon_creds_ctx
);
1789 reset_cm_connection_on_error(domain
, NULL
, status
);
1790 if (NT_STATUS_EQUAL(status
, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
)) {
1791 status
= NT_STATUS_NO_LOGON_SERVERS
;
1793 if (!NT_STATUS_IS_OK(status
)) {
1794 DEBUG(3, ("could not open handle to NETLOGON pipe: %s\n",
1795 nt_errstr(status
)));
1797 return ntstatus_to_werror(status
);
1799 b
= netlogon_pipe
->binding_handle
;
1801 status
= netlogon_creds_cli_GetForestTrustInformation(netlogon_creds_ctx
,
1804 if (!NT_STATUS_IS_OK(status
)) {
1805 if (!retry
&& reset_cm_connection_on_error(domain
, b
, status
)) {
1809 DEBUG(2, ("netlogon_creds_cli_GetForestTrustInformation(%s) failed: %s\n",
1810 domain
->name
, nt_errstr(status
)));
1812 return ntstatus_to_werror(status
);
1815 *r
->out
.forest_trust_info
= new_fti
;
1817 if (r
->in
.flags
& DS_GFTI_UPDATE_TDO
) {
1821 status
= dcerpc_lsa_lsaRQueryForestTrustInformation(local_lsa
, frame
,
1823 &trusted_domain_name
,
1824 LSA_FOREST_TRUST_DOMAIN_INFO
,
1826 if (!NT_STATUS_IS_OK(status
)) {
1827 DEBUG(0,("%s:%s: local_lsa.lsaRQueryForestTrustInformation(%s) failed %s\n",
1828 __location__
, __func__
, domain
->name
, nt_errstr(status
)));
1830 return WERR_INTERNAL_ERROR
;
1832 if (NT_STATUS_EQUAL(result
, NT_STATUS_NOT_FOUND
)) {
1833 DEBUG(2,("%s: no forest trust information available for domain[%s] yet.\n",
1834 __func__
, domain
->name
));
1836 old_fti
= &_old_fti
;
1837 result
= NT_STATUS_OK
;
1839 if (!NT_STATUS_IS_OK(result
)) {
1840 DEBUG(0,("%s:%s: local_lsa.lsaRQueryForestTrustInformation(%s) returned %s\n",
1841 __location__
, __func__
, domain
->name
, nt_errstr(result
)));
1843 return WERR_INTERNAL_ERROR
;
1846 if (old_fti
== NULL
) {
1847 DEBUG(0,("%s:%s: local_lsa.lsaRQueryForestTrustInformation() "
1848 "returned success without returning forest trust information\n",
1849 __location__
, __func__
));
1851 return WERR_INTERNAL_ERROR
;
1858 status
= dsdb_trust_merge_forest_info(frame
, tdo
, old_fti
, new_fti
,
1860 if (!NT_STATUS_IS_OK(status
)) {
1861 DEBUG(0,("%s:%s: dsdb_trust_merge_forest_info(%s) failed %s\n",
1862 __location__
, __func__
, domain
->name
, nt_errstr(status
)));
1864 return ntstatus_to_werror(status
);
1867 status
= dcerpc_lsa_lsaRSetForestTrustInformation(local_lsa
, frame
,
1869 &trusted_domain_name_l
,
1870 LSA_FOREST_TRUST_DOMAIN_INFO
,
1872 0, /* check_only=0 => store it! */
1875 if (!NT_STATUS_IS_OK(status
)) {
1876 DEBUG(0,("%s:%s: local_lsa.lsaRSetForestTrustInformation(%s) failed %s\n",
1877 __location__
, __func__
, domain
->name
, nt_errstr(status
)));
1879 return WERR_INTERNAL_ERROR
;
1881 if (!NT_STATUS_IS_OK(result
)) {
1882 DEBUG(0,("%s:%s: local_lsa.lsaRSetForestTrustInformation(%s) returned %s\n",
1883 __location__
, __func__
, domain
->name
, nt_errstr(result
)));
1885 return ntstatus_to_werror(result
);
1889 DEBUG(5, ("_winbind_GetForestTrustInformation succeeded\n"));
1894 NTSTATUS
_winbind_SendToSam(struct pipes_struct
*p
, struct winbind_SendToSam
*r
)
1896 struct winbindd_domain
*domain
;
1898 struct rpc_pipe_client
*netlogon_pipe
;
1899 struct netlogon_creds_cli_context
*netlogon_creds_ctx
= NULL
;
1900 struct dcerpc_binding_handle
*b
= NULL
;
1903 DEBUG(5, ("_winbind_SendToSam received\n"));
1904 domain
= wb_child_domain();
1905 if (domain
== NULL
) {
1906 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
1910 status
= cm_connect_netlogon_secure(domain
,
1912 &netlogon_creds_ctx
);
1913 reset_cm_connection_on_error(domain
, NULL
, status
);
1914 if (!NT_STATUS_IS_OK(status
)) {
1915 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
1919 b
= netlogon_pipe
->binding_handle
;
1921 status
= netlogon_creds_cli_SendToSam(netlogon_creds_ctx
,
1924 if (!retry
&& reset_cm_connection_on_error(domain
, b
, status
)) {
1932 NTSTATUS
_wbint_ListTrustedDomains(struct pipes_struct
*p
,
1933 struct wbint_ListTrustedDomains
*r
)
1935 struct winbindd_domain
*domain
= wb_child_domain();
1938 struct netr_DomainTrustList trusts
;
1939 struct netr_DomainTrustList
*out
= NULL
;
1942 if (domain
== NULL
) {
1943 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
1946 /* Cut client_pid to 32bit */
1947 client_pid
= r
->in
.client_pid
;
1948 if ((uint64_t)client_pid
!= r
->in
.client_pid
) {
1949 DBG_DEBUG("pid out of range\n");
1950 return NT_STATUS_INVALID_PARAMETER
;
1953 DBG_NOTICE("[%s %"PRIu32
"]: list trusted domains\n",
1954 r
->in
.client_name
, client_pid
);
1956 result
= wb_cache_trusted_domains(domain
, p
->mem_ctx
, &trusts
);
1957 if (!NT_STATUS_IS_OK(result
)) {
1958 DBG_NOTICE("wb_cache_trusted_domains returned %s\n",
1963 out
= talloc_zero(p
->mem_ctx
, struct netr_DomainTrustList
);
1965 return NT_STATUS_NO_MEMORY
;
1968 r
->out
.domains
= out
;
1970 for (i
=0; i
<trusts
.count
; i
++) {
1971 if (trusts
.array
[i
].sid
== NULL
) {
1974 if (dom_sid_equal(trusts
.array
[i
].sid
, &global_sid_NULL
)) {
1979 out
->array
= talloc_realloc(out
, out
->array
,
1980 struct netr_DomainTrust
,
1982 if (out
->array
== NULL
) {
1983 return NT_STATUS_NO_MEMORY
;
1987 out
->array
[n
].netbios_name
= talloc_steal(
1988 out
->array
, trusts
.array
[i
].netbios_name
);
1989 if (out
->array
[n
].netbios_name
== NULL
) {
1990 return NT_STATUS_NO_MEMORY
;
1993 out
->array
[n
].dns_name
= talloc_steal(
1994 out
->array
, trusts
.array
[i
].dns_name
);
1995 if (out
->array
[n
].dns_name
== NULL
) {
1996 return NT_STATUS_NO_MEMORY
;
1999 out
->array
[n
].sid
= dom_sid_dup(out
->array
,
2000 trusts
.array
[i
].sid
);
2001 if (out
->array
[n
].sid
== NULL
) {
2002 return NT_STATUS_NO_MEMORY
;
2005 out
->array
[n
].trust_flags
= trusts
.array
[i
].trust_flags
;
2006 out
->array
[n
].trust_type
= trusts
.array
[i
].trust_type
;
2007 out
->array
[n
].trust_attributes
= trusts
.array
[i
].trust_attributes
;
2010 return NT_STATUS_OK
;
2013 #include "librpc/gen_ndr/ndr_winbind_scompat.c"