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