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 26391 : struct winbindd_domain *domain_list(void)
60 : {
61 : /* Initialise list */
62 :
63 26391 : if ((!_domain_list) && (!init_domain_list())) {
64 0 : smb_panic("Init_domain_list failed");
65 : }
66 :
67 26391 : return _domain_list;
68 : }
69 :
70 : /* Free all entries in the trusted domain list */
71 :
72 68 : static void free_domain_list(void)
73 : {
74 68 : struct winbindd_domain *domain = _domain_list;
75 :
76 123 : 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 68 : }
84 :
85 : /**
86 : * Iterator for winbindd's domain list.
87 : * To be used (e.g.) in tevent based loops.
88 : */
89 746 : struct winbindd_domain *wb_next_domain(struct winbindd_domain *domain)
90 : {
91 746 : if (domain == NULL) {
92 152 : domain = domain_list();
93 : } else {
94 594 : domain = domain->next;
95 : }
96 :
97 1344 : if ((domain != NULL) &&
98 1196 : (lp_server_role() != ROLE_ACTIVE_DIRECTORY_DC) &&
99 598 : sid_check_is_our_sam(&domain->sid))
100 : {
101 150 : domain = domain->next;
102 : }
103 :
104 746 : return domain;
105 : }
106 :
107 446 : static bool is_internal_domain(const struct dom_sid *sid)
108 : {
109 446 : if (sid == NULL)
110 0 : return False;
111 :
112 446 : 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 1965 : 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 1965 : struct winbindd_domain *domain = NULL;
130 1965 : int role = lp_server_role();
131 : struct dom_sid_buf buf;
132 :
133 1965 : 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 1965 : 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 17055 : for (domain = _domain_list; domain; domain = domain->next) {
147 16832 : if (strequal(domain_name, domain->name)) {
148 1742 : break;
149 : }
150 : }
151 :
152 1965 : if (domain != NULL) {
153 1742 : struct winbindd_domain *check_domain = NULL;
154 :
155 28060 : for (check_domain = _domain_list;
156 2626 : check_domain != NULL;
157 27202 : check_domain = check_domain->next)
158 : {
159 27202 : if (check_domain == domain) {
160 1742 : continue;
161 : }
162 :
163 25460 : if (dom_sid_equal(&check_domain->sid, sid)) {
164 0 : break;
165 : }
166 : }
167 :
168 1742 : 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 1965 : if ((domain != NULL) && (dns_name != NULL)) {
179 1627 : struct winbindd_domain *check_domain = NULL;
180 :
181 27701 : for (check_domain = _domain_list;
182 2386 : check_domain != NULL;
183 26833 : check_domain = check_domain->next)
184 : {
185 26833 : if (check_domain == domain) {
186 1627 : continue;
187 : }
188 :
189 25206 : if (strequal(check_domain->alt_name, dns_name)) {
190 0 : break;
191 : }
192 : }
193 :
194 1627 : 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 1965 : if (domain != NULL) {
204 1742 : *_d = domain;
205 1742 : return NT_STATUS_OK;
206 : }
207 :
208 : /* Create new domain entry */
209 223 : domain = talloc_zero(NULL, struct winbindd_domain);
210 223 : if (domain == NULL) {
211 0 : return NT_STATUS_NO_MEMORY;
212 : }
213 :
214 223 : domain->children = talloc_zero_array(domain,
215 : struct winbindd_child,
216 : lp_winbind_max_domain_connections());
217 223 : if (domain->children == NULL) {
218 0 : TALLOC_FREE(domain);
219 0 : return NT_STATUS_NO_MEMORY;
220 : }
221 :
222 223 : domain->queue = tevent_queue_create(domain, "winbind_domain");
223 223 : if (domain->queue == NULL) {
224 0 : TALLOC_FREE(domain);
225 0 : return NT_STATUS_NO_MEMORY;
226 : }
227 :
228 223 : domain->binding_handle = wbint_binding_handle(domain, domain, NULL);
229 223 : if (domain->binding_handle == NULL) {
230 0 : TALLOC_FREE(domain);
231 0 : return NT_STATUS_NO_MEMORY;
232 : }
233 :
234 223 : domain->name = talloc_strdup(domain, domain_name);
235 223 : if (domain->name == NULL) {
236 0 : TALLOC_FREE(domain);
237 0 : return NT_STATUS_NO_MEMORY;
238 : }
239 :
240 223 : if (dns_name != NULL) {
241 122 : domain->alt_name = talloc_strdup(domain, dns_name);
242 122 : if (domain->alt_name == NULL) {
243 0 : TALLOC_FREE(domain);
244 0 : return NT_STATUS_NO_MEMORY;
245 : }
246 : }
247 :
248 223 : domain->backend = NULL;
249 223 : domain->internal = is_internal_domain(sid);
250 223 : domain->secure_channel_type = secure_channel_type;
251 223 : domain->sequence_number = DOM_SEQUENCE_NONE;
252 223 : domain->last_seq_check = 0;
253 223 : domain->initialized = false;
254 223 : domain->online = is_internal_domain(sid);
255 223 : domain->domain_flags = trust_flags;
256 223 : domain->domain_type = trust_type;
257 223 : domain->domain_trust_attribs = trust_attribs;
258 223 : domain->secure_channel_type = secure_channel_type;
259 223 : domain->routing_domain = routing_domain;
260 223 : sid_copy(&domain->sid, sid);
261 :
262 : /* Is this our primary domain ? */
263 223 : if (role == ROLE_DOMAIN_MEMBER) {
264 101 : domain->primary = strequal(domain_name, lp_workgroup());
265 : } else {
266 122 : domain->primary = strequal(domain_name, get_global_sam_name());
267 : }
268 :
269 223 : if (domain->primary) {
270 68 : if (role == ROLE_ACTIVE_DIRECTORY_DC) {
271 35 : domain->active_directory = true;
272 : }
273 68 : if (lp_security() == SEC_ADS) {
274 30 : domain->active_directory = true;
275 : }
276 155 : } else if (!domain->internal) {
277 56 : if (domain->domain_type == LSA_TRUST_TYPE_UPLEVEL) {
278 24 : domain->active_directory = true;
279 : }
280 : }
281 :
282 223 : domain->can_do_ncacn_ip_tcp = domain->active_directory;
283 :
284 : /* Link to domain list */
285 223 : DLIST_ADD_END(_domain_list, domain);
286 :
287 223 : wcache_tdc_add_domain( domain );
288 :
289 223 : setup_domain_child(domain);
290 :
291 223 : DBG_NOTICE("Added domain [%s] [%s] [%s]\n",
292 : domain->name, domain->alt_name,
293 : dom_sid_str_buf(&domain->sid, &buf));
294 :
295 223 : *_d = domain;
296 223 : 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 1105 : bool add_trusted_domain_from_auth(uint16_t validation_level,
313 : struct info3_text *info3,
314 : struct info6_text *info6)
315 : {
316 1105 : struct winbindd_domain *domain = NULL;
317 : struct dom_sid domain_sid;
318 1105 : const char *dns_domainname = NULL;
319 : NTSTATUS status;
320 : bool ok;
321 :
322 : /*
323 : * We got a successfull 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 1105 : if (IS_DC) {
330 66 : return true;
331 : }
332 :
333 1039 : ok = dom_sid_parse(info3->dom_sid, &domain_sid);
334 1039 : if (!ok) {
335 0 : DBG_NOTICE("dom_sid_parse [%s] failed\n", info3->dom_sid);
336 0 : return false;
337 : }
338 :
339 1039 : if (validation_level == 6) {
340 1007 : if (!strequal(info6->dns_domainname, "")) {
341 924 : dns_domainname = info6->dns_domainname;
342 : }
343 : }
344 :
345 1039 : 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 1039 : 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 1039 : 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 : struct trustdom_state *state;
390 : struct tevent_req *req;
391 0 : const char *client_name = NULL;
392 : 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 : NTSTATUS status, result;
425 : 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 : size_t i;
523 : 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 : size_t i;
600 : 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 the 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 use 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 901 : void winbindd_ping_offline_domains(struct tevent_context *ev,
706 : struct tevent_timer *te,
707 : struct timeval now,
708 : void *private_data)
709 : {
710 901 : struct winbindd_domain *domain = NULL;
711 :
712 901 : TALLOC_FREE(te);
713 :
714 4922 : for (domain = domain_list(); domain != NULL; domain = domain->next) {
715 4025 : DBG_DEBUG("Domain %s is %s\n",
716 : domain->name,
717 : domain->online ? "online" : "offline");
718 :
719 4025 : if (get_global_winbindd_state_offline()) {
720 4 : DBG_DEBUG("We are globally offline, do nothing.\n");
721 4 : break;
722 : }
723 :
724 5817 : if (domain->online ||
725 3644 : domain->check_online_event != NULL ||
726 1848 : domain->secure_channel_type == SEC_CHAN_NULL) {
727 2658 : continue;
728 : }
729 :
730 1363 : winbindd_flush_negative_conn_cache(domain);
731 :
732 1363 : domain->check_online_event =
733 1363 : dcerpc_wbint_PingDc_send(domain,
734 : ev,
735 : dom_child_handle(domain),
736 : &domain->ping_dcname);
737 1363 : if (domain->check_online_event == NULL) {
738 0 : DBG_WARNING("Failed to schedule ping, no-memory\n");
739 0 : continue;
740 : }
741 :
742 1363 : tevent_req_set_callback(domain->check_online_event,
743 : wbd_ping_dc_done, domain);
744 : }
745 :
746 901 : 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 901 : if (te == NULL) {
753 0 : DBG_ERR("Failed to schedule winbindd_ping_offline_domains()\n");
754 : }
755 :
756 901 : return;
757 : }
758 :
759 1362 : static void wbd_ping_dc_done(struct tevent_req *subreq)
760 : {
761 1347 : struct winbindd_domain *domain =
762 1362 : tevent_req_callback_data(subreq,
763 : struct winbindd_domain);
764 : NTSTATUS status, result;
765 :
766 1362 : SMB_ASSERT(subreq == domain->check_online_event);
767 1362 : domain->check_online_event = NULL;
768 :
769 1362 : status = dcerpc_wbint_PingDc_recv(subreq, domain, &result);
770 1362 : TALLOC_FREE(subreq);
771 1362 : if (any_nt_status_not_ok(status, result, &status)) {
772 1339 : DBG_WARNING("dcerpc_wbint_PingDc_recv failed for domain: "
773 : "%s - %s\n",
774 : domain->name,
775 : nt_errstr(status));
776 1339 : 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 163 : 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 : bool ok;
799 :
800 163 : if (num_fds != 0) {
801 0 : DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
802 0 : return;
803 : }
804 :
805 163 : DBG_NOTICE("Rescanning trusted domains\n");
806 :
807 163 : ok = add_trusted_domains_dc();
808 163 : 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 1 : static bool migrate_secrets_tdb_to_ldb(struct winbindd_domain *domain)
818 : {
819 : bool ok;
820 : struct cli_credentials *creds;
821 1 : NTSTATUS can_migrate = pdb_get_trust_credentials(domain->name,
822 : NULL, domain, &creds);
823 1 : 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 3 : 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 1 : &domain->sid,
843 1 : cli_credentials_get_password_last_changed_time(creds),
844 1 : cli_credentials_get_secure_channel_type(creds),
845 : false /* do_delete: Do not delete */);
846 1 : TALLOC_FREE(creds);
847 1 : if (ok == false) {
848 0 : DEBUG(0, ("Failed to write our our own, "
849 : "local AD domain join password for "
850 : "winbindd's internal use into secrets.tdb\n"));
851 0 : return false;
852 : }
853 1 : return true;
854 : }
855 :
856 200 : static bool add_trusted_domains_dc(void)
857 : {
858 200 : struct winbindd_domain *domain = NULL;
859 200 : struct pdb_trusted_domain **domains = NULL;
860 200 : uint32_t num_domains = 0;
861 : uint32_t i;
862 : NTSTATUS status;
863 :
864 200 : if (!(pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX)) {
865 2 : struct trustdom_info **ti = NULL;
866 :
867 2 : status = pdb_enum_trusteddoms(talloc_tos(), &num_domains, &ti);
868 2 : 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 2 : 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 2 : return true;
892 : }
893 :
894 198 : status = pdb_enum_trusted_domains(talloc_tos(), &num_domains, &domains);
895 198 : 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 957 : for (i = 0; i < num_domains; i++) {
902 759 : enum netr_SchannelType sec_chan_type = SEC_CHAN_DOMAIN;
903 759 : uint32_t trust_flags = 0;
904 :
905 759 : if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
906 291 : sec_chan_type = SEC_CHAN_DNS_DOMAIN;
907 : }
908 :
909 759 : if (!(domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
910 182 : sec_chan_type = SEC_CHAN_NULL;
911 : }
912 :
913 759 : if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
914 367 : trust_flags |= NETR_TRUST_FLAG_INBOUND;
915 : }
916 759 : if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
917 577 : trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
918 : }
919 759 : if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
920 0 : trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
921 : }
922 :
923 759 : 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 2277 : status = add_trusted_domain(domains[i]->netbios_name,
935 759 : domains[i]->domain_name,
936 759 : &domains[i]->security_identifier,
937 759 : domains[i]->trust_type,
938 : trust_flags,
939 759 : domains[i]->trust_attributes,
940 : sec_chan_type,
941 : NULL,
942 : &domain);
943 759 : 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 759 : if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
950 291 : domain->active_directory = true;
951 : }
952 759 : domain->domain_type = domains[i]->trust_type;
953 759 : domain->domain_trust_attribs = domains[i]->trust_attributes;
954 : }
955 :
956 957 : for (i = 0; i < num_domains; i++) {
957 : struct ForestTrustInfo fti;
958 : uint32_t fi;
959 : enum ndr_err_code ndr_err;
960 759 : struct winbindd_domain *routing_domain = NULL;
961 :
962 759 : if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
963 1185 : continue;
964 : }
965 :
966 291 : if (!(domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
967 242 : continue;
968 : }
969 :
970 49 : if (domains[i]->trust_forest_trust_info.length == 0) {
971 7 : continue;
972 : }
973 :
974 42 : routing_domain = find_domain_from_name_noinit(
975 42 : domains[i]->netbios_name);
976 42 : 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 84 : ndr_err = ndr_pull_struct_blob_all(
983 42 : &domains[i]->trust_forest_trust_info,
984 : talloc_tos(), &fti,
985 : (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
986 42 : 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 290 : for (fi = 0; fi < fti.count; fi++) {
994 248 : struct ForestTrustInfoRecord *rec =
995 248 : &fti.records[fi].record;
996 248 : struct ForestTrustDataDomainInfo *drec = NULL;
997 :
998 248 : if (rec->type != FOREST_TRUST_DOMAIN_INFO) {
999 206 : continue;
1000 : }
1001 42 : drec = &rec->data.info;
1002 :
1003 42 : if (rec->flags & LSA_NB_DISABLED_MASK) {
1004 14 : continue;
1005 : }
1006 :
1007 28 : if (rec->flags & LSA_SID_DISABLED_MASK) {
1008 2 : continue;
1009 : }
1010 :
1011 : /*
1012 : * TODO:
1013 : * also try to find a matching
1014 : * LSA_TLN_DISABLED_MASK ???
1015 : */
1016 :
1017 26 : domain = find_domain_from_name_noinit(drec->netbios_name.string);
1018 26 : if (domain != NULL) {
1019 26 : 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 198 : return true;
1043 : }
1044 :
1045 :
1046 : /* Look up global info for the winbind daemon */
1047 68 : bool init_domain_list(void)
1048 : {
1049 68 : int role = lp_server_role();
1050 68 : struct pdb_domain_info *pdb_domain_info = NULL;
1051 68 : struct winbindd_domain *domain = NULL;
1052 : NTSTATUS status;
1053 : bool ok;
1054 :
1055 : /* Free existing list */
1056 68 : free_domain_list();
1057 :
1058 : /* BUILTIN domain */
1059 :
1060 68 : 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 68 : 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 68 : pdb_domain_info = pdb_get_domain_info(talloc_tos());
1087 :
1088 68 : if ( role == ROLE_ACTIVE_DIRECTORY_DC ) {
1089 : uint32_t trust_flags;
1090 : bool is_root;
1091 : enum netr_SchannelType sec_chan_type;
1092 : const char *account_name;
1093 : struct samr_Password current_nt_hash;
1094 :
1095 35 : 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 35 : trust_flags = NETR_TRUST_FLAG_PRIMARY;
1102 35 : trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1103 35 : trust_flags |= NETR_TRUST_FLAG_NATIVE;
1104 35 : trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1105 :
1106 35 : is_root = strequal(pdb_domain_info->dns_domain,
1107 35 : pdb_domain_info->dns_forest);
1108 35 : if (is_root) {
1109 35 : trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1110 : }
1111 :
1112 35 : status = add_trusted_domain(pdb_domain_info->name,
1113 35 : pdb_domain_info->dns_domain,
1114 35 : &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 35 : TALLOC_FREE(pdb_domain_info);
1122 35 : 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 35 : ok = get_trust_pw_hash(domain->name,
1132 : current_nt_hash.hash,
1133 : &account_name,
1134 : &sec_chan_type);
1135 35 : 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 1 : ok = migrate_secrets_tdb_to_ldb(domain);
1143 :
1144 1 : 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 1 : ok = get_trust_pw_hash(domain->name,
1152 : current_nt_hash.hash,
1153 : &account_name,
1154 : &sec_chan_type);
1155 1 : if (!ok) {
1156 0 : DEBUG(0, ("Failed to find our 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 35 : domain->secure_channel_type = sec_chan_type;
1165 35 : if (sec_chan_type == SEC_CHAN_RODC) {
1166 1 : domain->rodc = true;
1167 : }
1168 :
1169 : } else {
1170 : uint32_t trust_flags;
1171 : enum netr_SchannelType secure_channel_type;
1172 :
1173 33 : trust_flags = NETR_TRUST_FLAG_OUTBOUND;
1174 33 : if (role != ROLE_DOMAIN_MEMBER) {
1175 2 : trust_flags |= NETR_TRUST_FLAG_PRIMARY;
1176 : }
1177 :
1178 33 : if (role > ROLE_DOMAIN_MEMBER) {
1179 2 : secure_channel_type = SEC_CHAN_BDC;
1180 : } else {
1181 31 : secure_channel_type = SEC_CHAN_LOCAL;
1182 : }
1183 :
1184 33 : 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 33 : status = add_trusted_domain(get_global_sam_name(),
1206 : NULL,
1207 33 : 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 33 : 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 68 : if (IS_DC) {
1223 37 : ok = add_trusted_domains_dc();
1224 37 : if (!ok) {
1225 0 : DBG_ERR("init_domain_list_dc failed\n");
1226 0 : return false;
1227 : }
1228 : }
1229 :
1230 68 : if ( role == ROLE_DOMAIN_MEMBER ) {
1231 : struct dom_sid our_sid;
1232 : 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 68 : status = imessaging_register(winbind_imessaging_context(), NULL,
1263 : MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1264 : wb_imsg_new_trusted_domain);
1265 68 : 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 68 : 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 6706 : struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
1286 : {
1287 : struct winbindd_domain *domain;
1288 :
1289 : /* Search through list */
1290 :
1291 39459 : for (domain = domain_list(); domain != NULL; domain = domain->next) {
1292 39317 : if (strequal(domain_name, domain->name)) {
1293 6380 : return domain;
1294 : }
1295 32937 : if (domain->alt_name == NULL) {
1296 7337 : continue;
1297 : }
1298 25600 : if (strequal(domain_name, domain->alt_name)) {
1299 184 : return domain;
1300 : }
1301 : }
1302 :
1303 : /* Not found */
1304 :
1305 142 : 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 80 : struct winbindd_domain *find_trust_from_name_noinit(const char *domain_name)
1315 : {
1316 80 : struct winbindd_domain *domain = NULL;
1317 :
1318 80 : domain = find_domain_from_name_noinit(domain_name);
1319 80 : if (domain == NULL) {
1320 2 : return NULL;
1321 : }
1322 :
1323 78 : if (domain->secure_channel_type != SEC_CHAN_NULL) {
1324 78 : return domain;
1325 : }
1326 :
1327 0 : return NULL;
1328 : }
1329 :
1330 45 : struct winbindd_domain *find_domain_from_name(const char *domain_name)
1331 : {
1332 : struct winbindd_domain *domain;
1333 :
1334 45 : domain = find_domain_from_name_noinit(domain_name);
1335 :
1336 45 : if (domain == NULL)
1337 0 : return NULL;
1338 :
1339 45 : if (!domain->initialized)
1340 1 : init_dc_connection(domain, false);
1341 :
1342 45 : return domain;
1343 : }
1344 :
1345 : /* Given a domain sid, return the struct winbindd domain info for it */
1346 :
1347 3843 : struct winbindd_domain *find_domain_from_sid_noinit(const struct dom_sid *sid)
1348 : {
1349 : struct winbindd_domain *domain;
1350 :
1351 : /* Search through list */
1352 :
1353 9749 : for (domain = domain_list(); domain != NULL; domain = domain->next) {
1354 9008 : if (dom_sid_compare_domain(sid, &domain->sid) == 0)
1355 3102 : return domain;
1356 : }
1357 :
1358 : /* Not found */
1359 :
1360 741 : 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 2532 : struct winbindd_domain *find_domain_from_sid(const struct dom_sid *sid)
1388 : {
1389 : struct winbindd_domain *domain;
1390 :
1391 2532 : domain = find_domain_from_sid_noinit(sid);
1392 :
1393 2532 : if (domain == NULL)
1394 0 : return NULL;
1395 :
1396 2532 : if (!domain->initialized)
1397 5 : init_dc_connection(domain, false);
1398 :
1399 2532 : return domain;
1400 : }
1401 :
1402 14733 : struct winbindd_domain *find_our_domain(void)
1403 : {
1404 : struct winbindd_domain *domain;
1405 :
1406 : /* Search through list */
1407 :
1408 41221 : for (domain = domain_list(); domain != NULL; domain = domain->next) {
1409 41221 : if (domain->primary)
1410 14733 : return domain;
1411 : }
1412 :
1413 0 : smb_panic("Could not find our domain");
1414 : return NULL;
1415 : }
1416 :
1417 1039 : struct winbindd_domain *find_default_route_domain(void)
1418 : {
1419 1039 : if (!IS_DC) {
1420 1039 : 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 8234 : struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)
1429 : {
1430 : struct dom_sid_buf buf;
1431 :
1432 8234 : 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 16468 : if ( sid_check_is_in_unix_groups(sid) ||
1440 16468 : sid_check_is_unix_groups(sid) ||
1441 16438 : sid_check_is_in_unix_users(sid) ||
1442 16408 : sid_check_is_unix_users(sid) ||
1443 16408 : sid_check_is_our_sam(sid) ||
1444 8204 : sid_check_is_in_our_sam(sid) )
1445 : {
1446 2413 : return find_domain_from_sid(get_global_sam_sid());
1447 : }
1448 :
1449 11634 : if ( sid_check_is_builtin(sid) ||
1450 11626 : sid_check_is_in_builtin(sid) ||
1451 11626 : sid_check_is_wellknown_domain(sid, NULL) ||
1452 5813 : sid_check_is_in_wellknown_domain(sid) )
1453 : {
1454 36 : return find_domain_from_sid(&global_sid_Builtin);
1455 : }
1456 :
1457 5785 : if (IS_DC) {
1458 60 : struct winbindd_domain *domain = NULL;
1459 :
1460 60 : domain = find_domain_from_sid_noinit(sid);
1461 60 : if (domain == NULL) {
1462 0 : return NULL;
1463 : }
1464 :
1465 60 : if (domain->secure_channel_type != SEC_CHAN_NULL) {
1466 60 : 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 5725 : DEBUG(10, ("calling find_our_domain\n"));
1476 5725 : return find_our_domain();
1477 : }
1478 :
1479 5852 : struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
1480 : {
1481 : bool predefined;
1482 :
1483 11620 : if ( strequal(domain_name, unix_users_domain_name() ) ||
1484 5768 : strequal(domain_name, unix_groups_domain_name() ) )
1485 : {
1486 : /*
1487 : * The "Unix User" and "Unix Group" domain are handled by
1488 : * passdb
1489 : */
1490 124 : return find_domain_from_name_noinit( get_global_sam_name() );
1491 : }
1492 :
1493 11456 : if (strequal(domain_name, "BUILTIN") ||
1494 5728 : strequal(domain_name, get_global_sam_name())) {
1495 3067 : return find_domain_from_name_noinit(domain_name);
1496 : }
1497 :
1498 2661 : predefined = dom_sid_lookup_is_predefined_domain(domain_name);
1499 2661 : if (predefined) {
1500 56 : return find_domain_from_name_noinit(builtin_domain_name());
1501 : }
1502 :
1503 2605 : if (IS_DC) {
1504 107 : struct winbindd_domain *domain = NULL;
1505 :
1506 107 : domain = find_domain_from_name_noinit(domain_name);
1507 107 : if (domain == NULL) {
1508 5 : return NULL;
1509 : }
1510 :
1511 102 : if (domain->secure_channel_type != SEC_CHAN_NULL) {
1512 102 : return domain;
1513 : }
1514 :
1515 0 : return domain->routing_domain;
1516 : }
1517 :
1518 2498 : return find_our_domain();
1519 : }
1520 :
1521 : /* Is this a domain which we may assume no DOMAIN\ prefix? */
1522 :
1523 6606 : static bool assume_domain(const char *domain)
1524 : {
1525 : /* never assume the domain on a standalone server */
1526 :
1527 6606 : if ( lp_server_role() == ROLE_STANDALONE )
1528 0 : return False;
1529 :
1530 : /* domain member servers may possibly assume for the domain name */
1531 :
1532 6606 : if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
1533 5791 : if ( !strequal(lp_workgroup(), domain) )
1534 258 : return False;
1535 :
1536 5533 : if ( lp_winbind_use_default_domain() )
1537 5 : return True;
1538 : }
1539 :
1540 : /* only left with a domain controller */
1541 :
1542 6343 : if ( strequal(get_global_sam_name(), domain) ) {
1543 815 : return True;
1544 : }
1545 :
1546 5528 : return False;
1547 : }
1548 :
1549 : /* Parse a DOMAIN\user or UPN string into a domain, namespace and a user */
1550 4795 : bool parse_domain_user(const char *domuser,
1551 : fstring namespace,
1552 : fstring domain,
1553 : fstring user)
1554 : {
1555 4795 : char *p = NULL;
1556 :
1557 4795 : if (strlen(domuser) == 0) {
1558 0 : return false;
1559 : }
1560 :
1561 4795 : p = strchr(domuser, *lp_winbind_separator());
1562 4795 : if (p != NULL) {
1563 3907 : fstrcpy(user, p + 1);
1564 3907 : fstrcpy(domain, domuser);
1565 3907 : domain[PTR_DIFF(p, domuser)] = '\0';
1566 3907 : fstrcpy(namespace, domain);
1567 : } else {
1568 888 : fstrcpy(user, domuser);
1569 :
1570 888 : domain[0] = '\0';
1571 888 : namespace[0] = '\0';
1572 888 : p = strchr(domuser, '@');
1573 888 : if (p != NULL) {
1574 : /* upn */
1575 16 : fstrcpy(namespace, p + 1);
1576 872 : } else if (assume_domain(lp_workgroup())) {
1577 816 : fstrcpy(domain, lp_workgroup());
1578 816 : fstrcpy(namespace, domain);
1579 : } else {
1580 56 : fstrcpy(namespace, lp_netbios_name());
1581 : }
1582 : }
1583 :
1584 4795 : return strupper_m(domain);
1585 : }
1586 :
1587 : /* Ensure an incoming username from NSS is fully qualified. Replace the
1588 : incoming fstring with DOMAIN <separator> user. Returns the same
1589 : values as parse_domain_user() but also replaces the incoming username.
1590 : Used to ensure all names are fully qualified within winbindd.
1591 : Used by the NSS protocols of auth, chauthtok, logoff and ccache_ntlm_auth.
1592 : The protocol definitions of auth_crap, chng_pswd_auth_crap
1593 : really should be changed to use this instead of doing things
1594 : by hand. JRA. */
1595 :
1596 452 : bool canonicalize_username(fstring username_inout,
1597 : fstring namespace,
1598 : fstring domain,
1599 : fstring user)
1600 : {
1601 : bool ok;
1602 :
1603 452 : ok = parse_domain_user(username_inout, namespace, domain, user);
1604 452 : if (!ok) {
1605 0 : return False;
1606 : }
1607 452 : slprintf(username_inout, sizeof(fstring) - 1, "%s%c%s",
1608 452 : domain, *lp_winbind_separator(),
1609 : user);
1610 452 : return True;
1611 : }
1612 :
1613 : /*
1614 : Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
1615 : 'winbind separator' options.
1616 : This means:
1617 : - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
1618 : lp_workgroup()
1619 :
1620 : If we are a PDC or BDC, and this is for our domain, do likewise.
1621 :
1622 : On an AD DC we always fill DOMAIN\\USERNAME.
1623 :
1624 : We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1625 : */
1626 : /**
1627 : * talloc version of fill_domain_username()
1628 : * return NULL on talloc failure.
1629 : */
1630 8403 : char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
1631 : const char *domain,
1632 : const char *user,
1633 : bool can_assume)
1634 : {
1635 : char *tmp_user, *name;
1636 :
1637 8403 : if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1638 2669 : can_assume = false;
1639 : }
1640 :
1641 8403 : if (user == NULL) {
1642 0 : return NULL;
1643 : }
1644 :
1645 8403 : tmp_user = talloc_strdup(mem_ctx, user);
1646 8403 : if (tmp_user == NULL) {
1647 0 : return NULL;
1648 : }
1649 8403 : if (!strlower_m(tmp_user)) {
1650 0 : TALLOC_FREE(tmp_user);
1651 0 : return NULL;
1652 : }
1653 :
1654 8403 : if (can_assume && assume_domain(domain)) {
1655 4 : name = tmp_user;
1656 : } else {
1657 8399 : name = talloc_asprintf(mem_ctx, "%s%c%s",
1658 : domain,
1659 8399 : *lp_winbind_separator(),
1660 : tmp_user);
1661 8399 : TALLOC_FREE(tmp_user);
1662 : }
1663 :
1664 8403 : return name;
1665 : }
1666 :
1667 : /*
1668 : * Client list accessor functions
1669 : */
1670 :
1671 : static struct winbindd_cli_state *_client_list;
1672 : static int _num_clients;
1673 :
1674 : /* Return list of all connected clients */
1675 :
1676 2 : struct winbindd_cli_state *winbindd_client_list(void)
1677 : {
1678 2 : return _client_list;
1679 : }
1680 :
1681 : /* Return list-tail of all connected clients */
1682 :
1683 13738 : struct winbindd_cli_state *winbindd_client_list_tail(void)
1684 : {
1685 13738 : return DLIST_TAIL(_client_list);
1686 : }
1687 :
1688 : /* Return previous (read:newer) client in list */
1689 :
1690 : struct winbindd_cli_state *
1691 7866 : winbindd_client_list_prev(struct winbindd_cli_state *cli)
1692 : {
1693 7866 : return DLIST_PREV(cli);
1694 : }
1695 :
1696 : /* Add a connection to the list */
1697 :
1698 8477 : void winbindd_add_client(struct winbindd_cli_state *cli)
1699 : {
1700 8477 : cli->last_access = time(NULL);
1701 8477 : DLIST_ADD(_client_list, cli);
1702 8477 : _num_clients++;
1703 8477 : }
1704 :
1705 : /* Remove a client from the list */
1706 :
1707 8435 : void winbindd_remove_client(struct winbindd_cli_state *cli)
1708 : {
1709 8435 : DLIST_REMOVE(_client_list, cli);
1710 8435 : _num_clients--;
1711 8435 : }
1712 :
1713 : /* Move a client to head or list */
1714 :
1715 72989 : void winbindd_promote_client(struct winbindd_cli_state *cli)
1716 : {
1717 72989 : cli->last_access = time(NULL);
1718 72989 : DLIST_PROMOTE(_client_list, cli);
1719 72989 : }
1720 :
1721 : /* Return number of open clients */
1722 :
1723 8477 : int winbindd_num_clients(void)
1724 : {
1725 8477 : return _num_clients;
1726 : }
1727 :
1728 98 : NTSTATUS lookup_usergroups_cached(TALLOC_CTX *mem_ctx,
1729 : const struct dom_sid *user_sid,
1730 : uint32_t *p_num_groups, struct dom_sid **user_sids)
1731 : {
1732 98 : struct netr_SamInfo3 *info3 = NULL;
1733 98 : NTSTATUS status = NT_STATUS_NO_MEMORY;
1734 98 : uint32_t num_groups = 0;
1735 :
1736 98 : DEBUG(3,(": lookup_usergroups_cached\n"));
1737 :
1738 98 : *user_sids = NULL;
1739 98 : *p_num_groups = 0;
1740 :
1741 98 : info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1742 :
1743 98 : if (info3 == NULL) {
1744 40 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1745 : }
1746 :
1747 : /*
1748 : * Before bug #7843 the "Domain Local" groups were added with a
1749 : * lookupuseraliases call, but this isn't done anymore for our domain
1750 : * so we need to resolve resource groups here.
1751 : *
1752 : * When to use Resource Groups:
1753 : * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
1754 : */
1755 58 : status = sid_array_from_info3(mem_ctx, info3,
1756 : user_sids,
1757 : &num_groups,
1758 : false);
1759 :
1760 58 : if (!NT_STATUS_IS_OK(status)) {
1761 0 : TALLOC_FREE(info3);
1762 0 : return status;
1763 : }
1764 :
1765 58 : TALLOC_FREE(info3);
1766 58 : *p_num_groups = num_groups;
1767 58 : status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1768 :
1769 58 : DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1770 :
1771 58 : return status;
1772 : }
1773 :
1774 : /*********************************************************************
1775 : We use this to remove spaces from user and group names
1776 : ********************************************************************/
1777 :
1778 7510 : NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
1779 : const char *domain_name,
1780 : const char *name,
1781 : char **normalized)
1782 : {
1783 7510 : struct winbindd_domain *domain = NULL;
1784 : NTSTATUS nt_status;
1785 :
1786 7510 : if (!name || !normalized) {
1787 0 : return NT_STATUS_INVALID_PARAMETER;
1788 : }
1789 :
1790 7510 : if (!lp_winbind_normalize_names()) {
1791 7510 : return NT_STATUS_PROCEDURE_NOT_FOUND;
1792 : }
1793 :
1794 0 : domain = find_domain_from_name_noinit(domain_name);
1795 0 : if (domain == NULL) {
1796 0 : DBG_ERR("Failed to find domain '%s'\n", domain_name);
1797 0 : return NT_STATUS_NO_SUCH_DOMAIN;
1798 : }
1799 :
1800 : /* Alias support and whitespace replacement are mutually
1801 : exclusive */
1802 :
1803 0 : nt_status = resolve_username_to_alias(mem_ctx, domain,
1804 : name, normalized );
1805 0 : if (NT_STATUS_IS_OK(nt_status)) {
1806 : /* special return code to let the caller know we
1807 : mapped to an alias */
1808 0 : return NT_STATUS_FILE_RENAMED;
1809 : }
1810 :
1811 : /* check for an unreachable domain */
1812 :
1813 0 : if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1814 0 : DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1815 : domain->name));
1816 0 : set_domain_offline(domain);
1817 0 : return nt_status;
1818 : }
1819 :
1820 : /* deal with whitespace */
1821 :
1822 0 : *normalized = talloc_strdup(mem_ctx, name);
1823 0 : if (!(*normalized)) {
1824 0 : return NT_STATUS_NO_MEMORY;
1825 : }
1826 :
1827 0 : all_string_sub( *normalized, " ", "_", 0 );
1828 :
1829 0 : return NT_STATUS_OK;
1830 : }
1831 :
1832 : /*********************************************************************
1833 : We use this to do the inverse of normalize_name_map()
1834 : ********************************************************************/
1835 :
1836 4735 : NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
1837 : const char *name,
1838 : char **normalized)
1839 : {
1840 : NTSTATUS nt_status;
1841 4735 : struct winbindd_domain *domain = find_our_domain();
1842 :
1843 4735 : if (!name || !normalized) {
1844 0 : return NT_STATUS_INVALID_PARAMETER;
1845 : }
1846 :
1847 4735 : if (!lp_winbind_normalize_names()) {
1848 4735 : return NT_STATUS_PROCEDURE_NOT_FOUND;
1849 : }
1850 :
1851 : /* Alias support and whitespace replacement are mutally
1852 : exclusive */
1853 :
1854 : /* When mapping from an alias to a username, we don't know the
1855 : domain. But we only need a domain structure to cache
1856 : a successful lookup , so just our own domain structure for
1857 : the seqnum. */
1858 :
1859 0 : nt_status = resolve_alias_to_username(mem_ctx, domain,
1860 : name, normalized);
1861 0 : if (NT_STATUS_IS_OK(nt_status)) {
1862 : /* Special return code to let the caller know we mapped
1863 : from an alias */
1864 0 : return NT_STATUS_FILE_RENAMED;
1865 : }
1866 :
1867 : /* check for an unreachable domain */
1868 :
1869 0 : if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1870 0 : DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1871 : domain->name));
1872 0 : set_domain_offline(domain);
1873 0 : return nt_status;
1874 : }
1875 :
1876 : /* deal with whitespace */
1877 :
1878 0 : *normalized = talloc_strdup(mem_ctx, name);
1879 0 : if (!(*normalized)) {
1880 0 : return NT_STATUS_NO_MEMORY;
1881 : }
1882 :
1883 0 : all_string_sub(*normalized, "_", " ", 0);
1884 :
1885 0 : return NT_STATUS_OK;
1886 : }
1887 :
1888 : /*********************************************************************
1889 : ********************************************************************/
1890 :
1891 0 : bool winbindd_can_contact_domain(struct winbindd_domain *domain)
1892 : {
1893 0 : struct winbindd_tdc_domain *tdc = NULL;
1894 0 : TALLOC_CTX *frame = talloc_stackframe();
1895 0 : bool ret = false;
1896 :
1897 : /* We can contact the domain if it is our primary domain */
1898 :
1899 0 : if (domain->primary) {
1900 0 : ret = true;
1901 0 : goto done;
1902 : }
1903 :
1904 : /* Trust the TDC cache and not the winbindd_domain flags */
1905 :
1906 0 : if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
1907 0 : DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
1908 : domain->name));
1909 0 : ret = false;
1910 0 : goto done;
1911 : }
1912 :
1913 : /* Can always contact a domain that is in out forest */
1914 :
1915 0 : if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1916 0 : ret = true;
1917 0 : goto done;
1918 : }
1919 :
1920 : /*
1921 : * On a _member_ server, we cannot contact the domain if it
1922 : * is running AD and we have no inbound trust.
1923 : */
1924 :
1925 0 : if (!IS_DC &&
1926 0 : domain->active_directory &&
1927 0 : ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
1928 : {
1929 0 : DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
1930 : "and we have no inbound trust.\n", domain->name));
1931 0 : goto done;
1932 : }
1933 :
1934 : /* Assume everything else is ok (probably not true but what
1935 : can you do?) */
1936 :
1937 0 : ret = true;
1938 :
1939 0 : done:
1940 0 : talloc_destroy(frame);
1941 :
1942 0 : return ret;
1943 : }
1944 :
1945 : #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
1946 :
1947 : /*********************************************************************
1948 : ********************************************************************/
1949 :
1950 26 : static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
1951 : {
1952 26 : char *var = NULL;
1953 : char addr[INET6_ADDRSTRLEN];
1954 26 : const char *kdc = NULL;
1955 26 : int lvl = 11;
1956 :
1957 26 : if (!domain || !domain->alt_name || !*domain->alt_name) {
1958 2 : return;
1959 : }
1960 :
1961 26 : if (domain->initialized && !domain->active_directory) {
1962 0 : DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
1963 : domain->alt_name));
1964 0 : return;
1965 : }
1966 :
1967 26 : print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
1968 26 : kdc = addr;
1969 26 : if (!*kdc) {
1970 2 : DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
1971 : domain->alt_name));
1972 2 : kdc = domain->dcname;
1973 : }
1974 :
1975 26 : if (!kdc || !*kdc) {
1976 2 : DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
1977 : domain->alt_name));
1978 2 : return;
1979 : }
1980 :
1981 24 : var = talloc_asprintf_strupper_m(
1982 : talloc_tos(),
1983 : "%s_%s",
1984 : WINBINDD_LOCATOR_KDC_ADDRESS,
1985 12 : domain->alt_name);
1986 24 : if (var == NULL) {
1987 0 : return;
1988 : }
1989 :
1990 24 : DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
1991 : var, kdc));
1992 :
1993 24 : setenv(var, kdc, 1);
1994 24 : TALLOC_FREE(var);
1995 : }
1996 :
1997 : /*********************************************************************
1998 : ********************************************************************/
1999 :
2000 18 : void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2001 : {
2002 18 : struct winbindd_domain *our_dom = find_our_domain();
2003 :
2004 18 : winbindd_set_locator_kdc_env(domain);
2005 :
2006 18 : if (domain != our_dom) {
2007 8 : winbindd_set_locator_kdc_env(our_dom);
2008 : }
2009 18 : }
2010 :
2011 : /*********************************************************************
2012 : ********************************************************************/
2013 :
2014 0 : void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2015 : {
2016 0 : char *var = NULL;
2017 :
2018 0 : if (!domain || !domain->alt_name || !*domain->alt_name) {
2019 0 : return;
2020 : }
2021 :
2022 0 : var = talloc_asprintf_strupper_m(
2023 : talloc_tos(),
2024 : "%s_%s",
2025 : WINBINDD_LOCATOR_KDC_ADDRESS,
2026 0 : domain->alt_name);
2027 0 : if (var == NULL) {
2028 0 : return;
2029 : }
2030 :
2031 0 : unsetenv(var);
2032 0 : TALLOC_FREE(var);
2033 : }
2034 : #else
2035 :
2036 : void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2037 : {
2038 : return;
2039 : }
2040 :
2041 : void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2042 : {
2043 : return;
2044 : }
2045 :
2046 : #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
2047 :
2048 1233 : void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
2049 : {
2050 : /*
2051 : * Make sure we start with authoritative=true,
2052 : * it will only set to false if we don't know the
2053 : * domain.
2054 : */
2055 1233 : resp->data.auth.authoritative = true;
2056 :
2057 1233 : resp->data.auth.nt_status = NT_STATUS_V(result);
2058 1233 : fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
2059 :
2060 : /* we might have given a more useful error above */
2061 1233 : if (*resp->data.auth.error_string == '\0')
2062 1233 : fstrcpy(resp->data.auth.error_string,
2063 : get_friendly_nt_error_msg(result));
2064 1233 : resp->data.auth.pam_error = nt_status_to_pam(result);
2065 1233 : }
2066 :
2067 6732 : bool is_domain_offline(const struct winbindd_domain *domain)
2068 : {
2069 6732 : if (get_global_winbindd_state_offline()) {
2070 0 : return true;
2071 : }
2072 6732 : return !domain->online;
2073 : }
2074 :
2075 6732 : bool is_domain_online(const struct winbindd_domain *domain)
2076 : {
2077 6732 : return !is_domain_offline(domain);
2078 : }
2079 :
2080 : /**
2081 : * Parse an char array into a list of sids.
2082 : *
2083 : * The input sidstr should consist of 0-terminated strings
2084 : * representing sids, separated by newline characters '\n'.
2085 : * The list is terminated by an empty string, i.e.
2086 : * character '\0' directly following a character '\n'
2087 : * (or '\0' right at the start of sidstr).
2088 : */
2089 5156 : bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
2090 : struct dom_sid **sids, uint32_t *num_sids)
2091 : {
2092 : const char *p;
2093 :
2094 5156 : p = sidstr;
2095 5156 : if (p == NULL)
2096 0 : return False;
2097 :
2098 56886 : while (p[0] != '\0') {
2099 : struct dom_sid sid;
2100 46923 : const char *q = NULL;
2101 :
2102 46923 : if (!dom_sid_parse_endp(p, &sid, &q)) {
2103 0 : DEBUG(1, ("Could not parse sid %s\n", p));
2104 0 : return false;
2105 : }
2106 46923 : if (q[0] != '\n') {
2107 0 : DEBUG(1, ("Got invalid sidstr: %s\n", p));
2108 0 : return false;
2109 : }
2110 46923 : if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
2111 : num_sids)))
2112 : {
2113 0 : return False;
2114 : }
2115 46923 : p = q+1;
2116 : }
2117 5156 : return True;
2118 : }
2119 :
2120 3138 : bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
2121 : struct unixid **pxids, uint32_t *pnum_xids)
2122 : {
2123 : const char *p;
2124 3138 : struct unixid *xids = NULL;
2125 3138 : uint32_t num_xids = 0;
2126 :
2127 3138 : p = xidstr;
2128 3138 : if (p == NULL) {
2129 0 : return false;
2130 : }
2131 :
2132 10585 : while (p[0] != '\0') {
2133 : struct unixid *tmp;
2134 : struct unixid xid;
2135 : unsigned long long id;
2136 : char *endp;
2137 4367 : int error = 0;
2138 :
2139 4367 : switch (p[0]) {
2140 1979 : case 'U':
2141 1979 : xid = (struct unixid) { .type = ID_TYPE_UID };
2142 1979 : break;
2143 2388 : case 'G':
2144 2388 : xid = (struct unixid) { .type = ID_TYPE_GID };
2145 2388 : break;
2146 0 : default:
2147 0 : return false;
2148 : }
2149 :
2150 4367 : p += 1;
2151 :
2152 4367 : id = smb_strtoull(p, &endp, 10, &error, SMB_STR_STANDARD);
2153 4367 : if (error != 0) {
2154 0 : goto fail;
2155 : }
2156 4367 : if (*endp != '\n') {
2157 0 : goto fail;
2158 : }
2159 4367 : p = endp+1;
2160 :
2161 4367 : xid.id = id;
2162 4367 : if ((unsigned long long)xid.id != id) {
2163 0 : goto fail;
2164 : }
2165 :
2166 4367 : tmp = talloc_realloc(mem_ctx, xids, struct unixid, num_xids+1);
2167 4367 : if (tmp == NULL) {
2168 0 : return 0;
2169 : }
2170 4367 : xids = tmp;
2171 :
2172 4367 : xids[num_xids] = xid;
2173 4367 : num_xids += 1;
2174 : }
2175 :
2176 3138 : *pxids = xids;
2177 3138 : *pnum_xids = num_xids;
2178 3138 : return true;
2179 :
2180 0 : fail:
2181 0 : TALLOC_FREE(xids);
2182 0 : return false;
2183 : }
|