winbindd: rework add_trusted_domain(), replacing add_trusted_domain_from_tdc()
[samba.git] / source3 / winbindd / winbindd_util.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Winbind daemon for ntdom nss module
5
6    Copyright (C) Tim Potter 2000-2001
7    Copyright (C) 2001 by Martin Pool <mbp@samba.org>
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "winbindd.h"
25 #include "lib/util_unixsids.h"
26 #include "secrets.h"
27 #include "../libcli/security/security.h"
28 #include "../libcli/auth/pam_errors.h"
29 #include "passdb/machine_sid.h"
30 #include "passdb.h"
31 #include "source4/lib/messaging/messaging.h"
32 #include "librpc/gen_ndr/ndr_lsa.h"
33 #include "auth/credentials/credentials.h"
34 #include "libsmb/samlogon_cache.h"
35
36 #undef DBGC_CLASS
37 #define DBGC_CLASS DBGC_WINBIND
38
39 /**
40  * @file winbindd_util.c
41  *
42  * Winbind daemon for NT domain authentication nss module.
43  **/
44
45
46 /* The list of trusted domains.  Note that the list can be deleted and
47    recreated using the init_domain_list() function so pointers to
48    individual winbindd_domain structures cannot be made.  Keep a copy of
49    the domain name instead. */
50
51 static struct winbindd_domain *_domain_list = NULL;
52
53 struct winbindd_domain *domain_list(void)
54 {
55         /* Initialise list */
56
57         if ((!_domain_list) && (!init_domain_list())) {
58                 smb_panic("Init_domain_list failed");
59         }
60
61         return _domain_list;
62 }
63
64 /* Free all entries in the trusted domain list */
65
66 static void free_domain_list(void)
67 {
68         struct winbindd_domain *domain = _domain_list;
69
70         while(domain) {
71                 struct winbindd_domain *next = domain->next;
72
73                 DLIST_REMOVE(_domain_list, domain);
74                 TALLOC_FREE(domain);
75                 domain = next;
76         }
77 }
78
79 /**
80  * Iterator for winbindd's domain list.
81  * To be used (e.g.) in tevent based loops.
82  */
83 struct winbindd_domain *wb_next_domain(struct winbindd_domain *domain)
84 {
85         if (domain == NULL) {
86                 domain = domain_list();
87         } else {
88                 domain = domain->next;
89         }
90
91         if ((domain != NULL) &&
92             (lp_server_role() != ROLE_ACTIVE_DIRECTORY_DC) &&
93             sid_check_is_our_sam(&domain->sid))
94         {
95                 domain = domain->next;
96         }
97
98         return domain;
99 }
100
101 static bool is_internal_domain(const struct dom_sid *sid)
102 {
103         if (sid == NULL)
104                 return False;
105
106         return (sid_check_is_our_sam(sid) || sid_check_is_builtin(sid));
107 }
108
109 static bool is_in_internal_domain(const struct dom_sid *sid)
110 {
111         if (sid == NULL)
112                 return False;
113
114         return (sid_check_is_in_our_sam(sid) || sid_check_is_in_builtin(sid));
115 }
116
117
118 /* Add a trusted domain to our list of domains.
119    If the domain already exists in the list,
120    return it and don't re-initialize.  */
121
122 static NTSTATUS add_trusted_domain(const char *domain_name,
123                                    const char *dns_name,
124                                    const struct dom_sid *sid,
125                                    uint32_t trust_type,
126                                    uint32_t trust_flags,
127                                    uint32_t trust_attribs,
128                                    struct winbindd_domain **_d)
129 {
130         struct winbindd_domain *domain = NULL;
131         const char **ignored_domains = NULL;
132         const char **dom = NULL;
133         int role = lp_server_role();
134
135         if (is_null_sid(sid)) {
136                 DBG_ERR("Got null SID for domain [%s]\n", domain_name);
137                 return NT_STATUS_INVALID_PARAMETER;
138         }
139
140         ignored_domains = lp_parm_string_list(-1, "winbind", "ignore domains", NULL);
141         for (dom=ignored_domains; dom && *dom; dom++) {
142                 if (gen_fnmatch(*dom, domain_name) == 0) {
143                         DEBUG(2,("Ignoring domain '%s'\n", domain_name));
144                         return NT_STATUS_NO_SUCH_DOMAIN;
145                 }
146         }
147
148         /*
149          * We can't call domain_list() as this function is called from
150          * init_domain_list() and we'll get stuck in a loop.
151          */
152         for (domain = _domain_list; domain; domain = domain->next) {
153                 if (strequal(domain_name, domain->name)) {
154                         break;
155                 }
156         }
157
158         if (domain != NULL) {
159                 struct winbindd_domain *check_domain = NULL;
160
161                 for (check_domain = _domain_list;
162                      check_domain != NULL;
163                      check_domain = check_domain->next)
164                 {
165                         if (check_domain == domain) {
166                                 continue;
167                         }
168
169                         if (dom_sid_equal(&check_domain->sid, sid)) {
170                                 break;
171                         }
172                 }
173
174                 if (check_domain != NULL) {
175                         DBG_ERR("SID [%s] already used by domain [%s], "
176                                 "expected [%s]\n",
177                                 sid_string_dbg(sid), check_domain->name,
178                                 domain->name);
179                         return NT_STATUS_INVALID_PARAMETER;
180                 }
181         }
182
183         if ((domain != NULL) && (dns_name != NULL)) {
184                 struct winbindd_domain *check_domain = NULL;
185
186                 for (check_domain = _domain_list;
187                      check_domain != NULL;
188                      check_domain = check_domain->next)
189                 {
190                         if (check_domain == domain) {
191                                 continue;
192                         }
193
194                         if (strequal(check_domain->alt_name, dns_name)) {
195                                 break;
196                         }
197                 }
198
199                 if (check_domain != NULL) {
200                         DBG_ERR("DNS name [%s] used by domain [%s], "
201                                 "expected [%s]\n",
202                                 dns_name, check_domain->name,
203                                 domain->name);
204                         return NT_STATUS_INVALID_PARAMETER;
205                 }
206         }
207
208         if (domain != NULL) {
209                 *_d = domain;
210                 return NT_STATUS_OK;
211         }
212
213         /* Create new domain entry */
214         domain = talloc_zero(NULL, struct winbindd_domain);
215         if (domain == NULL) {
216                 return NT_STATUS_NO_MEMORY;
217         }
218
219         domain->children = talloc_zero_array(domain,
220                                              struct winbindd_child,
221                                              lp_winbind_max_domain_connections());
222         if (domain->children == NULL) {
223                 TALLOC_FREE(domain);
224                 return NT_STATUS_NO_MEMORY;
225         }
226
227         domain->name = talloc_strdup(domain, domain_name);
228         if (domain->name == NULL) {
229                 TALLOC_FREE(domain);
230                 return NT_STATUS_NO_MEMORY;
231         }
232
233         if (dns_name != NULL) {
234                 domain->alt_name = talloc_strdup(domain, dns_name);
235                 if (domain->alt_name == NULL) {
236                         TALLOC_FREE(domain);
237                         return NT_STATUS_NO_MEMORY;
238                 }
239         }
240
241         domain->backend = NULL;
242         domain->internal = is_internal_domain(sid);
243         domain->sequence_number = DOM_SEQUENCE_NONE;
244         domain->last_seq_check = 0;
245         domain->initialized = false;
246         domain->online = is_internal_domain(sid);
247         domain->check_online_timeout = 0;
248         domain->dc_probe_pid = (pid_t)-1;
249         domain->domain_flags = trust_flags;
250         domain->domain_type = trust_type;
251         domain->domain_trust_attribs = trust_attribs;
252         sid_copy(&domain->sid, sid);
253
254         /* Is this our primary domain ? */
255         if (role == ROLE_DOMAIN_MEMBER) {
256                 domain->primary = strequal(domain_name, lp_workgroup());
257         } else {
258                 domain->primary = strequal(domain_name, get_global_sam_name());
259         }
260
261         if (domain->primary) {
262                 if (role == ROLE_ACTIVE_DIRECTORY_DC) {
263                         domain->active_directory = true;
264                 }
265                 if (lp_security() == SEC_ADS) {
266                         domain->active_directory = true;
267                 }
268         } else if (!domain->internal) {
269                 if (domain->domain_type == LSA_TRUST_TYPE_UPLEVEL) {
270                         domain->active_directory = true;
271                 }
272         }
273
274         /* Link to domain list */
275         DLIST_ADD_END(_domain_list, domain);
276
277         wcache_tdc_add_domain( domain );
278
279         setup_domain_child(domain);
280
281         DBG_NOTICE("Added domain [%s] [%s] [%s]\n",
282                    domain->name, domain->alt_name,
283                    sid_string_dbg(&domain->sid));
284
285         *_d = domain;
286         return NT_STATUS_OK;
287 }
288
289 bool domain_is_forest_root(const struct winbindd_domain *domain)
290 {
291         const uint32_t fr_flags =
292                 (NETR_TRUST_FLAG_TREEROOT|NETR_TRUST_FLAG_IN_FOREST);
293
294         return ((domain->domain_flags & fr_flags) == fr_flags);
295 }
296
297 /********************************************************************
298   rescan our domains looking for new trusted domains
299 ********************************************************************/
300
301 struct trustdom_state {
302         struct winbindd_domain *domain;
303         struct winbindd_request request;
304 };
305
306 static void trustdom_list_done(struct tevent_req *req);
307 static void rescan_forest_root_trusts( void );
308 static void rescan_forest_trusts( void );
309
310 static void add_trusted_domains( struct winbindd_domain *domain )
311 {
312         struct trustdom_state *state;
313         struct tevent_req *req;
314
315         state = talloc_zero(NULL, struct trustdom_state);
316         if (state == NULL) {
317                 DEBUG(0, ("talloc failed\n"));
318                 return;
319         }
320         state->domain = domain;
321
322         state->request.length = sizeof(state->request);
323         state->request.cmd = WINBINDD_LIST_TRUSTDOM;
324
325         req = wb_domain_request_send(state, server_event_context(),
326                                      domain, &state->request);
327         if (req == NULL) {
328                 DEBUG(1, ("wb_domain_request_send failed\n"));
329                 TALLOC_FREE(state);
330                 return;
331         }
332         tevent_req_set_callback(req, trustdom_list_done, state);
333 }
334
335 static void trustdom_list_done(struct tevent_req *req)
336 {
337         struct trustdom_state *state = tevent_req_callback_data(
338                 req, struct trustdom_state);
339         struct winbindd_response *response;
340         int res, err;
341         char *p;
342         ptrdiff_t extra_len;
343         bool within_forest = false;
344         NTSTATUS status;
345
346         /*
347          * Only when we enumerate our primary domain
348          * or our forest root domain, we should keep
349          * the NETR_TRUST_FLAG_IN_FOREST flag, in
350          * all other cases we need to clear it as the domain
351          * is not part of our forest.
352          */
353         if (state->domain->primary) {
354                 within_forest = true;
355         } else if (domain_is_forest_root(state->domain)) {
356                 within_forest = true;
357         }
358
359         res = wb_domain_request_recv(req, state, &response, &err);
360         if ((res == -1) || (response->result != WINBINDD_OK)) {
361                 DBG_WARNING("Could not receive trusts for domain %s\n",
362                             state->domain->name);
363                 TALLOC_FREE(state);
364                 return;
365         }
366
367         if (response->length < sizeof(struct winbindd_response)) {
368                 DBG_ERR("ill-formed trustdom response - short length\n");
369                 TALLOC_FREE(state);
370                 return;
371         }
372
373         extra_len = response->length - sizeof(struct winbindd_response);
374
375         p = (char *)response->extra_data.data;
376
377         while ((p - (char *)response->extra_data.data) < extra_len) {
378                 struct winbindd_domain *domain = NULL;
379                 char *name, *q, *sidstr, *alt_name;
380                 struct dom_sid sid;
381                 uint32_t trust_type;
382                 uint32_t trust_attribs;
383                 uint32_t trust_flags;
384
385                 DBG_DEBUG("parsing response line '%s'\n", p);
386
387                 name = p;
388
389                 alt_name = strchr(p, '\\');
390                 if (alt_name == NULL) {
391                         DBG_ERR("Got invalid trustdom response\n");
392                         break;
393                 }
394
395                 *alt_name = '\0';
396                 alt_name += 1;
397
398                 sidstr = strchr(alt_name, '\\');
399                 if (sidstr == NULL) {
400                         DBG_ERR("Got invalid trustdom response\n");
401                         break;
402                 }
403
404                 *sidstr = '\0';
405                 sidstr += 1;
406
407                 /* use the real alt_name if we have one, else pass in NULL */
408                 if (strequal(alt_name, "(null)")) {
409                         alt_name = NULL;
410                 }
411
412                 q = strtok(sidstr, "\\");
413                 if (q == NULL) {
414                         DBG_ERR("Got invalid trustdom response\n");
415                         break;
416                 }
417
418                 if (!string_to_sid(&sid, sidstr)) {
419                         DEBUG(0, ("Got invalid trustdom response\n"));
420                         break;
421                 }
422
423                 q = strtok(NULL, "\\");
424                 if (q == NULL) {
425                         DBG_ERR("Got invalid trustdom response\n");
426                         break;
427                 }
428
429                 trust_flags = (uint32_t)strtoul(q, NULL, 10);
430
431                 q = strtok(NULL, "\\");
432                 if (q == NULL) {
433                         DBG_ERR("Got invalid trustdom response\n");
434                         break;
435                 }
436
437                 trust_type = (uint32_t)strtoul(q, NULL, 10);
438
439                 q = strtok(NULL, "\n");
440                 if (q == NULL) {
441                         DBG_ERR("Got invalid trustdom response\n");
442                         break;
443                 }
444
445                 trust_attribs = (uint32_t)strtoul(q, NULL, 10);
446
447                 if (!within_forest) {
448                         trust_flags &= ~NETR_TRUST_FLAG_IN_FOREST;
449                 }
450
451                 if (!state->domain->primary) {
452                         trust_flags &= ~NETR_TRUST_FLAG_PRIMARY;
453                 }
454
455                 /*
456                  * We always call add_trusted_domain() cause on an existing
457                  * domain structure, it will update the SID if necessary.
458                  * This is important because we need the SID for sibling
459                  * domains.
460                  */
461                 status = add_trusted_domain(name,
462                                             alt_name,
463                                             &sid,
464                                             trust_type,
465                                             trust_flags,
466                                             trust_attribs,
467                                             &domain);
468                 if (!NT_STATUS_IS_OK(status) &&
469                     !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
470                 {
471                         DBG_NOTICE("add_trusted_domain returned %s\n",
472                                    nt_errstr(status));
473                         return;
474                 }
475
476                 p = q + strlen(q) + 1;
477         }
478
479         /*
480            Cases to consider when scanning trusts:
481            (a) we are calling from a child domain (primary && !forest_root)
482            (b) we are calling from the root of the forest (primary && forest_root)
483            (c) we are calling from a trusted forest domain (!primary
484                && !forest_root)
485         */
486
487         if (state->domain->primary) {
488                 /* If this is our primary domain and we are not in the
489                    forest root, we have to scan the root trusts first */
490
491                 if (!domain_is_forest_root(state->domain))
492                         rescan_forest_root_trusts();
493                 else
494                         rescan_forest_trusts();
495
496         } else if (domain_is_forest_root(state->domain)) {
497                 /* Once we have done root forest trust search, we can
498                    go on to search the trusted forests */
499
500                 rescan_forest_trusts();
501         }
502
503         TALLOC_FREE(state);
504
505         return;
506 }
507
508 /********************************************************************
509  Scan the trusts of our forest root
510 ********************************************************************/
511
512 static void rescan_forest_root_trusts( void )
513 {
514         struct winbindd_tdc_domain *dom_list = NULL;
515         size_t num_trusts = 0;
516         int i;
517         NTSTATUS status;
518
519         /* The only transitive trusts supported by Windows 2003 AD are
520            (a) Parent-Child, (b) Tree-Root, and (c) Forest.   The
521            first two are handled in forest and listed by
522            DsEnumerateDomainTrusts().  Forest trusts are not so we
523            have to do that ourselves. */
524
525         if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
526                 return;
527
528         for ( i=0; i<num_trusts; i++ ) {
529                 struct winbindd_domain *d = NULL;
530
531                 /* Find the forest root.  Don't necessarily trust
532                    the domain_list() as our primary domain may not
533                    have been initialized. */
534
535                 if ( !(dom_list[i].trust_flags & NETR_TRUST_FLAG_TREEROOT) ) {
536                         continue;
537                 }
538
539                 /* Here's the forest root */
540
541                 d = find_domain_from_name_noinit( dom_list[i].domain_name );
542                 if (d == NULL) {
543                         status = add_trusted_domain(dom_list[i].domain_name,
544                                                     dom_list[i].dns_name,
545                                                     &dom_list[i].sid,
546                                                     dom_list[i].trust_type,
547                                                     dom_list[i].trust_flags,
548                                                     dom_list[i].trust_attribs,
549                                                     &d);
550
551                         if (!NT_STATUS_IS_OK(status) &&
552                             NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
553                         {
554                                 DBG_ERR("add_trusted_domain returned %s\n",
555                                         nt_errstr(status));
556                                 return;
557                         }
558                 }
559                 if (d == NULL) {
560                         continue;
561                 }
562
563                 DEBUG(10,("rescan_forest_root_trusts: Following trust path "
564                           "for domain tree root %s (%s)\n",
565                           d->name, d->alt_name ));
566
567                 d->domain_flags = dom_list[i].trust_flags;
568                 d->domain_type  = dom_list[i].trust_type;
569                 d->domain_trust_attribs = dom_list[i].trust_attribs;
570
571                 add_trusted_domains( d );
572
573                 break;
574         }
575
576         TALLOC_FREE( dom_list );
577
578         return;
579 }
580
581 /********************************************************************
582  scan the transitive forest trusts (not our own)
583 ********************************************************************/
584
585
586 static void rescan_forest_trusts( void )
587 {
588         struct winbindd_domain *d = NULL;
589         struct winbindd_tdc_domain *dom_list = NULL;
590         size_t num_trusts = 0;
591         int i;
592         NTSTATUS status;
593
594         /* The only transitive trusts supported by Windows 2003 AD are
595            (a) Parent-Child, (b) Tree-Root, and (c) Forest.   The
596            first two are handled in forest and listed by
597            DsEnumerateDomainTrusts().  Forest trusts are not so we
598            have to do that ourselves. */
599
600         if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
601                 return;
602
603         for ( i=0; i<num_trusts; i++ ) {
604                 uint32_t flags   = dom_list[i].trust_flags;
605                 uint32_t type    = dom_list[i].trust_type;
606                 uint32_t attribs = dom_list[i].trust_attribs;
607
608                 d = find_domain_from_name_noinit( dom_list[i].domain_name );
609
610                 /* ignore our primary and internal domains */
611
612                 if ( d && (d->internal || d->primary ) )
613                         continue;
614
615                 if ( (flags & NETR_TRUST_FLAG_INBOUND) &&
616                      (type == LSA_TRUST_TYPE_UPLEVEL) &&
617                      (attribs == LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) )
618                 {
619                         /* add the trusted domain if we don't know
620                            about it */
621
622                         if (d == NULL) {
623                                 status = add_trusted_domain(
624                                         dom_list[i].domain_name,
625                                         dom_list[i].dns_name,
626                                         &dom_list[i].sid,
627                                         type,
628                                         flags,
629                                         attribs,
630                                         &d);
631                                 if (!NT_STATUS_IS_OK(status) &&
632                                     NT_STATUS_EQUAL(status,
633                                                     NT_STATUS_NO_SUCH_DOMAIN))
634                                 {
635                                         DBG_ERR("add_trusted_domain: %s\n",
636                                                 nt_errstr(status));
637                                         return;
638                                 }
639                         }
640
641                         if (d == NULL) {
642                                 continue;
643                         }
644
645                         DEBUG(10,("Following trust path for domain %s (%s)\n",
646                                   d->name, d->alt_name ));
647                         add_trusted_domains( d );
648                 }
649         }
650
651         TALLOC_FREE( dom_list );
652
653         return;
654 }
655
656 /*********************************************************************
657  The process of updating the trusted domain list is a three step
658  async process:
659  (a) ask our domain
660  (b) ask the root domain in our forest
661  (c) ask the a DC in any Win2003 trusted forests
662 *********************************************************************/
663
664 void rescan_trusted_domains(struct tevent_context *ev, struct tevent_timer *te,
665                             struct timeval now, void *private_data)
666 {
667         TALLOC_FREE(te);
668
669         /* I use to clear the cache here and start over but that
670            caused problems in child processes that needed the
671            trust dom list early on.  Removing it means we
672            could have some trusted domains listed that have been
673            removed from our primary domain's DC until a full
674            restart.  This should be ok since I think this is what
675            Windows does as well. */
676
677         /* this will only add new domains we didn't already know about
678            in the domain_list()*/
679
680         add_trusted_domains( find_our_domain() );
681
682         te = tevent_add_timer(
683                 ev, NULL, timeval_current_ofs(WINBINDD_RESCAN_FREQ, 0),
684                 rescan_trusted_domains, NULL);
685         /*
686          * If te == NULL, there's not much we can do here. Don't fail, the
687          * only thing we miss is new trusted domains.
688          */
689
690         return;
691 }
692
693 enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domain,
694                                                    struct winbindd_cli_state *state)
695 {
696         /* Ensure null termination */
697         state->request->domain_name
698                 [sizeof(state->request->domain_name)-1]='\0';
699         state->request->data.init_conn.dcname
700                 [sizeof(state->request->data.init_conn.dcname)-1]='\0';
701
702         if (strlen(state->request->data.init_conn.dcname) > 0) {
703                 fstrcpy(domain->dcname, state->request->data.init_conn.dcname);
704         }
705
706         init_dc_connection(domain, false);
707
708         if (!domain->initialized) {
709                 /* If we return error here we can't do any cached authentication,
710                    but we may be in disconnected mode and can't initialize correctly.
711                    Do what the previous code did and just return without initialization,
712                    once we go online we'll re-initialize.
713                 */
714                 DEBUG(5, ("winbindd_dual_init_connection: %s returning without initialization "
715                         "online = %d\n", domain->name, (int)domain->online ));
716         }
717
718         fstrcpy(state->response->data.domain_info.name, domain->name);
719         fstrcpy(state->response->data.domain_info.alt_name, domain->alt_name);
720         sid_to_fstring(state->response->data.domain_info.sid, &domain->sid);
721
722         state->response->data.domain_info.native_mode
723                 = domain->native_mode;
724         state->response->data.domain_info.active_directory
725                 = domain->active_directory;
726         state->response->data.domain_info.primary
727                 = domain->primary;
728
729         return WINBINDD_OK;
730 }
731
732 static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
733                                        void *private_data,
734                                        uint32_t msg_type,
735                                        struct server_id server_id,
736                                        DATA_BLOB *data)
737 {
738         TALLOC_CTX *frame = talloc_stackframe();
739         struct lsa_TrustDomainInfoInfoEx info;
740         enum ndr_err_code ndr_err;
741         struct winbindd_domain *d = NULL;
742         uint32_t trust_flags = 0;
743         NTSTATUS status;
744
745         DEBUG(5, ("wb_imsg_new_trusted_domain\n"));
746
747         if (data == NULL) {
748                 TALLOC_FREE(frame);
749                 return;
750         }
751
752         ndr_err = ndr_pull_struct_blob_all(data, frame, &info,
753                         (ndr_pull_flags_fn_t)ndr_pull_lsa_TrustDomainInfoInfoEx);
754         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
755                 TALLOC_FREE(frame);
756                 return;
757         }
758
759         d = find_domain_from_name_noinit(info.netbios_name.string);
760         if (d != NULL) {
761                 TALLOC_FREE(frame);
762                 return;
763         }
764
765         if (info.trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
766                 trust_flags |= NETR_TRUST_FLAG_INBOUND;
767         }
768         if (info.trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
769                 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
770         }
771         if (info.trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
772                 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
773         }
774
775         status = add_trusted_domain(info.netbios_name.string,
776                                     info.domain_name.string,
777                                     info.sid,
778                                     info.trust_type,
779                                     trust_flags,
780                                     info.trust_attributes,
781                                     &d);
782         if (!NT_STATUS_IS_OK(status) &&
783             !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
784         {
785                 DBG_NOTICE("add_trusted_domain returned %s\n",
786                            nt_errstr(status));
787                 TALLOC_FREE(frame);
788                 return;
789         }
790         TALLOC_FREE(frame);
791 }
792
793 /*
794  * We did not get the secret when we queried secrets.tdb, so read it
795  * from secrets.tdb and re-sync the databases
796  */
797 static bool migrate_secrets_tdb_to_ldb(struct winbindd_domain *domain)
798 {
799         bool ok;
800         struct cli_credentials *creds;
801         NTSTATUS can_migrate = pdb_get_trust_credentials(domain->name,
802                                                          NULL, domain, &creds);
803         if (!NT_STATUS_IS_OK(can_migrate)) {
804                 DEBUG(0, ("Failed to fetch our own, local AD domain join "
805                         "password for winbindd's internal use, both from "
806                         "secrets.tdb and secrets.ldb: %s\n",
807                         nt_errstr(can_migrate)));
808                 return false;
809         }
810
811         /*
812          * NOTE: It is very unlikely we end up here if there is an
813          * oldpass, because a new password is created at
814          * classicupgrade, so this is not a concern.
815          */
816         ok = secrets_store_machine_pw_sync(cli_credentials_get_password(creds),
817                    NULL /* oldpass */,
818                    cli_credentials_get_domain(creds),
819                    cli_credentials_get_realm(creds),
820                    cli_credentials_get_salt_principal(creds),
821                    0, /* Supported enc types, unused */
822                    &domain->sid,
823                    cli_credentials_get_password_last_changed_time(creds),
824                    cli_credentials_get_secure_channel_type(creds),
825                    false /* do_delete: Do not delete */);
826         TALLOC_FREE(creds);
827         if (ok == false) {
828                 DEBUG(0, ("Failed to write our our own, "
829                           "local AD domain join password for "
830                           "winbindd's internal use into secrets.tdb\n"));
831                 return false;
832         }
833         return true;
834 }
835
836 /* Look up global info for the winbind daemon */
837 bool init_domain_list(void)
838 {
839         int role = lp_server_role();
840         struct pdb_domain_info *pdb_domain_info = NULL;
841         struct winbindd_domain *domain =  NULL;
842         NTSTATUS status;
843
844         /* Free existing list */
845         free_domain_list();
846
847         /* BUILTIN domain */
848
849         status = add_trusted_domain("BUILTIN",
850                                     NULL,
851                                     &global_sid_Builtin,
852                                     LSA_TRUST_TYPE_DOWNLEVEL,
853                                     0, /* trust_flags */
854                                     0, /* trust_attribs */
855                                     &domain);
856         if (!NT_STATUS_IS_OK(status)) {
857                 DBG_ERR("add_trusted_domain BUILTIN returned %s\n",
858                         nt_errstr(status));
859                 return false;
860         }
861
862         /* Local SAM */
863
864         /*
865          * In case the passdb backend is passdb_dsdb the domain SID comes from
866          * dsdb, not from secrets.tdb. As we use the domain SID in various
867          * places, we must ensure the domain SID is migrated from dsdb to
868          * secrets.tdb before get_global_sam_sid() is called the first time.
869          *
870          * The migration is done as part of the passdb_dsdb initialisation,
871          * calling pdb_get_domain_info() triggers it.
872          */
873         pdb_domain_info = pdb_get_domain_info(talloc_tos());
874
875         if ( role == ROLE_ACTIVE_DIRECTORY_DC ) {
876                 uint32_t trust_flags;
877                 bool is_root;
878                 enum netr_SchannelType sec_chan_type;
879                 const char *account_name;
880                 struct samr_Password current_nt_hash;
881                 bool ok;
882
883                 if (pdb_domain_info == NULL) {
884                         DEBUG(0, ("Failed to fetch our own, local AD "
885                                 "domain info from sam.ldb\n"));
886                         return false;
887                 }
888
889                 trust_flags = NETR_TRUST_FLAG_PRIMARY;
890                 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
891                 trust_flags |= NETR_TRUST_FLAG_NATIVE;
892                 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
893
894                 is_root = strequal(pdb_domain_info->dns_domain,
895                                    pdb_domain_info->dns_forest);
896                 if (is_root) {
897                         trust_flags |= NETR_TRUST_FLAG_TREEROOT;
898                 }
899
900                 status = add_trusted_domain(pdb_domain_info->name,
901                                             pdb_domain_info->dns_domain,
902                                             &pdb_domain_info->sid,
903                                             LSA_TRUST_TYPE_UPLEVEL,
904                                             trust_flags,
905                                             LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
906                                             &domain);
907                 TALLOC_FREE(pdb_domain_info);
908                 if (!NT_STATUS_IS_OK(status)) {
909                         DBG_ERR("Failed to add our own, local AD "
910                                 "domain to winbindd's internal list\n");
911                         return false;
912                 }
913
914                 /*
915                  * We need to call this to find out if we are an RODC
916                  */
917                 ok = get_trust_pw_hash(domain->name,
918                                        current_nt_hash.hash,
919                                        &account_name,
920                                        &sec_chan_type);
921                 if (!ok) {
922                         /*
923                          * If get_trust_pw_hash() fails, then try and
924                          * fetch the password from the more recent of
925                          * secrets.{ldb,tdb} using the
926                          * pdb_get_trust_credentials()
927                          */
928                         ok = migrate_secrets_tdb_to_ldb(domain);
929
930                         if (!ok) {
931                                 DEBUG(0, ("Failed to migrate our own, "
932                                           "local AD domain join password for "
933                                           "winbindd's internal use into "
934                                           "secrets.tdb\n"));
935                                 return false;
936                         }
937                         ok = get_trust_pw_hash(domain->name,
938                                                current_nt_hash.hash,
939                                                &account_name,
940                                                &sec_chan_type);
941                         if (!ok) {
942                                 DEBUG(0, ("Failed to find our our own, just "
943                                           "written local AD domain join "
944                                           "password for winbindd's internal "
945                                           "use in secrets.tdb\n"));
946                                 return false;
947                         }
948                 }
949                 if (sec_chan_type == SEC_CHAN_RODC) {
950                         domain->rodc = true;
951                 }
952
953         } else {
954                 uint32_t trust_flags;
955
956                 trust_flags = NETR_TRUST_FLAG_OUTBOUND;
957                 if (role != ROLE_DOMAIN_MEMBER) {
958                         trust_flags |= NETR_TRUST_FLAG_PRIMARY;
959                 }
960
961                 status = add_trusted_domain(get_global_sam_name(),
962                                             NULL,
963                                             get_global_sam_sid(),
964                                             LSA_TRUST_TYPE_DOWNLEVEL,
965                                             trust_flags,
966                                             0, /* trust_attribs */
967                                             &domain);
968                 if (!NT_STATUS_IS_OK(status)) {
969                         DBG_ERR("Failed to add local SAM to "
970                                 "domain to winbindd's internal list\n");
971                         return false;
972                 }
973         }
974         /* Add ourselves as the first entry. */
975
976         if ( role == ROLE_DOMAIN_MEMBER ) {
977                 struct dom_sid our_sid;
978                 uint32_t trust_type;
979
980                 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
981                         DEBUG(0, ("Could not fetch our SID - did we join?\n"));
982                         return False;
983                 }
984
985                 if (lp_realm() != NULL) {
986                         trust_type = LSA_TRUST_TYPE_UPLEVEL;
987                 } else {
988                         trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
989                 }
990
991                 status = add_trusted_domain(lp_workgroup(),
992                                             lp_realm(),
993                                             &our_sid,
994                                             trust_type,
995                                             NETR_TRUST_FLAG_PRIMARY|
996                                             NETR_TRUST_FLAG_OUTBOUND,
997                                             0, /* trust_attribs */
998                                             &domain);
999                 if (!NT_STATUS_IS_OK(status)) {
1000                         DBG_ERR("Failed to add local SAM to "
1001                                 "domain to winbindd's internal list\n");
1002                         return false;
1003                 }
1004                 /* Even in the parent winbindd we'll need to
1005                    talk to the DC, so try and see if we can
1006                    contact it. Theoretically this isn't neccessary
1007                    as the init_dc_connection() in init_child_recv()
1008                    will do this, but we can start detecting the DC
1009                    early here. */
1010                 set_domain_online_request(domain);
1011
1012         }
1013
1014         status = imessaging_register(winbind_imessaging_context(), NULL,
1015                                      MSG_WINBIND_NEW_TRUSTED_DOMAIN,
1016                                      wb_imsg_new_trusted_domain);
1017         if (!NT_STATUS_IS_OK(status)) {
1018                 DEBUG(0, ("imessaging_register(MSG_WINBIND_NEW_TRUSTED_DOMAIN) - %s\n",
1019                           nt_errstr(status)));
1020                 return false;
1021         }
1022
1023         return True;
1024 }
1025
1026 /**
1027  * Given a domain name, return the struct winbindd domain info for it
1028  *
1029  * @note Do *not* pass lp_workgroup() to this function.  domain_list
1030  *       may modify it's value, and free that pointer.  Instead, our local
1031  *       domain may be found by calling find_our_domain().
1032  *       directly.
1033  *
1034  *
1035  * @return The domain structure for the named domain, if it is working.
1036  */
1037
1038 struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
1039 {
1040         struct winbindd_domain *domain;
1041
1042         /* Search through list */
1043
1044         for (domain = domain_list(); domain != NULL; domain = domain->next) {
1045                 if (strequal(domain_name, domain->name)) {
1046                         return domain;
1047                 }
1048                 if (domain->alt_name == NULL) {
1049                         continue;
1050                 }
1051                 if (strequal(domain_name, domain->alt_name)) {
1052                         return domain;
1053                 }
1054         }
1055
1056         /* Not found */
1057
1058         return NULL;
1059 }
1060
1061 struct winbindd_domain *find_domain_from_name(const char *domain_name)
1062 {
1063         struct winbindd_domain *domain;
1064
1065         domain = find_domain_from_name_noinit(domain_name);
1066
1067         if (domain == NULL)
1068                 return NULL;
1069
1070         if (!domain->initialized)
1071                 init_dc_connection(domain, false);
1072
1073         return domain;
1074 }
1075
1076 /* Given a domain sid, return the struct winbindd domain info for it */
1077
1078 struct winbindd_domain *find_domain_from_sid_noinit(const struct dom_sid *sid)
1079 {
1080         struct winbindd_domain *domain;
1081
1082         /* Search through list */
1083
1084         for (domain = domain_list(); domain != NULL; domain = domain->next) {
1085                 if (dom_sid_compare_domain(sid, &domain->sid) == 0)
1086                         return domain;
1087         }
1088
1089         /* Not found */
1090
1091         return NULL;
1092 }
1093
1094 /* Given a domain sid, return the struct winbindd domain info for it */
1095
1096 struct winbindd_domain *find_domain_from_sid(const struct dom_sid *sid)
1097 {
1098         struct winbindd_domain *domain;
1099
1100         domain = find_domain_from_sid_noinit(sid);
1101
1102         if (domain == NULL)
1103                 return NULL;
1104
1105         if (!domain->initialized)
1106                 init_dc_connection(domain, false);
1107
1108         return domain;
1109 }
1110
1111 struct winbindd_domain *find_our_domain(void)
1112 {
1113         struct winbindd_domain *domain;
1114
1115         /* Search through list */
1116
1117         for (domain = domain_list(); domain != NULL; domain = domain->next) {
1118                 if (domain->primary)
1119                         return domain;
1120         }
1121
1122         smb_panic("Could not find our domain");
1123         return NULL;
1124 }
1125
1126 /* Find the appropriate domain to lookup a name or SID */
1127
1128 struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)
1129 {
1130         DBG_DEBUG("SID [%s]\n", sid_string_dbg(sid));
1131
1132         /*
1133          * SIDs in the S-1-22-{1,2} domain and well-known SIDs should be handled
1134          * by our passdb.
1135          */
1136
1137         if ( sid_check_is_in_unix_groups(sid) ||
1138              sid_check_is_unix_groups(sid) ||
1139              sid_check_is_in_unix_users(sid) ||
1140              sid_check_is_unix_users(sid) ||
1141              sid_check_is_wellknown_domain(sid, NULL) ||
1142              sid_check_is_in_wellknown_domain(sid) )
1143         {
1144                 return find_domain_from_sid(get_global_sam_sid());
1145         }
1146
1147         /* A DC can't ask the local smbd for remote SIDs, here winbindd is the
1148          * one to contact the external DC's. On member servers the internal
1149          * domains are different: These are part of the local SAM. */
1150
1151         if (IS_DC || is_internal_domain(sid) || is_in_internal_domain(sid)) {
1152                 DEBUG(10, ("calling find_domain_from_sid\n"));
1153                 return find_domain_from_sid(sid);
1154         }
1155
1156         /* On a member server a query for SID or name can always go to our
1157          * primary DC. */
1158
1159         DEBUG(10, ("calling find_our_domain\n"));
1160         return find_our_domain();
1161 }
1162
1163 struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
1164 {
1165         if ( strequal(domain_name, unix_users_domain_name() ) ||
1166              strequal(domain_name, unix_groups_domain_name() ) )
1167         {
1168                 /*
1169                  * The "Unix User" and "Unix Group" domain our handled by
1170                  * passdb
1171                  */
1172                 return find_domain_from_name_noinit( get_global_sam_name() );
1173         }
1174
1175         if (IS_DC || strequal(domain_name, "BUILTIN") ||
1176             strequal(domain_name, get_global_sam_name()))
1177                 return find_domain_from_name_noinit(domain_name);
1178
1179
1180         return find_our_domain();
1181 }
1182
1183 /* Is this a domain which we may assume no DOMAIN\ prefix? */
1184
1185 static bool assume_domain(const char *domain)
1186 {
1187         /* never assume the domain on a standalone server */
1188
1189         if ( lp_server_role() == ROLE_STANDALONE )
1190                 return False;
1191
1192         /* domain member servers may possibly assume for the domain name */
1193
1194         if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
1195                 if ( !strequal(lp_workgroup(), domain) )
1196                         return False;
1197
1198                 if ( lp_winbind_use_default_domain() )
1199                         return True;
1200         }
1201
1202         /* only left with a domain controller */
1203
1204         if ( strequal(get_global_sam_name(), domain) )  {
1205                 return True;
1206         }
1207
1208         return False;
1209 }
1210
1211 /* Parse a string of the form DOMAIN\user into a domain and a user */
1212
1213 bool parse_domain_user(const char *domuser, fstring domain, fstring user)
1214 {
1215         char *p = strchr(domuser,*lp_winbind_separator());
1216
1217         if ( !p ) {
1218                 fstrcpy(user, domuser);
1219                 p = strchr(domuser, '@');
1220
1221                 if ( assume_domain(lp_workgroup()) && p == NULL) {
1222                         fstrcpy(domain, lp_workgroup());
1223                 } else if (p != NULL) {
1224                         fstrcpy(domain, p + 1);
1225                         user[PTR_DIFF(p, domuser)] = 0;
1226                 } else {
1227                         return False;
1228                 }
1229         } else {
1230                 fstrcpy(user, p+1);
1231                 fstrcpy(domain, domuser);
1232                 domain[PTR_DIFF(p, domuser)] = 0;
1233         }
1234
1235         return strupper_m(domain);
1236 }
1237
1238 bool parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser,
1239                               char **domain, char **user)
1240 {
1241         fstring fstr_domain, fstr_user;
1242         if (!parse_domain_user(domuser, fstr_domain, fstr_user)) {
1243                 return False;
1244         }
1245         *domain = talloc_strdup(mem_ctx, fstr_domain);
1246         *user = talloc_strdup(mem_ctx, fstr_user);
1247         return ((*domain != NULL) && (*user != NULL));
1248 }
1249
1250 /* Ensure an incoming username from NSS is fully qualified. Replace the
1251    incoming fstring with DOMAIN <separator> user. Returns the same
1252    values as parse_domain_user() but also replaces the incoming username.
1253    Used to ensure all names are fully qualified within winbindd.
1254    Used by the NSS protocols of auth, chauthtok, logoff and ccache_ntlm_auth.
1255    The protocol definitions of auth_crap, chng_pswd_auth_crap
1256    really should be changed to use this instead of doing things
1257    by hand. JRA. */
1258
1259 bool canonicalize_username(fstring username_inout, fstring domain, fstring user)
1260 {
1261         if (!parse_domain_user(username_inout, domain, user)) {
1262                 return False;
1263         }
1264         slprintf(username_inout, sizeof(fstring) - 1, "%s%c%s",
1265                  domain, *lp_winbind_separator(),
1266                  user);
1267         return True;
1268 }
1269
1270 /*
1271     Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
1272     'winbind separator' options.
1273     This means:
1274         - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
1275         lp_workgroup()
1276
1277     If we are a PDC or BDC, and this is for our domain, do likewise.
1278
1279     On an AD DC we always fill DOMAIN\\USERNAME.
1280
1281     We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1282 */
1283 void fill_domain_username(fstring name, const char *domain, const char *user, bool can_assume)
1284 {
1285         fstring tmp_user;
1286
1287         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1288                 can_assume = false;
1289         }
1290
1291         fstrcpy(tmp_user, user);
1292         (void)strlower_m(tmp_user);
1293
1294         if (can_assume && assume_domain(domain)) {
1295                 strlcpy(name, tmp_user, sizeof(fstring));
1296         } else {
1297                 slprintf(name, sizeof(fstring) - 1, "%s%c%s",
1298                          domain, *lp_winbind_separator(),
1299                          tmp_user);
1300         }
1301 }
1302
1303 /**
1304  * talloc version of fill_domain_username()
1305  * return NULL on talloc failure.
1306  */
1307 char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
1308                                   const char *domain,
1309                                   const char *user,
1310                                   bool can_assume)
1311 {
1312         char *tmp_user, *name;
1313
1314         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1315                 can_assume = false;
1316         }
1317
1318         tmp_user = talloc_strdup(mem_ctx, user);
1319         if (!strlower_m(tmp_user)) {
1320                 TALLOC_FREE(tmp_user);
1321                 return NULL;
1322         }
1323
1324         if (can_assume && assume_domain(domain)) {
1325                 name = tmp_user;
1326         } else {
1327                 name = talloc_asprintf(mem_ctx, "%s%c%s",
1328                                        domain,
1329                                        *lp_winbind_separator(),
1330                                        tmp_user);
1331                 TALLOC_FREE(tmp_user);
1332         }
1333
1334         return name;
1335 }
1336
1337 /*
1338  * Client list accessor functions
1339  */
1340
1341 static struct winbindd_cli_state *_client_list;
1342 static int _num_clients;
1343
1344 /* Return list of all connected clients */
1345
1346 struct winbindd_cli_state *winbindd_client_list(void)
1347 {
1348         return _client_list;
1349 }
1350
1351 /* Return list-tail of all connected clients */
1352
1353 struct winbindd_cli_state *winbindd_client_list_tail(void)
1354 {
1355         return DLIST_TAIL(_client_list);
1356 }
1357
1358 /* Return previous (read:newer) client in list */
1359
1360 struct winbindd_cli_state *
1361 winbindd_client_list_prev(struct winbindd_cli_state *cli)
1362 {
1363         return DLIST_PREV(cli);
1364 }
1365
1366 /* Add a connection to the list */
1367
1368 void winbindd_add_client(struct winbindd_cli_state *cli)
1369 {
1370         cli->last_access = time(NULL);
1371         DLIST_ADD(_client_list, cli);
1372         _num_clients++;
1373 }
1374
1375 /* Remove a client from the list */
1376
1377 void winbindd_remove_client(struct winbindd_cli_state *cli)
1378 {
1379         DLIST_REMOVE(_client_list, cli);
1380         _num_clients--;
1381 }
1382
1383 /* Move a client to head or list */
1384
1385 void winbindd_promote_client(struct winbindd_cli_state *cli)
1386 {
1387         cli->last_access = time(NULL);
1388         DLIST_PROMOTE(_client_list, cli);
1389 }
1390
1391 /* Return number of open clients */
1392
1393 int winbindd_num_clients(void)
1394 {
1395         return _num_clients;
1396 }
1397
1398 NTSTATUS lookup_usergroups_cached(TALLOC_CTX *mem_ctx,
1399                                   const struct dom_sid *user_sid,
1400                                   uint32_t *p_num_groups, struct dom_sid **user_sids)
1401 {
1402         struct netr_SamInfo3 *info3 = NULL;
1403         NTSTATUS status = NT_STATUS_NO_MEMORY;
1404         uint32_t num_groups = 0;
1405
1406         DEBUG(3,(": lookup_usergroups_cached\n"));
1407
1408         *user_sids = NULL;
1409         *p_num_groups = 0;
1410
1411         info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1412
1413         if (info3 == NULL) {
1414                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1415         }
1416
1417         /*
1418          * Before bug #7843 the "Domain Local" groups were added with a
1419          * lookupuseraliases call, but this isn't done anymore for our domain
1420          * so we need to resolve resource groups here.
1421          *
1422          * When to use Resource Groups:
1423          * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
1424          */
1425         status = sid_array_from_info3(mem_ctx, info3,
1426                                       user_sids,
1427                                       &num_groups,
1428                                       false);
1429
1430         if (!NT_STATUS_IS_OK(status)) {
1431                 TALLOC_FREE(info3);
1432                 return status;
1433         }
1434
1435         TALLOC_FREE(info3);
1436         *p_num_groups = num_groups;
1437         status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1438
1439         DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1440
1441         return status;
1442 }
1443
1444 /*********************************************************************
1445  We use this to remove spaces from user and group names
1446 ********************************************************************/
1447
1448 NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
1449                              const char *domain_name,
1450                              const char *name,
1451                              char **normalized)
1452 {
1453         struct winbindd_domain *domain = NULL;
1454         NTSTATUS nt_status;
1455
1456         if (!name || !normalized) {
1457                 return NT_STATUS_INVALID_PARAMETER;
1458         }
1459
1460         if (!lp_winbind_normalize_names()) {
1461                 return NT_STATUS_PROCEDURE_NOT_FOUND;
1462         }
1463
1464         domain = find_domain_from_name_noinit(domain_name);
1465         if (domain == NULL) {
1466                 DBG_ERR("Failed to find domain '%s'\n", domain_name);
1467                 return NT_STATUS_NO_SUCH_DOMAIN;
1468         }
1469
1470         /* Alias support and whitespace replacement are mutually
1471            exclusive */
1472
1473         nt_status = resolve_username_to_alias(mem_ctx, domain,
1474                                               name, normalized );
1475         if (NT_STATUS_IS_OK(nt_status)) {
1476                 /* special return code to let the caller know we
1477                    mapped to an alias */
1478                 return NT_STATUS_FILE_RENAMED;
1479         }
1480
1481         /* check for an unreachable domain */
1482
1483         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1484                 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1485                          domain->name));
1486                 set_domain_offline(domain);
1487                 return nt_status;
1488         }
1489
1490         /* deal with whitespace */
1491
1492         *normalized = talloc_strdup(mem_ctx, name);
1493         if (!(*normalized)) {
1494                 return NT_STATUS_NO_MEMORY;
1495         }
1496
1497         all_string_sub( *normalized, " ", "_", 0 );
1498
1499         return NT_STATUS_OK;
1500 }
1501
1502 /*********************************************************************
1503  We use this to do the inverse of normalize_name_map()
1504 ********************************************************************/
1505
1506 NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
1507                               char *name,
1508                               char **normalized)
1509 {
1510         NTSTATUS nt_status;
1511         struct winbindd_domain *domain = find_our_domain();
1512
1513         if (!name || !normalized) {
1514                 return NT_STATUS_INVALID_PARAMETER;
1515         }
1516
1517         if (!lp_winbind_normalize_names()) {
1518                 return NT_STATUS_PROCEDURE_NOT_FOUND;
1519         }
1520
1521         /* Alias support and whitespace replacement are mutally
1522            exclusive */
1523
1524         /* When mapping from an alias to a username, we don't know the
1525            domain.  But we only need a domain structure to cache
1526            a successful lookup , so just our own domain structure for
1527            the seqnum. */
1528
1529         nt_status = resolve_alias_to_username(mem_ctx, domain,
1530                                               name, normalized);
1531         if (NT_STATUS_IS_OK(nt_status)) {
1532                 /* Special return code to let the caller know we mapped
1533                    from an alias */
1534                 return NT_STATUS_FILE_RENAMED;
1535         }
1536
1537         /* check for an unreachable domain */
1538
1539         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1540                 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1541                          domain->name));
1542                 set_domain_offline(domain);
1543                 return nt_status;
1544         }
1545
1546         /* deal with whitespace */
1547
1548         *normalized = talloc_strdup(mem_ctx, name);
1549         if (!(*normalized)) {
1550                 return NT_STATUS_NO_MEMORY;
1551         }
1552
1553         all_string_sub(*normalized, "_", " ", 0);
1554
1555         return NT_STATUS_OK;
1556 }
1557
1558 /*********************************************************************
1559  ********************************************************************/
1560
1561 bool winbindd_can_contact_domain(struct winbindd_domain *domain)
1562 {
1563         struct winbindd_tdc_domain *tdc = NULL;
1564         TALLOC_CTX *frame = talloc_stackframe();
1565         bool ret = false;
1566
1567         /* We can contact the domain if it is our primary domain */
1568
1569         if (domain->primary) {
1570                 ret = true;
1571                 goto done;
1572         }
1573
1574         /* Trust the TDC cache and not the winbindd_domain flags */
1575
1576         if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
1577                 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
1578                           domain->name));
1579                 ret = false;
1580                 goto done;
1581         }
1582
1583         /* Can always contact a domain that is in out forest */
1584
1585         if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1586                 ret = true;
1587                 goto done;
1588         }
1589
1590         /*
1591          * On a _member_ server, we cannot contact the domain if it
1592          * is running AD and we have no inbound trust.
1593          */
1594
1595         if (!IS_DC &&
1596              domain->active_directory &&
1597             ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
1598         {
1599                 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
1600                            "and we have no inbound trust.\n", domain->name));
1601                 goto done;
1602         }
1603
1604         /* Assume everything else is ok (probably not true but what
1605            can you do?) */
1606
1607         ret = true;
1608
1609 done:
1610         talloc_destroy(frame);
1611
1612         return ret;
1613 }
1614
1615 /*********************************************************************
1616  ********************************************************************/
1617
1618 bool winbindd_internal_child(struct winbindd_child *child)
1619 {
1620         if ((child == idmap_child()) || (child == locator_child())) {
1621                 return True;
1622         }
1623
1624         return False;
1625 }
1626
1627 #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
1628
1629 /*********************************************************************
1630  ********************************************************************/
1631
1632 static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
1633 {
1634         char *var = NULL;
1635         char addr[INET6_ADDRSTRLEN];
1636         const char *kdc = NULL;
1637         int lvl = 11;
1638
1639         if (!domain || !domain->alt_name || !*domain->alt_name) {
1640                 return;
1641         }
1642
1643         if (domain->initialized && !domain->active_directory) {
1644                 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
1645                         domain->alt_name));
1646                 return;
1647         }
1648
1649         print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
1650         kdc = addr;
1651         if (!*kdc) {
1652                 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
1653                         domain->alt_name));
1654                 kdc = domain->dcname;
1655         }
1656
1657         if (!kdc || !*kdc) {
1658                 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
1659                         domain->alt_name));
1660                 return;
1661         }
1662
1663         if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
1664                                 domain->alt_name) == -1) {
1665                 return;
1666         }
1667
1668         DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
1669                 var, kdc));
1670
1671         setenv(var, kdc, 1);
1672         free(var);
1673 }
1674
1675 /*********************************************************************
1676  ********************************************************************/
1677
1678 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
1679 {
1680         struct winbindd_domain *our_dom = find_our_domain();
1681
1682         winbindd_set_locator_kdc_env(domain);
1683
1684         if (domain != our_dom) {
1685                 winbindd_set_locator_kdc_env(our_dom);
1686         }
1687 }
1688
1689 /*********************************************************************
1690  ********************************************************************/
1691
1692 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
1693 {
1694         char *var = NULL;
1695
1696         if (!domain || !domain->alt_name || !*domain->alt_name) {
1697                 return;
1698         }
1699
1700         if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
1701                                 domain->alt_name) == -1) {
1702                 return;
1703         }
1704
1705         unsetenv(var);
1706         free(var);
1707 }
1708 #else
1709
1710 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
1711 {
1712         return;
1713 }
1714
1715 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
1716 {
1717         return;
1718 }
1719
1720 #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
1721
1722 void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
1723 {
1724         resp->data.auth.nt_status = NT_STATUS_V(result);
1725         fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
1726
1727         /* we might have given a more useful error above */
1728         if (*resp->data.auth.error_string == '\0')
1729                 fstrcpy(resp->data.auth.error_string,
1730                         get_friendly_nt_error_msg(result));
1731         resp->data.auth.pam_error = nt_status_to_pam(result);
1732 }
1733
1734 bool is_domain_offline(const struct winbindd_domain *domain)
1735 {
1736         if (get_global_winbindd_state_offline()) {
1737                 return true;
1738         }
1739         return !domain->online;
1740 }
1741
1742 bool is_domain_online(const struct winbindd_domain *domain)
1743 {
1744         return !is_domain_offline(domain);
1745 }
1746
1747 /**
1748  * Parse an char array into a list of sids.
1749  *
1750  * The input sidstr should consist of 0-terminated strings
1751  * representing sids, separated by newline characters '\n'.
1752  * The list is terminated by an empty string, i.e.
1753  * character '\0' directly following a character '\n'
1754  * (or '\0' right at the start of sidstr).
1755  */
1756 bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
1757                    struct dom_sid **sids, uint32_t *num_sids)
1758 {
1759         const char *p;
1760
1761         p = sidstr;
1762         if (p == NULL)
1763                 return False;
1764
1765         while (p[0] != '\0') {
1766                 struct dom_sid sid;
1767                 const char *q = NULL;
1768
1769                 if (!dom_sid_parse_endp(p, &sid, &q)) {
1770                         DEBUG(1, ("Could not parse sid %s\n", p));
1771                         return false;
1772                 }
1773                 if (q[0] != '\n') {
1774                         DEBUG(1, ("Got invalid sidstr: %s\n", p));
1775                         return false;
1776                 }
1777                 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
1778                                                       num_sids)))
1779                 {
1780                         return False;
1781                 }
1782                 p = q+1;
1783         }
1784         return True;
1785 }
1786
1787 bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
1788                    struct unixid **pxids, uint32_t *pnum_xids)
1789 {
1790         const char *p;
1791         struct unixid *xids = NULL;
1792         uint32_t num_xids = 0;
1793
1794         p = xidstr;
1795         if (p == NULL) {
1796                 return false;
1797         }
1798
1799         while (p[0] != '\0') {
1800                 struct unixid *tmp;
1801                 struct unixid xid;
1802                 unsigned long long id;
1803                 char *endp;
1804
1805                 switch (p[0]) {
1806                 case 'U':
1807                         xid = (struct unixid) { .type = ID_TYPE_UID };
1808                         break;
1809                 case 'G':
1810                         xid = (struct unixid) { .type = ID_TYPE_GID };
1811                         break;
1812                 default:
1813                         return false;
1814                 }
1815
1816                 p += 1;
1817
1818                 id = strtoull(p, &endp, 10);
1819                 if ((id == ULLONG_MAX) && (errno == ERANGE)) {
1820                         goto fail;
1821                 }
1822                 if (*endp != '\n') {
1823                         goto fail;
1824                 }
1825                 p = endp+1;
1826
1827                 xid.id = id;
1828                 if ((unsigned long long)xid.id != id) {
1829                         goto fail;
1830                 }
1831
1832                 tmp = talloc_realloc(mem_ctx, xids, struct unixid, num_xids+1);
1833                 if (tmp == NULL) {
1834                         return 0;
1835                 }
1836                 xids = tmp;
1837
1838                 xids[num_xids] = xid;
1839                 num_xids += 1;
1840         }
1841
1842         *pxids = xids;
1843         *pnum_xids = num_xids;
1844         return true;
1845
1846 fail:
1847         TALLOC_FREE(xids);
1848         return false;
1849 }