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