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