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