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 static bool is_in_internal_domain(const struct dom_sid *sid)
116 return (sid_check_is_in_our_sam(sid) || sid_check_is_in_builtin(sid));
120 /* Add a trusted domain to our list of domains.
121 If the domain already exists in the list,
122 return it and don't re-initialize. */
124 static NTSTATUS add_trusted_domain(const char *domain_name,
125 const char *dns_name,
126 const struct dom_sid *sid,
128 uint32_t trust_flags,
129 uint32_t trust_attribs,
130 enum netr_SchannelType secure_channel_type,
131 struct winbindd_domain *routing_domain,
132 struct winbindd_domain **_d)
134 struct winbindd_domain *domain = NULL;
135 const char **ignored_domains = NULL;
136 const char **dom = NULL;
137 int role = lp_server_role();
139 if (is_null_sid(sid)) {
140 DBG_ERR("Got null SID for domain [%s]\n", domain_name);
141 return NT_STATUS_INVALID_PARAMETER;
144 ignored_domains = lp_parm_string_list(-1, "winbind", "ignore domains", NULL);
145 for (dom=ignored_domains; dom && *dom; dom++) {
146 if (gen_fnmatch(*dom, domain_name) == 0) {
147 DEBUG(2,("Ignoring domain '%s'\n", domain_name));
148 return NT_STATUS_NO_SUCH_DOMAIN;
153 * We can't call domain_list() as this function is called from
154 * init_domain_list() and we'll get stuck in a loop.
156 for (domain = _domain_list; domain; domain = domain->next) {
157 if (strequal(domain_name, domain->name)) {
162 if (domain != NULL) {
163 struct winbindd_domain *check_domain = NULL;
165 for (check_domain = _domain_list;
166 check_domain != NULL;
167 check_domain = check_domain->next)
169 if (check_domain == domain) {
173 if (dom_sid_equal(&check_domain->sid, sid)) {
178 if (check_domain != NULL) {
179 DBG_ERR("SID [%s] already used by domain [%s], "
181 sid_string_dbg(sid), check_domain->name,
183 return NT_STATUS_INVALID_PARAMETER;
187 if ((domain != NULL) && (dns_name != NULL)) {
188 struct winbindd_domain *check_domain = NULL;
190 for (check_domain = _domain_list;
191 check_domain != NULL;
192 check_domain = check_domain->next)
194 if (check_domain == domain) {
198 if (strequal(check_domain->alt_name, dns_name)) {
203 if (check_domain != NULL) {
204 DBG_ERR("DNS name [%s] used by domain [%s], "
206 dns_name, check_domain->name,
208 return NT_STATUS_INVALID_PARAMETER;
212 if (domain != NULL) {
217 /* Create new domain entry */
218 domain = talloc_zero(NULL, struct winbindd_domain);
219 if (domain == NULL) {
220 return NT_STATUS_NO_MEMORY;
223 domain->children = talloc_zero_array(domain,
224 struct winbindd_child,
225 lp_winbind_max_domain_connections());
226 if (domain->children == NULL) {
228 return NT_STATUS_NO_MEMORY;
231 domain->name = talloc_strdup(domain, domain_name);
232 if (domain->name == NULL) {
234 return NT_STATUS_NO_MEMORY;
237 if (dns_name != NULL) {
238 domain->alt_name = talloc_strdup(domain, dns_name);
239 if (domain->alt_name == NULL) {
241 return NT_STATUS_NO_MEMORY;
245 domain->backend = NULL;
246 domain->internal = is_internal_domain(sid);
247 domain->secure_channel_type = secure_channel_type;
248 domain->sequence_number = DOM_SEQUENCE_NONE;
249 domain->last_seq_check = 0;
250 domain->initialized = false;
251 domain->online = is_internal_domain(sid);
252 domain->check_online_timeout = 0;
253 domain->dc_probe_pid = (pid_t)-1;
254 domain->domain_flags = trust_flags;
255 domain->domain_type = trust_type;
256 domain->domain_trust_attribs = trust_attribs;
257 domain->secure_channel_type = secure_channel_type;
258 domain->routing_domain = routing_domain;
259 sid_copy(&domain->sid, sid);
261 /* Is this our primary domain ? */
262 if (role == ROLE_DOMAIN_MEMBER) {
263 domain->primary = strequal(domain_name, lp_workgroup());
265 domain->primary = strequal(domain_name, get_global_sam_name());
268 if (domain->primary) {
269 if (role == ROLE_ACTIVE_DIRECTORY_DC) {
270 domain->active_directory = true;
272 if (lp_security() == SEC_ADS) {
273 domain->active_directory = true;
275 } else if (!domain->internal) {
276 if (domain->domain_type == LSA_TRUST_TYPE_UPLEVEL) {
277 domain->active_directory = true;
281 domain->can_do_ncacn_ip_tcp = domain->active_directory;
283 /* Link to domain list */
284 DLIST_ADD_END(_domain_list, domain);
286 wcache_tdc_add_domain( domain );
288 setup_domain_child(domain);
290 DBG_NOTICE("Added domain [%s] [%s] [%s]\n",
291 domain->name, domain->alt_name,
292 sid_string_dbg(&domain->sid));
298 bool set_routing_domain(struct winbindd_domain *domain,
299 struct winbindd_domain *routing_domain)
301 if (domain->routing_domain == NULL) {
302 domain->routing_domain = routing_domain;
305 if (domain->routing_domain != routing_domain) {
311 bool add_trusted_domain_from_auth(uint16_t validation_level,
312 struct info3_text *info3,
313 struct info6_text *info6)
315 struct winbindd_domain *domain = NULL;
316 struct dom_sid domain_sid;
317 const char *dns_domainname = NULL;
322 * We got a successfull auth from a domain that might not yet be in our
323 * domain list. If we're a member we trust our DC who authenticated the
324 * user from that domain and add the domain to our list on-the-fly. If
325 * we're a DC we rely on configured trusts and don't add on-the-fly.
332 ok = dom_sid_parse(info3->dom_sid, &domain_sid);
334 DBG_NOTICE("dom_sid_parse [%s] failed\n", info3->dom_sid);
338 if (validation_level == 6) {
339 dns_domainname = &info6->dns_domainname[0];
342 status = add_trusted_domain(info3->logon_dom,
346 NETR_TRUST_FLAG_OUTBOUND,
349 find_default_route_domain(),
351 if (!NT_STATUS_IS_OK(status) &&
352 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
354 DBG_DEBUG("Adding domain [%s] with sid [%s] failed\n",
355 info3->logon_dom, info3->dom_sid);
362 bool domain_is_forest_root(const struct winbindd_domain *domain)
364 const uint32_t fr_flags =
365 (NETR_TRUST_FLAG_TREEROOT|NETR_TRUST_FLAG_IN_FOREST);
367 return ((domain->domain_flags & fr_flags) == fr_flags);
370 /********************************************************************
371 rescan our domains looking for new trusted domains
372 ********************************************************************/
374 struct trustdom_state {
375 struct winbindd_domain *domain;
376 struct winbindd_request request;
379 static void trustdom_list_done(struct tevent_req *req);
380 static void rescan_forest_root_trusts( void );
381 static void rescan_forest_trusts( void );
383 static void add_trusted_domains( struct winbindd_domain *domain )
385 struct trustdom_state *state;
386 struct tevent_req *req;
388 state = talloc_zero(NULL, struct trustdom_state);
390 DEBUG(0, ("talloc failed\n"));
393 state->domain = domain;
395 state->request.length = sizeof(state->request);
396 state->request.cmd = WINBINDD_LIST_TRUSTDOM;
398 req = wb_domain_request_send(state, server_event_context(),
399 domain, &state->request);
401 DEBUG(1, ("wb_domain_request_send failed\n"));
405 tevent_req_set_callback(req, trustdom_list_done, state);
408 static void trustdom_list_done(struct tevent_req *req)
410 struct trustdom_state *state = tevent_req_callback_data(
411 req, struct trustdom_state);
412 struct winbindd_response *response;
416 bool within_forest = false;
420 * Only when we enumerate our primary domain
421 * or our forest root domain, we should keep
422 * the NETR_TRUST_FLAG_IN_FOREST flag, in
423 * all other cases we need to clear it as the domain
424 * is not part of our forest.
426 if (state->domain->primary) {
427 within_forest = true;
428 } else if (domain_is_forest_root(state->domain)) {
429 within_forest = true;
432 res = wb_domain_request_recv(req, state, &response, &err);
433 if ((res == -1) || (response->result != WINBINDD_OK)) {
434 DBG_WARNING("Could not receive trusts for domain %s\n",
435 state->domain->name);
440 if (response->length < sizeof(struct winbindd_response)) {
441 DBG_ERR("ill-formed trustdom response - short length\n");
446 extra_len = response->length - sizeof(struct winbindd_response);
448 p = (char *)response->extra_data.data;
450 while ((p - (char *)response->extra_data.data) < extra_len) {
451 struct winbindd_domain *domain = NULL;
452 char *name, *q, *sidstr, *alt_name;
455 uint32_t trust_attribs;
456 uint32_t trust_flags;
458 DBG_DEBUG("parsing response line '%s'\n", p);
462 alt_name = strchr(p, '\\');
463 if (alt_name == NULL) {
464 DBG_ERR("Got invalid trustdom response\n");
471 sidstr = strchr(alt_name, '\\');
472 if (sidstr == NULL) {
473 DBG_ERR("Got invalid trustdom response\n");
480 /* use the real alt_name if we have one, else pass in NULL */
481 if (strequal(alt_name, "(null)")) {
485 q = strtok(sidstr, "\\");
487 DBG_ERR("Got invalid trustdom response\n");
491 if (!string_to_sid(&sid, sidstr)) {
492 DEBUG(0, ("Got invalid trustdom response\n"));
496 q = strtok(NULL, "\\");
498 DBG_ERR("Got invalid trustdom response\n");
502 trust_flags = (uint32_t)strtoul(q, NULL, 10);
504 q = strtok(NULL, "\\");
506 DBG_ERR("Got invalid trustdom response\n");
510 trust_type = (uint32_t)strtoul(q, NULL, 10);
512 q = strtok(NULL, "\n");
514 DBG_ERR("Got invalid trustdom response\n");
518 trust_attribs = (uint32_t)strtoul(q, NULL, 10);
520 if (!within_forest) {
521 trust_flags &= ~NETR_TRUST_FLAG_IN_FOREST;
524 if (!state->domain->primary) {
525 trust_flags &= ~NETR_TRUST_FLAG_PRIMARY;
529 * We always call add_trusted_domain() cause on an existing
530 * domain structure, it will update the SID if necessary.
531 * This is important because we need the SID for sibling
534 status = add_trusted_domain(name,
541 find_default_route_domain(),
543 if (!NT_STATUS_IS_OK(status) &&
544 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
546 DBG_NOTICE("add_trusted_domain returned %s\n",
551 p = q + strlen(q) + 1;
555 Cases to consider when scanning trusts:
556 (a) we are calling from a child domain (primary && !forest_root)
557 (b) we are calling from the root of the forest (primary && forest_root)
558 (c) we are calling from a trusted forest domain (!primary
562 if (state->domain->primary) {
563 /* If this is our primary domain and we are not in the
564 forest root, we have to scan the root trusts first */
566 if (!domain_is_forest_root(state->domain))
567 rescan_forest_root_trusts();
569 rescan_forest_trusts();
571 } else if (domain_is_forest_root(state->domain)) {
572 /* Once we have done root forest trust search, we can
573 go on to search the trusted forests */
575 rescan_forest_trusts();
583 /********************************************************************
584 Scan the trusts of our forest root
585 ********************************************************************/
587 static void rescan_forest_root_trusts( void )
589 struct winbindd_tdc_domain *dom_list = NULL;
590 size_t num_trusts = 0;
594 /* The only transitive trusts supported by Windows 2003 AD are
595 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
596 first two are handled in forest and listed by
597 DsEnumerateDomainTrusts(). Forest trusts are not so we
598 have to do that ourselves. */
600 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
603 for ( i=0; i<num_trusts; i++ ) {
604 struct winbindd_domain *d = NULL;
606 /* Find the forest root. Don't necessarily trust
607 the domain_list() as our primary domain may not
608 have been initialized. */
610 if ( !(dom_list[i].trust_flags & NETR_TRUST_FLAG_TREEROOT) ) {
614 /* Here's the forest root */
616 d = find_domain_from_name_noinit( dom_list[i].domain_name );
618 status = add_trusted_domain(dom_list[i].domain_name,
619 dom_list[i].dns_name,
621 dom_list[i].trust_type,
622 dom_list[i].trust_flags,
623 dom_list[i].trust_attribs,
625 find_default_route_domain(),
628 if (!NT_STATUS_IS_OK(status) &&
629 NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
631 DBG_ERR("add_trusted_domain returned %s\n",
640 DEBUG(10,("rescan_forest_root_trusts: Following trust path "
641 "for domain tree root %s (%s)\n",
642 d->name, d->alt_name ));
644 d->domain_flags = dom_list[i].trust_flags;
645 d->domain_type = dom_list[i].trust_type;
646 d->domain_trust_attribs = dom_list[i].trust_attribs;
648 add_trusted_domains( d );
653 TALLOC_FREE( dom_list );
658 /********************************************************************
659 scan the transitive forest trusts (not our own)
660 ********************************************************************/
663 static void rescan_forest_trusts( void )
665 struct winbindd_domain *d = NULL;
666 struct winbindd_tdc_domain *dom_list = NULL;
667 size_t num_trusts = 0;
671 /* The only transitive trusts supported by Windows 2003 AD are
672 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
673 first two are handled in forest and listed by
674 DsEnumerateDomainTrusts(). Forest trusts are not so we
675 have to do that ourselves. */
677 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
680 for ( i=0; i<num_trusts; i++ ) {
681 uint32_t flags = dom_list[i].trust_flags;
682 uint32_t type = dom_list[i].trust_type;
683 uint32_t attribs = dom_list[i].trust_attribs;
685 d = find_domain_from_name_noinit( dom_list[i].domain_name );
687 /* ignore our primary and internal domains */
689 if ( d && (d->internal || d->primary ) )
692 if ( (flags & NETR_TRUST_FLAG_INBOUND) &&
693 (type == LSA_TRUST_TYPE_UPLEVEL) &&
694 (attribs == LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) )
696 /* add the trusted domain if we don't know
700 status = add_trusted_domain(
701 dom_list[i].domain_name,
702 dom_list[i].dns_name,
708 find_default_route_domain(),
710 if (!NT_STATUS_IS_OK(status) &&
711 NT_STATUS_EQUAL(status,
712 NT_STATUS_NO_SUCH_DOMAIN))
714 DBG_ERR("add_trusted_domain: %s\n",
724 DEBUG(10,("Following trust path for domain %s (%s)\n",
725 d->name, d->alt_name ));
726 add_trusted_domains( d );
730 TALLOC_FREE( dom_list );
735 /*********************************************************************
736 The process of updating the trusted domain list is a three step
739 (b) ask the root domain in our forest
740 (c) ask the a DC in any Win2003 trusted forests
741 *********************************************************************/
743 void rescan_trusted_domains(struct tevent_context *ev, struct tevent_timer *te,
744 struct timeval now, void *private_data)
748 /* I use to clear the cache here and start over but that
749 caused problems in child processes that needed the
750 trust dom list early on. Removing it means we
751 could have some trusted domains listed that have been
752 removed from our primary domain's DC until a full
753 restart. This should be ok since I think this is what
754 Windows does as well. */
756 /* this will only add new domains we didn't already know about
757 in the domain_list()*/
759 add_trusted_domains( find_our_domain() );
761 te = tevent_add_timer(
762 ev, NULL, timeval_current_ofs(WINBINDD_RESCAN_FREQ, 0),
763 rescan_trusted_domains, NULL);
765 * If te == NULL, there's not much we can do here. Don't fail, the
766 * only thing we miss is new trusted domains.
772 enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domain,
773 struct winbindd_cli_state *state)
775 /* Ensure null termination */
776 state->request->domain_name
777 [sizeof(state->request->domain_name)-1]='\0';
778 state->request->data.init_conn.dcname
779 [sizeof(state->request->data.init_conn.dcname)-1]='\0';
781 if (strlen(state->request->data.init_conn.dcname) > 0) {
782 fstrcpy(domain->dcname, state->request->data.init_conn.dcname);
785 init_dc_connection(domain, false);
787 if (!domain->initialized) {
788 /* If we return error here we can't do any cached authentication,
789 but we may be in disconnected mode and can't initialize correctly.
790 Do what the previous code did and just return without initialization,
791 once we go online we'll re-initialize.
793 DEBUG(5, ("winbindd_dual_init_connection: %s returning without initialization "
794 "online = %d\n", domain->name, (int)domain->online ));
797 fstrcpy(state->response->data.domain_info.name, domain->name);
798 fstrcpy(state->response->data.domain_info.alt_name, domain->alt_name);
799 sid_to_fstring(state->response->data.domain_info.sid, &domain->sid);
801 state->response->data.domain_info.native_mode
802 = domain->native_mode;
803 state->response->data.domain_info.active_directory
804 = domain->active_directory;
805 state->response->data.domain_info.primary
811 static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
814 struct server_id server_id,
819 DBG_NOTICE("Rescanning trusted domains\n");
821 ok = add_trusted_domains_dc();
823 DBG_ERR("Failed to reload trusted domains\n");
828 * We did not get the secret when we queried secrets.tdb, so read it
829 * from secrets.tdb and re-sync the databases
831 static bool migrate_secrets_tdb_to_ldb(struct winbindd_domain *domain)
834 struct cli_credentials *creds;
835 NTSTATUS can_migrate = pdb_get_trust_credentials(domain->name,
836 NULL, domain, &creds);
837 if (!NT_STATUS_IS_OK(can_migrate)) {
838 DEBUG(0, ("Failed to fetch our own, local AD domain join "
839 "password for winbindd's internal use, both from "
840 "secrets.tdb and secrets.ldb: %s\n",
841 nt_errstr(can_migrate)));
846 * NOTE: It is very unlikely we end up here if there is an
847 * oldpass, because a new password is created at
848 * classicupgrade, so this is not a concern.
850 ok = secrets_store_machine_pw_sync(cli_credentials_get_password(creds),
852 cli_credentials_get_domain(creds),
853 cli_credentials_get_realm(creds),
854 cli_credentials_get_salt_principal(creds),
855 0, /* Supported enc types, unused */
857 cli_credentials_get_password_last_changed_time(creds),
858 cli_credentials_get_secure_channel_type(creds),
859 false /* do_delete: Do not delete */);
862 DEBUG(0, ("Failed to write our our own, "
863 "local AD domain join password for "
864 "winbindd's internal use into secrets.tdb\n"));
870 static bool add_trusted_domains_dc(void)
872 struct winbindd_domain *domain = NULL;
873 struct pdb_trusted_domain **domains = NULL;
874 uint32_t num_domains = 0;
878 if (!(pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX)) {
879 struct trustdom_info **ti = NULL;
881 status = pdb_enum_trusteddoms(talloc_tos(), &num_domains, &ti);
882 if (!NT_STATUS_IS_OK(status)) {
883 DBG_ERR("pdb_enum_trusteddoms() failed - %s\n",
888 for (i = 0; i < num_domains; i++) {
889 status = add_trusted_domain(ti[i]->name,
892 LSA_TRUST_TYPE_DOWNLEVEL,
893 NETR_TRUST_FLAG_OUTBOUND,
898 if (!NT_STATUS_IS_OK(status)) {
899 DBG_NOTICE("add_trusted_domain returned %s\n",
904 /* Even in the parent winbindd we'll need to
905 talk to the DC, so try and see if we can
906 contact it. Theoretically this isn't neccessary
907 as the init_dc_connection() in init_child_recv()
908 will do this, but we can start detecting the DC
910 set_domain_online_request(domain);
916 status = pdb_enum_trusted_domains(talloc_tos(), &num_domains, &domains);
917 if (!NT_STATUS_IS_OK(status)) {
918 DBG_ERR("pdb_enum_trusted_domains() failed - %s\n",
923 for (i = 0; i < num_domains; i++) {
924 enum netr_SchannelType sec_chan_type = SEC_CHAN_DOMAIN;
925 uint32_t trust_flags = 0;
927 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
928 sec_chan_type = SEC_CHAN_DNS_DOMAIN;
931 if (!(domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
932 sec_chan_type = SEC_CHAN_NULL;
935 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
936 trust_flags |= NETR_TRUST_FLAG_INBOUND;
938 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
939 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
941 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
942 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
945 status = add_trusted_domain(domains[i]->netbios_name,
946 domains[i]->domain_name,
947 &domains[i]->security_identifier,
948 domains[i]->trust_type,
950 domains[i]->trust_attributes,
954 if (!NT_STATUS_IS_OK(status)) {
955 DBG_NOTICE("add_trusted_domain returned %s\n",
960 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
961 domain->active_directory = true;
963 domain->domain_type = domains[i]->trust_type;
964 domain->domain_trust_attribs = domains[i]->trust_attributes;
966 if (sec_chan_type != SEC_CHAN_NULL) {
967 /* Even in the parent winbindd we'll need to
968 talk to the DC, so try and see if we can
969 contact it. Theoretically this isn't neccessary
970 as the init_dc_connection() in init_child_recv()
971 will do this, but we can start detecting the DC
973 set_domain_online_request(domain);
977 for (i = 0; i < num_domains; i++) {
978 struct ForestTrustInfo fti;
980 enum ndr_err_code ndr_err;
981 struct winbindd_domain *routing_domain = NULL;
983 if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
987 if (!(domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
991 if (domains[i]->trust_forest_trust_info.length == 0) {
995 routing_domain = find_domain_from_name_noinit(
996 domains[i]->netbios_name);
997 if (routing_domain == NULL) {
998 DBG_ERR("Can't find winbindd domain [%s]\n",
999 domains[i]->netbios_name);
1003 ndr_err = ndr_pull_struct_blob_all(
1004 &domains[i]->trust_forest_trust_info,
1006 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
1007 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1008 DBG_ERR("ndr_pull_ForestTrustInfo(%s) - %s\n",
1009 domains[i]->netbios_name,
1010 ndr_map_error2string(ndr_err));
1014 for (fi = 0; fi < fti.count; fi++) {
1015 struct ForestTrustInfoRecord *rec =
1016 &fti.records[fi].record;
1017 struct ForestTrustDataDomainInfo *drec = NULL;
1019 if (rec->type != FOREST_TRUST_DOMAIN_INFO) {
1022 drec = &rec->data.info;
1024 if (rec->flags & LSA_NB_DISABLED_MASK) {
1028 if (rec->flags & LSA_SID_DISABLED_MASK) {
1034 * also try to find a matching
1035 * LSA_TLN_DISABLED_MASK ???
1038 domain = find_domain_from_name_noinit(drec->netbios_name.string);
1039 if (domain != NULL) {
1043 status = add_trusted_domain(drec->netbios_name.string,
1044 drec->dns_name.string,
1046 LSA_TRUST_TYPE_UPLEVEL,
1047 NETR_TRUST_FLAG_OUTBOUND,
1052 if (!NT_STATUS_IS_OK(status)) {
1053 DBG_NOTICE("add_trusted_domain returned %s\n",
1057 if (domain == NULL) {
1067 /* Look up global info for the winbind daemon */
1068 bool init_domain_list(void)
1070 int role = lp_server_role();
1071 struct pdb_domain_info *pdb_domain_info = NULL;
1072 struct winbindd_domain *domain = NULL;
1076 /* Free existing list */
1079 /* BUILTIN domain */
1081 status = add_trusted_domain("BUILTIN",
1083 &global_sid_Builtin,
1084 LSA_TRUST_TYPE_DOWNLEVEL,
1085 0, /* trust_flags */
1086 0, /* trust_attribs */
1090 if (!NT_STATUS_IS_OK(status)) {
1091 DBG_ERR("add_trusted_domain BUILTIN returned %s\n",
1099 * In case the passdb backend is passdb_dsdb the domain SID comes from
1100 * dsdb, not from secrets.tdb. As we use the domain SID in various
1101 * places, we must ensure the domain SID is migrated from dsdb to
1102 * secrets.tdb before get_global_sam_sid() is called the first time.
1104 * The migration is done as part of the passdb_dsdb initialisation,
1105 * calling pdb_get_domain_info() triggers it.
1107 pdb_domain_info = pdb_get_domain_info(talloc_tos());
1109 if ( role == ROLE_ACTIVE_DIRECTORY_DC ) {
1110 uint32_t trust_flags;
1112 enum netr_SchannelType sec_chan_type;
1113 const char *account_name;
1114 struct samr_Password current_nt_hash;
1116 if (pdb_domain_info == NULL) {
1117 DEBUG(0, ("Failed to fetch our own, local AD "
1118 "domain info from sam.ldb\n"));
1122 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1123 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1124 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1125 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1127 is_root = strequal(pdb_domain_info->dns_domain,
1128 pdb_domain_info->dns_forest);
1130 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1133 status = add_trusted_domain(pdb_domain_info->name,
1134 pdb_domain_info->dns_domain,
1135 &pdb_domain_info->sid,
1136 LSA_TRUST_TYPE_UPLEVEL,
1138 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1142 TALLOC_FREE(pdb_domain_info);
1143 if (!NT_STATUS_IS_OK(status)) {
1144 DBG_ERR("Failed to add our own, local AD "
1145 "domain to winbindd's internal list\n");
1150 * We need to call this to find out if we are an RODC
1152 ok = get_trust_pw_hash(domain->name,
1153 current_nt_hash.hash,
1158 * If get_trust_pw_hash() fails, then try and
1159 * fetch the password from the more recent of
1160 * secrets.{ldb,tdb} using the
1161 * pdb_get_trust_credentials()
1163 ok = migrate_secrets_tdb_to_ldb(domain);
1166 DEBUG(0, ("Failed to migrate our own, "
1167 "local AD domain join password for "
1168 "winbindd's internal use into "
1172 ok = get_trust_pw_hash(domain->name,
1173 current_nt_hash.hash,
1177 DEBUG(0, ("Failed to find our our own, just "
1178 "written local AD domain join "
1179 "password for winbindd's internal "
1180 "use in secrets.tdb\n"));
1185 domain->secure_channel_type = sec_chan_type;
1186 if (sec_chan_type == SEC_CHAN_RODC) {
1187 domain->rodc = true;
1191 uint32_t trust_flags;
1192 enum netr_SchannelType secure_channel_type;
1194 trust_flags = NETR_TRUST_FLAG_OUTBOUND;
1195 if (role != ROLE_DOMAIN_MEMBER) {
1196 trust_flags |= NETR_TRUST_FLAG_PRIMARY;
1199 if (role > ROLE_DOMAIN_MEMBER) {
1200 secure_channel_type = SEC_CHAN_BDC;
1202 secure_channel_type = SEC_CHAN_LOCAL;
1205 status = add_trusted_domain(get_global_sam_name(),
1207 get_global_sam_sid(),
1208 LSA_TRUST_TYPE_DOWNLEVEL,
1210 0, /* trust_attribs */
1211 secure_channel_type,
1214 if (!NT_STATUS_IS_OK(status)) {
1215 DBG_ERR("Failed to add local SAM to "
1216 "domain to winbindd's internal list\n");
1222 ok = add_trusted_domains_dc();
1224 DBG_ERR("init_domain_list_dc failed\n");
1229 if ( role == ROLE_DOMAIN_MEMBER ) {
1230 struct dom_sid our_sid;
1231 uint32_t trust_type;
1233 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
1234 DEBUG(0, ("Could not fetch our SID - did we join?\n"));
1238 if (lp_realm() != NULL) {
1239 trust_type = LSA_TRUST_TYPE_UPLEVEL;
1241 trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1244 status = add_trusted_domain(lp_workgroup(),
1248 NETR_TRUST_FLAG_PRIMARY|
1249 NETR_TRUST_FLAG_OUTBOUND,
1250 0, /* trust_attribs */
1254 if (!NT_STATUS_IS_OK(status)) {
1255 DBG_ERR("Failed to add local SAM to "
1256 "domain to winbindd's internal list\n");
1259 /* Even in the parent winbindd we'll need to
1260 talk to the DC, so try and see if we can
1261 contact it. Theoretically this isn't neccessary
1262 as the init_dc_connection() in init_child_recv()
1263 will do this, but we can start detecting the DC
1265 set_domain_online_request(domain);
1269 status = imessaging_register(winbind_imessaging_context(), NULL,
1270 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1271 wb_imsg_new_trusted_domain);
1272 if (!NT_STATUS_IS_OK(status)) {
1273 DBG_ERR("imessaging_register failed %s\n", nt_errstr(status));
1281 * Given a domain name, return the struct winbindd domain info for it
1283 * @note Do *not* pass lp_workgroup() to this function. domain_list
1284 * may modify it's value, and free that pointer. Instead, our local
1285 * domain may be found by calling find_our_domain().
1289 * @return The domain structure for the named domain, if it is working.
1292 struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
1294 struct winbindd_domain *domain;
1296 /* Search through list */
1298 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1299 if (strequal(domain_name, domain->name)) {
1302 if (domain->alt_name == NULL) {
1305 if (strequal(domain_name, domain->alt_name)) {
1316 * Given a domain name, return the struct winbindd domain if it's a direct
1319 * @return The domain structure for the named domain, if it is a direct outgoing trust
1321 struct winbindd_domain *find_trust_from_name_noinit(const char *domain_name)
1323 struct winbindd_domain *domain = NULL;
1325 domain = find_domain_from_name_noinit(domain_name);
1326 if (domain == NULL) {
1330 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1337 struct winbindd_domain *find_domain_from_name(const char *domain_name)
1339 struct winbindd_domain *domain;
1341 domain = find_domain_from_name_noinit(domain_name);
1346 if (!domain->initialized)
1347 init_dc_connection(domain, false);
1352 /* Given a domain sid, return the struct winbindd domain info for it */
1354 struct winbindd_domain *find_domain_from_sid_noinit(const struct dom_sid *sid)
1356 struct winbindd_domain *domain;
1358 /* Search through list */
1360 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1361 if (dom_sid_compare_domain(sid, &domain->sid) == 0)
1371 * Given a domain sid, return the struct winbindd domain if it's a direct
1374 * @return The domain structure for the specified domain, if it is a direct outgoing trust
1376 struct winbindd_domain *find_trust_from_sid_noinit(const struct dom_sid *sid)
1378 struct winbindd_domain *domain = NULL;
1380 domain = find_domain_from_sid_noinit(sid);
1381 if (domain == NULL) {
1385 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1392 /* Given a domain sid, return the struct winbindd domain info for it */
1394 struct winbindd_domain *find_domain_from_sid(const struct dom_sid *sid)
1396 struct winbindd_domain *domain;
1398 domain = find_domain_from_sid_noinit(sid);
1403 if (!domain->initialized)
1404 init_dc_connection(domain, false);
1409 struct winbindd_domain *find_our_domain(void)
1411 struct winbindd_domain *domain;
1413 /* Search through list */
1415 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1416 if (domain->primary)
1420 smb_panic("Could not find our domain");
1424 struct winbindd_domain *find_default_route_domain(void)
1427 return find_our_domain();
1429 DBG_DEBUG("Routing logic not yet implemented on a DC\n");
1433 /* Find the appropriate domain to lookup a name or SID */
1435 struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)
1437 DBG_DEBUG("SID [%s]\n", sid_string_dbg(sid));
1440 * SIDs in the S-1-22-{1,2} domain and well-known SIDs should be handled
1444 if ( sid_check_is_in_unix_groups(sid) ||
1445 sid_check_is_unix_groups(sid) ||
1446 sid_check_is_in_unix_users(sid) ||
1447 sid_check_is_unix_users(sid) ||
1448 sid_check_is_wellknown_domain(sid, NULL) ||
1449 sid_check_is_in_wellknown_domain(sid) )
1451 return find_domain_from_sid(get_global_sam_sid());
1455 * On member servers the internal domains are different: These are part
1459 if (is_internal_domain(sid) || is_in_internal_domain(sid)) {
1460 DEBUG(10, ("calling find_domain_from_sid\n"));
1461 return find_domain_from_sid(sid);
1465 struct winbindd_domain *domain = NULL;
1467 domain = find_domain_from_sid_noinit(sid);
1468 if (domain == NULL) {
1472 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1476 return domain->routing_domain;
1479 /* On a member server a query for SID or name can always go to our
1482 DEBUG(10, ("calling find_our_domain\n"));
1483 return find_our_domain();
1486 struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
1488 if ( strequal(domain_name, unix_users_domain_name() ) ||
1489 strequal(domain_name, unix_groups_domain_name() ) )
1492 * The "Unix User" and "Unix Group" domain our handled by
1495 return find_domain_from_name_noinit( get_global_sam_name() );
1498 if (strequal(domain_name, "BUILTIN") ||
1499 strequal(domain_name, get_global_sam_name()))
1500 return find_domain_from_name_noinit(domain_name);
1503 struct winbindd_domain *domain = NULL;
1505 domain = find_domain_from_name_noinit(domain_name);
1506 if (domain == NULL) {
1510 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1514 return domain->routing_domain;
1517 return find_our_domain();
1520 /* Is this a domain which we may assume no DOMAIN\ prefix? */
1522 static bool assume_domain(const char *domain)
1524 /* never assume the domain on a standalone server */
1526 if ( lp_server_role() == ROLE_STANDALONE )
1529 /* domain member servers may possibly assume for the domain name */
1531 if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
1532 if ( !strequal(lp_workgroup(), domain) )
1535 if ( lp_winbind_use_default_domain() )
1539 /* only left with a domain controller */
1541 if ( strequal(get_global_sam_name(), domain) ) {
1548 /* Parse a string of the form DOMAIN\user into a domain and a user */
1550 bool parse_domain_user(const char *domuser, fstring domain, fstring user)
1552 char *p = strchr(domuser,*lp_winbind_separator());
1555 fstrcpy(user, domuser);
1556 p = strchr(domuser, '@');
1558 if ( assume_domain(lp_workgroup()) && p == NULL) {
1559 fstrcpy(domain, lp_workgroup());
1560 } else if (p != NULL) {
1561 fstrcpy(domain, p + 1);
1562 user[PTR_DIFF(p, domuser)] = 0;
1568 fstrcpy(domain, domuser);
1569 domain[PTR_DIFF(p, domuser)] = 0;
1572 return strupper_m(domain);
1575 bool parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser,
1576 char **domain, char **user)
1578 fstring fstr_domain, fstr_user;
1579 if (!parse_domain_user(domuser, fstr_domain, fstr_user)) {
1582 *domain = talloc_strdup(mem_ctx, fstr_domain);
1583 *user = talloc_strdup(mem_ctx, fstr_user);
1584 return ((*domain != NULL) && (*user != NULL));
1587 /* Ensure an incoming username from NSS is fully qualified. Replace the
1588 incoming fstring with DOMAIN <separator> user. Returns the same
1589 values as parse_domain_user() but also replaces the incoming username.
1590 Used to ensure all names are fully qualified within winbindd.
1591 Used by the NSS protocols of auth, chauthtok, logoff and ccache_ntlm_auth.
1592 The protocol definitions of auth_crap, chng_pswd_auth_crap
1593 really should be changed to use this instead of doing things
1596 bool canonicalize_username(fstring username_inout, fstring domain, fstring user)
1598 if (!parse_domain_user(username_inout, domain, user)) {
1601 slprintf(username_inout, sizeof(fstring) - 1, "%s%c%s",
1602 domain, *lp_winbind_separator(),
1608 Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
1609 'winbind separator' options.
1611 - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
1614 If we are a PDC or BDC, and this is for our domain, do likewise.
1616 On an AD DC we always fill DOMAIN\\USERNAME.
1618 We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1620 void fill_domain_username(fstring name, const char *domain, const char *user, bool can_assume)
1624 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1628 fstrcpy(tmp_user, user);
1629 (void)strlower_m(tmp_user);
1631 if (can_assume && assume_domain(domain)) {
1632 strlcpy(name, tmp_user, sizeof(fstring));
1634 slprintf(name, sizeof(fstring) - 1, "%s%c%s",
1635 domain, *lp_winbind_separator(),
1641 * talloc version of fill_domain_username()
1642 * return NULL on talloc failure.
1644 char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
1649 char *tmp_user, *name;
1651 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1655 tmp_user = talloc_strdup(mem_ctx, user);
1656 if (!strlower_m(tmp_user)) {
1657 TALLOC_FREE(tmp_user);
1661 if (can_assume && assume_domain(domain)) {
1664 name = talloc_asprintf(mem_ctx, "%s%c%s",
1666 *lp_winbind_separator(),
1668 TALLOC_FREE(tmp_user);
1675 * Client list accessor functions
1678 static struct winbindd_cli_state *_client_list;
1679 static int _num_clients;
1681 /* Return list of all connected clients */
1683 struct winbindd_cli_state *winbindd_client_list(void)
1685 return _client_list;
1688 /* Return list-tail of all connected clients */
1690 struct winbindd_cli_state *winbindd_client_list_tail(void)
1692 return DLIST_TAIL(_client_list);
1695 /* Return previous (read:newer) client in list */
1697 struct winbindd_cli_state *
1698 winbindd_client_list_prev(struct winbindd_cli_state *cli)
1700 return DLIST_PREV(cli);
1703 /* Add a connection to the list */
1705 void winbindd_add_client(struct winbindd_cli_state *cli)
1707 cli->last_access = time(NULL);
1708 DLIST_ADD(_client_list, cli);
1712 /* Remove a client from the list */
1714 void winbindd_remove_client(struct winbindd_cli_state *cli)
1716 DLIST_REMOVE(_client_list, cli);
1720 /* Move a client to head or list */
1722 void winbindd_promote_client(struct winbindd_cli_state *cli)
1724 cli->last_access = time(NULL);
1725 DLIST_PROMOTE(_client_list, cli);
1728 /* Return number of open clients */
1730 int winbindd_num_clients(void)
1732 return _num_clients;
1735 NTSTATUS lookup_usergroups_cached(TALLOC_CTX *mem_ctx,
1736 const struct dom_sid *user_sid,
1737 uint32_t *p_num_groups, struct dom_sid **user_sids)
1739 struct netr_SamInfo3 *info3 = NULL;
1740 NTSTATUS status = NT_STATUS_NO_MEMORY;
1741 uint32_t num_groups = 0;
1743 DEBUG(3,(": lookup_usergroups_cached\n"));
1748 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1750 if (info3 == NULL) {
1751 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1755 * Before bug #7843 the "Domain Local" groups were added with a
1756 * lookupuseraliases call, but this isn't done anymore for our domain
1757 * so we need to resolve resource groups here.
1759 * When to use Resource Groups:
1760 * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
1762 status = sid_array_from_info3(mem_ctx, info3,
1767 if (!NT_STATUS_IS_OK(status)) {
1773 *p_num_groups = num_groups;
1774 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1776 DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1781 /*********************************************************************
1782 We use this to remove spaces from user and group names
1783 ********************************************************************/
1785 NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
1786 const char *domain_name,
1790 struct winbindd_domain *domain = NULL;
1793 if (!name || !normalized) {
1794 return NT_STATUS_INVALID_PARAMETER;
1797 if (!lp_winbind_normalize_names()) {
1798 return NT_STATUS_PROCEDURE_NOT_FOUND;
1801 domain = find_domain_from_name_noinit(domain_name);
1802 if (domain == NULL) {
1803 DBG_ERR("Failed to find domain '%s'\n", domain_name);
1804 return NT_STATUS_NO_SUCH_DOMAIN;
1807 /* Alias support and whitespace replacement are mutually
1810 nt_status = resolve_username_to_alias(mem_ctx, domain,
1812 if (NT_STATUS_IS_OK(nt_status)) {
1813 /* special return code to let the caller know we
1814 mapped to an alias */
1815 return NT_STATUS_FILE_RENAMED;
1818 /* check for an unreachable domain */
1820 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1821 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1823 set_domain_offline(domain);
1827 /* deal with whitespace */
1829 *normalized = talloc_strdup(mem_ctx, name);
1830 if (!(*normalized)) {
1831 return NT_STATUS_NO_MEMORY;
1834 all_string_sub( *normalized, " ", "_", 0 );
1836 return NT_STATUS_OK;
1839 /*********************************************************************
1840 We use this to do the inverse of normalize_name_map()
1841 ********************************************************************/
1843 NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
1848 struct winbindd_domain *domain = find_our_domain();
1850 if (!name || !normalized) {
1851 return NT_STATUS_INVALID_PARAMETER;
1854 if (!lp_winbind_normalize_names()) {
1855 return NT_STATUS_PROCEDURE_NOT_FOUND;
1858 /* Alias support and whitespace replacement are mutally
1861 /* When mapping from an alias to a username, we don't know the
1862 domain. But we only need a domain structure to cache
1863 a successful lookup , so just our own domain structure for
1866 nt_status = resolve_alias_to_username(mem_ctx, domain,
1868 if (NT_STATUS_IS_OK(nt_status)) {
1869 /* Special return code to let the caller know we mapped
1871 return NT_STATUS_FILE_RENAMED;
1874 /* check for an unreachable domain */
1876 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1877 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1879 set_domain_offline(domain);
1883 /* deal with whitespace */
1885 *normalized = talloc_strdup(mem_ctx, name);
1886 if (!(*normalized)) {
1887 return NT_STATUS_NO_MEMORY;
1890 all_string_sub(*normalized, "_", " ", 0);
1892 return NT_STATUS_OK;
1895 /*********************************************************************
1896 ********************************************************************/
1898 bool winbindd_can_contact_domain(struct winbindd_domain *domain)
1900 struct winbindd_tdc_domain *tdc = NULL;
1901 TALLOC_CTX *frame = talloc_stackframe();
1904 /* We can contact the domain if it is our primary domain */
1906 if (domain->primary) {
1911 /* Trust the TDC cache and not the winbindd_domain flags */
1913 if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
1914 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
1920 /* Can always contact a domain that is in out forest */
1922 if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1928 * On a _member_ server, we cannot contact the domain if it
1929 * is running AD and we have no inbound trust.
1933 domain->active_directory &&
1934 ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
1936 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
1937 "and we have no inbound trust.\n", domain->name));
1941 /* Assume everything else is ok (probably not true but what
1947 talloc_destroy(frame);
1952 /*********************************************************************
1953 ********************************************************************/
1955 bool winbindd_internal_child(struct winbindd_child *child)
1957 if ((child == idmap_child()) || (child == locator_child())) {
1964 #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
1966 /*********************************************************************
1967 ********************************************************************/
1969 static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
1972 char addr[INET6_ADDRSTRLEN];
1973 const char *kdc = NULL;
1976 if (!domain || !domain->alt_name || !*domain->alt_name) {
1980 if (domain->initialized && !domain->active_directory) {
1981 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
1986 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
1989 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
1991 kdc = domain->dcname;
1994 if (!kdc || !*kdc) {
1995 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
2000 if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
2001 domain->alt_name) == -1) {
2005 DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
2008 setenv(var, kdc, 1);
2012 /*********************************************************************
2013 ********************************************************************/
2015 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2017 struct winbindd_domain *our_dom = find_our_domain();
2019 winbindd_set_locator_kdc_env(domain);
2021 if (domain != our_dom) {
2022 winbindd_set_locator_kdc_env(our_dom);
2026 /*********************************************************************
2027 ********************************************************************/
2029 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2033 if (!domain || !domain->alt_name || !*domain->alt_name) {
2037 if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
2038 domain->alt_name) == -1) {
2047 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2052 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2057 #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
2059 void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
2061 resp->data.auth.nt_status = NT_STATUS_V(result);
2062 fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
2064 /* we might have given a more useful error above */
2065 if (*resp->data.auth.error_string == '\0')
2066 fstrcpy(resp->data.auth.error_string,
2067 get_friendly_nt_error_msg(result));
2068 resp->data.auth.pam_error = nt_status_to_pam(result);
2071 bool is_domain_offline(const struct winbindd_domain *domain)
2073 if (get_global_winbindd_state_offline()) {
2076 return !domain->online;
2079 bool is_domain_online(const struct winbindd_domain *domain)
2081 return !is_domain_offline(domain);
2085 * Parse an char array into a list of sids.
2087 * The input sidstr should consist of 0-terminated strings
2088 * representing sids, separated by newline characters '\n'.
2089 * The list is terminated by an empty string, i.e.
2090 * character '\0' directly following a character '\n'
2091 * (or '\0' right at the start of sidstr).
2093 bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
2094 struct dom_sid **sids, uint32_t *num_sids)
2102 while (p[0] != '\0') {
2104 const char *q = NULL;
2106 if (!dom_sid_parse_endp(p, &sid, &q)) {
2107 DEBUG(1, ("Could not parse sid %s\n", p));
2111 DEBUG(1, ("Got invalid sidstr: %s\n", p));
2114 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
2124 bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
2125 struct unixid **pxids, uint32_t *pnum_xids)
2128 struct unixid *xids = NULL;
2129 uint32_t num_xids = 0;
2136 while (p[0] != '\0') {
2139 unsigned long long id;
2144 xid = (struct unixid) { .type = ID_TYPE_UID };
2147 xid = (struct unixid) { .type = ID_TYPE_GID };
2155 id = strtoull(p, &endp, 10);
2156 if ((id == ULLONG_MAX) && (errno == ERANGE)) {
2159 if (*endp != '\n') {
2165 if ((unsigned long long)xid.id != id) {
2169 tmp = talloc_realloc(mem_ctx, xids, struct unixid, num_xids+1);
2175 xids[num_xids] = xid;
2180 *pnum_xids = num_xids;