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