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