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 TALLOC_FREE(domain->dcname);
785 domain->dcname = talloc_strdup(domain,
786 state->request->data.init_conn.dcname);
787 if (domain->dcname == NULL) {
788 return WINBINDD_ERROR;
792 init_dc_connection(domain, false);
794 if (!domain->initialized) {
795 /* If we return error here we can't do any cached authentication,
796 but we may be in disconnected mode and can't initialize correctly.
797 Do what the previous code did and just return without initialization,
798 once we go online we'll re-initialize.
800 DEBUG(5, ("winbindd_dual_init_connection: %s returning without initialization "
801 "online = %d\n", domain->name, (int)domain->online ));
804 fstrcpy(state->response->data.domain_info.name, domain->name);
805 fstrcpy(state->response->data.domain_info.alt_name, domain->alt_name);
806 sid_to_fstring(state->response->data.domain_info.sid, &domain->sid);
808 state->response->data.domain_info.native_mode
809 = domain->native_mode;
810 state->response->data.domain_info.active_directory
811 = domain->active_directory;
812 state->response->data.domain_info.primary
818 static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
821 struct server_id server_id,
826 DBG_NOTICE("Rescanning trusted domains\n");
828 ok = add_trusted_domains_dc();
830 DBG_ERR("Failed to reload trusted domains\n");
835 * We did not get the secret when we queried secrets.tdb, so read it
836 * from secrets.tdb and re-sync the databases
838 static bool migrate_secrets_tdb_to_ldb(struct winbindd_domain *domain)
841 struct cli_credentials *creds;
842 NTSTATUS can_migrate = pdb_get_trust_credentials(domain->name,
843 NULL, domain, &creds);
844 if (!NT_STATUS_IS_OK(can_migrate)) {
845 DEBUG(0, ("Failed to fetch our own, local AD domain join "
846 "password for winbindd's internal use, both from "
847 "secrets.tdb and secrets.ldb: %s\n",
848 nt_errstr(can_migrate)));
853 * NOTE: It is very unlikely we end up here if there is an
854 * oldpass, because a new password is created at
855 * classicupgrade, so this is not a concern.
857 ok = secrets_store_machine_pw_sync(cli_credentials_get_password(creds),
859 cli_credentials_get_domain(creds),
860 cli_credentials_get_realm(creds),
861 cli_credentials_get_salt_principal(creds),
862 0, /* Supported enc types, unused */
864 cli_credentials_get_password_last_changed_time(creds),
865 cli_credentials_get_secure_channel_type(creds),
866 false /* do_delete: Do not delete */);
869 DEBUG(0, ("Failed to write our our own, "
870 "local AD domain join password for "
871 "winbindd's internal use into secrets.tdb\n"));
877 static bool add_trusted_domains_dc(void)
879 struct winbindd_domain *domain = NULL;
880 struct pdb_trusted_domain **domains = NULL;
881 uint32_t num_domains = 0;
885 if (!(pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX)) {
886 struct trustdom_info **ti = NULL;
888 status = pdb_enum_trusteddoms(talloc_tos(), &num_domains, &ti);
889 if (!NT_STATUS_IS_OK(status)) {
890 DBG_ERR("pdb_enum_trusteddoms() failed - %s\n",
895 for (i = 0; i < num_domains; i++) {
896 status = add_trusted_domain(ti[i]->name,
899 LSA_TRUST_TYPE_DOWNLEVEL,
900 NETR_TRUST_FLAG_OUTBOUND,
905 if (!NT_STATUS_IS_OK(status)) {
906 DBG_NOTICE("add_trusted_domain returned %s\n",
911 /* Even in the parent winbindd we'll need to
912 talk to the DC, so try and see if we can
913 contact it. Theoretically this isn't neccessary
914 as the init_dc_connection() in init_child_recv()
915 will do this, but we can start detecting the DC
917 set_domain_online_request(domain);
923 status = pdb_enum_trusted_domains(talloc_tos(), &num_domains, &domains);
924 if (!NT_STATUS_IS_OK(status)) {
925 DBG_ERR("pdb_enum_trusted_domains() failed - %s\n",
930 for (i = 0; i < num_domains; i++) {
931 enum netr_SchannelType sec_chan_type = SEC_CHAN_DOMAIN;
932 uint32_t trust_flags = 0;
934 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
935 sec_chan_type = SEC_CHAN_DNS_DOMAIN;
938 if (!(domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
939 sec_chan_type = SEC_CHAN_NULL;
942 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
943 trust_flags |= NETR_TRUST_FLAG_INBOUND;
945 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
946 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
948 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
949 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
952 status = add_trusted_domain(domains[i]->netbios_name,
953 domains[i]->domain_name,
954 &domains[i]->security_identifier,
955 domains[i]->trust_type,
957 domains[i]->trust_attributes,
961 if (!NT_STATUS_IS_OK(status)) {
962 DBG_NOTICE("add_trusted_domain returned %s\n",
967 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
968 domain->active_directory = true;
970 domain->domain_type = domains[i]->trust_type;
971 domain->domain_trust_attribs = domains[i]->trust_attributes;
973 if (sec_chan_type != SEC_CHAN_NULL) {
974 /* Even in the parent winbindd we'll need to
975 talk to the DC, so try and see if we can
976 contact it. Theoretically this isn't neccessary
977 as the init_dc_connection() in init_child_recv()
978 will do this, but we can start detecting the DC
980 set_domain_online_request(domain);
984 for (i = 0; i < num_domains; i++) {
985 struct ForestTrustInfo fti;
987 enum ndr_err_code ndr_err;
988 struct winbindd_domain *routing_domain = NULL;
990 if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
994 if (!(domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
998 if (domains[i]->trust_forest_trust_info.length == 0) {
1002 routing_domain = find_domain_from_name_noinit(
1003 domains[i]->netbios_name);
1004 if (routing_domain == NULL) {
1005 DBG_ERR("Can't find winbindd domain [%s]\n",
1006 domains[i]->netbios_name);
1010 ndr_err = ndr_pull_struct_blob_all(
1011 &domains[i]->trust_forest_trust_info,
1013 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
1014 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1015 DBG_ERR("ndr_pull_ForestTrustInfo(%s) - %s\n",
1016 domains[i]->netbios_name,
1017 ndr_map_error2string(ndr_err));
1021 for (fi = 0; fi < fti.count; fi++) {
1022 struct ForestTrustInfoRecord *rec =
1023 &fti.records[fi].record;
1024 struct ForestTrustDataDomainInfo *drec = NULL;
1026 if (rec->type != FOREST_TRUST_DOMAIN_INFO) {
1029 drec = &rec->data.info;
1031 if (rec->flags & LSA_NB_DISABLED_MASK) {
1035 if (rec->flags & LSA_SID_DISABLED_MASK) {
1041 * also try to find a matching
1042 * LSA_TLN_DISABLED_MASK ???
1045 domain = find_domain_from_name_noinit(drec->netbios_name.string);
1046 if (domain != NULL) {
1050 status = add_trusted_domain(drec->netbios_name.string,
1051 drec->dns_name.string,
1053 LSA_TRUST_TYPE_UPLEVEL,
1054 NETR_TRUST_FLAG_OUTBOUND,
1059 if (!NT_STATUS_IS_OK(status)) {
1060 DBG_NOTICE("add_trusted_domain returned %s\n",
1064 if (domain == NULL) {
1074 /* Look up global info for the winbind daemon */
1075 bool init_domain_list(void)
1077 int role = lp_server_role();
1078 struct pdb_domain_info *pdb_domain_info = NULL;
1079 struct winbindd_domain *domain = NULL;
1083 /* Free existing list */
1086 /* BUILTIN domain */
1088 status = add_trusted_domain("BUILTIN",
1090 &global_sid_Builtin,
1091 LSA_TRUST_TYPE_DOWNLEVEL,
1092 0, /* trust_flags */
1093 0, /* trust_attribs */
1097 if (!NT_STATUS_IS_OK(status)) {
1098 DBG_ERR("add_trusted_domain BUILTIN returned %s\n",
1106 * In case the passdb backend is passdb_dsdb the domain SID comes from
1107 * dsdb, not from secrets.tdb. As we use the domain SID in various
1108 * places, we must ensure the domain SID is migrated from dsdb to
1109 * secrets.tdb before get_global_sam_sid() is called the first time.
1111 * The migration is done as part of the passdb_dsdb initialisation,
1112 * calling pdb_get_domain_info() triggers it.
1114 pdb_domain_info = pdb_get_domain_info(talloc_tos());
1116 if ( role == ROLE_ACTIVE_DIRECTORY_DC ) {
1117 uint32_t trust_flags;
1119 enum netr_SchannelType sec_chan_type;
1120 const char *account_name;
1121 struct samr_Password current_nt_hash;
1123 if (pdb_domain_info == NULL) {
1124 DEBUG(0, ("Failed to fetch our own, local AD "
1125 "domain info from sam.ldb\n"));
1129 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1130 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1131 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1132 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1134 is_root = strequal(pdb_domain_info->dns_domain,
1135 pdb_domain_info->dns_forest);
1137 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1140 status = add_trusted_domain(pdb_domain_info->name,
1141 pdb_domain_info->dns_domain,
1142 &pdb_domain_info->sid,
1143 LSA_TRUST_TYPE_UPLEVEL,
1145 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1149 TALLOC_FREE(pdb_domain_info);
1150 if (!NT_STATUS_IS_OK(status)) {
1151 DBG_ERR("Failed to add our own, local AD "
1152 "domain to winbindd's internal list\n");
1157 * We need to call this to find out if we are an RODC
1159 ok = get_trust_pw_hash(domain->name,
1160 current_nt_hash.hash,
1165 * If get_trust_pw_hash() fails, then try and
1166 * fetch the password from the more recent of
1167 * secrets.{ldb,tdb} using the
1168 * pdb_get_trust_credentials()
1170 ok = migrate_secrets_tdb_to_ldb(domain);
1173 DEBUG(0, ("Failed to migrate our own, "
1174 "local AD domain join password for "
1175 "winbindd's internal use into "
1179 ok = get_trust_pw_hash(domain->name,
1180 current_nt_hash.hash,
1184 DEBUG(0, ("Failed to find our our own, just "
1185 "written local AD domain join "
1186 "password for winbindd's internal "
1187 "use in secrets.tdb\n"));
1192 domain->secure_channel_type = sec_chan_type;
1193 if (sec_chan_type == SEC_CHAN_RODC) {
1194 domain->rodc = true;
1198 uint32_t trust_flags;
1199 enum netr_SchannelType secure_channel_type;
1201 trust_flags = NETR_TRUST_FLAG_OUTBOUND;
1202 if (role != ROLE_DOMAIN_MEMBER) {
1203 trust_flags |= NETR_TRUST_FLAG_PRIMARY;
1206 if (role > ROLE_DOMAIN_MEMBER) {
1207 secure_channel_type = SEC_CHAN_BDC;
1209 secure_channel_type = SEC_CHAN_LOCAL;
1212 status = add_trusted_domain(get_global_sam_name(),
1214 get_global_sam_sid(),
1215 LSA_TRUST_TYPE_DOWNLEVEL,
1217 0, /* trust_attribs */
1218 secure_channel_type,
1221 if (!NT_STATUS_IS_OK(status)) {
1222 DBG_ERR("Failed to add local SAM to "
1223 "domain to winbindd's internal list\n");
1229 ok = add_trusted_domains_dc();
1231 DBG_ERR("init_domain_list_dc failed\n");
1236 if ( role == ROLE_DOMAIN_MEMBER ) {
1237 struct dom_sid our_sid;
1238 uint32_t trust_type;
1240 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
1241 DEBUG(0, ("Could not fetch our SID - did we join?\n"));
1245 if (lp_realm() != NULL) {
1246 trust_type = LSA_TRUST_TYPE_UPLEVEL;
1248 trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1251 status = add_trusted_domain(lp_workgroup(),
1255 NETR_TRUST_FLAG_PRIMARY|
1256 NETR_TRUST_FLAG_OUTBOUND,
1257 0, /* trust_attribs */
1261 if (!NT_STATUS_IS_OK(status)) {
1262 DBG_ERR("Failed to add local SAM to "
1263 "domain to winbindd's internal list\n");
1266 /* Even in the parent winbindd we'll need to
1267 talk to the DC, so try and see if we can
1268 contact it. Theoretically this isn't neccessary
1269 as the init_dc_connection() in init_child_recv()
1270 will do this, but we can start detecting the DC
1272 set_domain_online_request(domain);
1276 status = imessaging_register(winbind_imessaging_context(), NULL,
1277 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1278 wb_imsg_new_trusted_domain);
1279 if (!NT_STATUS_IS_OK(status)) {
1280 DBG_ERR("imessaging_register failed %s\n", nt_errstr(status));
1288 * Given a domain name, return the struct winbindd domain info for it
1290 * @note Do *not* pass lp_workgroup() to this function. domain_list
1291 * may modify it's value, and free that pointer. Instead, our local
1292 * domain may be found by calling find_our_domain().
1296 * @return The domain structure for the named domain, if it is working.
1299 struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
1301 struct winbindd_domain *domain;
1303 /* Search through list */
1305 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1306 if (strequal(domain_name, domain->name)) {
1309 if (domain->alt_name == NULL) {
1312 if (strequal(domain_name, domain->alt_name)) {
1323 * Given a domain name, return the struct winbindd domain if it's a direct
1326 * @return The domain structure for the named domain, if it is a direct outgoing trust
1328 struct winbindd_domain *find_trust_from_name_noinit(const char *domain_name)
1330 struct winbindd_domain *domain = NULL;
1332 domain = find_domain_from_name_noinit(domain_name);
1333 if (domain == NULL) {
1337 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1344 struct winbindd_domain *find_domain_from_name(const char *domain_name)
1346 struct winbindd_domain *domain;
1348 domain = find_domain_from_name_noinit(domain_name);
1353 if (!domain->initialized)
1354 init_dc_connection(domain, false);
1359 /* Given a domain sid, return the struct winbindd domain info for it */
1361 struct winbindd_domain *find_domain_from_sid_noinit(const struct dom_sid *sid)
1363 struct winbindd_domain *domain;
1365 /* Search through list */
1367 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1368 if (dom_sid_compare_domain(sid, &domain->sid) == 0)
1378 * Given a domain sid, return the struct winbindd domain if it's a direct
1381 * @return The domain structure for the specified domain, if it is a direct outgoing trust
1383 struct winbindd_domain *find_trust_from_sid_noinit(const struct dom_sid *sid)
1385 struct winbindd_domain *domain = NULL;
1387 domain = find_domain_from_sid_noinit(sid);
1388 if (domain == NULL) {
1392 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1399 /* Given a domain sid, return the struct winbindd domain info for it */
1401 struct winbindd_domain *find_domain_from_sid(const struct dom_sid *sid)
1403 struct winbindd_domain *domain;
1405 domain = find_domain_from_sid_noinit(sid);
1410 if (!domain->initialized)
1411 init_dc_connection(domain, false);
1416 struct winbindd_domain *find_our_domain(void)
1418 struct winbindd_domain *domain;
1420 /* Search through list */
1422 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1423 if (domain->primary)
1427 smb_panic("Could not find our domain");
1431 struct winbindd_domain *find_default_route_domain(void)
1434 return find_our_domain();
1436 DBG_DEBUG("Routing logic not yet implemented on a DC\n");
1440 /* Find the appropriate domain to lookup a name or SID */
1442 struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)
1444 DBG_DEBUG("SID [%s]\n", sid_string_dbg(sid));
1447 * SIDs in the S-1-22-{1,2} domain and well-known SIDs should be handled
1451 if ( sid_check_is_in_unix_groups(sid) ||
1452 sid_check_is_unix_groups(sid) ||
1453 sid_check_is_in_unix_users(sid) ||
1454 sid_check_is_unix_users(sid) ||
1455 sid_check_is_wellknown_domain(sid, NULL) ||
1456 sid_check_is_in_wellknown_domain(sid) )
1458 return find_domain_from_sid(get_global_sam_sid());
1462 * On member servers the internal domains are different: These are part
1466 if (is_internal_domain(sid) || is_in_internal_domain(sid)) {
1467 DEBUG(10, ("calling find_domain_from_sid\n"));
1468 return find_domain_from_sid(sid);
1472 struct winbindd_domain *domain = NULL;
1474 domain = find_domain_from_sid_noinit(sid);
1475 if (domain == NULL) {
1479 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1483 return domain->routing_domain;
1486 /* On a member server a query for SID or name can always go to our
1489 DEBUG(10, ("calling find_our_domain\n"));
1490 return find_our_domain();
1493 struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
1495 if ( strequal(domain_name, unix_users_domain_name() ) ||
1496 strequal(domain_name, unix_groups_domain_name() ) )
1499 * The "Unix User" and "Unix Group" domain our handled by
1502 return find_domain_from_name_noinit( get_global_sam_name() );
1505 if (strequal(domain_name, "BUILTIN") ||
1506 strequal(domain_name, get_global_sam_name()))
1507 return find_domain_from_name_noinit(domain_name);
1510 struct winbindd_domain *domain = NULL;
1512 domain = find_domain_from_name_noinit(domain_name);
1513 if (domain == NULL) {
1517 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1521 return domain->routing_domain;
1524 return find_our_domain();
1527 /* Is this a domain which we may assume no DOMAIN\ prefix? */
1529 static bool assume_domain(const char *domain)
1531 /* never assume the domain on a standalone server */
1533 if ( lp_server_role() == ROLE_STANDALONE )
1536 /* domain member servers may possibly assume for the domain name */
1538 if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
1539 if ( !strequal(lp_workgroup(), domain) )
1542 if ( lp_winbind_use_default_domain() )
1546 /* only left with a domain controller */
1548 if ( strequal(get_global_sam_name(), domain) ) {
1555 /* Parse a string of the form DOMAIN\user into a domain and a user */
1557 bool parse_domain_user(const char *domuser, fstring domain, fstring user)
1559 char *p = strchr(domuser,*lp_winbind_separator());
1562 fstrcpy(user, domuser);
1563 p = strchr(domuser, '@');
1565 if ( assume_domain(lp_workgroup()) && p == NULL) {
1566 fstrcpy(domain, lp_workgroup());
1567 } else if (p != NULL) {
1568 fstrcpy(domain, p + 1);
1569 user[PTR_DIFF(p, domuser)] = 0;
1575 fstrcpy(domain, domuser);
1576 domain[PTR_DIFF(p, domuser)] = 0;
1579 return strupper_m(domain);
1582 bool parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser,
1583 char **domain, char **user)
1585 fstring fstr_domain, fstr_user;
1586 if (!parse_domain_user(domuser, fstr_domain, fstr_user)) {
1589 *domain = talloc_strdup(mem_ctx, fstr_domain);
1590 *user = talloc_strdup(mem_ctx, fstr_user);
1591 return ((*domain != NULL) && (*user != NULL));
1594 /* Ensure an incoming username from NSS is fully qualified. Replace the
1595 incoming fstring with DOMAIN <separator> user. Returns the same
1596 values as parse_domain_user() but also replaces the incoming username.
1597 Used to ensure all names are fully qualified within winbindd.
1598 Used by the NSS protocols of auth, chauthtok, logoff and ccache_ntlm_auth.
1599 The protocol definitions of auth_crap, chng_pswd_auth_crap
1600 really should be changed to use this instead of doing things
1603 bool canonicalize_username(fstring username_inout, fstring domain, fstring user)
1605 if (!parse_domain_user(username_inout, domain, user)) {
1608 slprintf(username_inout, sizeof(fstring) - 1, "%s%c%s",
1609 domain, *lp_winbind_separator(),
1615 Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
1616 'winbind separator' options.
1618 - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
1621 If we are a PDC or BDC, and this is for our domain, do likewise.
1623 On an AD DC we always fill DOMAIN\\USERNAME.
1625 We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1627 void fill_domain_username(fstring name, const char *domain, const char *user, bool can_assume)
1631 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1635 fstrcpy(tmp_user, user);
1636 (void)strlower_m(tmp_user);
1638 if (can_assume && assume_domain(domain)) {
1639 strlcpy(name, tmp_user, sizeof(fstring));
1641 slprintf(name, sizeof(fstring) - 1, "%s%c%s",
1642 domain, *lp_winbind_separator(),
1648 * talloc version of fill_domain_username()
1649 * return NULL on talloc failure.
1651 char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
1656 char *tmp_user, *name;
1658 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1662 tmp_user = talloc_strdup(mem_ctx, user);
1663 if (!strlower_m(tmp_user)) {
1664 TALLOC_FREE(tmp_user);
1668 if (can_assume && assume_domain(domain)) {
1671 name = talloc_asprintf(mem_ctx, "%s%c%s",
1673 *lp_winbind_separator(),
1675 TALLOC_FREE(tmp_user);
1682 * Client list accessor functions
1685 static struct winbindd_cli_state *_client_list;
1686 static int _num_clients;
1688 /* Return list of all connected clients */
1690 struct winbindd_cli_state *winbindd_client_list(void)
1692 return _client_list;
1695 /* Return list-tail of all connected clients */
1697 struct winbindd_cli_state *winbindd_client_list_tail(void)
1699 return DLIST_TAIL(_client_list);
1702 /* Return previous (read:newer) client in list */
1704 struct winbindd_cli_state *
1705 winbindd_client_list_prev(struct winbindd_cli_state *cli)
1707 return DLIST_PREV(cli);
1710 /* Add a connection to the list */
1712 void winbindd_add_client(struct winbindd_cli_state *cli)
1714 cli->last_access = time(NULL);
1715 DLIST_ADD(_client_list, cli);
1719 /* Remove a client from the list */
1721 void winbindd_remove_client(struct winbindd_cli_state *cli)
1723 DLIST_REMOVE(_client_list, cli);
1727 /* Move a client to head or list */
1729 void winbindd_promote_client(struct winbindd_cli_state *cli)
1731 cli->last_access = time(NULL);
1732 DLIST_PROMOTE(_client_list, cli);
1735 /* Return number of open clients */
1737 int winbindd_num_clients(void)
1739 return _num_clients;
1742 NTSTATUS lookup_usergroups_cached(TALLOC_CTX *mem_ctx,
1743 const struct dom_sid *user_sid,
1744 uint32_t *p_num_groups, struct dom_sid **user_sids)
1746 struct netr_SamInfo3 *info3 = NULL;
1747 NTSTATUS status = NT_STATUS_NO_MEMORY;
1748 uint32_t num_groups = 0;
1750 DEBUG(3,(": lookup_usergroups_cached\n"));
1755 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1757 if (info3 == NULL) {
1758 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1762 * Before bug #7843 the "Domain Local" groups were added with a
1763 * lookupuseraliases call, but this isn't done anymore for our domain
1764 * so we need to resolve resource groups here.
1766 * When to use Resource Groups:
1767 * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
1769 status = sid_array_from_info3(mem_ctx, info3,
1774 if (!NT_STATUS_IS_OK(status)) {
1780 *p_num_groups = num_groups;
1781 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1783 DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1788 /*********************************************************************
1789 We use this to remove spaces from user and group names
1790 ********************************************************************/
1792 NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
1793 const char *domain_name,
1797 struct winbindd_domain *domain = NULL;
1800 if (!name || !normalized) {
1801 return NT_STATUS_INVALID_PARAMETER;
1804 if (!lp_winbind_normalize_names()) {
1805 return NT_STATUS_PROCEDURE_NOT_FOUND;
1808 domain = find_domain_from_name_noinit(domain_name);
1809 if (domain == NULL) {
1810 DBG_ERR("Failed to find domain '%s'\n", domain_name);
1811 return NT_STATUS_NO_SUCH_DOMAIN;
1814 /* Alias support and whitespace replacement are mutually
1817 nt_status = resolve_username_to_alias(mem_ctx, domain,
1819 if (NT_STATUS_IS_OK(nt_status)) {
1820 /* special return code to let the caller know we
1821 mapped to an alias */
1822 return NT_STATUS_FILE_RENAMED;
1825 /* check for an unreachable domain */
1827 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1828 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1830 set_domain_offline(domain);
1834 /* deal with whitespace */
1836 *normalized = talloc_strdup(mem_ctx, name);
1837 if (!(*normalized)) {
1838 return NT_STATUS_NO_MEMORY;
1841 all_string_sub( *normalized, " ", "_", 0 );
1843 return NT_STATUS_OK;
1846 /*********************************************************************
1847 We use this to do the inverse of normalize_name_map()
1848 ********************************************************************/
1850 NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
1855 struct winbindd_domain *domain = find_our_domain();
1857 if (!name || !normalized) {
1858 return NT_STATUS_INVALID_PARAMETER;
1861 if (!lp_winbind_normalize_names()) {
1862 return NT_STATUS_PROCEDURE_NOT_FOUND;
1865 /* Alias support and whitespace replacement are mutally
1868 /* When mapping from an alias to a username, we don't know the
1869 domain. But we only need a domain structure to cache
1870 a successful lookup , so just our own domain structure for
1873 nt_status = resolve_alias_to_username(mem_ctx, domain,
1875 if (NT_STATUS_IS_OK(nt_status)) {
1876 /* Special return code to let the caller know we mapped
1878 return NT_STATUS_FILE_RENAMED;
1881 /* check for an unreachable domain */
1883 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1884 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1886 set_domain_offline(domain);
1890 /* deal with whitespace */
1892 *normalized = talloc_strdup(mem_ctx, name);
1893 if (!(*normalized)) {
1894 return NT_STATUS_NO_MEMORY;
1897 all_string_sub(*normalized, "_", " ", 0);
1899 return NT_STATUS_OK;
1902 /*********************************************************************
1903 ********************************************************************/
1905 bool winbindd_can_contact_domain(struct winbindd_domain *domain)
1907 struct winbindd_tdc_domain *tdc = NULL;
1908 TALLOC_CTX *frame = talloc_stackframe();
1911 /* We can contact the domain if it is our primary domain */
1913 if (domain->primary) {
1918 /* Trust the TDC cache and not the winbindd_domain flags */
1920 if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
1921 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
1927 /* Can always contact a domain that is in out forest */
1929 if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1935 * On a _member_ server, we cannot contact the domain if it
1936 * is running AD and we have no inbound trust.
1940 domain->active_directory &&
1941 ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
1943 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
1944 "and we have no inbound trust.\n", domain->name));
1948 /* Assume everything else is ok (probably not true but what
1954 talloc_destroy(frame);
1959 /*********************************************************************
1960 ********************************************************************/
1962 bool winbindd_internal_child(struct winbindd_child *child)
1964 if ((child == idmap_child()) || (child == locator_child())) {
1971 #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
1973 /*********************************************************************
1974 ********************************************************************/
1976 static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
1979 char addr[INET6_ADDRSTRLEN];
1980 const char *kdc = NULL;
1983 if (!domain || !domain->alt_name || !*domain->alt_name) {
1987 if (domain->initialized && !domain->active_directory) {
1988 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
1993 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
1996 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
1998 kdc = domain->dcname;
2001 if (!kdc || !*kdc) {
2002 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
2007 if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
2008 domain->alt_name) == -1) {
2012 DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
2015 setenv(var, kdc, 1);
2019 /*********************************************************************
2020 ********************************************************************/
2022 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2024 struct winbindd_domain *our_dom = find_our_domain();
2026 winbindd_set_locator_kdc_env(domain);
2028 if (domain != our_dom) {
2029 winbindd_set_locator_kdc_env(our_dom);
2033 /*********************************************************************
2034 ********************************************************************/
2036 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2040 if (!domain || !domain->alt_name || !*domain->alt_name) {
2044 if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
2045 domain->alt_name) == -1) {
2054 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2059 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2064 #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
2066 void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
2068 resp->data.auth.nt_status = NT_STATUS_V(result);
2069 fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
2071 /* we might have given a more useful error above */
2072 if (*resp->data.auth.error_string == '\0')
2073 fstrcpy(resp->data.auth.error_string,
2074 get_friendly_nt_error_msg(result));
2075 resp->data.auth.pam_error = nt_status_to_pam(result);
2078 bool is_domain_offline(const struct winbindd_domain *domain)
2080 if (get_global_winbindd_state_offline()) {
2083 return !domain->online;
2086 bool is_domain_online(const struct winbindd_domain *domain)
2088 return !is_domain_offline(domain);
2092 * Parse an char array into a list of sids.
2094 * The input sidstr should consist of 0-terminated strings
2095 * representing sids, separated by newline characters '\n'.
2096 * The list is terminated by an empty string, i.e.
2097 * character '\0' directly following a character '\n'
2098 * (or '\0' right at the start of sidstr).
2100 bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
2101 struct dom_sid **sids, uint32_t *num_sids)
2109 while (p[0] != '\0') {
2111 const char *q = NULL;
2113 if (!dom_sid_parse_endp(p, &sid, &q)) {
2114 DEBUG(1, ("Could not parse sid %s\n", p));
2118 DEBUG(1, ("Got invalid sidstr: %s\n", p));
2121 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
2131 bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
2132 struct unixid **pxids, uint32_t *pnum_xids)
2135 struct unixid *xids = NULL;
2136 uint32_t num_xids = 0;
2143 while (p[0] != '\0') {
2146 unsigned long long id;
2151 xid = (struct unixid) { .type = ID_TYPE_UID };
2154 xid = (struct unixid) { .type = ID_TYPE_GID };
2162 id = strtoull(p, &endp, 10);
2163 if ((id == ULLONG_MAX) && (errno == ERANGE)) {
2166 if (*endp != '\n') {
2172 if ((unsigned long long)xid.id != id) {
2176 tmp = talloc_realloc(mem_ctx, xids, struct unixid, num_xids+1);
2182 xids[num_xids] = xid;
2187 *pnum_xids = num_xids;