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