librpc/idl: add winbind_LogonControl()
[obnox/samba/samba-obnox.git] / source3 / winbindd / winbindd_dual_srv.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    In-Child server implementation of the routines defined in wbint.idl
5
6    Copyright (C) Volker Lendecke 2009
7    Copyright (C) Guenther Deschner 2009
8
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.
13
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.
18
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/>.
21 */
22
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"
33
34 void _wbint_Ping(struct pipes_struct *p, struct wbint_Ping *r)
35 {
36         *r->out.out_data = r->in.in_data;
37 }
38
39 static bool reset_cm_connection_on_error(struct winbindd_domain *domain,
40                                         NTSTATUS status)
41 {
42         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
43                 invalidate_cm_connection(domain);
44                 /* We invalidated the connection. */
45                 return true;
46         }
47         return false;
48 }
49
50 NTSTATUS _wbint_LookupSid(struct pipes_struct *p, struct wbint_LookupSid *r)
51 {
52         struct winbindd_domain *domain = wb_child_domain();
53         char *dom_name;
54         char *name;
55         enum lsa_SidType type;
56         NTSTATUS status;
57
58         if (domain == NULL) {
59                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
60         }
61
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;
67         }
68
69         *r->out.domain = dom_name;
70         *r->out.name = name;
71         *r->out.type = type;
72         return NT_STATUS_OK;
73 }
74
75 NTSTATUS _wbint_LookupSids(struct pipes_struct *p, struct wbint_LookupSids *r)
76 {
77         struct winbindd_domain *domain = wb_child_domain();
78         struct lsa_RefDomainList *domains = r->out.domains;
79         NTSTATUS status;
80
81         if (domain == NULL) {
82                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
83         }
84
85         /*
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.
90          */
91         status = rpc_lookup_sids(p->mem_ctx, domain, r->in.sids,
92                                  &domains, &r->out.names);
93
94         if (domains != NULL) {
95                 r->out.domains = domains;
96         }
97
98         reset_cm_connection_on_error(domain, status);
99         return status;
100 }
101
102 NTSTATUS _wbint_LookupName(struct pipes_struct *p, struct wbint_LookupName *r)
103 {
104         struct winbindd_domain *domain = wb_child_domain();
105         NTSTATUS status;
106
107         if (domain == NULL) {
108                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
109         }
110
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;
116 }
117
118 NTSTATUS _wbint_Sids2UnixIDs(struct pipes_struct *p,
119                              struct wbint_Sids2UnixIDs *r)
120 {
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;
127
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;
132
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;
138                 }
139
140                 num_ids = 0;
141
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;
145                         }
146                 }
147
148                 ids = talloc_realloc(talloc_tos(), ids,
149                                            struct id_map, num_ids);
150                 if (ids == NULL) {
151                         goto nomem;
152                 }
153                 id_ptrs = talloc_realloc(talloc_tos(), id_ptrs,
154                                                struct id_map *, num_ids+1);
155                 if (id_ptrs == NULL) {
156                         goto nomem;
157                 }
158                 id_idx = talloc_realloc(talloc_tos(), id_idx,
159                                               uint32_t, num_ids);
160                 if (id_idx == NULL) {
161                         goto nomem;
162                 }
163                 sids = talloc_realloc(talloc_tos(), sids,
164                                             struct dom_sid, num_ids);
165                 if (sids == NULL) {
166                         goto nomem;
167                 }
168
169                 num_ids = 0;
170
171                 /*
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.
175                  */
176                 for (j=0; j<r->in.ids->num_ids; j++) {
177                         struct wbint_TransID *id = &r->in.ids->ids[j];
178
179                         if (id->domain_index != i) {
180                                 continue;
181                         }
182                         id_idx[num_ids] = j;
183                         id_ptrs[num_ids] = &ids[num_ids];
184
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;
190                 }
191                 id_ptrs[num_ids] = NULL;
192
193                 status = dom->methods->sids_to_unixids(dom, id_ptrs);
194                 DEBUG(10, ("sids_to_unixids returned %s\n",
195                            nt_errstr(status)));
196
197                 /*
198                  * Extract the results for handing them back to the caller.
199                  */
200                 for (j=0; j<num_ids; j++) {
201                         struct wbint_TransID *id = &r->in.ids->ids[id_idx[j]];
202
203                         if (ids[j].status != ID_MAPPED) {
204                                 id->xid.id = UINT32_MAX;
205                                 id->xid.type = ID_TYPE_NOT_SPECIFIED;
206                                 continue;
207                         }
208
209                         id->xid = ids[j].xid;
210                 }
211         }
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;
219 }
220
221 NTSTATUS _wbint_Uid2Sid(struct pipes_struct *p, struct wbint_Uid2Sid *r)
222 {
223         return idmap_uid_to_sid(r->in.dom_name ? r->in.dom_name : "",
224                                 r->out.sid, r->in.uid);
225 }
226
227 NTSTATUS _wbint_Gid2Sid(struct pipes_struct *p, struct wbint_Gid2Sid *r)
228 {
229         return idmap_gid_to_sid(r->in.dom_name ? r->in.dom_name : "",
230                                 r->out.sid, r->in.gid);
231 }
232
233 NTSTATUS _wbint_AllocateUid(struct pipes_struct *p, struct wbint_AllocateUid *r)
234 {
235         struct unixid xid;
236         NTSTATUS status;
237
238         status = idmap_allocate_uid(&xid);
239         if (!NT_STATUS_IS_OK(status)) {
240                 return status;
241         }
242         *r->out.uid = xid.id;
243         return NT_STATUS_OK;
244 }
245
246 NTSTATUS _wbint_AllocateGid(struct pipes_struct *p, struct wbint_AllocateGid *r)
247 {
248         struct unixid xid;
249         NTSTATUS status;
250
251         status = idmap_allocate_gid(&xid);
252         if (!NT_STATUS_IS_OK(status)) {
253                 return status;
254         }
255         *r->out.gid = xid.id;
256         return NT_STATUS_OK;
257 }
258
259 NTSTATUS _wbint_QueryUser(struct pipes_struct *p, struct wbint_QueryUser *r)
260 {
261         struct winbindd_domain *domain = wb_child_domain();
262         NTSTATUS status;
263
264         if (domain == NULL) {
265                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
266         }
267
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;
272 }
273
274 NTSTATUS _wbint_LookupUserAliases(struct pipes_struct *p,
275                                   struct wbint_LookupUserAliases *r)
276 {
277         struct winbindd_domain *domain = wb_child_domain();
278         NTSTATUS status;
279
280         if (domain == NULL) {
281                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
282         }
283
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;
289 }
290
291 NTSTATUS _wbint_LookupUserGroups(struct pipes_struct *p,
292                                  struct wbint_LookupUserGroups *r)
293 {
294         struct winbindd_domain *domain = wb_child_domain();
295         NTSTATUS status;
296
297         if (domain == NULL) {
298                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
299         }
300
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;
306 }
307
308 NTSTATUS _wbint_QuerySequenceNumber(struct pipes_struct *p,
309                                     struct wbint_QuerySequenceNumber *r)
310 {
311         struct winbindd_domain *domain = wb_child_domain();
312         NTSTATUS status;
313
314         if (domain == NULL) {
315                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
316         }
317
318         status = domain->methods->sequence_number(domain, r->out.sequence);
319         reset_cm_connection_on_error(domain, status);
320         return status;
321 }
322
323 NTSTATUS _wbint_LookupGroupMembers(struct pipes_struct *p,
324                                    struct wbint_LookupGroupMembers *r)
325 {
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;
332
333         if (domain == NULL) {
334                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
335         }
336
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;
343         }
344
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;
350         }
351
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];
357         }
358
359         return NT_STATUS_OK;
360 }
361
362 NTSTATUS _wbint_QueryUserList(struct pipes_struct *p,
363                               struct wbint_QueryUserList *r)
364 {
365         struct winbindd_domain *domain = wb_child_domain();
366         NTSTATUS status;
367
368         if (domain == NULL) {
369                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
370         }
371
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;
377 }
378
379 NTSTATUS _wbint_QueryGroupList(struct pipes_struct *p,
380                                struct wbint_QueryGroupList *r)
381 {
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;
393
394         if (domain == NULL) {
395                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
396         }
397
398         switch (lp_server_role()) {
399         case ROLE_ACTIVE_DIRECTORY_DC:
400                 if (domain->internal) {
401                         /*
402                          * we want to include local groups
403                          * for BUILTIN and WORKGROUP
404                          */
405                         include_local_groups = true;
406                 }
407                 break;
408         default:
409                 /*
410                  * We might include local groups in more
411                  * setups later, but that requires more work
412                  * elsewhere.
413                  */
414                 break;
415         }
416
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;
424                 }
425         }
426
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;
433         }
434
435         num_total = num_local_groups + num_dom_groups;
436         if (num_total > UINT32_MAX) {
437                 return NT_STATUS_INTERNAL_ERROR;
438         }
439
440         result = talloc_array(r->out.groups, struct wbint_Principal,
441                               num_total);
442         if (result == NULL) {
443                 return NT_STATUS_NO_MEMORY;
444         }
445
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++];
449
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;
458                 }
459         }
460         num_local_groups = 0;
461         TALLOC_FREE(local_groups);
462
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++];
466
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;
475                 }
476         }
477         num_dom_groups = 0;
478         TALLOC_FREE(dom_groups);
479
480         r->out.groups->num_principals = ti;
481         r->out.groups->principals = result;
482
483         return NT_STATUS_OK;
484 }
485
486 NTSTATUS _wbint_DsGetDcName(struct pipes_struct *p, struct wbint_DsGetDcName *r)
487 {
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;
495
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);
502         }
503
504         status = cm_connect_netlogon(domain, &netlogon_pipe);
505
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;
510         }
511
512         b = netlogon_pipe->binding_handle;
513
514         /* This call can take a long time - allow the server to time out.
515            35 seconds should do it. */
516
517         orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
518
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;
526                 }
527                 if (reset_cm_connection_on_error(domain, status)) {
528                         /* Re-initialize. */
529                         status = cm_connect_netlogon(domain, &netlogon_pipe);
530
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;
535                         }
536
537                         b = netlogon_pipe->binding_handle;
538
539                         /* This call can take a long time - allow the server to time out.
540                            35 seconds should do it. */
541
542                         orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
543                 }
544         }
545
546         /*
547          * Fallback to less capable methods
548          */
549
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;
554         }
555
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);
564         }
565
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;
571         }
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;
577         }
578
579         *r->out.dc_info = dc_info;
580         status = NT_STATUS_OK;
581
582 done:
583         /* And restore our original timeout. */
584         rpccli_set_timeout(netlogon_pipe, orig_timeout);
585
586         return status;
587 }
588
589 NTSTATUS _wbint_LookupRids(struct pipes_struct *p, struct wbint_LookupRids *r)
590 {
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;
598
599         if (domain == NULL) {
600                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
601         }
602
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;
609         }
610
611         *r->out.domain_name = talloc_move(r->out.domain_name, &domain_name);
612
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;
617         }
618
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]);
624         }
625         TALLOC_FREE(types);
626         TALLOC_FREE(names);
627
628         r->out.names->num_principals = r->in.rids->num_rids;
629         r->out.names->principals = result;
630         return NT_STATUS_OK;
631 }
632
633 NTSTATUS _wbint_CheckMachineAccount(struct pipes_struct *p,
634                                     struct wbint_CheckMachineAccount *r)
635 {
636         struct winbindd_domain *domain;
637         int num_retries = 0;
638         NTSTATUS status;
639
640         domain = wb_child_domain();
641         if (domain == NULL) {
642                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
643         }
644
645 again:
646         invalidate_cm_connection(domain);
647         domain->conn.netlogon_force_reauth = true;
648
649         {
650                 struct rpc_pipe_client *netlogon_pipe;
651                 status = cm_connect_netlogon(domain, &netlogon_pipe);
652         }
653
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. */
658
659 #define MAX_RETRIES 3
660
661         if ((num_retries < MAX_RETRIES)
662             && NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
663                 num_retries++;
664                 goto again;
665         }
666
667         if (!NT_STATUS_IS_OK(status)) {
668                 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
669                 goto done;
670         }
671
672         /* Pass back result code - zero for success, other values for
673            specific failures. */
674
675         DEBUG(3,("domain %s secret is %s\n", domain->name,
676                 NT_STATUS_IS_OK(status) ? "good" : "bad"));
677
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)));
682
683         return status;
684 }
685
686 NTSTATUS _wbint_ChangeMachineAccount(struct pipes_struct *p,
687                                      struct wbint_ChangeMachineAccount *r)
688 {
689         struct messaging_context *msg_ctx = winbind_messaging_context();
690         struct winbindd_domain *domain;
691         NTSTATUS status;
692         struct rpc_pipe_client *netlogon_pipe;
693
694         domain = wb_child_domain();
695         if (domain == NULL) {
696                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
697         }
698
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;
703         }
704
705         status = trust_pw_change(domain->conn.netlogon_creds,
706                                  msg_ctx,
707                                  netlogon_pipe->binding_handle,
708                                  domain->name,
709                                  true); /* force */
710
711         /* Pass back result code - zero for success, other values for
712            specific failures. */
713
714         DEBUG(3,("domain %s secret %s\n", domain->name,
715                 NT_STATUS_IS_OK(status) ? "changed" : "unchanged"));
716
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)));
721
722         return status;
723 }
724
725 NTSTATUS _wbint_PingDc(struct pipes_struct *p, struct wbint_PingDc *r)
726 {
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;
735
736         domain = wb_child_domain();
737         if (domain == NULL) {
738                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
739         }
740
741 reconnect:
742         status = cm_connect_netlogon(domain, &netlogon_pipe);
743         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
744                 /*
745                  * Retry to open new connection with new kerberos ticket.
746                  */
747                 invalidate_cm_connection(domain);
748                 status = cm_connect_netlogon(domain, &netlogon_pipe);
749         }
750
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;
756         }
757
758         b = netlogon_pipe->binding_handle;
759
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;
765         }
766
767         /*
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.
772          */
773         status = dcerpc_netr_LogonControl(b, p->mem_ctx,
774                                           logon_server, NETLOGON_CONTROL_QUERY,
775                                           2, &info, &werr);
776
777         if (!dcerpc_binding_handle_is_connected(b) && !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;
783         }
784
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;
790         }
791
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);
797         }
798
799         DEBUG(5, ("winbindd_dual_ping_dc succeeded\n"));
800         return NT_STATUS_OK;
801 }
802
803 NTSTATUS _winbind_DsrUpdateReadOnlyServerDnsRecords(struct pipes_struct *p,
804                                                     struct winbind_DsrUpdateReadOnlyServerDnsRecords *r)
805 {
806         struct winbindd_domain *domain;
807         NTSTATUS status;
808         struct rpc_pipe_client *netlogon_pipe;
809
810         domain = wb_child_domain();
811         if (domain == NULL) {
812                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
813         }
814
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;
819         }
820
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);
826
827         /* Pass back result code - zero for success, other values for
828            specific failures. */
829
830         DEBUG(3,("DNS records for domain %s %s\n", domain->name,
831                 NT_STATUS_IS_OK(status) ? "changed" : "unchanged"));
832
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)));
837
838         return status;
839 }
840
841 NTSTATUS _winbind_SamLogon(struct pipes_struct *p,
842                         struct winbind_SamLogon *r)
843 {
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;
850         }
851
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;
858         }
859
860
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);
863
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;
872 }
873
874 WERROR _winbind_LogonControl(struct pipes_struct *p,
875                              struct winbind_LogonControl *r)
876 {
877         struct winbindd_domain *domain;
878
879         domain = wb_child_domain();
880         if (domain == NULL) {
881                 return WERR_NO_SUCH_DOMAIN;
882         }
883
884         return WERR_NOT_SUPPORTED;
885 }