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