443f7c1a108b99767b71e062f15e5ec1543ab102
[metze/samba-autobuild/.git] / source3 / winbindd / winbindd_util.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Winbind daemon for ntdom nss module
5
6    Copyright (C) Tim Potter 2000-2001
7    Copyright (C) 2001 by Martin Pool <mbp@samba.org>
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "winbindd.h"
25 #include "lib/util_unixsids.h"
26 #include "secrets.h"
27 #include "../libcli/security/security.h"
28 #include "../libcli/auth/pam_errors.h"
29 #include "passdb/machine_sid.h"
30 #include "passdb.h"
31 #include "source4/lib/messaging/messaging.h"
32 #include "librpc/gen_ndr/ndr_lsa.h"
33 #include "librpc/gen_ndr/ndr_drsblobs.h"
34 #include "auth/credentials/credentials.h"
35 #include "libsmb/samlogon_cache.h"
36 #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
1690         ok = parse_domain_user(mem_ctx,
1691                         *pusername_inout,
1692                         &namespace, &domain, &user);
1693
1694         if (!ok) {
1695                 return False;
1696         }
1697
1698         username_inout = talloc_asprintf(mem_ctx, "%s%c%s",
1699                  domain, *lp_winbind_separator(),
1700                  user);
1701
1702         if (username_inout == NULL) {
1703                 goto fail;
1704         }
1705
1706         *pnamespace = namespace;
1707         *puser = user;
1708         *pdomain = domain;
1709         *pusername_inout = username_inout;
1710         return True;
1711 fail:
1712         TALLOC_FREE(username_inout);
1713         TALLOC_FREE(namespace);
1714         TALLOC_FREE(domain);
1715         TALLOC_FREE(user);
1716         return false;
1717 }
1718
1719 /*
1720     Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
1721     'winbind separator' options.
1722     This means:
1723         - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
1724         lp_workgroup()
1725
1726     If we are a PDC or BDC, and this is for our domain, do likewise.
1727
1728     On an AD DC we always fill DOMAIN\\USERNAME.
1729
1730     We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1731 */
1732 /**
1733  * talloc version of fill_domain_username()
1734  * return NULL on talloc failure.
1735  */
1736 char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
1737                                   const char *domain,
1738                                   const char *user,
1739                                   bool can_assume)
1740 {
1741         char *tmp_user, *name;
1742
1743         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1744                 can_assume = false;
1745         }
1746
1747         if (user == NULL) {
1748                 return NULL;
1749         }
1750
1751         tmp_user = talloc_strdup(mem_ctx, user);
1752         if (tmp_user == NULL) {
1753                 return NULL;
1754         }
1755         if (!strlower_m(tmp_user)) {
1756                 TALLOC_FREE(tmp_user);
1757                 return NULL;
1758         }
1759
1760         if (can_assume && assume_domain(domain)) {
1761                 name = tmp_user;
1762         } else {
1763                 name = talloc_asprintf(mem_ctx, "%s%c%s",
1764                                        domain,
1765                                        *lp_winbind_separator(),
1766                                        tmp_user);
1767                 TALLOC_FREE(tmp_user);
1768         }
1769
1770         return name;
1771 }
1772
1773 /*
1774  * Client list accessor functions
1775  */
1776
1777 static struct winbindd_cli_state *_client_list;
1778 static int _num_clients;
1779
1780 /* Return list of all connected clients */
1781
1782 struct winbindd_cli_state *winbindd_client_list(void)
1783 {
1784         return _client_list;
1785 }
1786
1787 /* Return list-tail of all connected clients */
1788
1789 struct winbindd_cli_state *winbindd_client_list_tail(void)
1790 {
1791         return DLIST_TAIL(_client_list);
1792 }
1793
1794 /* Return previous (read:newer) client in list */
1795
1796 struct winbindd_cli_state *
1797 winbindd_client_list_prev(struct winbindd_cli_state *cli)
1798 {
1799         return DLIST_PREV(cli);
1800 }
1801
1802 /* Add a connection to the list */
1803
1804 void winbindd_add_client(struct winbindd_cli_state *cli)
1805 {
1806         cli->last_access = time(NULL);
1807         DLIST_ADD(_client_list, cli);
1808         _num_clients++;
1809 }
1810
1811 /* Remove a client from the list */
1812
1813 void winbindd_remove_client(struct winbindd_cli_state *cli)
1814 {
1815         DLIST_REMOVE(_client_list, cli);
1816         _num_clients--;
1817 }
1818
1819 /* Move a client to head or list */
1820
1821 void winbindd_promote_client(struct winbindd_cli_state *cli)
1822 {
1823         cli->last_access = time(NULL);
1824         DLIST_PROMOTE(_client_list, cli);
1825 }
1826
1827 /* Return number of open clients */
1828
1829 int winbindd_num_clients(void)
1830 {
1831         return _num_clients;
1832 }
1833
1834 NTSTATUS lookup_usergroups_cached(TALLOC_CTX *mem_ctx,
1835                                   const struct dom_sid *user_sid,
1836                                   uint32_t *p_num_groups, struct dom_sid **user_sids)
1837 {
1838         struct netr_SamInfo3 *info3 = NULL;
1839         NTSTATUS status = NT_STATUS_NO_MEMORY;
1840         uint32_t num_groups = 0;
1841
1842         DEBUG(3,(": lookup_usergroups_cached\n"));
1843
1844         *user_sids = NULL;
1845         *p_num_groups = 0;
1846
1847         info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1848
1849         if (info3 == NULL) {
1850                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1851         }
1852
1853         /*
1854          * Before bug #7843 the "Domain Local" groups were added with a
1855          * lookupuseraliases call, but this isn't done anymore for our domain
1856          * so we need to resolve resource groups here.
1857          *
1858          * When to use Resource Groups:
1859          * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
1860          */
1861         status = sid_array_from_info3(mem_ctx, info3,
1862                                       user_sids,
1863                                       &num_groups,
1864                                       false);
1865
1866         if (!NT_STATUS_IS_OK(status)) {
1867                 TALLOC_FREE(info3);
1868                 return status;
1869         }
1870
1871         TALLOC_FREE(info3);
1872         *p_num_groups = num_groups;
1873         status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1874
1875         DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1876
1877         return status;
1878 }
1879
1880 /*********************************************************************
1881  We use this to remove spaces from user and group names
1882 ********************************************************************/
1883
1884 NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
1885                              const char *domain_name,
1886                              const char *name,
1887                              char **normalized)
1888 {
1889         struct winbindd_domain *domain = NULL;
1890         NTSTATUS nt_status;
1891
1892         if (!name || !normalized) {
1893                 return NT_STATUS_INVALID_PARAMETER;
1894         }
1895
1896         if (!lp_winbind_normalize_names()) {
1897                 return NT_STATUS_PROCEDURE_NOT_FOUND;
1898         }
1899
1900         domain = find_domain_from_name_noinit(domain_name);
1901         if (domain == NULL) {
1902                 DBG_ERR("Failed to find domain '%s'\n", domain_name);
1903                 return NT_STATUS_NO_SUCH_DOMAIN;
1904         }
1905
1906         /* Alias support and whitespace replacement are mutually
1907            exclusive */
1908
1909         nt_status = resolve_username_to_alias(mem_ctx, domain,
1910                                               name, normalized );
1911         if (NT_STATUS_IS_OK(nt_status)) {
1912                 /* special return code to let the caller know we
1913                    mapped to an alias */
1914                 return NT_STATUS_FILE_RENAMED;
1915         }
1916
1917         /* check for an unreachable domain */
1918
1919         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1920                 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1921                          domain->name));
1922                 set_domain_offline(domain);
1923                 return nt_status;
1924         }
1925
1926         /* deal with whitespace */
1927
1928         *normalized = talloc_strdup(mem_ctx, name);
1929         if (!(*normalized)) {
1930                 return NT_STATUS_NO_MEMORY;
1931         }
1932
1933         all_string_sub( *normalized, " ", "_", 0 );
1934
1935         return NT_STATUS_OK;
1936 }
1937
1938 /*********************************************************************
1939  We use this to do the inverse of normalize_name_map()
1940 ********************************************************************/
1941
1942 NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
1943                               const char *name,
1944                               char **normalized)
1945 {
1946         NTSTATUS nt_status;
1947         struct winbindd_domain *domain = find_our_domain();
1948
1949         if (!name || !normalized) {
1950                 return NT_STATUS_INVALID_PARAMETER;
1951         }
1952
1953         if (!lp_winbind_normalize_names()) {
1954                 return NT_STATUS_PROCEDURE_NOT_FOUND;
1955         }
1956
1957         /* Alias support and whitespace replacement are mutally
1958            exclusive */
1959
1960         /* When mapping from an alias to a username, we don't know the
1961            domain.  But we only need a domain structure to cache
1962            a successful lookup , so just our own domain structure for
1963            the seqnum. */
1964
1965         nt_status = resolve_alias_to_username(mem_ctx, domain,
1966                                               name, normalized);
1967         if (NT_STATUS_IS_OK(nt_status)) {
1968                 /* Special return code to let the caller know we mapped
1969                    from an alias */
1970                 return NT_STATUS_FILE_RENAMED;
1971         }
1972
1973         /* check for an unreachable domain */
1974
1975         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1976                 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1977                          domain->name));
1978                 set_domain_offline(domain);
1979                 return nt_status;
1980         }
1981
1982         /* deal with whitespace */
1983
1984         *normalized = talloc_strdup(mem_ctx, name);
1985         if (!(*normalized)) {
1986                 return NT_STATUS_NO_MEMORY;
1987         }
1988
1989         all_string_sub(*normalized, "_", " ", 0);
1990
1991         return NT_STATUS_OK;
1992 }
1993
1994 /*********************************************************************
1995  ********************************************************************/
1996
1997 bool winbindd_can_contact_domain(struct winbindd_domain *domain)
1998 {
1999         struct winbindd_tdc_domain *tdc = NULL;
2000         TALLOC_CTX *frame = talloc_stackframe();
2001         bool ret = false;
2002
2003         /* We can contact the domain if it is our primary domain */
2004
2005         if (domain->primary) {
2006                 ret = true;
2007                 goto done;
2008         }
2009
2010         /* Trust the TDC cache and not the winbindd_domain flags */
2011
2012         if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
2013                 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
2014                           domain->name));
2015                 ret = false;
2016                 goto done;
2017         }
2018
2019         /* Can always contact a domain that is in out forest */
2020
2021         if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2022                 ret = true;
2023                 goto done;
2024         }
2025
2026         /*
2027          * On a _member_ server, we cannot contact the domain if it
2028          * is running AD and we have no inbound trust.
2029          */
2030
2031         if (!IS_DC &&
2032              domain->active_directory &&
2033             ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
2034         {
2035                 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
2036                            "and we have no inbound trust.\n", domain->name));
2037                 goto done;
2038         }
2039
2040         /* Assume everything else is ok (probably not true but what
2041            can you do?) */
2042
2043         ret = true;
2044
2045 done:
2046         talloc_destroy(frame);
2047
2048         return ret;
2049 }
2050
2051 #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
2052
2053 /*********************************************************************
2054  ********************************************************************/
2055
2056 static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
2057 {
2058         char *var = NULL;
2059         char addr[INET6_ADDRSTRLEN];
2060         const char *kdc = NULL;
2061         int lvl = 11;
2062
2063         if (!domain || !domain->alt_name || !*domain->alt_name) {
2064                 return;
2065         }
2066
2067         if (domain->initialized && !domain->active_directory) {
2068                 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
2069                         domain->alt_name));
2070                 return;
2071         }
2072
2073         print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
2074         kdc = addr;
2075         if (!*kdc) {
2076                 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
2077                         domain->alt_name));
2078                 kdc = domain->dcname;
2079         }
2080
2081         if (!kdc || !*kdc) {
2082                 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
2083                         domain->alt_name));
2084                 return;
2085         }
2086
2087         var = talloc_asprintf_strupper_m(
2088                 talloc_tos(),
2089                 "%s_%s",
2090                 WINBINDD_LOCATOR_KDC_ADDRESS,
2091                 domain->alt_name);
2092         if (var == NULL) {
2093                 return;
2094         }
2095
2096         DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
2097                 var, kdc));
2098
2099         setenv(var, kdc, 1);
2100         TALLOC_FREE(var);
2101 }
2102
2103 /*********************************************************************
2104  ********************************************************************/
2105
2106 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2107 {
2108         struct winbindd_domain *our_dom = find_our_domain();
2109
2110         winbindd_set_locator_kdc_env(domain);
2111
2112         if (domain != our_dom) {
2113                 winbindd_set_locator_kdc_env(our_dom);
2114         }
2115 }
2116
2117 /*********************************************************************
2118  ********************************************************************/
2119
2120 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2121 {
2122         char *var = NULL;
2123
2124         if (!domain || !domain->alt_name || !*domain->alt_name) {
2125                 return;
2126         }
2127
2128         var = talloc_asprintf_strupper_m(
2129                 talloc_tos(),
2130                 "%s_%s",
2131                 WINBINDD_LOCATOR_KDC_ADDRESS,
2132                 domain->alt_name);
2133         if (var == NULL) {
2134                 return;
2135         }
2136
2137         unsetenv(var);
2138         TALLOC_FREE(var);
2139 }
2140 #else
2141
2142 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2143 {
2144         return;
2145 }
2146
2147 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2148 {
2149         return;
2150 }
2151
2152 #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
2153
2154 void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
2155 {
2156         /*
2157          * Make sure we start with authoritative=true,
2158          * it will only set to false if we don't know the
2159          * domain.
2160          */
2161         resp->data.auth.authoritative = true;
2162
2163         resp->data.auth.nt_status = NT_STATUS_V(result);
2164         fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
2165
2166         /* we might have given a more useful error above */
2167         if (*resp->data.auth.error_string == '\0')
2168                 fstrcpy(resp->data.auth.error_string,
2169                         get_friendly_nt_error_msg(result));
2170         resp->data.auth.pam_error = nt_status_to_pam(result);
2171 }
2172
2173 bool is_domain_offline(const struct winbindd_domain *domain)
2174 {
2175         if (get_global_winbindd_state_offline()) {
2176                 return true;
2177         }
2178         return !domain->online;
2179 }
2180
2181 bool is_domain_online(const struct winbindd_domain *domain)
2182 {
2183         return !is_domain_offline(domain);
2184 }
2185
2186 /**
2187  * Parse an char array into a list of sids.
2188  *
2189  * The input sidstr should consist of 0-terminated strings
2190  * representing sids, separated by newline characters '\n'.
2191  * The list is terminated by an empty string, i.e.
2192  * character '\0' directly following a character '\n'
2193  * (or '\0' right at the start of sidstr).
2194  */
2195 bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
2196                    struct dom_sid **sids, uint32_t *num_sids)
2197 {
2198         const char *p;
2199
2200         p = sidstr;
2201         if (p == NULL)
2202                 return False;
2203
2204         while (p[0] != '\0') {
2205                 struct dom_sid sid;
2206                 const char *q = NULL;
2207
2208                 if (!dom_sid_parse_endp(p, &sid, &q)) {
2209                         DEBUG(1, ("Could not parse sid %s\n", p));
2210                         return false;
2211                 }
2212                 if (q[0] != '\n') {
2213                         DEBUG(1, ("Got invalid sidstr: %s\n", p));
2214                         return false;
2215                 }
2216                 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
2217                                                       num_sids)))
2218                 {
2219                         return False;
2220                 }
2221                 p = q+1;
2222         }
2223         return True;
2224 }
2225
2226 bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
2227                    struct unixid **pxids, uint32_t *pnum_xids)
2228 {
2229         const char *p;
2230         struct unixid *xids = NULL;
2231         uint32_t num_xids = 0;
2232
2233         p = xidstr;
2234         if (p == NULL) {
2235                 return false;
2236         }
2237
2238         while (p[0] != '\0') {
2239                 struct unixid *tmp;
2240                 struct unixid xid;
2241                 unsigned long long id;
2242                 char *endp;
2243                 int error = 0;
2244
2245                 switch (p[0]) {
2246                 case 'U':
2247                         xid = (struct unixid) { .type = ID_TYPE_UID };
2248                         break;
2249                 case 'G':
2250                         xid = (struct unixid) { .type = ID_TYPE_GID };
2251                         break;
2252                 default:
2253                         return false;
2254                 }
2255
2256                 p += 1;
2257
2258                 id = smb_strtoull(p, &endp, 10, &error, SMB_STR_STANDARD);
2259                 if (error != 0) {
2260                         goto fail;
2261                 }
2262                 if (*endp != '\n') {
2263                         goto fail;
2264                 }
2265                 p = endp+1;
2266
2267                 xid.id = id;
2268                 if ((unsigned long long)xid.id != id) {
2269                         goto fail;
2270                 }
2271
2272                 tmp = talloc_realloc(mem_ctx, xids, struct unixid, num_xids+1);
2273                 if (tmp == NULL) {
2274                         return 0;
2275                 }
2276                 xids = tmp;
2277
2278                 xids[num_xids] = xid;
2279                 num_xids += 1;
2280         }
2281
2282         *pxids = xids;
2283         *pnum_xids = num_xids;
2284         return true;
2285
2286 fail:
2287         TALLOC_FREE(xids);
2288         return false;
2289 }