python/samba/tests: add test cases for s3/registry init funcs
[Samba.git] / source3 / winbindd / winbindd_util.c
blob53e7f32b5b982acf4f9f5a63d4a0e7082426d867
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind daemon for ntdom nss module
6 Copyright (C) Tim Potter 2000-2001
7 Copyright (C) 2001 by Martin Pool <mbp@samba.org>
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.
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.
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/>.
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"
41 #undef DBGC_CLASS
42 #define DBGC_CLASS DBGC_WINBIND
44 /**
45 * @file winbindd_util.c
47 * Winbind daemon for NT domain authentication nss module.
48 **/
50 static bool add_trusted_domains_dc(void);
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. */
57 static struct winbindd_domain *_domain_list = NULL;
59 struct winbindd_domain *domain_list(void)
61 /* Initialise list */
63 if ((!_domain_list) && (!init_domain_list())) {
64 smb_panic("Init_domain_list failed");
67 return _domain_list;
70 /* Free all entries in the trusted domain list */
72 static void free_domain_list(void)
74 struct winbindd_domain *domain = _domain_list;
76 while(domain) {
77 struct winbindd_domain *next = domain->next;
79 DLIST_REMOVE(_domain_list, domain);
80 TALLOC_FREE(domain);
81 domain = next;
85 /**
86 * Iterator for winbindd's domain list.
87 * To be used (e.g.) in tevent based loops.
89 struct winbindd_domain *wb_next_domain(struct winbindd_domain *domain)
91 if (domain == NULL) {
92 domain = domain_list();
93 } else {
94 domain = domain->next;
97 if ((domain != NULL) &&
98 (lp_server_role() != ROLE_ACTIVE_DIRECTORY_DC) &&
99 sid_check_is_our_sam(&domain->sid))
101 domain = domain->next;
104 return domain;
107 static bool is_internal_domain(const struct dom_sid *sid)
109 if (sid == NULL)
110 return False;
112 return (sid_check_is_our_sam(sid) || sid_check_is_builtin(sid));
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. */
119 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)
129 struct winbindd_domain *domain = NULL;
130 int role = lp_server_role();
131 struct dom_sid_buf buf;
133 if (is_null_sid(sid)) {
134 DBG_ERR("Got null SID for domain [%s]\n", domain_name);
135 return NT_STATUS_INVALID_PARAMETER;
138 if (secure_channel_type == SEC_CHAN_NULL && !is_allowed_domain(domain_name)) {
139 return NT_STATUS_NO_SUCH_DOMAIN;
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.
146 for (domain = _domain_list; domain; domain = domain->next) {
147 if (strequal(domain_name, domain->name)) {
148 break;
152 if (domain != NULL) {
153 struct winbindd_domain *check_domain = NULL;
155 for (check_domain = _domain_list;
156 check_domain != NULL;
157 check_domain = check_domain->next)
159 if (check_domain == domain) {
160 continue;
163 if (dom_sid_equal(&check_domain->sid, sid)) {
164 break;
168 if (check_domain != NULL) {
169 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 return NT_STATUS_INVALID_PARAMETER;
178 if ((domain != NULL) && (dns_name != NULL)) {
179 struct winbindd_domain *check_domain = NULL;
181 for (check_domain = _domain_list;
182 check_domain != NULL;
183 check_domain = check_domain->next)
185 if (check_domain == domain) {
186 continue;
189 if (strequal(check_domain->alt_name, dns_name)) {
190 break;
194 if (check_domain != NULL) {
195 DBG_ERR("DNS name [%s] used by domain [%s], "
196 "expected [%s]\n",
197 dns_name, check_domain->name,
198 domain->name);
199 return NT_STATUS_INVALID_PARAMETER;
203 if (domain != NULL) {
204 *_d = domain;
205 return NT_STATUS_OK;
208 /* Create new domain entry */
209 domain = talloc_zero(NULL, struct winbindd_domain);
210 if (domain == NULL) {
211 return NT_STATUS_NO_MEMORY;
214 domain->children = talloc_zero_array(domain,
215 struct winbindd_child,
216 lp_winbind_max_domain_connections());
217 if (domain->children == NULL) {
218 TALLOC_FREE(domain);
219 return NT_STATUS_NO_MEMORY;
222 domain->queue = tevent_queue_create(domain, "winbind_domain");
223 if (domain->queue == NULL) {
224 TALLOC_FREE(domain);
225 return NT_STATUS_NO_MEMORY;
228 domain->binding_handle = wbint_binding_handle(domain, domain, NULL);
229 if (domain->binding_handle == NULL) {
230 TALLOC_FREE(domain);
231 return NT_STATUS_NO_MEMORY;
234 domain->name = talloc_strdup(domain, domain_name);
235 if (domain->name == NULL) {
236 TALLOC_FREE(domain);
237 return NT_STATUS_NO_MEMORY;
240 if (dns_name != NULL) {
241 domain->alt_name = talloc_strdup(domain, dns_name);
242 if (domain->alt_name == NULL) {
243 TALLOC_FREE(domain);
244 return NT_STATUS_NO_MEMORY;
248 domain->backend = NULL;
249 domain->internal = is_internal_domain(sid);
250 domain->secure_channel_type = secure_channel_type;
251 domain->sequence_number = DOM_SEQUENCE_NONE;
252 domain->last_seq_check = 0;
253 domain->initialized = false;
254 domain->online = is_internal_domain(sid);
255 domain->domain_flags = trust_flags;
256 domain->domain_type = trust_type;
257 domain->domain_trust_attribs = trust_attribs;
258 domain->secure_channel_type = secure_channel_type;
259 domain->routing_domain = routing_domain;
260 sid_copy(&domain->sid, sid);
262 /* Is this our primary domain ? */
263 if (role == ROLE_DOMAIN_MEMBER) {
264 domain->primary = strequal(domain_name, lp_workgroup());
265 } else {
266 domain->primary = strequal(domain_name, get_global_sam_name());
269 if (domain->primary) {
270 if (role == ROLE_ACTIVE_DIRECTORY_DC) {
271 domain->active_directory = true;
273 if (lp_security() == SEC_ADS) {
274 domain->active_directory = true;
276 } else if (!domain->internal) {
277 if (domain->domain_type == LSA_TRUST_TYPE_UPLEVEL) {
278 domain->active_directory = true;
282 domain->can_do_ncacn_ip_tcp = domain->active_directory;
284 /* Link to domain list */
285 DLIST_ADD_END(_domain_list, domain);
287 wcache_tdc_add_domain( domain );
289 setup_domain_child(domain);
291 DBG_NOTICE("Added domain [%s] [%s] [%s]\n",
292 domain->name, domain->alt_name,
293 dom_sid_str_buf(&domain->sid, &buf));
295 *_d = domain;
296 return NT_STATUS_OK;
299 bool set_routing_domain(struct winbindd_domain *domain,
300 struct winbindd_domain *routing_domain)
302 if (domain->routing_domain == NULL) {
303 domain->routing_domain = routing_domain;
304 return true;
306 if (domain->routing_domain != routing_domain) {
307 return false;
309 return true;
312 bool add_trusted_domain_from_auth(uint16_t validation_level,
313 struct info3_text *info3,
314 struct info6_text *info6)
316 struct winbindd_domain *domain = NULL;
317 struct dom_sid domain_sid;
318 const char *dns_domainname = NULL;
319 NTSTATUS status;
320 bool ok;
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.
329 if (IS_DC) {
330 return true;
333 ok = dom_sid_parse(info3->dom_sid, &domain_sid);
334 if (!ok) {
335 DBG_NOTICE("dom_sid_parse [%s] failed\n", info3->dom_sid);
336 return false;
339 if (validation_level == 6) {
340 if (!strequal(info6->dns_domainname, "")) {
341 dns_domainname = info6->dns_domainname;
345 status = add_trusted_domain(info3->logon_dom,
346 dns_domainname,
347 &domain_sid,
349 NETR_TRUST_FLAG_OUTBOUND,
351 SEC_CHAN_NULL,
352 find_default_route_domain(),
353 &domain);
354 if (!NT_STATUS_IS_OK(status) &&
355 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
357 DBG_DEBUG("Adding domain [%s] with sid [%s] failed\n",
358 info3->logon_dom, info3->dom_sid);
359 return false;
362 return true;
365 bool domain_is_forest_root(const struct winbindd_domain *domain)
367 const uint32_t fr_flags =
368 (NETR_TRUST_FLAG_TREEROOT|NETR_TRUST_FLAG_IN_FOREST);
370 return ((domain->domain_flags & fr_flags) == fr_flags);
373 /********************************************************************
374 rescan our domains looking for new trusted domains
375 ********************************************************************/
377 struct trustdom_state {
378 struct winbindd_domain *domain;
379 struct netr_DomainTrustList trusts;
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 );
386 static void add_trusted_domains( struct winbindd_domain *domain )
388 struct tevent_context *ev = global_event_context();
389 struct trustdom_state *state;
390 struct tevent_req *req;
391 const char *client_name = NULL;
392 pid_t client_pid;
394 state = talloc_zero(NULL, struct trustdom_state);
395 if (state == NULL) {
396 DEBUG(0, ("talloc failed\n"));
397 return;
399 state->domain = domain;
401 /* Called from timer, not from a real client */
402 client_name = getprogname();
403 client_pid = getpid();
405 req = dcerpc_wbint_ListTrustedDomains_send(state,
407 dom_child_handle(domain),
408 client_name,
409 client_pid,
410 &state->trusts);
411 if (req == NULL) {
412 DBG_ERR("dcerpc_wbint_ListTrustedDomains_send failed\n");
413 TALLOC_FREE(state);
414 return;
416 tevent_req_set_callback(req, trustdom_list_done, state);
419 static void trustdom_list_done(struct tevent_req *req)
421 struct trustdom_state *state = tevent_req_callback_data(
422 req, struct trustdom_state);
423 bool within_forest = false;
424 NTSTATUS status, result;
425 uint32_t i;
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.
434 if (state->domain->primary) {
435 within_forest = true;
436 } else if (domain_is_forest_root(state->domain)) {
437 within_forest = true;
440 status = dcerpc_wbint_ListTrustedDomains_recv(req, state, &result);
441 if (any_nt_status_not_ok(status, result, &status)) {
442 DBG_WARNING("Could not receive trusts for domain %s: %s-%s\n",
443 state->domain->name, nt_errstr(status),
444 nt_errstr(result));
445 TALLOC_FREE(state);
446 return;
449 for (i=0; i<state->trusts.count; i++) {
450 struct netr_DomainTrust *trust = &state->trusts.array[i];
451 struct winbindd_domain *domain = NULL;
453 if (!within_forest) {
454 trust->trust_flags &= ~NETR_TRUST_FLAG_IN_FOREST;
457 if (!state->domain->primary) {
458 trust->trust_flags &= ~NETR_TRUST_FLAG_PRIMARY;
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.
467 status = add_trusted_domain(trust->netbios_name,
468 trust->dns_name,
469 trust->sid,
470 trust->trust_type,
471 trust->trust_flags,
472 trust->trust_attributes,
473 SEC_CHAN_NULL,
474 find_default_route_domain(),
475 &domain);
476 if (!NT_STATUS_IS_OK(status) &&
477 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
479 DBG_NOTICE("add_trusted_domain returned %s\n",
480 nt_errstr(status));
481 return;
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)
493 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 */
497 if (!domain_is_forest_root(state->domain))
498 rescan_forest_root_trusts();
499 else
500 rescan_forest_trusts();
502 } 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 */
506 rescan_forest_trusts();
509 TALLOC_FREE(state);
511 return;
514 /********************************************************************
515 Scan the trusts of our forest root
516 ********************************************************************/
518 static void rescan_forest_root_trusts( void )
520 struct winbindd_tdc_domain *dom_list = NULL;
521 size_t num_trusts = 0;
522 size_t i;
523 NTSTATUS status;
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. */
531 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
532 return;
534 for ( i=0; i<num_trusts; i++ ) {
535 struct winbindd_domain *d = NULL;
537 /* Find the forest root. Don't necessarily trust
538 the domain_list() as our primary domain may not
539 have been initialized. */
541 if ( !(dom_list[i].trust_flags & NETR_TRUST_FLAG_TREEROOT) ) {
542 continue;
545 /* Here's the forest root */
547 d = find_domain_from_name_noinit( dom_list[i].domain_name );
548 if (d == NULL) {
549 status = add_trusted_domain(dom_list[i].domain_name,
550 dom_list[i].dns_name,
551 &dom_list[i].sid,
552 dom_list[i].trust_type,
553 dom_list[i].trust_flags,
554 dom_list[i].trust_attribs,
555 SEC_CHAN_NULL,
556 find_default_route_domain(),
557 &d);
559 if (!NT_STATUS_IS_OK(status) &&
560 NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
562 DBG_ERR("add_trusted_domain returned %s\n",
563 nt_errstr(status));
564 return;
567 if (d == NULL) {
568 continue;
571 DEBUG(10,("rescan_forest_root_trusts: Following trust path "
572 "for domain tree root %s (%s)\n",
573 d->name, d->alt_name ));
575 d->domain_flags = dom_list[i].trust_flags;
576 d->domain_type = dom_list[i].trust_type;
577 d->domain_trust_attribs = dom_list[i].trust_attribs;
579 add_trusted_domains( d );
581 break;
584 TALLOC_FREE( dom_list );
586 return;
589 /********************************************************************
590 scan the transitive forest trusts (not our own)
591 ********************************************************************/
594 static void rescan_forest_trusts( void )
596 struct winbindd_domain *d = NULL;
597 struct winbindd_tdc_domain *dom_list = NULL;
598 size_t num_trusts = 0;
599 size_t i;
600 NTSTATUS status;
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. */
608 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
609 return;
611 for ( i=0; i<num_trusts; i++ ) {
612 uint32_t flags = dom_list[i].trust_flags;
613 uint32_t type = dom_list[i].trust_type;
614 uint32_t attribs = dom_list[i].trust_attribs;
616 d = find_domain_from_name_noinit( dom_list[i].domain_name );
618 /* ignore our primary and internal domains */
620 if ( d && (d->internal || d->primary ) )
621 continue;
623 if ( (flags & NETR_TRUST_FLAG_INBOUND) &&
624 (type == LSA_TRUST_TYPE_UPLEVEL) &&
625 (attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) )
627 /* add the trusted domain if we don't know
628 about it */
630 if (d == NULL) {
631 status = add_trusted_domain(
632 dom_list[i].domain_name,
633 dom_list[i].dns_name,
634 &dom_list[i].sid,
635 type,
636 flags,
637 attribs,
638 SEC_CHAN_NULL,
639 find_default_route_domain(),
640 &d);
641 if (!NT_STATUS_IS_OK(status) &&
642 NT_STATUS_EQUAL(status,
643 NT_STATUS_NO_SUCH_DOMAIN))
645 DBG_ERR("add_trusted_domain: %s\n",
646 nt_errstr(status));
647 return;
651 if (d == NULL) {
652 continue;
655 DEBUG(10,("Following trust path for domain %s (%s)\n",
656 d->name, d->alt_name ));
657 add_trusted_domains( d );
661 TALLOC_FREE( dom_list );
663 return;
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 *********************************************************************/
674 void rescan_trusted_domains(struct tevent_context *ev, struct tevent_timer *te,
675 struct timeval now, void *private_data)
677 TALLOC_FREE(te);
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. */
687 /* this will only add new domains we didn't already know about
688 in the domain_list()*/
690 add_trusted_domains( find_our_domain() );
692 te = tevent_add_timer(
693 ev, NULL, timeval_current_ofs(WINBINDD_RESCAN_FREQ, 0),
694 rescan_trusted_domains, NULL);
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.
700 return;
703 static void wbd_ping_dc_done(struct tevent_req *subreq);
705 void winbindd_ping_offline_domains(struct tevent_context *ev,
706 struct tevent_timer *te,
707 struct timeval now,
708 void *private_data)
710 struct winbindd_domain *domain = NULL;
712 TALLOC_FREE(te);
714 for (domain = domain_list(); domain != NULL; domain = domain->next) {
715 DBG_DEBUG("Domain %s is %s\n",
716 domain->name,
717 domain->online ? "online" : "offline");
719 if (get_global_winbindd_state_offline()) {
720 DBG_DEBUG("We are globally offline, do nothing.\n");
721 break;
724 if (domain->online ||
725 domain->check_online_event != NULL ||
726 domain->secure_channel_type == SEC_CHAN_NULL) {
727 continue;
730 winbindd_flush_negative_conn_cache(domain);
732 domain->check_online_event =
733 dcerpc_wbint_PingDc_send(domain,
735 dom_child_handle(domain),
736 &domain->ping_dcname);
737 if (domain->check_online_event == NULL) {
738 DBG_WARNING("Failed to schedule ping, no-memory\n");
739 continue;
742 tevent_req_set_callback(domain->check_online_event,
743 wbd_ping_dc_done, domain);
746 te = tevent_add_timer(ev,
747 NULL,
748 timeval_current_ofs(lp_winbind_reconnect_delay(),
750 winbindd_ping_offline_domains,
751 NULL);
752 if (te == NULL) {
753 DBG_ERR("Failed to schedule winbindd_ping_offline_domains()\n");
756 return;
759 static void wbd_ping_dc_done(struct tevent_req *subreq)
761 struct winbindd_domain *domain =
762 tevent_req_callback_data(subreq,
763 struct winbindd_domain);
764 NTSTATUS status, result;
766 SMB_ASSERT(subreq == domain->check_online_event);
767 domain->check_online_event = NULL;
769 status = dcerpc_wbint_PingDc_recv(subreq, domain, &result);
770 TALLOC_FREE(subreq);
771 if (any_nt_status_not_ok(status, result, &status)) {
772 DBG_WARNING("dcerpc_wbint_PingDc_recv failed for domain: "
773 "%s - %s\n",
774 domain->name,
775 nt_errstr(status));
776 return;
779 DBG_DEBUG("dcerpc_wbint_PingDc_recv() succeeded, "
780 "domain: %s, dc-name: %s\n",
781 domain->name,
782 domain->ping_dcname);
784 talloc_free(discard_const(domain->ping_dcname));
785 domain->ping_dcname = NULL;
787 return;
790 enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domain,
791 struct winbindd_cli_state *state)
793 /* Ensure null termination */
794 state->request->domain_name
795 [sizeof(state->request->domain_name)-1]='\0';
796 state->request->data.init_conn.dcname
797 [sizeof(state->request->data.init_conn.dcname)-1]='\0';
799 if (strlen(state->request->data.init_conn.dcname) > 0) {
800 TALLOC_FREE(domain->dcname);
801 domain->dcname = talloc_strdup(domain,
802 state->request->data.init_conn.dcname);
803 if (domain->dcname == NULL) {
804 return WINBINDD_ERROR;
808 init_dc_connection(domain, false);
810 if (!domain->initialized) {
811 /* If we return error here we can't do any cached authentication,
812 but we may be in disconnected mode and can't initialize correctly.
813 Do what the previous code did and just return without initialization,
814 once we go online we'll re-initialize.
816 DEBUG(5, ("winbindd_dual_init_connection: %s returning without initialization "
817 "online = %d\n", domain->name, (int)domain->online ));
820 fstrcpy(state->response->data.domain_info.name, domain->name);
821 fstrcpy(state->response->data.domain_info.alt_name, domain->alt_name);
822 sid_to_fstring(state->response->data.domain_info.sid, &domain->sid);
824 state->response->data.domain_info.native_mode
825 = domain->native_mode;
826 state->response->data.domain_info.active_directory
827 = domain->active_directory;
828 state->response->data.domain_info.primary
829 = domain->primary;
831 return WINBINDD_OK;
834 static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
835 void *private_data,
836 uint32_t msg_type,
837 struct server_id server_id,
838 size_t num_fds,
839 int *fds,
840 DATA_BLOB *data)
842 bool ok;
844 if (num_fds != 0) {
845 DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
846 return;
849 DBG_NOTICE("Rescanning trusted domains\n");
851 ok = add_trusted_domains_dc();
852 if (!ok) {
853 DBG_ERR("Failed to reload trusted domains\n");
858 * We did not get the secret when we queried secrets.tdb, so read it
859 * from secrets.tdb and re-sync the databases
861 static bool migrate_secrets_tdb_to_ldb(struct winbindd_domain *domain)
863 bool ok;
864 struct cli_credentials *creds;
865 NTSTATUS can_migrate = pdb_get_trust_credentials(domain->name,
866 NULL, domain, &creds);
867 if (!NT_STATUS_IS_OK(can_migrate)) {
868 DEBUG(0, ("Failed to fetch our own, local AD domain join "
869 "password for winbindd's internal use, both from "
870 "secrets.tdb and secrets.ldb: %s\n",
871 nt_errstr(can_migrate)));
872 return false;
876 * NOTE: It is very unlikely we end up here if there is an
877 * oldpass, because a new password is created at
878 * classicupgrade, so this is not a concern.
880 ok = secrets_store_machine_pw_sync(cli_credentials_get_password(creds),
881 NULL /* oldpass */,
882 cli_credentials_get_domain(creds),
883 cli_credentials_get_realm(creds),
884 cli_credentials_get_salt_principal(creds),
885 0, /* Supported enc types, unused */
886 &domain->sid,
887 cli_credentials_get_password_last_changed_time(creds),
888 cli_credentials_get_secure_channel_type(creds),
889 false /* do_delete: Do not delete */);
890 TALLOC_FREE(creds);
891 if (ok == false) {
892 DEBUG(0, ("Failed to write our our own, "
893 "local AD domain join password for "
894 "winbindd's internal use into secrets.tdb\n"));
895 return false;
897 return true;
900 static bool add_trusted_domains_dc(void)
902 struct winbindd_domain *domain = NULL;
903 struct pdb_trusted_domain **domains = NULL;
904 uint32_t num_domains = 0;
905 uint32_t i;
906 NTSTATUS status;
908 if (!(pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX)) {
909 struct trustdom_info **ti = NULL;
911 status = pdb_enum_trusteddoms(talloc_tos(), &num_domains, &ti);
912 if (!NT_STATUS_IS_OK(status)) {
913 DBG_ERR("pdb_enum_trusteddoms() failed - %s\n",
914 nt_errstr(status));
915 return false;
918 for (i = 0; i < num_domains; i++) {
919 status = add_trusted_domain(ti[i]->name,
920 NULL,
921 &ti[i]->sid,
922 LSA_TRUST_TYPE_DOWNLEVEL,
923 NETR_TRUST_FLAG_OUTBOUND,
925 SEC_CHAN_DOMAIN,
926 NULL,
927 &domain);
928 if (!NT_STATUS_IS_OK(status)) {
929 DBG_NOTICE("add_trusted_domain returned %s\n",
930 nt_errstr(status));
931 return false;
935 return true;
938 status = pdb_enum_trusted_domains(talloc_tos(), &num_domains, &domains);
939 if (!NT_STATUS_IS_OK(status)) {
940 DBG_ERR("pdb_enum_trusted_domains() failed - %s\n",
941 nt_errstr(status));
942 return false;
945 for (i = 0; i < num_domains; i++) {
946 enum netr_SchannelType sec_chan_type = SEC_CHAN_DOMAIN;
947 uint32_t trust_flags = 0;
949 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
950 sec_chan_type = SEC_CHAN_DNS_DOMAIN;
953 if (!(domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
954 sec_chan_type = SEC_CHAN_NULL;
957 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
958 trust_flags |= NETR_TRUST_FLAG_INBOUND;
960 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
961 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
963 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
964 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
967 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION) {
969 * We don't support selective authentication yet.
971 DBG_WARNING("Ignoring CROSS_ORGANIZATION trust to "
972 "domain[%s/%s]\n",
973 domains[i]->netbios_name,
974 domains[i]->domain_name);
975 continue;
978 status = add_trusted_domain(domains[i]->netbios_name,
979 domains[i]->domain_name,
980 &domains[i]->security_identifier,
981 domains[i]->trust_type,
982 trust_flags,
983 domains[i]->trust_attributes,
984 sec_chan_type,
985 NULL,
986 &domain);
987 if (!NT_STATUS_IS_OK(status)) {
988 DBG_NOTICE("add_trusted_domain returned %s\n",
989 nt_errstr(status));
990 return false;
993 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
994 domain->active_directory = true;
996 domain->domain_type = domains[i]->trust_type;
997 domain->domain_trust_attribs = domains[i]->trust_attributes;
1000 for (i = 0; i < num_domains; i++) {
1001 struct ForestTrustInfo fti;
1002 uint32_t fi;
1003 enum ndr_err_code ndr_err;
1004 struct winbindd_domain *routing_domain = NULL;
1006 if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
1007 continue;
1010 if (!(domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
1011 continue;
1014 if (domains[i]->trust_forest_trust_info.length == 0) {
1015 continue;
1018 routing_domain = find_domain_from_name_noinit(
1019 domains[i]->netbios_name);
1020 if (routing_domain == NULL) {
1021 DBG_ERR("Can't find winbindd domain [%s]\n",
1022 domains[i]->netbios_name);
1023 return false;
1026 ndr_err = ndr_pull_struct_blob_all(
1027 &domains[i]->trust_forest_trust_info,
1028 talloc_tos(), &fti,
1029 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
1030 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1031 DBG_ERR("ndr_pull_ForestTrustInfo(%s) - %s\n",
1032 domains[i]->netbios_name,
1033 ndr_map_error2string(ndr_err));
1034 return false;
1037 for (fi = 0; fi < fti.count; fi++) {
1038 struct ForestTrustInfoRecord *rec =
1039 &fti.records[fi].record;
1040 struct ForestTrustDataDomainInfo *drec = NULL;
1042 if (rec->type != FOREST_TRUST_DOMAIN_INFO) {
1043 continue;
1045 drec = &rec->data.info;
1047 if (rec->flags & LSA_NB_DISABLED_MASK) {
1048 continue;
1051 if (rec->flags & LSA_SID_DISABLED_MASK) {
1052 continue;
1056 * TODO:
1057 * also try to find a matching
1058 * LSA_TLN_DISABLED_MASK ???
1061 domain = find_domain_from_name_noinit(drec->netbios_name.string);
1062 if (domain != NULL) {
1063 continue;
1066 status = add_trusted_domain(drec->netbios_name.string,
1067 drec->dns_name.string,
1068 &drec->sid,
1069 LSA_TRUST_TYPE_UPLEVEL,
1070 NETR_TRUST_FLAG_OUTBOUND,
1072 SEC_CHAN_NULL,
1073 routing_domain,
1074 &domain);
1075 if (!NT_STATUS_IS_OK(status)) {
1076 DBG_NOTICE("add_trusted_domain returned %s\n",
1077 nt_errstr(status));
1078 return false;
1080 if (domain == NULL) {
1081 continue;
1086 return true;
1090 /* Look up global info for the winbind daemon */
1091 bool init_domain_list(void)
1093 int role = lp_server_role();
1094 struct pdb_domain_info *pdb_domain_info = NULL;
1095 struct winbindd_domain *domain = NULL;
1096 NTSTATUS status;
1097 bool ok;
1099 /* Free existing list */
1100 free_domain_list();
1102 /* BUILTIN domain */
1104 status = add_trusted_domain("BUILTIN",
1105 NULL,
1106 &global_sid_Builtin,
1107 LSA_TRUST_TYPE_DOWNLEVEL,
1108 0, /* trust_flags */
1109 0, /* trust_attribs */
1110 SEC_CHAN_LOCAL,
1111 NULL,
1112 &domain);
1113 if (!NT_STATUS_IS_OK(status)) {
1114 DBG_ERR("add_trusted_domain BUILTIN returned %s\n",
1115 nt_errstr(status));
1116 return false;
1119 /* Local SAM */
1122 * In case the passdb backend is passdb_dsdb the domain SID comes from
1123 * dsdb, not from secrets.tdb. As we use the domain SID in various
1124 * places, we must ensure the domain SID is migrated from dsdb to
1125 * secrets.tdb before get_global_sam_sid() is called the first time.
1127 * The migration is done as part of the passdb_dsdb initialisation,
1128 * calling pdb_get_domain_info() triggers it.
1130 pdb_domain_info = pdb_get_domain_info(talloc_tos());
1132 if ( role == ROLE_ACTIVE_DIRECTORY_DC ) {
1133 uint32_t trust_flags;
1134 bool is_root;
1135 enum netr_SchannelType sec_chan_type;
1136 const char *account_name;
1137 struct samr_Password current_nt_hash;
1139 if (pdb_domain_info == NULL) {
1140 DEBUG(0, ("Failed to fetch our own, local AD "
1141 "domain info from sam.ldb\n"));
1142 return false;
1145 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1146 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1147 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1148 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1150 is_root = strequal(pdb_domain_info->dns_domain,
1151 pdb_domain_info->dns_forest);
1152 if (is_root) {
1153 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1156 status = add_trusted_domain(pdb_domain_info->name,
1157 pdb_domain_info->dns_domain,
1158 &pdb_domain_info->sid,
1159 LSA_TRUST_TYPE_UPLEVEL,
1160 trust_flags,
1161 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1162 SEC_CHAN_BDC,
1163 NULL,
1164 &domain);
1165 TALLOC_FREE(pdb_domain_info);
1166 if (!NT_STATUS_IS_OK(status)) {
1167 DBG_ERR("Failed to add our own, local AD "
1168 "domain to winbindd's internal list\n");
1169 return false;
1173 * We need to call this to find out if we are an RODC
1175 ok = get_trust_pw_hash(domain->name,
1176 current_nt_hash.hash,
1177 &account_name,
1178 &sec_chan_type);
1179 if (!ok) {
1181 * If get_trust_pw_hash() fails, then try and
1182 * fetch the password from the more recent of
1183 * secrets.{ldb,tdb} using the
1184 * pdb_get_trust_credentials()
1186 ok = migrate_secrets_tdb_to_ldb(domain);
1188 if (!ok) {
1189 DEBUG(0, ("Failed to migrate our own, "
1190 "local AD domain join password for "
1191 "winbindd's internal use into "
1192 "secrets.tdb\n"));
1193 return false;
1195 ok = get_trust_pw_hash(domain->name,
1196 current_nt_hash.hash,
1197 &account_name,
1198 &sec_chan_type);
1199 if (!ok) {
1200 DEBUG(0, ("Failed to find our our own, just "
1201 "written local AD domain join "
1202 "password for winbindd's internal "
1203 "use in secrets.tdb\n"));
1204 return false;
1208 domain->secure_channel_type = sec_chan_type;
1209 if (sec_chan_type == SEC_CHAN_RODC) {
1210 domain->rodc = true;
1213 } else {
1214 uint32_t trust_flags;
1215 enum netr_SchannelType secure_channel_type;
1217 trust_flags = NETR_TRUST_FLAG_OUTBOUND;
1218 if (role != ROLE_DOMAIN_MEMBER) {
1219 trust_flags |= NETR_TRUST_FLAG_PRIMARY;
1222 if (role > ROLE_DOMAIN_MEMBER) {
1223 secure_channel_type = SEC_CHAN_BDC;
1224 } else {
1225 secure_channel_type = SEC_CHAN_LOCAL;
1228 if ((pdb_domain_info != NULL) && (role == ROLE_IPA_DC)) {
1229 /* This is IPA DC that presents itself as
1230 * an Active Directory domain controller to trusted AD
1231 * forests but in fact is a classic domain controller.
1233 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1234 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1235 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1236 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1237 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1238 status = add_trusted_domain(pdb_domain_info->name,
1239 pdb_domain_info->dns_domain,
1240 &pdb_domain_info->sid,
1241 LSA_TRUST_TYPE_UPLEVEL,
1242 trust_flags,
1243 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1244 secure_channel_type,
1245 NULL,
1246 &domain);
1247 TALLOC_FREE(pdb_domain_info);
1248 } else {
1249 status = add_trusted_domain(get_global_sam_name(),
1250 NULL,
1251 get_global_sam_sid(),
1252 LSA_TRUST_TYPE_DOWNLEVEL,
1253 trust_flags,
1254 0, /* trust_attribs */
1255 secure_channel_type,
1256 NULL,
1257 &domain);
1259 if (!NT_STATUS_IS_OK(status)) {
1260 DBG_ERR("Failed to add local SAM to "
1261 "domain to winbindd's internal list\n");
1262 return false;
1266 if (IS_DC) {
1267 ok = add_trusted_domains_dc();
1268 if (!ok) {
1269 DBG_ERR("init_domain_list_dc failed\n");
1270 return false;
1274 if ( role == ROLE_DOMAIN_MEMBER ) {
1275 struct dom_sid our_sid;
1276 uint32_t trust_type;
1278 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
1279 DEBUG(0, ("Could not fetch our SID - did we join?\n"));
1280 return False;
1283 if (lp_realm() != NULL) {
1284 trust_type = LSA_TRUST_TYPE_UPLEVEL;
1285 } else {
1286 trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1289 status = add_trusted_domain(lp_workgroup(),
1290 lp_realm(),
1291 &our_sid,
1292 trust_type,
1293 NETR_TRUST_FLAG_PRIMARY|
1294 NETR_TRUST_FLAG_OUTBOUND,
1295 0, /* trust_attribs */
1296 SEC_CHAN_WKSTA,
1297 NULL,
1298 &domain);
1299 if (!NT_STATUS_IS_OK(status)) {
1300 DBG_ERR("Failed to add local SAM to "
1301 "domain to winbindd's internal list\n");
1302 return false;
1306 status = imessaging_register(winbind_imessaging_context(), NULL,
1307 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1308 wb_imsg_new_trusted_domain);
1309 if (!NT_STATUS_IS_OK(status)) {
1310 DBG_ERR("imessaging_register failed %s\n", nt_errstr(status));
1311 return false;
1314 return True;
1318 * Given a domain name, return the struct winbindd domain info for it
1320 * @note Do *not* pass lp_workgroup() to this function. domain_list
1321 * may modify it's value, and free that pointer. Instead, our local
1322 * domain may be found by calling find_our_domain().
1323 * directly.
1326 * @return The domain structure for the named domain, if it is working.
1329 struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
1331 struct winbindd_domain *domain;
1333 /* Search through list */
1335 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1336 if (strequal(domain_name, domain->name)) {
1337 return domain;
1339 if (domain->alt_name == NULL) {
1340 continue;
1342 if (strequal(domain_name, domain->alt_name)) {
1343 return domain;
1347 /* Not found */
1349 return NULL;
1353 * Given a domain name, return the struct winbindd domain if it's a direct
1354 * outgoing trust
1356 * @return The domain structure for the named domain, if it is a direct outgoing trust
1358 struct winbindd_domain *find_trust_from_name_noinit(const char *domain_name)
1360 struct winbindd_domain *domain = NULL;
1362 domain = find_domain_from_name_noinit(domain_name);
1363 if (domain == NULL) {
1364 return NULL;
1367 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1368 return domain;
1371 return NULL;
1374 struct winbindd_domain *find_domain_from_name(const char *domain_name)
1376 struct winbindd_domain *domain;
1378 domain = find_domain_from_name_noinit(domain_name);
1380 if (domain == NULL)
1381 return NULL;
1383 if (!domain->initialized)
1384 init_dc_connection(domain, false);
1386 return domain;
1389 /* Given a domain sid, return the struct winbindd domain info for it */
1391 struct winbindd_domain *find_domain_from_sid_noinit(const struct dom_sid *sid)
1393 struct winbindd_domain *domain;
1395 /* Search through list */
1397 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1398 if (dom_sid_compare_domain(sid, &domain->sid) == 0)
1399 return domain;
1402 /* Not found */
1404 return NULL;
1408 * Given a domain sid, return the struct winbindd domain if it's a direct
1409 * outgoing trust
1411 * @return The domain structure for the specified domain, if it is a direct outgoing trust
1413 struct winbindd_domain *find_trust_from_sid_noinit(const struct dom_sid *sid)
1415 struct winbindd_domain *domain = NULL;
1417 domain = find_domain_from_sid_noinit(sid);
1418 if (domain == NULL) {
1419 return NULL;
1422 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1423 return domain;
1426 return NULL;
1429 /* Given a domain sid, return the struct winbindd domain info for it */
1431 struct winbindd_domain *find_domain_from_sid(const struct dom_sid *sid)
1433 struct winbindd_domain *domain;
1435 domain = find_domain_from_sid_noinit(sid);
1437 if (domain == NULL)
1438 return NULL;
1440 if (!domain->initialized)
1441 init_dc_connection(domain, false);
1443 return domain;
1446 struct winbindd_domain *find_our_domain(void)
1448 struct winbindd_domain *domain;
1450 /* Search through list */
1452 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1453 if (domain->primary)
1454 return domain;
1457 smb_panic("Could not find our domain");
1458 return NULL;
1461 struct winbindd_domain *find_default_route_domain(void)
1463 if (!IS_DC) {
1464 return find_our_domain();
1466 DBG_DEBUG("Routing logic not yet implemented on a DC\n");
1467 return NULL;
1470 /* Find the appropriate domain to lookup a name or SID */
1472 struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)
1474 struct dom_sid_buf buf;
1476 DBG_DEBUG("SID [%s]\n", dom_sid_str_buf(sid, &buf));
1479 * SIDs in the S-1-22-{1,2} domain and well-known SIDs should be handled
1480 * by our passdb.
1483 if ( sid_check_is_in_unix_groups(sid) ||
1484 sid_check_is_unix_groups(sid) ||
1485 sid_check_is_in_unix_users(sid) ||
1486 sid_check_is_unix_users(sid) ||
1487 sid_check_is_our_sam(sid) ||
1488 sid_check_is_in_our_sam(sid) )
1490 return find_domain_from_sid(get_global_sam_sid());
1493 if ( sid_check_is_builtin(sid) ||
1494 sid_check_is_in_builtin(sid) ||
1495 sid_check_is_wellknown_domain(sid, NULL) ||
1496 sid_check_is_in_wellknown_domain(sid) )
1498 return find_domain_from_sid(&global_sid_Builtin);
1501 if (IS_DC) {
1502 struct winbindd_domain *domain = NULL;
1504 domain = find_domain_from_sid_noinit(sid);
1505 if (domain == NULL) {
1506 return NULL;
1509 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1510 return domain;
1513 return domain->routing_domain;
1516 /* On a member server a query for SID or name can always go to our
1517 * primary DC. */
1519 DEBUG(10, ("calling find_our_domain\n"));
1520 return find_our_domain();
1523 struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
1525 bool predefined;
1527 if ( strequal(domain_name, unix_users_domain_name() ) ||
1528 strequal(domain_name, unix_groups_domain_name() ) )
1531 * The "Unix User" and "Unix Group" domain are handled by
1532 * passdb
1534 return find_domain_from_name_noinit( get_global_sam_name() );
1537 if (strequal(domain_name, "BUILTIN") ||
1538 strequal(domain_name, get_global_sam_name())) {
1539 return find_domain_from_name_noinit(domain_name);
1542 predefined = dom_sid_lookup_is_predefined_domain(domain_name);
1543 if (predefined) {
1544 return find_domain_from_name_noinit(builtin_domain_name());
1547 if (IS_DC) {
1548 struct winbindd_domain *domain = NULL;
1550 domain = find_domain_from_name_noinit(domain_name);
1551 if (domain == NULL) {
1552 return NULL;
1555 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1556 return domain;
1559 return domain->routing_domain;
1562 return find_our_domain();
1565 /* Is this a domain which we may assume no DOMAIN\ prefix? */
1567 static bool assume_domain(const char *domain)
1569 /* never assume the domain on a standalone server */
1571 if ( lp_server_role() == ROLE_STANDALONE )
1572 return False;
1574 /* domain member servers may possibly assume for the domain name */
1576 if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
1577 if ( !strequal(lp_workgroup(), domain) )
1578 return False;
1580 if ( lp_winbind_use_default_domain() )
1581 return True;
1584 /* only left with a domain controller */
1586 if ( strequal(get_global_sam_name(), domain) ) {
1587 return True;
1590 return False;
1593 /* Parse a DOMAIN\user or UPN string into a domain, namespace and a user */
1594 bool parse_domain_user(const char *domuser,
1595 fstring namespace,
1596 fstring domain,
1597 fstring user)
1599 char *p = NULL;
1601 if (strlen(domuser) == 0) {
1602 return false;
1605 p = strchr(domuser, *lp_winbind_separator());
1606 if (p != NULL) {
1607 fstrcpy(user, p + 1);
1608 fstrcpy(domain, domuser);
1609 domain[PTR_DIFF(p, domuser)] = '\0';
1610 fstrcpy(namespace, domain);
1611 } else {
1612 fstrcpy(user, domuser);
1614 domain[0] = '\0';
1615 namespace[0] = '\0';
1616 p = strchr(domuser, '@');
1617 if (p != NULL) {
1618 /* upn */
1619 fstrcpy(namespace, p + 1);
1620 } else if (assume_domain(lp_workgroup())) {
1621 fstrcpy(domain, lp_workgroup());
1622 fstrcpy(namespace, domain);
1623 } else {
1624 fstrcpy(namespace, lp_netbios_name());
1628 return strupper_m(domain);
1631 /* Ensure an incoming username from NSS is fully qualified. Replace the
1632 incoming fstring with DOMAIN <separator> user. Returns the same
1633 values as parse_domain_user() but also replaces the incoming username.
1634 Used to ensure all names are fully qualified within winbindd.
1635 Used by the NSS protocols of auth, chauthtok, logoff and ccache_ntlm_auth.
1636 The protocol definitions of auth_crap, chng_pswd_auth_crap
1637 really should be changed to use this instead of doing things
1638 by hand. JRA. */
1640 bool canonicalize_username(fstring username_inout,
1641 fstring namespace,
1642 fstring domain,
1643 fstring user)
1645 bool ok;
1647 ok = parse_domain_user(username_inout, namespace, domain, user);
1648 if (!ok) {
1649 return False;
1651 slprintf(username_inout, sizeof(fstring) - 1, "%s%c%s",
1652 domain, *lp_winbind_separator(),
1653 user);
1654 return True;
1658 Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
1659 'winbind separator' options.
1660 This means:
1661 - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
1662 lp_workgroup()
1664 If we are a PDC or BDC, and this is for our domain, do likewise.
1666 On an AD DC we always fill DOMAIN\\USERNAME.
1668 We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1671 * talloc version of fill_domain_username()
1672 * return NULL on talloc failure.
1674 char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
1675 const char *domain,
1676 const char *user,
1677 bool can_assume)
1679 char *tmp_user, *name;
1681 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1682 can_assume = false;
1685 if (user == NULL) {
1686 return NULL;
1689 tmp_user = talloc_strdup(mem_ctx, user);
1690 if (tmp_user == NULL) {
1691 return NULL;
1693 if (!strlower_m(tmp_user)) {
1694 TALLOC_FREE(tmp_user);
1695 return NULL;
1698 if (can_assume && assume_domain(domain)) {
1699 name = tmp_user;
1700 } else {
1701 name = talloc_asprintf(mem_ctx, "%s%c%s",
1702 domain,
1703 *lp_winbind_separator(),
1704 tmp_user);
1705 TALLOC_FREE(tmp_user);
1708 return name;
1712 * Client list accessor functions
1715 static struct winbindd_cli_state *_client_list;
1716 static int _num_clients;
1718 /* Return list of all connected clients */
1720 struct winbindd_cli_state *winbindd_client_list(void)
1722 return _client_list;
1725 /* Return list-tail of all connected clients */
1727 struct winbindd_cli_state *winbindd_client_list_tail(void)
1729 return DLIST_TAIL(_client_list);
1732 /* Return previous (read:newer) client in list */
1734 struct winbindd_cli_state *
1735 winbindd_client_list_prev(struct winbindd_cli_state *cli)
1737 return DLIST_PREV(cli);
1740 /* Add a connection to the list */
1742 void winbindd_add_client(struct winbindd_cli_state *cli)
1744 cli->last_access = time(NULL);
1745 DLIST_ADD(_client_list, cli);
1746 _num_clients++;
1749 /* Remove a client from the list */
1751 void winbindd_remove_client(struct winbindd_cli_state *cli)
1753 DLIST_REMOVE(_client_list, cli);
1754 _num_clients--;
1757 /* Move a client to head or list */
1759 void winbindd_promote_client(struct winbindd_cli_state *cli)
1761 cli->last_access = time(NULL);
1762 DLIST_PROMOTE(_client_list, cli);
1765 /* Return number of open clients */
1767 int winbindd_num_clients(void)
1769 return _num_clients;
1772 NTSTATUS lookup_usergroups_cached(TALLOC_CTX *mem_ctx,
1773 const struct dom_sid *user_sid,
1774 uint32_t *p_num_groups, struct dom_sid **user_sids)
1776 struct netr_SamInfo3 *info3 = NULL;
1777 NTSTATUS status = NT_STATUS_NO_MEMORY;
1778 uint32_t num_groups = 0;
1780 DEBUG(3,(": lookup_usergroups_cached\n"));
1782 *user_sids = NULL;
1783 *p_num_groups = 0;
1785 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1787 if (info3 == NULL) {
1788 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1792 * Before bug #7843 the "Domain Local" groups were added with a
1793 * lookupuseraliases call, but this isn't done anymore for our domain
1794 * so we need to resolve resource groups here.
1796 * When to use Resource Groups:
1797 * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
1799 status = sid_array_from_info3(mem_ctx, info3,
1800 user_sids,
1801 &num_groups,
1802 false);
1804 if (!NT_STATUS_IS_OK(status)) {
1805 TALLOC_FREE(info3);
1806 return status;
1809 TALLOC_FREE(info3);
1810 *p_num_groups = num_groups;
1811 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1813 DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1815 return status;
1818 /*********************************************************************
1819 We use this to remove spaces from user and group names
1820 ********************************************************************/
1822 NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
1823 const char *domain_name,
1824 const char *name,
1825 char **normalized)
1827 struct winbindd_domain *domain = NULL;
1828 NTSTATUS nt_status;
1830 if (!name || !normalized) {
1831 return NT_STATUS_INVALID_PARAMETER;
1834 if (!lp_winbind_normalize_names()) {
1835 return NT_STATUS_PROCEDURE_NOT_FOUND;
1838 domain = find_domain_from_name_noinit(domain_name);
1839 if (domain == NULL) {
1840 DBG_ERR("Failed to find domain '%s'\n", domain_name);
1841 return NT_STATUS_NO_SUCH_DOMAIN;
1844 /* Alias support and whitespace replacement are mutually
1845 exclusive */
1847 nt_status = resolve_username_to_alias(mem_ctx, domain,
1848 name, normalized );
1849 if (NT_STATUS_IS_OK(nt_status)) {
1850 /* special return code to let the caller know we
1851 mapped to an alias */
1852 return NT_STATUS_FILE_RENAMED;
1855 /* check for an unreachable domain */
1857 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1858 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1859 domain->name));
1860 set_domain_offline(domain);
1861 return nt_status;
1864 /* deal with whitespace */
1866 *normalized = talloc_strdup(mem_ctx, name);
1867 if (!(*normalized)) {
1868 return NT_STATUS_NO_MEMORY;
1871 all_string_sub( *normalized, " ", "_", 0 );
1873 return NT_STATUS_OK;
1876 /*********************************************************************
1877 We use this to do the inverse of normalize_name_map()
1878 ********************************************************************/
1880 NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
1881 const char *name,
1882 char **normalized)
1884 NTSTATUS nt_status;
1885 struct winbindd_domain *domain = find_our_domain();
1887 if (!name || !normalized) {
1888 return NT_STATUS_INVALID_PARAMETER;
1891 if (!lp_winbind_normalize_names()) {
1892 return NT_STATUS_PROCEDURE_NOT_FOUND;
1895 /* Alias support and whitespace replacement are mutally
1896 exclusive */
1898 /* When mapping from an alias to a username, we don't know the
1899 domain. But we only need a domain structure to cache
1900 a successful lookup , so just our own domain structure for
1901 the seqnum. */
1903 nt_status = resolve_alias_to_username(mem_ctx, domain,
1904 name, normalized);
1905 if (NT_STATUS_IS_OK(nt_status)) {
1906 /* Special return code to let the caller know we mapped
1907 from an alias */
1908 return NT_STATUS_FILE_RENAMED;
1911 /* check for an unreachable domain */
1913 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1914 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1915 domain->name));
1916 set_domain_offline(domain);
1917 return nt_status;
1920 /* deal with whitespace */
1922 *normalized = talloc_strdup(mem_ctx, name);
1923 if (!(*normalized)) {
1924 return NT_STATUS_NO_MEMORY;
1927 all_string_sub(*normalized, "_", " ", 0);
1929 return NT_STATUS_OK;
1932 /*********************************************************************
1933 ********************************************************************/
1935 bool winbindd_can_contact_domain(struct winbindd_domain *domain)
1937 struct winbindd_tdc_domain *tdc = NULL;
1938 TALLOC_CTX *frame = talloc_stackframe();
1939 bool ret = false;
1941 /* We can contact the domain if it is our primary domain */
1943 if (domain->primary) {
1944 ret = true;
1945 goto done;
1948 /* Trust the TDC cache and not the winbindd_domain flags */
1950 if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
1951 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
1952 domain->name));
1953 ret = false;
1954 goto done;
1957 /* Can always contact a domain that is in out forest */
1959 if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1960 ret = true;
1961 goto done;
1965 * On a _member_ server, we cannot contact the domain if it
1966 * is running AD and we have no inbound trust.
1969 if (!IS_DC &&
1970 domain->active_directory &&
1971 ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
1973 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
1974 "and we have no inbound trust.\n", domain->name));
1975 goto done;
1978 /* Assume everything else is ok (probably not true but what
1979 can you do?) */
1981 ret = true;
1983 done:
1984 talloc_destroy(frame);
1986 return ret;
1989 #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
1991 /*********************************************************************
1992 ********************************************************************/
1994 static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
1996 char *var = NULL;
1997 char addr[INET6_ADDRSTRLEN];
1998 const char *kdc = NULL;
1999 int lvl = 11;
2001 if (!domain || !domain->alt_name || !*domain->alt_name) {
2002 return;
2005 if (domain->initialized && !domain->active_directory) {
2006 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
2007 domain->alt_name));
2008 return;
2011 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
2012 kdc = addr;
2013 if (!*kdc) {
2014 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
2015 domain->alt_name));
2016 kdc = domain->dcname;
2019 if (!kdc || !*kdc) {
2020 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
2021 domain->alt_name));
2022 return;
2025 var = talloc_asprintf_strupper_m(
2026 talloc_tos(),
2027 "%s_%s",
2028 WINBINDD_LOCATOR_KDC_ADDRESS,
2029 domain->alt_name);
2030 if (var == NULL) {
2031 return;
2034 DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
2035 var, kdc));
2037 setenv(var, kdc, 1);
2038 TALLOC_FREE(var);
2041 /*********************************************************************
2042 ********************************************************************/
2044 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2046 struct winbindd_domain *our_dom = find_our_domain();
2048 winbindd_set_locator_kdc_env(domain);
2050 if (domain != our_dom) {
2051 winbindd_set_locator_kdc_env(our_dom);
2055 /*********************************************************************
2056 ********************************************************************/
2058 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2060 char *var = NULL;
2062 if (!domain || !domain->alt_name || !*domain->alt_name) {
2063 return;
2066 var = talloc_asprintf_strupper_m(
2067 talloc_tos(),
2068 "%s_%s",
2069 WINBINDD_LOCATOR_KDC_ADDRESS,
2070 domain->alt_name);
2071 if (var == NULL) {
2072 return;
2075 unsetenv(var);
2076 TALLOC_FREE(var);
2078 #else
2080 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2082 return;
2085 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2087 return;
2090 #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
2092 void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
2095 * Make sure we start with authoritative=true,
2096 * it will only set to false if we don't know the
2097 * domain.
2099 resp->data.auth.authoritative = true;
2101 resp->data.auth.nt_status = NT_STATUS_V(result);
2102 fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
2104 /* we might have given a more useful error above */
2105 if (*resp->data.auth.error_string == '\0')
2106 fstrcpy(resp->data.auth.error_string,
2107 get_friendly_nt_error_msg(result));
2108 resp->data.auth.pam_error = nt_status_to_pam(result);
2111 bool is_domain_offline(const struct winbindd_domain *domain)
2113 if (get_global_winbindd_state_offline()) {
2114 return true;
2116 return !domain->online;
2119 bool is_domain_online(const struct winbindd_domain *domain)
2121 return !is_domain_offline(domain);
2125 * Parse an char array into a list of sids.
2127 * The input sidstr should consist of 0-terminated strings
2128 * representing sids, separated by newline characters '\n'.
2129 * The list is terminated by an empty string, i.e.
2130 * character '\0' directly following a character '\n'
2131 * (or '\0' right at the start of sidstr).
2133 bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
2134 struct dom_sid **sids, uint32_t *num_sids)
2136 const char *p;
2138 p = sidstr;
2139 if (p == NULL)
2140 return False;
2142 while (p[0] != '\0') {
2143 struct dom_sid sid;
2144 const char *q = NULL;
2146 if (!dom_sid_parse_endp(p, &sid, &q)) {
2147 DEBUG(1, ("Could not parse sid %s\n", p));
2148 return false;
2150 if (q[0] != '\n') {
2151 DEBUG(1, ("Got invalid sidstr: %s\n", p));
2152 return false;
2154 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
2155 num_sids)))
2157 return False;
2159 p = q+1;
2161 return True;
2164 bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
2165 struct unixid **pxids, uint32_t *pnum_xids)
2167 const char *p;
2168 struct unixid *xids = NULL;
2169 uint32_t num_xids = 0;
2171 p = xidstr;
2172 if (p == NULL) {
2173 return false;
2176 while (p[0] != '\0') {
2177 struct unixid *tmp;
2178 struct unixid xid;
2179 unsigned long long id;
2180 char *endp;
2181 int error = 0;
2183 switch (p[0]) {
2184 case 'U':
2185 xid = (struct unixid) { .type = ID_TYPE_UID };
2186 break;
2187 case 'G':
2188 xid = (struct unixid) { .type = ID_TYPE_GID };
2189 break;
2190 default:
2191 return false;
2194 p += 1;
2196 id = smb_strtoull(p, &endp, 10, &error, SMB_STR_STANDARD);
2197 if (error != 0) {
2198 goto fail;
2200 if (*endp != '\n') {
2201 goto fail;
2203 p = endp+1;
2205 xid.id = id;
2206 if ((unsigned long long)xid.id != id) {
2207 goto fail;
2210 tmp = talloc_realloc(mem_ctx, xids, struct unixid, num_xids+1);
2211 if (tmp == NULL) {
2212 return 0;
2214 xids = tmp;
2216 xids[num_xids] = xid;
2217 num_xids += 1;
2220 *pxids = xids;
2221 *pnum_xids = num_xids;
2222 return true;
2224 fail:
2225 TALLOC_FREE(xids);
2226 return false;