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