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/gen_ndr/srv_winbind.h"
29 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
30 #include "../librpc/gen_ndr/ndr_lsa_c.h"
32 #include "../libcli/security/security.h"
33 #include "../libcli/auth/netlogon_creds_cli.h"
35 #include "../source4/dsdb/samdb/samdb.h"
36 #include "rpc_client/cli_netlogon.h"
37 #include "rpc_client/util_netlogon.h"
38 #include "libsmb/dsgetdcname.h"
40 void _wbint_Ping(struct pipes_struct *p, struct wbint_Ping *r)
42 *r->out.out_data = r->in.in_data;
45 bool reset_cm_connection_on_error(struct winbindd_domain *domain,
46 struct dcerpc_binding_handle *b,
49 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
50 NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
51 NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
52 invalidate_cm_connection(domain);
53 domain->conn.netlogon_force_reauth = true;
57 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
58 NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR))
60 invalidate_cm_connection(domain);
61 /* We invalidated the connection. */
65 if (b != NULL && !dcerpc_binding_handle_is_connected(b)) {
66 invalidate_cm_connection(domain);
73 NTSTATUS _wbint_LookupSid(struct pipes_struct *p, struct wbint_LookupSid *r)
75 struct winbindd_domain *domain = wb_child_domain();
78 enum lsa_SidType type;
82 return NT_STATUS_REQUEST_NOT_ACCEPTED;
85 status = wb_cache_sid_to_name(domain, p->mem_ctx, r->in.sid,
86 &dom_name, &name, &type);
87 reset_cm_connection_on_error(domain, NULL, status);
88 if (!NT_STATUS_IS_OK(status)) {
92 *r->out.domain = dom_name;
98 NTSTATUS _wbint_LookupSids(struct pipes_struct *p, struct wbint_LookupSids *r)
100 struct winbindd_domain *domain = wb_child_domain();
101 struct lsa_RefDomainList *domains = r->out.domains;
105 if (domain == NULL) {
106 return NT_STATUS_REQUEST_NOT_ACCEPTED;
110 * This breaks the winbindd_domain->methods abstraction: This
111 * is only called for remote domains, and both winbindd_msrpc
112 * and winbindd_ad call into lsa_lookupsids anyway. Caching is
113 * done at the wbint RPC layer.
116 status = rpc_lookup_sids(p->mem_ctx, domain, r->in.sids,
117 &domains, &r->out.names);
119 if (domains != NULL) {
120 r->out.domains = domains;
123 if (!retry && reset_cm_connection_on_error(domain, NULL, status)) {
131 NTSTATUS _wbint_LookupName(struct pipes_struct *p, struct wbint_LookupName *r)
133 struct winbindd_domain *domain = wb_child_domain();
136 if (domain == NULL) {
137 return NT_STATUS_REQUEST_NOT_ACCEPTED;
140 status = wb_cache_name_to_sid(domain, p->mem_ctx, r->in.domain,
141 r->in.name, r->in.flags,
142 r->out.sid, r->out.type);
143 reset_cm_connection_on_error(domain, NULL, status);
147 NTSTATUS _wbint_Sids2UnixIDs(struct pipes_struct *p,
148 struct wbint_Sids2UnixIDs *r)
152 struct lsa_DomainInfo *d;
153 struct wbint_TransID *ids;
156 struct id_map **id_map_ptrs = NULL;
157 struct idmap_domain *dom;
158 NTSTATUS status = NT_STATUS_NO_MEMORY;
160 if (r->in.domains->count != 1) {
161 return NT_STATUS_INVALID_PARAMETER;
164 d = &r->in.domains->domains[0];
165 ids = r->in.ids->ids;
166 num_ids = r->in.ids->num_ids;
168 dom = idmap_find_domain_with_sid(d->name.string, d->sid);
170 struct dom_sid_buf buf;
171 DEBUG(10, ("idmap domain %s:%s not found\n",
173 dom_sid_str_buf(d->sid, &buf)));
175 for (i=0; i<num_ids; i++) {
177 ids[i].xid = (struct unixid) {
179 .type = ID_TYPE_NOT_SPECIFIED
186 id_map_ptrs = id_map_ptrs_init(talloc_tos(), num_ids);
187 if (id_map_ptrs == NULL) {
192 * Convert the input data into a list of id_map structs
193 * suitable for handing in to the idmap sids_to_unixids
197 for (i=0; i<num_ids; i++) {
198 struct id_map *m = id_map_ptrs[i];
200 sid_compose(m->sid, d->sid, ids[i].rid);
201 m->status = ID_UNKNOWN;
202 m->xid = (struct unixid) { .type = ids[i].type };
205 status = dom->methods->sids_to_unixids(dom, id_map_ptrs);
207 if (NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
209 * This is okay. We need to transfer the mapped ones
210 * up to our caller. The individual mappings carry the
211 * information whether they are mapped or not.
213 status = NT_STATUS_OK;
216 if (!NT_STATUS_IS_OK(status)) {
217 DEBUG(10, ("sids_to_unixids returned %s\n",
223 * Extract the results for handing them back to the caller.
226 for (i=0; i<num_ids; i++) {
227 struct id_map *m = id_map_ptrs[i];
229 if (!idmap_unix_id_is_in_range(m->xid.id, dom)) {
230 DBG_DEBUG("id %"PRIu32" is out of range "
231 "%"PRIu32"-%"PRIu32" for domain %s\n",
232 m->xid.id, dom->low_id, dom->high_id,
234 m->status = ID_UNMAPPED;
237 if (m->status == ID_MAPPED) {
240 ids[i].xid.id = UINT32_MAX;
241 ids[i].xid.type = ID_TYPE_NOT_SPECIFIED;
247 status = NT_STATUS_NO_MEMORY;
249 TALLOC_FREE(id_map_ptrs);
253 NTSTATUS _wbint_UnixIDs2Sids(struct pipes_struct *p,
254 struct wbint_UnixIDs2Sids *r)
256 struct id_map **maps;
260 maps = id_map_ptrs_init(talloc_tos(), r->in.num_ids);
262 return NT_STATUS_NO_MEMORY;
265 for (i=0; i<r->in.num_ids; i++) {
266 maps[i]->status = ID_UNKNOWN;
267 maps[i]->xid = r->in.xids[i];
270 status = idmap_backend_unixids_to_sids(maps, r->in.domain_name,
272 if (!NT_STATUS_IS_OK(status)) {
277 for (i=0; i<r->in.num_ids; i++) {
278 r->out.xids[i] = maps[i]->xid;
279 sid_copy(&r->out.sids[i], maps[i]->sid);
287 NTSTATUS _wbint_AllocateUid(struct pipes_struct *p, struct wbint_AllocateUid *r)
292 status = idmap_allocate_uid(&xid);
293 if (!NT_STATUS_IS_OK(status)) {
296 *r->out.uid = xid.id;
300 NTSTATUS _wbint_AllocateGid(struct pipes_struct *p, struct wbint_AllocateGid *r)
305 status = idmap_allocate_gid(&xid);
306 if (!NT_STATUS_IS_OK(status)) {
309 *r->out.gid = xid.id;
313 NTSTATUS _wbint_GetNssInfo(struct pipes_struct *p, struct wbint_GetNssInfo *r)
315 struct idmap_domain *domain;
318 domain = idmap_find_domain(r->in.info->domain_name);
319 if ((domain == NULL) || (domain->query_user == NULL)) {
320 return NT_STATUS_REQUEST_NOT_ACCEPTED;
323 status = domain->query_user(domain, r->in.info);
327 NTSTATUS _wbint_LookupUserAliases(struct pipes_struct *p,
328 struct wbint_LookupUserAliases *r)
330 struct winbindd_domain *domain = wb_child_domain();
333 if (domain == NULL) {
334 return NT_STATUS_REQUEST_NOT_ACCEPTED;
337 status = wb_cache_lookup_useraliases(domain, p->mem_ctx,
338 r->in.sids->num_sids,
340 &r->out.rids->num_rids,
342 reset_cm_connection_on_error(domain, NULL, status);
346 NTSTATUS _wbint_LookupUserGroups(struct pipes_struct *p,
347 struct wbint_LookupUserGroups *r)
349 struct winbindd_domain *domain = wb_child_domain();
352 if (domain == NULL) {
353 return NT_STATUS_REQUEST_NOT_ACCEPTED;
356 status = wb_cache_lookup_usergroups(domain, p->mem_ctx, r->in.sid,
357 &r->out.sids->num_sids,
359 reset_cm_connection_on_error(domain, NULL, status);
363 NTSTATUS _wbint_QuerySequenceNumber(struct pipes_struct *p,
364 struct wbint_QuerySequenceNumber *r)
366 struct winbindd_domain *domain = wb_child_domain();
369 if (domain == NULL) {
370 return NT_STATUS_REQUEST_NOT_ACCEPTED;
373 status = wb_cache_sequence_number(domain, r->out.sequence);
374 reset_cm_connection_on_error(domain, NULL, status);
378 NTSTATUS _wbint_LookupGroupMembers(struct pipes_struct *p,
379 struct wbint_LookupGroupMembers *r)
381 struct winbindd_domain *domain = wb_child_domain();
382 uint32_t i, num_names;
383 struct dom_sid *sid_mem;
385 uint32_t *name_types;
388 if (domain == NULL) {
389 return NT_STATUS_REQUEST_NOT_ACCEPTED;
392 status = wb_cache_lookup_groupmem(domain, p->mem_ctx, r->in.sid,
393 r->in.type, &num_names, &sid_mem,
394 &names, &name_types);
395 reset_cm_connection_on_error(domain, NULL, status);
396 if (!NT_STATUS_IS_OK(status)) {
400 r->out.members->num_principals = num_names;
401 r->out.members->principals = talloc_array(
402 r->out.members, struct wbint_Principal, num_names);
403 if (r->out.members->principals == NULL) {
404 return NT_STATUS_NO_MEMORY;
407 for (i=0; i<num_names; i++) {
408 struct wbint_Principal *m = &r->out.members->principals[i];
409 sid_copy(&m->sid, &sid_mem[i]);
410 m->name = talloc_move(r->out.members->principals, &names[i]);
411 m->type = (enum lsa_SidType)name_types[i];
417 NTSTATUS _wbint_QueryGroupList(struct pipes_struct *p,
418 struct wbint_QueryGroupList *r)
420 TALLOC_CTX *frame = NULL;
421 struct winbindd_domain *domain = wb_child_domain();
423 uint32_t num_local_groups = 0;
424 struct wb_acct_info *local_groups = NULL;
425 uint32_t num_dom_groups = 0;
426 struct wb_acct_info *dom_groups = NULL;
428 uint64_t num_total = 0;
429 struct wbint_Principal *result;
430 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
431 bool include_local_groups = false;
433 if (domain == NULL) {
434 return NT_STATUS_REQUEST_NOT_ACCEPTED;
437 frame = talloc_stackframe();
439 switch (lp_server_role()) {
440 case ROLE_ACTIVE_DIRECTORY_DC:
441 if (domain->internal) {
443 * we want to include local groups
444 * for BUILTIN and WORKGROUP
446 include_local_groups = true;
451 * We might include local groups in more
452 * setups later, but that requires more work
458 if (include_local_groups) {
459 status = wb_cache_enum_local_groups(domain, frame,
462 reset_cm_connection_on_error(domain, NULL, status);
463 if (!NT_STATUS_IS_OK(status)) {
468 status = wb_cache_enum_dom_groups(domain, frame,
471 reset_cm_connection_on_error(domain, NULL, status);
472 if (!NT_STATUS_IS_OK(status)) {
476 num_total = num_local_groups + num_dom_groups;
477 if (num_total > UINT32_MAX) {
478 status = NT_STATUS_INTERNAL_ERROR;
482 result = talloc_array(frame, struct wbint_Principal, num_total);
483 if (result == NULL) {
484 status = NT_STATUS_NO_MEMORY;
488 for (i = 0; i < num_local_groups; i++) {
489 struct wb_acct_info *lg = &local_groups[i];
490 struct wbint_Principal *rg = &result[ti++];
492 sid_compose(&rg->sid, &domain->sid, lg->rid);
493 rg->type = SID_NAME_ALIAS;
494 rg->name = talloc_strdup(result, lg->acct_name);
495 if (rg->name == NULL) {
496 status = NT_STATUS_NO_MEMORY;
500 num_local_groups = 0;
502 for (i = 0; i < num_dom_groups; i++) {
503 struct wb_acct_info *dg = &dom_groups[i];
504 struct wbint_Principal *rg = &result[ti++];
506 sid_compose(&rg->sid, &domain->sid, dg->rid);
507 rg->type = SID_NAME_DOM_GRP;
508 rg->name = talloc_strdup(result, dg->acct_name);
509 if (rg->name == NULL) {
510 status = NT_STATUS_NO_MEMORY;
516 r->out.groups->num_principals = ti;
517 r->out.groups->principals = talloc_move(r->out.groups, &result);
519 status = NT_STATUS_OK;
525 NTSTATUS _wbint_QueryUserRidList(struct pipes_struct *p,
526 struct wbint_QueryUserRidList *r)
528 struct winbindd_domain *domain = wb_child_domain();
531 if (domain == NULL) {
532 return NT_STATUS_REQUEST_NOT_ACCEPTED;
536 * Right now this is overkill. We should add a backend call
537 * just querying the rids.
540 status = wb_cache_query_user_list(domain, p->mem_ctx,
542 reset_cm_connection_on_error(domain, NULL, status);
544 if (!NT_STATUS_IS_OK(status)) {
548 r->out.rids->num_rids = talloc_array_length(r->out.rids->rids);
553 NTSTATUS _wbint_DsGetDcName(struct pipes_struct *p, struct wbint_DsGetDcName *r)
555 struct winbindd_domain *domain = wb_child_domain();
556 struct rpc_pipe_client *netlogon_pipe;
557 struct netr_DsRGetDCNameInfo *dc_info;
560 unsigned int orig_timeout;
561 struct dcerpc_binding_handle *b;
563 bool try_dsrgetdcname = false;
565 if (domain == NULL) {
566 return dsgetdcname(p->mem_ctx, global_messaging_context(),
567 r->in.domain_name, r->in.domain_guid,
568 r->in.site_name ? r->in.site_name : "",
573 if (domain->active_directory) {
574 try_dsrgetdcname = true;
578 status = cm_connect_netlogon(domain, &netlogon_pipe);
580 reset_cm_connection_on_error(domain, NULL, status);
581 if (!NT_STATUS_IS_OK(status)) {
582 DEBUG(10, ("Can't contact the NETLOGON pipe\n"));
586 b = netlogon_pipe->binding_handle;
588 /* This call can take a long time - allow the server to time out.
589 35 seconds should do it. */
591 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
593 if (try_dsrgetdcname) {
594 status = dcerpc_netr_DsRGetDCName(b,
595 p->mem_ctx, domain->dcname,
596 r->in.domain_name, NULL, r->in.domain_guid,
597 r->in.flags, r->out.dc_info, &werr);
598 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(werr)) {
602 reset_cm_connection_on_error(domain, NULL, status))
607 try_dsrgetdcname = false;
612 * Fallback to less capable methods
615 dc_info = talloc_zero(r->out.dc_info, struct netr_DsRGetDCNameInfo);
616 if (dc_info == NULL) {
617 status = NT_STATUS_NO_MEMORY;
621 if (r->in.flags & DS_PDC_REQUIRED) {
622 status = dcerpc_netr_GetDcName(b,
623 p->mem_ctx, domain->dcname,
624 r->in.domain_name, &dc_info->dc_unc, &werr);
626 status = dcerpc_netr_GetAnyDCName(b,
627 p->mem_ctx, domain->dcname,
628 r->in.domain_name, &dc_info->dc_unc, &werr);
631 if (!retry && reset_cm_connection_on_error(domain, b, status)) {
635 if (!NT_STATUS_IS_OK(status)) {
636 DEBUG(10, ("dcerpc_netr_Get[Any]DCName failed: %s\n",
640 if (!W_ERROR_IS_OK(werr)) {
641 DEBUG(10, ("dcerpc_netr_Get[Any]DCName failed: %s\n",
643 status = werror_to_ntstatus(werr);
647 *r->out.dc_info = dc_info;
648 status = NT_STATUS_OK;
651 /* And restore our original timeout. */
652 rpccli_set_timeout(netlogon_pipe, orig_timeout);
657 NTSTATUS _wbint_LookupRids(struct pipes_struct *p, struct wbint_LookupRids *r)
659 struct winbindd_domain *domain = wb_child_domain();
662 enum lsa_SidType *types;
663 struct wbint_Principal *result;
667 if (domain == NULL) {
668 return NT_STATUS_REQUEST_NOT_ACCEPTED;
671 status = wb_cache_rids_to_names(domain, talloc_tos(), r->in.domain_sid,
672 r->in.rids->rids, r->in.rids->num_rids,
673 &domain_name, &names, &types);
674 reset_cm_connection_on_error(domain, NULL, status);
675 if (!NT_STATUS_IS_OK(status)) {
679 *r->out.domain_name = talloc_move(r->out.domain_name, &domain_name);
681 result = talloc_array(p->mem_ctx, struct wbint_Principal,
682 r->in.rids->num_rids);
683 if (result == NULL) {
684 return NT_STATUS_NO_MEMORY;
687 for (i=0; i<r->in.rids->num_rids; i++) {
688 sid_compose(&result[i].sid, r->in.domain_sid,
689 r->in.rids->rids[i]);
690 result[i].type = types[i];
691 result[i].name = talloc_move(result, &names[i]);
696 r->out.names->num_principals = r->in.rids->num_rids;
697 r->out.names->principals = result;
701 NTSTATUS _wbint_CheckMachineAccount(struct pipes_struct *p,
702 struct wbint_CheckMachineAccount *r)
704 struct winbindd_domain *domain;
708 domain = wb_child_domain();
709 if (domain == NULL) {
710 return NT_STATUS_REQUEST_NOT_ACCEPTED;
714 invalidate_cm_connection(domain);
715 domain->conn.netlogon_force_reauth = true;
718 struct rpc_pipe_client *netlogon_pipe = NULL;
719 struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
720 status = cm_connect_netlogon_secure(domain,
722 &netlogon_creds_ctx);
725 /* There is a race condition between fetching the trust account
726 password and the periodic machine password change. So it's
727 possible that the trust account password has been changed on us.
728 We are returned NT_STATUS_ACCESS_DENIED if this happens. */
730 #define MAX_RETRIES 3
732 if ((num_retries < MAX_RETRIES)
733 && NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
738 if (!NT_STATUS_IS_OK(status)) {
739 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
743 /* Pass back result code - zero for success, other values for
744 specific failures. */
746 DEBUG(3,("domain %s secret is %s\n", domain->name,
747 NT_STATUS_IS_OK(status) ? "good" : "bad"));
750 DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
751 ("Checking the trust account password for domain %s returned %s\n",
752 domain->name, nt_errstr(status)));
757 NTSTATUS _wbint_ChangeMachineAccount(struct pipes_struct *p,
758 struct wbint_ChangeMachineAccount *r)
760 struct messaging_context *msg_ctx = global_messaging_context();
761 struct winbindd_domain *domain;
763 struct rpc_pipe_client *netlogon_pipe = NULL;
764 struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
766 domain = wb_child_domain();
767 if (domain == NULL) {
768 return NT_STATUS_REQUEST_NOT_ACCEPTED;
771 status = cm_connect_netlogon_secure(domain,
773 &netlogon_creds_ctx);
774 if (!NT_STATUS_IS_OK(status)) {
775 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
779 status = trust_pw_change(netlogon_creds_ctx,
781 netlogon_pipe->binding_handle,
786 /* Pass back result code - zero for success, other values for
787 specific failures. */
789 DEBUG(3,("domain %s secret %s\n", domain->name,
790 NT_STATUS_IS_OK(status) ? "changed" : "unchanged"));
793 DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
794 ("Changing the trust account password for domain %s returned %s\n",
795 domain->name, nt_errstr(status)));
800 NTSTATUS _wbint_PingDc(struct pipes_struct *p, struct wbint_PingDc *r)
803 struct winbindd_domain *domain;
804 struct rpc_pipe_client *netlogon_pipe;
805 union netr_CONTROL_QUERY_INFORMATION info;
807 fstring logon_server;
808 struct dcerpc_binding_handle *b;
811 domain = wb_child_domain();
812 if (domain == NULL) {
813 return NT_STATUS_REQUEST_NOT_ACCEPTED;
817 status = cm_connect_netlogon(domain, &netlogon_pipe);
818 reset_cm_connection_on_error(domain, NULL, status);
819 if (!NT_STATUS_IS_OK(status)) {
820 DEBUG(3, ("could not open handle to NETLOGON pipe: %s\n",
825 b = netlogon_pipe->binding_handle;
827 fstr_sprintf(logon_server, "\\\\%s", domain->dcname);
828 *r->out.dcname = talloc_strdup(p->mem_ctx, domain->dcname);
829 if (*r->out.dcname == NULL) {
830 DEBUG(2, ("Could not allocate memory\n"));
831 return NT_STATUS_NO_MEMORY;
835 * This provokes a WERR_NOT_SUPPORTED error message. This is
836 * documented in the wspp docs. I could not get a successful
837 * call to work, but the main point here is testing that the
838 * netlogon pipe works.
840 status = dcerpc_netr_LogonControl(b, p->mem_ctx,
841 logon_server, NETLOGON_CONTROL_QUERY,
844 if (!retry && reset_cm_connection_on_error(domain, b, status)) {
849 if (!NT_STATUS_IS_OK(status)) {
850 DEBUG(2, ("dcerpc_netr_LogonControl failed: %s\n",
855 if (!W_ERROR_EQUAL(werr, WERR_NOT_SUPPORTED)) {
856 DEBUG(2, ("dcerpc_netr_LogonControl returned %s, expected "
857 "WERR_NOT_SUPPORTED\n",
859 return werror_to_ntstatus(werr);
862 DEBUG(5, ("winbindd_dual_ping_dc succeeded\n"));
866 NTSTATUS _winbind_DsrUpdateReadOnlyServerDnsRecords(struct pipes_struct *p,
867 struct winbind_DsrUpdateReadOnlyServerDnsRecords *r)
869 struct winbindd_domain *domain;
871 struct rpc_pipe_client *netlogon_pipe = NULL;
872 struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
873 struct dcerpc_binding_handle *b = NULL;
876 domain = wb_child_domain();
877 if (domain == NULL) {
878 return NT_STATUS_REQUEST_NOT_ACCEPTED;
882 status = cm_connect_netlogon_secure(domain,
884 &netlogon_creds_ctx);
885 if (!NT_STATUS_IS_OK(status)) {
886 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
890 b = netlogon_pipe->binding_handle;
892 status = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(netlogon_creds_ctx,
893 netlogon_pipe->binding_handle,
898 if (!retry && reset_cm_connection_on_error(domain, b, status)) {
903 /* Pass back result code - zero for success, other values for
904 specific failures. */
906 DEBUG(3,("DNS records for domain %s %s\n", domain->name,
907 NT_STATUS_IS_OK(status) ? "changed" : "unchanged"));
910 DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
911 ("Update of DNS records via RW DC %s returned %s\n",
912 domain->name, nt_errstr(status)));
917 NTSTATUS _winbind_SamLogon(struct pipes_struct *p,
918 struct winbind_SamLogon *r)
920 struct winbindd_domain *domain;
922 struct netr_IdentityInfo *identity_info = NULL;
923 const uint8_t chal_zero[8] = {0, };
924 const uint8_t *challenge = chal_zero;
925 DATA_BLOB lm_response, nt_response;
927 uint16_t validation_level;
928 union netr_Validation *validation = NULL;
929 bool interactive = false;
931 domain = wb_child_domain();
932 if (domain == NULL) {
933 return NT_STATUS_REQUEST_NOT_ACCEPTED;
936 switch (r->in.validation_level) {
941 return NT_STATUS_REQUEST_NOT_ACCEPTED;
944 switch (r->in.logon_level) {
945 case NetlogonInteractiveInformation:
946 case NetlogonServiceInformation:
947 case NetlogonInteractiveTransitiveInformation:
948 case NetlogonServiceTransitiveInformation:
949 if (r->in.logon.password == NULL) {
950 return NT_STATUS_REQUEST_NOT_ACCEPTED;
954 identity_info = &r->in.logon.password->identity_info;
956 challenge = chal_zero;
957 lm_response = data_blob_talloc(p->mem_ctx,
958 r->in.logon.password->lmpassword.hash,
959 sizeof(r->in.logon.password->lmpassword.hash));
960 nt_response = data_blob_talloc(p->mem_ctx,
961 r->in.logon.password->ntpassword.hash,
962 sizeof(r->in.logon.password->ntpassword.hash));
965 case NetlogonNetworkInformation:
966 case NetlogonNetworkTransitiveInformation:
967 if (r->in.logon.network == NULL) {
968 return NT_STATUS_REQUEST_NOT_ACCEPTED;
972 identity_info = &r->in.logon.network->identity_info;
974 challenge = r->in.logon.network->challenge;
975 lm_response = data_blob_talloc(p->mem_ctx,
976 r->in.logon.network->lm.data,
977 r->in.logon.network->lm.length);
978 nt_response = data_blob_talloc(p->mem_ctx,
979 r->in.logon.network->nt.data,
980 r->in.logon.network->nt.length);
983 case NetlogonGenericInformation:
984 if (r->in.logon.generic == NULL) {
985 return NT_STATUS_REQUEST_NOT_ACCEPTED;
988 identity_info = &r->in.logon.generic->identity_info;
990 * Not implemented here...
992 return NT_STATUS_REQUEST_NOT_ACCEPTED;
995 return NT_STATUS_REQUEST_NOT_ACCEPTED;
998 status = winbind_dual_SamLogon(domain, p->mem_ctx,
1000 identity_info->parameter_control,
1001 identity_info->account_name.string,
1002 identity_info->domain_name.string,
1003 identity_info->workstation.string,
1005 lm_response, nt_response,
1006 &r->out.authoritative,
1007 true, /* skip_sam */
1011 if (!NT_STATUS_IS_OK(status)) {
1014 switch (r->in.validation_level) {
1016 status = map_validation_to_info3(p->mem_ctx,
1019 &r->out.validation.sam3);
1020 TALLOC_FREE(validation);
1021 if (!NT_STATUS_IS_OK(status)) {
1024 return NT_STATUS_OK;
1026 status = map_validation_to_info6(p->mem_ctx,
1029 &r->out.validation.sam6);
1030 TALLOC_FREE(validation);
1031 if (!NT_STATUS_IS_OK(status)) {
1034 return NT_STATUS_OK;
1037 smb_panic(__location__);
1038 return NT_STATUS_INTERNAL_ERROR;
1041 static WERROR _winbind_LogonControl_REDISCOVER(struct pipes_struct *p,
1042 struct winbindd_domain *domain,
1043 struct winbind_LogonControl *r)
1046 struct rpc_pipe_client *netlogon_pipe = NULL;
1047 struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
1048 struct netr_NETLOGON_INFO_2 *info2 = NULL;
1049 WERROR check_result = WERR_INTERNAL_ERROR;
1051 info2 = talloc_zero(p->mem_ctx, struct netr_NETLOGON_INFO_2);
1052 if (info2 == NULL) {
1053 return WERR_NOT_ENOUGH_MEMORY;
1056 if (domain->internal) {
1057 check_result = WERR_OK;
1062 * For now we just force a reconnect
1064 * TODO: take care of the optional '\dcname'
1066 invalidate_cm_connection(domain);
1067 domain->conn.netlogon_force_reauth = true;
1068 status = cm_connect_netlogon_secure(domain,
1070 &netlogon_creds_ctx);
1071 reset_cm_connection_on_error(domain, NULL, status);
1072 if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1073 status = NT_STATUS_NO_LOGON_SERVERS;
1075 if (!NT_STATUS_IS_OK(status)) {
1076 DEBUG(2, ("%s: domain[%s/%s] cm_connect_netlogon() returned %s\n",
1077 __func__, domain->name, domain->alt_name,
1078 nt_errstr(status)));
1080 * Here we return a top level error!
1081 * This is different than TC_QUERY or TC_VERIFY.
1083 return ntstatus_to_werror(status);
1085 check_result = WERR_OK;
1088 info2->pdc_connection_status = WERR_OK;
1089 if (domain->dcname != NULL) {
1090 info2->flags |= NETLOGON_HAS_IP;
1091 info2->flags |= NETLOGON_HAS_TIMESERV;
1092 info2->trusted_dc_name = talloc_asprintf(info2, "\\\\%s",
1094 if (info2->trusted_dc_name == NULL) {
1095 return WERR_NOT_ENOUGH_MEMORY;
1098 info2->trusted_dc_name = talloc_strdup(info2, "");
1099 if (info2->trusted_dc_name == NULL) {
1100 return WERR_NOT_ENOUGH_MEMORY;
1103 info2->tc_connection_status = check_result;
1105 if (!W_ERROR_IS_OK(info2->pdc_connection_status)) {
1106 DEBUG(2, ("%s: domain[%s/%s] dcname[%s] "
1107 "pdc_connection[%s] tc_connection[%s]\n",
1108 __func__, domain->name, domain->alt_name,
1110 win_errstr(info2->pdc_connection_status),
1111 win_errstr(info2->tc_connection_status)));
1114 r->out.query->info2 = info2;
1116 DEBUG(5, ("%s: succeeded.\n", __func__));
1120 static WERROR _winbind_LogonControl_TC_QUERY(struct pipes_struct *p,
1121 struct winbindd_domain *domain,
1122 struct winbind_LogonControl *r)
1125 struct rpc_pipe_client *netlogon_pipe = NULL;
1126 struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
1127 struct netr_NETLOGON_INFO_2 *info2 = NULL;
1128 WERROR check_result = WERR_INTERNAL_ERROR;
1130 info2 = talloc_zero(p->mem_ctx, struct netr_NETLOGON_INFO_2);
1131 if (info2 == NULL) {
1132 return WERR_NOT_ENOUGH_MEMORY;
1135 if (domain->internal) {
1136 check_result = WERR_OK;
1140 status = cm_connect_netlogon_secure(domain,
1142 &netlogon_creds_ctx);
1143 reset_cm_connection_on_error(domain, NULL, status);
1144 if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1145 status = NT_STATUS_NO_LOGON_SERVERS;
1147 if (!NT_STATUS_IS_OK(status)) {
1148 DEBUG(3, ("could not open handle to NETLOGON pipe: %s\n",
1149 nt_errstr(status)));
1150 check_result = ntstatus_to_werror(status);
1153 check_result = WERR_OK;
1156 info2->pdc_connection_status = WERR_OK;
1157 if (domain->dcname != NULL) {
1158 info2->flags |= NETLOGON_HAS_IP;
1159 info2->flags |= NETLOGON_HAS_TIMESERV;
1160 info2->trusted_dc_name = talloc_asprintf(info2, "\\\\%s",
1162 if (info2->trusted_dc_name == NULL) {
1163 return WERR_NOT_ENOUGH_MEMORY;
1166 info2->trusted_dc_name = talloc_strdup(info2, "");
1167 if (info2->trusted_dc_name == NULL) {
1168 return WERR_NOT_ENOUGH_MEMORY;
1171 info2->tc_connection_status = check_result;
1173 if (!W_ERROR_IS_OK(info2->pdc_connection_status)) {
1174 DEBUG(2, ("%s: domain[%s/%s] dcname[%s] "
1175 "pdc_connection[%s] tc_connection[%s]\n",
1176 __func__, domain->name, domain->alt_name,
1178 win_errstr(info2->pdc_connection_status),
1179 win_errstr(info2->tc_connection_status)));
1182 r->out.query->info2 = info2;
1184 DEBUG(5, ("%s: succeeded.\n", __func__));
1188 static WERROR _winbind_LogonControl_TC_VERIFY(struct pipes_struct *p,
1189 struct winbindd_domain *domain,
1190 struct winbind_LogonControl *r)
1192 TALLOC_CTX *frame = talloc_stackframe();
1195 struct lsa_String trusted_domain_name = {};
1196 struct lsa_StringLarge trusted_domain_name_l = {};
1197 struct rpc_pipe_client *local_lsa_pipe = NULL;
1198 struct policy_handle local_lsa_policy = {};
1199 struct dcerpc_binding_handle *local_lsa = NULL;
1200 struct rpc_pipe_client *netlogon_pipe = NULL;
1201 struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
1202 struct cli_credentials *creds = NULL;
1203 struct samr_Password *cur_nt_hash = NULL;
1204 uint32_t trust_attributes = 0;
1205 struct samr_Password new_owf_password = {};
1207 struct samr_Password old_owf_password = {};
1209 const struct lsa_TrustDomainInfoInfoEx *local_tdo = NULL;
1210 bool fetch_fti = false;
1211 struct lsa_ForestTrustInformation *new_fti = NULL;
1212 struct netr_TrustInfo *trust_info = NULL;
1213 struct netr_NETLOGON_INFO_2 *info2 = NULL;
1214 struct dcerpc_binding_handle *b = NULL;
1215 WERROR check_result = WERR_INTERNAL_ERROR;
1216 WERROR verify_result = WERR_INTERNAL_ERROR;
1219 trusted_domain_name.string = domain->name;
1220 trusted_domain_name_l.string = domain->name;
1222 info2 = talloc_zero(p->mem_ctx, struct netr_NETLOGON_INFO_2);
1223 if (info2 == NULL) {
1225 return WERR_NOT_ENOUGH_MEMORY;
1228 if (domain->internal) {
1229 check_result = WERR_OK;
1233 status = pdb_get_trust_credentials(domain->name,
1237 if (NT_STATUS_IS_OK(status)) {
1238 cur_nt_hash = cli_credentials_get_nt_hash(creds, frame);
1242 if (!domain->primary) {
1243 union lsa_TrustedDomainInfo *tdi = NULL;
1245 status = open_internal_lsa_conn(frame, &local_lsa_pipe,
1247 if (!NT_STATUS_IS_OK(status)) {
1248 DEBUG(0,("%s:%s: open_internal_lsa_conn() failed - %s\n",
1249 __location__, __func__, nt_errstr(status)));
1251 return WERR_INTERNAL_ERROR;
1253 local_lsa = local_lsa_pipe->binding_handle;
1255 status = dcerpc_lsa_QueryTrustedDomainInfoByName(local_lsa, frame,
1257 &trusted_domain_name,
1258 LSA_TRUSTED_DOMAIN_INFO_INFO_EX,
1260 if (!NT_STATUS_IS_OK(status)) {
1261 DEBUG(0,("%s:%s: local_lsa.QueryTrustedDomainInfoByName(%s) failed - %s\n",
1262 __location__, __func__, domain->name, nt_errstr(status)));
1264 return WERR_INTERNAL_ERROR;
1266 if (NT_STATUS_EQUAL(result, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1267 DEBUG(1,("%s:%s: domain[%s] not found via LSA, might be removed already.\n",
1268 __location__, __func__, domain->name));
1270 return WERR_NO_SUCH_DOMAIN;
1272 if (!NT_STATUS_IS_OK(result)) {
1273 DEBUG(0,("%s:%s: local_lsa.QueryTrustedDomainInfoByName(%s) returned %s\n",
1274 __location__, __func__, domain->name, nt_errstr(result)));
1276 return WERR_INTERNAL_ERROR;
1279 DEBUG(0,("%s:%s: local_lsa.QueryTrustedDomainInfoByName() "
1280 "returned no trusted domain information\n",
1281 __location__, __func__));
1283 return WERR_INTERNAL_ERROR;
1286 local_tdo = &tdi->info_ex;
1287 trust_attributes = local_tdo->trust_attributes;
1290 if (trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1291 struct lsa_ForestTrustInformation *old_fti = NULL;
1293 status = dcerpc_lsa_lsaRQueryForestTrustInformation(local_lsa, frame,
1295 &trusted_domain_name,
1296 LSA_FOREST_TRUST_DOMAIN_INFO,
1298 if (!NT_STATUS_IS_OK(status)) {
1299 DEBUG(0,("%s:%s: local_lsa.lsaRQueryForestTrustInformation(%s) failed %s\n",
1300 __location__, __func__, domain->name, nt_errstr(status)));
1302 return WERR_INTERNAL_ERROR;
1304 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_FOUND)) {
1305 DEBUG(2,("%s: no forest trust information available for domain[%s] yet.\n",
1306 __func__, domain->name));
1309 result = NT_STATUS_OK;
1311 if (!NT_STATUS_IS_OK(result)) {
1312 DEBUG(0,("%s:%s: local_lsa.lsaRQueryForestTrustInformation(%s) returned %s\n",
1313 __location__, __func__, domain->name, nt_errstr(result)));
1315 return WERR_INTERNAL_ERROR;
1318 TALLOC_FREE(old_fti);
1322 status = cm_connect_netlogon_secure(domain,
1324 &netlogon_creds_ctx);
1325 reset_cm_connection_on_error(domain, NULL, status);
1326 if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1327 status = NT_STATUS_NO_LOGON_SERVERS;
1329 if (!NT_STATUS_IS_OK(status)) {
1330 DEBUG(3, ("could not open handle to NETLOGON pipe: %s\n",
1331 nt_errstr(status)));
1332 check_result = ntstatus_to_werror(status);
1335 check_result = WERR_OK;
1336 b = netlogon_pipe->binding_handle;
1338 if (cur_nt_hash == NULL) {
1339 verify_result = WERR_NO_TRUST_LSA_SECRET;
1344 status = netlogon_creds_cli_GetForestTrustInformation(netlogon_creds_ctx,
1347 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1348 status = NT_STATUS_NOT_SUPPORTED;
1350 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
1352 status = NT_STATUS_OK;
1354 if (!NT_STATUS_IS_OK(status)) {
1356 reset_cm_connection_on_error(domain, b, status))
1361 DEBUG(2, ("netlogon_creds_cli_GetForestTrustInformation(%s)"
1363 domain->name, nt_errstr(status)));
1364 check_result = ntstatus_to_werror(status);
1369 if (new_fti != NULL) {
1370 struct lsa_ForestTrustInformation old_fti = {};
1371 struct lsa_ForestTrustInformation *merged_fti = NULL;
1372 struct lsa_ForestTrustCollisionInfo *collision_info = NULL;
1374 status = dsdb_trust_merge_forest_info(frame, local_tdo,
1377 if (!NT_STATUS_IS_OK(status)) {
1378 DEBUG(0,("%s:%s: dsdb_trust_merge_forest_info(%s) failed %s\n",
1379 __location__, __func__,
1380 domain->name, nt_errstr(status)));
1382 return ntstatus_to_werror(status);
1385 status = dcerpc_lsa_lsaRSetForestTrustInformation(local_lsa, frame,
1387 &trusted_domain_name_l,
1388 LSA_FOREST_TRUST_DOMAIN_INFO,
1390 0, /* check_only=0 => store it! */
1393 if (!NT_STATUS_IS_OK(status)) {
1394 DEBUG(0,("%s:%s: local_lsa.lsaRSetForestTrustInformation(%s) failed %s\n",
1395 __location__, __func__, domain->name, nt_errstr(status)));
1397 return WERR_INTERNAL_ERROR;
1399 if (!NT_STATUS_IS_OK(result)) {
1400 DEBUG(0,("%s:%s: local_lsa.lsaRSetForestTrustInformation(%s) returned %s\n",
1401 __location__, __func__, domain->name, nt_errstr(result)));
1403 return ntstatus_to_werror(result);
1407 status = netlogon_creds_cli_ServerGetTrustInfo(netlogon_creds_ctx,
1412 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1413 status = NT_STATUS_NOT_SUPPORTED;
1415 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
1416 DEBUG(5, ("netlogon_creds_cli_ServerGetTrustInfo failed: %s\n",
1417 nt_errstr(status)));
1418 verify_result = WERR_OK;
1421 if (!NT_STATUS_IS_OK(status)) {
1422 if (!retry && reset_cm_connection_on_error(domain, b, status)) {
1426 DEBUG(2, ("netlogon_creds_cli_ServerGetTrustInfo failed: %s\n",
1427 nt_errstr(status)));
1429 if (!dcerpc_binding_handle_is_connected(b)) {
1430 check_result = ntstatus_to_werror(status);
1433 verify_result = ntstatus_to_werror(status);
1438 if (trust_info != NULL && trust_info->count >= 1) {
1439 uint32_t diff = trust_info->data[0] ^ trust_attributes;
1441 if (diff & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1442 verify_result = WERR_DOMAIN_TRUST_INCONSISTENT;
1447 cmp_new = memcmp(new_owf_password.hash,
1449 sizeof(cur_nt_hash->hash));
1450 cmp_old = memcmp(old_owf_password.hash,
1452 sizeof(cur_nt_hash->hash));
1453 if (cmp_new != 0 && cmp_old != 0) {
1454 DEBUG(1,("%s:Error: credentials for domain[%s/%s] doesn't match "
1455 "any password known to dcname[%s]\n",
1456 __func__, domain->name, domain->alt_name,
1458 verify_result = WERR_WRONG_PASSWORD;
1463 DEBUG(2,("%s:Warning: credentials for domain[%s/%s] only match "
1464 "against the old password known to dcname[%s]\n",
1465 __func__, domain->name, domain->alt_name,
1469 verify_result = WERR_OK;
1473 verify_result = check_result;
1475 info2->flags |= NETLOGON_VERIFY_STATUS_RETURNED;
1476 info2->pdc_connection_status = verify_result;
1477 if (domain->dcname != NULL) {
1478 info2->flags |= NETLOGON_HAS_IP;
1479 info2->flags |= NETLOGON_HAS_TIMESERV;
1480 info2->trusted_dc_name = talloc_asprintf(info2, "\\\\%s",
1482 if (info2->trusted_dc_name == NULL) {
1484 return WERR_NOT_ENOUGH_MEMORY;
1487 info2->trusted_dc_name = talloc_strdup(info2, "");
1488 if (info2->trusted_dc_name == NULL) {
1490 return WERR_NOT_ENOUGH_MEMORY;
1493 info2->tc_connection_status = check_result;
1495 if (!W_ERROR_IS_OK(info2->pdc_connection_status)) {
1496 DEBUG(2, ("%s: domain[%s/%s] dcname[%s] "
1497 "pdc_connection[%s] tc_connection[%s]\n",
1498 __func__, domain->name, domain->alt_name,
1500 win_errstr(info2->pdc_connection_status),
1501 win_errstr(info2->tc_connection_status)));
1504 r->out.query->info2 = info2;
1506 DEBUG(5, ("%s: succeeded.\n", __func__));
1511 static WERROR _winbind_LogonControl_CHANGE_PASSWORD(struct pipes_struct *p,
1512 struct winbindd_domain *domain,
1513 struct winbind_LogonControl *r)
1515 struct messaging_context *msg_ctx = global_messaging_context();
1517 struct rpc_pipe_client *netlogon_pipe = NULL;
1518 struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
1519 struct cli_credentials *creds = NULL;
1520 struct samr_Password *cur_nt_hash = NULL;
1521 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1522 struct dcerpc_binding_handle *b;
1523 WERROR change_result = WERR_OK;
1526 info1 = talloc_zero(p->mem_ctx, struct netr_NETLOGON_INFO_1);
1527 if (info1 == NULL) {
1528 return WERR_NOT_ENOUGH_MEMORY;
1531 if (domain->internal) {
1532 return WERR_NOT_SUPPORTED;
1535 status = pdb_get_trust_credentials(domain->name,
1539 if (NT_STATUS_IS_OK(status)) {
1540 cur_nt_hash = cli_credentials_get_nt_hash(creds, p->mem_ctx);
1545 status = cm_connect_netlogon_secure(domain,
1547 &netlogon_creds_ctx);
1548 reset_cm_connection_on_error(domain, NULL, status);
1549 if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1550 status = NT_STATUS_NO_LOGON_SERVERS;
1552 if (!NT_STATUS_IS_OK(status)) {
1553 DEBUG(2, ("%s: domain[%s/%s] cm_connect_netlogon() returned %s\n",
1554 __func__, domain->name, domain->alt_name,
1555 nt_errstr(status)));
1557 * Here we return a top level error!
1558 * This is different than TC_QUERY or TC_VERIFY.
1560 return ntstatus_to_werror(status);
1562 b = netlogon_pipe->binding_handle;
1564 if (cur_nt_hash == NULL) {
1565 change_result = WERR_NO_TRUST_LSA_SECRET;
1568 TALLOC_FREE(cur_nt_hash);
1570 status = trust_pw_change(netlogon_creds_ctx,
1571 msg_ctx, b, domain->name,
1574 if (!NT_STATUS_IS_OK(status)) {
1575 if (!retry && reset_cm_connection_on_error(domain, b, status)) {
1580 DEBUG(1, ("trust_pw_change(%s): %s\n",
1581 domain->name, nt_errstr(status)));
1583 change_result = ntstatus_to_werror(status);
1587 change_result = WERR_OK;
1590 info1->pdc_connection_status = change_result;
1592 if (!W_ERROR_IS_OK(info1->pdc_connection_status)) {
1593 DEBUG(2, ("%s: domain[%s/%s] dcname[%s] "
1594 "pdc_connection[%s]\n",
1595 __func__, domain->name, domain->alt_name,
1597 win_errstr(info1->pdc_connection_status)));
1600 r->out.query->info1 = info1;
1602 DEBUG(5, ("%s: succeeded.\n", __func__));
1606 WERROR _winbind_LogonControl(struct pipes_struct *p,
1607 struct winbind_LogonControl *r)
1609 struct winbindd_domain *domain;
1611 domain = wb_child_domain();
1612 if (domain == NULL) {
1613 return WERR_NO_SUCH_DOMAIN;
1616 switch (r->in.function_code) {
1617 case NETLOGON_CONTROL_REDISCOVER:
1618 if (r->in.level != 2) {
1619 return WERR_INVALID_PARAMETER;
1621 return _winbind_LogonControl_REDISCOVER(p, domain, r);
1622 case NETLOGON_CONTROL_TC_QUERY:
1623 if (r->in.level != 2) {
1624 return WERR_INVALID_PARAMETER;
1626 return _winbind_LogonControl_TC_QUERY(p, domain, r);
1627 case NETLOGON_CONTROL_TC_VERIFY:
1628 if (r->in.level != 2) {
1629 return WERR_INVALID_PARAMETER;
1631 return _winbind_LogonControl_TC_VERIFY(p, domain, r);
1632 case NETLOGON_CONTROL_CHANGE_PASSWORD:
1633 if (r->in.level != 1) {
1634 return WERR_INVALID_PARAMETER;
1636 return _winbind_LogonControl_CHANGE_PASSWORD(p, domain, r);
1641 DEBUG(4, ("%s: function_code[0x%x] not supported\n",
1642 __func__, r->in.function_code));
1643 return WERR_NOT_SUPPORTED;
1646 WERROR _winbind_GetForestTrustInformation(struct pipes_struct *p,
1647 struct winbind_GetForestTrustInformation *r)
1649 TALLOC_CTX *frame = talloc_stackframe();
1650 NTSTATUS status, result;
1651 struct winbindd_domain *domain;
1652 struct rpc_pipe_client *netlogon_pipe = NULL;
1653 struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
1654 struct dcerpc_binding_handle *b;
1656 struct lsa_String trusted_domain_name = {};
1657 struct lsa_StringLarge trusted_domain_name_l = {};
1658 union lsa_TrustedDomainInfo *tdi = NULL;
1659 const struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
1660 struct lsa_ForestTrustInformation _old_fti = {};
1661 struct lsa_ForestTrustInformation *old_fti = NULL;
1662 struct lsa_ForestTrustInformation *new_fti = NULL;
1663 struct lsa_ForestTrustInformation *merged_fti = NULL;
1664 struct lsa_ForestTrustCollisionInfo *collision_info = NULL;
1665 bool update_fti = false;
1666 struct rpc_pipe_client *local_lsa_pipe;
1667 struct policy_handle local_lsa_policy;
1668 struct dcerpc_binding_handle *local_lsa = NULL;
1670 domain = wb_child_domain();
1671 if (domain == NULL) {
1673 return WERR_NO_SUCH_DOMAIN;
1677 * checking for domain->internal and domain->primary
1678 * makes sure we only do some work when running as DC.
1681 if (domain->internal) {
1683 return WERR_NO_SUCH_DOMAIN;
1686 if (domain->primary) {
1688 return WERR_NO_SUCH_DOMAIN;
1691 trusted_domain_name.string = domain->name;
1692 trusted_domain_name_l.string = domain->name;
1694 status = open_internal_lsa_conn(frame, &local_lsa_pipe,
1696 if (!NT_STATUS_IS_OK(status)) {
1697 DEBUG(0,("%s:%s: open_internal_lsa_conn() failed - %s\n",
1698 __location__, __func__, nt_errstr(status)));
1700 return WERR_INTERNAL_ERROR;
1702 local_lsa = local_lsa_pipe->binding_handle;
1704 status = dcerpc_lsa_QueryTrustedDomainInfoByName(local_lsa, frame,
1706 &trusted_domain_name,
1707 LSA_TRUSTED_DOMAIN_INFO_INFO_EX,
1709 if (!NT_STATUS_IS_OK(status)) {
1710 DEBUG(0,("%s:%s: local_lsa.QueryTrustedDomainInfoByName(%s) failed - %s\n",
1711 __location__, __func__, domain->name, nt_errstr(status)));
1713 return WERR_INTERNAL_ERROR;
1715 if (NT_STATUS_EQUAL(result, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1716 DEBUG(1,("%s:%s: domain[%s] not found via LSA, might be removed already.\n",
1717 __location__, __func__, domain->name));
1719 return WERR_NO_SUCH_DOMAIN;
1721 if (!NT_STATUS_IS_OK(result)) {
1722 DEBUG(0,("%s:%s: local_lsa.QueryTrustedDomainInfoByName(%s) returned %s\n",
1723 __location__, __func__, domain->name, nt_errstr(result)));
1725 return WERR_INTERNAL_ERROR;
1728 DEBUG(0,("%s:%s: local_lsa.QueryTrustedDomainInfoByName() "
1729 "returned no trusted domain information\n",
1730 __location__, __func__));
1732 return WERR_INTERNAL_ERROR;
1735 tdo = &tdi->info_ex;
1737 if (!(tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
1738 DEBUG(2,("%s: tdo[%s/%s] is no forest trust attributes[0x%08X]\n",
1739 __func__, tdo->netbios_name.string,
1740 tdo->domain_name.string,
1741 (unsigned)tdo->trust_attributes));
1743 return WERR_NO_SUCH_DOMAIN;
1746 if (r->in.flags & ~DS_GFTI_UPDATE_TDO) {
1748 return WERR_INVALID_FLAGS;
1752 status = cm_connect_netlogon_secure(domain,
1754 &netlogon_creds_ctx);
1755 reset_cm_connection_on_error(domain, NULL, status);
1756 if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1757 status = NT_STATUS_NO_LOGON_SERVERS;
1759 if (!NT_STATUS_IS_OK(status)) {
1760 DEBUG(3, ("could not open handle to NETLOGON pipe: %s\n",
1761 nt_errstr(status)));
1763 return ntstatus_to_werror(status);
1765 b = netlogon_pipe->binding_handle;
1767 status = netlogon_creds_cli_GetForestTrustInformation(netlogon_creds_ctx,
1770 if (!NT_STATUS_IS_OK(status)) {
1771 if (!retry && reset_cm_connection_on_error(domain, b, status)) {
1775 DEBUG(2, ("netlogon_creds_cli_GetForestTrustInformation(%s) failed: %s\n",
1776 domain->name, nt_errstr(status)));
1778 return ntstatus_to_werror(status);
1781 *r->out.forest_trust_info = new_fti;
1783 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
1787 status = dcerpc_lsa_lsaRQueryForestTrustInformation(local_lsa, frame,
1789 &trusted_domain_name,
1790 LSA_FOREST_TRUST_DOMAIN_INFO,
1792 if (!NT_STATUS_IS_OK(status)) {
1793 DEBUG(0,("%s:%s: local_lsa.lsaRQueryForestTrustInformation(%s) failed %s\n",
1794 __location__, __func__, domain->name, nt_errstr(status)));
1796 return WERR_INTERNAL_ERROR;
1798 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_FOUND)) {
1799 DEBUG(2,("%s: no forest trust information available for domain[%s] yet.\n",
1800 __func__, domain->name));
1802 old_fti = &_old_fti;
1803 result = NT_STATUS_OK;
1805 if (!NT_STATUS_IS_OK(result)) {
1806 DEBUG(0,("%s:%s: local_lsa.lsaRQueryForestTrustInformation(%s) returned %s\n",
1807 __location__, __func__, domain->name, nt_errstr(result)));
1809 return WERR_INTERNAL_ERROR;
1812 if (old_fti == NULL) {
1813 DEBUG(0,("%s:%s: local_lsa.lsaRQueryForestTrustInformation() "
1814 "returned success without returning forest trust information\n",
1815 __location__, __func__));
1817 return WERR_INTERNAL_ERROR;
1824 status = dsdb_trust_merge_forest_info(frame, tdo, old_fti, new_fti,
1826 if (!NT_STATUS_IS_OK(status)) {
1827 DEBUG(0,("%s:%s: dsdb_trust_merge_forest_info(%s) failed %s\n",
1828 __location__, __func__, domain->name, nt_errstr(status)));
1830 return ntstatus_to_werror(status);
1833 status = dcerpc_lsa_lsaRSetForestTrustInformation(local_lsa, frame,
1835 &trusted_domain_name_l,
1836 LSA_FOREST_TRUST_DOMAIN_INFO,
1838 0, /* check_only=0 => store it! */
1841 if (!NT_STATUS_IS_OK(status)) {
1842 DEBUG(0,("%s:%s: local_lsa.lsaRSetForestTrustInformation(%s) failed %s\n",
1843 __location__, __func__, domain->name, nt_errstr(status)));
1845 return WERR_INTERNAL_ERROR;
1847 if (!NT_STATUS_IS_OK(result)) {
1848 DEBUG(0,("%s:%s: local_lsa.lsaRSetForestTrustInformation(%s) returned %s\n",
1849 __location__, __func__, domain->name, nt_errstr(result)));
1851 return ntstatus_to_werror(result);
1855 DEBUG(5, ("_winbind_GetForestTrustInformation succeeded\n"));
1860 NTSTATUS _winbind_SendToSam(struct pipes_struct *p, struct winbind_SendToSam *r)
1862 struct winbindd_domain *domain;
1864 struct rpc_pipe_client *netlogon_pipe;
1865 struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
1866 struct dcerpc_binding_handle *b = NULL;
1869 DEBUG(5, ("_winbind_SendToSam received\n"));
1870 domain = wb_child_domain();
1871 if (domain == NULL) {
1872 return NT_STATUS_REQUEST_NOT_ACCEPTED;
1876 status = cm_connect_netlogon_secure(domain,
1878 &netlogon_creds_ctx);
1879 reset_cm_connection_on_error(domain, NULL, status);
1880 if (!NT_STATUS_IS_OK(status)) {
1881 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
1885 b = netlogon_pipe->binding_handle;
1887 status = netlogon_creds_cli_SendToSam(netlogon_creds_ctx,
1890 if (!retry && reset_cm_connection_on_error(domain, b, status)) {