idmap: Remove "domname" from idmap_uid_to_sid
[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 "../librpc/gen_ndr/ndr_lsa_c.h"
31 #include "idmap.h"
32 #include "../libcli/security/security.h"
33 #include "../libcli/auth/netlogon_creds_cli.h"
34 #include "passdb.h"
35 #include "../source4/dsdb/samdb/samdb.h"
36
37 void _wbint_Ping(struct pipes_struct *p, struct wbint_Ping *r)
38 {
39         *r->out.out_data = r->in.in_data;
40 }
41
42 static bool reset_cm_connection_on_error(struct winbindd_domain *domain,
43                                         NTSTATUS status)
44 {
45         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
46                 invalidate_cm_connection(domain);
47                 /* We invalidated the connection. */
48                 return true;
49         }
50         return false;
51 }
52
53 NTSTATUS _wbint_LookupSid(struct pipes_struct *p, struct wbint_LookupSid *r)
54 {
55         struct winbindd_domain *domain = wb_child_domain();
56         char *dom_name;
57         char *name;
58         enum lsa_SidType type;
59         NTSTATUS status;
60
61         if (domain == NULL) {
62                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
63         }
64
65         status = domain->methods->sid_to_name(domain, p->mem_ctx, r->in.sid,
66                                               &dom_name, &name, &type);
67         reset_cm_connection_on_error(domain, status);
68         if (!NT_STATUS_IS_OK(status)) {
69                 return status;
70         }
71
72         *r->out.domain = dom_name;
73         *r->out.name = name;
74         *r->out.type = type;
75         return NT_STATUS_OK;
76 }
77
78 NTSTATUS _wbint_LookupSids(struct pipes_struct *p, struct wbint_LookupSids *r)
79 {
80         struct winbindd_domain *domain = wb_child_domain();
81         struct lsa_RefDomainList *domains = r->out.domains;
82         NTSTATUS status;
83
84         if (domain == NULL) {
85                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
86         }
87
88         /*
89          * This breaks the winbindd_domain->methods abstraction: This
90          * is only called for remote domains, and both winbindd_msrpc
91          * and winbindd_ad call into lsa_lookupsids anyway. Caching is
92          * done at the wbint RPC layer.
93          */
94         status = rpc_lookup_sids(p->mem_ctx, domain, r->in.sids,
95                                  &domains, &r->out.names);
96
97         if (domains != NULL) {
98                 r->out.domains = domains;
99         }
100
101         reset_cm_connection_on_error(domain, status);
102         return status;
103 }
104
105 NTSTATUS _wbint_LookupName(struct pipes_struct *p, struct wbint_LookupName *r)
106 {
107         struct winbindd_domain *domain = wb_child_domain();
108         NTSTATUS status;
109
110         if (domain == NULL) {
111                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
112         }
113
114         status = domain->methods->name_to_sid(
115                 domain, p->mem_ctx, r->in.domain, r->in.name, r->in.flags,
116                 r->out.sid, r->out.type);
117         reset_cm_connection_on_error(domain, status);
118         return status;
119 }
120
121 NTSTATUS _wbint_Sids2UnixIDs(struct pipes_struct *p,
122                              struct wbint_Sids2UnixIDs *r)
123 {
124         uint32_t i, j;
125         struct id_map *ids = NULL;
126         struct id_map **id_ptrs = NULL;
127         struct dom_sid *sids = NULL;
128         uint32_t *id_idx = NULL;
129         NTSTATUS status = NT_STATUS_NO_MEMORY;
130
131         for (i=0; i<r->in.domains->count; i++) {
132                 struct lsa_DomainInfo *d = &r->in.domains->domains[i];
133                 struct idmap_domain *dom;
134                 uint32_t num_ids;
135
136                 dom = idmap_find_domain_with_sid(d->name.string, d->sid);
137                 if (dom == NULL) {
138                         DEBUG(10, ("idmap domain %s:%s not found\n",
139                                    d->name.string, sid_string_dbg(d->sid)));
140                         continue;
141                 }
142
143                 num_ids = 0;
144
145                 for (j=0; j<r->in.ids->num_ids; j++) {
146                         if (r->in.ids->ids[j].domain_index == i) {
147                                 num_ids += 1;
148                         }
149                 }
150
151                 ids = talloc_realloc(talloc_tos(), ids,
152                                            struct id_map, num_ids);
153                 if (ids == NULL) {
154                         goto nomem;
155                 }
156                 id_ptrs = talloc_realloc(talloc_tos(), id_ptrs,
157                                                struct id_map *, num_ids+1);
158                 if (id_ptrs == NULL) {
159                         goto nomem;
160                 }
161                 id_idx = talloc_realloc(talloc_tos(), id_idx,
162                                               uint32_t, num_ids);
163                 if (id_idx == NULL) {
164                         goto nomem;
165                 }
166                 sids = talloc_realloc(talloc_tos(), sids,
167                                             struct dom_sid, num_ids);
168                 if (sids == NULL) {
169                         goto nomem;
170                 }
171
172                 num_ids = 0;
173
174                 /*
175                  * Convert the input data into a list of
176                  * id_map structs suitable for handing in
177                  * to the idmap sids_to_unixids method.
178                  */
179                 for (j=0; j<r->in.ids->num_ids; j++) {
180                         struct wbint_TransID *id = &r->in.ids->ids[j];
181
182                         if (id->domain_index != i) {
183                                 continue;
184                         }
185                         id_idx[num_ids] = j;
186                         id_ptrs[num_ids] = &ids[num_ids];
187
188                         ids[num_ids].sid = &sids[num_ids];
189                         sid_compose(ids[num_ids].sid, d->sid, id->rid);
190                         ids[num_ids].xid.type = id->type;
191                         ids[num_ids].status = ID_UNKNOWN;
192                         num_ids += 1;
193                 }
194                 id_ptrs[num_ids] = NULL;
195
196                 status = dom->methods->sids_to_unixids(dom, id_ptrs);
197                 DEBUG(10, ("sids_to_unixids returned %s\n",
198                            nt_errstr(status)));
199
200                 /*
201                  * Extract the results for handing them back to the caller.
202                  */
203                 for (j=0; j<num_ids; j++) {
204                         struct wbint_TransID *id = &r->in.ids->ids[id_idx[j]];
205
206                         if (ids[j].status != ID_MAPPED) {
207                                 id->xid.id = UINT32_MAX;
208                                 id->xid.type = ID_TYPE_NOT_SPECIFIED;
209                                 continue;
210                         }
211
212                         id->xid = ids[j].xid;
213                 }
214         }
215         status = NT_STATUS_OK;
216 nomem:
217         TALLOC_FREE(ids);
218         TALLOC_FREE(id_ptrs);
219         TALLOC_FREE(id_idx);
220         TALLOC_FREE(sids);
221         return status;
222 }
223
224 NTSTATUS _wbint_Uid2Sid(struct pipes_struct *p, struct wbint_Uid2Sid *r)
225 {
226         return idmap_uid_to_sid(r->out.sid, r->in.uid);
227 }
228
229 NTSTATUS _wbint_Gid2Sid(struct pipes_struct *p, struct wbint_Gid2Sid *r)
230 {
231         return idmap_gid_to_sid(r->in.dom_name ? r->in.dom_name : "",
232                                 r->out.sid, r->in.gid);
233 }
234
235 NTSTATUS _wbint_AllocateUid(struct pipes_struct *p, struct wbint_AllocateUid *r)
236 {
237         struct unixid xid;
238         NTSTATUS status;
239
240         status = idmap_allocate_uid(&xid);
241         if (!NT_STATUS_IS_OK(status)) {
242                 return status;
243         }
244         *r->out.uid = xid.id;
245         return NT_STATUS_OK;
246 }
247
248 NTSTATUS _wbint_AllocateGid(struct pipes_struct *p, struct wbint_AllocateGid *r)
249 {
250         struct unixid xid;
251         NTSTATUS status;
252
253         status = idmap_allocate_gid(&xid);
254         if (!NT_STATUS_IS_OK(status)) {
255                 return status;
256         }
257         *r->out.gid = xid.id;
258         return NT_STATUS_OK;
259 }
260
261 NTSTATUS _wbint_QueryUser(struct pipes_struct *p, struct wbint_QueryUser *r)
262 {
263         struct winbindd_domain *domain = wb_child_domain();
264         NTSTATUS status;
265
266         if (domain == NULL) {
267                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
268         }
269
270         status = domain->methods->query_user(domain, p->mem_ctx, r->in.sid,
271                                              r->out.info);
272         reset_cm_connection_on_error(domain, status);
273         return status;
274 }
275
276 NTSTATUS _wbint_LookupUserAliases(struct pipes_struct *p,
277                                   struct wbint_LookupUserAliases *r)
278 {
279         struct winbindd_domain *domain = wb_child_domain();
280         NTSTATUS status;
281
282         if (domain == NULL) {
283                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
284         }
285
286         status = domain->methods->lookup_useraliases(
287                 domain, p->mem_ctx, r->in.sids->num_sids, r->in.sids->sids,
288                 &r->out.rids->num_rids, &r->out.rids->rids);
289         reset_cm_connection_on_error(domain, status);
290         return status;
291 }
292
293 NTSTATUS _wbint_LookupUserGroups(struct pipes_struct *p,
294                                  struct wbint_LookupUserGroups *r)
295 {
296         struct winbindd_domain *domain = wb_child_domain();
297         NTSTATUS status;
298
299         if (domain == NULL) {
300                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
301         }
302
303         status = domain->methods->lookup_usergroups(
304                 domain, p->mem_ctx, r->in.sid,
305                 &r->out.sids->num_sids, &r->out.sids->sids);
306         reset_cm_connection_on_error(domain, status);
307         return status;
308 }
309
310 NTSTATUS _wbint_QuerySequenceNumber(struct pipes_struct *p,
311                                     struct wbint_QuerySequenceNumber *r)
312 {
313         struct winbindd_domain *domain = wb_child_domain();
314         NTSTATUS status;
315
316         if (domain == NULL) {
317                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
318         }
319
320         status = domain->methods->sequence_number(domain, r->out.sequence);
321         reset_cm_connection_on_error(domain, status);
322         return status;
323 }
324
325 NTSTATUS _wbint_LookupGroupMembers(struct pipes_struct *p,
326                                    struct wbint_LookupGroupMembers *r)
327 {
328         struct winbindd_domain *domain = wb_child_domain();
329         uint32_t i, num_names;
330         struct dom_sid *sid_mem;
331         char **names;
332         uint32_t *name_types;
333         NTSTATUS status;
334
335         if (domain == NULL) {
336                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
337         }
338
339         status = domain->methods->lookup_groupmem(
340                 domain, p->mem_ctx, r->in.sid, r->in.type,
341                 &num_names, &sid_mem, &names, &name_types);
342         reset_cm_connection_on_error(domain, status);
343         if (!NT_STATUS_IS_OK(status)) {
344                 return status;
345         }
346
347         r->out.members->num_principals = num_names;
348         r->out.members->principals = talloc_array(
349                 r->out.members, struct wbint_Principal, num_names);
350         if (r->out.members->principals == NULL) {
351                 return NT_STATUS_NO_MEMORY;
352         }
353
354         for (i=0; i<num_names; i++) {
355                 struct wbint_Principal *m = &r->out.members->principals[i];
356                 sid_copy(&m->sid, &sid_mem[i]);
357                 m->name = talloc_move(r->out.members->principals, &names[i]);
358                 m->type = (enum lsa_SidType)name_types[i];
359         }
360
361         return NT_STATUS_OK;
362 }
363
364 NTSTATUS _wbint_QueryUserList(struct pipes_struct *p,
365                               struct wbint_QueryUserList *r)
366 {
367         struct winbindd_domain *domain = wb_child_domain();
368         NTSTATUS status;
369
370         if (domain == NULL) {
371                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
372         }
373
374         status = domain->methods->query_user_list(
375                 domain, p->mem_ctx, &r->out.users->num_userinfos,
376                 &r->out.users->userinfos);
377         reset_cm_connection_on_error(domain, status);
378         return status;
379 }
380
381 NTSTATUS _wbint_QueryGroupList(struct pipes_struct *p,
382                                struct wbint_QueryGroupList *r)
383 {
384         struct winbindd_domain *domain = wb_child_domain();
385         uint32_t i;
386         uint32_t num_local_groups = 0;
387         struct wb_acct_info *local_groups = NULL;
388         uint32_t num_dom_groups = 0;
389         struct wb_acct_info *dom_groups = NULL;
390         uint32_t ti = 0;
391         uint64_t num_total = 0;
392         struct wbint_Principal *result;
393         NTSTATUS status;
394         bool include_local_groups = false;
395
396         if (domain == NULL) {
397                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
398         }
399
400         switch (lp_server_role()) {
401         case ROLE_ACTIVE_DIRECTORY_DC:
402                 if (domain->internal) {
403                         /*
404                          * we want to include local groups
405                          * for BUILTIN and WORKGROUP
406                          */
407                         include_local_groups = true;
408                 }
409                 break;
410         default:
411                 /*
412                  * We might include local groups in more
413                  * setups later, but that requires more work
414                  * elsewhere.
415                  */
416                 break;
417         }
418
419         if (include_local_groups) {
420                 status = domain->methods->enum_local_groups(domain, talloc_tos(),
421                                                             &num_local_groups,
422                                                             &local_groups);
423                 reset_cm_connection_on_error(domain, status);
424                 if (!NT_STATUS_IS_OK(status)) {
425                         return status;
426                 }
427         }
428
429         status = domain->methods->enum_dom_groups(domain, talloc_tos(),
430                                                   &num_dom_groups,
431                                                   &dom_groups);
432         reset_cm_connection_on_error(domain, status);
433         if (!NT_STATUS_IS_OK(status)) {
434                 return status;
435         }
436
437         num_total = num_local_groups + num_dom_groups;
438         if (num_total > UINT32_MAX) {
439                 return NT_STATUS_INTERNAL_ERROR;
440         }
441
442         result = talloc_array(r->out.groups, struct wbint_Principal,
443                               num_total);
444         if (result == NULL) {
445                 return NT_STATUS_NO_MEMORY;
446         }
447
448         for (i = 0; i < num_local_groups; i++) {
449                 struct wb_acct_info *lg = &local_groups[i];
450                 struct wbint_Principal *rg = &result[ti++];
451
452                 sid_compose(&rg->sid, &domain->sid, lg->rid);
453                 rg->type = SID_NAME_ALIAS;
454                 rg->name = talloc_strdup(result, lg->acct_name);
455                 if (rg->name == NULL) {
456                         TALLOC_FREE(result);
457                         TALLOC_FREE(dom_groups);
458                         TALLOC_FREE(local_groups);
459                         return NT_STATUS_NO_MEMORY;
460                 }
461         }
462         num_local_groups = 0;
463         TALLOC_FREE(local_groups);
464
465         for (i = 0; i < num_dom_groups; i++) {
466                 struct wb_acct_info *dg = &dom_groups[i];
467                 struct wbint_Principal *rg = &result[ti++];
468
469                 sid_compose(&rg->sid, &domain->sid, dg->rid);
470                 rg->type = SID_NAME_DOM_GRP;
471                 rg->name = talloc_strdup(result, dg->acct_name);
472                 if (rg->name == NULL) {
473                         TALLOC_FREE(result);
474                         TALLOC_FREE(dom_groups);
475                         TALLOC_FREE(local_groups);
476                         return NT_STATUS_NO_MEMORY;
477                 }
478         }
479         num_dom_groups = 0;
480         TALLOC_FREE(dom_groups);
481
482         r->out.groups->num_principals = ti;
483         r->out.groups->principals = result;
484
485         return NT_STATUS_OK;
486 }
487
488 NTSTATUS _wbint_DsGetDcName(struct pipes_struct *p, struct wbint_DsGetDcName *r)
489 {
490         struct winbindd_domain *domain = wb_child_domain();
491         struct rpc_pipe_client *netlogon_pipe;
492         struct netr_DsRGetDCNameInfo *dc_info;
493         NTSTATUS status;
494         WERROR werr;
495         unsigned int orig_timeout;
496         struct dcerpc_binding_handle *b;
497
498         if (domain == NULL) {
499                 return dsgetdcname(p->mem_ctx, winbind_messaging_context(),
500                                    r->in.domain_name, r->in.domain_guid,
501                                    r->in.site_name ? r->in.site_name : "",
502                                    r->in.flags,
503                                    r->out.dc_info);
504         }
505
506         status = cm_connect_netlogon(domain, &netlogon_pipe);
507
508         reset_cm_connection_on_error(domain, status);
509         if (!NT_STATUS_IS_OK(status)) {
510                 DEBUG(10, ("Can't contact the NETLOGON pipe\n"));
511                 return status;
512         }
513
514         b = netlogon_pipe->binding_handle;
515
516         /* This call can take a long time - allow the server to time out.
517            35 seconds should do it. */
518
519         orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
520
521         if (domain->active_directory) {
522                 status = dcerpc_netr_DsRGetDCName(b,
523                         p->mem_ctx, domain->dcname,
524                         r->in.domain_name, NULL, r->in.domain_guid,
525                         r->in.flags, r->out.dc_info, &werr);
526                 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(werr)) {
527                         goto done;
528                 }
529                 if (reset_cm_connection_on_error(domain, status)) {
530                         /* Re-initialize. */
531                         status = cm_connect_netlogon(domain, &netlogon_pipe);
532
533                         reset_cm_connection_on_error(domain, status);
534                         if (!NT_STATUS_IS_OK(status)) {
535                                 DEBUG(10, ("Can't contact the NETLOGON pipe\n"));
536                                 return status;
537                         }
538
539                         b = netlogon_pipe->binding_handle;
540
541                         /* This call can take a long time - allow the server to time out.
542                            35 seconds should do it. */
543
544                         orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
545                 }
546         }
547
548         /*
549          * Fallback to less capable methods
550          */
551
552         dc_info = talloc_zero(r->out.dc_info, struct netr_DsRGetDCNameInfo);
553         if (dc_info == NULL) {
554                 status = NT_STATUS_NO_MEMORY;
555                 goto done;
556         }
557
558         if (r->in.flags & DS_PDC_REQUIRED) {
559                 status = dcerpc_netr_GetDcName(b,
560                         p->mem_ctx, domain->dcname,
561                         r->in.domain_name, &dc_info->dc_unc, &werr);
562         } else {
563                 status = dcerpc_netr_GetAnyDCName(b,
564                         p->mem_ctx, domain->dcname,
565                         r->in.domain_name, &dc_info->dc_unc, &werr);
566         }
567
568         reset_cm_connection_on_error(domain, status);
569         if (!NT_STATUS_IS_OK(status)) {
570                 DEBUG(10, ("dcerpc_netr_Get[Any]DCName failed: %s\n",
571                            nt_errstr(status)));
572                 goto done;
573         }
574         if (!W_ERROR_IS_OK(werr)) {
575                 DEBUG(10, ("dcerpc_netr_Get[Any]DCName failed: %s\n",
576                            win_errstr(werr)));
577                 status = werror_to_ntstatus(werr);
578                 goto done;
579         }
580
581         *r->out.dc_info = dc_info;
582         status = NT_STATUS_OK;
583
584 done:
585         /* And restore our original timeout. */
586         rpccli_set_timeout(netlogon_pipe, orig_timeout);
587
588         return status;
589 }
590
591 NTSTATUS _wbint_LookupRids(struct pipes_struct *p, struct wbint_LookupRids *r)
592 {
593         struct winbindd_domain *domain = wb_child_domain();
594         char *domain_name;
595         char **names;
596         enum lsa_SidType *types;
597         struct wbint_Principal *result;
598         NTSTATUS status;
599         int i;
600
601         if (domain == NULL) {
602                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
603         }
604
605         status = domain->methods->rids_to_names(
606                 domain, talloc_tos(), r->in.domain_sid, r->in.rids->rids,
607                 r->in.rids->num_rids, &domain_name, &names, &types);
608         reset_cm_connection_on_error(domain, status);
609         if (!NT_STATUS_IS_OK(status)) {
610                 return status;
611         }
612
613         *r->out.domain_name = talloc_move(r->out.domain_name, &domain_name);
614
615         result = talloc_array(p->mem_ctx, struct wbint_Principal,
616                               r->in.rids->num_rids);
617         if (result == NULL) {
618                 return NT_STATUS_NO_MEMORY;
619         }
620
621         for (i=0; i<r->in.rids->num_rids; i++) {
622                 sid_compose(&result[i].sid, r->in.domain_sid,
623                             r->in.rids->rids[i]);
624                 result[i].type = types[i];
625                 result[i].name = talloc_move(result, &names[i]);
626         }
627         TALLOC_FREE(types);
628         TALLOC_FREE(names);
629
630         r->out.names->num_principals = r->in.rids->num_rids;
631         r->out.names->principals = result;
632         return NT_STATUS_OK;
633 }
634
635 NTSTATUS _wbint_CheckMachineAccount(struct pipes_struct *p,
636                                     struct wbint_CheckMachineAccount *r)
637 {
638         struct winbindd_domain *domain;
639         int num_retries = 0;
640         NTSTATUS status;
641
642         domain = wb_child_domain();
643         if (domain == NULL) {
644                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
645         }
646
647 again:
648         invalidate_cm_connection(domain);
649         domain->conn.netlogon_force_reauth = true;
650
651         {
652                 struct rpc_pipe_client *netlogon_pipe;
653                 status = cm_connect_netlogon(domain, &netlogon_pipe);
654         }
655
656         /* There is a race condition between fetching the trust account
657            password and the periodic machine password change.  So it's
658            possible that the trust account password has been changed on us.
659            We are returned NT_STATUS_ACCESS_DENIED if this happens. */
660
661 #define MAX_RETRIES 3
662
663         if ((num_retries < MAX_RETRIES)
664             && NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
665                 num_retries++;
666                 goto again;
667         }
668
669         if (!NT_STATUS_IS_OK(status)) {
670                 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
671                 goto done;
672         }
673
674         /* Pass back result code - zero for success, other values for
675            specific failures. */
676
677         DEBUG(3,("domain %s secret is %s\n", domain->name,
678                 NT_STATUS_IS_OK(status) ? "good" : "bad"));
679
680  done:
681         DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
682               ("Checking the trust account password for domain %s returned %s\n",
683                domain->name, nt_errstr(status)));
684
685         return status;
686 }
687
688 NTSTATUS _wbint_ChangeMachineAccount(struct pipes_struct *p,
689                                      struct wbint_ChangeMachineAccount *r)
690 {
691         struct messaging_context *msg_ctx = winbind_messaging_context();
692         struct winbindd_domain *domain;
693         NTSTATUS status;
694         struct rpc_pipe_client *netlogon_pipe;
695
696         domain = wb_child_domain();
697         if (domain == NULL) {
698                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
699         }
700
701         status = cm_connect_netlogon(domain, &netlogon_pipe);
702         if (!NT_STATUS_IS_OK(status)) {
703                 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
704                 goto done;
705         }
706
707         status = trust_pw_change(domain->conn.netlogon_creds,
708                                  msg_ctx,
709                                  netlogon_pipe->binding_handle,
710                                  domain->name,
711                                  true); /* force */
712
713         /* Pass back result code - zero for success, other values for
714            specific failures. */
715
716         DEBUG(3,("domain %s secret %s\n", domain->name,
717                 NT_STATUS_IS_OK(status) ? "changed" : "unchanged"));
718
719  done:
720         DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
721               ("Changing the trust account password for domain %s returned %s\n",
722                domain->name, nt_errstr(status)));
723
724         return status;
725 }
726
727 NTSTATUS _wbint_PingDc(struct pipes_struct *p, struct wbint_PingDc *r)
728 {
729         NTSTATUS status;
730         struct winbindd_domain *domain;
731         struct rpc_pipe_client *netlogon_pipe;
732         union netr_CONTROL_QUERY_INFORMATION info;
733         WERROR werr;
734         fstring logon_server;
735         struct dcerpc_binding_handle *b;
736         bool retry = false;
737
738         domain = wb_child_domain();
739         if (domain == NULL) {
740                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
741         }
742
743 reconnect:
744         status = cm_connect_netlogon(domain, &netlogon_pipe);
745         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
746                 /*
747                  * Retry to open new connection with new kerberos ticket.
748                  */
749                 invalidate_cm_connection(domain);
750                 status = cm_connect_netlogon(domain, &netlogon_pipe);
751         }
752
753         reset_cm_connection_on_error(domain, status);
754         if (!NT_STATUS_IS_OK(status)) {
755                 DEBUG(3, ("could not open handle to NETLOGON pipe: %s\n",
756                           nt_errstr(status)));
757                 return status;
758         }
759
760         b = netlogon_pipe->binding_handle;
761
762         fstr_sprintf(logon_server, "\\\\%s", domain->dcname);
763         *r->out.dcname = talloc_strdup(p->mem_ctx, domain->dcname);
764         if (*r->out.dcname == NULL) {
765                 DEBUG(2, ("Could not allocate memory\n"));
766                 return NT_STATUS_NO_MEMORY;
767         }
768
769         /*
770          * This provokes a WERR_NOT_SUPPORTED error message. This is
771          * documented in the wspp docs. I could not get a successful
772          * call to work, but the main point here is testing that the
773          * netlogon pipe works.
774          */
775         status = dcerpc_netr_LogonControl(b, p->mem_ctx,
776                                           logon_server, NETLOGON_CONTROL_QUERY,
777                                           2, &info, &werr);
778
779         if (!dcerpc_binding_handle_is_connected(b) && !retry) {
780                 DEBUG(10, ("Session might have expired. "
781                            "Reconnect and retry once.\n"));
782                 invalidate_cm_connection(domain);
783                 retry = true;
784                 goto reconnect;
785         }
786
787         reset_cm_connection_on_error(domain, status);
788         if (!NT_STATUS_IS_OK(status)) {
789                 DEBUG(2, ("dcerpc_netr_LogonControl failed: %s\n",
790                         nt_errstr(status)));
791                 return status;
792         }
793
794         if (!W_ERROR_EQUAL(werr, WERR_NOT_SUPPORTED)) {
795                 DEBUG(2, ("dcerpc_netr_LogonControl returned %s, expected "
796                           "WERR_NOT_SUPPORTED\n",
797                           win_errstr(werr)));
798                 return werror_to_ntstatus(werr);
799         }
800
801         DEBUG(5, ("winbindd_dual_ping_dc succeeded\n"));
802         return NT_STATUS_OK;
803 }
804
805 NTSTATUS _winbind_DsrUpdateReadOnlyServerDnsRecords(struct pipes_struct *p,
806                                                     struct winbind_DsrUpdateReadOnlyServerDnsRecords *r)
807 {
808         struct winbindd_domain *domain;
809         NTSTATUS status;
810         struct rpc_pipe_client *netlogon_pipe;
811
812         domain = wb_child_domain();
813         if (domain == NULL) {
814                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
815         }
816
817         status = cm_connect_netlogon(domain, &netlogon_pipe);
818         if (!NT_STATUS_IS_OK(status)) {
819                 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
820                 goto done;
821         }
822
823         status = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(domain->conn.netlogon_creds,
824                                                                       netlogon_pipe->binding_handle,
825                                                                       r->in.site_name,
826                                                                       r->in.dns_ttl,
827                                                                       r->in.dns_names);
828
829         /* Pass back result code - zero for success, other values for
830            specific failures. */
831
832         DEBUG(3,("DNS records for domain %s %s\n", domain->name,
833                 NT_STATUS_IS_OK(status) ? "changed" : "unchanged"));
834
835  done:
836         DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
837               ("Update of DNS records via RW DC %s returned %s\n",
838                domain->name, nt_errstr(status)));
839
840         return status;
841 }
842
843 NTSTATUS _winbind_SamLogon(struct pipes_struct *p,
844                         struct winbind_SamLogon *r)
845 {
846         struct winbindd_domain *domain;
847         NTSTATUS status;
848         DATA_BLOB lm_response, nt_response;
849         domain = wb_child_domain();
850         if (domain == NULL) {
851                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
852         }
853
854         /* TODO: Handle interactive logons here */
855         if (r->in.validation_level != 3 ||
856             r->in.logon.network == NULL ||
857             (r->in.logon_level != NetlogonNetworkInformation
858              && r->in.logon_level != NetlogonNetworkTransitiveInformation)) {
859                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
860         }
861
862
863         lm_response = data_blob_talloc(p->mem_ctx, r->in.logon.network->lm.data, r->in.logon.network->lm.length);
864         nt_response = data_blob_talloc(p->mem_ctx, r->in.logon.network->nt.data, r->in.logon.network->nt.length);
865
866         status = winbind_dual_SamLogon(domain, p->mem_ctx,
867                                        r->in.logon.network->identity_info.parameter_control,
868                                        r->in.logon.network->identity_info.account_name.string,
869                                        r->in.logon.network->identity_info.domain_name.string,
870                                        r->in.logon.network->identity_info.workstation.string,
871                                        r->in.logon.network->challenge,
872                                        lm_response, nt_response, &r->out.validation.sam3);
873         return status;
874 }
875
876 static WERROR _winbind_LogonControl_REDISCOVER(struct pipes_struct *p,
877                              struct winbindd_domain *domain,
878                              struct winbind_LogonControl *r)
879 {
880         NTSTATUS status;
881         struct rpc_pipe_client *netlogon_pipe = NULL;
882         struct netr_NETLOGON_INFO_2 *info2 = NULL;
883         WERROR check_result = WERR_INTERNAL_ERROR;
884
885         info2 = talloc_zero(p->mem_ctx, struct netr_NETLOGON_INFO_2);
886         if (info2 == NULL) {
887                 return WERR_NOMEM;
888         }
889
890         if (domain->internal) {
891                 check_result = WERR_OK;
892                 goto check_return;
893         }
894
895         /*
896          * For now we just force a reconnect
897          *
898          * TODO: take care of the optional '\dcname'
899          */
900         invalidate_cm_connection(domain);
901         domain->conn.netlogon_force_reauth = true;
902         status = cm_connect_netlogon(domain, &netlogon_pipe);
903         reset_cm_connection_on_error(domain, status);
904         if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
905                 status = NT_STATUS_NO_LOGON_SERVERS;
906         }
907         if (!NT_STATUS_IS_OK(status)) {
908                 DEBUG(2, ("%s: domain[%s/%s] cm_connect_netlogon() returned %s\n",
909                           __func__, domain->name, domain->alt_name,
910                           nt_errstr(status)));
911                 /*
912                  * Here we return a top level error!
913                  * This is different than TC_QUERY or TC_VERIFY.
914                  */
915                 return ntstatus_to_werror(status);
916         }
917         check_result = WERR_OK;
918
919 check_return:
920         info2->pdc_connection_status = WERR_OK;
921         if (domain->dcname != NULL) {
922                 info2->flags |= NETLOGON_HAS_IP;
923                 info2->flags |= NETLOGON_HAS_TIMESERV;
924                 info2->trusted_dc_name = talloc_asprintf(info2, "\\\\%s",
925                                                          domain->dcname);
926                 if (info2->trusted_dc_name == NULL) {
927                         return WERR_NOMEM;
928                 }
929         } else {
930                 info2->trusted_dc_name = talloc_strdup(info2, "");
931                 if (info2->trusted_dc_name == NULL) {
932                         return WERR_NOMEM;
933                 }
934         }
935         info2->tc_connection_status = check_result;
936
937         if (!W_ERROR_IS_OK(info2->pdc_connection_status)) {
938                 DEBUG(2, ("%s: domain[%s/%s] dcname[%s] "
939                           "pdc_connection[%s] tc_connection[%s]\n",
940                           __func__, domain->name, domain->alt_name,
941                           domain->dcname,
942                           win_errstr(info2->pdc_connection_status),
943                           win_errstr(info2->tc_connection_status)));
944         }
945
946         r->out.query->info2 = info2;
947
948         DEBUG(5, ("%s: succeeded.\n", __func__));
949         return WERR_OK;
950 }
951
952 static WERROR _winbind_LogonControl_TC_QUERY(struct pipes_struct *p,
953                              struct winbindd_domain *domain,
954                              struct winbind_LogonControl *r)
955 {
956         NTSTATUS status;
957         struct rpc_pipe_client *netlogon_pipe = NULL;
958         struct netr_NETLOGON_INFO_2 *info2 = NULL;
959         WERROR check_result = WERR_INTERNAL_ERROR;
960
961         info2 = talloc_zero(p->mem_ctx, struct netr_NETLOGON_INFO_2);
962         if (info2 == NULL) {
963                 return WERR_NOMEM;
964         }
965
966         if (domain->internal) {
967                 check_result = WERR_OK;
968                 goto check_return;
969         }
970
971         status = cm_connect_netlogon(domain, &netlogon_pipe);
972         reset_cm_connection_on_error(domain, status);
973         if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
974                 status = NT_STATUS_NO_LOGON_SERVERS;
975         }
976         if (!NT_STATUS_IS_OK(status)) {
977                 DEBUG(3, ("could not open handle to NETLOGON pipe: %s\n",
978                           nt_errstr(status)));
979                 check_result = ntstatus_to_werror(status);
980                 goto check_return;
981         }
982         check_result = WERR_OK;
983
984 check_return:
985         info2->pdc_connection_status = WERR_OK;
986         if (domain->dcname != NULL) {
987                 info2->flags |= NETLOGON_HAS_IP;
988                 info2->flags |= NETLOGON_HAS_TIMESERV;
989                 info2->trusted_dc_name = talloc_asprintf(info2, "\\\\%s",
990                                                          domain->dcname);
991                 if (info2->trusted_dc_name == NULL) {
992                         return WERR_NOMEM;
993                 }
994         } else {
995                 info2->trusted_dc_name = talloc_strdup(info2, "");
996                 if (info2->trusted_dc_name == NULL) {
997                         return WERR_NOMEM;
998                 }
999         }
1000         info2->tc_connection_status = check_result;
1001
1002         if (!W_ERROR_IS_OK(info2->pdc_connection_status)) {
1003                 DEBUG(2, ("%s: domain[%s/%s] dcname[%s] "
1004                           "pdc_connection[%s] tc_connection[%s]\n",
1005                           __func__, domain->name, domain->alt_name,
1006                           domain->dcname,
1007                           win_errstr(info2->pdc_connection_status),
1008                           win_errstr(info2->tc_connection_status)));
1009         }
1010
1011         r->out.query->info2 = info2;
1012
1013         DEBUG(5, ("%s: succeeded.\n", __func__));
1014         return WERR_OK;
1015 }
1016
1017 static WERROR _winbind_LogonControl_TC_VERIFY(struct pipes_struct *p,
1018                              struct winbindd_domain *domain,
1019                              struct winbind_LogonControl *r)
1020 {
1021         TALLOC_CTX *frame = talloc_stackframe();
1022         NTSTATUS status;
1023         NTSTATUS result;
1024         struct lsa_String trusted_domain_name = {};
1025         struct lsa_StringLarge trusted_domain_name_l = {};
1026         struct rpc_pipe_client *local_lsa_pipe = NULL;
1027         struct policy_handle local_lsa_policy = {};
1028         struct dcerpc_binding_handle *local_lsa = NULL;
1029         struct rpc_pipe_client *netlogon_pipe = NULL;
1030         struct cli_credentials *creds = NULL;
1031         struct samr_Password *cur_nt_hash = NULL;
1032         uint32_t trust_attributes = 0;
1033         struct samr_Password new_owf_password = {};
1034         int cmp_new = -1;
1035         struct samr_Password old_owf_password = {};
1036         int cmp_old = -1;
1037         const struct lsa_TrustDomainInfoInfoEx *local_tdo = NULL;
1038         bool fetch_fti = false;
1039         struct lsa_ForestTrustInformation *new_fti = NULL;
1040         struct netr_TrustInfo *trust_info = NULL;
1041         struct netr_NETLOGON_INFO_2 *info2 = NULL;
1042         struct dcerpc_binding_handle *b = NULL;
1043         WERROR check_result = WERR_INTERNAL_ERROR;
1044         WERROR verify_result = WERR_INTERNAL_ERROR;
1045         bool retry = false;
1046
1047         trusted_domain_name.string = domain->name;
1048         trusted_domain_name_l.string = domain->name;
1049
1050         info2 = talloc_zero(p->mem_ctx, struct netr_NETLOGON_INFO_2);
1051         if (info2 == NULL) {
1052                 TALLOC_FREE(frame);
1053                 return WERR_NOMEM;
1054         }
1055
1056         if (domain->internal) {
1057                 check_result = WERR_OK;
1058                 goto check_return;
1059         }
1060
1061         status = pdb_get_trust_credentials(domain->name,
1062                                            domain->alt_name,
1063                                            frame,
1064                                            &creds);
1065         if (NT_STATUS_IS_OK(status)) {
1066                 cur_nt_hash = cli_credentials_get_nt_hash(creds, frame);
1067                 TALLOC_FREE(creds);
1068         }
1069
1070         if (!domain->primary) {
1071                 union lsa_TrustedDomainInfo *tdi = NULL;
1072
1073                 status = open_internal_lsa_conn(frame, &local_lsa_pipe,
1074                                                 &local_lsa_policy);
1075                 if (!NT_STATUS_IS_OK(status)) {
1076                         DEBUG(0,("%s:%s: open_internal_lsa_conn() failed - %s\n",
1077                                  __location__, __func__, nt_errstr(status)));
1078                         TALLOC_FREE(frame);
1079                         return WERR_INTERNAL_ERROR;
1080                 }
1081                 local_lsa = local_lsa_pipe->binding_handle;
1082
1083                 status = dcerpc_lsa_QueryTrustedDomainInfoByName(local_lsa, frame,
1084                                                         &local_lsa_policy,
1085                                                         &trusted_domain_name,
1086                                                         LSA_TRUSTED_DOMAIN_INFO_INFO_EX,
1087                                                         &tdi, &result);
1088                 if (!NT_STATUS_IS_OK(status)) {
1089                         DEBUG(0,("%s:%s: local_lsa.QueryTrustedDomainInfoByName(%s) failed - %s\n",
1090                                  __location__, __func__, domain->name, nt_errstr(status)));
1091                         TALLOC_FREE(frame);
1092                         return WERR_INTERNAL_ERROR;
1093                 }
1094                 if (NT_STATUS_EQUAL(result, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1095                         DEBUG(1,("%s:%s: domain[%s] not found via LSA, might be removed already.\n",
1096                                  __location__, __func__, domain->name));
1097                         TALLOC_FREE(frame);
1098                         return WERR_NO_SUCH_DOMAIN;
1099                 }
1100                 if (!NT_STATUS_IS_OK(result)) {
1101                         DEBUG(0,("%s:%s: local_lsa.QueryTrustedDomainInfoByName(%s) returned %s\n",
1102                                  __location__, __func__, domain->name, nt_errstr(result)));
1103                         TALLOC_FREE(frame);
1104                         return WERR_INTERNAL_ERROR;
1105                 }
1106                 if (tdi == NULL) {
1107                         DEBUG(0,("%s:%s: local_lsa.QueryTrustedDomainInfoByName() "
1108                                  "returned no trusted domain information\n",
1109                                  __location__, __func__));
1110                         TALLOC_FREE(frame);
1111                         return WERR_INTERNAL_ERROR;
1112                 }
1113
1114                 local_tdo = &tdi->info_ex;
1115                 trust_attributes = local_tdo->trust_attributes;
1116         }
1117
1118         if (trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1119                 struct lsa_ForestTrustInformation *old_fti = NULL;
1120
1121                 status = dcerpc_lsa_lsaRQueryForestTrustInformation(local_lsa, frame,
1122                                                         &local_lsa_policy,
1123                                                         &trusted_domain_name,
1124                                                         LSA_FOREST_TRUST_DOMAIN_INFO,
1125                                                         &old_fti, &result);
1126                 if (!NT_STATUS_IS_OK(status)) {
1127                         DEBUG(0,("%s:%s: local_lsa.lsaRQueryForestTrustInformation(%s) failed %s\n",
1128                                  __location__, __func__, domain->name, nt_errstr(status)));
1129                         TALLOC_FREE(frame);
1130                         return WERR_INTERNAL_ERROR;
1131                 }
1132                 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_FOUND)) {
1133                         DEBUG(2,("%s: no forest trust information available for domain[%s] yet.\n",
1134                                   __func__, domain->name));
1135                         old_fti = NULL;
1136                         fetch_fti = true;
1137                         result = NT_STATUS_OK;
1138                 }
1139                 if (!NT_STATUS_IS_OK(result)) {
1140                         DEBUG(0,("%s:%s: local_lsa.lsaRQueryForestTrustInformation(%s) returned %s\n",
1141                                  __location__, __func__, domain->name, nt_errstr(result)));
1142                         TALLOC_FREE(frame);
1143                         return WERR_INTERNAL_ERROR;
1144                 }
1145
1146                 TALLOC_FREE(old_fti);
1147         }
1148
1149 reconnect:
1150         status = cm_connect_netlogon(domain, &netlogon_pipe);
1151         reset_cm_connection_on_error(domain, status);
1152         if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1153                 status = NT_STATUS_NO_LOGON_SERVERS;
1154         }
1155         if (!NT_STATUS_IS_OK(status)) {
1156                 DEBUG(3, ("could not open handle to NETLOGON pipe: %s\n",
1157                           nt_errstr(status)));
1158                 check_result = ntstatus_to_werror(status);
1159                 goto check_return;
1160         }
1161         check_result = WERR_OK;
1162         b = netlogon_pipe->binding_handle;
1163
1164         if (cur_nt_hash == NULL) {
1165                 verify_result = WERR_NO_TRUST_LSA_SECRET;
1166                 goto verify_return;
1167         }
1168
1169         if (fetch_fti) {
1170                 status = netlogon_creds_cli_GetForestTrustInformation(domain->conn.netlogon_creds,
1171                                                                       b, frame,
1172                                                                       &new_fti);
1173                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1174                         status = NT_STATUS_NOT_SUPPORTED;
1175                 }
1176                 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
1177                         new_fti = NULL;
1178                         status = NT_STATUS_OK;
1179                 }
1180                 if (!NT_STATUS_IS_OK(status)) {
1181                         if (!retry && dcerpc_binding_handle_is_connected(b)) {
1182                                 invalidate_cm_connection(domain);
1183                                 retry = true;
1184                                 goto reconnect;
1185                         }
1186                         DEBUG(2, ("netlogon_creds_cli_GetForestTrustInformation(%s)"
1187                                   "failed: %s\n",
1188                                   domain->name, nt_errstr(status)));
1189                         check_result = ntstatus_to_werror(status);
1190                         goto check_return;
1191                 }
1192         }
1193
1194         if (new_fti != NULL) {
1195                 struct lsa_ForestTrustInformation old_fti = {};
1196                 struct lsa_ForestTrustInformation *merged_fti = NULL;
1197                 struct lsa_ForestTrustCollisionInfo *collision_info = NULL;
1198
1199                 status = dsdb_trust_merge_forest_info(frame, local_tdo,
1200                                                       &old_fti, new_fti,
1201                                                       &merged_fti);
1202                 if (!NT_STATUS_IS_OK(status)) {
1203                         DEBUG(0,("%s:%s: dsdb_trust_merge_forest_info(%s) failed %s\n",
1204                                  __location__, __func__,
1205                                  domain->name, nt_errstr(status)));
1206                         TALLOC_FREE(frame);
1207                         return ntstatus_to_werror(status);
1208                 }
1209
1210                 status = dcerpc_lsa_lsaRSetForestTrustInformation(local_lsa, frame,
1211                                                 &local_lsa_policy,
1212                                                 &trusted_domain_name_l,
1213                                                 LSA_FOREST_TRUST_DOMAIN_INFO,
1214                                                 merged_fti,
1215                                                 0, /* check_only=0 => store it! */
1216                                                 &collision_info,
1217                                                 &result);
1218                 if (!NT_STATUS_IS_OK(status)) {
1219                         DEBUG(0,("%s:%s: local_lsa.lsaRSetForestTrustInformation(%s) failed %s\n",
1220                                  __location__, __func__, domain->name, nt_errstr(status)));
1221                         TALLOC_FREE(frame);
1222                         return WERR_INTERNAL_ERROR;
1223                 }
1224                 if (!NT_STATUS_IS_OK(result)) {
1225                         DEBUG(0,("%s:%s: local_lsa.lsaRSetForestTrustInformation(%s) returned %s\n",
1226                                  __location__, __func__, domain->name, nt_errstr(result)));
1227                         TALLOC_FREE(frame);
1228                         return ntstatus_to_werror(result);
1229                 }
1230         }
1231
1232         status = netlogon_creds_cli_ServerGetTrustInfo(domain->conn.netlogon_creds,
1233                                                        b, frame,
1234                                                        &new_owf_password,
1235                                                        &old_owf_password,
1236                                                        &trust_info);
1237         if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
1238                 status = NT_STATUS_NOT_SUPPORTED;
1239         }
1240         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
1241                 DEBUG(5, ("netlogon_creds_cli_ServerGetTrustInfo failed: %s\n",
1242                         nt_errstr(status)));
1243                 verify_result = WERR_OK;
1244                 goto verify_return;
1245         }
1246         if (!NT_STATUS_IS_OK(status)) {
1247                 if (!retry && dcerpc_binding_handle_is_connected(b)) {
1248                         invalidate_cm_connection(domain);
1249                         retry = true;
1250                         goto reconnect;
1251                 }
1252                 DEBUG(2, ("netlogon_creds_cli_ServerGetTrustInfo failed: %s\n",
1253                         nt_errstr(status)));
1254
1255                 if (!dcerpc_binding_handle_is_connected(b)) {
1256                         check_result = ntstatus_to_werror(status);
1257                         goto check_return;
1258                 } else {
1259                         verify_result = ntstatus_to_werror(status);
1260                         goto verify_return;
1261                 }
1262         }
1263
1264         if (trust_info != NULL && trust_info->count >= 1) {
1265                 uint32_t diff = trust_info->data[0] ^ trust_attributes;
1266
1267                 if (diff & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1268                         verify_result = WERR_DOMAIN_TRUST_INCONSISTENT;
1269                         goto verify_return;
1270                 }
1271         }
1272
1273         cmp_new = memcmp(new_owf_password.hash,
1274                          cur_nt_hash->hash,
1275                          sizeof(cur_nt_hash->hash));
1276         cmp_old = memcmp(old_owf_password.hash,
1277                          cur_nt_hash->hash,
1278                          sizeof(cur_nt_hash->hash));
1279         if (cmp_new != 0 && cmp_old != 0) {
1280                 DEBUG(1,("%s:Error: credentials for domain[%s/%s] doesn't match "
1281                          "any password known to dcname[%s]\n",
1282                          __func__, domain->name, domain->alt_name,
1283                          domain->dcname));
1284                 verify_result = WERR_WRONG_PASSWORD;
1285                 goto verify_return;
1286         }
1287
1288         if (cmp_new != 0) {
1289                 DEBUG(2,("%s:Warning: credentials for domain[%s/%s] only match "
1290                          "against the old password known to dcname[%s]\n",
1291                          __func__, domain->name, domain->alt_name,
1292                          domain->dcname));
1293         }
1294
1295         verify_result = WERR_OK;
1296         goto verify_return;
1297
1298 check_return:
1299         verify_result = check_result;
1300 verify_return:
1301         info2->flags |= NETLOGON_VERIFY_STATUS_RETURNED;
1302         info2->pdc_connection_status = verify_result;
1303         if (domain->dcname != NULL) {
1304                 info2->flags |= NETLOGON_HAS_IP;
1305                 info2->flags |= NETLOGON_HAS_TIMESERV;
1306                 info2->trusted_dc_name = talloc_asprintf(info2, "\\\\%s",
1307                                                          domain->dcname);
1308                 if (info2->trusted_dc_name == NULL) {
1309                         TALLOC_FREE(frame);
1310                         return WERR_NOMEM;
1311                 }
1312         } else {
1313                 info2->trusted_dc_name = talloc_strdup(info2, "");
1314                 if (info2->trusted_dc_name == NULL) {
1315                         TALLOC_FREE(frame);
1316                         return WERR_NOMEM;
1317                 }
1318         }
1319         info2->tc_connection_status = check_result;
1320
1321         if (!W_ERROR_IS_OK(info2->pdc_connection_status)) {
1322                 DEBUG(2, ("%s: domain[%s/%s] dcname[%s] "
1323                           "pdc_connection[%s] tc_connection[%s]\n",
1324                           __func__, domain->name, domain->alt_name,
1325                           domain->dcname,
1326                           win_errstr(info2->pdc_connection_status),
1327                           win_errstr(info2->tc_connection_status)));
1328         }
1329
1330         r->out.query->info2 = info2;
1331
1332         DEBUG(5, ("%s: succeeded.\n", __func__));
1333         TALLOC_FREE(frame);
1334         return WERR_OK;
1335 }
1336
1337 static WERROR _winbind_LogonControl_CHANGE_PASSWORD(struct pipes_struct *p,
1338                              struct winbindd_domain *domain,
1339                              struct winbind_LogonControl *r)
1340 {
1341         struct messaging_context *msg_ctx = winbind_messaging_context();
1342         NTSTATUS status;
1343         struct rpc_pipe_client *netlogon_pipe;
1344         struct cli_credentials *creds = NULL;
1345         struct samr_Password *cur_nt_hash = NULL;
1346         struct netr_NETLOGON_INFO_1 *info1 = NULL;
1347         struct dcerpc_binding_handle *b;
1348         WERROR change_result = WERR_OK;
1349         bool retry = false;
1350
1351         info1 = talloc_zero(p->mem_ctx, struct netr_NETLOGON_INFO_1);
1352         if (info1 == NULL) {
1353                 return WERR_NOMEM;
1354         }
1355
1356         if (domain->internal) {
1357                 return WERR_NOT_SUPPORTED;
1358         }
1359
1360         status = pdb_get_trust_credentials(domain->name,
1361                                            domain->alt_name,
1362                                            p->mem_ctx,
1363                                            &creds);
1364         if (NT_STATUS_IS_OK(status)) {
1365                 cur_nt_hash = cli_credentials_get_nt_hash(creds, p->mem_ctx);
1366                 TALLOC_FREE(creds);
1367         }
1368
1369 reconnect:
1370         status = cm_connect_netlogon(domain, &netlogon_pipe);
1371         reset_cm_connection_on_error(domain, status);
1372         if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1373                 status = NT_STATUS_NO_LOGON_SERVERS;
1374         }
1375         if (!NT_STATUS_IS_OK(status)) {
1376                 DEBUG(2, ("%s: domain[%s/%s] cm_connect_netlogon() returned %s\n",
1377                           __func__, domain->name, domain->alt_name,
1378                           nt_errstr(status)));
1379                 /*
1380                  * Here we return a top level error!
1381                  * This is different than TC_QUERY or TC_VERIFY.
1382                  */
1383                 return ntstatus_to_werror(status);
1384         }
1385         b = netlogon_pipe->binding_handle;
1386
1387         if (cur_nt_hash == NULL) {
1388                 change_result = WERR_NO_TRUST_LSA_SECRET;
1389                 goto change_return;
1390         }
1391         TALLOC_FREE(cur_nt_hash);
1392
1393         status = trust_pw_change(domain->conn.netlogon_creds,
1394                                  msg_ctx, b, domain->name,
1395                                  true); /* force */
1396         if (!NT_STATUS_IS_OK(status)) {
1397                 if (!retry && dcerpc_binding_handle_is_connected(b)) {
1398                         invalidate_cm_connection(domain);
1399                         retry = true;
1400                         goto reconnect;
1401                 }
1402
1403                 DEBUG(1, ("trust_pw_change(%s): %s\n",
1404                           domain->name, nt_errstr(status)));
1405
1406                 change_result = ntstatus_to_werror(status);
1407                 goto change_return;
1408         }
1409
1410         change_result = WERR_OK;
1411
1412 change_return:
1413         info1->pdc_connection_status = change_result;
1414
1415         if (!W_ERROR_IS_OK(info1->pdc_connection_status)) {
1416                 DEBUG(2, ("%s: domain[%s/%s] dcname[%s] "
1417                           "pdc_connection[%s]\n",
1418                           __func__, domain->name, domain->alt_name,
1419                           domain->dcname,
1420                           win_errstr(info1->pdc_connection_status)));
1421         }
1422
1423         r->out.query->info1 = info1;
1424
1425         DEBUG(5, ("%s: succeeded.\n", __func__));
1426         return WERR_OK;
1427 }
1428
1429 WERROR _winbind_LogonControl(struct pipes_struct *p,
1430                              struct winbind_LogonControl *r)
1431 {
1432         struct winbindd_domain *domain;
1433
1434         domain = wb_child_domain();
1435         if (domain == NULL) {
1436                 return WERR_NO_SUCH_DOMAIN;
1437         }
1438
1439         switch (r->in.function_code) {
1440         case NETLOGON_CONTROL_REDISCOVER:
1441                 if (r->in.level != 2) {
1442                         return WERR_INVALID_PARAMETER;
1443                 }
1444                 return _winbind_LogonControl_REDISCOVER(p, domain, r);
1445         case NETLOGON_CONTROL_TC_QUERY:
1446                 if (r->in.level != 2) {
1447                         return WERR_INVALID_PARAMETER;
1448                 }
1449                 return _winbind_LogonControl_TC_QUERY(p, domain, r);
1450         case NETLOGON_CONTROL_TC_VERIFY:
1451                 if (r->in.level != 2) {
1452                         return WERR_INVALID_PARAMETER;
1453                 }
1454                 return _winbind_LogonControl_TC_VERIFY(p, domain, r);
1455         case NETLOGON_CONTROL_CHANGE_PASSWORD:
1456                 if (r->in.level != 1) {
1457                         return WERR_INVALID_PARAMETER;
1458                 }
1459                 return _winbind_LogonControl_CHANGE_PASSWORD(p, domain, r);
1460         default:
1461                 break;
1462         }
1463
1464         DEBUG(4, ("%s: function_code[0x%x] not supported\n",
1465                   __func__, r->in.function_code));
1466         return WERR_NOT_SUPPORTED;
1467 }
1468
1469 WERROR _winbind_GetForestTrustInformation(struct pipes_struct *p,
1470                              struct winbind_GetForestTrustInformation *r)
1471 {
1472         TALLOC_CTX *frame = talloc_stackframe();
1473         NTSTATUS status, result;
1474         struct winbindd_domain *domain;
1475         struct rpc_pipe_client *netlogon_pipe;
1476         struct dcerpc_binding_handle *b;
1477         bool retry = false;
1478         struct lsa_String trusted_domain_name = {};
1479         struct lsa_StringLarge trusted_domain_name_l = {};
1480         union lsa_TrustedDomainInfo *tdi = NULL;
1481         const struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
1482         struct lsa_ForestTrustInformation _old_fti = {};
1483         struct lsa_ForestTrustInformation *old_fti = NULL;
1484         struct lsa_ForestTrustInformation *new_fti = NULL;
1485         struct lsa_ForestTrustInformation *merged_fti = NULL;
1486         struct lsa_ForestTrustCollisionInfo *collision_info = NULL;
1487         bool update_fti = false;
1488         struct rpc_pipe_client *local_lsa_pipe;
1489         struct policy_handle local_lsa_policy;
1490         struct dcerpc_binding_handle *local_lsa = NULL;
1491
1492         domain = wb_child_domain();
1493         if (domain == NULL) {
1494                 TALLOC_FREE(frame);
1495                 return WERR_NO_SUCH_DOMAIN;
1496         }
1497
1498         /*
1499          * checking for domain->internal and domain->primary
1500          * makes sure we only do some work when running as DC.
1501          */
1502
1503         if (domain->internal) {
1504                 TALLOC_FREE(frame);
1505                 return WERR_NO_SUCH_DOMAIN;
1506         }
1507
1508         if (domain->primary) {
1509                 TALLOC_FREE(frame);
1510                 return WERR_NO_SUCH_DOMAIN;
1511         }
1512
1513         trusted_domain_name.string = domain->name;
1514         trusted_domain_name_l.string = domain->name;
1515
1516         status = open_internal_lsa_conn(frame, &local_lsa_pipe,
1517                                         &local_lsa_policy);
1518         if (!NT_STATUS_IS_OK(status)) {
1519                 DEBUG(0,("%s:%s: open_internal_lsa_conn() failed - %s\n",
1520                          __location__, __func__, nt_errstr(status)));
1521                 TALLOC_FREE(frame);
1522                 return WERR_INTERNAL_ERROR;
1523         }
1524         local_lsa = local_lsa_pipe->binding_handle;
1525
1526         status = dcerpc_lsa_QueryTrustedDomainInfoByName(local_lsa, frame,
1527                                                 &local_lsa_policy,
1528                                                 &trusted_domain_name,
1529                                                 LSA_TRUSTED_DOMAIN_INFO_INFO_EX,
1530                                                 &tdi, &result);
1531         if (!NT_STATUS_IS_OK(status)) {
1532                 DEBUG(0,("%s:%s: local_lsa.QueryTrustedDomainInfoByName(%s) failed - %s\n",
1533                          __location__, __func__, domain->name, nt_errstr(status)));
1534                 TALLOC_FREE(frame);
1535                 return WERR_INTERNAL_ERROR;
1536         }
1537         if (NT_STATUS_EQUAL(result, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1538                 DEBUG(1,("%s:%s: domain[%s] not found via LSA, might be removed already.\n",
1539                          __location__, __func__, domain->name));
1540                 TALLOC_FREE(frame);
1541                 return WERR_NO_SUCH_DOMAIN;
1542         }
1543         if (!NT_STATUS_IS_OK(result)) {
1544                 DEBUG(0,("%s:%s: local_lsa.QueryTrustedDomainInfoByName(%s) returned %s\n",
1545                          __location__, __func__, domain->name, nt_errstr(result)));
1546                 TALLOC_FREE(frame);
1547                 return WERR_INTERNAL_ERROR;
1548         }
1549         if (tdi == NULL) {
1550                 DEBUG(0,("%s:%s: local_lsa.QueryTrustedDomainInfoByName() "
1551                          "returned no trusted domain information\n",
1552                          __location__, __func__));
1553                 TALLOC_FREE(frame);
1554                 return WERR_INTERNAL_ERROR;
1555         }
1556
1557         tdo = &tdi->info_ex;
1558
1559         if (!(tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
1560                 DEBUG(2,("%s: tdo[%s/%s] is no forest trust attributes[0x%08X]\n",
1561                          __func__, tdo->netbios_name.string,
1562                          tdo->domain_name.string,
1563                          (unsigned)tdo->trust_attributes));
1564                 TALLOC_FREE(frame);
1565                 return WERR_NO_SUCH_DOMAIN;
1566         }
1567
1568         if (r->in.flags & ~DS_GFTI_UPDATE_TDO) {
1569                 TALLOC_FREE(frame);
1570                 return WERR_INVALID_FLAGS;
1571         }
1572
1573 reconnect:
1574         status = cm_connect_netlogon(domain, &netlogon_pipe);
1575         reset_cm_connection_on_error(domain, status);
1576         if (NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1577                 status = NT_STATUS_NO_LOGON_SERVERS;
1578         }
1579         if (!NT_STATUS_IS_OK(status)) {
1580                 DEBUG(3, ("could not open handle to NETLOGON pipe: %s\n",
1581                           nt_errstr(status)));
1582                 TALLOC_FREE(frame);
1583                 return ntstatus_to_werror(status);
1584         }
1585         b = netlogon_pipe->binding_handle;
1586
1587         status = netlogon_creds_cli_GetForestTrustInformation(domain->conn.netlogon_creds,
1588                                                               b, p->mem_ctx,
1589                                                               &new_fti);
1590         if (!NT_STATUS_IS_OK(status)) {
1591                 if (!retry && dcerpc_binding_handle_is_connected(b)) {
1592                         invalidate_cm_connection(domain);
1593                         retry = true;
1594                         goto reconnect;
1595                 }
1596                 DEBUG(2, ("netlogon_creds_cli_GetForestTrustInformation(%s) failed: %s\n",
1597                           domain->name, nt_errstr(status)));
1598                 TALLOC_FREE(frame);
1599                 return ntstatus_to_werror(status);
1600         }
1601
1602         *r->out.forest_trust_info = new_fti;
1603
1604         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
1605                 update_fti = true;
1606         }
1607
1608         status = dcerpc_lsa_lsaRQueryForestTrustInformation(local_lsa, frame,
1609                                                 &local_lsa_policy,
1610                                                 &trusted_domain_name,
1611                                                 LSA_FOREST_TRUST_DOMAIN_INFO,
1612                                                 &old_fti, &result);
1613         if (!NT_STATUS_IS_OK(status)) {
1614                 DEBUG(0,("%s:%s: local_lsa.lsaRQueryForestTrustInformation(%s) failed %s\n",
1615                          __location__, __func__, domain->name, nt_errstr(status)));
1616                 TALLOC_FREE(frame);
1617                 return WERR_INTERNAL_ERROR;
1618         }
1619         if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_FOUND)) {
1620                 DEBUG(2,("%s: no forest trust information available for domain[%s] yet.\n",
1621                           __func__, domain->name));
1622                 update_fti = true;
1623                 old_fti = &_old_fti;
1624                 result = NT_STATUS_OK;
1625         }
1626         if (!NT_STATUS_IS_OK(result)) {
1627                 DEBUG(0,("%s:%s: local_lsa.lsaRQueryForestTrustInformation(%s) returned %s\n",
1628                          __location__, __func__, domain->name, nt_errstr(result)));
1629                 TALLOC_FREE(frame);
1630                 return WERR_INTERNAL_ERROR;
1631         }
1632
1633         if (old_fti == NULL) {
1634                 DEBUG(0,("%s:%s: local_lsa.lsaRQueryForestTrustInformation() "
1635                          "returned success without returning forest trust information\n",
1636                          __location__, __func__));
1637                 TALLOC_FREE(frame);
1638                 return WERR_INTERNAL_ERROR;
1639         }
1640
1641         if (!update_fti) {
1642                 goto done;
1643         }
1644
1645         status = dsdb_trust_merge_forest_info(frame, tdo, old_fti, new_fti,
1646                                               &merged_fti);
1647         if (!NT_STATUS_IS_OK(status)) {
1648                 DEBUG(0,("%s:%s: dsdb_trust_merge_forest_info(%s) failed %s\n",
1649                          __location__, __func__, domain->name, nt_errstr(status)));
1650                 TALLOC_FREE(frame);
1651                 return ntstatus_to_werror(status);
1652         }
1653
1654         status = dcerpc_lsa_lsaRSetForestTrustInformation(local_lsa, frame,
1655                                                 &local_lsa_policy,
1656                                                 &trusted_domain_name_l,
1657                                                 LSA_FOREST_TRUST_DOMAIN_INFO,
1658                                                 merged_fti,
1659                                                 0, /* check_only=0 => store it! */
1660                                                 &collision_info,
1661                                                 &result);
1662         if (!NT_STATUS_IS_OK(status)) {
1663                 DEBUG(0,("%s:%s: local_lsa.lsaRSetForestTrustInformation(%s) failed %s\n",
1664                          __location__, __func__, domain->name, nt_errstr(status)));
1665                 TALLOC_FREE(frame);
1666                 return WERR_INTERNAL_ERROR;
1667         }
1668         if (!NT_STATUS_IS_OK(result)) {
1669                 DEBUG(0,("%s:%s: local_lsa.lsaRSetForestTrustInformation(%s) returned %s\n",
1670                          __location__, __func__, domain->name, nt_errstr(result)));
1671                 TALLOC_FREE(frame);
1672                 return ntstatus_to_werror(result);
1673         }
1674
1675 done:
1676         DEBUG(5, ("_winbind_GetForestTrustInformation succeeded\n"));
1677         TALLOC_FREE(frame);
1678         return WERR_OK;
1679 }