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/>.
25 #include "lib/util_unixsids.h"
27 #include "../libcli/security/security.h"
28 #include "../libcli/auth/pam_errors.h"
29 #include "passdb/machine_sid.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"
42 #define DBGC_CLASS DBGC_WINBIND
45 * @file winbindd_util.c
47 * Winbind daemon for NT domain authentication nss module.
50 /* The list of trusted domains. Note that the list can be deleted and
51 recreated using the init_domain_list() function so pointers to
52 individual winbindd_domain structures cannot be made. Keep a copy of
53 the domain name instead. */
55 static struct winbindd_domain *_domain_list = NULL;
57 struct winbindd_domain *domain_list(void)
61 if ((!_domain_list) && (!init_domain_list())) {
62 smb_panic("Init_domain_list failed");
68 /* Free all entries in the trusted domain list */
70 static void free_domain_list(void)
72 struct winbindd_domain *domain = _domain_list;
75 struct winbindd_domain *next = domain->next;
77 DLIST_REMOVE(_domain_list, domain);
84 * Iterator for winbindd's domain list.
85 * To be used (e.g.) in tevent based loops.
87 struct winbindd_domain *wb_next_domain(struct winbindd_domain *domain)
90 domain = domain_list();
92 domain = domain->next;
95 if ((domain != NULL) &&
96 (lp_server_role() != ROLE_ACTIVE_DIRECTORY_DC) &&
97 sid_check_is_our_sam(&domain->sid))
99 domain = domain->next;
105 static bool is_internal_domain(const struct dom_sid *sid)
110 return (sid_check_is_our_sam(sid) || sid_check_is_builtin(sid));
113 /* Add a trusted domain to our list of domains.
114 If the domain already exists in the list,
115 return it and don't re-initialize. */
117 static NTSTATUS add_trusted_domain(const char *domain_name,
118 const char *dns_name,
119 const struct dom_sid *sid,
121 uint32_t trust_flags,
122 uint32_t trust_attribs,
123 enum netr_SchannelType secure_channel_type,
124 struct winbindd_domain *routing_domain,
125 struct winbindd_domain **_d)
127 struct winbindd_domain *domain = NULL;
128 int role = lp_server_role();
129 struct dom_sid_buf buf;
131 if (is_null_sid(sid)) {
132 DBG_ERR("Got null SID for domain [%s]\n", domain_name);
133 return NT_STATUS_INVALID_PARAMETER;
136 if (secure_channel_type == SEC_CHAN_NULL && !is_allowed_domain(domain_name)) {
137 return NT_STATUS_NO_SUCH_DOMAIN;
141 * We can't call domain_list() as this function is called from
142 * init_domain_list() and we'll get stuck in a loop.
144 for (domain = _domain_list; domain; domain = domain->next) {
145 if (strequal(domain_name, domain->name)) {
150 if (domain != NULL) {
151 struct winbindd_domain *check_domain = NULL;
153 for (check_domain = _domain_list;
154 check_domain != NULL;
155 check_domain = check_domain->next)
157 if (check_domain == domain) {
161 if (dom_sid_equal(&check_domain->sid, sid)) {
166 if (check_domain != NULL) {
167 DBG_ERR("SID [%s] already used by domain [%s], "
169 dom_sid_str_buf(sid, &buf),
172 return NT_STATUS_INVALID_PARAMETER;
176 if ((domain != NULL) && (dns_name != NULL)) {
177 struct winbindd_domain *check_domain = NULL;
179 for (check_domain = _domain_list;
180 check_domain != NULL;
181 check_domain = check_domain->next)
183 if (check_domain == domain) {
187 if (strequal(check_domain->alt_name, dns_name)) {
192 if (check_domain != NULL) {
193 DBG_ERR("DNS name [%s] used by domain [%s], "
195 dns_name, check_domain->name,
197 return NT_STATUS_INVALID_PARAMETER;
201 if (domain != NULL) {
206 /* Create new domain entry */
207 domain = talloc_zero(NULL, struct winbindd_domain);
208 if (domain == NULL) {
209 return NT_STATUS_NO_MEMORY;
212 domain->children = talloc_zero_array(domain,
213 struct winbindd_child,
214 lp_winbind_max_domain_connections());
215 if (domain->children == NULL) {
217 return NT_STATUS_NO_MEMORY;
220 domain->queue = tevent_queue_create(domain, "winbind_domain");
221 if (domain->queue == NULL) {
223 return NT_STATUS_NO_MEMORY;
226 domain->binding_handle = wbint_binding_handle(domain, domain, NULL);
227 if (domain->binding_handle == NULL) {
229 return NT_STATUS_NO_MEMORY;
232 domain->name = talloc_strdup(domain, domain_name);
233 if (domain->name == NULL) {
235 return NT_STATUS_NO_MEMORY;
238 if (dns_name != NULL) {
239 domain->alt_name = talloc_strdup(domain, dns_name);
240 if (domain->alt_name == NULL) {
242 return NT_STATUS_NO_MEMORY;
246 domain->backend = NULL;
247 domain->internal = is_internal_domain(sid);
248 domain->secure_channel_type = secure_channel_type;
249 domain->sequence_number = DOM_SEQUENCE_NONE;
250 domain->last_seq_check = 0;
251 domain->initialized = false;
252 domain->online = is_internal_domain(sid);
253 domain->domain_flags = trust_flags;
254 domain->domain_type = trust_type;
255 domain->domain_trust_attribs = trust_attribs;
256 domain->secure_channel_type = secure_channel_type;
257 domain->routing_domain = routing_domain;
258 sid_copy(&domain->sid, sid);
260 /* Is this our primary domain ? */
261 if (role == ROLE_DOMAIN_MEMBER) {
262 domain->primary = strequal(domain_name, lp_workgroup());
264 domain->primary = strequal(domain_name, get_global_sam_name());
267 if (domain->primary) {
268 if (role == ROLE_ACTIVE_DIRECTORY_DC) {
269 domain->active_directory = true;
271 if (lp_security() == SEC_ADS) {
272 domain->active_directory = true;
274 } else if (!domain->internal) {
275 if (domain->domain_type == LSA_TRUST_TYPE_UPLEVEL) {
276 domain->active_directory = true;
280 domain->can_do_ncacn_ip_tcp = domain->active_directory;
282 /* Link to domain list */
283 DLIST_ADD_END(_domain_list, domain);
285 wcache_tdc_add_domain( domain );
287 setup_domain_child(domain);
289 DBG_NOTICE("Added domain [%s] [%s] [%s]\n",
290 domain->name, domain->alt_name,
291 dom_sid_str_buf(&domain->sid, &buf));
297 bool set_routing_domain(struct winbindd_domain *domain,
298 struct winbindd_domain *routing_domain)
300 if (domain->routing_domain == NULL) {
301 domain->routing_domain = routing_domain;
304 if (domain->routing_domain != routing_domain) {
310 bool add_trusted_domain_from_auth(uint16_t validation_level,
311 struct info3_text *info3,
312 struct info6_text *info6)
314 struct winbindd_domain *domain = NULL;
315 struct dom_sid domain_sid;
316 const char *dns_domainname = NULL;
321 * We got a successful auth from a domain that might not yet be in our
322 * domain list. If we're a member we trust our DC who authenticated the
323 * user from that domain and add the domain to our list on-the-fly. If
324 * we're a DC we rely on configured trusts and don't add on-the-fly.
331 ok = dom_sid_parse(info3->dom_sid, &domain_sid);
333 DBG_NOTICE("dom_sid_parse [%s] failed\n", info3->dom_sid);
337 if (validation_level == 6) {
338 if (!strequal(info6->dns_domainname, "")) {
339 dns_domainname = info6->dns_domainname;
343 status = add_trusted_domain(info3->logon_dom,
347 NETR_TRUST_FLAG_OUTBOUND,
350 find_default_route_domain(),
352 if (!NT_STATUS_IS_OK(status) &&
353 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
355 DBG_DEBUG("Adding domain [%s] with sid [%s] failed\n",
356 info3->logon_dom, info3->dom_sid);
363 bool domain_is_forest_root(const struct winbindd_domain *domain)
365 const uint32_t fr_flags =
366 (NETR_TRUST_FLAG_TREEROOT|NETR_TRUST_FLAG_IN_FOREST);
368 return ((domain->domain_flags & fr_flags) == fr_flags);
371 /********************************************************************
372 rescan our domains looking for new trusted domains
373 ********************************************************************/
375 struct trustdom_state {
376 struct winbindd_domain *domain;
377 struct netr_DomainTrustList trusts;
380 static void trustdom_list_done(struct tevent_req *req);
381 static void rescan_forest_root_trusts( void );
382 static void rescan_forest_trusts( void );
384 static void add_trusted_domains( struct winbindd_domain *domain )
386 struct tevent_context *ev = global_event_context();
387 struct trustdom_state *state;
388 struct tevent_req *req;
389 const char *client_name = NULL;
392 state = talloc_zero(NULL, struct trustdom_state);
394 DEBUG(0, ("talloc failed\n"));
397 state->domain = domain;
399 /* Called from timer, not from a real client */
400 client_name = getprogname();
401 client_pid = getpid();
403 req = dcerpc_wbint_ListTrustedDomains_send(state,
405 dom_child_handle(domain),
410 DBG_ERR("dcerpc_wbint_ListTrustedDomains_send failed\n");
414 tevent_req_set_callback(req, trustdom_list_done, state);
417 static void trustdom_list_done(struct tevent_req *req)
419 struct trustdom_state *state = tevent_req_callback_data(
420 req, struct trustdom_state);
421 bool within_forest = false;
422 NTSTATUS status, result;
426 * Only when we enumerate our primary domain
427 * or our forest root domain, we should keep
428 * the NETR_TRUST_FLAG_IN_FOREST flag, in
429 * all other cases we need to clear it as the domain
430 * is not part of our forest.
432 if (state->domain->primary) {
433 within_forest = true;
434 } else if (domain_is_forest_root(state->domain)) {
435 within_forest = true;
438 status = dcerpc_wbint_ListTrustedDomains_recv(req, state, &result);
439 if (any_nt_status_not_ok(status, result, &status)) {
440 DBG_WARNING("Could not receive trusts for domain %s: %s-%s\n",
441 state->domain->name, nt_errstr(status),
447 for (i=0; i<state->trusts.count; i++) {
448 struct netr_DomainTrust *trust = &state->trusts.array[i];
449 struct winbindd_domain *domain = NULL;
451 if (!within_forest) {
452 trust->trust_flags &= ~NETR_TRUST_FLAG_IN_FOREST;
455 if (!state->domain->primary) {
456 trust->trust_flags &= ~NETR_TRUST_FLAG_PRIMARY;
460 * We always call add_trusted_domain() cause on an existing
461 * domain structure, it will update the SID if necessary.
462 * This is important because we need the SID for sibling
465 status = add_trusted_domain(trust->netbios_name,
470 trust->trust_attributes,
472 find_default_route_domain(),
474 if (!NT_STATUS_IS_OK(status) &&
475 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
477 DBG_NOTICE("add_trusted_domain returned %s\n",
484 Cases to consider when scanning trusts:
485 (a) we are calling from a child domain (primary && !forest_root)
486 (b) we are calling from the root of the forest (primary && forest_root)
487 (c) we are calling from a trusted forest domain (!primary
491 if (state->domain->primary) {
492 /* If this is our primary domain and we are not in the
493 forest root, we have to scan the root trusts first */
495 if (!domain_is_forest_root(state->domain))
496 rescan_forest_root_trusts();
498 rescan_forest_trusts();
500 } else if (domain_is_forest_root(state->domain)) {
501 /* Once we have done root forest trust search, we can
502 go on to search the trusted forests */
504 rescan_forest_trusts();
512 /********************************************************************
513 Scan the trusts of our forest root
514 ********************************************************************/
516 static void rescan_forest_root_trusts( void )
518 struct winbindd_tdc_domain *dom_list = NULL;
519 size_t num_trusts = 0;
523 /* The only transitive trusts supported by Windows 2003 AD are
524 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
525 first two are handled in forest and listed by
526 DsEnumerateDomainTrusts(). Forest trusts are not so we
527 have to do that ourselves. */
529 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
532 for ( i=0; i<num_trusts; i++ ) {
533 struct winbindd_domain *d = NULL;
535 /* Find the forest root. Don't necessarily trust
536 the domain_list() as our primary domain may not
537 have been initialized. */
539 if ( !(dom_list[i].trust_flags & NETR_TRUST_FLAG_TREEROOT) ) {
543 /* Here's the forest root */
545 d = find_domain_from_name_noinit( dom_list[i].domain_name );
547 status = add_trusted_domain(dom_list[i].domain_name,
548 dom_list[i].dns_name,
550 dom_list[i].trust_type,
551 dom_list[i].trust_flags,
552 dom_list[i].trust_attribs,
554 find_default_route_domain(),
557 if (!NT_STATUS_IS_OK(status) &&
558 NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
560 DBG_ERR("add_trusted_domain returned %s\n",
569 DEBUG(10,("rescan_forest_root_trusts: Following trust path "
570 "for domain tree root %s (%s)\n",
571 d->name, d->alt_name ));
573 d->domain_flags = dom_list[i].trust_flags;
574 d->domain_type = dom_list[i].trust_type;
575 d->domain_trust_attribs = dom_list[i].trust_attribs;
577 add_trusted_domains( d );
582 TALLOC_FREE( dom_list );
587 /********************************************************************
588 scan the transitive forest trusts (not our own)
589 ********************************************************************/
592 static void rescan_forest_trusts( void )
594 struct winbindd_domain *d = NULL;
595 struct winbindd_tdc_domain *dom_list = NULL;
596 size_t num_trusts = 0;
600 /* The only transitive trusts supported by Windows 2003 AD are
601 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
602 first two are handled in forest and listed by
603 DsEnumerateDomainTrusts(). Forest trusts are not so we
604 have to do that ourselves. */
606 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
609 for ( i=0; i<num_trusts; i++ ) {
610 uint32_t flags = dom_list[i].trust_flags;
611 uint32_t type = dom_list[i].trust_type;
612 uint32_t attribs = dom_list[i].trust_attribs;
614 d = find_domain_from_name_noinit( dom_list[i].domain_name );
616 /* ignore our primary and internal domains */
618 if ( d && (d->internal || d->primary ) )
621 if ( (flags & NETR_TRUST_FLAG_INBOUND) &&
622 (type == LSA_TRUST_TYPE_UPLEVEL) &&
623 (attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) )
625 /* add the trusted domain if we don't know
629 status = add_trusted_domain(
630 dom_list[i].domain_name,
631 dom_list[i].dns_name,
637 find_default_route_domain(),
639 if (!NT_STATUS_IS_OK(status) &&
640 NT_STATUS_EQUAL(status,
641 NT_STATUS_NO_SUCH_DOMAIN))
643 DBG_ERR("add_trusted_domain: %s\n",
653 DEBUG(10,("Following trust path for domain %s (%s)\n",
654 d->name, d->alt_name ));
655 add_trusted_domains( d );
659 TALLOC_FREE( dom_list );
664 /*********************************************************************
665 The process of updating the trusted domain list is a three step
668 (b) ask the root domain in our forest
669 (c) ask a DC in any Win2003 trusted forests
670 *********************************************************************/
672 void rescan_trusted_domains(struct tevent_context *ev, struct tevent_timer *te,
673 struct timeval now, void *private_data)
677 /* I used to clear the cache here and start over but that
678 caused problems in child processes that needed the
679 trust dom list early on. Removing it means we
680 could have some trusted domains listed that have been
681 removed from our primary domain's DC until a full
682 restart. This should be ok since I think this is what
683 Windows does as well. */
685 /* this will only add new domains we didn't already know about
686 in the domain_list()*/
688 add_trusted_domains( find_our_domain() );
690 te = tevent_add_timer(
691 ev, NULL, timeval_current_ofs(WINBINDD_RESCAN_FREQ, 0),
692 rescan_trusted_domains, NULL);
694 * If te == NULL, there's not much we can do here. Don't fail, the
695 * only thing we miss is new trusted domains.
701 static void wbd_ping_dc_done(struct tevent_req *subreq);
703 void winbindd_ping_offline_domains(struct tevent_context *ev,
704 struct tevent_timer *te,
708 struct winbindd_domain *domain = NULL;
712 for (domain = domain_list(); domain != NULL; domain = domain->next) {
713 DBG_DEBUG("Domain %s is %s\n",
715 domain->online ? "online" : "offline");
717 if (get_global_winbindd_state_offline()) {
718 DBG_DEBUG("We are globally offline, do nothing.\n");
722 if (domain->online ||
723 domain->check_online_event != NULL ||
724 domain->secure_channel_type == SEC_CHAN_NULL) {
728 winbindd_flush_negative_conn_cache(domain);
730 domain->check_online_event =
731 dcerpc_wbint_PingDc_send(domain,
733 dom_child_handle(domain),
734 &domain->ping_dcname);
735 if (domain->check_online_event == NULL) {
736 DBG_WARNING("Failed to schedule ping, no-memory\n");
740 tevent_req_set_callback(domain->check_online_event,
741 wbd_ping_dc_done, domain);
744 te = tevent_add_timer(ev,
746 timeval_current_ofs(lp_winbind_reconnect_delay(),
748 winbindd_ping_offline_domains,
751 DBG_ERR("Failed to schedule winbindd_ping_offline_domains()\n");
757 static void wbd_ping_dc_done(struct tevent_req *subreq)
759 struct winbindd_domain *domain =
760 tevent_req_callback_data(subreq,
761 struct winbindd_domain);
762 NTSTATUS status, result;
764 SMB_ASSERT(subreq == domain->check_online_event);
765 domain->check_online_event = NULL;
767 status = dcerpc_wbint_PingDc_recv(subreq, domain, &result);
769 if (any_nt_status_not_ok(status, result, &status)) {
770 DBG_WARNING("dcerpc_wbint_PingDc_recv failed for domain: "
777 DBG_DEBUG("dcerpc_wbint_PingDc_recv() succeeded, "
778 "domain: %s, dc-name: %s\n",
780 domain->ping_dcname);
782 talloc_free(discard_const(domain->ping_dcname));
783 domain->ping_dcname = NULL;
788 static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
791 struct server_id server_id,
799 DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
803 DBG_NOTICE("Rescanning trusted domains\n");
805 ok = add_trusted_domains_dc();
807 DBG_ERR("Failed to reload trusted domains\n");
812 * We did not get the secret when we queried secrets.tdb, so read it
813 * from secrets.tdb and re-sync the databases
815 static bool migrate_secrets_tdb_to_ldb(struct winbindd_domain *domain)
818 struct cli_credentials *creds;
819 NTSTATUS can_migrate = pdb_get_trust_credentials(domain->name,
820 NULL, domain, &creds);
821 if (!NT_STATUS_IS_OK(can_migrate)) {
822 DEBUG(0, ("Failed to fetch our own local AD domain join "
823 "password for winbindd's internal use, both from "
824 "secrets.tdb and secrets.ldb: %s\n",
825 nt_errstr(can_migrate)));
830 * NOTE: It is very unlikely we end up here if there is an
831 * oldpass, because a new password is created at
832 * classicupgrade, so this is not a concern.
834 ok = secrets_store_machine_pw_sync(cli_credentials_get_password(creds),
836 cli_credentials_get_domain(creds),
837 cli_credentials_get_realm(creds),
838 cli_credentials_get_salt_principal(creds, creds),
839 0, /* Supported enc types, unused */
841 cli_credentials_get_password_last_changed_time(creds),
842 cli_credentials_get_secure_channel_type(creds),
843 false /* do_delete: Do not delete */);
846 DEBUG(0, ("Failed to write our own "
847 "local AD domain join password for "
848 "winbindd's internal use into secrets.tdb\n"));
854 bool add_trusted_domains_dc(void)
856 struct winbindd_domain *domain = NULL;
857 struct pdb_trusted_domain **domains = NULL;
858 uint32_t num_domains = 0;
862 if (!(pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX)) {
863 struct trustdom_info **ti = NULL;
865 status = pdb_enum_trusteddoms(talloc_tos(), &num_domains, &ti);
866 if (!NT_STATUS_IS_OK(status)) {
867 DBG_ERR("pdb_enum_trusteddoms() failed - %s\n",
872 for (i = 0; i < num_domains; i++) {
873 status = add_trusted_domain(ti[i]->name,
876 LSA_TRUST_TYPE_DOWNLEVEL,
877 NETR_TRUST_FLAG_OUTBOUND,
882 if (!NT_STATUS_IS_OK(status)) {
883 DBG_NOTICE("add_trusted_domain returned %s\n",
892 status = pdb_enum_trusted_domains(talloc_tos(), &num_domains, &domains);
893 if (!NT_STATUS_IS_OK(status)) {
894 DBG_ERR("pdb_enum_trusted_domains() failed - %s\n",
899 for (i = 0; i < num_domains; i++) {
900 enum netr_SchannelType sec_chan_type = SEC_CHAN_DOMAIN;
901 uint32_t trust_flags = 0;
903 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
904 sec_chan_type = SEC_CHAN_DNS_DOMAIN;
907 if (!(domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
908 sec_chan_type = SEC_CHAN_NULL;
911 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
912 trust_flags |= NETR_TRUST_FLAG_INBOUND;
914 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
915 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
917 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
918 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
921 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION) {
923 * We don't support selective authentication yet.
925 DBG_WARNING("Ignoring CROSS_ORGANIZATION trust to "
927 domains[i]->netbios_name,
928 domains[i]->domain_name);
932 status = add_trusted_domain(domains[i]->netbios_name,
933 domains[i]->domain_name,
934 &domains[i]->security_identifier,
935 domains[i]->trust_type,
937 domains[i]->trust_attributes,
941 if (!NT_STATUS_IS_OK(status)) {
942 DBG_NOTICE("add_trusted_domain returned %s\n",
947 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
948 domain->active_directory = true;
950 domain->domain_type = domains[i]->trust_type;
951 domain->domain_trust_attribs = domains[i]->trust_attributes;
954 for (i = 0; i < num_domains; i++) {
955 struct ForestTrustInfo fti;
957 enum ndr_err_code ndr_err;
958 struct winbindd_domain *routing_domain = NULL;
960 if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
964 if (!(domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
968 if (domains[i]->trust_forest_trust_info.length == 0) {
972 routing_domain = find_domain_from_name_noinit(
973 domains[i]->netbios_name);
974 if (routing_domain == NULL) {
975 DBG_ERR("Can't find winbindd domain [%s]\n",
976 domains[i]->netbios_name);
980 ndr_err = ndr_pull_struct_blob_all(
981 &domains[i]->trust_forest_trust_info,
983 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
984 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
985 DBG_ERR("ndr_pull_ForestTrustInfo(%s) - %s\n",
986 domains[i]->netbios_name,
987 ndr_map_error2string(ndr_err));
991 for (fi = 0; fi < fti.count; fi++) {
992 struct ForestTrustInfoRecord *rec =
993 &fti.records[fi].record;
994 struct ForestTrustDataDomainInfo *drec = NULL;
996 if (rec->type != FOREST_TRUST_DOMAIN_INFO) {
999 drec = &rec->data.info;
1001 if (rec->flags & LSA_NB_DISABLED_MASK) {
1005 if (rec->flags & LSA_SID_DISABLED_MASK) {
1011 * also try to find a matching
1012 * LSA_TLN_DISABLED_MASK ???
1015 domain = find_domain_from_name_noinit(drec->netbios_name.string);
1016 if (domain != NULL) {
1020 status = add_trusted_domain(drec->netbios_name.string,
1021 drec->dns_name.string,
1023 LSA_TRUST_TYPE_UPLEVEL,
1024 NETR_TRUST_FLAG_OUTBOUND,
1029 if (!NT_STATUS_IS_OK(status)) {
1030 DBG_NOTICE("add_trusted_domain returned %s\n",
1034 if (domain == NULL) {
1044 /* Look up global info for the winbind daemon */
1045 bool init_domain_list(void)
1047 int role = lp_server_role();
1048 struct pdb_domain_info *pdb_domain_info = NULL;
1049 struct winbindd_domain *domain = NULL;
1053 /* Free existing list */
1056 /* BUILTIN domain */
1058 status = add_trusted_domain("BUILTIN",
1060 &global_sid_Builtin,
1061 LSA_TRUST_TYPE_DOWNLEVEL,
1062 0, /* trust_flags */
1063 0, /* trust_attribs */
1067 if (!NT_STATUS_IS_OK(status)) {
1068 DBG_ERR("add_trusted_domain BUILTIN returned %s\n",
1076 * In case the passdb backend is passdb_dsdb the domain SID comes from
1077 * dsdb, not from secrets.tdb. As we use the domain SID in various
1078 * places, we must ensure the domain SID is migrated from dsdb to
1079 * secrets.tdb before get_global_sam_sid() is called the first time.
1081 * The migration is done as part of the passdb_dsdb initialisation,
1082 * calling pdb_get_domain_info() triggers it.
1084 pdb_domain_info = pdb_get_domain_info(talloc_tos());
1086 if ( role == ROLE_ACTIVE_DIRECTORY_DC ) {
1087 uint32_t trust_flags;
1089 enum netr_SchannelType sec_chan_type;
1090 const char *account_name;
1091 struct samr_Password current_nt_hash;
1093 if (pdb_domain_info == NULL) {
1094 DEBUG(0, ("Failed to fetch our own local AD "
1095 "domain info from sam.ldb\n"));
1099 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1100 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1101 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1102 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1104 is_root = strequal(pdb_domain_info->dns_domain,
1105 pdb_domain_info->dns_forest);
1107 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1110 status = add_trusted_domain(pdb_domain_info->name,
1111 pdb_domain_info->dns_domain,
1112 &pdb_domain_info->sid,
1113 LSA_TRUST_TYPE_UPLEVEL,
1115 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1119 TALLOC_FREE(pdb_domain_info);
1120 if (!NT_STATUS_IS_OK(status)) {
1121 DBG_ERR("Failed to add our own local AD "
1122 "domain to winbindd's internal list\n");
1127 * We need to call this to find out if we are an RODC
1129 ok = get_trust_pw_hash(domain->name,
1130 current_nt_hash.hash,
1135 * If get_trust_pw_hash() fails, then try and
1136 * fetch the password from the more recent of
1137 * secrets.{ldb,tdb} using the
1138 * pdb_get_trust_credentials()
1140 ok = migrate_secrets_tdb_to_ldb(domain);
1143 DEBUG(0, ("Failed to migrate our own "
1144 "local AD domain join password for "
1145 "winbindd's internal use into "
1149 ok = get_trust_pw_hash(domain->name,
1150 current_nt_hash.hash,
1154 DEBUG(0, ("Failed to find our own just "
1155 "written local AD domain join "
1156 "password for winbindd's internal "
1157 "use in secrets.tdb\n"));
1162 domain->secure_channel_type = sec_chan_type;
1163 if (sec_chan_type == SEC_CHAN_RODC) {
1164 domain->rodc = true;
1168 uint32_t trust_flags;
1169 enum netr_SchannelType secure_channel_type;
1171 trust_flags = NETR_TRUST_FLAG_OUTBOUND;
1172 if (role != ROLE_DOMAIN_MEMBER) {
1173 trust_flags |= NETR_TRUST_FLAG_PRIMARY;
1176 if (role > ROLE_DOMAIN_MEMBER) {
1177 secure_channel_type = SEC_CHAN_BDC;
1179 secure_channel_type = SEC_CHAN_LOCAL;
1182 if ((pdb_domain_info != NULL) && (role == ROLE_IPA_DC)) {
1183 /* This is IPA DC that presents itself as
1184 * an Active Directory domain controller to trusted AD
1185 * forests but in fact is a classic domain controller.
1187 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1188 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1189 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1190 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1191 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1192 status = add_trusted_domain(pdb_domain_info->name,
1193 pdb_domain_info->dns_domain,
1194 &pdb_domain_info->sid,
1195 LSA_TRUST_TYPE_UPLEVEL,
1197 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1198 secure_channel_type,
1201 TALLOC_FREE(pdb_domain_info);
1203 status = add_trusted_domain(get_global_sam_name(),
1205 get_global_sam_sid(),
1206 LSA_TRUST_TYPE_DOWNLEVEL,
1208 0, /* trust_attribs */
1209 secure_channel_type,
1213 if (!NT_STATUS_IS_OK(status)) {
1214 DBG_ERR("Failed to add local SAM to "
1215 "domain to winbindd's internal list\n");
1221 ok = add_trusted_domains_dc();
1223 DBG_ERR("init_domain_list_dc failed\n");
1228 if ( role == ROLE_DOMAIN_MEMBER ) {
1229 struct dom_sid our_sid;
1230 uint32_t trust_type;
1232 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
1233 DEBUG(0, ("Could not fetch our SID - did we join?\n"));
1237 if (lp_realm() != NULL) {
1238 trust_type = LSA_TRUST_TYPE_UPLEVEL;
1240 trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1243 status = add_trusted_domain(lp_workgroup(),
1247 NETR_TRUST_FLAG_PRIMARY|
1248 NETR_TRUST_FLAG_OUTBOUND,
1249 0, /* trust_attribs */
1253 if (!NT_STATUS_IS_OK(status)) {
1254 DBG_ERR("Failed to add local SAM to "
1255 "domain to winbindd's internal list\n");
1260 status = imessaging_register(winbind_imessaging_context(), NULL,
1261 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1262 wb_imsg_new_trusted_domain);
1263 if (!NT_STATUS_IS_OK(status)) {
1264 DBG_ERR("imessaging_register failed %s\n", nt_errstr(status));
1272 * Given a domain name, return the struct winbindd domain info for it
1274 * @note Do *not* pass lp_workgroup() to this function. domain_list
1275 * may modify it's value, and free that pointer. Instead, our local
1276 * domain may be found by calling find_our_domain().
1280 * @return The domain structure for the named domain, if it is working.
1283 struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
1285 struct winbindd_domain *domain;
1287 /* Search through list */
1289 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1290 if (strequal(domain_name, domain->name)) {
1293 if (domain->alt_name == NULL) {
1296 if (strequal(domain_name, domain->alt_name)) {
1307 * Given a domain name, return the struct winbindd domain if it's a direct
1310 * @return The domain structure for the named domain, if it is a direct outgoing trust
1312 struct winbindd_domain *find_trust_from_name_noinit(const char *domain_name)
1314 struct winbindd_domain *domain = NULL;
1316 domain = find_domain_from_name_noinit(domain_name);
1317 if (domain == NULL) {
1321 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1328 struct winbindd_domain *find_domain_from_name(const char *domain_name)
1330 struct winbindd_domain *domain;
1332 domain = find_domain_from_name_noinit(domain_name);
1337 if (!domain->initialized)
1338 init_dc_connection(domain, false);
1343 /* Given a domain sid, return the struct winbindd domain info for it */
1345 struct winbindd_domain *find_domain_from_sid_noinit(const struct dom_sid *sid)
1347 struct winbindd_domain *domain;
1349 /* Search through list */
1351 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1352 if (dom_sid_compare_domain(sid, &domain->sid) == 0)
1362 * Given a domain sid, return the struct winbindd domain if it's a direct
1365 * @return The domain structure for the specified domain, if it is a direct outgoing trust
1367 struct winbindd_domain *find_trust_from_sid_noinit(const struct dom_sid *sid)
1369 struct winbindd_domain *domain = NULL;
1371 domain = find_domain_from_sid_noinit(sid);
1372 if (domain == NULL) {
1376 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1383 /* Given a domain sid, return the struct winbindd domain info for it */
1385 struct winbindd_domain *find_domain_from_sid(const struct dom_sid *sid)
1387 struct winbindd_domain *domain;
1389 domain = find_domain_from_sid_noinit(sid);
1394 if (!domain->initialized)
1395 init_dc_connection(domain, false);
1400 struct winbindd_domain *find_our_domain(void)
1402 struct winbindd_domain *domain;
1404 /* Search through list */
1406 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1407 if (domain->primary)
1411 smb_panic("Could not find our domain");
1415 struct winbindd_domain *find_default_route_domain(void)
1418 return find_our_domain();
1420 DBG_DEBUG("Routing logic not yet implemented on a DC\n");
1424 /* Find the appropriate domain to lookup a name or SID */
1426 struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)
1428 struct dom_sid_buf buf;
1430 DBG_DEBUG("SID [%s]\n", dom_sid_str_buf(sid, &buf));
1433 * SIDs in the S-1-22-{1,2} domain and well-known SIDs should be handled
1437 if ( sid_check_is_in_unix_groups(sid) ||
1438 sid_check_is_unix_groups(sid) ||
1439 sid_check_is_in_unix_users(sid) ||
1440 sid_check_is_unix_users(sid) ||
1441 sid_check_is_our_sam(sid) ||
1442 sid_check_is_in_our_sam(sid) )
1444 return find_domain_from_sid(get_global_sam_sid());
1447 if ( sid_check_is_builtin(sid) ||
1448 sid_check_is_in_builtin(sid) ||
1449 sid_check_is_wellknown_domain(sid, NULL) ||
1450 sid_check_is_in_wellknown_domain(sid) )
1452 return find_domain_from_sid(&global_sid_Builtin);
1456 struct winbindd_domain *domain = NULL;
1458 domain = find_domain_from_sid_noinit(sid);
1459 if (domain == NULL) {
1463 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1467 return domain->routing_domain;
1470 /* On a member server a query for SID or name can always go to our
1473 DEBUG(10, ("calling find_our_domain\n"));
1474 return find_our_domain();
1477 struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
1481 if ( strequal(domain_name, unix_users_domain_name() ) ||
1482 strequal(domain_name, unix_groups_domain_name() ) )
1485 * The "Unix User" and "Unix Group" domain are handled by
1488 return find_domain_from_name_noinit( get_global_sam_name() );
1491 if (strequal(domain_name, "BUILTIN") ||
1492 strequal(domain_name, get_global_sam_name())) {
1493 return find_domain_from_name_noinit(domain_name);
1496 predefined = dom_sid_lookup_is_predefined_domain(domain_name);
1498 return find_domain_from_name_noinit(builtin_domain_name());
1502 struct winbindd_domain *domain = NULL;
1504 domain = find_domain_from_name_noinit(domain_name);
1505 if (domain == NULL) {
1509 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1513 return domain->routing_domain;
1516 return find_our_domain();
1519 /* Is this a domain which we may assume no DOMAIN\ prefix? */
1521 static bool assume_domain(const char *domain)
1523 /* never assume the domain on a standalone server */
1525 if ( lp_server_role() == ROLE_STANDALONE )
1528 /* domain member servers may possibly assume for the domain name */
1530 if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
1531 if ( !strequal(lp_workgroup(), domain) )
1534 if ( lp_winbind_use_default_domain() )
1538 /* only left with a domain controller */
1540 if ( strequal(get_global_sam_name(), domain) ) {
1547 /* Parse a DOMAIN\user or UPN string into a domain, namespace and a user */
1548 bool parse_domain_user(TALLOC_CTX *ctx,
1549 const char *domuser,
1555 char *namespace = NULL;
1556 char *domain = NULL;
1559 if (strlen(domuser) == 0) {
1563 p = strchr(domuser, *lp_winbind_separator());
1565 user = talloc_strdup(ctx, p + 1);
1569 domain = talloc_strdup(ctx,
1571 if (domain == NULL) {
1574 domain[PTR_DIFF(p, domuser)] = '\0';
1575 namespace = talloc_strdup(ctx, domain);
1576 if (namespace == NULL) {
1580 user = talloc_strdup(ctx, domuser);
1584 p = strchr(domuser, '@');
1587 namespace = talloc_strdup(ctx, p + 1);
1588 if (namespace == NULL) {
1591 domain = talloc_strdup(ctx, "");
1592 if (domain == NULL) {
1596 } else if (assume_domain(lp_workgroup())) {
1597 domain = talloc_strdup(ctx, lp_workgroup());
1598 if (domain == NULL) {
1601 namespace = talloc_strdup(ctx, domain);
1602 if (namespace == NULL) {
1606 namespace = talloc_strdup(ctx, lp_netbios_name());
1607 if (namespace == NULL) {
1610 domain = talloc_strdup(ctx, "");
1611 if (domain == NULL) {
1617 if (!strupper_m(domain)) {
1621 *pnamespace = namespace;
1627 TALLOC_FREE(domain);
1628 TALLOC_FREE(namespace);
1632 bool canonicalize_username(TALLOC_CTX *mem_ctx,
1633 char **pusername_inout,
1639 char *namespace = NULL;
1640 char *domain = NULL;
1642 char *username_inout = NULL;
1644 ok = parse_domain_user(mem_ctx,
1646 &namespace, &domain, &user);
1652 username_inout = talloc_asprintf(mem_ctx, "%s%c%s",
1653 domain, *lp_winbind_separator(),
1656 if (username_inout == NULL) {
1660 *pnamespace = namespace;
1663 *pusername_inout = username_inout;
1666 TALLOC_FREE(username_inout);
1667 TALLOC_FREE(namespace);
1668 TALLOC_FREE(domain);
1674 Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
1675 'winbind separator' options.
1677 - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
1680 If we are a PDC or BDC, and this is for our domain, do likewise.
1682 On an AD DC we always fill DOMAIN\\USERNAME.
1684 We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1687 * talloc version of fill_domain_username()
1688 * return NULL on talloc failure.
1690 char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
1695 char *tmp_user, *name;
1697 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1705 tmp_user = talloc_strdup(mem_ctx, user);
1706 if (tmp_user == NULL) {
1709 if (!strlower_m(tmp_user)) {
1710 TALLOC_FREE(tmp_user);
1714 if (can_assume && assume_domain(domain)) {
1717 name = talloc_asprintf(mem_ctx, "%s%c%s",
1719 *lp_winbind_separator(),
1721 TALLOC_FREE(tmp_user);
1728 * Client list accessor functions
1731 static struct winbindd_cli_state *_client_list;
1732 static int _num_clients;
1734 /* Return list of all connected clients */
1736 struct winbindd_cli_state *winbindd_client_list(void)
1738 return _client_list;
1741 /* Return list-tail of all connected clients */
1743 struct winbindd_cli_state *winbindd_client_list_tail(void)
1745 return DLIST_TAIL(_client_list);
1748 /* Return previous (read:newer) client in list */
1750 struct winbindd_cli_state *
1751 winbindd_client_list_prev(struct winbindd_cli_state *cli)
1753 return DLIST_PREV(cli);
1756 /* Add a connection to the list */
1758 void winbindd_add_client(struct winbindd_cli_state *cli)
1760 cli->last_access = time(NULL);
1761 DLIST_ADD(_client_list, cli);
1765 /* Remove a client from the list */
1767 void winbindd_remove_client(struct winbindd_cli_state *cli)
1769 DLIST_REMOVE(_client_list, cli);
1773 /* Move a client to head or list */
1775 void winbindd_promote_client(struct winbindd_cli_state *cli)
1777 cli->last_access = time(NULL);
1778 DLIST_PROMOTE(_client_list, cli);
1781 /* Return number of open clients */
1783 int winbindd_num_clients(void)
1785 return _num_clients;
1788 NTSTATUS lookup_usergroups_cached(TALLOC_CTX *mem_ctx,
1789 const struct dom_sid *user_sid,
1790 uint32_t *p_num_groups, struct dom_sid **user_sids)
1792 struct netr_SamInfo3 *info3 = NULL;
1793 NTSTATUS status = NT_STATUS_NO_MEMORY;
1794 uint32_t num_groups = 0;
1796 DEBUG(3,(": lookup_usergroups_cached\n"));
1801 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1803 if (info3 == NULL) {
1804 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1808 * Before bug #7843 the "Domain Local" groups were added with a
1809 * lookupuseraliases call, but this isn't done anymore for our domain
1810 * so we need to resolve resource groups here.
1812 * When to use Resource Groups:
1813 * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
1815 status = sid_array_from_info3(mem_ctx, info3,
1820 if (!NT_STATUS_IS_OK(status)) {
1826 *p_num_groups = num_groups;
1827 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1829 DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1834 /*********************************************************************
1835 We use this to remove spaces from user and group names
1836 ********************************************************************/
1838 NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
1839 const char *domain_name,
1843 struct winbindd_domain *domain = NULL;
1846 if (!name || !normalized) {
1847 return NT_STATUS_INVALID_PARAMETER;
1850 if (!lp_winbind_normalize_names()) {
1851 return NT_STATUS_PROCEDURE_NOT_FOUND;
1854 domain = find_domain_from_name_noinit(domain_name);
1855 if (domain == NULL) {
1856 DBG_ERR("Failed to find domain '%s'\n", domain_name);
1857 return NT_STATUS_NO_SUCH_DOMAIN;
1860 /* Alias support and whitespace replacement are mutually
1863 nt_status = resolve_username_to_alias(mem_ctx, domain,
1865 if (NT_STATUS_IS_OK(nt_status)) {
1866 /* special return code to let the caller know we
1867 mapped to an alias */
1868 return NT_STATUS_FILE_RENAMED;
1871 /* check for an unreachable domain */
1873 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1874 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1876 set_domain_offline(domain);
1880 /* deal with whitespace */
1882 *normalized = talloc_strdup(mem_ctx, name);
1883 if (!(*normalized)) {
1884 return NT_STATUS_NO_MEMORY;
1887 all_string_sub( *normalized, " ", "_", 0 );
1889 return NT_STATUS_OK;
1892 /*********************************************************************
1893 We use this to do the inverse of normalize_name_map()
1894 ********************************************************************/
1896 NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
1901 struct winbindd_domain *domain = find_our_domain();
1903 if (!name || !normalized) {
1904 return NT_STATUS_INVALID_PARAMETER;
1907 if (!lp_winbind_normalize_names()) {
1908 return NT_STATUS_PROCEDURE_NOT_FOUND;
1911 /* Alias support and whitespace replacement are mutally
1914 /* When mapping from an alias to a username, we don't know the
1915 domain. But we only need a domain structure to cache
1916 a successful lookup , so just our own domain structure for
1919 nt_status = resolve_alias_to_username(mem_ctx, domain,
1921 if (NT_STATUS_IS_OK(nt_status)) {
1922 /* Special return code to let the caller know we mapped
1924 return NT_STATUS_FILE_RENAMED;
1927 /* check for an unreachable domain */
1929 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1930 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1932 set_domain_offline(domain);
1936 /* deal with whitespace */
1938 *normalized = talloc_strdup(mem_ctx, name);
1939 if (!(*normalized)) {
1940 return NT_STATUS_NO_MEMORY;
1943 all_string_sub(*normalized, "_", " ", 0);
1945 return NT_STATUS_OK;
1948 /*********************************************************************
1949 ********************************************************************/
1951 bool winbindd_can_contact_domain(struct winbindd_domain *domain)
1953 struct winbindd_tdc_domain *tdc = NULL;
1954 TALLOC_CTX *frame = talloc_stackframe();
1957 /* We can contact the domain if it is our primary domain */
1959 if (domain->primary) {
1964 /* Trust the TDC cache and not the winbindd_domain flags */
1966 if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
1967 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
1973 /* Can always contact a domain that is in out forest */
1975 if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1981 * On a _member_ server, we cannot contact the domain if it
1982 * is running AD and we have no inbound trust.
1986 domain->active_directory &&
1987 ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
1989 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
1990 "and we have no inbound trust.\n", domain->name));
1994 /* Assume everything else is ok (probably not true but what
2000 talloc_destroy(frame);
2005 #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
2007 /*********************************************************************
2008 ********************************************************************/
2010 static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
2013 char addr[INET6_ADDRSTRLEN];
2014 const char *kdc = NULL;
2017 if (!domain || !domain->alt_name || !*domain->alt_name) {
2021 if (domain->initialized && !domain->active_directory) {
2022 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
2027 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
2030 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
2032 kdc = domain->dcname;
2035 if (!kdc || !*kdc) {
2036 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
2041 var = talloc_asprintf_strupper_m(
2044 WINBINDD_LOCATOR_KDC_ADDRESS,
2050 DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
2053 setenv(var, kdc, 1);
2057 /*********************************************************************
2058 ********************************************************************/
2060 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2062 struct winbindd_domain *our_dom = find_our_domain();
2064 winbindd_set_locator_kdc_env(domain);
2066 if (domain != our_dom) {
2067 winbindd_set_locator_kdc_env(our_dom);
2071 /*********************************************************************
2072 ********************************************************************/
2074 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2078 if (!domain || !domain->alt_name || !*domain->alt_name) {
2082 var = talloc_asprintf_strupper_m(
2085 WINBINDD_LOCATOR_KDC_ADDRESS,
2096 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2101 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2106 #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
2108 void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
2111 * Make sure we start with authoritative=true,
2112 * it will only set to false if we don't know the
2115 resp->data.auth.authoritative = true;
2117 resp->data.auth.nt_status = NT_STATUS_V(result);
2118 fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
2120 /* we might have given a more useful error above */
2121 if (*resp->data.auth.error_string == '\0')
2122 fstrcpy(resp->data.auth.error_string,
2123 get_friendly_nt_error_msg(result));
2124 resp->data.auth.pam_error = nt_status_to_pam(result);
2127 bool is_domain_offline(const struct winbindd_domain *domain)
2129 if (get_global_winbindd_state_offline()) {
2132 return !domain->online;
2135 bool is_domain_online(const struct winbindd_domain *domain)
2137 return !is_domain_offline(domain);
2141 * Parse an char array into a list of sids.
2143 * The input sidstr should consist of 0-terminated strings
2144 * representing sids, separated by newline characters '\n'.
2145 * The list is terminated by an empty string, i.e.
2146 * character '\0' directly following a character '\n'
2147 * (or '\0' right at the start of sidstr).
2149 bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
2150 struct dom_sid **sids, uint32_t *num_sids)
2158 while (p[0] != '\0') {
2160 const char *q = NULL;
2162 if (!dom_sid_parse_endp(p, &sid, &q)) {
2163 DEBUG(1, ("Could not parse sid %s\n", p));
2167 DEBUG(1, ("Got invalid sidstr: %s\n", p));
2170 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
2180 bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
2181 struct unixid **pxids, uint32_t *pnum_xids)
2184 struct unixid *xids = NULL;
2185 uint32_t num_xids = 0;
2192 while (p[0] != '\0') {
2195 unsigned long long id;
2201 xid = (struct unixid) { .type = ID_TYPE_UID };
2204 xid = (struct unixid) { .type = ID_TYPE_GID };
2212 id = smb_strtoull(p, &endp, 10, &error, SMB_STR_STANDARD);
2216 if (*endp != '\n') {
2222 if ((unsigned long long)xid.id != id) {
2226 tmp = talloc_realloc(mem_ctx, xids, struct unixid, num_xids+1);
2232 xids[num_xids] = xid;
2237 *pnum_xids = num_xids;