s3-winbind: fix setup_domain_child() callers.
[abartlet/samba.git/.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
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_WINBIND
28
29 extern struct winbindd_methods cache_methods;
30 extern struct winbindd_methods builtin_passdb_methods;
31 extern struct winbindd_methods sam_passdb_methods;
32
33
34 /**
35  * @file winbindd_util.c
36  *
37  * Winbind daemon for NT domain authentication nss module.
38  **/
39
40
41 /* The list of trusted domains.  Note that the list can be deleted and
42    recreated using the init_domain_list() function so pointers to
43    individual winbindd_domain structures cannot be made.  Keep a copy of
44    the domain name instead. */
45
46 static struct winbindd_domain *_domain_list = NULL;
47
48 struct winbindd_domain *domain_list(void)
49 {
50         /* Initialise list */
51
52         if ((!_domain_list) && (!init_domain_list())) {
53                 smb_panic("Init_domain_list failed");
54         }
55
56         return _domain_list;
57 }
58
59 /* Free all entries in the trusted domain list */
60
61 static void free_domain_list(void)
62 {
63         struct winbindd_domain *domain = _domain_list;
64
65         while(domain) {
66                 struct winbindd_domain *next = domain->next;
67
68                 DLIST_REMOVE(_domain_list, domain);
69                 SAFE_FREE(domain);
70                 domain = next;
71         }
72 }
73
74 static bool is_internal_domain(const DOM_SID *sid)
75 {
76         if (sid == NULL)
77                 return False;
78
79         return (sid_check_is_domain(sid) || sid_check_is_builtin(sid));
80 }
81
82 static bool is_in_internal_domain(const DOM_SID *sid)
83 {
84         if (sid == NULL)
85                 return False;
86
87         return (sid_check_is_in_our_domain(sid) || sid_check_is_in_builtin(sid));
88 }
89
90
91 /* Add a trusted domain to our list of domains */
92 static struct winbindd_domain *add_trusted_domain(const char *domain_name, const char *alt_name,
93                                                   struct winbindd_methods *methods,
94                                                   const DOM_SID *sid)
95 {
96         struct winbindd_domain *domain;
97         const char *alternative_name = NULL;
98         char *idmap_config_option;
99         const char *param;
100         const char **ignored_domains, **dom;
101
102         ignored_domains = lp_parm_string_list(-1, "winbind", "ignore domains", NULL);
103         for (dom=ignored_domains; dom && *dom; dom++) {
104                 if (gen_fnmatch(*dom, domain_name) == 0) {
105                         DEBUG(2,("Ignoring domain '%s'\n", domain_name));
106                         return NULL;
107                 }
108         }
109
110         /* ignore alt_name if we are not in an AD domain */
111
112         if ( (lp_security() == SEC_ADS) && alt_name && *alt_name) {
113                 alternative_name = alt_name;
114         }
115
116         /* We can't call domain_list() as this function is called from
117            init_domain_list() and we'll get stuck in a loop. */
118         for (domain = _domain_list; domain; domain = domain->next) {
119                 if (strequal(domain_name, domain->name) ||
120                     strequal(domain_name, domain->alt_name))
121                 {
122                         break;
123                 }
124
125                 if (alternative_name && *alternative_name)
126                 {
127                         if (strequal(alternative_name, domain->name) ||
128                             strequal(alternative_name, domain->alt_name))
129                         {
130                                 break;
131                         }
132                 }
133
134                 if (sid)
135                 {
136                         if (is_null_sid(sid)) {
137                                 continue;
138                         }
139
140                         if (sid_equal(sid, &domain->sid)) {
141                                 break;
142                         }
143                 }
144         }
145
146         if (domain != NULL) {
147                 /*
148                  * We found a match. Possibly update the SID
149                  */
150                 if ((sid != NULL)
151                     && sid_equal(&domain->sid, &global_sid_NULL)) {
152                         sid_copy( &domain->sid, sid );
153                 }
154                 return domain;
155         }
156
157         /* Create new domain entry */
158
159         if ((domain = SMB_MALLOC_P(struct winbindd_domain)) == NULL)
160                 return NULL;
161
162         /* Fill in fields */
163
164         ZERO_STRUCTP(domain);
165
166         fstrcpy(domain->name, domain_name);
167         if (alternative_name) {
168                 fstrcpy(domain->alt_name, alternative_name);
169         }
170
171         domain->methods = methods;
172         domain->backend = NULL;
173         domain->internal = is_internal_domain(sid);
174         domain->sequence_number = DOM_SEQUENCE_NONE;
175         domain->last_seq_check = 0;
176         domain->initialized = False;
177         domain->online = is_internal_domain(sid);
178         domain->check_online_timeout = 0;
179         domain->dc_probe_pid = (pid_t)-1;
180         if (sid) {
181                 sid_copy(&domain->sid, sid);
182         }
183
184         /* Link to domain list */
185         DLIST_ADD_END(_domain_list, domain, struct winbindd_domain *);
186
187         wcache_tdc_add_domain( domain );
188
189         idmap_config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
190                                               domain->name);
191         if (idmap_config_option == NULL) {
192                 DEBUG(0, ("talloc failed, not looking for idmap config\n"));
193                 goto done;
194         }
195
196         param = lp_parm_const_string(-1, idmap_config_option, "range", NULL);
197
198         DEBUG(10, ("%s : range = %s\n", idmap_config_option,
199                    param ? param : "not defined"));
200
201         if (param != NULL) {
202                 unsigned low_id, high_id;
203                 if (sscanf(param, "%u - %u", &low_id, &high_id) != 2) {
204                         DEBUG(1, ("invalid range syntax in %s: %s\n",
205                                   idmap_config_option, param));
206                         goto done;
207                 }
208                 if (low_id > high_id) {
209                         DEBUG(1, ("invalid range in %s: %s\n",
210                                   idmap_config_option, param));
211                         goto done;
212                 }
213                 domain->have_idmap_config = true;
214                 domain->id_range_low = low_id;
215                 domain->id_range_high = high_id;
216         }
217
218 done:
219
220         DEBUG(2,("Added domain %s %s %s\n",
221                  domain->name, domain->alt_name,
222                  &domain->sid?sid_string_dbg(&domain->sid):""));
223
224         return domain;
225 }
226
227 bool domain_is_forest_root(const struct winbindd_domain *domain)
228 {
229         const uint32_t fr_flags =
230                 (NETR_TRUST_FLAG_TREEROOT|NETR_TRUST_FLAG_IN_FOREST);
231
232         return ((domain->domain_flags & fr_flags) == fr_flags);
233 }
234
235 /********************************************************************
236   rescan our domains looking for new trusted domains
237 ********************************************************************/
238
239 struct trustdom_state {
240         TALLOC_CTX *mem_ctx;
241         bool primary;
242         bool forest_root;
243         struct winbindd_response *response;
244 };
245
246 static void trustdom_recv(void *private_data, bool success);
247 static void rescan_forest_root_trusts( void );
248 static void rescan_forest_trusts( void );
249
250 static void add_trusted_domains( struct winbindd_domain *domain )
251 {
252         TALLOC_CTX *mem_ctx;
253         struct winbindd_request *request;
254         struct winbindd_response *response;
255         struct trustdom_state *state;
256
257         mem_ctx = talloc_init("add_trusted_domains");
258         if (mem_ctx == NULL) {
259                 DEBUG(0, ("talloc_init failed\n"));
260                 return;
261         }
262
263         request = TALLOC_ZERO_P(mem_ctx, struct winbindd_request);
264         response = TALLOC_P(mem_ctx, struct winbindd_response);
265         state = TALLOC_P(mem_ctx, struct trustdom_state);
266
267         if ((request == NULL) || (response == NULL) || (state == NULL)) {
268                 DEBUG(0, ("talloc failed\n"));
269                 talloc_destroy(mem_ctx);
270                 return;
271         }
272
273         state->mem_ctx = mem_ctx;
274         state->response = response;
275
276         /* Flags used to know how to continue the forest trust search */
277
278         state->primary = domain->primary;
279         state->forest_root = domain_is_forest_root(domain);
280
281         request->length = sizeof(*request);
282         request->cmd = WINBINDD_LIST_TRUSTDOM;
283
284         async_domain_request(mem_ctx, domain, request, response,
285                              trustdom_recv, state);
286 }
287
288 static void trustdom_recv(void *private_data, bool success)
289 {
290         struct trustdom_state *state =
291                 talloc_get_type_abort(private_data, struct trustdom_state);
292         struct winbindd_response *response = state->response;
293         char *p;
294
295         if ((!success) || (response->result != WINBINDD_OK)) {
296                 DEBUG(1, ("Could not receive trustdoms\n"));
297                 talloc_destroy(state->mem_ctx);
298                 return;
299         }
300
301         p = (char *)response->extra_data.data;
302
303         while ((p != NULL) && (*p != '\0')) {
304                 char *q, *sidstr, *alt_name;
305                 DOM_SID sid;
306                 struct winbindd_domain *domain;
307                 char *alternate_name = NULL;
308
309                 alt_name = strchr(p, '\\');
310                 if (alt_name == NULL) {
311                         DEBUG(0, ("Got invalid trustdom response\n"));
312                         break;
313                 }
314
315                 *alt_name = '\0';
316                 alt_name += 1;
317
318                 sidstr = strchr(alt_name, '\\');
319                 if (sidstr == NULL) {
320                         DEBUG(0, ("Got invalid trustdom response\n"));
321                         break;
322                 }
323
324                 *sidstr = '\0';
325                 sidstr += 1;
326
327                 q = strchr(sidstr, '\n');
328                 if (q != NULL)
329                         *q = '\0';
330
331                 if (!string_to_sid(&sid, sidstr)) {
332                         DEBUG(0, ("Got invalid trustdom response\n"));
333                         break;
334                 }
335
336                 /* use the real alt_name if we have one, else pass in NULL */
337
338                 if ( !strequal( alt_name, "(null)" ) )
339                         alternate_name = alt_name;
340
341                 /* If we have an existing domain structure, calling
342                    add_trusted_domain() will update the SID if
343                    necessary.  This is important because we need the
344                    SID for sibling domains */
345
346                 if ( find_domain_from_name_noinit(p) != NULL ) {
347                         domain = add_trusted_domain(p, alternate_name,
348                                                     &cache_methods,
349                                                     &sid);
350                 } else {
351                         domain = add_trusted_domain(p, alternate_name,
352                                                     &cache_methods,
353                                                     &sid);
354                         if (domain) {
355                                 setup_domain_child(domain);
356                         }
357                 }
358                 p=q;
359                 if (p != NULL)
360                         p += 1;
361         }
362
363         /*
364            Cases to consider when scanning trusts:
365            (a) we are calling from a child domain (primary && !forest_root)
366            (b) we are calling from the root of the forest (primary && forest_root)
367            (c) we are calling from a trusted forest domain (!primary
368                && !forest_root)
369         */
370
371         if ( state->primary ) {
372                 /* If this is our primary domain and we are not in the
373                    forest root, we have to scan the root trusts first */
374
375                 if ( !state->forest_root )
376                         rescan_forest_root_trusts();
377                 else
378                         rescan_forest_trusts();
379
380         } else if ( state->forest_root ) {
381                 /* Once we have done root forest trust search, we can
382                    go on to search the trusted forests */
383
384                 rescan_forest_trusts();
385         }
386
387         talloc_destroy(state->mem_ctx);
388
389         return;
390 }
391
392 /********************************************************************
393  Scan the trusts of our forest root
394 ********************************************************************/
395
396 static void rescan_forest_root_trusts( void )
397 {
398         struct winbindd_tdc_domain *dom_list = NULL;
399         size_t num_trusts = 0;
400         int i;
401
402         /* The only transitive trusts supported by Windows 2003 AD are
403            (a) Parent-Child, (b) Tree-Root, and (c) Forest.   The
404            first two are handled in forest and listed by
405            DsEnumerateDomainTrusts().  Forest trusts are not so we
406            have to do that ourselves. */
407
408         if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
409                 return;
410
411         for ( i=0; i<num_trusts; i++ ) {
412                 struct winbindd_domain *d = NULL;
413
414                 /* Find the forest root.  Don't necessarily trust
415                    the domain_list() as our primary domain may not
416                    have been initialized. */
417
418                 if ( !(dom_list[i].trust_flags & NETR_TRUST_FLAG_TREEROOT) ) {
419                         continue;
420                 }
421
422                 /* Here's the forest root */
423
424                 d = find_domain_from_name_noinit( dom_list[i].domain_name );
425
426                 if ( !d ) {
427                         d = add_trusted_domain( dom_list[i].domain_name,
428                                                 dom_list[i].dns_name,
429                                                 &cache_methods,
430                                                 &dom_list[i].sid );
431                         if (d != NULL) {
432                                 setup_domain_child(d);
433                         }
434                 }
435
436                 if (d == NULL) {
437                         continue;
438                 }
439
440                 DEBUG(10,("rescan_forest_root_trusts: Following trust path "
441                           "for domain tree root %s (%s)\n",
442                           d->name, d->alt_name ));
443
444                 d->domain_flags = dom_list[i].trust_flags;
445                 d->domain_type  = dom_list[i].trust_type;
446                 d->domain_trust_attribs = dom_list[i].trust_attribs;
447
448                 add_trusted_domains( d );
449
450                 break;
451         }
452
453         TALLOC_FREE( dom_list );
454
455         return;
456 }
457
458 /********************************************************************
459  scan the transitive forest trusts (not our own)
460 ********************************************************************/
461
462
463 static void rescan_forest_trusts( void )
464 {
465         struct winbindd_domain *d = NULL;
466         struct winbindd_tdc_domain *dom_list = NULL;
467         size_t num_trusts = 0;
468         int i;
469
470         /* The only transitive trusts supported by Windows 2003 AD are
471            (a) Parent-Child, (b) Tree-Root, and (c) Forest.   The
472            first two are handled in forest and listed by
473            DsEnumerateDomainTrusts().  Forest trusts are not so we
474            have to do that ourselves. */
475
476         if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
477                 return;
478
479         for ( i=0; i<num_trusts; i++ ) {
480                 uint32 flags   = dom_list[i].trust_flags;
481                 uint32 type    = dom_list[i].trust_type;
482                 uint32 attribs = dom_list[i].trust_attribs;
483
484                 d = find_domain_from_name_noinit( dom_list[i].domain_name );
485
486                 /* ignore our primary and internal domains */
487
488                 if ( d && (d->internal || d->primary ) )
489                         continue;
490
491                 if ( (flags & NETR_TRUST_FLAG_INBOUND) &&
492                      (type == NETR_TRUST_TYPE_UPLEVEL) &&
493                      (attribs == NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) )
494                 {
495                         /* add the trusted domain if we don't know
496                            about it */
497
498                         if ( !d ) {
499                                 d = add_trusted_domain( dom_list[i].domain_name,
500                                                         dom_list[i].dns_name,
501                                                         &cache_methods,
502                                                         &dom_list[i].sid );
503                                 if (d != NULL) {
504                                         setup_domain_child(d);
505                                 }
506                         }
507
508                         if (d == NULL) {
509                                 continue;
510                         }
511
512                         DEBUG(10,("Following trust path for domain %s (%s)\n",
513                                   d->name, d->alt_name ));
514                         add_trusted_domains( d );
515                 }
516         }
517
518         TALLOC_FREE( dom_list );
519
520         return;
521 }
522
523 /*********************************************************************
524  The process of updating the trusted domain list is a three step
525  async process:
526  (a) ask our domain
527  (b) ask the root domain in our forest
528  (c) ask the a DC in any Win2003 trusted forests
529 *********************************************************************/
530
531 void rescan_trusted_domains(struct tevent_context *ev, struct tevent_timer *te,
532                             struct timeval now, void *private_data)
533 {
534         TALLOC_FREE(te);
535
536         /* I use to clear the cache here and start over but that
537            caused problems in child processes that needed the
538            trust dom list early on.  Removing it means we
539            could have some trusted domains listed that have been
540            removed from our primary domain's DC until a full
541            restart.  This should be ok since I think this is what
542            Windows does as well. */
543
544         /* this will only add new domains we didn't already know about
545            in the domain_list()*/
546
547         add_trusted_domains( find_our_domain() );
548
549         te = tevent_add_timer(
550                 ev, NULL, timeval_current_ofs(WINBINDD_RESCAN_FREQ, 0),
551                 rescan_trusted_domains, NULL);
552         /*
553          * If te == NULL, there's not much we can do here. Don't fail, the
554          * only thing we miss is new trusted domains.
555          */
556
557         return;
558 }
559
560 enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domain,
561                                                    struct winbindd_cli_state *state)
562 {
563         /* Ensure null termination */
564         state->request->domain_name
565                 [sizeof(state->request->domain_name)-1]='\0';
566         state->request->data.init_conn.dcname
567                 [sizeof(state->request->data.init_conn.dcname)-1]='\0';
568
569         if (strlen(state->request->data.init_conn.dcname) > 0) {
570                 fstrcpy(domain->dcname, state->request->data.init_conn.dcname);
571         }
572
573         if (domain->internal) {
574                 domain->initialized = true;
575         } else {
576                 init_dc_connection(domain);
577         }
578
579         if (!domain->initialized) {
580                 /* If we return error here we can't do any cached authentication,
581                    but we may be in disconnected mode and can't initialize correctly.
582                    Do what the previous code did and just return without initialization,
583                    once we go online we'll re-initialize.
584                 */
585                 DEBUG(5, ("winbindd_dual_init_connection: %s returning without initialization "
586                         "online = %d\n", domain->name, (int)domain->online ));
587         }
588
589         fstrcpy(state->response->data.domain_info.name, domain->name);
590         fstrcpy(state->response->data.domain_info.alt_name, domain->alt_name);
591         sid_to_fstring(state->response->data.domain_info.sid, &domain->sid);
592
593         state->response->data.domain_info.native_mode
594                 = domain->native_mode;
595         state->response->data.domain_info.active_directory
596                 = domain->active_directory;
597         state->response->data.domain_info.primary
598                 = domain->primary;
599
600         return WINBINDD_OK;
601 }
602
603 /* Look up global info for the winbind daemon */
604 bool init_domain_list(void)
605 {
606         struct winbindd_domain *domain;
607         int role = lp_server_role();
608
609         /* Free existing list */
610         free_domain_list();
611
612         /* BUILTIN domain */
613
614         domain = add_trusted_domain("BUILTIN", NULL, &builtin_passdb_methods,
615                                     &global_sid_Builtin);
616         if (domain) {
617                 setup_domain_child(domain);
618         }
619
620         /* Local SAM */
621
622         domain = add_trusted_domain(get_global_sam_name(), NULL,
623                                     &sam_passdb_methods, get_global_sam_sid());
624         if (domain) {
625                 if ( role != ROLE_DOMAIN_MEMBER ) {
626                         domain->primary = True;
627                 }
628                 setup_domain_child(domain);
629         }
630
631         /* Add ourselves as the first entry. */
632
633         if ( role == ROLE_DOMAIN_MEMBER ) {
634                 DOM_SID our_sid;
635
636                 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
637                         DEBUG(0, ("Could not fetch our SID - did we join?\n"));
638                         return False;
639                 }
640
641                 domain = add_trusted_domain( lp_workgroup(), lp_realm(),
642                                              &cache_methods, &our_sid);
643                 if (domain) {
644                         domain->primary = True;
645                         setup_domain_child(domain);
646
647                         /* Even in the parent winbindd we'll need to
648                            talk to the DC, so try and see if we can
649                            contact it. Theoretically this isn't neccessary
650                            as the init_dc_connection() in init_child_recv()
651                            will do this, but we can start detecting the DC
652                            early here. */
653                         set_domain_online_request(domain);
654                 }
655         }
656
657         return True;
658 }
659
660 void check_domain_trusted( const char *name, const DOM_SID *user_sid )
661 {
662         struct winbindd_domain *domain;
663         DOM_SID dom_sid;
664         uint32 rid;
665
666         /* Check if we even care */
667
668         if (!lp_allow_trusted_domains())
669                 return;
670
671         domain = find_domain_from_name_noinit( name );
672         if ( domain )
673                 return;
674
675         sid_copy( &dom_sid, user_sid );
676         if ( !sid_split_rid( &dom_sid, &rid ) )
677                 return;
678
679         /* add the newly discovered trusted domain */
680
681         domain = add_trusted_domain( name, NULL, &cache_methods,
682                                      &dom_sid);
683
684         if ( !domain )
685                 return;
686
687         /* assume this is a trust from a one-way transitive
688            forest trust */
689
690         domain->active_directory = True;
691         domain->domain_flags = NETR_TRUST_FLAG_OUTBOUND;
692         domain->domain_type  = NETR_TRUST_TYPE_UPLEVEL;
693         domain->internal = False;
694         domain->online = True;
695
696         setup_domain_child(domain);
697
698         wcache_tdc_add_domain( domain );
699
700         return;
701 }
702
703 /**
704  * Given a domain name, return the struct winbindd domain info for it
705  *
706  * @note Do *not* pass lp_workgroup() to this function.  domain_list
707  *       may modify it's value, and free that pointer.  Instead, our local
708  *       domain may be found by calling find_our_domain().
709  *       directly.
710  *
711  *
712  * @return The domain structure for the named domain, if it is working.
713  */
714
715 struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
716 {
717         struct winbindd_domain *domain;
718
719         /* Search through list */
720
721         for (domain = domain_list(); domain != NULL; domain = domain->next) {
722                 if (strequal(domain_name, domain->name) ||
723                     (domain->alt_name[0] &&
724                      strequal(domain_name, domain->alt_name))) {
725                         return domain;
726                 }
727         }
728
729         /* Not found */
730
731         return NULL;
732 }
733
734 struct winbindd_domain *find_domain_from_name(const char *domain_name)
735 {
736         struct winbindd_domain *domain;
737
738         domain = find_domain_from_name_noinit(domain_name);
739
740         if (domain == NULL)
741                 return NULL;
742
743         if (!domain->initialized)
744                 init_dc_connection(domain);
745
746         return domain;
747 }
748
749 /* Given a domain sid, return the struct winbindd domain info for it */
750
751 struct winbindd_domain *find_domain_from_sid_noinit(const DOM_SID *sid)
752 {
753         struct winbindd_domain *domain;
754
755         /* Search through list */
756
757         for (domain = domain_list(); domain != NULL; domain = domain->next) {
758                 if (sid_compare_domain(sid, &domain->sid) == 0)
759                         return domain;
760         }
761
762         /* Not found */
763
764         return NULL;
765 }
766
767 /* Given a domain sid, return the struct winbindd domain info for it */
768
769 struct winbindd_domain *find_domain_from_sid(const DOM_SID *sid)
770 {
771         struct winbindd_domain *domain;
772
773         domain = find_domain_from_sid_noinit(sid);
774
775         if (domain == NULL)
776                 return NULL;
777
778         if (!domain->initialized)
779                 init_dc_connection(domain);
780
781         return domain;
782 }
783
784 struct winbindd_domain *find_our_domain(void)
785 {
786         struct winbindd_domain *domain;
787
788         /* Search through list */
789
790         for (domain = domain_list(); domain != NULL; domain = domain->next) {
791                 if (domain->primary)
792                         return domain;
793         }
794
795         smb_panic("Could not find our domain");
796         return NULL;
797 }
798
799 struct winbindd_domain *find_root_domain(void)
800 {
801         struct winbindd_domain *ours = find_our_domain();
802
803         if (ours->forest_name[0] == '\0') {
804                 return NULL;
805         }
806
807         return find_domain_from_name( ours->forest_name );
808 }
809
810 struct winbindd_domain *find_builtin_domain(void)
811 {
812         struct winbindd_domain *domain;
813
814         domain = find_domain_from_sid(&global_sid_Builtin);
815         if (domain == NULL) {
816                 smb_panic("Could not find BUILTIN domain");
817         }
818
819         return domain;
820 }
821
822 /* Find the appropriate domain to lookup a name or SID */
823
824 struct winbindd_domain *find_lookup_domain_from_sid(const DOM_SID *sid)
825 {
826         /* SIDs in the S-1-22-{1,2} domain should be handled by our passdb */
827
828         if ( sid_check_is_in_unix_groups(sid) ||
829              sid_check_is_unix_groups(sid) ||
830              sid_check_is_in_unix_users(sid) ||
831              sid_check_is_unix_users(sid) )
832         {
833                 return find_domain_from_sid(get_global_sam_sid());
834         }
835
836         /* A DC can't ask the local smbd for remote SIDs, here winbindd is the
837          * one to contact the external DC's. On member servers the internal
838          * domains are different: These are part of the local SAM. */
839
840         DEBUG(10, ("find_lookup_domain_from_sid(%s)\n", sid_string_dbg(sid)));
841
842         if (IS_DC || is_internal_domain(sid) || is_in_internal_domain(sid)) {
843                 DEBUG(10, ("calling find_domain_from_sid\n"));
844                 return find_domain_from_sid(sid);
845         }
846
847         /* On a member server a query for SID or name can always go to our
848          * primary DC. */
849
850         DEBUG(10, ("calling find_our_domain\n"));
851         return find_our_domain();
852 }
853
854 struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
855 {
856         if ( strequal(domain_name, unix_users_domain_name() ) ||
857              strequal(domain_name, unix_groups_domain_name() ) )
858         {
859                 /*
860                  * The "Unix User" and "Unix Group" domain our handled by
861                  * passdb
862                  */
863                 return find_domain_from_name_noinit( get_global_sam_name() );
864         }
865
866         if (IS_DC || strequal(domain_name, "BUILTIN") ||
867             strequal(domain_name, get_global_sam_name()))
868                 return find_domain_from_name_noinit(domain_name);
869
870
871         return find_our_domain();
872 }
873
874 /* Is this a domain which we may assume no DOMAIN\ prefix? */
875
876 static bool assume_domain(const char *domain)
877 {
878         /* never assume the domain on a standalone server */
879
880         if ( lp_server_role() == ROLE_STANDALONE )
881                 return False;
882
883         /* domain member servers may possibly assume for the domain name */
884
885         if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
886                 if ( !strequal(lp_workgroup(), domain) )
887                         return False;
888
889                 if ( lp_winbind_use_default_domain() || lp_winbind_trusted_domains_only() )
890                         return True;
891         }
892
893         /* only left with a domain controller */
894
895         if ( strequal(get_global_sam_name(), domain) )  {
896                 return True;
897         }
898
899         return False;
900 }
901
902 /* Parse a string of the form DOMAIN\user into a domain and a user */
903
904 bool parse_domain_user(const char *domuser, fstring domain, fstring user)
905 {
906         char *p = strchr(domuser,*lp_winbind_separator());
907
908         if ( !p ) {
909                 fstrcpy(user, domuser);
910
911                 if ( assume_domain(lp_workgroup())) {
912                         fstrcpy(domain, lp_workgroup());
913                 } else if ((p = strchr(domuser, '@')) != NULL) {
914                         fstrcpy(domain, p + 1);
915                         user[PTR_DIFF(p, domuser)] = 0;
916                 } else {
917                         return False;
918                 }
919         } else {
920                 fstrcpy(user, p+1);
921                 fstrcpy(domain, domuser);
922                 domain[PTR_DIFF(p, domuser)] = 0;
923         }
924
925         strupper_m(domain);
926
927         return True;
928 }
929
930 bool parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser,
931                               char **domain, char **user)
932 {
933         fstring fstr_domain, fstr_user;
934         if (!parse_domain_user(domuser, fstr_domain, fstr_user)) {
935                 return False;
936         }
937         *domain = talloc_strdup(mem_ctx, fstr_domain);
938         *user = talloc_strdup(mem_ctx, fstr_user);
939         return ((*domain != NULL) && (*user != NULL));
940 }
941
942 /* add a domain user name to a buffer */
943 void parse_add_domuser(void *buf, char *domuser, int *len)
944 {
945         fstring domain;
946         char *p, *user;
947
948         user = domuser;
949         p = strchr(domuser, *lp_winbind_separator());
950
951         if (p) {
952
953                 fstrcpy(domain, domuser);
954                 domain[PTR_DIFF(p, domuser)] = 0;
955                 p++;
956
957                 if (assume_domain(domain)) {
958
959                         user = p;
960                         *len -= (PTR_DIFF(p, domuser));
961                 }
962         }
963
964         safe_strcpy((char *)buf, user, *len);
965 }
966
967 /* Ensure an incoming username from NSS is fully qualified. Replace the
968    incoming fstring with DOMAIN <separator> user. Returns the same
969    values as parse_domain_user() but also replaces the incoming username.
970    Used to ensure all names are fully qualified within winbindd.
971    Used by the NSS protocols of auth, chauthtok, logoff and ccache_ntlm_auth.
972    The protocol definitions of auth_crap, chng_pswd_auth_crap
973    really should be changed to use this instead of doing things
974    by hand. JRA. */
975
976 bool canonicalize_username(fstring username_inout, fstring domain, fstring user)
977 {
978         if (!parse_domain_user(username_inout, domain, user)) {
979                 return False;
980         }
981         slprintf(username_inout, sizeof(fstring) - 1, "%s%c%s",
982                  domain, *lp_winbind_separator(),
983                  user);
984         return True;
985 }
986
987 /*
988     Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
989     'winbind separator' options.
990     This means:
991         - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
992         lp_workgroup()
993
994     If we are a PDC or BDC, and this is for our domain, do likewise.
995
996     Also, if omit DOMAIN if 'winbind trusted domains only = true', as the
997     username is then unqualified in unix
998
999     We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1000 */
1001 void fill_domain_username(fstring name, const char *domain, const char *user, bool can_assume)
1002 {
1003         fstring tmp_user;
1004
1005         fstrcpy(tmp_user, user);
1006         strlower_m(tmp_user);
1007
1008         if (can_assume && assume_domain(domain)) {
1009                 strlcpy(name, tmp_user, sizeof(fstring));
1010         } else {
1011                 slprintf(name, sizeof(fstring) - 1, "%s%c%s",
1012                          domain, *lp_winbind_separator(),
1013                          tmp_user);
1014         }
1015 }
1016
1017 /**
1018  * talloc version of fill_domain_username()
1019  * return NULL on talloc failure.
1020  */
1021 char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
1022                                   const char *domain,
1023                                   const char *user,
1024                                   bool can_assume)
1025 {
1026         char *tmp_user, *name;
1027
1028         tmp_user = talloc_strdup(mem_ctx, user);
1029         strlower_m(tmp_user);
1030
1031         if (can_assume && assume_domain(domain)) {
1032                 name = tmp_user;
1033         } else {
1034                 name = talloc_asprintf(mem_ctx, "%s%c%s",
1035                                        domain,
1036                                        *lp_winbind_separator(),
1037                                        tmp_user);
1038                 TALLOC_FREE(tmp_user);
1039         }
1040
1041         return name;
1042 }
1043
1044 /*
1045  * Winbindd socket accessor functions
1046  */
1047
1048 const char *get_winbind_pipe_dir(void)
1049 {
1050         return lp_parm_const_string(-1, "winbindd", "socket dir", WINBINDD_SOCKET_DIR);
1051 }
1052
1053 char *get_winbind_priv_pipe_dir(void)
1054 {
1055         return lock_path(WINBINDD_PRIV_SOCKET_SUBDIR);
1056 }
1057
1058 /* Open the winbindd socket */
1059
1060 static int _winbindd_socket = -1;
1061 static int _winbindd_priv_socket = -1;
1062
1063 int open_winbindd_socket(void)
1064 {
1065         if (_winbindd_socket == -1) {
1066                 _winbindd_socket = create_pipe_sock(
1067                         get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME, 0755);
1068                 DEBUG(10, ("open_winbindd_socket: opened socket fd %d\n",
1069                            _winbindd_socket));
1070         }
1071
1072         return _winbindd_socket;
1073 }
1074
1075 int open_winbindd_priv_socket(void)
1076 {
1077         if (_winbindd_priv_socket == -1) {
1078                 _winbindd_priv_socket = create_pipe_sock(
1079                         get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750);
1080                 DEBUG(10, ("open_winbindd_priv_socket: opened socket fd %d\n",
1081                            _winbindd_priv_socket));
1082         }
1083
1084         return _winbindd_priv_socket;
1085 }
1086
1087 /*
1088  * Client list accessor functions
1089  */
1090
1091 static struct winbindd_cli_state *_client_list;
1092 static int _num_clients;
1093
1094 /* Return list of all connected clients */
1095
1096 struct winbindd_cli_state *winbindd_client_list(void)
1097 {
1098         return _client_list;
1099 }
1100
1101 /* Add a connection to the list */
1102
1103 void winbindd_add_client(struct winbindd_cli_state *cli)
1104 {
1105         DLIST_ADD(_client_list, cli);
1106         _num_clients++;
1107 }
1108
1109 /* Remove a client from the list */
1110
1111 void winbindd_remove_client(struct winbindd_cli_state *cli)
1112 {
1113         DLIST_REMOVE(_client_list, cli);
1114         _num_clients--;
1115 }
1116
1117 /* Close all open clients */
1118
1119 void winbindd_kill_all_clients(void)
1120 {
1121         struct winbindd_cli_state *cl = winbindd_client_list();
1122
1123         DEBUG(10, ("winbindd_kill_all_clients: going postal\n"));
1124
1125         while (cl) {
1126                 struct winbindd_cli_state *next;
1127
1128                 next = cl->next;
1129                 winbindd_remove_client(cl);
1130                 cl = next;
1131         }
1132 }
1133
1134 /* Return number of open clients */
1135
1136 int winbindd_num_clients(void)
1137 {
1138         return _num_clients;
1139 }
1140
1141 NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain,
1142                                   TALLOC_CTX *mem_ctx,
1143                                   const DOM_SID *user_sid,
1144                                   uint32 *p_num_groups, DOM_SID **user_sids)
1145 {
1146         struct netr_SamInfo3 *info3 = NULL;
1147         NTSTATUS status = NT_STATUS_NO_MEMORY;
1148         size_t num_groups = 0;
1149
1150         DEBUG(3,(": lookup_usergroups_cached\n"));
1151
1152         *user_sids = NULL;
1153         *p_num_groups = 0;
1154
1155         info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1156
1157         if (info3 == NULL) {
1158                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1159         }
1160
1161         if (info3->base.groups.count == 0) {
1162                 TALLOC_FREE(info3);
1163                 return NT_STATUS_UNSUCCESSFUL;
1164         }
1165
1166         /* Skip Domain local groups outside our domain.
1167            We'll get these from the getsidaliases() RPC call. */
1168         status = sid_array_from_info3(mem_ctx, info3,
1169                                       user_sids,
1170                                       &num_groups,
1171                                       false, true);
1172
1173         if (!NT_STATUS_IS_OK(status)) {
1174                 TALLOC_FREE(info3);
1175                 return status;
1176         }
1177
1178         TALLOC_FREE(info3);
1179         *p_num_groups = num_groups;
1180         status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1181
1182         DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1183
1184         return status;
1185 }
1186
1187 /*********************************************************************
1188  We use this to remove spaces from user and group names
1189 ********************************************************************/
1190
1191 NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
1192                              struct winbindd_domain *domain,
1193                              const char *name,
1194                              char **normalized)
1195 {
1196         NTSTATUS nt_status;
1197
1198         if (!name || !normalized) {
1199                 return NT_STATUS_INVALID_PARAMETER;
1200         }
1201
1202         if (!lp_winbind_normalize_names()) {
1203                 return NT_STATUS_PROCEDURE_NOT_FOUND;
1204         }
1205
1206         /* Alias support and whitespace replacement are mutually
1207            exclusive */
1208
1209         nt_status = resolve_username_to_alias(mem_ctx, domain,
1210                                               name, normalized );
1211         if (NT_STATUS_IS_OK(nt_status)) {
1212                 /* special return code to let the caller know we
1213                    mapped to an alias */
1214                 return NT_STATUS_FILE_RENAMED;
1215         }
1216
1217         /* check for an unreachable domain */
1218
1219         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1220                 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1221                          domain->name));
1222                 set_domain_offline(domain);
1223                 return nt_status;
1224         }
1225
1226         /* deal with whitespace */
1227
1228         *normalized = talloc_strdup(mem_ctx, name);
1229         if (!(*normalized)) {
1230                 return NT_STATUS_NO_MEMORY;
1231         }
1232
1233         all_string_sub( *normalized, " ", "_", 0 );
1234
1235         return NT_STATUS_OK;
1236 }
1237
1238 /*********************************************************************
1239  We use this to do the inverse of normalize_name_map()
1240 ********************************************************************/
1241
1242 NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
1243                               char *name,
1244                               char **normalized)
1245 {
1246         NTSTATUS nt_status;
1247         struct winbindd_domain *domain = find_our_domain();
1248
1249         if (!name || !normalized) {
1250                 return NT_STATUS_INVALID_PARAMETER;
1251         }
1252
1253         if (!lp_winbind_normalize_names()) {
1254                 return NT_STATUS_PROCEDURE_NOT_FOUND;
1255         }
1256
1257         /* Alias support and whitespace replacement are mutally
1258            exclusive */
1259
1260         /* When mapping from an alias to a username, we don't know the
1261            domain.  But we only need a domain structure to cache
1262            a successful lookup , so just our own domain structure for
1263            the seqnum. */
1264
1265         nt_status = resolve_alias_to_username(mem_ctx, domain,
1266                                               name, normalized);
1267         if (NT_STATUS_IS_OK(nt_status)) {
1268                 /* Special return code to let the caller know we mapped
1269                    from an alias */
1270                 return NT_STATUS_FILE_RENAMED;
1271         }
1272
1273         /* check for an unreachable domain */
1274
1275         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1276                 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1277                          domain->name));
1278                 set_domain_offline(domain);
1279                 return nt_status;
1280         }
1281
1282         /* deal with whitespace */
1283
1284         *normalized = talloc_strdup(mem_ctx, name);
1285         if (!(*normalized)) {
1286                 return NT_STATUS_NO_MEMORY;
1287         }
1288
1289         all_string_sub(*normalized, "_", " ", 0);
1290
1291         return NT_STATUS_OK;
1292 }
1293
1294 /*********************************************************************
1295  ********************************************************************/
1296
1297 bool winbindd_can_contact_domain(struct winbindd_domain *domain)
1298 {
1299         struct winbindd_tdc_domain *tdc = NULL;
1300         TALLOC_CTX *frame = talloc_stackframe();
1301         bool ret = false;
1302
1303         /* We can contact the domain if it is our primary domain */
1304
1305         if (domain->primary) {
1306                 return true;
1307         }
1308
1309         /* Trust the TDC cache and not the winbindd_domain flags */
1310
1311         if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
1312                 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
1313                           domain->name));
1314                 return false;
1315         }
1316
1317         /* Can always contact a domain that is in out forest */
1318
1319         if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1320                 ret = true;
1321                 goto done;
1322         }
1323
1324         /*
1325          * On a _member_ server, we cannot contact the domain if it
1326          * is running AD and we have no inbound trust.
1327          */
1328
1329         if (!IS_DC &&
1330              domain->active_directory &&
1331             ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
1332         {
1333                 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
1334                            "and we have no inbound trust.\n", domain->name));
1335                 goto done;
1336         }
1337
1338         /* Assume everything else is ok (probably not true but what
1339            can you do?) */
1340
1341         ret = true;
1342
1343 done:
1344         talloc_destroy(frame);
1345
1346         return ret;
1347 }
1348
1349 /*********************************************************************
1350  ********************************************************************/
1351
1352 bool winbindd_internal_child(struct winbindd_child *child)
1353 {
1354         if ((child == idmap_child()) || (child == locator_child())) {
1355                 return True;
1356         }
1357
1358         return False;
1359 }
1360
1361 #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
1362
1363 /*********************************************************************
1364  ********************************************************************/
1365
1366 static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
1367 {
1368         char *var = NULL;
1369         char addr[INET6_ADDRSTRLEN];
1370         const char *kdc = NULL;
1371         int lvl = 11;
1372
1373         if (!domain || !domain->alt_name || !*domain->alt_name) {
1374                 return;
1375         }
1376
1377         if (domain->initialized && !domain->active_directory) {
1378                 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
1379                         domain->alt_name));
1380                 return;
1381         }
1382
1383         print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
1384         kdc = addr;
1385         if (!*kdc) {
1386                 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
1387                         domain->alt_name));
1388                 kdc = domain->dcname;
1389         }
1390
1391         if (!kdc || !*kdc) {
1392                 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
1393                         domain->alt_name));
1394                 return;
1395         }
1396
1397         if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
1398                                 domain->alt_name) == -1) {
1399                 return;
1400         }
1401
1402         DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
1403                 var, kdc));
1404
1405         setenv(var, kdc, 1);
1406         free(var);
1407 }
1408
1409 /*********************************************************************
1410  ********************************************************************/
1411
1412 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
1413 {
1414         struct winbindd_domain *our_dom = find_our_domain();
1415
1416         winbindd_set_locator_kdc_env(domain);
1417
1418         if (domain != our_dom) {
1419                 winbindd_set_locator_kdc_env(our_dom);
1420         }
1421 }
1422
1423 /*********************************************************************
1424  ********************************************************************/
1425
1426 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
1427 {
1428         char *var = NULL;
1429
1430         if (!domain || !domain->alt_name || !*domain->alt_name) {
1431                 return;
1432         }
1433
1434         if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
1435                                 domain->alt_name) == -1) {
1436                 return;
1437         }
1438
1439         unsetenv(var);
1440         free(var);
1441 }
1442 #else
1443
1444 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
1445 {
1446         return;
1447 }
1448
1449 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
1450 {
1451         return;
1452 }
1453
1454 #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
1455
1456 void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
1457 {
1458         resp->data.auth.nt_status = NT_STATUS_V(result);
1459         fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
1460
1461         /* we might have given a more useful error above */
1462         if (*resp->data.auth.error_string == '\0')
1463                 fstrcpy(resp->data.auth.error_string,
1464                         get_friendly_nt_error_msg(result));
1465         resp->data.auth.pam_error = nt_status_to_pam(result);
1466 }
1467
1468 bool is_domain_offline(const struct winbindd_domain *domain)
1469 {
1470         if (!lp_winbind_offline_logon()) {
1471                 return false;
1472         }
1473         if (get_global_winbindd_state_offline()) {
1474                 return true;
1475         }
1476         return !domain->online;
1477 }