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 if (!strequal(info6->dns_domainname, "")) {
340 dns_domainname = info6->dns_domainname;
344 status = add_trusted_domain(info3->logon_dom,
348 NETR_TRUST_FLAG_OUTBOUND,
351 find_default_route_domain(),
353 if (!NT_STATUS_IS_OK(status) &&
354 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
356 DBG_DEBUG("Adding domain [%s] with sid [%s] failed\n",
357 info3->logon_dom, info3->dom_sid);
364 bool domain_is_forest_root(const struct winbindd_domain *domain)
366 const uint32_t fr_flags =
367 (NETR_TRUST_FLAG_TREEROOT|NETR_TRUST_FLAG_IN_FOREST);
369 return ((domain->domain_flags & fr_flags) == fr_flags);
372 /********************************************************************
373 rescan our domains looking for new trusted domains
374 ********************************************************************/
376 struct trustdom_state {
377 struct winbindd_domain *domain;
378 struct winbindd_request request;
381 static void trustdom_list_done(struct tevent_req *req);
382 static void rescan_forest_root_trusts( void );
383 static void rescan_forest_trusts( void );
385 static void add_trusted_domains( struct winbindd_domain *domain )
387 struct trustdom_state *state;
388 struct tevent_req *req;
390 state = talloc_zero(NULL, struct trustdom_state);
392 DEBUG(0, ("talloc failed\n"));
395 state->domain = domain;
397 state->request.length = sizeof(state->request);
398 state->request.cmd = WINBINDD_LIST_TRUSTDOM;
400 req = wb_domain_request_send(state, server_event_context(),
401 domain, &state->request);
403 DEBUG(1, ("wb_domain_request_send failed\n"));
407 tevent_req_set_callback(req, trustdom_list_done, state);
410 static void trustdom_list_done(struct tevent_req *req)
412 struct trustdom_state *state = tevent_req_callback_data(
413 req, struct trustdom_state);
414 struct winbindd_response *response;
418 bool within_forest = false;
422 * Only when we enumerate our primary domain
423 * or our forest root domain, we should keep
424 * the NETR_TRUST_FLAG_IN_FOREST flag, in
425 * all other cases we need to clear it as the domain
426 * is not part of our forest.
428 if (state->domain->primary) {
429 within_forest = true;
430 } else if (domain_is_forest_root(state->domain)) {
431 within_forest = true;
434 res = wb_domain_request_recv(req, state, &response, &err);
435 if ((res == -1) || (response->result != WINBINDD_OK)) {
436 DBG_WARNING("Could not receive trusts for domain %s\n",
437 state->domain->name);
442 if (response->length < sizeof(struct winbindd_response)) {
443 DBG_ERR("ill-formed trustdom response - short length\n");
448 extra_len = response->length - sizeof(struct winbindd_response);
450 p = (char *)response->extra_data.data;
452 while ((p - (char *)response->extra_data.data) < extra_len) {
453 struct winbindd_domain *domain = NULL;
454 char *name, *q, *sidstr, *alt_name;
457 uint32_t trust_attribs;
458 uint32_t trust_flags;
460 DBG_DEBUG("parsing response line '%s'\n", p);
464 alt_name = strchr(p, '\\');
465 if (alt_name == NULL) {
466 DBG_ERR("Got invalid trustdom response\n");
473 sidstr = strchr(alt_name, '\\');
474 if (sidstr == NULL) {
475 DBG_ERR("Got invalid trustdom response\n");
482 /* use the real alt_name if we have one, else pass in NULL */
483 if (strequal(alt_name, "(null)")) {
487 q = strtok(sidstr, "\\");
489 DBG_ERR("Got invalid trustdom response\n");
493 if (!string_to_sid(&sid, sidstr)) {
494 DEBUG(0, ("Got invalid trustdom response\n"));
498 q = strtok(NULL, "\\");
500 DBG_ERR("Got invalid trustdom response\n");
504 trust_flags = (uint32_t)strtoul(q, NULL, 10);
506 q = strtok(NULL, "\\");
508 DBG_ERR("Got invalid trustdom response\n");
512 trust_type = (uint32_t)strtoul(q, NULL, 10);
514 q = strtok(NULL, "\n");
516 DBG_ERR("Got invalid trustdom response\n");
520 trust_attribs = (uint32_t)strtoul(q, NULL, 10);
522 if (!within_forest) {
523 trust_flags &= ~NETR_TRUST_FLAG_IN_FOREST;
526 if (!state->domain->primary) {
527 trust_flags &= ~NETR_TRUST_FLAG_PRIMARY;
531 * We always call add_trusted_domain() cause on an existing
532 * domain structure, it will update the SID if necessary.
533 * This is important because we need the SID for sibling
536 status = add_trusted_domain(name,
543 find_default_route_domain(),
545 if (!NT_STATUS_IS_OK(status) &&
546 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
548 DBG_NOTICE("add_trusted_domain returned %s\n",
553 p = q + strlen(q) + 1;
557 Cases to consider when scanning trusts:
558 (a) we are calling from a child domain (primary && !forest_root)
559 (b) we are calling from the root of the forest (primary && forest_root)
560 (c) we are calling from a trusted forest domain (!primary
564 if (state->domain->primary) {
565 /* If this is our primary domain and we are not in the
566 forest root, we have to scan the root trusts first */
568 if (!domain_is_forest_root(state->domain))
569 rescan_forest_root_trusts();
571 rescan_forest_trusts();
573 } else if (domain_is_forest_root(state->domain)) {
574 /* Once we have done root forest trust search, we can
575 go on to search the trusted forests */
577 rescan_forest_trusts();
585 /********************************************************************
586 Scan the trusts of our forest root
587 ********************************************************************/
589 static void rescan_forest_root_trusts( void )
591 struct winbindd_tdc_domain *dom_list = NULL;
592 size_t num_trusts = 0;
596 /* The only transitive trusts supported by Windows 2003 AD are
597 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
598 first two are handled in forest and listed by
599 DsEnumerateDomainTrusts(). Forest trusts are not so we
600 have to do that ourselves. */
602 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
605 for ( i=0; i<num_trusts; i++ ) {
606 struct winbindd_domain *d = NULL;
608 /* Find the forest root. Don't necessarily trust
609 the domain_list() as our primary domain may not
610 have been initialized. */
612 if ( !(dom_list[i].trust_flags & NETR_TRUST_FLAG_TREEROOT) ) {
616 /* Here's the forest root */
618 d = find_domain_from_name_noinit( dom_list[i].domain_name );
620 status = add_trusted_domain(dom_list[i].domain_name,
621 dom_list[i].dns_name,
623 dom_list[i].trust_type,
624 dom_list[i].trust_flags,
625 dom_list[i].trust_attribs,
627 find_default_route_domain(),
630 if (!NT_STATUS_IS_OK(status) &&
631 NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
633 DBG_ERR("add_trusted_domain returned %s\n",
642 DEBUG(10,("rescan_forest_root_trusts: Following trust path "
643 "for domain tree root %s (%s)\n",
644 d->name, d->alt_name ));
646 d->domain_flags = dom_list[i].trust_flags;
647 d->domain_type = dom_list[i].trust_type;
648 d->domain_trust_attribs = dom_list[i].trust_attribs;
650 add_trusted_domains( d );
655 TALLOC_FREE( dom_list );
660 /********************************************************************
661 scan the transitive forest trusts (not our own)
662 ********************************************************************/
665 static void rescan_forest_trusts( void )
667 struct winbindd_domain *d = NULL;
668 struct winbindd_tdc_domain *dom_list = NULL;
669 size_t num_trusts = 0;
673 /* The only transitive trusts supported by Windows 2003 AD are
674 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
675 first two are handled in forest and listed by
676 DsEnumerateDomainTrusts(). Forest trusts are not so we
677 have to do that ourselves. */
679 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
682 for ( i=0; i<num_trusts; i++ ) {
683 uint32_t flags = dom_list[i].trust_flags;
684 uint32_t type = dom_list[i].trust_type;
685 uint32_t attribs = dom_list[i].trust_attribs;
687 d = find_domain_from_name_noinit( dom_list[i].domain_name );
689 /* ignore our primary and internal domains */
691 if ( d && (d->internal || d->primary ) )
694 if ( (flags & NETR_TRUST_FLAG_INBOUND) &&
695 (type == LSA_TRUST_TYPE_UPLEVEL) &&
696 (attribs == LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) )
698 /* add the trusted domain if we don't know
702 status = add_trusted_domain(
703 dom_list[i].domain_name,
704 dom_list[i].dns_name,
710 find_default_route_domain(),
712 if (!NT_STATUS_IS_OK(status) &&
713 NT_STATUS_EQUAL(status,
714 NT_STATUS_NO_SUCH_DOMAIN))
716 DBG_ERR("add_trusted_domain: %s\n",
726 DEBUG(10,("Following trust path for domain %s (%s)\n",
727 d->name, d->alt_name ));
728 add_trusted_domains( d );
732 TALLOC_FREE( dom_list );
737 /*********************************************************************
738 The process of updating the trusted domain list is a three step
741 (b) ask the root domain in our forest
742 (c) ask the a DC in any Win2003 trusted forests
743 *********************************************************************/
745 void rescan_trusted_domains(struct tevent_context *ev, struct tevent_timer *te,
746 struct timeval now, void *private_data)
750 /* I use to clear the cache here and start over but that
751 caused problems in child processes that needed the
752 trust dom list early on. Removing it means we
753 could have some trusted domains listed that have been
754 removed from our primary domain's DC until a full
755 restart. This should be ok since I think this is what
756 Windows does as well. */
758 /* this will only add new domains we didn't already know about
759 in the domain_list()*/
761 add_trusted_domains( find_our_domain() );
763 te = tevent_add_timer(
764 ev, NULL, timeval_current_ofs(WINBINDD_RESCAN_FREQ, 0),
765 rescan_trusted_domains, NULL);
767 * If te == NULL, there's not much we can do here. Don't fail, the
768 * only thing we miss is new trusted domains.
774 enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domain,
775 struct winbindd_cli_state *state)
777 /* Ensure null termination */
778 state->request->domain_name
779 [sizeof(state->request->domain_name)-1]='\0';
780 state->request->data.init_conn.dcname
781 [sizeof(state->request->data.init_conn.dcname)-1]='\0';
783 if (strlen(state->request->data.init_conn.dcname) > 0) {
784 fstrcpy(domain->dcname, state->request->data.init_conn.dcname);
787 init_dc_connection(domain, false);
789 if (!domain->initialized) {
790 /* If we return error here we can't do any cached authentication,
791 but we may be in disconnected mode and can't initialize correctly.
792 Do what the previous code did and just return without initialization,
793 once we go online we'll re-initialize.
795 DEBUG(5, ("winbindd_dual_init_connection: %s returning without initialization "
796 "online = %d\n", domain->name, (int)domain->online ));
799 fstrcpy(state->response->data.domain_info.name, domain->name);
800 fstrcpy(state->response->data.domain_info.alt_name, domain->alt_name);
801 sid_to_fstring(state->response->data.domain_info.sid, &domain->sid);
803 state->response->data.domain_info.native_mode
804 = domain->native_mode;
805 state->response->data.domain_info.active_directory
806 = domain->active_directory;
807 state->response->data.domain_info.primary
813 static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
816 struct server_id server_id,
821 DBG_NOTICE("Rescanning trusted domains\n");
823 ok = add_trusted_domains_dc();
825 DBG_ERR("Failed to reload trusted domains\n");
830 * We did not get the secret when we queried secrets.tdb, so read it
831 * from secrets.tdb and re-sync the databases
833 static bool migrate_secrets_tdb_to_ldb(struct winbindd_domain *domain)
836 struct cli_credentials *creds;
837 NTSTATUS can_migrate = pdb_get_trust_credentials(domain->name,
838 NULL, domain, &creds);
839 if (!NT_STATUS_IS_OK(can_migrate)) {
840 DEBUG(0, ("Failed to fetch our own, local AD domain join "
841 "password for winbindd's internal use, both from "
842 "secrets.tdb and secrets.ldb: %s\n",
843 nt_errstr(can_migrate)));
848 * NOTE: It is very unlikely we end up here if there is an
849 * oldpass, because a new password is created at
850 * classicupgrade, so this is not a concern.
852 ok = secrets_store_machine_pw_sync(cli_credentials_get_password(creds),
854 cli_credentials_get_domain(creds),
855 cli_credentials_get_realm(creds),
856 cli_credentials_get_salt_principal(creds),
857 0, /* Supported enc types, unused */
859 cli_credentials_get_password_last_changed_time(creds),
860 cli_credentials_get_secure_channel_type(creds),
861 false /* do_delete: Do not delete */);
864 DEBUG(0, ("Failed to write our our own, "
865 "local AD domain join password for "
866 "winbindd's internal use into secrets.tdb\n"));
872 static bool add_trusted_domains_dc(void)
874 struct winbindd_domain *domain = NULL;
875 struct pdb_trusted_domain **domains = NULL;
876 uint32_t num_domains = 0;
880 if (!(pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX)) {
881 struct trustdom_info **ti = NULL;
883 status = pdb_enum_trusteddoms(talloc_tos(), &num_domains, &ti);
884 if (!NT_STATUS_IS_OK(status)) {
885 DBG_ERR("pdb_enum_trusteddoms() failed - %s\n",
890 for (i = 0; i < num_domains; i++) {
891 status = add_trusted_domain(ti[i]->name,
894 LSA_TRUST_TYPE_DOWNLEVEL,
895 NETR_TRUST_FLAG_OUTBOUND,
900 if (!NT_STATUS_IS_OK(status)) {
901 DBG_NOTICE("add_trusted_domain returned %s\n",
906 /* Even in the parent winbindd we'll need to
907 talk to the DC, so try and see if we can
908 contact it. Theoretically this isn't neccessary
909 as the init_dc_connection() in init_child_recv()
910 will do this, but we can start detecting the DC
912 set_domain_online_request(domain);
918 status = pdb_enum_trusted_domains(talloc_tos(), &num_domains, &domains);
919 if (!NT_STATUS_IS_OK(status)) {
920 DBG_ERR("pdb_enum_trusted_domains() failed - %s\n",
925 for (i = 0; i < num_domains; i++) {
926 enum netr_SchannelType sec_chan_type = SEC_CHAN_DOMAIN;
927 uint32_t trust_flags = 0;
929 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
930 sec_chan_type = SEC_CHAN_DNS_DOMAIN;
933 if (!(domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
934 sec_chan_type = SEC_CHAN_NULL;
937 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
938 trust_flags |= NETR_TRUST_FLAG_INBOUND;
940 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
941 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
943 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
944 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
947 status = add_trusted_domain(domains[i]->netbios_name,
948 domains[i]->domain_name,
949 &domains[i]->security_identifier,
950 domains[i]->trust_type,
952 domains[i]->trust_attributes,
956 if (!NT_STATUS_IS_OK(status)) {
957 DBG_NOTICE("add_trusted_domain returned %s\n",
962 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
963 domain->active_directory = true;
965 domain->domain_type = domains[i]->trust_type;
966 domain->domain_trust_attribs = domains[i]->trust_attributes;
968 if (sec_chan_type != SEC_CHAN_NULL) {
969 /* Even in the parent winbindd we'll need to
970 talk to the DC, so try and see if we can
971 contact it. Theoretically this isn't neccessary
972 as the init_dc_connection() in init_child_recv()
973 will do this, but we can start detecting the DC
975 set_domain_online_request(domain);
979 for (i = 0; i < num_domains; i++) {
980 struct ForestTrustInfo fti;
982 enum ndr_err_code ndr_err;
983 struct winbindd_domain *routing_domain = NULL;
985 if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
989 if (!(domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
993 if (domains[i]->trust_forest_trust_info.length == 0) {
997 routing_domain = find_domain_from_name_noinit(
998 domains[i]->netbios_name);
999 if (routing_domain == NULL) {
1000 DBG_ERR("Can't find winbindd domain [%s]\n",
1001 domains[i]->netbios_name);
1005 ndr_err = ndr_pull_struct_blob_all(
1006 &domains[i]->trust_forest_trust_info,
1008 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
1009 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1010 DBG_ERR("ndr_pull_ForestTrustInfo(%s) - %s\n",
1011 domains[i]->netbios_name,
1012 ndr_map_error2string(ndr_err));
1016 for (fi = 0; fi < fti.count; fi++) {
1017 struct ForestTrustInfoRecord *rec =
1018 &fti.records[fi].record;
1019 struct ForestTrustDataDomainInfo *drec = NULL;
1021 if (rec->type != FOREST_TRUST_DOMAIN_INFO) {
1024 drec = &rec->data.info;
1026 if (rec->flags & LSA_NB_DISABLED_MASK) {
1030 if (rec->flags & LSA_SID_DISABLED_MASK) {
1036 * also try to find a matching
1037 * LSA_TLN_DISABLED_MASK ???
1040 domain = find_domain_from_name_noinit(drec->netbios_name.string);
1041 if (domain != NULL) {
1045 status = add_trusted_domain(drec->netbios_name.string,
1046 drec->dns_name.string,
1048 LSA_TRUST_TYPE_UPLEVEL,
1049 NETR_TRUST_FLAG_OUTBOUND,
1054 if (!NT_STATUS_IS_OK(status)) {
1055 DBG_NOTICE("add_trusted_domain returned %s\n",
1059 if (domain == NULL) {
1069 /* Look up global info for the winbind daemon */
1070 bool init_domain_list(void)
1072 int role = lp_server_role();
1073 struct pdb_domain_info *pdb_domain_info = NULL;
1074 struct winbindd_domain *domain = NULL;
1078 /* Free existing list */
1081 /* BUILTIN domain */
1083 status = add_trusted_domain("BUILTIN",
1085 &global_sid_Builtin,
1086 LSA_TRUST_TYPE_DOWNLEVEL,
1087 0, /* trust_flags */
1088 0, /* trust_attribs */
1092 if (!NT_STATUS_IS_OK(status)) {
1093 DBG_ERR("add_trusted_domain BUILTIN returned %s\n",
1101 * In case the passdb backend is passdb_dsdb the domain SID comes from
1102 * dsdb, not from secrets.tdb. As we use the domain SID in various
1103 * places, we must ensure the domain SID is migrated from dsdb to
1104 * secrets.tdb before get_global_sam_sid() is called the first time.
1106 * The migration is done as part of the passdb_dsdb initialisation,
1107 * calling pdb_get_domain_info() triggers it.
1109 pdb_domain_info = pdb_get_domain_info(talloc_tos());
1111 if ( role == ROLE_ACTIVE_DIRECTORY_DC ) {
1112 uint32_t trust_flags;
1114 enum netr_SchannelType sec_chan_type;
1115 const char *account_name;
1116 struct samr_Password current_nt_hash;
1118 if (pdb_domain_info == NULL) {
1119 DEBUG(0, ("Failed to fetch our own, local AD "
1120 "domain info from sam.ldb\n"));
1124 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1125 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1126 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1127 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1129 is_root = strequal(pdb_domain_info->dns_domain,
1130 pdb_domain_info->dns_forest);
1132 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1135 status = add_trusted_domain(pdb_domain_info->name,
1136 pdb_domain_info->dns_domain,
1137 &pdb_domain_info->sid,
1138 LSA_TRUST_TYPE_UPLEVEL,
1140 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1144 TALLOC_FREE(pdb_domain_info);
1145 if (!NT_STATUS_IS_OK(status)) {
1146 DBG_ERR("Failed to add our own, local AD "
1147 "domain to winbindd's internal list\n");
1152 * We need to call this to find out if we are an RODC
1154 ok = get_trust_pw_hash(domain->name,
1155 current_nt_hash.hash,
1160 * If get_trust_pw_hash() fails, then try and
1161 * fetch the password from the more recent of
1162 * secrets.{ldb,tdb} using the
1163 * pdb_get_trust_credentials()
1165 ok = migrate_secrets_tdb_to_ldb(domain);
1168 DEBUG(0, ("Failed to migrate our own, "
1169 "local AD domain join password for "
1170 "winbindd's internal use into "
1174 ok = get_trust_pw_hash(domain->name,
1175 current_nt_hash.hash,
1179 DEBUG(0, ("Failed to find our our own, just "
1180 "written local AD domain join "
1181 "password for winbindd's internal "
1182 "use in secrets.tdb\n"));
1187 domain->secure_channel_type = sec_chan_type;
1188 if (sec_chan_type == SEC_CHAN_RODC) {
1189 domain->rodc = true;
1193 uint32_t trust_flags;
1194 enum netr_SchannelType secure_channel_type;
1196 trust_flags = NETR_TRUST_FLAG_OUTBOUND;
1197 if (role != ROLE_DOMAIN_MEMBER) {
1198 trust_flags |= NETR_TRUST_FLAG_PRIMARY;
1201 if (role > ROLE_DOMAIN_MEMBER) {
1202 secure_channel_type = SEC_CHAN_BDC;
1204 secure_channel_type = SEC_CHAN_LOCAL;
1207 status = add_trusted_domain(get_global_sam_name(),
1209 get_global_sam_sid(),
1210 LSA_TRUST_TYPE_DOWNLEVEL,
1212 0, /* trust_attribs */
1213 secure_channel_type,
1216 if (!NT_STATUS_IS_OK(status)) {
1217 DBG_ERR("Failed to add local SAM to "
1218 "domain to winbindd's internal list\n");
1224 ok = add_trusted_domains_dc();
1226 DBG_ERR("init_domain_list_dc failed\n");
1231 if ( role == ROLE_DOMAIN_MEMBER ) {
1232 struct dom_sid our_sid;
1233 uint32_t trust_type;
1235 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
1236 DEBUG(0, ("Could not fetch our SID - did we join?\n"));
1240 if (lp_realm() != NULL) {
1241 trust_type = LSA_TRUST_TYPE_UPLEVEL;
1243 trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1246 status = add_trusted_domain(lp_workgroup(),
1250 NETR_TRUST_FLAG_PRIMARY|
1251 NETR_TRUST_FLAG_OUTBOUND,
1252 0, /* trust_attribs */
1256 if (!NT_STATUS_IS_OK(status)) {
1257 DBG_ERR("Failed to add local SAM to "
1258 "domain to winbindd's internal list\n");
1261 /* Even in the parent winbindd we'll need to
1262 talk to the DC, so try and see if we can
1263 contact it. Theoretically this isn't neccessary
1264 as the init_dc_connection() in init_child_recv()
1265 will do this, but we can start detecting the DC
1267 set_domain_online_request(domain);
1271 status = imessaging_register(winbind_imessaging_context(), NULL,
1272 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1273 wb_imsg_new_trusted_domain);
1274 if (!NT_STATUS_IS_OK(status)) {
1275 DBG_ERR("imessaging_register failed %s\n", nt_errstr(status));
1283 * Given a domain name, return the struct winbindd domain info for it
1285 * @note Do *not* pass lp_workgroup() to this function. domain_list
1286 * may modify it's value, and free that pointer. Instead, our local
1287 * domain may be found by calling find_our_domain().
1291 * @return The domain structure for the named domain, if it is working.
1294 struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
1296 struct winbindd_domain *domain;
1298 /* Search through list */
1300 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1301 if (strequal(domain_name, domain->name)) {
1304 if (domain->alt_name == NULL) {
1307 if (strequal(domain_name, domain->alt_name)) {
1318 * Given a domain name, return the struct winbindd domain if it's a direct
1321 * @return The domain structure for the named domain, if it is a direct outgoing trust
1323 struct winbindd_domain *find_trust_from_name_noinit(const char *domain_name)
1325 struct winbindd_domain *domain = NULL;
1327 domain = find_domain_from_name_noinit(domain_name);
1328 if (domain == NULL) {
1332 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1339 struct winbindd_domain *find_domain_from_name(const char *domain_name)
1341 struct winbindd_domain *domain;
1343 domain = find_domain_from_name_noinit(domain_name);
1348 if (!domain->initialized)
1349 init_dc_connection(domain, false);
1354 /* Given a domain sid, return the struct winbindd domain info for it */
1356 struct winbindd_domain *find_domain_from_sid_noinit(const struct dom_sid *sid)
1358 struct winbindd_domain *domain;
1360 /* Search through list */
1362 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1363 if (dom_sid_compare_domain(sid, &domain->sid) == 0)
1373 * Given a domain sid, return the struct winbindd domain if it's a direct
1376 * @return The domain structure for the specified domain, if it is a direct outgoing trust
1378 struct winbindd_domain *find_trust_from_sid_noinit(const struct dom_sid *sid)
1380 struct winbindd_domain *domain = NULL;
1382 domain = find_domain_from_sid_noinit(sid);
1383 if (domain == NULL) {
1387 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1394 /* Given a domain sid, return the struct winbindd domain info for it */
1396 struct winbindd_domain *find_domain_from_sid(const struct dom_sid *sid)
1398 struct winbindd_domain *domain;
1400 domain = find_domain_from_sid_noinit(sid);
1405 if (!domain->initialized)
1406 init_dc_connection(domain, false);
1411 struct winbindd_domain *find_our_domain(void)
1413 struct winbindd_domain *domain;
1415 /* Search through list */
1417 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1418 if (domain->primary)
1422 smb_panic("Could not find our domain");
1426 struct winbindd_domain *find_default_route_domain(void)
1429 return find_our_domain();
1431 DBG_DEBUG("Routing logic not yet implemented on a DC\n");
1435 /* Find the appropriate domain to lookup a name or SID */
1437 struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)
1439 DBG_DEBUG("SID [%s]\n", sid_string_dbg(sid));
1442 * SIDs in the S-1-22-{1,2} domain and well-known SIDs should be handled
1446 if ( sid_check_is_in_unix_groups(sid) ||
1447 sid_check_is_unix_groups(sid) ||
1448 sid_check_is_in_unix_users(sid) ||
1449 sid_check_is_unix_users(sid) ||
1450 sid_check_is_wellknown_domain(sid, NULL) ||
1451 sid_check_is_in_wellknown_domain(sid) )
1453 return find_domain_from_sid(get_global_sam_sid());
1457 * On member servers the internal domains are different: These are part
1461 if (is_internal_domain(sid) || is_in_internal_domain(sid)) {
1462 DEBUG(10, ("calling find_domain_from_sid\n"));
1463 return find_domain_from_sid(sid);
1467 struct winbindd_domain *domain = NULL;
1469 domain = find_domain_from_sid_noinit(sid);
1470 if (domain == NULL) {
1474 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1478 return domain->routing_domain;
1481 /* On a member server a query for SID or name can always go to our
1484 DEBUG(10, ("calling find_our_domain\n"));
1485 return find_our_domain();
1488 struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
1490 if ( strequal(domain_name, unix_users_domain_name() ) ||
1491 strequal(domain_name, unix_groups_domain_name() ) )
1494 * The "Unix User" and "Unix Group" domain our handled by
1497 return find_domain_from_name_noinit( get_global_sam_name() );
1500 if (strequal(domain_name, "BUILTIN") ||
1501 strequal(domain_name, get_global_sam_name()))
1502 return find_domain_from_name_noinit(domain_name);
1505 struct winbindd_domain *domain = NULL;
1507 domain = find_domain_from_name_noinit(domain_name);
1508 if (domain == NULL) {
1512 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1516 return domain->routing_domain;
1519 return find_our_domain();
1522 /* Is this a domain which we may assume no DOMAIN\ prefix? */
1524 static bool assume_domain(const char *domain)
1526 /* never assume the domain on a standalone server */
1528 if ( lp_server_role() == ROLE_STANDALONE )
1531 /* domain member servers may possibly assume for the domain name */
1533 if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
1534 if ( !strequal(lp_workgroup(), domain) )
1537 if ( lp_winbind_use_default_domain() )
1541 /* only left with a domain controller */
1543 if ( strequal(get_global_sam_name(), domain) ) {
1550 /* Parse a string of the form DOMAIN\user into a domain and a user */
1552 bool parse_domain_user(const char *domuser, fstring domain, fstring user)
1554 char *p = strchr(domuser,*lp_winbind_separator());
1557 fstrcpy(user, domuser);
1558 p = strchr(domuser, '@');
1560 if ( assume_domain(lp_workgroup()) && p == NULL) {
1561 fstrcpy(domain, lp_workgroup());
1562 } else if (p != NULL) {
1563 fstrcpy(domain, p + 1);
1564 user[PTR_DIFF(p, domuser)] = 0;
1570 fstrcpy(domain, domuser);
1571 domain[PTR_DIFF(p, domuser)] = 0;
1574 return strupper_m(domain);
1577 bool parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser,
1578 char **domain, char **user)
1580 fstring fstr_domain, fstr_user;
1581 if (!parse_domain_user(domuser, fstr_domain, fstr_user)) {
1584 *domain = talloc_strdup(mem_ctx, fstr_domain);
1585 *user = talloc_strdup(mem_ctx, fstr_user);
1586 return ((*domain != NULL) && (*user != NULL));
1589 /* Ensure an incoming username from NSS is fully qualified. Replace the
1590 incoming fstring with DOMAIN <separator> user. Returns the same
1591 values as parse_domain_user() but also replaces the incoming username.
1592 Used to ensure all names are fully qualified within winbindd.
1593 Used by the NSS protocols of auth, chauthtok, logoff and ccache_ntlm_auth.
1594 The protocol definitions of auth_crap, chng_pswd_auth_crap
1595 really should be changed to use this instead of doing things
1598 bool canonicalize_username(fstring username_inout, fstring domain, fstring user)
1600 if (!parse_domain_user(username_inout, domain, user)) {
1603 slprintf(username_inout, sizeof(fstring) - 1, "%s%c%s",
1604 domain, *lp_winbind_separator(),
1610 Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
1611 'winbind separator' options.
1613 - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
1616 If we are a PDC or BDC, and this is for our domain, do likewise.
1618 On an AD DC we always fill DOMAIN\\USERNAME.
1620 We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1622 void fill_domain_username(fstring name, const char *domain, const char *user, bool can_assume)
1626 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1630 fstrcpy(tmp_user, user);
1631 (void)strlower_m(tmp_user);
1633 if (can_assume && assume_domain(domain)) {
1634 strlcpy(name, tmp_user, sizeof(fstring));
1636 slprintf(name, sizeof(fstring) - 1, "%s%c%s",
1637 domain, *lp_winbind_separator(),
1643 * talloc version of fill_domain_username()
1644 * return NULL on talloc failure.
1646 char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
1651 char *tmp_user, *name;
1653 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1657 tmp_user = talloc_strdup(mem_ctx, user);
1658 if (!strlower_m(tmp_user)) {
1659 TALLOC_FREE(tmp_user);
1663 if (can_assume && assume_domain(domain)) {
1666 name = talloc_asprintf(mem_ctx, "%s%c%s",
1668 *lp_winbind_separator(),
1670 TALLOC_FREE(tmp_user);
1677 * Client list accessor functions
1680 static struct winbindd_cli_state *_client_list;
1681 static int _num_clients;
1683 /* Return list of all connected clients */
1685 struct winbindd_cli_state *winbindd_client_list(void)
1687 return _client_list;
1690 /* Return list-tail of all connected clients */
1692 struct winbindd_cli_state *winbindd_client_list_tail(void)
1694 return DLIST_TAIL(_client_list);
1697 /* Return previous (read:newer) client in list */
1699 struct winbindd_cli_state *
1700 winbindd_client_list_prev(struct winbindd_cli_state *cli)
1702 return DLIST_PREV(cli);
1705 /* Add a connection to the list */
1707 void winbindd_add_client(struct winbindd_cli_state *cli)
1709 cli->last_access = time(NULL);
1710 DLIST_ADD(_client_list, cli);
1714 /* Remove a client from the list */
1716 void winbindd_remove_client(struct winbindd_cli_state *cli)
1718 DLIST_REMOVE(_client_list, cli);
1722 /* Move a client to head or list */
1724 void winbindd_promote_client(struct winbindd_cli_state *cli)
1726 cli->last_access = time(NULL);
1727 DLIST_PROMOTE(_client_list, cli);
1730 /* Return number of open clients */
1732 int winbindd_num_clients(void)
1734 return _num_clients;
1737 NTSTATUS lookup_usergroups_cached(TALLOC_CTX *mem_ctx,
1738 const struct dom_sid *user_sid,
1739 uint32_t *p_num_groups, struct dom_sid **user_sids)
1741 struct netr_SamInfo3 *info3 = NULL;
1742 NTSTATUS status = NT_STATUS_NO_MEMORY;
1743 uint32_t num_groups = 0;
1745 DEBUG(3,(": lookup_usergroups_cached\n"));
1750 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1752 if (info3 == NULL) {
1753 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1757 * Before bug #7843 the "Domain Local" groups were added with a
1758 * lookupuseraliases call, but this isn't done anymore for our domain
1759 * so we need to resolve resource groups here.
1761 * When to use Resource Groups:
1762 * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
1764 status = sid_array_from_info3(mem_ctx, info3,
1769 if (!NT_STATUS_IS_OK(status)) {
1775 *p_num_groups = num_groups;
1776 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1778 DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1783 /*********************************************************************
1784 We use this to remove spaces from user and group names
1785 ********************************************************************/
1787 NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
1788 const char *domain_name,
1792 struct winbindd_domain *domain = NULL;
1795 if (!name || !normalized) {
1796 return NT_STATUS_INVALID_PARAMETER;
1799 if (!lp_winbind_normalize_names()) {
1800 return NT_STATUS_PROCEDURE_NOT_FOUND;
1803 domain = find_domain_from_name_noinit(domain_name);
1804 if (domain == NULL) {
1805 DBG_ERR("Failed to find domain '%s'\n", domain_name);
1806 return NT_STATUS_NO_SUCH_DOMAIN;
1809 /* Alias support and whitespace replacement are mutually
1812 nt_status = resolve_username_to_alias(mem_ctx, domain,
1814 if (NT_STATUS_IS_OK(nt_status)) {
1815 /* special return code to let the caller know we
1816 mapped to an alias */
1817 return NT_STATUS_FILE_RENAMED;
1820 /* check for an unreachable domain */
1822 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1823 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1825 set_domain_offline(domain);
1829 /* deal with whitespace */
1831 *normalized = talloc_strdup(mem_ctx, name);
1832 if (!(*normalized)) {
1833 return NT_STATUS_NO_MEMORY;
1836 all_string_sub( *normalized, " ", "_", 0 );
1838 return NT_STATUS_OK;
1841 /*********************************************************************
1842 We use this to do the inverse of normalize_name_map()
1843 ********************************************************************/
1845 NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
1850 struct winbindd_domain *domain = find_our_domain();
1852 if (!name || !normalized) {
1853 return NT_STATUS_INVALID_PARAMETER;
1856 if (!lp_winbind_normalize_names()) {
1857 return NT_STATUS_PROCEDURE_NOT_FOUND;
1860 /* Alias support and whitespace replacement are mutally
1863 /* When mapping from an alias to a username, we don't know the
1864 domain. But we only need a domain structure to cache
1865 a successful lookup , so just our own domain structure for
1868 nt_status = resolve_alias_to_username(mem_ctx, domain,
1870 if (NT_STATUS_IS_OK(nt_status)) {
1871 /* Special return code to let the caller know we mapped
1873 return NT_STATUS_FILE_RENAMED;
1876 /* check for an unreachable domain */
1878 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1879 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1881 set_domain_offline(domain);
1885 /* deal with whitespace */
1887 *normalized = talloc_strdup(mem_ctx, name);
1888 if (!(*normalized)) {
1889 return NT_STATUS_NO_MEMORY;
1892 all_string_sub(*normalized, "_", " ", 0);
1894 return NT_STATUS_OK;
1897 /*********************************************************************
1898 ********************************************************************/
1900 bool winbindd_can_contact_domain(struct winbindd_domain *domain)
1902 struct winbindd_tdc_domain *tdc = NULL;
1903 TALLOC_CTX *frame = talloc_stackframe();
1906 /* We can contact the domain if it is our primary domain */
1908 if (domain->primary) {
1913 /* Trust the TDC cache and not the winbindd_domain flags */
1915 if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
1916 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
1922 /* Can always contact a domain that is in out forest */
1924 if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1930 * On a _member_ server, we cannot contact the domain if it
1931 * is running AD and we have no inbound trust.
1935 domain->active_directory &&
1936 ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
1938 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
1939 "and we have no inbound trust.\n", domain->name));
1943 /* Assume everything else is ok (probably not true but what
1949 talloc_destroy(frame);
1954 /*********************************************************************
1955 ********************************************************************/
1957 bool winbindd_internal_child(struct winbindd_child *child)
1959 if ((child == idmap_child()) || (child == locator_child())) {
1966 #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
1968 /*********************************************************************
1969 ********************************************************************/
1971 static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
1974 char addr[INET6_ADDRSTRLEN];
1975 const char *kdc = NULL;
1978 if (!domain || !domain->alt_name || !*domain->alt_name) {
1982 if (domain->initialized && !domain->active_directory) {
1983 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
1988 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
1991 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
1993 kdc = domain->dcname;
1996 if (!kdc || !*kdc) {
1997 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
2002 if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
2003 domain->alt_name) == -1) {
2007 DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
2010 setenv(var, kdc, 1);
2014 /*********************************************************************
2015 ********************************************************************/
2017 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2019 struct winbindd_domain *our_dom = find_our_domain();
2021 winbindd_set_locator_kdc_env(domain);
2023 if (domain != our_dom) {
2024 winbindd_set_locator_kdc_env(our_dom);
2028 /*********************************************************************
2029 ********************************************************************/
2031 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2035 if (!domain || !domain->alt_name || !*domain->alt_name) {
2039 if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
2040 domain->alt_name) == -1) {
2049 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2054 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2059 #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
2061 void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
2063 resp->data.auth.nt_status = NT_STATUS_V(result);
2064 fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
2066 /* we might have given a more useful error above */
2067 if (*resp->data.auth.error_string == '\0')
2068 fstrcpy(resp->data.auth.error_string,
2069 get_friendly_nt_error_msg(result));
2070 resp->data.auth.pam_error = nt_status_to_pam(result);
2073 bool is_domain_offline(const struct winbindd_domain *domain)
2075 if (get_global_winbindd_state_offline()) {
2078 return !domain->online;
2081 bool is_domain_online(const struct winbindd_domain *domain)
2083 return !is_domain_offline(domain);
2087 * Parse an char array into a list of sids.
2089 * The input sidstr should consist of 0-terminated strings
2090 * representing sids, separated by newline characters '\n'.
2091 * The list is terminated by an empty string, i.e.
2092 * character '\0' directly following a character '\n'
2093 * (or '\0' right at the start of sidstr).
2095 bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
2096 struct dom_sid **sids, uint32_t *num_sids)
2104 while (p[0] != '\0') {
2106 const char *q = NULL;
2108 if (!dom_sid_parse_endp(p, &sid, &q)) {
2109 DEBUG(1, ("Could not parse sid %s\n", p));
2113 DEBUG(1, ("Got invalid sidstr: %s\n", p));
2116 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
2126 bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
2127 struct unixid **pxids, uint32_t *pnum_xids)
2130 struct unixid *xids = NULL;
2131 uint32_t num_xids = 0;
2138 while (p[0] != '\0') {
2141 unsigned long long id;
2146 xid = (struct unixid) { .type = ID_TYPE_UID };
2149 xid = (struct unixid) { .type = ID_TYPE_GID };
2157 id = strtoull(p, &endp, 10);
2158 if ((id == ULLONG_MAX) && (errno == ERANGE)) {
2161 if (*endp != '\n') {
2167 if ((unsigned long long)xid.id != id) {
2171 tmp = talloc_realloc(mem_ctx, xids, struct unixid, num_xids+1);
2177 xids[num_xids] = xid;
2182 *pnum_xids = num_xids;