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->binding_handle = wbint_binding_handle(domain, domain, NULL);
232 if (domain->binding_handle == NULL) {
234 return NT_STATUS_NO_MEMORY;
237 domain->name = talloc_strdup(domain, domain_name);
238 if (domain->name == NULL) {
240 return NT_STATUS_NO_MEMORY;
243 if (dns_name != NULL) {
244 domain->alt_name = talloc_strdup(domain, dns_name);
245 if (domain->alt_name == NULL) {
247 return NT_STATUS_NO_MEMORY;
251 domain->backend = NULL;
252 domain->internal = is_internal_domain(sid);
253 domain->secure_channel_type = secure_channel_type;
254 domain->sequence_number = DOM_SEQUENCE_NONE;
255 domain->last_seq_check = 0;
256 domain->initialized = false;
257 domain->online = is_internal_domain(sid);
258 domain->check_online_timeout = 0;
259 domain->dc_probe_pid = (pid_t)-1;
260 domain->domain_flags = trust_flags;
261 domain->domain_type = trust_type;
262 domain->domain_trust_attribs = trust_attribs;
263 domain->secure_channel_type = secure_channel_type;
264 domain->routing_domain = routing_domain;
265 sid_copy(&domain->sid, sid);
267 /* Is this our primary domain ? */
268 if (role == ROLE_DOMAIN_MEMBER) {
269 domain->primary = strequal(domain_name, lp_workgroup());
271 domain->primary = strequal(domain_name, get_global_sam_name());
274 if (domain->primary) {
275 if (role == ROLE_ACTIVE_DIRECTORY_DC) {
276 domain->active_directory = true;
278 if (lp_security() == SEC_ADS) {
279 domain->active_directory = true;
281 } else if (!domain->internal) {
282 if (domain->domain_type == LSA_TRUST_TYPE_UPLEVEL) {
283 domain->active_directory = true;
287 domain->can_do_ncacn_ip_tcp = domain->active_directory;
289 /* Link to domain list */
290 DLIST_ADD_END(_domain_list, domain);
292 wcache_tdc_add_domain( domain );
294 setup_domain_child(domain);
296 DBG_NOTICE("Added domain [%s] [%s] [%s]\n",
297 domain->name, domain->alt_name,
298 sid_string_dbg(&domain->sid));
304 bool set_routing_domain(struct winbindd_domain *domain,
305 struct winbindd_domain *routing_domain)
307 if (domain->routing_domain == NULL) {
308 domain->routing_domain = routing_domain;
311 if (domain->routing_domain != routing_domain) {
317 bool add_trusted_domain_from_auth(uint16_t validation_level,
318 struct info3_text *info3,
319 struct info6_text *info6)
321 struct winbindd_domain *domain = NULL;
322 struct dom_sid domain_sid;
323 const char *dns_domainname = NULL;
328 * We got a successfull auth from a domain that might not yet be in our
329 * domain list. If we're a member we trust our DC who authenticated the
330 * user from that domain and add the domain to our list on-the-fly. If
331 * we're a DC we rely on configured trusts and don't add on-the-fly.
338 ok = dom_sid_parse(info3->dom_sid, &domain_sid);
340 DBG_NOTICE("dom_sid_parse [%s] failed\n", info3->dom_sid);
344 if (validation_level == 6) {
345 if (!strequal(info6->dns_domainname, "")) {
346 dns_domainname = info6->dns_domainname;
350 status = add_trusted_domain(info3->logon_dom,
354 NETR_TRUST_FLAG_OUTBOUND,
357 find_default_route_domain(),
359 if (!NT_STATUS_IS_OK(status) &&
360 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
362 DBG_DEBUG("Adding domain [%s] with sid [%s] failed\n",
363 info3->logon_dom, info3->dom_sid);
370 bool domain_is_forest_root(const struct winbindd_domain *domain)
372 const uint32_t fr_flags =
373 (NETR_TRUST_FLAG_TREEROOT|NETR_TRUST_FLAG_IN_FOREST);
375 return ((domain->domain_flags & fr_flags) == fr_flags);
378 /********************************************************************
379 rescan our domains looking for new trusted domains
380 ********************************************************************/
382 struct trustdom_state {
383 struct winbindd_domain *domain;
384 struct winbindd_request request;
387 static void trustdom_list_done(struct tevent_req *req);
388 static void rescan_forest_root_trusts( void );
389 static void rescan_forest_trusts( void );
391 static void add_trusted_domains( struct winbindd_domain *domain )
393 struct trustdom_state *state;
394 struct tevent_req *req;
396 state = talloc_zero(NULL, struct trustdom_state);
398 DEBUG(0, ("talloc failed\n"));
401 state->domain = domain;
403 state->request.length = sizeof(state->request);
404 state->request.cmd = WINBINDD_LIST_TRUSTDOM;
406 req = wb_domain_request_send(state, server_event_context(),
407 domain, &state->request);
409 DEBUG(1, ("wb_domain_request_send failed\n"));
413 tevent_req_set_callback(req, trustdom_list_done, state);
416 static void trustdom_list_done(struct tevent_req *req)
418 struct trustdom_state *state = tevent_req_callback_data(
419 req, struct trustdom_state);
420 struct winbindd_response *response;
424 bool within_forest = false;
428 * Only when we enumerate our primary domain
429 * or our forest root domain, we should keep
430 * the NETR_TRUST_FLAG_IN_FOREST flag, in
431 * all other cases we need to clear it as the domain
432 * is not part of our forest.
434 if (state->domain->primary) {
435 within_forest = true;
436 } else if (domain_is_forest_root(state->domain)) {
437 within_forest = true;
440 res = wb_domain_request_recv(req, state, &response, &err);
441 if ((res == -1) || (response->result != WINBINDD_OK)) {
442 DBG_WARNING("Could not receive trusts for domain %s\n",
443 state->domain->name);
448 if (response->length < sizeof(struct winbindd_response)) {
449 DBG_ERR("ill-formed trustdom response - short length\n");
454 extra_len = response->length - sizeof(struct winbindd_response);
456 p = (char *)response->extra_data.data;
458 while ((p - (char *)response->extra_data.data) < extra_len) {
459 struct winbindd_domain *domain = NULL;
460 char *name, *q, *sidstr, *alt_name;
463 uint32_t trust_attribs;
464 uint32_t trust_flags;
466 DBG_DEBUG("parsing response line '%s'\n", p);
470 alt_name = strchr(p, '\\');
471 if (alt_name == NULL) {
472 DBG_ERR("Got invalid trustdom response\n");
479 sidstr = strchr(alt_name, '\\');
480 if (sidstr == NULL) {
481 DBG_ERR("Got invalid trustdom response\n");
488 /* use the real alt_name if we have one, else pass in NULL */
489 if (strequal(alt_name, "(null)")) {
493 q = strtok(sidstr, "\\");
495 DBG_ERR("Got invalid trustdom response\n");
499 if (!string_to_sid(&sid, sidstr)) {
500 DEBUG(0, ("Got invalid trustdom response\n"));
504 q = strtok(NULL, "\\");
506 DBG_ERR("Got invalid trustdom response\n");
510 trust_flags = (uint32_t)strtoul(q, NULL, 10);
512 q = strtok(NULL, "\\");
514 DBG_ERR("Got invalid trustdom response\n");
518 trust_type = (uint32_t)strtoul(q, NULL, 10);
520 q = strtok(NULL, "\n");
522 DBG_ERR("Got invalid trustdom response\n");
526 trust_attribs = (uint32_t)strtoul(q, NULL, 10);
528 if (!within_forest) {
529 trust_flags &= ~NETR_TRUST_FLAG_IN_FOREST;
532 if (!state->domain->primary) {
533 trust_flags &= ~NETR_TRUST_FLAG_PRIMARY;
537 * We always call add_trusted_domain() cause on an existing
538 * domain structure, it will update the SID if necessary.
539 * This is important because we need the SID for sibling
542 status = add_trusted_domain(name,
549 find_default_route_domain(),
551 if (!NT_STATUS_IS_OK(status) &&
552 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
554 DBG_NOTICE("add_trusted_domain returned %s\n",
559 p = q + strlen(q) + 1;
563 Cases to consider when scanning trusts:
564 (a) we are calling from a child domain (primary && !forest_root)
565 (b) we are calling from the root of the forest (primary && forest_root)
566 (c) we are calling from a trusted forest domain (!primary
570 if (state->domain->primary) {
571 /* If this is our primary domain and we are not in the
572 forest root, we have to scan the root trusts first */
574 if (!domain_is_forest_root(state->domain))
575 rescan_forest_root_trusts();
577 rescan_forest_trusts();
579 } else if (domain_is_forest_root(state->domain)) {
580 /* Once we have done root forest trust search, we can
581 go on to search the trusted forests */
583 rescan_forest_trusts();
591 /********************************************************************
592 Scan the trusts of our forest root
593 ********************************************************************/
595 static void rescan_forest_root_trusts( void )
597 struct winbindd_tdc_domain *dom_list = NULL;
598 size_t num_trusts = 0;
602 /* The only transitive trusts supported by Windows 2003 AD are
603 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
604 first two are handled in forest and listed by
605 DsEnumerateDomainTrusts(). Forest trusts are not so we
606 have to do that ourselves. */
608 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
611 for ( i=0; i<num_trusts; i++ ) {
612 struct winbindd_domain *d = NULL;
614 /* Find the forest root. Don't necessarily trust
615 the domain_list() as our primary domain may not
616 have been initialized. */
618 if ( !(dom_list[i].trust_flags & NETR_TRUST_FLAG_TREEROOT) ) {
622 /* Here's the forest root */
624 d = find_domain_from_name_noinit( dom_list[i].domain_name );
626 status = add_trusted_domain(dom_list[i].domain_name,
627 dom_list[i].dns_name,
629 dom_list[i].trust_type,
630 dom_list[i].trust_flags,
631 dom_list[i].trust_attribs,
633 find_default_route_domain(),
636 if (!NT_STATUS_IS_OK(status) &&
637 NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
639 DBG_ERR("add_trusted_domain returned %s\n",
648 DEBUG(10,("rescan_forest_root_trusts: Following trust path "
649 "for domain tree root %s (%s)\n",
650 d->name, d->alt_name ));
652 d->domain_flags = dom_list[i].trust_flags;
653 d->domain_type = dom_list[i].trust_type;
654 d->domain_trust_attribs = dom_list[i].trust_attribs;
656 add_trusted_domains( d );
661 TALLOC_FREE( dom_list );
666 /********************************************************************
667 scan the transitive forest trusts (not our own)
668 ********************************************************************/
671 static void rescan_forest_trusts( void )
673 struct winbindd_domain *d = NULL;
674 struct winbindd_tdc_domain *dom_list = NULL;
675 size_t num_trusts = 0;
679 /* The only transitive trusts supported by Windows 2003 AD are
680 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
681 first two are handled in forest and listed by
682 DsEnumerateDomainTrusts(). Forest trusts are not so we
683 have to do that ourselves. */
685 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
688 for ( i=0; i<num_trusts; i++ ) {
689 uint32_t flags = dom_list[i].trust_flags;
690 uint32_t type = dom_list[i].trust_type;
691 uint32_t attribs = dom_list[i].trust_attribs;
693 d = find_domain_from_name_noinit( dom_list[i].domain_name );
695 /* ignore our primary and internal domains */
697 if ( d && (d->internal || d->primary ) )
700 if ( (flags & NETR_TRUST_FLAG_INBOUND) &&
701 (type == LSA_TRUST_TYPE_UPLEVEL) &&
702 (attribs == LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) )
704 /* add the trusted domain if we don't know
708 status = add_trusted_domain(
709 dom_list[i].domain_name,
710 dom_list[i].dns_name,
716 find_default_route_domain(),
718 if (!NT_STATUS_IS_OK(status) &&
719 NT_STATUS_EQUAL(status,
720 NT_STATUS_NO_SUCH_DOMAIN))
722 DBG_ERR("add_trusted_domain: %s\n",
732 DEBUG(10,("Following trust path for domain %s (%s)\n",
733 d->name, d->alt_name ));
734 add_trusted_domains( d );
738 TALLOC_FREE( dom_list );
743 /*********************************************************************
744 The process of updating the trusted domain list is a three step
747 (b) ask the root domain in our forest
748 (c) ask the a DC in any Win2003 trusted forests
749 *********************************************************************/
751 void rescan_trusted_domains(struct tevent_context *ev, struct tevent_timer *te,
752 struct timeval now, void *private_data)
756 /* I use to clear the cache here and start over but that
757 caused problems in child processes that needed the
758 trust dom list early on. Removing it means we
759 could have some trusted domains listed that have been
760 removed from our primary domain's DC until a full
761 restart. This should be ok since I think this is what
762 Windows does as well. */
764 /* this will only add new domains we didn't already know about
765 in the domain_list()*/
767 add_trusted_domains( find_our_domain() );
769 te = tevent_add_timer(
770 ev, NULL, timeval_current_ofs(WINBINDD_RESCAN_FREQ, 0),
771 rescan_trusted_domains, NULL);
773 * If te == NULL, there's not much we can do here. Don't fail, the
774 * only thing we miss is new trusted domains.
780 enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domain,
781 struct winbindd_cli_state *state)
783 /* Ensure null termination */
784 state->request->domain_name
785 [sizeof(state->request->domain_name)-1]='\0';
786 state->request->data.init_conn.dcname
787 [sizeof(state->request->data.init_conn.dcname)-1]='\0';
789 if (strlen(state->request->data.init_conn.dcname) > 0) {
790 TALLOC_FREE(domain->dcname);
791 domain->dcname = talloc_strdup(domain,
792 state->request->data.init_conn.dcname);
793 if (domain->dcname == NULL) {
794 return WINBINDD_ERROR;
798 init_dc_connection(domain, false);
800 if (!domain->initialized) {
801 /* If we return error here we can't do any cached authentication,
802 but we may be in disconnected mode and can't initialize correctly.
803 Do what the previous code did and just return without initialization,
804 once we go online we'll re-initialize.
806 DEBUG(5, ("winbindd_dual_init_connection: %s returning without initialization "
807 "online = %d\n", domain->name, (int)domain->online ));
810 fstrcpy(state->response->data.domain_info.name, domain->name);
811 fstrcpy(state->response->data.domain_info.alt_name, domain->alt_name);
812 sid_to_fstring(state->response->data.domain_info.sid, &domain->sid);
814 state->response->data.domain_info.native_mode
815 = domain->native_mode;
816 state->response->data.domain_info.active_directory
817 = domain->active_directory;
818 state->response->data.domain_info.primary
824 static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
827 struct server_id server_id,
832 DBG_NOTICE("Rescanning trusted domains\n");
834 ok = add_trusted_domains_dc();
836 DBG_ERR("Failed to reload trusted domains\n");
841 * We did not get the secret when we queried secrets.tdb, so read it
842 * from secrets.tdb and re-sync the databases
844 static bool migrate_secrets_tdb_to_ldb(struct winbindd_domain *domain)
847 struct cli_credentials *creds;
848 NTSTATUS can_migrate = pdb_get_trust_credentials(domain->name,
849 NULL, domain, &creds);
850 if (!NT_STATUS_IS_OK(can_migrate)) {
851 DEBUG(0, ("Failed to fetch our own, local AD domain join "
852 "password for winbindd's internal use, both from "
853 "secrets.tdb and secrets.ldb: %s\n",
854 nt_errstr(can_migrate)));
859 * NOTE: It is very unlikely we end up here if there is an
860 * oldpass, because a new password is created at
861 * classicupgrade, so this is not a concern.
863 ok = secrets_store_machine_pw_sync(cli_credentials_get_password(creds),
865 cli_credentials_get_domain(creds),
866 cli_credentials_get_realm(creds),
867 cli_credentials_get_salt_principal(creds),
868 0, /* Supported enc types, unused */
870 cli_credentials_get_password_last_changed_time(creds),
871 cli_credentials_get_secure_channel_type(creds),
872 false /* do_delete: Do not delete */);
875 DEBUG(0, ("Failed to write our our own, "
876 "local AD domain join password for "
877 "winbindd's internal use into secrets.tdb\n"));
883 static bool add_trusted_domains_dc(void)
885 struct winbindd_domain *domain = NULL;
886 struct pdb_trusted_domain **domains = NULL;
887 uint32_t num_domains = 0;
891 if (!(pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX)) {
892 struct trustdom_info **ti = NULL;
894 status = pdb_enum_trusteddoms(talloc_tos(), &num_domains, &ti);
895 if (!NT_STATUS_IS_OK(status)) {
896 DBG_ERR("pdb_enum_trusteddoms() failed - %s\n",
901 for (i = 0; i < num_domains; i++) {
902 status = add_trusted_domain(ti[i]->name,
905 LSA_TRUST_TYPE_DOWNLEVEL,
906 NETR_TRUST_FLAG_OUTBOUND,
911 if (!NT_STATUS_IS_OK(status)) {
912 DBG_NOTICE("add_trusted_domain returned %s\n",
917 /* Even in the parent winbindd we'll need to
918 talk to the DC, so try and see if we can
919 contact it. Theoretically this isn't neccessary
920 as the init_dc_connection() in init_child_recv()
921 will do this, but we can start detecting the DC
923 set_domain_online_request(domain);
929 status = pdb_enum_trusted_domains(talloc_tos(), &num_domains, &domains);
930 if (!NT_STATUS_IS_OK(status)) {
931 DBG_ERR("pdb_enum_trusted_domains() failed - %s\n",
936 for (i = 0; i < num_domains; i++) {
937 enum netr_SchannelType sec_chan_type = SEC_CHAN_DOMAIN;
938 uint32_t trust_flags = 0;
940 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
941 sec_chan_type = SEC_CHAN_DNS_DOMAIN;
944 if (!(domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
945 sec_chan_type = SEC_CHAN_NULL;
948 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
949 trust_flags |= NETR_TRUST_FLAG_INBOUND;
951 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
952 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
954 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
955 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
958 status = add_trusted_domain(domains[i]->netbios_name,
959 domains[i]->domain_name,
960 &domains[i]->security_identifier,
961 domains[i]->trust_type,
963 domains[i]->trust_attributes,
967 if (!NT_STATUS_IS_OK(status)) {
968 DBG_NOTICE("add_trusted_domain returned %s\n",
973 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
974 domain->active_directory = true;
976 domain->domain_type = domains[i]->trust_type;
977 domain->domain_trust_attribs = domains[i]->trust_attributes;
979 if (sec_chan_type != SEC_CHAN_NULL) {
980 /* Even in the parent winbindd we'll need to
981 talk to the DC, so try and see if we can
982 contact it. Theoretically this isn't neccessary
983 as the init_dc_connection() in init_child_recv()
984 will do this, but we can start detecting the DC
986 set_domain_online_request(domain);
990 for (i = 0; i < num_domains; i++) {
991 struct ForestTrustInfo fti;
993 enum ndr_err_code ndr_err;
994 struct winbindd_domain *routing_domain = NULL;
996 if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
1000 if (!(domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
1004 if (domains[i]->trust_forest_trust_info.length == 0) {
1008 routing_domain = find_domain_from_name_noinit(
1009 domains[i]->netbios_name);
1010 if (routing_domain == NULL) {
1011 DBG_ERR("Can't find winbindd domain [%s]\n",
1012 domains[i]->netbios_name);
1016 ndr_err = ndr_pull_struct_blob_all(
1017 &domains[i]->trust_forest_trust_info,
1019 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
1020 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1021 DBG_ERR("ndr_pull_ForestTrustInfo(%s) - %s\n",
1022 domains[i]->netbios_name,
1023 ndr_map_error2string(ndr_err));
1027 for (fi = 0; fi < fti.count; fi++) {
1028 struct ForestTrustInfoRecord *rec =
1029 &fti.records[fi].record;
1030 struct ForestTrustDataDomainInfo *drec = NULL;
1032 if (rec->type != FOREST_TRUST_DOMAIN_INFO) {
1035 drec = &rec->data.info;
1037 if (rec->flags & LSA_NB_DISABLED_MASK) {
1041 if (rec->flags & LSA_SID_DISABLED_MASK) {
1047 * also try to find a matching
1048 * LSA_TLN_DISABLED_MASK ???
1051 domain = find_domain_from_name_noinit(drec->netbios_name.string);
1052 if (domain != NULL) {
1056 status = add_trusted_domain(drec->netbios_name.string,
1057 drec->dns_name.string,
1059 LSA_TRUST_TYPE_UPLEVEL,
1060 NETR_TRUST_FLAG_OUTBOUND,
1065 if (!NT_STATUS_IS_OK(status)) {
1066 DBG_NOTICE("add_trusted_domain returned %s\n",
1070 if (domain == NULL) {
1080 /* Look up global info for the winbind daemon */
1081 bool init_domain_list(void)
1083 int role = lp_server_role();
1084 struct pdb_domain_info *pdb_domain_info = NULL;
1085 struct winbindd_domain *domain = NULL;
1089 /* Free existing list */
1092 /* BUILTIN domain */
1094 status = add_trusted_domain("BUILTIN",
1096 &global_sid_Builtin,
1097 LSA_TRUST_TYPE_DOWNLEVEL,
1098 0, /* trust_flags */
1099 0, /* trust_attribs */
1103 if (!NT_STATUS_IS_OK(status)) {
1104 DBG_ERR("add_trusted_domain BUILTIN returned %s\n",
1112 * In case the passdb backend is passdb_dsdb the domain SID comes from
1113 * dsdb, not from secrets.tdb. As we use the domain SID in various
1114 * places, we must ensure the domain SID is migrated from dsdb to
1115 * secrets.tdb before get_global_sam_sid() is called the first time.
1117 * The migration is done as part of the passdb_dsdb initialisation,
1118 * calling pdb_get_domain_info() triggers it.
1120 pdb_domain_info = pdb_get_domain_info(talloc_tos());
1122 if ( role == ROLE_ACTIVE_DIRECTORY_DC ) {
1123 uint32_t trust_flags;
1125 enum netr_SchannelType sec_chan_type;
1126 const char *account_name;
1127 struct samr_Password current_nt_hash;
1129 if (pdb_domain_info == NULL) {
1130 DEBUG(0, ("Failed to fetch our own, local AD "
1131 "domain info from sam.ldb\n"));
1135 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1136 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1137 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1138 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1140 is_root = strequal(pdb_domain_info->dns_domain,
1141 pdb_domain_info->dns_forest);
1143 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1146 status = add_trusted_domain(pdb_domain_info->name,
1147 pdb_domain_info->dns_domain,
1148 &pdb_domain_info->sid,
1149 LSA_TRUST_TYPE_UPLEVEL,
1151 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1155 TALLOC_FREE(pdb_domain_info);
1156 if (!NT_STATUS_IS_OK(status)) {
1157 DBG_ERR("Failed to add our own, local AD "
1158 "domain to winbindd's internal list\n");
1163 * We need to call this to find out if we are an RODC
1165 ok = get_trust_pw_hash(domain->name,
1166 current_nt_hash.hash,
1171 * If get_trust_pw_hash() fails, then try and
1172 * fetch the password from the more recent of
1173 * secrets.{ldb,tdb} using the
1174 * pdb_get_trust_credentials()
1176 ok = migrate_secrets_tdb_to_ldb(domain);
1179 DEBUG(0, ("Failed to migrate our own, "
1180 "local AD domain join password for "
1181 "winbindd's internal use into "
1185 ok = get_trust_pw_hash(domain->name,
1186 current_nt_hash.hash,
1190 DEBUG(0, ("Failed to find our our own, just "
1191 "written local AD domain join "
1192 "password for winbindd's internal "
1193 "use in secrets.tdb\n"));
1198 domain->secure_channel_type = sec_chan_type;
1199 if (sec_chan_type == SEC_CHAN_RODC) {
1200 domain->rodc = true;
1204 uint32_t trust_flags;
1205 enum netr_SchannelType secure_channel_type;
1207 trust_flags = NETR_TRUST_FLAG_OUTBOUND;
1208 if (role != ROLE_DOMAIN_MEMBER) {
1209 trust_flags |= NETR_TRUST_FLAG_PRIMARY;
1212 if (role > ROLE_DOMAIN_MEMBER) {
1213 secure_channel_type = SEC_CHAN_BDC;
1215 secure_channel_type = SEC_CHAN_LOCAL;
1218 status = add_trusted_domain(get_global_sam_name(),
1220 get_global_sam_sid(),
1221 LSA_TRUST_TYPE_DOWNLEVEL,
1223 0, /* trust_attribs */
1224 secure_channel_type,
1227 if (!NT_STATUS_IS_OK(status)) {
1228 DBG_ERR("Failed to add local SAM to "
1229 "domain to winbindd's internal list\n");
1235 ok = add_trusted_domains_dc();
1237 DBG_ERR("init_domain_list_dc failed\n");
1242 if ( role == ROLE_DOMAIN_MEMBER ) {
1243 struct dom_sid our_sid;
1244 uint32_t trust_type;
1246 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
1247 DEBUG(0, ("Could not fetch our SID - did we join?\n"));
1251 if (lp_realm() != NULL) {
1252 trust_type = LSA_TRUST_TYPE_UPLEVEL;
1254 trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1257 status = add_trusted_domain(lp_workgroup(),
1261 NETR_TRUST_FLAG_PRIMARY|
1262 NETR_TRUST_FLAG_OUTBOUND,
1263 0, /* trust_attribs */
1267 if (!NT_STATUS_IS_OK(status)) {
1268 DBG_ERR("Failed to add local SAM to "
1269 "domain to winbindd's internal list\n");
1272 /* Even in the parent winbindd we'll need to
1273 talk to the DC, so try and see if we can
1274 contact it. Theoretically this isn't neccessary
1275 as the init_dc_connection() in init_child_recv()
1276 will do this, but we can start detecting the DC
1278 set_domain_online_request(domain);
1282 status = imessaging_register(winbind_imessaging_context(), NULL,
1283 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1284 wb_imsg_new_trusted_domain);
1285 if (!NT_STATUS_IS_OK(status)) {
1286 DBG_ERR("imessaging_register failed %s\n", nt_errstr(status));
1294 * Given a domain name, return the struct winbindd domain info for it
1296 * @note Do *not* pass lp_workgroup() to this function. domain_list
1297 * may modify it's value, and free that pointer. Instead, our local
1298 * domain may be found by calling find_our_domain().
1302 * @return The domain structure for the named domain, if it is working.
1305 struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
1307 struct winbindd_domain *domain;
1309 /* Search through list */
1311 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1312 if (strequal(domain_name, domain->name)) {
1315 if (domain->alt_name == NULL) {
1318 if (strequal(domain_name, domain->alt_name)) {
1329 * Given a domain name, return the struct winbindd domain if it's a direct
1332 * @return The domain structure for the named domain, if it is a direct outgoing trust
1334 struct winbindd_domain *find_trust_from_name_noinit(const char *domain_name)
1336 struct winbindd_domain *domain = NULL;
1338 domain = find_domain_from_name_noinit(domain_name);
1339 if (domain == NULL) {
1343 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1350 struct winbindd_domain *find_domain_from_name(const char *domain_name)
1352 struct winbindd_domain *domain;
1354 domain = find_domain_from_name_noinit(domain_name);
1359 if (!domain->initialized)
1360 init_dc_connection(domain, false);
1365 /* Given a domain sid, return the struct winbindd domain info for it */
1367 struct winbindd_domain *find_domain_from_sid_noinit(const struct dom_sid *sid)
1369 struct winbindd_domain *domain;
1371 /* Search through list */
1373 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1374 if (dom_sid_compare_domain(sid, &domain->sid) == 0)
1384 * Given a domain sid, return the struct winbindd domain if it's a direct
1387 * @return The domain structure for the specified domain, if it is a direct outgoing trust
1389 struct winbindd_domain *find_trust_from_sid_noinit(const struct dom_sid *sid)
1391 struct winbindd_domain *domain = NULL;
1393 domain = find_domain_from_sid_noinit(sid);
1394 if (domain == NULL) {
1398 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1405 /* Given a domain sid, return the struct winbindd domain info for it */
1407 struct winbindd_domain *find_domain_from_sid(const struct dom_sid *sid)
1409 struct winbindd_domain *domain;
1411 domain = find_domain_from_sid_noinit(sid);
1416 if (!domain->initialized)
1417 init_dc_connection(domain, false);
1422 struct winbindd_domain *find_our_domain(void)
1424 struct winbindd_domain *domain;
1426 /* Search through list */
1428 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1429 if (domain->primary)
1433 smb_panic("Could not find our domain");
1437 struct winbindd_domain *find_default_route_domain(void)
1440 return find_our_domain();
1442 DBG_DEBUG("Routing logic not yet implemented on a DC\n");
1446 /* Find the appropriate domain to lookup a name or SID */
1448 struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)
1450 DBG_DEBUG("SID [%s]\n", sid_string_dbg(sid));
1453 * SIDs in the S-1-22-{1,2} domain and well-known SIDs should be handled
1457 if ( sid_check_is_in_unix_groups(sid) ||
1458 sid_check_is_unix_groups(sid) ||
1459 sid_check_is_in_unix_users(sid) ||
1460 sid_check_is_unix_users(sid) ||
1461 sid_check_is_wellknown_domain(sid, NULL) ||
1462 sid_check_is_in_wellknown_domain(sid) )
1464 return find_domain_from_sid(get_global_sam_sid());
1468 * On member servers the internal domains are different: These are part
1472 if (is_internal_domain(sid) || is_in_internal_domain(sid)) {
1473 DEBUG(10, ("calling find_domain_from_sid\n"));
1474 return find_domain_from_sid(sid);
1478 struct winbindd_domain *domain = NULL;
1480 domain = find_domain_from_sid_noinit(sid);
1481 if (domain == NULL) {
1485 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1489 return domain->routing_domain;
1492 /* On a member server a query for SID or name can always go to our
1495 DEBUG(10, ("calling find_our_domain\n"));
1496 return find_our_domain();
1499 struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
1501 if ( strequal(domain_name, unix_users_domain_name() ) ||
1502 strequal(domain_name, unix_groups_domain_name() ) )
1505 * The "Unix User" and "Unix Group" domain our handled by
1508 return find_domain_from_name_noinit( get_global_sam_name() );
1511 if (strequal(domain_name, "BUILTIN") ||
1512 strequal(domain_name, get_global_sam_name()))
1513 return find_domain_from_name_noinit(domain_name);
1516 struct winbindd_domain *domain = NULL;
1518 domain = find_domain_from_name_noinit(domain_name);
1519 if (domain == NULL) {
1523 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1527 return domain->routing_domain;
1530 return find_our_domain();
1533 /* Is this a domain which we may assume no DOMAIN\ prefix? */
1535 static bool assume_domain(const char *domain)
1537 /* never assume the domain on a standalone server */
1539 if ( lp_server_role() == ROLE_STANDALONE )
1542 /* domain member servers may possibly assume for the domain name */
1544 if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
1545 if ( !strequal(lp_workgroup(), domain) )
1548 if ( lp_winbind_use_default_domain() )
1552 /* only left with a domain controller */
1554 if ( strequal(get_global_sam_name(), domain) ) {
1561 /* Parse a string of the form DOMAIN\user into a domain and a user */
1563 bool parse_domain_user(const char *domuser, fstring domain, fstring user)
1565 char *p = strchr(domuser,*lp_winbind_separator());
1568 fstrcpy(user, domuser);
1569 p = strchr(domuser, '@');
1571 if ( assume_domain(lp_workgroup()) && p == NULL) {
1572 fstrcpy(domain, lp_workgroup());
1573 } else if (p != NULL) {
1574 fstrcpy(domain, p + 1);
1575 user[PTR_DIFF(p, domuser)] = 0;
1581 fstrcpy(domain, domuser);
1582 domain[PTR_DIFF(p, domuser)] = 0;
1585 return strupper_m(domain);
1588 bool parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser,
1589 char **domain, char **user)
1591 fstring fstr_domain, fstr_user;
1592 if (!parse_domain_user(domuser, fstr_domain, fstr_user)) {
1595 *domain = talloc_strdup(mem_ctx, fstr_domain);
1596 *user = talloc_strdup(mem_ctx, fstr_user);
1597 return ((*domain != NULL) && (*user != NULL));
1600 /* Ensure an incoming username from NSS is fully qualified. Replace the
1601 incoming fstring with DOMAIN <separator> user. Returns the same
1602 values as parse_domain_user() but also replaces the incoming username.
1603 Used to ensure all names are fully qualified within winbindd.
1604 Used by the NSS protocols of auth, chauthtok, logoff and ccache_ntlm_auth.
1605 The protocol definitions of auth_crap, chng_pswd_auth_crap
1606 really should be changed to use this instead of doing things
1609 bool canonicalize_username(fstring username_inout, fstring domain, fstring user)
1611 if (!parse_domain_user(username_inout, domain, user)) {
1614 slprintf(username_inout, sizeof(fstring) - 1, "%s%c%s",
1615 domain, *lp_winbind_separator(),
1621 Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
1622 'winbind separator' options.
1624 - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
1627 If we are a PDC or BDC, and this is for our domain, do likewise.
1629 On an AD DC we always fill DOMAIN\\USERNAME.
1631 We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1633 void fill_domain_username(fstring name, const char *domain, const char *user, bool can_assume)
1637 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1641 fstrcpy(tmp_user, user);
1642 (void)strlower_m(tmp_user);
1644 if (can_assume && assume_domain(domain)) {
1645 strlcpy(name, tmp_user, sizeof(fstring));
1647 slprintf(name, sizeof(fstring) - 1, "%s%c%s",
1648 domain, *lp_winbind_separator(),
1654 * talloc version of fill_domain_username()
1655 * return NULL on talloc failure.
1657 char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
1662 char *tmp_user, *name;
1664 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1668 tmp_user = talloc_strdup(mem_ctx, user);
1669 if (!strlower_m(tmp_user)) {
1670 TALLOC_FREE(tmp_user);
1674 if (can_assume && assume_domain(domain)) {
1677 name = talloc_asprintf(mem_ctx, "%s%c%s",
1679 *lp_winbind_separator(),
1681 TALLOC_FREE(tmp_user);
1688 * Client list accessor functions
1691 static struct winbindd_cli_state *_client_list;
1692 static int _num_clients;
1694 /* Return list of all connected clients */
1696 struct winbindd_cli_state *winbindd_client_list(void)
1698 return _client_list;
1701 /* Return list-tail of all connected clients */
1703 struct winbindd_cli_state *winbindd_client_list_tail(void)
1705 return DLIST_TAIL(_client_list);
1708 /* Return previous (read:newer) client in list */
1710 struct winbindd_cli_state *
1711 winbindd_client_list_prev(struct winbindd_cli_state *cli)
1713 return DLIST_PREV(cli);
1716 /* Add a connection to the list */
1718 void winbindd_add_client(struct winbindd_cli_state *cli)
1720 cli->last_access = time(NULL);
1721 DLIST_ADD(_client_list, cli);
1725 /* Remove a client from the list */
1727 void winbindd_remove_client(struct winbindd_cli_state *cli)
1729 DLIST_REMOVE(_client_list, cli);
1733 /* Move a client to head or list */
1735 void winbindd_promote_client(struct winbindd_cli_state *cli)
1737 cli->last_access = time(NULL);
1738 DLIST_PROMOTE(_client_list, cli);
1741 /* Return number of open clients */
1743 int winbindd_num_clients(void)
1745 return _num_clients;
1748 NTSTATUS lookup_usergroups_cached(TALLOC_CTX *mem_ctx,
1749 const struct dom_sid *user_sid,
1750 uint32_t *p_num_groups, struct dom_sid **user_sids)
1752 struct netr_SamInfo3 *info3 = NULL;
1753 NTSTATUS status = NT_STATUS_NO_MEMORY;
1754 uint32_t num_groups = 0;
1756 DEBUG(3,(": lookup_usergroups_cached\n"));
1761 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1763 if (info3 == NULL) {
1764 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1768 * Before bug #7843 the "Domain Local" groups were added with a
1769 * lookupuseraliases call, but this isn't done anymore for our domain
1770 * so we need to resolve resource groups here.
1772 * When to use Resource Groups:
1773 * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
1775 status = sid_array_from_info3(mem_ctx, info3,
1780 if (!NT_STATUS_IS_OK(status)) {
1786 *p_num_groups = num_groups;
1787 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1789 DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1794 /*********************************************************************
1795 We use this to remove spaces from user and group names
1796 ********************************************************************/
1798 NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
1799 const char *domain_name,
1803 struct winbindd_domain *domain = NULL;
1806 if (!name || !normalized) {
1807 return NT_STATUS_INVALID_PARAMETER;
1810 if (!lp_winbind_normalize_names()) {
1811 return NT_STATUS_PROCEDURE_NOT_FOUND;
1814 domain = find_domain_from_name_noinit(domain_name);
1815 if (domain == NULL) {
1816 DBG_ERR("Failed to find domain '%s'\n", domain_name);
1817 return NT_STATUS_NO_SUCH_DOMAIN;
1820 /* Alias support and whitespace replacement are mutually
1823 nt_status = resolve_username_to_alias(mem_ctx, domain,
1825 if (NT_STATUS_IS_OK(nt_status)) {
1826 /* special return code to let the caller know we
1827 mapped to an alias */
1828 return NT_STATUS_FILE_RENAMED;
1831 /* check for an unreachable domain */
1833 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1834 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1836 set_domain_offline(domain);
1840 /* deal with whitespace */
1842 *normalized = talloc_strdup(mem_ctx, name);
1843 if (!(*normalized)) {
1844 return NT_STATUS_NO_MEMORY;
1847 all_string_sub( *normalized, " ", "_", 0 );
1849 return NT_STATUS_OK;
1852 /*********************************************************************
1853 We use this to do the inverse of normalize_name_map()
1854 ********************************************************************/
1856 NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
1861 struct winbindd_domain *domain = find_our_domain();
1863 if (!name || !normalized) {
1864 return NT_STATUS_INVALID_PARAMETER;
1867 if (!lp_winbind_normalize_names()) {
1868 return NT_STATUS_PROCEDURE_NOT_FOUND;
1871 /* Alias support and whitespace replacement are mutally
1874 /* When mapping from an alias to a username, we don't know the
1875 domain. But we only need a domain structure to cache
1876 a successful lookup , so just our own domain structure for
1879 nt_status = resolve_alias_to_username(mem_ctx, domain,
1881 if (NT_STATUS_IS_OK(nt_status)) {
1882 /* Special return code to let the caller know we mapped
1884 return NT_STATUS_FILE_RENAMED;
1887 /* check for an unreachable domain */
1889 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1890 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1892 set_domain_offline(domain);
1896 /* deal with whitespace */
1898 *normalized = talloc_strdup(mem_ctx, name);
1899 if (!(*normalized)) {
1900 return NT_STATUS_NO_MEMORY;
1903 all_string_sub(*normalized, "_", " ", 0);
1905 return NT_STATUS_OK;
1908 /*********************************************************************
1909 ********************************************************************/
1911 bool winbindd_can_contact_domain(struct winbindd_domain *domain)
1913 struct winbindd_tdc_domain *tdc = NULL;
1914 TALLOC_CTX *frame = talloc_stackframe();
1917 /* We can contact the domain if it is our primary domain */
1919 if (domain->primary) {
1924 /* Trust the TDC cache and not the winbindd_domain flags */
1926 if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
1927 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
1933 /* Can always contact a domain that is in out forest */
1935 if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1941 * On a _member_ server, we cannot contact the domain if it
1942 * is running AD and we have no inbound trust.
1946 domain->active_directory &&
1947 ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
1949 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
1950 "and we have no inbound trust.\n", domain->name));
1954 /* Assume everything else is ok (probably not true but what
1960 talloc_destroy(frame);
1965 /*********************************************************************
1966 ********************************************************************/
1968 bool winbindd_internal_child(struct winbindd_child *child)
1970 if ((child == idmap_child()) || (child == locator_child())) {
1977 #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
1979 /*********************************************************************
1980 ********************************************************************/
1982 static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
1985 char addr[INET6_ADDRSTRLEN];
1986 const char *kdc = NULL;
1989 if (!domain || !domain->alt_name || !*domain->alt_name) {
1993 if (domain->initialized && !domain->active_directory) {
1994 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
1999 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
2002 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
2004 kdc = domain->dcname;
2007 if (!kdc || !*kdc) {
2008 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
2013 if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
2014 domain->alt_name) == -1) {
2018 DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
2021 setenv(var, kdc, 1);
2025 /*********************************************************************
2026 ********************************************************************/
2028 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2030 struct winbindd_domain *our_dom = find_our_domain();
2032 winbindd_set_locator_kdc_env(domain);
2034 if (domain != our_dom) {
2035 winbindd_set_locator_kdc_env(our_dom);
2039 /*********************************************************************
2040 ********************************************************************/
2042 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2046 if (!domain || !domain->alt_name || !*domain->alt_name) {
2050 if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
2051 domain->alt_name) == -1) {
2060 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2065 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2070 #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
2072 void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
2074 resp->data.auth.nt_status = NT_STATUS_V(result);
2075 fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
2077 /* we might have given a more useful error above */
2078 if (*resp->data.auth.error_string == '\0')
2079 fstrcpy(resp->data.auth.error_string,
2080 get_friendly_nt_error_msg(result));
2081 resp->data.auth.pam_error = nt_status_to_pam(result);
2084 bool is_domain_offline(const struct winbindd_domain *domain)
2086 if (get_global_winbindd_state_offline()) {
2089 return !domain->online;
2092 bool is_domain_online(const struct winbindd_domain *domain)
2094 return !is_domain_offline(domain);
2098 * Parse an char array into a list of sids.
2100 * The input sidstr should consist of 0-terminated strings
2101 * representing sids, separated by newline characters '\n'.
2102 * The list is terminated by an empty string, i.e.
2103 * character '\0' directly following a character '\n'
2104 * (or '\0' right at the start of sidstr).
2106 bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
2107 struct dom_sid **sids, uint32_t *num_sids)
2115 while (p[0] != '\0') {
2117 const char *q = NULL;
2119 if (!dom_sid_parse_endp(p, &sid, &q)) {
2120 DEBUG(1, ("Could not parse sid %s\n", p));
2124 DEBUG(1, ("Got invalid sidstr: %s\n", p));
2127 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
2137 bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
2138 struct unixid **pxids, uint32_t *pnum_xids)
2141 struct unixid *xids = NULL;
2142 uint32_t num_xids = 0;
2149 while (p[0] != '\0') {
2152 unsigned long long id;
2157 xid = (struct unixid) { .type = ID_TYPE_UID };
2160 xid = (struct unixid) { .type = ID_TYPE_GID };
2168 id = strtoull(p, &endp, 10);
2169 if ((id == ULLONG_MAX) && (errno == ERANGE)) {
2172 if (*endp != '\n') {
2178 if ((unsigned long long)xid.id != id) {
2182 tmp = talloc_realloc(mem_ctx, xids, struct unixid, num_xids+1);
2188 xids[num_xids] = xid;
2193 *pnum_xids = num_xids;