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