winbind: Use one queue for all domain children
[samba.git] / source3 / winbindd / winbindd_util.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Winbind daemon for ntdom nss module
5
6    Copyright (C) Tim Potter 2000-2001
7    Copyright (C) 2001 by Martin Pool <mbp@samba.org>
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.h"
25 #include "lib/util_unixsids.h"
26 #include "secrets.h"
27 #include "../libcli/security/security.h"
28 #include "../libcli/auth/pam_errors.h"
29 #include "passdb/machine_sid.h"
30 #include "passdb.h"
31 #include "source4/lib/messaging/messaging.h"
32 #include "librpc/gen_ndr/ndr_lsa.h"
33 #include "librpc/gen_ndr/ndr_drsblobs.h"
34 #include "auth/credentials/credentials.h"
35 #include "libsmb/samlogon_cache.h"
36
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_WINBIND
39
40 /**
41  * @file winbindd_util.c
42  *
43  * Winbind daemon for NT domain authentication nss module.
44  **/
45
46 static bool add_trusted_domains_dc(void);
47
48 /* The list of trusted domains.  Note that the list can be deleted and
49    recreated using the init_domain_list() function so pointers to
50    individual winbindd_domain structures cannot be made.  Keep a copy of
51    the domain name instead. */
52
53 static struct winbindd_domain *_domain_list = NULL;
54
55 struct winbindd_domain *domain_list(void)
56 {
57         /* Initialise list */
58
59         if ((!_domain_list) && (!init_domain_list())) {
60                 smb_panic("Init_domain_list failed");
61         }
62
63         return _domain_list;
64 }
65
66 /* Free all entries in the trusted domain list */
67
68 static void free_domain_list(void)
69 {
70         struct winbindd_domain *domain = _domain_list;
71
72         while(domain) {
73                 struct winbindd_domain *next = domain->next;
74
75                 DLIST_REMOVE(_domain_list, domain);
76                 TALLOC_FREE(domain);
77                 domain = next;
78         }
79 }
80
81 /**
82  * Iterator for winbindd's domain list.
83  * To be used (e.g.) in tevent based loops.
84  */
85 struct winbindd_domain *wb_next_domain(struct winbindd_domain *domain)
86 {
87         if (domain == NULL) {
88                 domain = domain_list();
89         } else {
90                 domain = domain->next;
91         }
92
93         if ((domain != NULL) &&
94             (lp_server_role() != ROLE_ACTIVE_DIRECTORY_DC) &&
95             sid_check_is_our_sam(&domain->sid))
96         {
97                 domain = domain->next;
98         }
99
100         return domain;
101 }
102
103 static bool is_internal_domain(const struct dom_sid *sid)
104 {
105         if (sid == NULL)
106                 return False;
107
108         return (sid_check_is_our_sam(sid) || sid_check_is_builtin(sid));
109 }
110
111 static bool is_in_internal_domain(const struct dom_sid *sid)
112 {
113         if (sid == NULL)
114                 return False;
115
116         return (sid_check_is_in_our_sam(sid) || sid_check_is_in_builtin(sid));
117 }
118
119
120 /* Add a trusted domain to our list of domains.
121    If the domain already exists in the list,
122    return it and don't re-initialize.  */
123
124 static NTSTATUS add_trusted_domain(const char *domain_name,
125                                    const char *dns_name,
126                                    const struct dom_sid *sid,
127                                    uint32_t trust_type,
128                                    uint32_t trust_flags,
129                                    uint32_t trust_attribs,
130                                    enum netr_SchannelType secure_channel_type,
131                                    struct winbindd_domain *routing_domain,
132                                    struct winbindd_domain **_d)
133 {
134         struct winbindd_domain *domain = NULL;
135         const char **ignored_domains = NULL;
136         const char **dom = NULL;
137         int role = lp_server_role();
138
139         if (is_null_sid(sid)) {
140                 DBG_ERR("Got null SID for domain [%s]\n", domain_name);
141                 return NT_STATUS_INVALID_PARAMETER;
142         }
143
144         ignored_domains = lp_parm_string_list(-1, "winbind", "ignore domains", NULL);
145         for (dom=ignored_domains; dom && *dom; dom++) {
146                 if (gen_fnmatch(*dom, domain_name) == 0) {
147                         DEBUG(2,("Ignoring domain '%s'\n", domain_name));
148                         return NT_STATUS_NO_SUCH_DOMAIN;
149                 }
150         }
151
152         /*
153          * We can't call domain_list() as this function is called from
154          * init_domain_list() and we'll get stuck in a loop.
155          */
156         for (domain = _domain_list; domain; domain = domain->next) {
157                 if (strequal(domain_name, domain->name)) {
158                         break;
159                 }
160         }
161
162         if (domain != NULL) {
163                 struct winbindd_domain *check_domain = NULL;
164
165                 for (check_domain = _domain_list;
166                      check_domain != NULL;
167                      check_domain = check_domain->next)
168                 {
169                         if (check_domain == domain) {
170                                 continue;
171                         }
172
173                         if (dom_sid_equal(&check_domain->sid, sid)) {
174                                 break;
175                         }
176                 }
177
178                 if (check_domain != NULL) {
179                         DBG_ERR("SID [%s] already used by domain [%s], "
180                                 "expected [%s]\n",
181                                 sid_string_dbg(sid), check_domain->name,
182                                 domain->name);
183                         return NT_STATUS_INVALID_PARAMETER;
184                 }
185         }
186
187         if ((domain != NULL) && (dns_name != NULL)) {
188                 struct winbindd_domain *check_domain = NULL;
189
190                 for (check_domain = _domain_list;
191                      check_domain != NULL;
192                      check_domain = check_domain->next)
193                 {
194                         if (check_domain == domain) {
195                                 continue;
196                         }
197
198                         if (strequal(check_domain->alt_name, dns_name)) {
199                                 break;
200                         }
201                 }
202
203                 if (check_domain != NULL) {
204                         DBG_ERR("DNS name [%s] used by domain [%s], "
205                                 "expected [%s]\n",
206                                 dns_name, check_domain->name,
207                                 domain->name);
208                         return NT_STATUS_INVALID_PARAMETER;
209                 }
210         }
211
212         if (domain != NULL) {
213                 *_d = domain;
214                 return NT_STATUS_OK;
215         }
216
217         /* Create new domain entry */
218         domain = talloc_zero(NULL, struct winbindd_domain);
219         if (domain == NULL) {
220                 return NT_STATUS_NO_MEMORY;
221         }
222
223         domain->children = talloc_zero_array(domain,
224                                              struct winbindd_child,
225                                              lp_winbind_max_domain_connections());
226         if (domain->children == NULL) {
227                 TALLOC_FREE(domain);
228                 return NT_STATUS_NO_MEMORY;
229         }
230
231         domain->queue = tevent_queue_create(domain, "winbind_domain");
232         if (domain->queue == NULL) {
233                 TALLOC_FREE(domain);
234                 return NT_STATUS_NO_MEMORY;
235         }
236
237         domain->binding_handle = wbint_binding_handle(domain, domain, NULL);
238         if (domain->binding_handle == NULL) {
239                 TALLOC_FREE(domain);
240                 return NT_STATUS_NO_MEMORY;
241         }
242
243         domain->name = talloc_strdup(domain, domain_name);
244         if (domain->name == NULL) {
245                 TALLOC_FREE(domain);
246                 return NT_STATUS_NO_MEMORY;
247         }
248
249         if (dns_name != NULL) {
250                 domain->alt_name = talloc_strdup(domain, dns_name);
251                 if (domain->alt_name == NULL) {
252                         TALLOC_FREE(domain);
253                         return NT_STATUS_NO_MEMORY;
254                 }
255         }
256
257         domain->backend = NULL;
258         domain->internal = is_internal_domain(sid);
259         domain->secure_channel_type = secure_channel_type;
260         domain->sequence_number = DOM_SEQUENCE_NONE;
261         domain->last_seq_check = 0;
262         domain->initialized = false;
263         domain->online = is_internal_domain(sid);
264         domain->check_online_timeout = 0;
265         domain->dc_probe_pid = (pid_t)-1;
266         domain->domain_flags = trust_flags;
267         domain->domain_type = trust_type;
268         domain->domain_trust_attribs = trust_attribs;
269         domain->secure_channel_type = secure_channel_type;
270         domain->routing_domain = routing_domain;
271         sid_copy(&domain->sid, sid);
272
273         /* Is this our primary domain ? */
274         if (role == ROLE_DOMAIN_MEMBER) {
275                 domain->primary = strequal(domain_name, lp_workgroup());
276         } else {
277                 domain->primary = strequal(domain_name, get_global_sam_name());
278         }
279
280         if (domain->primary) {
281                 if (role == ROLE_ACTIVE_DIRECTORY_DC) {
282                         domain->active_directory = true;
283                 }
284                 if (lp_security() == SEC_ADS) {
285                         domain->active_directory = true;
286                 }
287         } else if (!domain->internal) {
288                 if (domain->domain_type == LSA_TRUST_TYPE_UPLEVEL) {
289                         domain->active_directory = true;
290                 }
291         }
292
293         domain->can_do_ncacn_ip_tcp = domain->active_directory;
294
295         /* Link to domain list */
296         DLIST_ADD_END(_domain_list, domain);
297
298         wcache_tdc_add_domain( domain );
299
300         setup_domain_child(domain);
301
302         DBG_NOTICE("Added domain [%s] [%s] [%s]\n",
303                    domain->name, domain->alt_name,
304                    sid_string_dbg(&domain->sid));
305
306         *_d = domain;
307         return NT_STATUS_OK;
308 }
309
310 bool set_routing_domain(struct winbindd_domain *domain,
311                         struct winbindd_domain *routing_domain)
312 {
313         if (domain->routing_domain == NULL) {
314                 domain->routing_domain = routing_domain;
315                 return true;
316         }
317         if (domain->routing_domain != routing_domain) {
318                 return false;
319         }
320         return true;
321 }
322
323 bool add_trusted_domain_from_auth(uint16_t validation_level,
324                                   struct info3_text *info3,
325                                   struct info6_text *info6)
326 {
327         struct winbindd_domain *domain = NULL;
328         struct dom_sid domain_sid;
329         const char *dns_domainname = NULL;
330         NTSTATUS status;
331         bool ok;
332
333         /*
334          * We got a successfull auth from a domain that might not yet be in our
335          * domain list. If we're a member we trust our DC who authenticated the
336          * user from that domain and add the domain to our list on-the-fly. If
337          * we're a DC we rely on configured trusts and don't add on-the-fly.
338          */
339
340         if (IS_DC) {
341                 return true;
342         }
343
344         ok = dom_sid_parse(info3->dom_sid, &domain_sid);
345         if (!ok) {
346                 DBG_NOTICE("dom_sid_parse [%s] failed\n", info3->dom_sid);
347                 return false;
348         }
349
350         if (validation_level == 6) {
351                 if (!strequal(info6->dns_domainname, "")) {
352                         dns_domainname = info6->dns_domainname;
353                 }
354         }
355
356         status = add_trusted_domain(info3->logon_dom,
357                                     dns_domainname,
358                                     &domain_sid,
359                                     0,
360                                     NETR_TRUST_FLAG_OUTBOUND,
361                                     0,
362                                     SEC_CHAN_NULL,
363                                     find_default_route_domain(),
364                                     &domain);
365         if (!NT_STATUS_IS_OK(status) &&
366             !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
367         {
368                 DBG_DEBUG("Adding domain [%s] with sid [%s] failed\n",
369                           info3->logon_dom, info3->dom_sid);
370                 return false;
371         }
372
373         return true;
374 }
375
376 bool domain_is_forest_root(const struct winbindd_domain *domain)
377 {
378         const uint32_t fr_flags =
379                 (NETR_TRUST_FLAG_TREEROOT|NETR_TRUST_FLAG_IN_FOREST);
380
381         return ((domain->domain_flags & fr_flags) == fr_flags);
382 }
383
384 /********************************************************************
385   rescan our domains looking for new trusted domains
386 ********************************************************************/
387
388 struct trustdom_state {
389         struct winbindd_domain *domain;
390         struct winbindd_request request;
391 };
392
393 static void trustdom_list_done(struct tevent_req *req);
394 static void rescan_forest_root_trusts( void );
395 static void rescan_forest_trusts( void );
396
397 static void add_trusted_domains( struct winbindd_domain *domain )
398 {
399         struct trustdom_state *state;
400         struct tevent_req *req;
401
402         state = talloc_zero(NULL, struct trustdom_state);
403         if (state == NULL) {
404                 DEBUG(0, ("talloc failed\n"));
405                 return;
406         }
407         state->domain = domain;
408
409         state->request.length = sizeof(state->request);
410         state->request.cmd = WINBINDD_LIST_TRUSTDOM;
411
412         req = wb_domain_request_send(state, server_event_context(),
413                                      domain, &state->request);
414         if (req == NULL) {
415                 DEBUG(1, ("wb_domain_request_send failed\n"));
416                 TALLOC_FREE(state);
417                 return;
418         }
419         tevent_req_set_callback(req, trustdom_list_done, state);
420 }
421
422 static void trustdom_list_done(struct tevent_req *req)
423 {
424         struct trustdom_state *state = tevent_req_callback_data(
425                 req, struct trustdom_state);
426         struct winbindd_response *response;
427         int res, err;
428         char *p;
429         ptrdiff_t extra_len;
430         bool within_forest = false;
431         NTSTATUS status;
432
433         /*
434          * Only when we enumerate our primary domain
435          * or our forest root domain, we should keep
436          * the NETR_TRUST_FLAG_IN_FOREST flag, in
437          * all other cases we need to clear it as the domain
438          * is not part of our forest.
439          */
440         if (state->domain->primary) {
441                 within_forest = true;
442         } else if (domain_is_forest_root(state->domain)) {
443                 within_forest = true;
444         }
445
446         res = wb_domain_request_recv(req, state, &response, &err);
447         if ((res == -1) || (response->result != WINBINDD_OK)) {
448                 DBG_WARNING("Could not receive trusts for domain %s\n",
449                             state->domain->name);
450                 TALLOC_FREE(state);
451                 return;
452         }
453
454         if (response->length < sizeof(struct winbindd_response)) {
455                 DBG_ERR("ill-formed trustdom response - short length\n");
456                 TALLOC_FREE(state);
457                 return;
458         }
459
460         extra_len = response->length - sizeof(struct winbindd_response);
461
462         p = (char *)response->extra_data.data;
463
464         while ((p - (char *)response->extra_data.data) < extra_len) {
465                 struct winbindd_domain *domain = NULL;
466                 char *name, *q, *sidstr, *alt_name;
467                 struct dom_sid sid;
468                 uint32_t trust_type;
469                 uint32_t trust_attribs;
470                 uint32_t trust_flags;
471
472                 DBG_DEBUG("parsing response line '%s'\n", p);
473
474                 name = p;
475
476                 alt_name = strchr(p, '\\');
477                 if (alt_name == NULL) {
478                         DBG_ERR("Got invalid trustdom response\n");
479                         break;
480                 }
481
482                 *alt_name = '\0';
483                 alt_name += 1;
484
485                 sidstr = strchr(alt_name, '\\');
486                 if (sidstr == NULL) {
487                         DBG_ERR("Got invalid trustdom response\n");
488                         break;
489                 }
490
491                 *sidstr = '\0';
492                 sidstr += 1;
493
494                 /* use the real alt_name if we have one, else pass in NULL */
495                 if (strequal(alt_name, "(null)")) {
496                         alt_name = NULL;
497                 }
498
499                 q = strtok(sidstr, "\\");
500                 if (q == NULL) {
501                         DBG_ERR("Got invalid trustdom response\n");
502                         break;
503                 }
504
505                 if (!string_to_sid(&sid, sidstr)) {
506                         DEBUG(0, ("Got invalid trustdom response\n"));
507                         break;
508                 }
509
510                 q = strtok(NULL, "\\");
511                 if (q == NULL) {
512                         DBG_ERR("Got invalid trustdom response\n");
513                         break;
514                 }
515
516                 trust_flags = (uint32_t)strtoul(q, NULL, 10);
517
518                 q = strtok(NULL, "\\");
519                 if (q == NULL) {
520                         DBG_ERR("Got invalid trustdom response\n");
521                         break;
522                 }
523
524                 trust_type = (uint32_t)strtoul(q, NULL, 10);
525
526                 q = strtok(NULL, "\n");
527                 if (q == NULL) {
528                         DBG_ERR("Got invalid trustdom response\n");
529                         break;
530                 }
531
532                 trust_attribs = (uint32_t)strtoul(q, NULL, 10);
533
534                 if (!within_forest) {
535                         trust_flags &= ~NETR_TRUST_FLAG_IN_FOREST;
536                 }
537
538                 if (!state->domain->primary) {
539                         trust_flags &= ~NETR_TRUST_FLAG_PRIMARY;
540                 }
541
542                 /*
543                  * We always call add_trusted_domain() cause on an existing
544                  * domain structure, it will update the SID if necessary.
545                  * This is important because we need the SID for sibling
546                  * domains.
547                  */
548                 status = add_trusted_domain(name,
549                                             alt_name,
550                                             &sid,
551                                             trust_type,
552                                             trust_flags,
553                                             trust_attribs,
554                                             SEC_CHAN_NULL,
555                                             find_default_route_domain(),
556                                             &domain);
557                 if (!NT_STATUS_IS_OK(status) &&
558                     !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
559                 {
560                         DBG_NOTICE("add_trusted_domain returned %s\n",
561                                    nt_errstr(status));
562                         return;
563                 }
564
565                 p = q + strlen(q) + 1;
566         }
567
568         /*
569            Cases to consider when scanning trusts:
570            (a) we are calling from a child domain (primary && !forest_root)
571            (b) we are calling from the root of the forest (primary && forest_root)
572            (c) we are calling from a trusted forest domain (!primary
573                && !forest_root)
574         */
575
576         if (state->domain->primary) {
577                 /* If this is our primary domain and we are not in the
578                    forest root, we have to scan the root trusts first */
579
580                 if (!domain_is_forest_root(state->domain))
581                         rescan_forest_root_trusts();
582                 else
583                         rescan_forest_trusts();
584
585         } else if (domain_is_forest_root(state->domain)) {
586                 /* Once we have done root forest trust search, we can
587                    go on to search the trusted forests */
588
589                 rescan_forest_trusts();
590         }
591
592         TALLOC_FREE(state);
593
594         return;
595 }
596
597 /********************************************************************
598  Scan the trusts of our forest root
599 ********************************************************************/
600
601 static void rescan_forest_root_trusts( void )
602 {
603         struct winbindd_tdc_domain *dom_list = NULL;
604         size_t num_trusts = 0;
605         int i;
606         NTSTATUS status;
607
608         /* The only transitive trusts supported by Windows 2003 AD are
609            (a) Parent-Child, (b) Tree-Root, and (c) Forest.   The
610            first two are handled in forest and listed by
611            DsEnumerateDomainTrusts().  Forest trusts are not so we
612            have to do that ourselves. */
613
614         if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
615                 return;
616
617         for ( i=0; i<num_trusts; i++ ) {
618                 struct winbindd_domain *d = NULL;
619
620                 /* Find the forest root.  Don't necessarily trust
621                    the domain_list() as our primary domain may not
622                    have been initialized. */
623
624                 if ( !(dom_list[i].trust_flags & NETR_TRUST_FLAG_TREEROOT) ) {
625                         continue;
626                 }
627
628                 /* Here's the forest root */
629
630                 d = find_domain_from_name_noinit( dom_list[i].domain_name );
631                 if (d == NULL) {
632                         status = add_trusted_domain(dom_list[i].domain_name,
633                                                     dom_list[i].dns_name,
634                                                     &dom_list[i].sid,
635                                                     dom_list[i].trust_type,
636                                                     dom_list[i].trust_flags,
637                                                     dom_list[i].trust_attribs,
638                                                     SEC_CHAN_NULL,
639                                                     find_default_route_domain(),
640                                                     &d);
641
642                         if (!NT_STATUS_IS_OK(status) &&
643                             NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
644                         {
645                                 DBG_ERR("add_trusted_domain returned %s\n",
646                                         nt_errstr(status));
647                                 return;
648                         }
649                 }
650                 if (d == NULL) {
651                         continue;
652                 }
653
654                 DEBUG(10,("rescan_forest_root_trusts: Following trust path "
655                           "for domain tree root %s (%s)\n",
656                           d->name, d->alt_name ));
657
658                 d->domain_flags = dom_list[i].trust_flags;
659                 d->domain_type  = dom_list[i].trust_type;
660                 d->domain_trust_attribs = dom_list[i].trust_attribs;
661
662                 add_trusted_domains( d );
663
664                 break;
665         }
666
667         TALLOC_FREE( dom_list );
668
669         return;
670 }
671
672 /********************************************************************
673  scan the transitive forest trusts (not our own)
674 ********************************************************************/
675
676
677 static void rescan_forest_trusts( void )
678 {
679         struct winbindd_domain *d = NULL;
680         struct winbindd_tdc_domain *dom_list = NULL;
681         size_t num_trusts = 0;
682         int i;
683         NTSTATUS status;
684
685         /* The only transitive trusts supported by Windows 2003 AD are
686            (a) Parent-Child, (b) Tree-Root, and (c) Forest.   The
687            first two are handled in forest and listed by
688            DsEnumerateDomainTrusts().  Forest trusts are not so we
689            have to do that ourselves. */
690
691         if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
692                 return;
693
694         for ( i=0; i<num_trusts; i++ ) {
695                 uint32_t flags   = dom_list[i].trust_flags;
696                 uint32_t type    = dom_list[i].trust_type;
697                 uint32_t attribs = dom_list[i].trust_attribs;
698
699                 d = find_domain_from_name_noinit( dom_list[i].domain_name );
700
701                 /* ignore our primary and internal domains */
702
703                 if ( d && (d->internal || d->primary ) )
704                         continue;
705
706                 if ( (flags & NETR_TRUST_FLAG_INBOUND) &&
707                      (type == LSA_TRUST_TYPE_UPLEVEL) &&
708                      (attribs == LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) )
709                 {
710                         /* add the trusted domain if we don't know
711                            about it */
712
713                         if (d == NULL) {
714                                 status = add_trusted_domain(
715                                         dom_list[i].domain_name,
716                                         dom_list[i].dns_name,
717                                         &dom_list[i].sid,
718                                         type,
719                                         flags,
720                                         attribs,
721                                         SEC_CHAN_NULL,
722                                         find_default_route_domain(),
723                                         &d);
724                                 if (!NT_STATUS_IS_OK(status) &&
725                                     NT_STATUS_EQUAL(status,
726                                                     NT_STATUS_NO_SUCH_DOMAIN))
727                                 {
728                                         DBG_ERR("add_trusted_domain: %s\n",
729                                                 nt_errstr(status));
730                                         return;
731                                 }
732                         }
733
734                         if (d == NULL) {
735                                 continue;
736                         }
737
738                         DEBUG(10,("Following trust path for domain %s (%s)\n",
739                                   d->name, d->alt_name ));
740                         add_trusted_domains( d );
741                 }
742         }
743
744         TALLOC_FREE( dom_list );
745
746         return;
747 }
748
749 /*********************************************************************
750  The process of updating the trusted domain list is a three step
751  async process:
752  (a) ask our domain
753  (b) ask the root domain in our forest
754  (c) ask the a DC in any Win2003 trusted forests
755 *********************************************************************/
756
757 void rescan_trusted_domains(struct tevent_context *ev, struct tevent_timer *te,
758                             struct timeval now, void *private_data)
759 {
760         TALLOC_FREE(te);
761
762         /* I use to clear the cache here and start over but that
763            caused problems in child processes that needed the
764            trust dom list early on.  Removing it means we
765            could have some trusted domains listed that have been
766            removed from our primary domain's DC until a full
767            restart.  This should be ok since I think this is what
768            Windows does as well. */
769
770         /* this will only add new domains we didn't already know about
771            in the domain_list()*/
772
773         add_trusted_domains( find_our_domain() );
774
775         te = tevent_add_timer(
776                 ev, NULL, timeval_current_ofs(WINBINDD_RESCAN_FREQ, 0),
777                 rescan_trusted_domains, NULL);
778         /*
779          * If te == NULL, there's not much we can do here. Don't fail, the
780          * only thing we miss is new trusted domains.
781          */
782
783         return;
784 }
785
786 enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domain,
787                                                    struct winbindd_cli_state *state)
788 {
789         /* Ensure null termination */
790         state->request->domain_name
791                 [sizeof(state->request->domain_name)-1]='\0';
792         state->request->data.init_conn.dcname
793                 [sizeof(state->request->data.init_conn.dcname)-1]='\0';
794
795         if (strlen(state->request->data.init_conn.dcname) > 0) {
796                 TALLOC_FREE(domain->dcname);
797                 domain->dcname = talloc_strdup(domain,
798                                 state->request->data.init_conn.dcname);
799                 if (domain->dcname == NULL) {
800                         return WINBINDD_ERROR;
801                 }
802         }
803
804         init_dc_connection(domain, false);
805
806         if (!domain->initialized) {
807                 /* If we return error here we can't do any cached authentication,
808                    but we may be in disconnected mode and can't initialize correctly.
809                    Do what the previous code did and just return without initialization,
810                    once we go online we'll re-initialize.
811                 */
812                 DEBUG(5, ("winbindd_dual_init_connection: %s returning without initialization "
813                         "online = %d\n", domain->name, (int)domain->online ));
814         }
815
816         fstrcpy(state->response->data.domain_info.name, domain->name);
817         fstrcpy(state->response->data.domain_info.alt_name, domain->alt_name);
818         sid_to_fstring(state->response->data.domain_info.sid, &domain->sid);
819
820         state->response->data.domain_info.native_mode
821                 = domain->native_mode;
822         state->response->data.domain_info.active_directory
823                 = domain->active_directory;
824         state->response->data.domain_info.primary
825                 = domain->primary;
826
827         return WINBINDD_OK;
828 }
829
830 static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
831                                        void *private_data,
832                                        uint32_t msg_type,
833                                        struct server_id server_id,
834                                        DATA_BLOB *data)
835 {
836         bool ok;
837
838         DBG_NOTICE("Rescanning trusted domains\n");
839
840         ok = add_trusted_domains_dc();
841         if (!ok) {
842                 DBG_ERR("Failed to reload trusted domains\n");
843         }
844 }
845
846 /*
847  * We did not get the secret when we queried secrets.tdb, so read it
848  * from secrets.tdb and re-sync the databases
849  */
850 static bool migrate_secrets_tdb_to_ldb(struct winbindd_domain *domain)
851 {
852         bool ok;
853         struct cli_credentials *creds;
854         NTSTATUS can_migrate = pdb_get_trust_credentials(domain->name,
855                                                          NULL, domain, &creds);
856         if (!NT_STATUS_IS_OK(can_migrate)) {
857                 DEBUG(0, ("Failed to fetch our own, local AD domain join "
858                         "password for winbindd's internal use, both from "
859                         "secrets.tdb and secrets.ldb: %s\n",
860                         nt_errstr(can_migrate)));
861                 return false;
862         }
863
864         /*
865          * NOTE: It is very unlikely we end up here if there is an
866          * oldpass, because a new password is created at
867          * classicupgrade, so this is not a concern.
868          */
869         ok = secrets_store_machine_pw_sync(cli_credentials_get_password(creds),
870                    NULL /* oldpass */,
871                    cli_credentials_get_domain(creds),
872                    cli_credentials_get_realm(creds),
873                    cli_credentials_get_salt_principal(creds),
874                    0, /* Supported enc types, unused */
875                    &domain->sid,
876                    cli_credentials_get_password_last_changed_time(creds),
877                    cli_credentials_get_secure_channel_type(creds),
878                    false /* do_delete: Do not delete */);
879         TALLOC_FREE(creds);
880         if (ok == false) {
881                 DEBUG(0, ("Failed to write our our own, "
882                           "local AD domain join password for "
883                           "winbindd's internal use into secrets.tdb\n"));
884                 return false;
885         }
886         return true;
887 }
888
889 static bool add_trusted_domains_dc(void)
890 {
891         struct winbindd_domain *domain =  NULL;
892         struct pdb_trusted_domain **domains = NULL;
893         uint32_t num_domains = 0;
894         uint32_t i;
895         NTSTATUS status;
896
897         if (!(pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX)) {
898                 struct trustdom_info **ti = NULL;
899
900                 status = pdb_enum_trusteddoms(talloc_tos(), &num_domains, &ti);
901                 if (!NT_STATUS_IS_OK(status)) {
902                         DBG_ERR("pdb_enum_trusteddoms() failed - %s\n",
903                                 nt_errstr(status));
904                         return false;
905                 }
906
907                 for (i = 0; i < num_domains; i++) {
908                         status = add_trusted_domain(ti[i]->name,
909                                                     NULL,
910                                                     &ti[i]->sid,
911                                                     LSA_TRUST_TYPE_DOWNLEVEL,
912                                                     NETR_TRUST_FLAG_OUTBOUND,
913                                                     0,
914                                                     SEC_CHAN_DOMAIN,
915                                                     NULL,
916                                                     &domain);
917                         if (!NT_STATUS_IS_OK(status)) {
918                                 DBG_NOTICE("add_trusted_domain returned %s\n",
919                                            nt_errstr(status));
920                                 return false;
921                         }
922
923                         /* Even in the parent winbindd we'll need to
924                            talk to the DC, so try and see if we can
925                            contact it. Theoretically this isn't neccessary
926                            as the init_dc_connection() in init_child_recv()
927                            will do this, but we can start detecting the DC
928                            early here. */
929                         set_domain_online_request(domain);
930                 }
931
932                 return true;
933         }
934
935         status = pdb_enum_trusted_domains(talloc_tos(), &num_domains, &domains);
936         if (!NT_STATUS_IS_OK(status)) {
937                 DBG_ERR("pdb_enum_trusted_domains() failed - %s\n",
938                         nt_errstr(status));
939                 return false;
940         }
941
942         for (i = 0; i < num_domains; i++) {
943                 enum netr_SchannelType sec_chan_type = SEC_CHAN_DOMAIN;
944                 uint32_t trust_flags = 0;
945
946                 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
947                         sec_chan_type = SEC_CHAN_DNS_DOMAIN;
948                 }
949
950                 if (!(domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
951                         sec_chan_type = SEC_CHAN_NULL;
952                 }
953
954                 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
955                         trust_flags |= NETR_TRUST_FLAG_INBOUND;
956                 }
957                 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
958                         trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
959                 }
960                 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
961                         trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
962                 }
963
964                 status = add_trusted_domain(domains[i]->netbios_name,
965                                             domains[i]->domain_name,
966                                             &domains[i]->security_identifier,
967                                             domains[i]->trust_type,
968                                             trust_flags,
969                                             domains[i]->trust_attributes,
970                                             sec_chan_type,
971                                             NULL,
972                                             &domain);
973                 if (!NT_STATUS_IS_OK(status)) {
974                         DBG_NOTICE("add_trusted_domain returned %s\n",
975                                    nt_errstr(status));
976                         return false;
977                 }
978
979                 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
980                         domain->active_directory = true;
981                 }
982                 domain->domain_type = domains[i]->trust_type;
983                 domain->domain_trust_attribs = domains[i]->trust_attributes;
984
985                 if (sec_chan_type != SEC_CHAN_NULL) {
986                         /* Even in the parent winbindd we'll need to
987                            talk to the DC, so try and see if we can
988                            contact it. Theoretically this isn't neccessary
989                            as the init_dc_connection() in init_child_recv()
990                            will do this, but we can start detecting the DC
991                            early here. */
992                         set_domain_online_request(domain);
993                 }
994         }
995
996         for (i = 0; i < num_domains; i++) {
997                 struct ForestTrustInfo fti;
998                 uint32_t fi;
999                 enum ndr_err_code ndr_err;
1000                 struct winbindd_domain *routing_domain = NULL;
1001
1002                 if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
1003                         continue;
1004                 }
1005
1006                 if (!(domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
1007                         continue;
1008                 }
1009
1010                 if (domains[i]->trust_forest_trust_info.length == 0) {
1011                         continue;
1012                 }
1013
1014                 routing_domain = find_domain_from_name_noinit(
1015                         domains[i]->netbios_name);
1016                 if (routing_domain == NULL) {
1017                         DBG_ERR("Can't find winbindd domain [%s]\n",
1018                                 domains[i]->netbios_name);
1019                         return false;
1020                 }
1021
1022                 ndr_err = ndr_pull_struct_blob_all(
1023                         &domains[i]->trust_forest_trust_info,
1024                         talloc_tos(), &fti,
1025                         (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
1026                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1027                         DBG_ERR("ndr_pull_ForestTrustInfo(%s) - %s\n",
1028                                 domains[i]->netbios_name,
1029                                 ndr_map_error2string(ndr_err));
1030                         return false;
1031                 }
1032
1033                 for (fi = 0; fi < fti.count; fi++) {
1034                         struct ForestTrustInfoRecord *rec =
1035                                 &fti.records[fi].record;
1036                         struct ForestTrustDataDomainInfo *drec = NULL;
1037
1038                         if (rec->type != FOREST_TRUST_DOMAIN_INFO) {
1039                                 continue;
1040                         }
1041                         drec = &rec->data.info;
1042
1043                         if (rec->flags & LSA_NB_DISABLED_MASK) {
1044                                 continue;
1045                         }
1046
1047                         if (rec->flags & LSA_SID_DISABLED_MASK) {
1048                                 continue;
1049                         }
1050
1051                         /*
1052                          * TODO:
1053                          * also try to find a matching
1054                          * LSA_TLN_DISABLED_MASK ???
1055                          */
1056
1057                         domain = find_domain_from_name_noinit(drec->netbios_name.string);
1058                         if (domain != NULL) {
1059                                 continue;
1060                         }
1061
1062                         status = add_trusted_domain(drec->netbios_name.string,
1063                                                     drec->dns_name.string,
1064                                                     &drec->sid,
1065                                                     LSA_TRUST_TYPE_UPLEVEL,
1066                                                     NETR_TRUST_FLAG_OUTBOUND,
1067                                                     0,
1068                                                     SEC_CHAN_NULL,
1069                                                     routing_domain,
1070                                                     &domain);
1071                         if (!NT_STATUS_IS_OK(status)) {
1072                                 DBG_NOTICE("add_trusted_domain returned %s\n",
1073                                            nt_errstr(status));
1074                                 return false;
1075                         }
1076                         if (domain == NULL) {
1077                                 continue;
1078                         }
1079                 }
1080         }
1081
1082         return true;
1083 }
1084
1085
1086 /* Look up global info for the winbind daemon */
1087 bool init_domain_list(void)
1088 {
1089         int role = lp_server_role();
1090         struct pdb_domain_info *pdb_domain_info = NULL;
1091         struct winbindd_domain *domain =  NULL;
1092         NTSTATUS status;
1093         bool ok;
1094
1095         /* Free existing list */
1096         free_domain_list();
1097
1098         /* BUILTIN domain */
1099
1100         status = add_trusted_domain("BUILTIN",
1101                                     NULL,
1102                                     &global_sid_Builtin,
1103                                     LSA_TRUST_TYPE_DOWNLEVEL,
1104                                     0, /* trust_flags */
1105                                     0, /* trust_attribs */
1106                                     SEC_CHAN_LOCAL,
1107                                     NULL,
1108                                     &domain);
1109         if (!NT_STATUS_IS_OK(status)) {
1110                 DBG_ERR("add_trusted_domain BUILTIN returned %s\n",
1111                         nt_errstr(status));
1112                 return false;
1113         }
1114
1115         /* Local SAM */
1116
1117         /*
1118          * In case the passdb backend is passdb_dsdb the domain SID comes from
1119          * dsdb, not from secrets.tdb. As we use the domain SID in various
1120          * places, we must ensure the domain SID is migrated from dsdb to
1121          * secrets.tdb before get_global_sam_sid() is called the first time.
1122          *
1123          * The migration is done as part of the passdb_dsdb initialisation,
1124          * calling pdb_get_domain_info() triggers it.
1125          */
1126         pdb_domain_info = pdb_get_domain_info(talloc_tos());
1127
1128         if ( role == ROLE_ACTIVE_DIRECTORY_DC ) {
1129                 uint32_t trust_flags;
1130                 bool is_root;
1131                 enum netr_SchannelType sec_chan_type;
1132                 const char *account_name;
1133                 struct samr_Password current_nt_hash;
1134
1135                 if (pdb_domain_info == NULL) {
1136                         DEBUG(0, ("Failed to fetch our own, local AD "
1137                                 "domain info from sam.ldb\n"));
1138                         return false;
1139                 }
1140
1141                 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1142                 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1143                 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1144                 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1145
1146                 is_root = strequal(pdb_domain_info->dns_domain,
1147                                    pdb_domain_info->dns_forest);
1148                 if (is_root) {
1149                         trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1150                 }
1151
1152                 status = add_trusted_domain(pdb_domain_info->name,
1153                                             pdb_domain_info->dns_domain,
1154                                             &pdb_domain_info->sid,
1155                                             LSA_TRUST_TYPE_UPLEVEL,
1156                                             trust_flags,
1157                                             LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1158                                             SEC_CHAN_BDC,
1159                                             NULL,
1160                                             &domain);
1161                 TALLOC_FREE(pdb_domain_info);
1162                 if (!NT_STATUS_IS_OK(status)) {
1163                         DBG_ERR("Failed to add our own, local AD "
1164                                 "domain to winbindd's internal list\n");
1165                         return false;
1166                 }
1167
1168                 /*
1169                  * We need to call this to find out if we are an RODC
1170                  */
1171                 ok = get_trust_pw_hash(domain->name,
1172                                        current_nt_hash.hash,
1173                                        &account_name,
1174                                        &sec_chan_type);
1175                 if (!ok) {
1176                         /*
1177                          * If get_trust_pw_hash() fails, then try and
1178                          * fetch the password from the more recent of
1179                          * secrets.{ldb,tdb} using the
1180                          * pdb_get_trust_credentials()
1181                          */
1182                         ok = migrate_secrets_tdb_to_ldb(domain);
1183
1184                         if (!ok) {
1185                                 DEBUG(0, ("Failed to migrate our own, "
1186                                           "local AD domain join password for "
1187                                           "winbindd's internal use into "
1188                                           "secrets.tdb\n"));
1189                                 return false;
1190                         }
1191                         ok = get_trust_pw_hash(domain->name,
1192                                                current_nt_hash.hash,
1193                                                &account_name,
1194                                                &sec_chan_type);
1195                         if (!ok) {
1196                                 DEBUG(0, ("Failed to find our our own, just "
1197                                           "written local AD domain join "
1198                                           "password for winbindd's internal "
1199                                           "use in secrets.tdb\n"));
1200                                 return false;
1201                         }
1202                 }
1203
1204                 domain->secure_channel_type = sec_chan_type;
1205                 if (sec_chan_type == SEC_CHAN_RODC) {
1206                         domain->rodc = true;
1207                 }
1208
1209         } else {
1210                 uint32_t trust_flags;
1211                 enum netr_SchannelType secure_channel_type;
1212
1213                 trust_flags = NETR_TRUST_FLAG_OUTBOUND;
1214                 if (role != ROLE_DOMAIN_MEMBER) {
1215                         trust_flags |= NETR_TRUST_FLAG_PRIMARY;
1216                 }
1217
1218                 if (role > ROLE_DOMAIN_MEMBER) {
1219                         secure_channel_type = SEC_CHAN_BDC;
1220                 } else {
1221                         secure_channel_type = SEC_CHAN_LOCAL;
1222                 }
1223
1224                 status = add_trusted_domain(get_global_sam_name(),
1225                                             NULL,
1226                                             get_global_sam_sid(),
1227                                             LSA_TRUST_TYPE_DOWNLEVEL,
1228                                             trust_flags,
1229                                             0, /* trust_attribs */
1230                                             secure_channel_type,
1231                                             NULL,
1232                                             &domain);
1233                 if (!NT_STATUS_IS_OK(status)) {
1234                         DBG_ERR("Failed to add local SAM to "
1235                                 "domain to winbindd's internal list\n");
1236                         return false;
1237                 }
1238         }
1239
1240         if (IS_DC) {
1241                 ok = add_trusted_domains_dc();
1242                 if (!ok) {
1243                         DBG_ERR("init_domain_list_dc failed\n");
1244                         return false;
1245                 }
1246         }
1247
1248         if ( role == ROLE_DOMAIN_MEMBER ) {
1249                 struct dom_sid our_sid;
1250                 uint32_t trust_type;
1251
1252                 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
1253                         DEBUG(0, ("Could not fetch our SID - did we join?\n"));
1254                         return False;
1255                 }
1256
1257                 if (lp_realm() != NULL) {
1258                         trust_type = LSA_TRUST_TYPE_UPLEVEL;
1259                 } else {
1260                         trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1261                 }
1262
1263                 status = add_trusted_domain(lp_workgroup(),
1264                                             lp_realm(),
1265                                             &our_sid,
1266                                             trust_type,
1267                                             NETR_TRUST_FLAG_PRIMARY|
1268                                             NETR_TRUST_FLAG_OUTBOUND,
1269                                             0, /* trust_attribs */
1270                                             SEC_CHAN_WKSTA,
1271                                             NULL,
1272                                             &domain);
1273                 if (!NT_STATUS_IS_OK(status)) {
1274                         DBG_ERR("Failed to add local SAM to "
1275                                 "domain to winbindd's internal list\n");
1276                         return false;
1277                 }
1278                 /* Even in the parent winbindd we'll need to
1279                    talk to the DC, so try and see if we can
1280                    contact it. Theoretically this isn't neccessary
1281                    as the init_dc_connection() in init_child_recv()
1282                    will do this, but we can start detecting the DC
1283                    early here. */
1284                 set_domain_online_request(domain);
1285
1286         }
1287
1288         status = imessaging_register(winbind_imessaging_context(), NULL,
1289                                      MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1290                                      wb_imsg_new_trusted_domain);
1291         if (!NT_STATUS_IS_OK(status)) {
1292                 DBG_ERR("imessaging_register failed %s\n", nt_errstr(status));
1293                 return false;
1294         }
1295
1296         return True;
1297 }
1298
1299 /**
1300  * Given a domain name, return the struct winbindd domain info for it
1301  *
1302  * @note Do *not* pass lp_workgroup() to this function.  domain_list
1303  *       may modify it's value, and free that pointer.  Instead, our local
1304  *       domain may be found by calling find_our_domain().
1305  *       directly.
1306  *
1307  *
1308  * @return The domain structure for the named domain, if it is working.
1309  */
1310
1311 struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
1312 {
1313         struct winbindd_domain *domain;
1314
1315         /* Search through list */
1316
1317         for (domain = domain_list(); domain != NULL; domain = domain->next) {
1318                 if (strequal(domain_name, domain->name)) {
1319                         return domain;
1320                 }
1321                 if (domain->alt_name == NULL) {
1322                         continue;
1323                 }
1324                 if (strequal(domain_name, domain->alt_name)) {
1325                         return domain;
1326                 }
1327         }
1328
1329         /* Not found */
1330
1331         return NULL;
1332 }
1333
1334 /**
1335  * Given a domain name, return the struct winbindd domain if it's a direct
1336  * outgoing trust
1337  *
1338  * @return The domain structure for the named domain, if it is a direct outgoing trust
1339  */
1340 struct winbindd_domain *find_trust_from_name_noinit(const char *domain_name)
1341 {
1342         struct winbindd_domain *domain = NULL;
1343
1344         domain = find_domain_from_name_noinit(domain_name);
1345         if (domain == NULL) {
1346                 return NULL;
1347         }
1348
1349         if (domain->secure_channel_type != SEC_CHAN_NULL) {
1350                 return domain;
1351         }
1352
1353         return NULL;
1354 }
1355
1356 struct winbindd_domain *find_domain_from_name(const char *domain_name)
1357 {
1358         struct winbindd_domain *domain;
1359
1360         domain = find_domain_from_name_noinit(domain_name);
1361
1362         if (domain == NULL)
1363                 return NULL;
1364
1365         if (!domain->initialized)
1366                 init_dc_connection(domain, false);
1367
1368         return domain;
1369 }
1370
1371 /* Given a domain sid, return the struct winbindd domain info for it */
1372
1373 struct winbindd_domain *find_domain_from_sid_noinit(const struct dom_sid *sid)
1374 {
1375         struct winbindd_domain *domain;
1376
1377         /* Search through list */
1378
1379         for (domain = domain_list(); domain != NULL; domain = domain->next) {
1380                 if (dom_sid_compare_domain(sid, &domain->sid) == 0)
1381                         return domain;
1382         }
1383
1384         /* Not found */
1385
1386         return NULL;
1387 }
1388
1389 /**
1390  * Given a domain sid, return the struct winbindd domain if it's a direct
1391  * outgoing trust
1392  *
1393  * @return The domain structure for the specified domain, if it is a direct outgoing trust
1394  */
1395 struct winbindd_domain *find_trust_from_sid_noinit(const struct dom_sid *sid)
1396 {
1397         struct winbindd_domain *domain = NULL;
1398
1399         domain = find_domain_from_sid_noinit(sid);
1400         if (domain == NULL) {
1401                 return NULL;
1402         }
1403
1404         if (domain->secure_channel_type != SEC_CHAN_NULL) {
1405                 return domain;
1406         }
1407
1408         return NULL;
1409 }
1410
1411 /* Given a domain sid, return the struct winbindd domain info for it */
1412
1413 struct winbindd_domain *find_domain_from_sid(const struct dom_sid *sid)
1414 {
1415         struct winbindd_domain *domain;
1416
1417         domain = find_domain_from_sid_noinit(sid);
1418
1419         if (domain == NULL)
1420                 return NULL;
1421
1422         if (!domain->initialized)
1423                 init_dc_connection(domain, false);
1424
1425         return domain;
1426 }
1427
1428 struct winbindd_domain *find_our_domain(void)
1429 {
1430         struct winbindd_domain *domain;
1431
1432         /* Search through list */
1433
1434         for (domain = domain_list(); domain != NULL; domain = domain->next) {
1435                 if (domain->primary)
1436                         return domain;
1437         }
1438
1439         smb_panic("Could not find our domain");
1440         return NULL;
1441 }
1442
1443 struct winbindd_domain *find_default_route_domain(void)
1444 {
1445         if (!IS_DC) {
1446                 return find_our_domain();
1447         }
1448         DBG_DEBUG("Routing logic not yet implemented on a DC\n");
1449         return NULL;
1450 }
1451
1452 /* Find the appropriate domain to lookup a name or SID */
1453
1454 struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)
1455 {
1456         DBG_DEBUG("SID [%s]\n", sid_string_dbg(sid));
1457
1458         /*
1459          * SIDs in the S-1-22-{1,2} domain and well-known SIDs should be handled
1460          * by our passdb.
1461          */
1462
1463         if ( sid_check_is_in_unix_groups(sid) ||
1464              sid_check_is_unix_groups(sid) ||
1465              sid_check_is_in_unix_users(sid) ||
1466              sid_check_is_unix_users(sid) ||
1467              sid_check_is_wellknown_domain(sid, NULL) ||
1468              sid_check_is_in_wellknown_domain(sid) )
1469         {
1470                 return find_domain_from_sid(get_global_sam_sid());
1471         }
1472
1473         /*
1474          * On member servers the internal domains are different: These are part
1475          * of the local SAM.
1476          */
1477
1478         if (is_internal_domain(sid) || is_in_internal_domain(sid)) {
1479                 DEBUG(10, ("calling find_domain_from_sid\n"));
1480                 return find_domain_from_sid(sid);
1481         }
1482
1483         if (IS_DC) {
1484                 struct winbindd_domain *domain = NULL;
1485
1486                 domain = find_domain_from_sid_noinit(sid);
1487                 if (domain == NULL) {
1488                         return NULL;
1489                 }
1490
1491                 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1492                         return domain;
1493                 }
1494
1495                 return domain->routing_domain;
1496         }
1497
1498         /* On a member server a query for SID or name can always go to our
1499          * primary DC. */
1500
1501         DEBUG(10, ("calling find_our_domain\n"));
1502         return find_our_domain();
1503 }
1504
1505 struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
1506 {
1507         if ( strequal(domain_name, unix_users_domain_name() ) ||
1508              strequal(domain_name, unix_groups_domain_name() ) )
1509         {
1510                 /*
1511                  * The "Unix User" and "Unix Group" domain our handled by
1512                  * passdb
1513                  */
1514                 return find_domain_from_name_noinit( get_global_sam_name() );
1515         }
1516
1517         if (strequal(domain_name, "BUILTIN") ||
1518             strequal(domain_name, get_global_sam_name()))
1519                 return find_domain_from_name_noinit(domain_name);
1520
1521         if (IS_DC) {
1522                 struct winbindd_domain *domain = NULL;
1523
1524                 domain = find_domain_from_name_noinit(domain_name);
1525                 if (domain == NULL) {
1526                         return NULL;
1527                 }
1528
1529                 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1530                         return domain;
1531                 }
1532
1533                 return domain->routing_domain;
1534         }
1535
1536         return find_our_domain();
1537 }
1538
1539 /* Is this a domain which we may assume no DOMAIN\ prefix? */
1540
1541 static bool assume_domain(const char *domain)
1542 {
1543         /* never assume the domain on a standalone server */
1544
1545         if ( lp_server_role() == ROLE_STANDALONE )
1546                 return False;
1547
1548         /* domain member servers may possibly assume for the domain name */
1549
1550         if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
1551                 if ( !strequal(lp_workgroup(), domain) )
1552                         return False;
1553
1554                 if ( lp_winbind_use_default_domain() )
1555                         return True;
1556         }
1557
1558         /* only left with a domain controller */
1559
1560         if ( strequal(get_global_sam_name(), domain) )  {
1561                 return True;
1562         }
1563
1564         return False;
1565 }
1566
1567 /* Parse a string of the form DOMAIN\user into a domain and a user */
1568
1569 bool parse_domain_user(const char *domuser, fstring domain, fstring user)
1570 {
1571         char *p = strchr(domuser,*lp_winbind_separator());
1572
1573         if ( !p ) {
1574                 fstrcpy(user, domuser);
1575                 p = strchr(domuser, '@');
1576
1577                 if ( assume_domain(lp_workgroup()) && p == NULL) {
1578                         fstrcpy(domain, lp_workgroup());
1579                 } else if (p != NULL) {
1580                         fstrcpy(domain, p + 1);
1581                         user[PTR_DIFF(p, domuser)] = 0;
1582                 } else {
1583                         return False;
1584                 }
1585         } else {
1586                 fstrcpy(user, p+1);
1587                 fstrcpy(domain, domuser);
1588                 domain[PTR_DIFF(p, domuser)] = 0;
1589         }
1590
1591         return strupper_m(domain);
1592 }
1593
1594 bool parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser,
1595                               char **domain, char **user)
1596 {
1597         fstring fstr_domain, fstr_user;
1598         if (!parse_domain_user(domuser, fstr_domain, fstr_user)) {
1599                 return False;
1600         }
1601         *domain = talloc_strdup(mem_ctx, fstr_domain);
1602         *user = talloc_strdup(mem_ctx, fstr_user);
1603         return ((*domain != NULL) && (*user != NULL));
1604 }
1605
1606 /* Ensure an incoming username from NSS is fully qualified. Replace the
1607    incoming fstring with DOMAIN <separator> user. Returns the same
1608    values as parse_domain_user() but also replaces the incoming username.
1609    Used to ensure all names are fully qualified within winbindd.
1610    Used by the NSS protocols of auth, chauthtok, logoff and ccache_ntlm_auth.
1611    The protocol definitions of auth_crap, chng_pswd_auth_crap
1612    really should be changed to use this instead of doing things
1613    by hand. JRA. */
1614
1615 bool canonicalize_username(fstring username_inout, fstring domain, fstring user)
1616 {
1617         if (!parse_domain_user(username_inout, domain, user)) {
1618                 return False;
1619         }
1620         slprintf(username_inout, sizeof(fstring) - 1, "%s%c%s",
1621                  domain, *lp_winbind_separator(),
1622                  user);
1623         return True;
1624 }
1625
1626 /*
1627     Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
1628     'winbind separator' options.
1629     This means:
1630         - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
1631         lp_workgroup()
1632
1633     If we are a PDC or BDC, and this is for our domain, do likewise.
1634
1635     On an AD DC we always fill DOMAIN\\USERNAME.
1636
1637     We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1638 */
1639 void fill_domain_username(fstring name, const char *domain, const char *user, bool can_assume)
1640 {
1641         fstring tmp_user;
1642
1643         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1644                 can_assume = false;
1645         }
1646
1647         fstrcpy(tmp_user, user);
1648         (void)strlower_m(tmp_user);
1649
1650         if (can_assume && assume_domain(domain)) {
1651                 strlcpy(name, tmp_user, sizeof(fstring));
1652         } else {
1653                 slprintf(name, sizeof(fstring) - 1, "%s%c%s",
1654                          domain, *lp_winbind_separator(),
1655                          tmp_user);
1656         }
1657 }
1658
1659 /**
1660  * talloc version of fill_domain_username()
1661  * return NULL on talloc failure.
1662  */
1663 char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
1664                                   const char *domain,
1665                                   const char *user,
1666                                   bool can_assume)
1667 {
1668         char *tmp_user, *name;
1669
1670         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1671                 can_assume = false;
1672         }
1673
1674         tmp_user = talloc_strdup(mem_ctx, user);
1675         if (!strlower_m(tmp_user)) {
1676                 TALLOC_FREE(tmp_user);
1677                 return NULL;
1678         }
1679
1680         if (can_assume && assume_domain(domain)) {
1681                 name = tmp_user;
1682         } else {
1683                 name = talloc_asprintf(mem_ctx, "%s%c%s",
1684                                        domain,
1685                                        *lp_winbind_separator(),
1686                                        tmp_user);
1687                 TALLOC_FREE(tmp_user);
1688         }
1689
1690         return name;
1691 }
1692
1693 /*
1694  * Client list accessor functions
1695  */
1696
1697 static struct winbindd_cli_state *_client_list;
1698 static int _num_clients;
1699
1700 /* Return list of all connected clients */
1701
1702 struct winbindd_cli_state *winbindd_client_list(void)
1703 {
1704         return _client_list;
1705 }
1706
1707 /* Return list-tail of all connected clients */
1708
1709 struct winbindd_cli_state *winbindd_client_list_tail(void)
1710 {
1711         return DLIST_TAIL(_client_list);
1712 }
1713
1714 /* Return previous (read:newer) client in list */
1715
1716 struct winbindd_cli_state *
1717 winbindd_client_list_prev(struct winbindd_cli_state *cli)
1718 {
1719         return DLIST_PREV(cli);
1720 }
1721
1722 /* Add a connection to the list */
1723
1724 void winbindd_add_client(struct winbindd_cli_state *cli)
1725 {
1726         cli->last_access = time(NULL);
1727         DLIST_ADD(_client_list, cli);
1728         _num_clients++;
1729 }
1730
1731 /* Remove a client from the list */
1732
1733 void winbindd_remove_client(struct winbindd_cli_state *cli)
1734 {
1735         DLIST_REMOVE(_client_list, cli);
1736         _num_clients--;
1737 }
1738
1739 /* Move a client to head or list */
1740
1741 void winbindd_promote_client(struct winbindd_cli_state *cli)
1742 {
1743         cli->last_access = time(NULL);
1744         DLIST_PROMOTE(_client_list, cli);
1745 }
1746
1747 /* Return number of open clients */
1748
1749 int winbindd_num_clients(void)
1750 {
1751         return _num_clients;
1752 }
1753
1754 NTSTATUS lookup_usergroups_cached(TALLOC_CTX *mem_ctx,
1755                                   const struct dom_sid *user_sid,
1756                                   uint32_t *p_num_groups, struct dom_sid **user_sids)
1757 {
1758         struct netr_SamInfo3 *info3 = NULL;
1759         NTSTATUS status = NT_STATUS_NO_MEMORY;
1760         uint32_t num_groups = 0;
1761
1762         DEBUG(3,(": lookup_usergroups_cached\n"));
1763
1764         *user_sids = NULL;
1765         *p_num_groups = 0;
1766
1767         info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1768
1769         if (info3 == NULL) {
1770                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1771         }
1772
1773         /*
1774          * Before bug #7843 the "Domain Local" groups were added with a
1775          * lookupuseraliases call, but this isn't done anymore for our domain
1776          * so we need to resolve resource groups here.
1777          *
1778          * When to use Resource Groups:
1779          * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
1780          */
1781         status = sid_array_from_info3(mem_ctx, info3,
1782                                       user_sids,
1783                                       &num_groups,
1784                                       false);
1785
1786         if (!NT_STATUS_IS_OK(status)) {
1787                 TALLOC_FREE(info3);
1788                 return status;
1789         }
1790
1791         TALLOC_FREE(info3);
1792         *p_num_groups = num_groups;
1793         status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1794
1795         DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1796
1797         return status;
1798 }
1799
1800 /*********************************************************************
1801  We use this to remove spaces from user and group names
1802 ********************************************************************/
1803
1804 NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
1805                              const char *domain_name,
1806                              const char *name,
1807                              char **normalized)
1808 {
1809         struct winbindd_domain *domain = NULL;
1810         NTSTATUS nt_status;
1811
1812         if (!name || !normalized) {
1813                 return NT_STATUS_INVALID_PARAMETER;
1814         }
1815
1816         if (!lp_winbind_normalize_names()) {
1817                 return NT_STATUS_PROCEDURE_NOT_FOUND;
1818         }
1819
1820         domain = find_domain_from_name_noinit(domain_name);
1821         if (domain == NULL) {
1822                 DBG_ERR("Failed to find domain '%s'\n", domain_name);
1823                 return NT_STATUS_NO_SUCH_DOMAIN;
1824         }
1825
1826         /* Alias support and whitespace replacement are mutually
1827            exclusive */
1828
1829         nt_status = resolve_username_to_alias(mem_ctx, domain,
1830                                               name, normalized );
1831         if (NT_STATUS_IS_OK(nt_status)) {
1832                 /* special return code to let the caller know we
1833                    mapped to an alias */
1834                 return NT_STATUS_FILE_RENAMED;
1835         }
1836
1837         /* check for an unreachable domain */
1838
1839         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1840                 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1841                          domain->name));
1842                 set_domain_offline(domain);
1843                 return nt_status;
1844         }
1845
1846         /* deal with whitespace */
1847
1848         *normalized = talloc_strdup(mem_ctx, name);
1849         if (!(*normalized)) {
1850                 return NT_STATUS_NO_MEMORY;
1851         }
1852
1853         all_string_sub( *normalized, " ", "_", 0 );
1854
1855         return NT_STATUS_OK;
1856 }
1857
1858 /*********************************************************************
1859  We use this to do the inverse of normalize_name_map()
1860 ********************************************************************/
1861
1862 NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
1863                               char *name,
1864                               char **normalized)
1865 {
1866         NTSTATUS nt_status;
1867         struct winbindd_domain *domain = find_our_domain();
1868
1869         if (!name || !normalized) {
1870                 return NT_STATUS_INVALID_PARAMETER;
1871         }
1872
1873         if (!lp_winbind_normalize_names()) {
1874                 return NT_STATUS_PROCEDURE_NOT_FOUND;
1875         }
1876
1877         /* Alias support and whitespace replacement are mutally
1878            exclusive */
1879
1880         /* When mapping from an alias to a username, we don't know the
1881            domain.  But we only need a domain structure to cache
1882            a successful lookup , so just our own domain structure for
1883            the seqnum. */
1884
1885         nt_status = resolve_alias_to_username(mem_ctx, domain,
1886                                               name, normalized);
1887         if (NT_STATUS_IS_OK(nt_status)) {
1888                 /* Special return code to let the caller know we mapped
1889                    from an alias */
1890                 return NT_STATUS_FILE_RENAMED;
1891         }
1892
1893         /* check for an unreachable domain */
1894
1895         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1896                 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1897                          domain->name));
1898                 set_domain_offline(domain);
1899                 return nt_status;
1900         }
1901
1902         /* deal with whitespace */
1903
1904         *normalized = talloc_strdup(mem_ctx, name);
1905         if (!(*normalized)) {
1906                 return NT_STATUS_NO_MEMORY;
1907         }
1908
1909         all_string_sub(*normalized, "_", " ", 0);
1910
1911         return NT_STATUS_OK;
1912 }
1913
1914 /*********************************************************************
1915  ********************************************************************/
1916
1917 bool winbindd_can_contact_domain(struct winbindd_domain *domain)
1918 {
1919         struct winbindd_tdc_domain *tdc = NULL;
1920         TALLOC_CTX *frame = talloc_stackframe();
1921         bool ret = false;
1922
1923         /* We can contact the domain if it is our primary domain */
1924
1925         if (domain->primary) {
1926                 ret = true;
1927                 goto done;
1928         }
1929
1930         /* Trust the TDC cache and not the winbindd_domain flags */
1931
1932         if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
1933                 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
1934                           domain->name));
1935                 ret = false;
1936                 goto done;
1937         }
1938
1939         /* Can always contact a domain that is in out forest */
1940
1941         if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1942                 ret = true;
1943                 goto done;
1944         }
1945
1946         /*
1947          * On a _member_ server, we cannot contact the domain if it
1948          * is running AD and we have no inbound trust.
1949          */
1950
1951         if (!IS_DC &&
1952              domain->active_directory &&
1953             ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
1954         {
1955                 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
1956                            "and we have no inbound trust.\n", domain->name));
1957                 goto done;
1958         }
1959
1960         /* Assume everything else is ok (probably not true but what
1961            can you do?) */
1962
1963         ret = true;
1964
1965 done:
1966         talloc_destroy(frame);
1967
1968         return ret;
1969 }
1970
1971 /*********************************************************************
1972  ********************************************************************/
1973
1974 bool winbindd_internal_child(struct winbindd_child *child)
1975 {
1976         if ((child == idmap_child()) || (child == locator_child())) {
1977                 return True;
1978         }
1979
1980         return False;
1981 }
1982
1983 #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
1984
1985 /*********************************************************************
1986  ********************************************************************/
1987
1988 static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
1989 {
1990         char *var = NULL;
1991         char addr[INET6_ADDRSTRLEN];
1992         const char *kdc = NULL;
1993         int lvl = 11;
1994
1995         if (!domain || !domain->alt_name || !*domain->alt_name) {
1996                 return;
1997         }
1998
1999         if (domain->initialized && !domain->active_directory) {
2000                 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
2001                         domain->alt_name));
2002                 return;
2003         }
2004
2005         print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
2006         kdc = addr;
2007         if (!*kdc) {
2008                 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
2009                         domain->alt_name));
2010                 kdc = domain->dcname;
2011         }
2012
2013         if (!kdc || !*kdc) {
2014                 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
2015                         domain->alt_name));
2016                 return;
2017         }
2018
2019         if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
2020                                 domain->alt_name) == -1) {
2021                 return;
2022         }
2023
2024         DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
2025                 var, kdc));
2026
2027         setenv(var, kdc, 1);
2028         free(var);
2029 }
2030
2031 /*********************************************************************
2032  ********************************************************************/
2033
2034 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2035 {
2036         struct winbindd_domain *our_dom = find_our_domain();
2037
2038         winbindd_set_locator_kdc_env(domain);
2039
2040         if (domain != our_dom) {
2041                 winbindd_set_locator_kdc_env(our_dom);
2042         }
2043 }
2044
2045 /*********************************************************************
2046  ********************************************************************/
2047
2048 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2049 {
2050         char *var = NULL;
2051
2052         if (!domain || !domain->alt_name || !*domain->alt_name) {
2053                 return;
2054         }
2055
2056         if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
2057                                 domain->alt_name) == -1) {
2058                 return;
2059         }
2060
2061         unsetenv(var);
2062         free(var);
2063 }
2064 #else
2065
2066 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2067 {
2068         return;
2069 }
2070
2071 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2072 {
2073         return;
2074 }
2075
2076 #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
2077
2078 void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
2079 {
2080         resp->data.auth.nt_status = NT_STATUS_V(result);
2081         fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
2082
2083         /* we might have given a more useful error above */
2084         if (*resp->data.auth.error_string == '\0')
2085                 fstrcpy(resp->data.auth.error_string,
2086                         get_friendly_nt_error_msg(result));
2087         resp->data.auth.pam_error = nt_status_to_pam(result);
2088 }
2089
2090 bool is_domain_offline(const struct winbindd_domain *domain)
2091 {
2092         if (get_global_winbindd_state_offline()) {
2093                 return true;
2094         }
2095         return !domain->online;
2096 }
2097
2098 bool is_domain_online(const struct winbindd_domain *domain)
2099 {
2100         return !is_domain_offline(domain);
2101 }
2102
2103 /**
2104  * Parse an char array into a list of sids.
2105  *
2106  * The input sidstr should consist of 0-terminated strings
2107  * representing sids, separated by newline characters '\n'.
2108  * The list is terminated by an empty string, i.e.
2109  * character '\0' directly following a character '\n'
2110  * (or '\0' right at the start of sidstr).
2111  */
2112 bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
2113                    struct dom_sid **sids, uint32_t *num_sids)
2114 {
2115         const char *p;
2116
2117         p = sidstr;
2118         if (p == NULL)
2119                 return False;
2120
2121         while (p[0] != '\0') {
2122                 struct dom_sid sid;
2123                 const char *q = NULL;
2124
2125                 if (!dom_sid_parse_endp(p, &sid, &q)) {
2126                         DEBUG(1, ("Could not parse sid %s\n", p));
2127                         return false;
2128                 }
2129                 if (q[0] != '\n') {
2130                         DEBUG(1, ("Got invalid sidstr: %s\n", p));
2131                         return false;
2132                 }
2133                 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
2134                                                       num_sids)))
2135                 {
2136                         return False;
2137                 }
2138                 p = q+1;
2139         }
2140         return True;
2141 }
2142
2143 bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
2144                    struct unixid **pxids, uint32_t *pnum_xids)
2145 {
2146         const char *p;
2147         struct unixid *xids = NULL;
2148         uint32_t num_xids = 0;
2149
2150         p = xidstr;
2151         if (p == NULL) {
2152                 return false;
2153         }
2154
2155         while (p[0] != '\0') {
2156                 struct unixid *tmp;
2157                 struct unixid xid;
2158                 unsigned long long id;
2159                 char *endp;
2160
2161                 switch (p[0]) {
2162                 case 'U':
2163                         xid = (struct unixid) { .type = ID_TYPE_UID };
2164                         break;
2165                 case 'G':
2166                         xid = (struct unixid) { .type = ID_TYPE_GID };
2167                         break;
2168                 default:
2169                         return false;
2170                 }
2171
2172                 p += 1;
2173
2174                 id = strtoull(p, &endp, 10);
2175                 if ((id == ULLONG_MAX) && (errno == ERANGE)) {
2176                         goto fail;
2177                 }
2178                 if (*endp != '\n') {
2179                         goto fail;
2180                 }
2181                 p = endp+1;
2182
2183                 xid.id = id;
2184                 if ((unsigned long long)xid.id != id) {
2185                         goto fail;
2186                 }
2187
2188                 tmp = talloc_realloc(mem_ctx, xids, struct unixid, num_xids+1);
2189                 if (tmp == NULL) {
2190                         return 0;
2191                 }
2192                 xids = tmp;
2193
2194                 xids[num_xids] = xid;
2195                 num_xids += 1;
2196         }
2197
2198         *pxids = xids;
2199         *pnum_xids = num_xids;
2200         return true;
2201
2202 fail:
2203         TALLOC_FREE(xids);
2204         return false;
2205 }