auth: Explain why GSS_KRB5_CRED_NO_CI_FLAGS_X is needed
[Samba.git] / source3 / winbindd / winbindd_dual_srv.c
blob97d8a1b3e890ee8ff99f74e4fd20bdcf7865b655
1 /*
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/>.
23 #include "includes.h"
24 #include "winbindd/winbindd.h"
25 #include "winbindd/winbindd_proto.h"
26 #include "rpc_client/cli_pipe.h"
27 #include "ntdomain.h"
28 #include "librpc/gen_ndr/srv_winbind.h"
29 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
30 #include "idmap.h"
31 #include "../libcli/security/security.h"
32 #include "../libcli/auth/netlogon_creds_cli.h"
34 void _wbint_Ping(struct pipes_struct *p, struct wbint_Ping *r)
36 *r->out.out_data = r->in.in_data;
39 static bool reset_cm_connection_on_error(struct winbindd_domain *domain,
40 NTSTATUS status)
42 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
43 invalidate_cm_connection(domain);
44 /* We invalidated the connection. */
45 return true;
47 return false;
50 NTSTATUS _wbint_LookupSid(struct pipes_struct *p, struct wbint_LookupSid *r)
52 struct winbindd_domain *domain = wb_child_domain();
53 char *dom_name;
54 char *name;
55 enum lsa_SidType type;
56 NTSTATUS status;
58 if (domain == NULL) {
59 return NT_STATUS_REQUEST_NOT_ACCEPTED;
62 status = domain->methods->sid_to_name(domain, p->mem_ctx, r->in.sid,
63 &dom_name, &name, &type);
64 reset_cm_connection_on_error(domain, status);
65 if (!NT_STATUS_IS_OK(status)) {
66 return status;
69 *r->out.domain = dom_name;
70 *r->out.name = name;
71 *r->out.type = type;
72 return NT_STATUS_OK;
75 NTSTATUS _wbint_LookupSids(struct pipes_struct *p, struct wbint_LookupSids *r)
77 struct winbindd_domain *domain = wb_child_domain();
78 struct lsa_RefDomainList *domains = r->out.domains;
79 NTSTATUS status;
81 if (domain == NULL) {
82 return NT_STATUS_REQUEST_NOT_ACCEPTED;
86 * This breaks the winbindd_domain->methods abstraction: This
87 * is only called for remote domains, and both winbindd_msrpc
88 * and winbindd_ad call into lsa_lookupsids anyway. Caching is
89 * done at the wbint RPC layer.
91 status = rpc_lookup_sids(p->mem_ctx, domain, r->in.sids,
92 &domains, &r->out.names);
94 if (domains != NULL) {
95 r->out.domains = domains;
98 reset_cm_connection_on_error(domain, status);
99 return status;
102 NTSTATUS _wbint_LookupName(struct pipes_struct *p, struct wbint_LookupName *r)
104 struct winbindd_domain *domain = wb_child_domain();
105 NTSTATUS status;
107 if (domain == NULL) {
108 return NT_STATUS_REQUEST_NOT_ACCEPTED;
111 status = domain->methods->name_to_sid(
112 domain, p->mem_ctx, r->in.domain, r->in.name, r->in.flags,
113 r->out.sid, r->out.type);
114 reset_cm_connection_on_error(domain, status);
115 return status;
118 NTSTATUS _wbint_Sids2UnixIDs(struct pipes_struct *p,
119 struct wbint_Sids2UnixIDs *r)
121 uint32_t i, j;
122 struct id_map *ids = NULL;
123 struct id_map **id_ptrs = NULL;
124 struct dom_sid *sids = NULL;
125 uint32_t *id_idx = NULL;
126 NTSTATUS status = NT_STATUS_NO_MEMORY;
128 for (i=0; i<r->in.domains->count; i++) {
129 struct lsa_DomainInfo *d = &r->in.domains->domains[i];
130 struct idmap_domain *dom;
131 uint32_t num_ids;
133 dom = idmap_find_domain_with_sid(d->name.string, d->sid);
134 if (dom == NULL) {
135 DEBUG(10, ("idmap domain %s:%s not found\n",
136 d->name.string, sid_string_dbg(d->sid)));
137 continue;
140 num_ids = 0;
142 for (j=0; j<r->in.ids->num_ids; j++) {
143 if (r->in.ids->ids[j].domain_index == i) {
144 num_ids += 1;
148 ids = talloc_realloc(talloc_tos(), ids,
149 struct id_map, num_ids);
150 if (ids == NULL) {
151 goto nomem;
153 id_ptrs = talloc_realloc(talloc_tos(), id_ptrs,
154 struct id_map *, num_ids+1);
155 if (id_ptrs == NULL) {
156 goto nomem;
158 id_idx = talloc_realloc(talloc_tos(), id_idx,
159 uint32_t, num_ids);
160 if (id_idx == NULL) {
161 goto nomem;
163 sids = talloc_realloc(talloc_tos(), sids,
164 struct dom_sid, num_ids);
165 if (sids == NULL) {
166 goto nomem;
169 num_ids = 0;
172 * Convert the input data into a list of
173 * id_map structs suitable for handing in
174 * to the idmap sids_to_unixids method.
176 for (j=0; j<r->in.ids->num_ids; j++) {
177 struct wbint_TransID *id = &r->in.ids->ids[j];
179 if (id->domain_index != i) {
180 continue;
182 id_idx[num_ids] = j;
183 id_ptrs[num_ids] = &ids[num_ids];
185 ids[num_ids].sid = &sids[num_ids];
186 sid_compose(ids[num_ids].sid, d->sid, id->rid);
187 ids[num_ids].xid.type = id->type;
188 ids[num_ids].status = ID_UNKNOWN;
189 num_ids += 1;
191 id_ptrs[num_ids] = NULL;
193 status = dom->methods->sids_to_unixids(dom, id_ptrs);
194 DEBUG(10, ("sids_to_unixids returned %s\n",
195 nt_errstr(status)));
198 * Extract the results for handing them back to the caller.
200 for (j=0; j<num_ids; j++) {
201 struct wbint_TransID *id = &r->in.ids->ids[id_idx[j]];
203 if (ids[j].status != ID_MAPPED) {
204 id->xid.id = UINT32_MAX;
205 id->xid.type = ID_TYPE_NOT_SPECIFIED;
206 continue;
209 id->xid = ids[j].xid;
212 status = NT_STATUS_OK;
213 nomem:
214 TALLOC_FREE(ids);
215 TALLOC_FREE(id_ptrs);
216 TALLOC_FREE(id_idx);
217 TALLOC_FREE(sids);
218 return status;
221 NTSTATUS _wbint_Uid2Sid(struct pipes_struct *p, struct wbint_Uid2Sid *r)
223 return idmap_uid_to_sid(r->in.dom_name ? r->in.dom_name : "",
224 r->out.sid, r->in.uid);
227 NTSTATUS _wbint_Gid2Sid(struct pipes_struct *p, struct wbint_Gid2Sid *r)
229 return idmap_gid_to_sid(r->in.dom_name ? r->in.dom_name : "",
230 r->out.sid, r->in.gid);
233 NTSTATUS _wbint_AllocateUid(struct pipes_struct *p, struct wbint_AllocateUid *r)
235 struct unixid xid;
236 NTSTATUS status;
238 status = idmap_allocate_uid(&xid);
239 if (!NT_STATUS_IS_OK(status)) {
240 return status;
242 *r->out.uid = xid.id;
243 return NT_STATUS_OK;
246 NTSTATUS _wbint_AllocateGid(struct pipes_struct *p, struct wbint_AllocateGid *r)
248 struct unixid xid;
249 NTSTATUS status;
251 status = idmap_allocate_gid(&xid);
252 if (!NT_STATUS_IS_OK(status)) {
253 return status;
255 *r->out.gid = xid.id;
256 return NT_STATUS_OK;
259 NTSTATUS _wbint_QueryUser(struct pipes_struct *p, struct wbint_QueryUser *r)
261 struct winbindd_domain *domain = wb_child_domain();
262 NTSTATUS status;
264 if (domain == NULL) {
265 return NT_STATUS_REQUEST_NOT_ACCEPTED;
268 status = domain->methods->query_user(domain, p->mem_ctx, r->in.sid,
269 r->out.info);
270 reset_cm_connection_on_error(domain, status);
271 return status;
274 NTSTATUS _wbint_LookupUserAliases(struct pipes_struct *p,
275 struct wbint_LookupUserAliases *r)
277 struct winbindd_domain *domain = wb_child_domain();
278 NTSTATUS status;
280 if (domain == NULL) {
281 return NT_STATUS_REQUEST_NOT_ACCEPTED;
284 status = domain->methods->lookup_useraliases(
285 domain, p->mem_ctx, r->in.sids->num_sids, r->in.sids->sids,
286 &r->out.rids->num_rids, &r->out.rids->rids);
287 reset_cm_connection_on_error(domain, status);
288 return status;
291 NTSTATUS _wbint_LookupUserGroups(struct pipes_struct *p,
292 struct wbint_LookupUserGroups *r)
294 struct winbindd_domain *domain = wb_child_domain();
295 NTSTATUS status;
297 if (domain == NULL) {
298 return NT_STATUS_REQUEST_NOT_ACCEPTED;
301 status = domain->methods->lookup_usergroups(
302 domain, p->mem_ctx, r->in.sid,
303 &r->out.sids->num_sids, &r->out.sids->sids);
304 reset_cm_connection_on_error(domain, status);
305 return status;
308 NTSTATUS _wbint_QuerySequenceNumber(struct pipes_struct *p,
309 struct wbint_QuerySequenceNumber *r)
311 struct winbindd_domain *domain = wb_child_domain();
312 NTSTATUS status;
314 if (domain == NULL) {
315 return NT_STATUS_REQUEST_NOT_ACCEPTED;
318 status = domain->methods->sequence_number(domain, r->out.sequence);
319 reset_cm_connection_on_error(domain, status);
320 return status;
323 NTSTATUS _wbint_LookupGroupMembers(struct pipes_struct *p,
324 struct wbint_LookupGroupMembers *r)
326 struct winbindd_domain *domain = wb_child_domain();
327 uint32_t i, num_names;
328 struct dom_sid *sid_mem;
329 char **names;
330 uint32_t *name_types;
331 NTSTATUS status;
333 if (domain == NULL) {
334 return NT_STATUS_REQUEST_NOT_ACCEPTED;
337 status = domain->methods->lookup_groupmem(
338 domain, p->mem_ctx, r->in.sid, r->in.type,
339 &num_names, &sid_mem, &names, &name_types);
340 reset_cm_connection_on_error(domain, status);
341 if (!NT_STATUS_IS_OK(status)) {
342 return status;
345 r->out.members->num_principals = num_names;
346 r->out.members->principals = talloc_array(
347 r->out.members, struct wbint_Principal, num_names);
348 if (r->out.members->principals == NULL) {
349 return NT_STATUS_NO_MEMORY;
352 for (i=0; i<num_names; i++) {
353 struct wbint_Principal *m = &r->out.members->principals[i];
354 sid_copy(&m->sid, &sid_mem[i]);
355 m->name = talloc_move(r->out.members->principals, &names[i]);
356 m->type = (enum lsa_SidType)name_types[i];
359 return NT_STATUS_OK;
362 NTSTATUS _wbint_QueryUserList(struct pipes_struct *p,
363 struct wbint_QueryUserList *r)
365 struct winbindd_domain *domain = wb_child_domain();
366 NTSTATUS status;
368 if (domain == NULL) {
369 return NT_STATUS_REQUEST_NOT_ACCEPTED;
372 status = domain->methods->query_user_list(
373 domain, p->mem_ctx, &r->out.users->num_userinfos,
374 &r->out.users->userinfos);
375 reset_cm_connection_on_error(domain, status);
376 return status;
379 NTSTATUS _wbint_QueryGroupList(struct pipes_struct *p,
380 struct wbint_QueryGroupList *r)
382 struct winbindd_domain *domain = wb_child_domain();
383 uint32_t i;
384 uint32_t num_local_groups = 0;
385 struct wb_acct_info *local_groups = NULL;
386 uint32_t num_dom_groups = 0;
387 struct wb_acct_info *dom_groups = NULL;
388 uint32_t ti = 0;
389 uint64_t num_total = 0;
390 struct wbint_Principal *result;
391 NTSTATUS status;
392 bool include_local_groups = false;
394 if (domain == NULL) {
395 return NT_STATUS_REQUEST_NOT_ACCEPTED;
398 switch (lp_server_role()) {
399 case ROLE_ACTIVE_DIRECTORY_DC:
400 if (domain->internal) {
402 * we want to include local groups
403 * for BUILTIN and WORKGROUP
405 include_local_groups = true;
407 break;
408 default:
410 * We might include local groups in more
411 * setups later, but that requires more work
412 * elsewhere.
414 break;
417 if (include_local_groups) {
418 status = domain->methods->enum_local_groups(domain, talloc_tos(),
419 &num_local_groups,
420 &local_groups);
421 reset_cm_connection_on_error(domain, status);
422 if (!NT_STATUS_IS_OK(status)) {
423 return status;
427 status = domain->methods->enum_dom_groups(domain, talloc_tos(),
428 &num_dom_groups,
429 &dom_groups);
430 reset_cm_connection_on_error(domain, status);
431 if (!NT_STATUS_IS_OK(status)) {
432 return status;
435 num_total = num_local_groups + num_dom_groups;
436 if (num_total > UINT32_MAX) {
437 return NT_STATUS_INTERNAL_ERROR;
440 result = talloc_array(r->out.groups, struct wbint_Principal,
441 num_total);
442 if (result == NULL) {
443 return NT_STATUS_NO_MEMORY;
446 for (i = 0; i < num_local_groups; i++) {
447 struct wb_acct_info *lg = &local_groups[i];
448 struct wbint_Principal *rg = &result[ti++];
450 sid_compose(&rg->sid, &domain->sid, lg->rid);
451 rg->type = SID_NAME_ALIAS;
452 rg->name = talloc_strdup(result, lg->acct_name);
453 if (rg->name == NULL) {
454 TALLOC_FREE(result);
455 TALLOC_FREE(dom_groups);
456 TALLOC_FREE(local_groups);
457 return NT_STATUS_NO_MEMORY;
460 num_local_groups = 0;
461 TALLOC_FREE(local_groups);
463 for (i = 0; i < num_dom_groups; i++) {
464 struct wb_acct_info *dg = &dom_groups[i];
465 struct wbint_Principal *rg = &result[ti++];
467 sid_compose(&rg->sid, &domain->sid, dg->rid);
468 rg->type = SID_NAME_DOM_GRP;
469 rg->name = talloc_strdup(result, dg->acct_name);
470 if (rg->name == NULL) {
471 TALLOC_FREE(result);
472 TALLOC_FREE(dom_groups);
473 TALLOC_FREE(local_groups);
474 return NT_STATUS_NO_MEMORY;
477 num_dom_groups = 0;
478 TALLOC_FREE(dom_groups);
480 r->out.groups->num_principals = ti;
481 r->out.groups->principals = result;
483 return NT_STATUS_OK;
486 NTSTATUS _wbint_DsGetDcName(struct pipes_struct *p, struct wbint_DsGetDcName *r)
488 struct winbindd_domain *domain = wb_child_domain();
489 struct rpc_pipe_client *netlogon_pipe;
490 struct netr_DsRGetDCNameInfo *dc_info;
491 NTSTATUS status;
492 WERROR werr;
493 unsigned int orig_timeout;
494 struct dcerpc_binding_handle *b;
496 if (domain == NULL) {
497 return dsgetdcname(p->mem_ctx, winbind_messaging_context(),
498 r->in.domain_name, r->in.domain_guid,
499 r->in.site_name ? r->in.site_name : "",
500 r->in.flags,
501 r->out.dc_info);
504 status = cm_connect_netlogon(domain, &netlogon_pipe);
506 reset_cm_connection_on_error(domain, status);
507 if (!NT_STATUS_IS_OK(status)) {
508 DEBUG(10, ("Can't contact the NETLOGON pipe\n"));
509 return status;
512 b = netlogon_pipe->binding_handle;
514 /* This call can take a long time - allow the server to time out.
515 35 seconds should do it. */
517 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
519 if (domain->active_directory) {
520 status = dcerpc_netr_DsRGetDCName(b,
521 p->mem_ctx, domain->dcname,
522 r->in.domain_name, NULL, r->in.domain_guid,
523 r->in.flags, r->out.dc_info, &werr);
524 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(werr)) {
525 goto done;
527 if (reset_cm_connection_on_error(domain, status)) {
528 /* Re-initialize. */
529 status = cm_connect_netlogon(domain, &netlogon_pipe);
531 reset_cm_connection_on_error(domain, status);
532 if (!NT_STATUS_IS_OK(status)) {
533 DEBUG(10, ("Can't contact the NETLOGON pipe\n"));
534 return status;
537 b = netlogon_pipe->binding_handle;
539 /* This call can take a long time - allow the server to time out.
540 35 seconds should do it. */
542 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
547 * Fallback to less capable methods
550 dc_info = talloc_zero(r->out.dc_info, struct netr_DsRGetDCNameInfo);
551 if (dc_info == NULL) {
552 status = NT_STATUS_NO_MEMORY;
553 goto done;
556 if (r->in.flags & DS_PDC_REQUIRED) {
557 status = dcerpc_netr_GetDcName(b,
558 p->mem_ctx, domain->dcname,
559 r->in.domain_name, &dc_info->dc_unc, &werr);
560 } else {
561 status = dcerpc_netr_GetAnyDCName(b,
562 p->mem_ctx, domain->dcname,
563 r->in.domain_name, &dc_info->dc_unc, &werr);
566 reset_cm_connection_on_error(domain, status);
567 if (!NT_STATUS_IS_OK(status)) {
568 DEBUG(10, ("dcerpc_netr_Get[Any]DCName failed: %s\n",
569 nt_errstr(status)));
570 goto done;
572 if (!W_ERROR_IS_OK(werr)) {
573 DEBUG(10, ("dcerpc_netr_Get[Any]DCName failed: %s\n",
574 win_errstr(werr)));
575 status = werror_to_ntstatus(werr);
576 goto done;
579 *r->out.dc_info = dc_info;
580 status = NT_STATUS_OK;
582 done:
583 /* And restore our original timeout. */
584 rpccli_set_timeout(netlogon_pipe, orig_timeout);
586 return status;
589 NTSTATUS _wbint_LookupRids(struct pipes_struct *p, struct wbint_LookupRids *r)
591 struct winbindd_domain *domain = wb_child_domain();
592 char *domain_name;
593 char **names;
594 enum lsa_SidType *types;
595 struct wbint_Principal *result;
596 NTSTATUS status;
597 int i;
599 if (domain == NULL) {
600 return NT_STATUS_REQUEST_NOT_ACCEPTED;
603 status = domain->methods->rids_to_names(
604 domain, talloc_tos(), r->in.domain_sid, r->in.rids->rids,
605 r->in.rids->num_rids, &domain_name, &names, &types);
606 reset_cm_connection_on_error(domain, status);
607 if (!NT_STATUS_IS_OK(status)) {
608 return status;
611 *r->out.domain_name = talloc_move(r->out.domain_name, &domain_name);
613 result = talloc_array(p->mem_ctx, struct wbint_Principal,
614 r->in.rids->num_rids);
615 if (result == NULL) {
616 return NT_STATUS_NO_MEMORY;
619 for (i=0; i<r->in.rids->num_rids; i++) {
620 sid_compose(&result[i].sid, r->in.domain_sid,
621 r->in.rids->rids[i]);
622 result[i].type = types[i];
623 result[i].name = talloc_move(result, &names[i]);
625 TALLOC_FREE(types);
626 TALLOC_FREE(names);
628 r->out.names->num_principals = r->in.rids->num_rids;
629 r->out.names->principals = result;
630 return NT_STATUS_OK;
633 NTSTATUS _wbint_CheckMachineAccount(struct pipes_struct *p,
634 struct wbint_CheckMachineAccount *r)
636 struct winbindd_domain *domain;
637 int num_retries = 0;
638 NTSTATUS status;
640 domain = wb_child_domain();
641 if (domain == NULL) {
642 return NT_STATUS_REQUEST_NOT_ACCEPTED;
645 again:
646 invalidate_cm_connection(domain);
647 domain->conn.netlogon_force_reauth = true;
650 struct rpc_pipe_client *netlogon_pipe;
651 status = cm_connect_netlogon(domain, &netlogon_pipe);
654 /* There is a race condition between fetching the trust account
655 password and the periodic machine password change. So it's
656 possible that the trust account password has been changed on us.
657 We are returned NT_STATUS_ACCESS_DENIED if this happens. */
659 #define MAX_RETRIES 3
661 if ((num_retries < MAX_RETRIES)
662 && NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
663 num_retries++;
664 goto again;
667 if (!NT_STATUS_IS_OK(status)) {
668 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
669 goto done;
672 /* Pass back result code - zero for success, other values for
673 specific failures. */
675 DEBUG(3,("domain %s secret is %s\n", domain->name,
676 NT_STATUS_IS_OK(status) ? "good" : "bad"));
678 done:
679 DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
680 ("Checking the trust account password for domain %s returned %s\n",
681 domain->name, nt_errstr(status)));
683 return status;
686 NTSTATUS _wbint_ChangeMachineAccount(struct pipes_struct *p,
687 struct wbint_ChangeMachineAccount *r)
689 struct messaging_context *msg_ctx = winbind_messaging_context();
690 struct winbindd_domain *domain;
691 NTSTATUS status;
692 struct rpc_pipe_client *netlogon_pipe;
694 domain = wb_child_domain();
695 if (domain == NULL) {
696 return NT_STATUS_REQUEST_NOT_ACCEPTED;
699 status = cm_connect_netlogon(domain, &netlogon_pipe);
700 if (!NT_STATUS_IS_OK(status)) {
701 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
702 goto done;
705 status = trust_pw_change(domain->conn.netlogon_creds,
706 msg_ctx,
707 netlogon_pipe->binding_handle,
708 domain->name,
709 true); /* force */
711 /* Pass back result code - zero for success, other values for
712 specific failures. */
714 DEBUG(3,("domain %s secret %s\n", domain->name,
715 NT_STATUS_IS_OK(status) ? "changed" : "unchanged"));
717 done:
718 DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
719 ("Changing the trust account password for domain %s returned %s\n",
720 domain->name, nt_errstr(status)));
722 return status;
725 NTSTATUS _wbint_PingDc(struct pipes_struct *p, struct wbint_PingDc *r)
727 NTSTATUS status;
728 struct winbindd_domain *domain;
729 struct rpc_pipe_client *netlogon_pipe;
730 union netr_CONTROL_QUERY_INFORMATION info;
731 WERROR werr;
732 fstring logon_server;
733 struct dcerpc_binding_handle *b;
734 bool retry = false;
736 domain = wb_child_domain();
737 if (domain == NULL) {
738 return NT_STATUS_REQUEST_NOT_ACCEPTED;
741 reconnect:
742 status = cm_connect_netlogon(domain, &netlogon_pipe);
743 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
745 * Retry to open new connection with new kerberos ticket.
747 invalidate_cm_connection(domain);
748 status = cm_connect_netlogon(domain, &netlogon_pipe);
751 reset_cm_connection_on_error(domain, status);
752 if (!NT_STATUS_IS_OK(status)) {
753 DEBUG(3, ("could not open handle to NETLOGON pipe: %s\n",
754 nt_errstr(status)));
755 return status;
758 b = netlogon_pipe->binding_handle;
760 fstr_sprintf(logon_server, "\\\\%s", domain->dcname);
761 *r->out.dcname = talloc_strdup(p->mem_ctx, domain->dcname);
762 if (*r->out.dcname == NULL) {
763 DEBUG(2, ("Could not allocate memory\n"));
764 return NT_STATUS_NO_MEMORY;
768 * This provokes a WERR_NOT_SUPPORTED error message. This is
769 * documented in the wspp docs. I could not get a successful
770 * call to work, but the main point here is testing that the
771 * netlogon pipe works.
773 status = dcerpc_netr_LogonControl(b, p->mem_ctx,
774 logon_server, NETLOGON_CONTROL_QUERY,
775 2, &info, &werr);
777 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
778 DEBUG(10, ("Session might have expired. "
779 "Reconnect and retry once.\n"));
780 invalidate_cm_connection(domain);
781 retry = true;
782 goto reconnect;
785 reset_cm_connection_on_error(domain, status);
786 if (!NT_STATUS_IS_OK(status)) {
787 DEBUG(2, ("dcerpc_netr_LogonControl failed: %s\n",
788 nt_errstr(status)));
789 return status;
792 if (!W_ERROR_EQUAL(werr, WERR_NOT_SUPPORTED)) {
793 DEBUG(2, ("dcerpc_netr_LogonControl returned %s, expected "
794 "WERR_NOT_SUPPORTED\n",
795 win_errstr(werr)));
796 return werror_to_ntstatus(werr);
799 DEBUG(5, ("winbindd_dual_ping_dc succeeded\n"));
800 return NT_STATUS_OK;
803 NTSTATUS _winbind_DsrUpdateReadOnlyServerDnsRecords(struct pipes_struct *p,
804 struct winbind_DsrUpdateReadOnlyServerDnsRecords *r)
806 struct winbindd_domain *domain;
807 NTSTATUS status;
808 struct rpc_pipe_client *netlogon_pipe;
810 domain = wb_child_domain();
811 if (domain == NULL) {
812 return NT_STATUS_REQUEST_NOT_ACCEPTED;
815 status = cm_connect_netlogon(domain, &netlogon_pipe);
816 if (!NT_STATUS_IS_OK(status)) {
817 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
818 goto done;
821 status = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(domain->conn.netlogon_creds,
822 netlogon_pipe->binding_handle,
823 r->in.site_name,
824 r->in.dns_ttl,
825 r->in.dns_names);
827 /* Pass back result code - zero for success, other values for
828 specific failures. */
830 DEBUG(3,("DNS records for domain %s %s\n", domain->name,
831 NT_STATUS_IS_OK(status) ? "changed" : "unchanged"));
833 done:
834 DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
835 ("Update of DNS records via RW DC %s returned %s\n",
836 domain->name, nt_errstr(status)));
838 return status;
841 NTSTATUS _winbind_SamLogon(struct pipes_struct *p,
842 struct winbind_SamLogon *r)
844 struct winbindd_domain *domain;
845 NTSTATUS status;
846 DATA_BLOB lm_response, nt_response;
847 domain = wb_child_domain();
848 if (domain == NULL) {
849 return NT_STATUS_REQUEST_NOT_ACCEPTED;
852 /* TODO: Handle interactive logons here */
853 if (r->in.validation_level != 3 ||
854 r->in.logon.network == NULL ||
855 (r->in.logon_level != NetlogonNetworkInformation
856 && r->in.logon_level != NetlogonNetworkTransitiveInformation)) {
857 return NT_STATUS_REQUEST_NOT_ACCEPTED;
861 lm_response = data_blob_talloc(p->mem_ctx, r->in.logon.network->lm.data, r->in.logon.network->lm.length);
862 nt_response = data_blob_talloc(p->mem_ctx, r->in.logon.network->nt.data, r->in.logon.network->nt.length);
864 status = winbind_dual_SamLogon(domain, p->mem_ctx,
865 r->in.logon.network->identity_info.parameter_control,
866 r->in.logon.network->identity_info.account_name.string,
867 r->in.logon.network->identity_info.domain_name.string,
868 r->in.logon.network->identity_info.workstation.string,
869 r->in.logon.network->challenge,
870 lm_response, nt_response, &r->out.validation.sam3);
871 return status;