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"
38 #define DBGC_CLASS DBGC_WINBIND
41 * @file winbindd_util.c
43 * Winbind daemon for NT domain authentication nss module.
46 static bool add_trusted_domains_dc(void);
48 /* The list of trusted domains. Note that the list can be deleted and
49 recreated using the init_domain_list() function so pointers to
50 individual winbindd_domain structures cannot be made. Keep a copy of
51 the domain name instead. */
53 static struct winbindd_domain *_domain_list = NULL;
55 struct winbindd_domain *domain_list(void)
59 if ((!_domain_list) && (!init_domain_list())) {
60 smb_panic("Init_domain_list failed");
66 /* Free all entries in the trusted domain list */
68 static void free_domain_list(void)
70 struct winbindd_domain *domain = _domain_list;
73 struct winbindd_domain *next = domain->next;
75 DLIST_REMOVE(_domain_list, domain);
82 * Iterator for winbindd's domain list.
83 * To be used (e.g.) in tevent based loops.
85 struct winbindd_domain *wb_next_domain(struct winbindd_domain *domain)
88 domain = domain_list();
90 domain = domain->next;
93 if ((domain != NULL) &&
94 (lp_server_role() != ROLE_ACTIVE_DIRECTORY_DC) &&
95 sid_check_is_our_sam(&domain->sid))
97 domain = domain->next;
103 static bool is_internal_domain(const struct dom_sid *sid)
108 return (sid_check_is_our_sam(sid) || sid_check_is_builtin(sid));
111 /* Add a trusted domain to our list of domains.
112 If the domain already exists in the list,
113 return it and don't re-initialize. */
115 static NTSTATUS add_trusted_domain(const char *domain_name,
116 const char *dns_name,
117 const struct dom_sid *sid,
119 uint32_t trust_flags,
120 uint32_t trust_attribs,
121 enum netr_SchannelType secure_channel_type,
122 struct winbindd_domain *routing_domain,
123 struct winbindd_domain **_d)
125 struct winbindd_domain *domain = NULL;
126 const char **ignored_domains = NULL;
127 const char **dom = 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 ignored_domains = lp_parm_string_list(-1, "winbind", "ignore domains", NULL);
137 for (dom=ignored_domains; dom && *dom; dom++) {
138 if (gen_fnmatch(*dom, domain_name) == 0) {
139 DEBUG(2,("Ignoring domain '%s'\n", domain_name));
140 return NT_STATUS_NO_SUCH_DOMAIN;
145 * We can't call domain_list() as this function is called from
146 * init_domain_list() and we'll get stuck in a loop.
148 for (domain = _domain_list; domain; domain = domain->next) {
149 if (strequal(domain_name, domain->name)) {
154 if (domain != NULL) {
155 struct winbindd_domain *check_domain = NULL;
157 for (check_domain = _domain_list;
158 check_domain != NULL;
159 check_domain = check_domain->next)
161 if (check_domain == domain) {
165 if (dom_sid_equal(&check_domain->sid, sid)) {
170 if (check_domain != NULL) {
171 DBG_ERR("SID [%s] already used by domain [%s], "
173 dom_sid_str_buf(sid, &buf),
176 return NT_STATUS_INVALID_PARAMETER;
180 if ((domain != NULL) && (dns_name != NULL)) {
181 struct winbindd_domain *check_domain = NULL;
183 for (check_domain = _domain_list;
184 check_domain != NULL;
185 check_domain = check_domain->next)
187 if (check_domain == domain) {
191 if (strequal(check_domain->alt_name, dns_name)) {
196 if (check_domain != NULL) {
197 DBG_ERR("DNS name [%s] used by domain [%s], "
199 dns_name, check_domain->name,
201 return NT_STATUS_INVALID_PARAMETER;
205 if (domain != NULL) {
210 /* Create new domain entry */
211 domain = talloc_zero(NULL, struct winbindd_domain);
212 if (domain == NULL) {
213 return NT_STATUS_NO_MEMORY;
216 domain->children = talloc_zero_array(domain,
217 struct winbindd_child,
218 lp_winbind_max_domain_connections());
219 if (domain->children == NULL) {
221 return NT_STATUS_NO_MEMORY;
224 domain->queue = tevent_queue_create(domain, "winbind_domain");
225 if (domain->queue == NULL) {
227 return NT_STATUS_NO_MEMORY;
230 domain->binding_handle = wbint_binding_handle(domain, domain, NULL);
231 if (domain->binding_handle == NULL) {
233 return NT_STATUS_NO_MEMORY;
236 domain->name = talloc_strdup(domain, domain_name);
237 if (domain->name == NULL) {
239 return NT_STATUS_NO_MEMORY;
242 if (dns_name != NULL) {
243 domain->alt_name = talloc_strdup(domain, dns_name);
244 if (domain->alt_name == NULL) {
246 return NT_STATUS_NO_MEMORY;
250 domain->backend = NULL;
251 domain->internal = is_internal_domain(sid);
252 domain->secure_channel_type = secure_channel_type;
253 domain->sequence_number = DOM_SEQUENCE_NONE;
254 domain->last_seq_check = 0;
255 domain->initialized = false;
256 domain->online = is_internal_domain(sid);
257 domain->check_online_timeout = 0;
258 domain->dc_probe_pid = (pid_t)-1;
259 domain->domain_flags = trust_flags;
260 domain->domain_type = trust_type;
261 domain->domain_trust_attribs = trust_attribs;
262 domain->secure_channel_type = secure_channel_type;
263 domain->routing_domain = routing_domain;
264 sid_copy(&domain->sid, sid);
266 /* Is this our primary domain ? */
267 if (role == ROLE_DOMAIN_MEMBER) {
268 domain->primary = strequal(domain_name, lp_workgroup());
270 domain->primary = strequal(domain_name, get_global_sam_name());
273 if (domain->primary) {
274 if (role == ROLE_ACTIVE_DIRECTORY_DC) {
275 domain->active_directory = true;
277 if (lp_security() == SEC_ADS) {
278 domain->active_directory = true;
280 } else if (!domain->internal) {
281 if (domain->domain_type == LSA_TRUST_TYPE_UPLEVEL) {
282 domain->active_directory = true;
286 domain->can_do_ncacn_ip_tcp = domain->active_directory;
288 /* Link to domain list */
289 DLIST_ADD_END(_domain_list, domain);
291 wcache_tdc_add_domain( domain );
293 setup_domain_child(domain);
295 DBG_NOTICE("Added domain [%s] [%s] [%s]\n",
296 domain->name, domain->alt_name,
297 dom_sid_str_buf(&domain->sid, &buf));
303 bool set_routing_domain(struct winbindd_domain *domain,
304 struct winbindd_domain *routing_domain)
306 if (domain->routing_domain == NULL) {
307 domain->routing_domain = routing_domain;
310 if (domain->routing_domain != routing_domain) {
316 bool add_trusted_domain_from_auth(uint16_t validation_level,
317 struct info3_text *info3,
318 struct info6_text *info6)
320 struct winbindd_domain *domain = NULL;
321 struct dom_sid domain_sid;
322 const char *dns_domainname = NULL;
327 * We got a successfull auth from a domain that might not yet be in our
328 * domain list. If we're a member we trust our DC who authenticated the
329 * user from that domain and add the domain to our list on-the-fly. If
330 * we're a DC we rely on configured trusts and don't add on-the-fly.
337 ok = dom_sid_parse(info3->dom_sid, &domain_sid);
339 DBG_NOTICE("dom_sid_parse [%s] failed\n", info3->dom_sid);
343 if (validation_level == 6) {
344 if (!strequal(info6->dns_domainname, "")) {
345 dns_domainname = info6->dns_domainname;
349 status = add_trusted_domain(info3->logon_dom,
353 NETR_TRUST_FLAG_OUTBOUND,
356 find_default_route_domain(),
358 if (!NT_STATUS_IS_OK(status) &&
359 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
361 DBG_DEBUG("Adding domain [%s] with sid [%s] failed\n",
362 info3->logon_dom, info3->dom_sid);
369 bool domain_is_forest_root(const struct winbindd_domain *domain)
371 const uint32_t fr_flags =
372 (NETR_TRUST_FLAG_TREEROOT|NETR_TRUST_FLAG_IN_FOREST);
374 return ((domain->domain_flags & fr_flags) == fr_flags);
377 /********************************************************************
378 rescan our domains looking for new trusted domains
379 ********************************************************************/
381 struct trustdom_state {
382 struct winbindd_domain *domain;
383 struct winbindd_request request;
386 static void trustdom_list_done(struct tevent_req *req);
387 static void rescan_forest_root_trusts( void );
388 static void rescan_forest_trusts( void );
390 static void add_trusted_domains( struct winbindd_domain *domain )
392 struct trustdom_state *state;
393 struct tevent_req *req;
395 state = talloc_zero(NULL, struct trustdom_state);
397 DEBUG(0, ("talloc failed\n"));
400 state->domain = domain;
402 state->request.length = sizeof(state->request);
403 state->request.cmd = WINBINDD_LIST_TRUSTDOM;
405 req = wb_domain_request_send(state, global_event_context(),
406 domain, &state->request);
408 DEBUG(1, ("wb_domain_request_send failed\n"));
412 tevent_req_set_callback(req, trustdom_list_done, state);
415 static void trustdom_list_done(struct tevent_req *req)
417 struct trustdom_state *state = tevent_req_callback_data(
418 req, struct trustdom_state);
419 struct winbindd_response *response;
423 bool within_forest = false;
427 * Only when we enumerate our primary domain
428 * or our forest root domain, we should keep
429 * the NETR_TRUST_FLAG_IN_FOREST flag, in
430 * all other cases we need to clear it as the domain
431 * is not part of our forest.
433 if (state->domain->primary) {
434 within_forest = true;
435 } else if (domain_is_forest_root(state->domain)) {
436 within_forest = true;
439 res = wb_domain_request_recv(req, state, &response, &err);
440 if ((res == -1) || (response->result != WINBINDD_OK)) {
441 DBG_WARNING("Could not receive trusts for domain %s\n",
442 state->domain->name);
447 if (response->length < sizeof(struct winbindd_response)) {
448 DBG_ERR("ill-formed trustdom response - short length\n");
453 extra_len = response->length - sizeof(struct winbindd_response);
455 p = (char *)response->extra_data.data;
457 while ((p - (char *)response->extra_data.data) < extra_len) {
458 struct winbindd_domain *domain = NULL;
459 char *name, *q, *sidstr, *alt_name;
462 uint32_t trust_attribs;
463 uint32_t trust_flags;
466 DBG_DEBUG("parsing response line '%s'\n", p);
470 alt_name = strchr(p, '\\');
471 if (alt_name == NULL) {
472 DBG_ERR("Got invalid trustdom response\n");
479 sidstr = strchr(alt_name, '\\');
480 if (sidstr == NULL) {
481 DBG_ERR("Got invalid trustdom response\n");
488 /* use the real alt_name if we have one, else pass in NULL */
489 if (strequal(alt_name, "(null)")) {
493 q = strtok(sidstr, "\\");
495 DBG_ERR("Got invalid trustdom response\n");
499 if (!string_to_sid(&sid, sidstr)) {
500 DEBUG(0, ("Got invalid trustdom response\n"));
504 q = strtok(NULL, "\\");
506 DBG_ERR("Got invalid trustdom response\n");
510 trust_flags = (uint32_t)strtoul_err(q, NULL, 10, &error);
512 DBG_ERR("Failed to convert trust_flags\n");
516 q = strtok(NULL, "\\");
518 DBG_ERR("Got invalid trustdom response\n");
522 trust_type = (uint32_t)strtoul_err(q, NULL, 10, &error);
524 DBG_ERR("Failed to convert trust_type\n");
528 q = strtok(NULL, "\n");
530 DBG_ERR("Got invalid trustdom response\n");
534 trust_attribs = (uint32_t)strtoul_err(q, NULL, 10, &error);
536 DBG_ERR("Failed to convert trust_attribs\n");
540 if (!within_forest) {
541 trust_flags &= ~NETR_TRUST_FLAG_IN_FOREST;
544 if (!state->domain->primary) {
545 trust_flags &= ~NETR_TRUST_FLAG_PRIMARY;
549 * We always call add_trusted_domain() cause on an existing
550 * domain structure, it will update the SID if necessary.
551 * This is important because we need the SID for sibling
554 status = add_trusted_domain(name,
561 find_default_route_domain(),
563 if (!NT_STATUS_IS_OK(status) &&
564 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
566 DBG_NOTICE("add_trusted_domain returned %s\n",
571 p = q + strlen(q) + 1;
575 Cases to consider when scanning trusts:
576 (a) we are calling from a child domain (primary && !forest_root)
577 (b) we are calling from the root of the forest (primary && forest_root)
578 (c) we are calling from a trusted forest domain (!primary
582 if (state->domain->primary) {
583 /* If this is our primary domain and we are not in the
584 forest root, we have to scan the root trusts first */
586 if (!domain_is_forest_root(state->domain))
587 rescan_forest_root_trusts();
589 rescan_forest_trusts();
591 } else if (domain_is_forest_root(state->domain)) {
592 /* Once we have done root forest trust search, we can
593 go on to search the trusted forests */
595 rescan_forest_trusts();
603 /********************************************************************
604 Scan the trusts of our forest root
605 ********************************************************************/
607 static void rescan_forest_root_trusts( void )
609 struct winbindd_tdc_domain *dom_list = NULL;
610 size_t num_trusts = 0;
614 /* The only transitive trusts supported by Windows 2003 AD are
615 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
616 first two are handled in forest and listed by
617 DsEnumerateDomainTrusts(). Forest trusts are not so we
618 have to do that ourselves. */
620 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
623 for ( i=0; i<num_trusts; i++ ) {
624 struct winbindd_domain *d = NULL;
626 /* Find the forest root. Don't necessarily trust
627 the domain_list() as our primary domain may not
628 have been initialized. */
630 if ( !(dom_list[i].trust_flags & NETR_TRUST_FLAG_TREEROOT) ) {
634 /* Here's the forest root */
636 d = find_domain_from_name_noinit( dom_list[i].domain_name );
638 status = add_trusted_domain(dom_list[i].domain_name,
639 dom_list[i].dns_name,
641 dom_list[i].trust_type,
642 dom_list[i].trust_flags,
643 dom_list[i].trust_attribs,
645 find_default_route_domain(),
648 if (!NT_STATUS_IS_OK(status) &&
649 NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
651 DBG_ERR("add_trusted_domain returned %s\n",
660 DEBUG(10,("rescan_forest_root_trusts: Following trust path "
661 "for domain tree root %s (%s)\n",
662 d->name, d->alt_name ));
664 d->domain_flags = dom_list[i].trust_flags;
665 d->domain_type = dom_list[i].trust_type;
666 d->domain_trust_attribs = dom_list[i].trust_attribs;
668 add_trusted_domains( d );
673 TALLOC_FREE( dom_list );
678 /********************************************************************
679 scan the transitive forest trusts (not our own)
680 ********************************************************************/
683 static void rescan_forest_trusts( void )
685 struct winbindd_domain *d = NULL;
686 struct winbindd_tdc_domain *dom_list = NULL;
687 size_t num_trusts = 0;
691 /* The only transitive trusts supported by Windows 2003 AD are
692 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
693 first two are handled in forest and listed by
694 DsEnumerateDomainTrusts(). Forest trusts are not so we
695 have to do that ourselves. */
697 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
700 for ( i=0; i<num_trusts; i++ ) {
701 uint32_t flags = dom_list[i].trust_flags;
702 uint32_t type = dom_list[i].trust_type;
703 uint32_t attribs = dom_list[i].trust_attribs;
705 d = find_domain_from_name_noinit( dom_list[i].domain_name );
707 /* ignore our primary and internal domains */
709 if ( d && (d->internal || d->primary ) )
712 if ( (flags & NETR_TRUST_FLAG_INBOUND) &&
713 (type == LSA_TRUST_TYPE_UPLEVEL) &&
714 (attribs == LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) )
716 /* add the trusted domain if we don't know
720 status = add_trusted_domain(
721 dom_list[i].domain_name,
722 dom_list[i].dns_name,
728 find_default_route_domain(),
730 if (!NT_STATUS_IS_OK(status) &&
731 NT_STATUS_EQUAL(status,
732 NT_STATUS_NO_SUCH_DOMAIN))
734 DBG_ERR("add_trusted_domain: %s\n",
744 DEBUG(10,("Following trust path for domain %s (%s)\n",
745 d->name, d->alt_name ));
746 add_trusted_domains( d );
750 TALLOC_FREE( dom_list );
755 /*********************************************************************
756 The process of updating the trusted domain list is a three step
759 (b) ask the root domain in our forest
760 (c) ask the a DC in any Win2003 trusted forests
761 *********************************************************************/
763 void rescan_trusted_domains(struct tevent_context *ev, struct tevent_timer *te,
764 struct timeval now, void *private_data)
768 /* I use to clear the cache here and start over but that
769 caused problems in child processes that needed the
770 trust dom list early on. Removing it means we
771 could have some trusted domains listed that have been
772 removed from our primary domain's DC until a full
773 restart. This should be ok since I think this is what
774 Windows does as well. */
776 /* this will only add new domains we didn't already know about
777 in the domain_list()*/
779 add_trusted_domains( find_our_domain() );
781 te = tevent_add_timer(
782 ev, NULL, timeval_current_ofs(WINBINDD_RESCAN_FREQ, 0),
783 rescan_trusted_domains, NULL);
785 * If te == NULL, there's not much we can do here. Don't fail, the
786 * only thing we miss is new trusted domains.
792 enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domain,
793 struct winbindd_cli_state *state)
795 /* Ensure null termination */
796 state->request->domain_name
797 [sizeof(state->request->domain_name)-1]='\0';
798 state->request->data.init_conn.dcname
799 [sizeof(state->request->data.init_conn.dcname)-1]='\0';
801 if (strlen(state->request->data.init_conn.dcname) > 0) {
802 TALLOC_FREE(domain->dcname);
803 domain->dcname = talloc_strdup(domain,
804 state->request->data.init_conn.dcname);
805 if (domain->dcname == NULL) {
806 return WINBINDD_ERROR;
810 init_dc_connection(domain, false);
812 if (!domain->initialized) {
813 /* If we return error here we can't do any cached authentication,
814 but we may be in disconnected mode and can't initialize correctly.
815 Do what the previous code did and just return without initialization,
816 once we go online we'll re-initialize.
818 DEBUG(5, ("winbindd_dual_init_connection: %s returning without initialization "
819 "online = %d\n", domain->name, (int)domain->online ));
822 fstrcpy(state->response->data.domain_info.name, domain->name);
823 fstrcpy(state->response->data.domain_info.alt_name, domain->alt_name);
824 sid_to_fstring(state->response->data.domain_info.sid, &domain->sid);
826 state->response->data.domain_info.native_mode
827 = domain->native_mode;
828 state->response->data.domain_info.active_directory
829 = domain->active_directory;
830 state->response->data.domain_info.primary
836 static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
839 struct server_id server_id,
844 DBG_NOTICE("Rescanning trusted domains\n");
846 ok = add_trusted_domains_dc();
848 DBG_ERR("Failed to reload trusted domains\n");
853 * We did not get the secret when we queried secrets.tdb, so read it
854 * from secrets.tdb and re-sync the databases
856 static bool migrate_secrets_tdb_to_ldb(struct winbindd_domain *domain)
859 struct cli_credentials *creds;
860 NTSTATUS can_migrate = pdb_get_trust_credentials(domain->name,
861 NULL, domain, &creds);
862 if (!NT_STATUS_IS_OK(can_migrate)) {
863 DEBUG(0, ("Failed to fetch our own, local AD domain join "
864 "password for winbindd's internal use, both from "
865 "secrets.tdb and secrets.ldb: %s\n",
866 nt_errstr(can_migrate)));
871 * NOTE: It is very unlikely we end up here if there is an
872 * oldpass, because a new password is created at
873 * classicupgrade, so this is not a concern.
875 ok = secrets_store_machine_pw_sync(cli_credentials_get_password(creds),
877 cli_credentials_get_domain(creds),
878 cli_credentials_get_realm(creds),
879 cli_credentials_get_salt_principal(creds),
880 0, /* Supported enc types, unused */
882 cli_credentials_get_password_last_changed_time(creds),
883 cli_credentials_get_secure_channel_type(creds),
884 false /* do_delete: Do not delete */);
887 DEBUG(0, ("Failed to write our our own, "
888 "local AD domain join password for "
889 "winbindd's internal use into secrets.tdb\n"));
895 static bool add_trusted_domains_dc(void)
897 struct winbindd_domain *domain = NULL;
898 struct pdb_trusted_domain **domains = NULL;
899 uint32_t num_domains = 0;
903 if (!(pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX)) {
904 struct trustdom_info **ti = NULL;
906 status = pdb_enum_trusteddoms(talloc_tos(), &num_domains, &ti);
907 if (!NT_STATUS_IS_OK(status)) {
908 DBG_ERR("pdb_enum_trusteddoms() failed - %s\n",
913 for (i = 0; i < num_domains; i++) {
914 status = add_trusted_domain(ti[i]->name,
917 LSA_TRUST_TYPE_DOWNLEVEL,
918 NETR_TRUST_FLAG_OUTBOUND,
923 if (!NT_STATUS_IS_OK(status)) {
924 DBG_NOTICE("add_trusted_domain returned %s\n",
929 /* Even in the parent winbindd we'll need to
930 talk to the DC, so try and see if we can
931 contact it. Theoretically this isn't neccessary
932 as the init_dc_connection() in init_child_recv()
933 will do this, but we can start detecting the DC
935 set_domain_online_request(domain);
941 status = pdb_enum_trusted_domains(talloc_tos(), &num_domains, &domains);
942 if (!NT_STATUS_IS_OK(status)) {
943 DBG_ERR("pdb_enum_trusted_domains() failed - %s\n",
948 for (i = 0; i < num_domains; i++) {
949 enum netr_SchannelType sec_chan_type = SEC_CHAN_DOMAIN;
950 uint32_t trust_flags = 0;
952 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
953 sec_chan_type = SEC_CHAN_DNS_DOMAIN;
956 if (!(domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
957 sec_chan_type = SEC_CHAN_NULL;
960 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
961 trust_flags |= NETR_TRUST_FLAG_INBOUND;
963 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
964 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
966 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
967 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
970 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION) {
972 * We don't support selective authentication yet.
974 DBG_WARNING("Ignoring CROSS_ORGANIZATION trust to "
976 domains[i]->netbios_name,
977 domains[i]->domain_name);
981 status = add_trusted_domain(domains[i]->netbios_name,
982 domains[i]->domain_name,
983 &domains[i]->security_identifier,
984 domains[i]->trust_type,
986 domains[i]->trust_attributes,
990 if (!NT_STATUS_IS_OK(status)) {
991 DBG_NOTICE("add_trusted_domain returned %s\n",
996 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
997 domain->active_directory = true;
999 domain->domain_type = domains[i]->trust_type;
1000 domain->domain_trust_attribs = domains[i]->trust_attributes;
1002 if (sec_chan_type != SEC_CHAN_NULL) {
1003 /* Even in the parent winbindd we'll need to
1004 talk to the DC, so try and see if we can
1005 contact it. Theoretically this isn't neccessary
1006 as the init_dc_connection() in init_child_recv()
1007 will do this, but we can start detecting the DC
1009 set_domain_online_request(domain);
1013 for (i = 0; i < num_domains; i++) {
1014 struct ForestTrustInfo fti;
1016 enum ndr_err_code ndr_err;
1017 struct winbindd_domain *routing_domain = NULL;
1019 if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
1023 if (!(domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
1027 if (domains[i]->trust_forest_trust_info.length == 0) {
1031 routing_domain = find_domain_from_name_noinit(
1032 domains[i]->netbios_name);
1033 if (routing_domain == NULL) {
1034 DBG_ERR("Can't find winbindd domain [%s]\n",
1035 domains[i]->netbios_name);
1039 ndr_err = ndr_pull_struct_blob_all(
1040 &domains[i]->trust_forest_trust_info,
1042 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
1043 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1044 DBG_ERR("ndr_pull_ForestTrustInfo(%s) - %s\n",
1045 domains[i]->netbios_name,
1046 ndr_map_error2string(ndr_err));
1050 for (fi = 0; fi < fti.count; fi++) {
1051 struct ForestTrustInfoRecord *rec =
1052 &fti.records[fi].record;
1053 struct ForestTrustDataDomainInfo *drec = NULL;
1055 if (rec->type != FOREST_TRUST_DOMAIN_INFO) {
1058 drec = &rec->data.info;
1060 if (rec->flags & LSA_NB_DISABLED_MASK) {
1064 if (rec->flags & LSA_SID_DISABLED_MASK) {
1070 * also try to find a matching
1071 * LSA_TLN_DISABLED_MASK ???
1074 domain = find_domain_from_name_noinit(drec->netbios_name.string);
1075 if (domain != NULL) {
1079 status = add_trusted_domain(drec->netbios_name.string,
1080 drec->dns_name.string,
1082 LSA_TRUST_TYPE_UPLEVEL,
1083 NETR_TRUST_FLAG_OUTBOUND,
1088 if (!NT_STATUS_IS_OK(status)) {
1089 DBG_NOTICE("add_trusted_domain returned %s\n",
1093 if (domain == NULL) {
1103 /* Look up global info for the winbind daemon */
1104 bool init_domain_list(void)
1106 int role = lp_server_role();
1107 struct pdb_domain_info *pdb_domain_info = NULL;
1108 struct winbindd_domain *domain = NULL;
1112 /* Free existing list */
1115 /* BUILTIN domain */
1117 status = add_trusted_domain("BUILTIN",
1119 &global_sid_Builtin,
1120 LSA_TRUST_TYPE_DOWNLEVEL,
1121 0, /* trust_flags */
1122 0, /* trust_attribs */
1126 if (!NT_STATUS_IS_OK(status)) {
1127 DBG_ERR("add_trusted_domain BUILTIN returned %s\n",
1135 * In case the passdb backend is passdb_dsdb the domain SID comes from
1136 * dsdb, not from secrets.tdb. As we use the domain SID in various
1137 * places, we must ensure the domain SID is migrated from dsdb to
1138 * secrets.tdb before get_global_sam_sid() is called the first time.
1140 * The migration is done as part of the passdb_dsdb initialisation,
1141 * calling pdb_get_domain_info() triggers it.
1143 pdb_domain_info = pdb_get_domain_info(talloc_tos());
1145 if ( role == ROLE_ACTIVE_DIRECTORY_DC ) {
1146 uint32_t trust_flags;
1148 enum netr_SchannelType sec_chan_type;
1149 const char *account_name;
1150 struct samr_Password current_nt_hash;
1152 if (pdb_domain_info == NULL) {
1153 DEBUG(0, ("Failed to fetch our own, local AD "
1154 "domain info from sam.ldb\n"));
1158 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1159 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1160 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1161 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1163 is_root = strequal(pdb_domain_info->dns_domain,
1164 pdb_domain_info->dns_forest);
1166 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1169 status = add_trusted_domain(pdb_domain_info->name,
1170 pdb_domain_info->dns_domain,
1171 &pdb_domain_info->sid,
1172 LSA_TRUST_TYPE_UPLEVEL,
1174 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1178 TALLOC_FREE(pdb_domain_info);
1179 if (!NT_STATUS_IS_OK(status)) {
1180 DBG_ERR("Failed to add our own, local AD "
1181 "domain to winbindd's internal list\n");
1186 * We need to call this to find out if we are an RODC
1188 ok = get_trust_pw_hash(domain->name,
1189 current_nt_hash.hash,
1194 * If get_trust_pw_hash() fails, then try and
1195 * fetch the password from the more recent of
1196 * secrets.{ldb,tdb} using the
1197 * pdb_get_trust_credentials()
1199 ok = migrate_secrets_tdb_to_ldb(domain);
1202 DEBUG(0, ("Failed to migrate our own, "
1203 "local AD domain join password for "
1204 "winbindd's internal use into "
1208 ok = get_trust_pw_hash(domain->name,
1209 current_nt_hash.hash,
1213 DEBUG(0, ("Failed to find our our own, just "
1214 "written local AD domain join "
1215 "password for winbindd's internal "
1216 "use in secrets.tdb\n"));
1221 domain->secure_channel_type = sec_chan_type;
1222 if (sec_chan_type == SEC_CHAN_RODC) {
1223 domain->rodc = true;
1227 uint32_t trust_flags;
1228 enum netr_SchannelType secure_channel_type;
1230 trust_flags = NETR_TRUST_FLAG_OUTBOUND;
1231 if (role != ROLE_DOMAIN_MEMBER) {
1232 trust_flags |= NETR_TRUST_FLAG_PRIMARY;
1235 if (role > ROLE_DOMAIN_MEMBER) {
1236 secure_channel_type = SEC_CHAN_BDC;
1238 secure_channel_type = SEC_CHAN_LOCAL;
1241 status = add_trusted_domain(get_global_sam_name(),
1243 get_global_sam_sid(),
1244 LSA_TRUST_TYPE_DOWNLEVEL,
1246 0, /* trust_attribs */
1247 secure_channel_type,
1250 if (!NT_STATUS_IS_OK(status)) {
1251 DBG_ERR("Failed to add local SAM to "
1252 "domain to winbindd's internal list\n");
1258 ok = add_trusted_domains_dc();
1260 DBG_ERR("init_domain_list_dc failed\n");
1265 if ( role == ROLE_DOMAIN_MEMBER ) {
1266 struct dom_sid our_sid;
1267 uint32_t trust_type;
1269 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
1270 DEBUG(0, ("Could not fetch our SID - did we join?\n"));
1274 if (lp_realm() != NULL) {
1275 trust_type = LSA_TRUST_TYPE_UPLEVEL;
1277 trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1280 status = add_trusted_domain(lp_workgroup(),
1284 NETR_TRUST_FLAG_PRIMARY|
1285 NETR_TRUST_FLAG_OUTBOUND,
1286 0, /* trust_attribs */
1290 if (!NT_STATUS_IS_OK(status)) {
1291 DBG_ERR("Failed to add local SAM to "
1292 "domain to winbindd's internal list\n");
1295 /* Even in the parent winbindd we'll need to
1296 talk to the DC, so try and see if we can
1297 contact it. Theoretically this isn't neccessary
1298 as the init_dc_connection() in init_child_recv()
1299 will do this, but we can start detecting the DC
1301 set_domain_online_request(domain);
1305 status = imessaging_register(winbind_imessaging_context(), NULL,
1306 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1307 wb_imsg_new_trusted_domain);
1308 if (!NT_STATUS_IS_OK(status)) {
1309 DBG_ERR("imessaging_register failed %s\n", nt_errstr(status));
1317 * Given a domain name, return the struct winbindd domain info for it
1319 * @note Do *not* pass lp_workgroup() to this function. domain_list
1320 * may modify it's value, and free that pointer. Instead, our local
1321 * domain may be found by calling find_our_domain().
1325 * @return The domain structure for the named domain, if it is working.
1328 struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
1330 struct winbindd_domain *domain;
1332 /* Search through list */
1334 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1335 if (strequal(domain_name, domain->name)) {
1338 if (domain->alt_name == NULL) {
1341 if (strequal(domain_name, domain->alt_name)) {
1352 * Given a domain name, return the struct winbindd domain if it's a direct
1355 * @return The domain structure for the named domain, if it is a direct outgoing trust
1357 struct winbindd_domain *find_trust_from_name_noinit(const char *domain_name)
1359 struct winbindd_domain *domain = NULL;
1361 domain = find_domain_from_name_noinit(domain_name);
1362 if (domain == NULL) {
1366 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1373 struct winbindd_domain *find_domain_from_name(const char *domain_name)
1375 struct winbindd_domain *domain;
1377 domain = find_domain_from_name_noinit(domain_name);
1382 if (!domain->initialized)
1383 init_dc_connection(domain, false);
1388 /* Given a domain sid, return the struct winbindd domain info for it */
1390 struct winbindd_domain *find_domain_from_sid_noinit(const struct dom_sid *sid)
1392 struct winbindd_domain *domain;
1394 /* Search through list */
1396 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1397 if (dom_sid_compare_domain(sid, &domain->sid) == 0)
1407 * Given a domain sid, return the struct winbindd domain if it's a direct
1410 * @return The domain structure for the specified domain, if it is a direct outgoing trust
1412 struct winbindd_domain *find_trust_from_sid_noinit(const struct dom_sid *sid)
1414 struct winbindd_domain *domain = NULL;
1416 domain = find_domain_from_sid_noinit(sid);
1417 if (domain == NULL) {
1421 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1428 /* Given a domain sid, return the struct winbindd domain info for it */
1430 struct winbindd_domain *find_domain_from_sid(const struct dom_sid *sid)
1432 struct winbindd_domain *domain;
1434 domain = find_domain_from_sid_noinit(sid);
1439 if (!domain->initialized)
1440 init_dc_connection(domain, false);
1445 struct winbindd_domain *find_our_domain(void)
1447 struct winbindd_domain *domain;
1449 /* Search through list */
1451 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1452 if (domain->primary)
1456 smb_panic("Could not find our domain");
1460 struct winbindd_domain *find_default_route_domain(void)
1463 return find_our_domain();
1465 DBG_DEBUG("Routing logic not yet implemented on a DC\n");
1469 /* Find the appropriate domain to lookup a name or SID */
1471 struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)
1473 struct dom_sid_buf buf;
1475 DBG_DEBUG("SID [%s]\n", dom_sid_str_buf(sid, &buf));
1478 * SIDs in the S-1-22-{1,2} domain and well-known SIDs should be handled
1482 if ( sid_check_is_in_unix_groups(sid) ||
1483 sid_check_is_unix_groups(sid) ||
1484 sid_check_is_in_unix_users(sid) ||
1485 sid_check_is_unix_users(sid) ||
1486 sid_check_is_our_sam(sid) ||
1487 sid_check_is_in_our_sam(sid) )
1489 return find_domain_from_sid(get_global_sam_sid());
1492 if ( sid_check_is_builtin(sid) ||
1493 sid_check_is_in_builtin(sid) ||
1494 sid_check_is_wellknown_domain(sid, NULL) ||
1495 sid_check_is_in_wellknown_domain(sid) )
1497 return find_domain_from_sid(&global_sid_Builtin);
1501 struct winbindd_domain *domain = NULL;
1503 domain = find_domain_from_sid_noinit(sid);
1504 if (domain == NULL) {
1508 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1512 return domain->routing_domain;
1515 /* On a member server a query for SID or name can always go to our
1518 DEBUG(10, ("calling find_our_domain\n"));
1519 return find_our_domain();
1522 struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
1526 if ( strequal(domain_name, unix_users_domain_name() ) ||
1527 strequal(domain_name, unix_groups_domain_name() ) )
1530 * The "Unix User" and "Unix Group" domain our handled by
1533 return find_domain_from_name_noinit( get_global_sam_name() );
1536 if (strequal(domain_name, "BUILTIN") ||
1537 strequal(domain_name, get_global_sam_name())) {
1538 return find_domain_from_name_noinit(domain_name);
1541 predefined = dom_sid_lookup_is_predefined_domain(domain_name);
1543 return find_domain_from_name_noinit(builtin_domain_name());
1547 struct winbindd_domain *domain = NULL;
1549 domain = find_domain_from_name_noinit(domain_name);
1550 if (domain == NULL) {
1554 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1558 return domain->routing_domain;
1561 return find_our_domain();
1564 /* Is this a domain which we may assume no DOMAIN\ prefix? */
1566 static bool assume_domain(const char *domain)
1568 /* never assume the domain on a standalone server */
1570 if ( lp_server_role() == ROLE_STANDALONE )
1573 /* domain member servers may possibly assume for the domain name */
1575 if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
1576 if ( !strequal(lp_workgroup(), domain) )
1579 if ( lp_winbind_use_default_domain() )
1583 /* only left with a domain controller */
1585 if ( strequal(get_global_sam_name(), domain) ) {
1592 /* Parse a DOMAIN\user or UPN string into a domain, namespace and a user */
1593 bool parse_domain_user(const char *domuser,
1600 if (strlen(domuser) == 0) {
1604 p = strchr(domuser, *lp_winbind_separator());
1606 fstrcpy(user, p + 1);
1607 fstrcpy(domain, domuser);
1608 domain[PTR_DIFF(p, domuser)] = '\0';
1609 fstrcpy(namespace, domain);
1611 fstrcpy(user, domuser);
1614 namespace[0] = '\0';
1615 p = strchr(domuser, '@');
1618 fstrcpy(namespace, p + 1);
1619 } else if (assume_domain(lp_workgroup())) {
1620 fstrcpy(domain, lp_workgroup());
1621 fstrcpy(namespace, domain);
1623 fstrcpy(namespace, lp_netbios_name());
1627 return strupper_m(domain);
1630 /* Ensure an incoming username from NSS is fully qualified. Replace the
1631 incoming fstring with DOMAIN <separator> user. Returns the same
1632 values as parse_domain_user() but also replaces the incoming username.
1633 Used to ensure all names are fully qualified within winbindd.
1634 Used by the NSS protocols of auth, chauthtok, logoff and ccache_ntlm_auth.
1635 The protocol definitions of auth_crap, chng_pswd_auth_crap
1636 really should be changed to use this instead of doing things
1639 bool canonicalize_username(fstring username_inout,
1646 ok = parse_domain_user(username_inout, namespace, domain, user);
1650 slprintf(username_inout, sizeof(fstring) - 1, "%s%c%s",
1651 domain, *lp_winbind_separator(),
1657 Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
1658 'winbind separator' options.
1660 - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
1663 If we are a PDC or BDC, and this is for our domain, do likewise.
1665 On an AD DC we always fill DOMAIN\\USERNAME.
1667 We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1670 * talloc version of fill_domain_username()
1671 * return NULL on talloc failure.
1673 char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
1678 char *tmp_user, *name;
1680 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1684 tmp_user = talloc_strdup(mem_ctx, user);
1685 if (!strlower_m(tmp_user)) {
1686 TALLOC_FREE(tmp_user);
1690 if (can_assume && assume_domain(domain)) {
1693 name = talloc_asprintf(mem_ctx, "%s%c%s",
1695 *lp_winbind_separator(),
1697 TALLOC_FREE(tmp_user);
1704 * Client list accessor functions
1707 static struct winbindd_cli_state *_client_list;
1708 static int _num_clients;
1710 /* Return list of all connected clients */
1712 struct winbindd_cli_state *winbindd_client_list(void)
1714 return _client_list;
1717 /* Return list-tail of all connected clients */
1719 struct winbindd_cli_state *winbindd_client_list_tail(void)
1721 return DLIST_TAIL(_client_list);
1724 /* Return previous (read:newer) client in list */
1726 struct winbindd_cli_state *
1727 winbindd_client_list_prev(struct winbindd_cli_state *cli)
1729 return DLIST_PREV(cli);
1732 /* Add a connection to the list */
1734 void winbindd_add_client(struct winbindd_cli_state *cli)
1736 cli->last_access = time(NULL);
1737 DLIST_ADD(_client_list, cli);
1741 /* Remove a client from the list */
1743 void winbindd_remove_client(struct winbindd_cli_state *cli)
1745 DLIST_REMOVE(_client_list, cli);
1749 /* Move a client to head or list */
1751 void winbindd_promote_client(struct winbindd_cli_state *cli)
1753 cli->last_access = time(NULL);
1754 DLIST_PROMOTE(_client_list, cli);
1757 /* Return number of open clients */
1759 int winbindd_num_clients(void)
1761 return _num_clients;
1764 NTSTATUS lookup_usergroups_cached(TALLOC_CTX *mem_ctx,
1765 const struct dom_sid *user_sid,
1766 uint32_t *p_num_groups, struct dom_sid **user_sids)
1768 struct netr_SamInfo3 *info3 = NULL;
1769 NTSTATUS status = NT_STATUS_NO_MEMORY;
1770 uint32_t num_groups = 0;
1772 DEBUG(3,(": lookup_usergroups_cached\n"));
1777 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1779 if (info3 == NULL) {
1780 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1784 * Before bug #7843 the "Domain Local" groups were added with a
1785 * lookupuseraliases call, but this isn't done anymore for our domain
1786 * so we need to resolve resource groups here.
1788 * When to use Resource Groups:
1789 * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
1791 status = sid_array_from_info3(mem_ctx, info3,
1796 if (!NT_STATUS_IS_OK(status)) {
1802 *p_num_groups = num_groups;
1803 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1805 DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1810 /*********************************************************************
1811 We use this to remove spaces from user and group names
1812 ********************************************************************/
1814 NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
1815 const char *domain_name,
1819 struct winbindd_domain *domain = NULL;
1822 if (!name || !normalized) {
1823 return NT_STATUS_INVALID_PARAMETER;
1826 if (!lp_winbind_normalize_names()) {
1827 return NT_STATUS_PROCEDURE_NOT_FOUND;
1830 domain = find_domain_from_name_noinit(domain_name);
1831 if (domain == NULL) {
1832 DBG_ERR("Failed to find domain '%s'\n", domain_name);
1833 return NT_STATUS_NO_SUCH_DOMAIN;
1836 /* Alias support and whitespace replacement are mutually
1839 nt_status = resolve_username_to_alias(mem_ctx, domain,
1841 if (NT_STATUS_IS_OK(nt_status)) {
1842 /* special return code to let the caller know we
1843 mapped to an alias */
1844 return NT_STATUS_FILE_RENAMED;
1847 /* check for an unreachable domain */
1849 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1850 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1852 set_domain_offline(domain);
1856 /* deal with whitespace */
1858 *normalized = talloc_strdup(mem_ctx, name);
1859 if (!(*normalized)) {
1860 return NT_STATUS_NO_MEMORY;
1863 all_string_sub( *normalized, " ", "_", 0 );
1865 return NT_STATUS_OK;
1868 /*********************************************************************
1869 We use this to do the inverse of normalize_name_map()
1870 ********************************************************************/
1872 NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
1877 struct winbindd_domain *domain = find_our_domain();
1879 if (!name || !normalized) {
1880 return NT_STATUS_INVALID_PARAMETER;
1883 if (!lp_winbind_normalize_names()) {
1884 return NT_STATUS_PROCEDURE_NOT_FOUND;
1887 /* Alias support and whitespace replacement are mutally
1890 /* When mapping from an alias to a username, we don't know the
1891 domain. But we only need a domain structure to cache
1892 a successful lookup , so just our own domain structure for
1895 nt_status = resolve_alias_to_username(mem_ctx, domain,
1897 if (NT_STATUS_IS_OK(nt_status)) {
1898 /* Special return code to let the caller know we mapped
1900 return NT_STATUS_FILE_RENAMED;
1903 /* check for an unreachable domain */
1905 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1906 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1908 set_domain_offline(domain);
1912 /* deal with whitespace */
1914 *normalized = talloc_strdup(mem_ctx, name);
1915 if (!(*normalized)) {
1916 return NT_STATUS_NO_MEMORY;
1919 all_string_sub(*normalized, "_", " ", 0);
1921 return NT_STATUS_OK;
1924 /*********************************************************************
1925 ********************************************************************/
1927 bool winbindd_can_contact_domain(struct winbindd_domain *domain)
1929 struct winbindd_tdc_domain *tdc = NULL;
1930 TALLOC_CTX *frame = talloc_stackframe();
1933 /* We can contact the domain if it is our primary domain */
1935 if (domain->primary) {
1940 /* Trust the TDC cache and not the winbindd_domain flags */
1942 if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
1943 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
1949 /* Can always contact a domain that is in out forest */
1951 if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1957 * On a _member_ server, we cannot contact the domain if it
1958 * is running AD and we have no inbound trust.
1962 domain->active_directory &&
1963 ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
1965 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
1966 "and we have no inbound trust.\n", domain->name));
1970 /* Assume everything else is ok (probably not true but what
1976 talloc_destroy(frame);
1981 #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
1983 /*********************************************************************
1984 ********************************************************************/
1986 static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
1989 char addr[INET6_ADDRSTRLEN];
1990 const char *kdc = NULL;
1993 if (!domain || !domain->alt_name || !*domain->alt_name) {
1997 if (domain->initialized && !domain->active_directory) {
1998 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
2003 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
2006 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
2008 kdc = domain->dcname;
2011 if (!kdc || !*kdc) {
2012 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
2017 if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
2018 domain->alt_name) == -1) {
2022 DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
2025 setenv(var, kdc, 1);
2029 /*********************************************************************
2030 ********************************************************************/
2032 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2034 struct winbindd_domain *our_dom = find_our_domain();
2036 winbindd_set_locator_kdc_env(domain);
2038 if (domain != our_dom) {
2039 winbindd_set_locator_kdc_env(our_dom);
2043 /*********************************************************************
2044 ********************************************************************/
2046 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2050 if (!domain || !domain->alt_name || !*domain->alt_name) {
2054 if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
2055 domain->alt_name) == -1) {
2064 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2069 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2074 #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
2076 void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
2078 resp->data.auth.nt_status = NT_STATUS_V(result);
2079 fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
2081 /* we might have given a more useful error above */
2082 if (*resp->data.auth.error_string == '\0')
2083 fstrcpy(resp->data.auth.error_string,
2084 get_friendly_nt_error_msg(result));
2085 resp->data.auth.pam_error = nt_status_to_pam(result);
2088 bool is_domain_offline(const struct winbindd_domain *domain)
2090 if (get_global_winbindd_state_offline()) {
2093 return !domain->online;
2096 bool is_domain_online(const struct winbindd_domain *domain)
2098 return !is_domain_offline(domain);
2102 * Parse an char array into a list of sids.
2104 * The input sidstr should consist of 0-terminated strings
2105 * representing sids, separated by newline characters '\n'.
2106 * The list is terminated by an empty string, i.e.
2107 * character '\0' directly following a character '\n'
2108 * (or '\0' right at the start of sidstr).
2110 bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
2111 struct dom_sid **sids, uint32_t *num_sids)
2119 while (p[0] != '\0') {
2121 const char *q = NULL;
2123 if (!dom_sid_parse_endp(p, &sid, &q)) {
2124 DEBUG(1, ("Could not parse sid %s\n", p));
2128 DEBUG(1, ("Got invalid sidstr: %s\n", p));
2131 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
2141 bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
2142 struct unixid **pxids, uint32_t *pnum_xids)
2145 struct unixid *xids = NULL;
2146 uint32_t num_xids = 0;
2153 while (p[0] != '\0') {
2156 unsigned long long id;
2162 xid = (struct unixid) { .type = ID_TYPE_UID };
2165 xid = (struct unixid) { .type = ID_TYPE_GID };
2173 id = strtoull_err(p, &endp, 10, &error);
2177 if (*endp != '\n') {
2183 if ((unsigned long long)xid.id != id) {
2187 tmp = talloc_realloc(mem_ctx, xids, struct unixid, num_xids+1);
2193 xids[num_xids] = xid;
2198 *pnum_xids = num_xids;