2 Unix SMB/CIFS implementation.
4 Winbind daemon for ntdom nss module
6 Copyright (C) Tim Potter 2000-2001
7 Copyright (C) 2001 by Martin Pool <mbp@samba.org>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "lib/util_unixsids.h"
27 #include "../libcli/security/security.h"
28 #include "../libcli/auth/pam_errors.h"
29 #include "passdb/machine_sid.h"
31 #include "source4/lib/messaging/messaging.h"
32 #include "librpc/gen_ndr/ndr_lsa.h"
33 #include "librpc/gen_ndr/ndr_drsblobs.h"
34 #include "auth/credentials/credentials.h"
35 #include "libsmb/samlogon_cache.h"
38 #define DBGC_CLASS DBGC_WINBIND
41 * @file winbindd_util.c
43 * Winbind daemon for NT domain authentication nss module.
46 static bool add_trusted_domains_dc(void);
48 /* The list of trusted domains. Note that the list can be deleted and
49 recreated using the init_domain_list() function so pointers to
50 individual winbindd_domain structures cannot be made. Keep a copy of
51 the domain name instead. */
53 static struct winbindd_domain *_domain_list = NULL;
55 struct winbindd_domain *domain_list(void)
59 if ((!_domain_list) && (!init_domain_list())) {
60 smb_panic("Init_domain_list failed");
66 /* Free all entries in the trusted domain list */
68 static void free_domain_list(void)
70 struct winbindd_domain *domain = _domain_list;
73 struct winbindd_domain *next = domain->next;
75 DLIST_REMOVE(_domain_list, domain);
82 * Iterator for winbindd's domain list.
83 * To be used (e.g.) in tevent based loops.
85 struct winbindd_domain *wb_next_domain(struct winbindd_domain *domain)
88 domain = domain_list();
90 domain = domain->next;
93 if ((domain != NULL) &&
94 (lp_server_role() != ROLE_ACTIVE_DIRECTORY_DC) &&
95 sid_check_is_our_sam(&domain->sid))
97 domain = domain->next;
103 static bool is_internal_domain(const struct dom_sid *sid)
108 return (sid_check_is_our_sam(sid) || sid_check_is_builtin(sid));
111 /* Add a trusted domain to our list of domains.
112 If the domain already exists in the list,
113 return it and don't re-initialize. */
115 static NTSTATUS add_trusted_domain(const char *domain_name,
116 const char *dns_name,
117 const struct dom_sid *sid,
119 uint32_t trust_flags,
120 uint32_t trust_attribs,
121 enum netr_SchannelType secure_channel_type,
122 struct winbindd_domain *routing_domain,
123 struct winbindd_domain **_d)
125 struct winbindd_domain *domain = NULL;
126 const char **ignored_domains = NULL;
127 const char **dom = NULL;
128 int role = lp_server_role();
130 if (is_null_sid(sid)) {
131 DBG_ERR("Got null SID for domain [%s]\n", domain_name);
132 return NT_STATUS_INVALID_PARAMETER;
135 ignored_domains = lp_parm_string_list(-1, "winbind", "ignore domains", NULL);
136 for (dom=ignored_domains; dom && *dom; dom++) {
137 if (gen_fnmatch(*dom, domain_name) == 0) {
138 DEBUG(2,("Ignoring domain '%s'\n", domain_name));
139 return NT_STATUS_NO_SUCH_DOMAIN;
144 * We can't call domain_list() as this function is called from
145 * init_domain_list() and we'll get stuck in a loop.
147 for (domain = _domain_list; domain; domain = domain->next) {
148 if (strequal(domain_name, domain->name)) {
153 if (domain != NULL) {
154 struct winbindd_domain *check_domain = NULL;
156 for (check_domain = _domain_list;
157 check_domain != NULL;
158 check_domain = check_domain->next)
160 if (check_domain == domain) {
164 if (dom_sid_equal(&check_domain->sid, sid)) {
169 if (check_domain != NULL) {
170 DBG_ERR("SID [%s] already used by domain [%s], "
172 sid_string_dbg(sid), check_domain->name,
174 return NT_STATUS_INVALID_PARAMETER;
178 if ((domain != NULL) && (dns_name != NULL)) {
179 struct winbindd_domain *check_domain = NULL;
181 for (check_domain = _domain_list;
182 check_domain != NULL;
183 check_domain = check_domain->next)
185 if (check_domain == domain) {
189 if (strequal(check_domain->alt_name, dns_name)) {
194 if (check_domain != NULL) {
195 DBG_ERR("DNS name [%s] used by domain [%s], "
197 dns_name, check_domain->name,
199 return NT_STATUS_INVALID_PARAMETER;
203 if (domain != NULL) {
208 /* Create new domain entry */
209 domain = talloc_zero(NULL, struct winbindd_domain);
210 if (domain == NULL) {
211 return NT_STATUS_NO_MEMORY;
214 domain->children = talloc_zero_array(domain,
215 struct winbindd_child,
216 lp_winbind_max_domain_connections());
217 if (domain->children == NULL) {
219 return NT_STATUS_NO_MEMORY;
222 domain->queue = tevent_queue_create(domain, "winbind_domain");
223 if (domain->queue == NULL) {
225 return NT_STATUS_NO_MEMORY;
228 domain->binding_handle = wbint_binding_handle(domain, domain, NULL);
229 if (domain->binding_handle == NULL) {
231 return NT_STATUS_NO_MEMORY;
234 domain->name = talloc_strdup(domain, domain_name);
235 if (domain->name == NULL) {
237 return NT_STATUS_NO_MEMORY;
240 if (dns_name != NULL) {
241 domain->alt_name = talloc_strdup(domain, dns_name);
242 if (domain->alt_name == NULL) {
244 return NT_STATUS_NO_MEMORY;
248 domain->backend = NULL;
249 domain->internal = is_internal_domain(sid);
250 domain->secure_channel_type = secure_channel_type;
251 domain->sequence_number = DOM_SEQUENCE_NONE;
252 domain->last_seq_check = 0;
253 domain->initialized = false;
254 domain->online = is_internal_domain(sid);
255 domain->check_online_timeout = 0;
256 domain->dc_probe_pid = (pid_t)-1;
257 domain->domain_flags = trust_flags;
258 domain->domain_type = trust_type;
259 domain->domain_trust_attribs = trust_attribs;
260 domain->secure_channel_type = secure_channel_type;
261 domain->routing_domain = routing_domain;
262 sid_copy(&domain->sid, sid);
264 /* Is this our primary domain ? */
265 if (role == ROLE_DOMAIN_MEMBER) {
266 domain->primary = strequal(domain_name, lp_workgroup());
268 domain->primary = strequal(domain_name, get_global_sam_name());
271 if (domain->primary) {
272 if (role == ROLE_ACTIVE_DIRECTORY_DC) {
273 domain->active_directory = true;
275 if (lp_security() == SEC_ADS) {
276 domain->active_directory = true;
278 } else if (!domain->internal) {
279 if (domain->domain_type == LSA_TRUST_TYPE_UPLEVEL) {
280 domain->active_directory = true;
284 domain->can_do_ncacn_ip_tcp = domain->active_directory;
286 /* Link to domain list */
287 DLIST_ADD_END(_domain_list, domain);
289 wcache_tdc_add_domain( domain );
291 setup_domain_child(domain);
293 DBG_NOTICE("Added domain [%s] [%s] [%s]\n",
294 domain->name, domain->alt_name,
295 sid_string_dbg(&domain->sid));
301 bool set_routing_domain(struct winbindd_domain *domain,
302 struct winbindd_domain *routing_domain)
304 if (domain->routing_domain == NULL) {
305 domain->routing_domain = routing_domain;
308 if (domain->routing_domain != routing_domain) {
314 bool add_trusted_domain_from_auth(uint16_t validation_level,
315 struct info3_text *info3,
316 struct info6_text *info6)
318 struct winbindd_domain *domain = NULL;
319 struct dom_sid domain_sid;
320 const char *dns_domainname = NULL;
325 * We got a successfull auth from a domain that might not yet be in our
326 * domain list. If we're a member we trust our DC who authenticated the
327 * user from that domain and add the domain to our list on-the-fly. If
328 * we're a DC we rely on configured trusts and don't add on-the-fly.
335 ok = dom_sid_parse(info3->dom_sid, &domain_sid);
337 DBG_NOTICE("dom_sid_parse [%s] failed\n", info3->dom_sid);
341 if (validation_level == 6) {
342 if (!strequal(info6->dns_domainname, "")) {
343 dns_domainname = info6->dns_domainname;
347 status = add_trusted_domain(info3->logon_dom,
351 NETR_TRUST_FLAG_OUTBOUND,
354 find_default_route_domain(),
356 if (!NT_STATUS_IS_OK(status) &&
357 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
359 DBG_DEBUG("Adding domain [%s] with sid [%s] failed\n",
360 info3->logon_dom, info3->dom_sid);
367 bool domain_is_forest_root(const struct winbindd_domain *domain)
369 const uint32_t fr_flags =
370 (NETR_TRUST_FLAG_TREEROOT|NETR_TRUST_FLAG_IN_FOREST);
372 return ((domain->domain_flags & fr_flags) == fr_flags);
375 /********************************************************************
376 rescan our domains looking for new trusted domains
377 ********************************************************************/
379 struct trustdom_state {
380 struct winbindd_domain *domain;
381 struct winbindd_request request;
384 static void trustdom_list_done(struct tevent_req *req);
385 static void rescan_forest_root_trusts( void );
386 static void rescan_forest_trusts( void );
388 static void add_trusted_domains( struct winbindd_domain *domain )
390 struct trustdom_state *state;
391 struct tevent_req *req;
393 state = talloc_zero(NULL, struct trustdom_state);
395 DEBUG(0, ("talloc failed\n"));
398 state->domain = domain;
400 state->request.length = sizeof(state->request);
401 state->request.cmd = WINBINDD_LIST_TRUSTDOM;
403 req = wb_domain_request_send(state, global_event_context(),
404 domain, &state->request);
406 DEBUG(1, ("wb_domain_request_send failed\n"));
410 tevent_req_set_callback(req, trustdom_list_done, state);
413 static void trustdom_list_done(struct tevent_req *req)
415 struct trustdom_state *state = tevent_req_callback_data(
416 req, struct trustdom_state);
417 struct winbindd_response *response;
421 bool within_forest = false;
425 * Only when we enumerate our primary domain
426 * or our forest root domain, we should keep
427 * the NETR_TRUST_FLAG_IN_FOREST flag, in
428 * all other cases we need to clear it as the domain
429 * is not part of our forest.
431 if (state->domain->primary) {
432 within_forest = true;
433 } else if (domain_is_forest_root(state->domain)) {
434 within_forest = true;
437 res = wb_domain_request_recv(req, state, &response, &err);
438 if ((res == -1) || (response->result != WINBINDD_OK)) {
439 DBG_WARNING("Could not receive trusts for domain %s\n",
440 state->domain->name);
445 if (response->length < sizeof(struct winbindd_response)) {
446 DBG_ERR("ill-formed trustdom response - short length\n");
451 extra_len = response->length - sizeof(struct winbindd_response);
453 p = (char *)response->extra_data.data;
455 while ((p - (char *)response->extra_data.data) < extra_len) {
456 struct winbindd_domain *domain = NULL;
457 char *name, *q, *sidstr, *alt_name;
460 uint32_t trust_attribs;
461 uint32_t trust_flags;
463 DBG_DEBUG("parsing response line '%s'\n", p);
467 alt_name = strchr(p, '\\');
468 if (alt_name == NULL) {
469 DBG_ERR("Got invalid trustdom response\n");
476 sidstr = strchr(alt_name, '\\');
477 if (sidstr == NULL) {
478 DBG_ERR("Got invalid trustdom response\n");
485 /* use the real alt_name if we have one, else pass in NULL */
486 if (strequal(alt_name, "(null)")) {
490 q = strtok(sidstr, "\\");
492 DBG_ERR("Got invalid trustdom response\n");
496 if (!string_to_sid(&sid, sidstr)) {
497 DEBUG(0, ("Got invalid trustdom response\n"));
501 q = strtok(NULL, "\\");
503 DBG_ERR("Got invalid trustdom response\n");
507 trust_flags = (uint32_t)strtoul(q, NULL, 10);
509 q = strtok(NULL, "\\");
511 DBG_ERR("Got invalid trustdom response\n");
515 trust_type = (uint32_t)strtoul(q, NULL, 10);
517 q = strtok(NULL, "\n");
519 DBG_ERR("Got invalid trustdom response\n");
523 trust_attribs = (uint32_t)strtoul(q, NULL, 10);
525 if (!within_forest) {
526 trust_flags &= ~NETR_TRUST_FLAG_IN_FOREST;
529 if (!state->domain->primary) {
530 trust_flags &= ~NETR_TRUST_FLAG_PRIMARY;
534 * We always call add_trusted_domain() cause on an existing
535 * domain structure, it will update the SID if necessary.
536 * This is important because we need the SID for sibling
539 status = add_trusted_domain(name,
546 find_default_route_domain(),
548 if (!NT_STATUS_IS_OK(status) &&
549 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
551 DBG_NOTICE("add_trusted_domain returned %s\n",
556 p = q + strlen(q) + 1;
560 Cases to consider when scanning trusts:
561 (a) we are calling from a child domain (primary && !forest_root)
562 (b) we are calling from the root of the forest (primary && forest_root)
563 (c) we are calling from a trusted forest domain (!primary
567 if (state->domain->primary) {
568 /* If this is our primary domain and we are not in the
569 forest root, we have to scan the root trusts first */
571 if (!domain_is_forest_root(state->domain))
572 rescan_forest_root_trusts();
574 rescan_forest_trusts();
576 } else if (domain_is_forest_root(state->domain)) {
577 /* Once we have done root forest trust search, we can
578 go on to search the trusted forests */
580 rescan_forest_trusts();
588 /********************************************************************
589 Scan the trusts of our forest root
590 ********************************************************************/
592 static void rescan_forest_root_trusts( void )
594 struct winbindd_tdc_domain *dom_list = NULL;
595 size_t num_trusts = 0;
599 /* The only transitive trusts supported by Windows 2003 AD are
600 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
601 first two are handled in forest and listed by
602 DsEnumerateDomainTrusts(). Forest trusts are not so we
603 have to do that ourselves. */
605 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
608 for ( i=0; i<num_trusts; i++ ) {
609 struct winbindd_domain *d = NULL;
611 /* Find the forest root. Don't necessarily trust
612 the domain_list() as our primary domain may not
613 have been initialized. */
615 if ( !(dom_list[i].trust_flags & NETR_TRUST_FLAG_TREEROOT) ) {
619 /* Here's the forest root */
621 d = find_domain_from_name_noinit( dom_list[i].domain_name );
623 status = add_trusted_domain(dom_list[i].domain_name,
624 dom_list[i].dns_name,
626 dom_list[i].trust_type,
627 dom_list[i].trust_flags,
628 dom_list[i].trust_attribs,
630 find_default_route_domain(),
633 if (!NT_STATUS_IS_OK(status) &&
634 NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
636 DBG_ERR("add_trusted_domain returned %s\n",
645 DEBUG(10,("rescan_forest_root_trusts: Following trust path "
646 "for domain tree root %s (%s)\n",
647 d->name, d->alt_name ));
649 d->domain_flags = dom_list[i].trust_flags;
650 d->domain_type = dom_list[i].trust_type;
651 d->domain_trust_attribs = dom_list[i].trust_attribs;
653 add_trusted_domains( d );
658 TALLOC_FREE( dom_list );
663 /********************************************************************
664 scan the transitive forest trusts (not our own)
665 ********************************************************************/
668 static void rescan_forest_trusts( void )
670 struct winbindd_domain *d = NULL;
671 struct winbindd_tdc_domain *dom_list = NULL;
672 size_t num_trusts = 0;
676 /* The only transitive trusts supported by Windows 2003 AD are
677 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
678 first two are handled in forest and listed by
679 DsEnumerateDomainTrusts(). Forest trusts are not so we
680 have to do that ourselves. */
682 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
685 for ( i=0; i<num_trusts; i++ ) {
686 uint32_t flags = dom_list[i].trust_flags;
687 uint32_t type = dom_list[i].trust_type;
688 uint32_t attribs = dom_list[i].trust_attribs;
690 d = find_domain_from_name_noinit( dom_list[i].domain_name );
692 /* ignore our primary and internal domains */
694 if ( d && (d->internal || d->primary ) )
697 if ( (flags & NETR_TRUST_FLAG_INBOUND) &&
698 (type == LSA_TRUST_TYPE_UPLEVEL) &&
699 (attribs == LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) )
701 /* add the trusted domain if we don't know
705 status = add_trusted_domain(
706 dom_list[i].domain_name,
707 dom_list[i].dns_name,
713 find_default_route_domain(),
715 if (!NT_STATUS_IS_OK(status) &&
716 NT_STATUS_EQUAL(status,
717 NT_STATUS_NO_SUCH_DOMAIN))
719 DBG_ERR("add_trusted_domain: %s\n",
729 DEBUG(10,("Following trust path for domain %s (%s)\n",
730 d->name, d->alt_name ));
731 add_trusted_domains( d );
735 TALLOC_FREE( dom_list );
740 /*********************************************************************
741 The process of updating the trusted domain list is a three step
744 (b) ask the root domain in our forest
745 (c) ask the a DC in any Win2003 trusted forests
746 *********************************************************************/
748 void rescan_trusted_domains(struct tevent_context *ev, struct tevent_timer *te,
749 struct timeval now, void *private_data)
753 /* I use to clear the cache here and start over but that
754 caused problems in child processes that needed the
755 trust dom list early on. Removing it means we
756 could have some trusted domains listed that have been
757 removed from our primary domain's DC until a full
758 restart. This should be ok since I think this is what
759 Windows does as well. */
761 /* this will only add new domains we didn't already know about
762 in the domain_list()*/
764 add_trusted_domains( find_our_domain() );
766 te = tevent_add_timer(
767 ev, NULL, timeval_current_ofs(WINBINDD_RESCAN_FREQ, 0),
768 rescan_trusted_domains, NULL);
770 * If te == NULL, there's not much we can do here. Don't fail, the
771 * only thing we miss is new trusted domains.
777 enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domain,
778 struct winbindd_cli_state *state)
780 /* Ensure null termination */
781 state->request->domain_name
782 [sizeof(state->request->domain_name)-1]='\0';
783 state->request->data.init_conn.dcname
784 [sizeof(state->request->data.init_conn.dcname)-1]='\0';
786 if (strlen(state->request->data.init_conn.dcname) > 0) {
787 TALLOC_FREE(domain->dcname);
788 domain->dcname = talloc_strdup(domain,
789 state->request->data.init_conn.dcname);
790 if (domain->dcname == NULL) {
791 return WINBINDD_ERROR;
795 init_dc_connection(domain, false);
797 if (!domain->initialized) {
798 /* If we return error here we can't do any cached authentication,
799 but we may be in disconnected mode and can't initialize correctly.
800 Do what the previous code did and just return without initialization,
801 once we go online we'll re-initialize.
803 DEBUG(5, ("winbindd_dual_init_connection: %s returning without initialization "
804 "online = %d\n", domain->name, (int)domain->online ));
807 fstrcpy(state->response->data.domain_info.name, domain->name);
808 fstrcpy(state->response->data.domain_info.alt_name, domain->alt_name);
809 sid_to_fstring(state->response->data.domain_info.sid, &domain->sid);
811 state->response->data.domain_info.native_mode
812 = domain->native_mode;
813 state->response->data.domain_info.active_directory
814 = domain->active_directory;
815 state->response->data.domain_info.primary
821 static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
824 struct server_id server_id,
829 DBG_NOTICE("Rescanning trusted domains\n");
831 ok = add_trusted_domains_dc();
833 DBG_ERR("Failed to reload trusted domains\n");
838 * We did not get the secret when we queried secrets.tdb, so read it
839 * from secrets.tdb and re-sync the databases
841 static bool migrate_secrets_tdb_to_ldb(struct winbindd_domain *domain)
844 struct cli_credentials *creds;
845 NTSTATUS can_migrate = pdb_get_trust_credentials(domain->name,
846 NULL, domain, &creds);
847 if (!NT_STATUS_IS_OK(can_migrate)) {
848 DEBUG(0, ("Failed to fetch our own, local AD domain join "
849 "password for winbindd's internal use, both from "
850 "secrets.tdb and secrets.ldb: %s\n",
851 nt_errstr(can_migrate)));
856 * NOTE: It is very unlikely we end up here if there is an
857 * oldpass, because a new password is created at
858 * classicupgrade, so this is not a concern.
860 ok = secrets_store_machine_pw_sync(cli_credentials_get_password(creds),
862 cli_credentials_get_domain(creds),
863 cli_credentials_get_realm(creds),
864 cli_credentials_get_salt_principal(creds),
865 0, /* Supported enc types, unused */
867 cli_credentials_get_password_last_changed_time(creds),
868 cli_credentials_get_secure_channel_type(creds),
869 false /* do_delete: Do not delete */);
872 DEBUG(0, ("Failed to write our our own, "
873 "local AD domain join password for "
874 "winbindd's internal use into secrets.tdb\n"));
880 static bool add_trusted_domains_dc(void)
882 struct winbindd_domain *domain = NULL;
883 struct pdb_trusted_domain **domains = NULL;
884 uint32_t num_domains = 0;
888 if (!(pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX)) {
889 struct trustdom_info **ti = NULL;
891 status = pdb_enum_trusteddoms(talloc_tos(), &num_domains, &ti);
892 if (!NT_STATUS_IS_OK(status)) {
893 DBG_ERR("pdb_enum_trusteddoms() failed - %s\n",
898 for (i = 0; i < num_domains; i++) {
899 status = add_trusted_domain(ti[i]->name,
902 LSA_TRUST_TYPE_DOWNLEVEL,
903 NETR_TRUST_FLAG_OUTBOUND,
908 if (!NT_STATUS_IS_OK(status)) {
909 DBG_NOTICE("add_trusted_domain returned %s\n",
914 /* Even in the parent winbindd we'll need to
915 talk to the DC, so try and see if we can
916 contact it. Theoretically this isn't neccessary
917 as the init_dc_connection() in init_child_recv()
918 will do this, but we can start detecting the DC
920 set_domain_online_request(domain);
926 status = pdb_enum_trusted_domains(talloc_tos(), &num_domains, &domains);
927 if (!NT_STATUS_IS_OK(status)) {
928 DBG_ERR("pdb_enum_trusted_domains() failed - %s\n",
933 for (i = 0; i < num_domains; i++) {
934 enum netr_SchannelType sec_chan_type = SEC_CHAN_DOMAIN;
935 uint32_t trust_flags = 0;
937 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
938 sec_chan_type = SEC_CHAN_DNS_DOMAIN;
941 if (!(domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
942 sec_chan_type = SEC_CHAN_NULL;
945 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
946 trust_flags |= NETR_TRUST_FLAG_INBOUND;
948 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
949 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
951 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
952 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
955 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION) {
957 * We don't support selective authentication yet.
959 DBG_WARNING("Ignoring CROSS_ORGANIZATION trust to "
961 domains[i]->netbios_name,
962 domains[i]->domain_name);
966 status = add_trusted_domain(domains[i]->netbios_name,
967 domains[i]->domain_name,
968 &domains[i]->security_identifier,
969 domains[i]->trust_type,
971 domains[i]->trust_attributes,
975 if (!NT_STATUS_IS_OK(status)) {
976 DBG_NOTICE("add_trusted_domain returned %s\n",
981 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
982 domain->active_directory = true;
984 domain->domain_type = domains[i]->trust_type;
985 domain->domain_trust_attribs = domains[i]->trust_attributes;
987 if (sec_chan_type != SEC_CHAN_NULL) {
988 /* Even in the parent winbindd we'll need to
989 talk to the DC, so try and see if we can
990 contact it. Theoretically this isn't neccessary
991 as the init_dc_connection() in init_child_recv()
992 will do this, but we can start detecting the DC
994 set_domain_online_request(domain);
998 for (i = 0; i < num_domains; i++) {
999 struct ForestTrustInfo fti;
1001 enum ndr_err_code ndr_err;
1002 struct winbindd_domain *routing_domain = NULL;
1004 if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
1008 if (!(domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
1012 if (domains[i]->trust_forest_trust_info.length == 0) {
1016 routing_domain = find_domain_from_name_noinit(
1017 domains[i]->netbios_name);
1018 if (routing_domain == NULL) {
1019 DBG_ERR("Can't find winbindd domain [%s]\n",
1020 domains[i]->netbios_name);
1024 ndr_err = ndr_pull_struct_blob_all(
1025 &domains[i]->trust_forest_trust_info,
1027 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
1028 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1029 DBG_ERR("ndr_pull_ForestTrustInfo(%s) - %s\n",
1030 domains[i]->netbios_name,
1031 ndr_map_error2string(ndr_err));
1035 for (fi = 0; fi < fti.count; fi++) {
1036 struct ForestTrustInfoRecord *rec =
1037 &fti.records[fi].record;
1038 struct ForestTrustDataDomainInfo *drec = NULL;
1040 if (rec->type != FOREST_TRUST_DOMAIN_INFO) {
1043 drec = &rec->data.info;
1045 if (rec->flags & LSA_NB_DISABLED_MASK) {
1049 if (rec->flags & LSA_SID_DISABLED_MASK) {
1055 * also try to find a matching
1056 * LSA_TLN_DISABLED_MASK ???
1059 domain = find_domain_from_name_noinit(drec->netbios_name.string);
1060 if (domain != NULL) {
1064 status = add_trusted_domain(drec->netbios_name.string,
1065 drec->dns_name.string,
1067 LSA_TRUST_TYPE_UPLEVEL,
1068 NETR_TRUST_FLAG_OUTBOUND,
1073 if (!NT_STATUS_IS_OK(status)) {
1074 DBG_NOTICE("add_trusted_domain returned %s\n",
1078 if (domain == NULL) {
1088 /* Look up global info for the winbind daemon */
1089 bool init_domain_list(void)
1091 int role = lp_server_role();
1092 struct pdb_domain_info *pdb_domain_info = NULL;
1093 struct winbindd_domain *domain = NULL;
1097 /* Free existing list */
1100 /* BUILTIN domain */
1102 status = add_trusted_domain("BUILTIN",
1104 &global_sid_Builtin,
1105 LSA_TRUST_TYPE_DOWNLEVEL,
1106 0, /* trust_flags */
1107 0, /* trust_attribs */
1111 if (!NT_STATUS_IS_OK(status)) {
1112 DBG_ERR("add_trusted_domain BUILTIN returned %s\n",
1120 * In case the passdb backend is passdb_dsdb the domain SID comes from
1121 * dsdb, not from secrets.tdb. As we use the domain SID in various
1122 * places, we must ensure the domain SID is migrated from dsdb to
1123 * secrets.tdb before get_global_sam_sid() is called the first time.
1125 * The migration is done as part of the passdb_dsdb initialisation,
1126 * calling pdb_get_domain_info() triggers it.
1128 pdb_domain_info = pdb_get_domain_info(talloc_tos());
1130 if ( role == ROLE_ACTIVE_DIRECTORY_DC ) {
1131 uint32_t trust_flags;
1133 enum netr_SchannelType sec_chan_type;
1134 const char *account_name;
1135 struct samr_Password current_nt_hash;
1137 if (pdb_domain_info == NULL) {
1138 DEBUG(0, ("Failed to fetch our own, local AD "
1139 "domain info from sam.ldb\n"));
1143 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1144 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1145 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1146 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1148 is_root = strequal(pdb_domain_info->dns_domain,
1149 pdb_domain_info->dns_forest);
1151 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1154 status = add_trusted_domain(pdb_domain_info->name,
1155 pdb_domain_info->dns_domain,
1156 &pdb_domain_info->sid,
1157 LSA_TRUST_TYPE_UPLEVEL,
1159 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1163 TALLOC_FREE(pdb_domain_info);
1164 if (!NT_STATUS_IS_OK(status)) {
1165 DBG_ERR("Failed to add our own, local AD "
1166 "domain to winbindd's internal list\n");
1171 * We need to call this to find out if we are an RODC
1173 ok = get_trust_pw_hash(domain->name,
1174 current_nt_hash.hash,
1179 * If get_trust_pw_hash() fails, then try and
1180 * fetch the password from the more recent of
1181 * secrets.{ldb,tdb} using the
1182 * pdb_get_trust_credentials()
1184 ok = migrate_secrets_tdb_to_ldb(domain);
1187 DEBUG(0, ("Failed to migrate our own, "
1188 "local AD domain join password for "
1189 "winbindd's internal use into "
1193 ok = get_trust_pw_hash(domain->name,
1194 current_nt_hash.hash,
1198 DEBUG(0, ("Failed to find our our own, just "
1199 "written local AD domain join "
1200 "password for winbindd's internal "
1201 "use in secrets.tdb\n"));
1206 domain->secure_channel_type = sec_chan_type;
1207 if (sec_chan_type == SEC_CHAN_RODC) {
1208 domain->rodc = true;
1212 uint32_t trust_flags;
1213 enum netr_SchannelType secure_channel_type;
1215 trust_flags = NETR_TRUST_FLAG_OUTBOUND;
1216 if (role != ROLE_DOMAIN_MEMBER) {
1217 trust_flags |= NETR_TRUST_FLAG_PRIMARY;
1220 if (role > ROLE_DOMAIN_MEMBER) {
1221 secure_channel_type = SEC_CHAN_BDC;
1223 secure_channel_type = SEC_CHAN_LOCAL;
1226 status = add_trusted_domain(get_global_sam_name(),
1228 get_global_sam_sid(),
1229 LSA_TRUST_TYPE_DOWNLEVEL,
1231 0, /* trust_attribs */
1232 secure_channel_type,
1235 if (!NT_STATUS_IS_OK(status)) {
1236 DBG_ERR("Failed to add local SAM to "
1237 "domain to winbindd's internal list\n");
1243 ok = add_trusted_domains_dc();
1245 DBG_ERR("init_domain_list_dc failed\n");
1250 if ( role == ROLE_DOMAIN_MEMBER ) {
1251 struct dom_sid our_sid;
1252 uint32_t trust_type;
1254 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
1255 DEBUG(0, ("Could not fetch our SID - did we join?\n"));
1259 if (lp_realm() != NULL) {
1260 trust_type = LSA_TRUST_TYPE_UPLEVEL;
1262 trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1265 status = add_trusted_domain(lp_workgroup(),
1269 NETR_TRUST_FLAG_PRIMARY|
1270 NETR_TRUST_FLAG_OUTBOUND,
1271 0, /* trust_attribs */
1275 if (!NT_STATUS_IS_OK(status)) {
1276 DBG_ERR("Failed to add local SAM to "
1277 "domain to winbindd's internal list\n");
1280 /* Even in the parent winbindd we'll need to
1281 talk to the DC, so try and see if we can
1282 contact it. Theoretically this isn't neccessary
1283 as the init_dc_connection() in init_child_recv()
1284 will do this, but we can start detecting the DC
1286 set_domain_online_request(domain);
1290 status = imessaging_register(winbind_imessaging_context(), NULL,
1291 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1292 wb_imsg_new_trusted_domain);
1293 if (!NT_STATUS_IS_OK(status)) {
1294 DBG_ERR("imessaging_register failed %s\n", nt_errstr(status));
1302 * Given a domain name, return the struct winbindd domain info for it
1304 * @note Do *not* pass lp_workgroup() to this function. domain_list
1305 * may modify it's value, and free that pointer. Instead, our local
1306 * domain may be found by calling find_our_domain().
1310 * @return The domain structure for the named domain, if it is working.
1313 struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
1315 struct winbindd_domain *domain;
1317 /* Search through list */
1319 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1320 if (strequal(domain_name, domain->name)) {
1323 if (domain->alt_name == NULL) {
1326 if (strequal(domain_name, domain->alt_name)) {
1337 * Given a domain name, return the struct winbindd domain if it's a direct
1340 * @return The domain structure for the named domain, if it is a direct outgoing trust
1342 struct winbindd_domain *find_trust_from_name_noinit(const char *domain_name)
1344 struct winbindd_domain *domain = NULL;
1346 domain = find_domain_from_name_noinit(domain_name);
1347 if (domain == NULL) {
1351 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1358 struct winbindd_domain *find_domain_from_name(const char *domain_name)
1360 struct winbindd_domain *domain;
1362 domain = find_domain_from_name_noinit(domain_name);
1367 if (!domain->initialized)
1368 init_dc_connection(domain, false);
1373 /* Given a domain sid, return the struct winbindd domain info for it */
1375 struct winbindd_domain *find_domain_from_sid_noinit(const struct dom_sid *sid)
1377 struct winbindd_domain *domain;
1379 /* Search through list */
1381 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1382 if (dom_sid_compare_domain(sid, &domain->sid) == 0)
1392 * Given a domain sid, return the struct winbindd domain if it's a direct
1395 * @return The domain structure for the specified domain, if it is a direct outgoing trust
1397 struct winbindd_domain *find_trust_from_sid_noinit(const struct dom_sid *sid)
1399 struct winbindd_domain *domain = NULL;
1401 domain = find_domain_from_sid_noinit(sid);
1402 if (domain == NULL) {
1406 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1413 /* Given a domain sid, return the struct winbindd domain info for it */
1415 struct winbindd_domain *find_domain_from_sid(const struct dom_sid *sid)
1417 struct winbindd_domain *domain;
1419 domain = find_domain_from_sid_noinit(sid);
1424 if (!domain->initialized)
1425 init_dc_connection(domain, false);
1430 struct winbindd_domain *find_our_domain(void)
1432 struct winbindd_domain *domain;
1434 /* Search through list */
1436 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1437 if (domain->primary)
1441 smb_panic("Could not find our domain");
1445 struct winbindd_domain *find_default_route_domain(void)
1448 return find_our_domain();
1450 DBG_DEBUG("Routing logic not yet implemented on a DC\n");
1454 /* Find the appropriate domain to lookup a name or SID */
1456 struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)
1458 DBG_DEBUG("SID [%s]\n", sid_string_dbg(sid));
1461 * SIDs in the S-1-22-{1,2} domain and well-known SIDs should be handled
1465 if ( sid_check_is_in_unix_groups(sid) ||
1466 sid_check_is_unix_groups(sid) ||
1467 sid_check_is_in_unix_users(sid) ||
1468 sid_check_is_unix_users(sid) ||
1469 sid_check_is_our_sam(sid) ||
1470 sid_check_is_in_our_sam(sid) )
1472 return find_domain_from_sid(get_global_sam_sid());
1475 if ( sid_check_is_builtin(sid) ||
1476 sid_check_is_in_builtin(sid) ||
1477 sid_check_is_wellknown_domain(sid, NULL) ||
1478 sid_check_is_in_wellknown_domain(sid) )
1480 return find_domain_from_sid(&global_sid_Builtin);
1484 struct winbindd_domain *domain = NULL;
1486 domain = find_domain_from_sid_noinit(sid);
1487 if (domain == NULL) {
1491 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1495 return domain->routing_domain;
1498 /* On a member server a query for SID or name can always go to our
1501 DEBUG(10, ("calling find_our_domain\n"));
1502 return find_our_domain();
1505 struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
1507 if ( strequal(domain_name, unix_users_domain_name() ) ||
1508 strequal(domain_name, unix_groups_domain_name() ) )
1511 * The "Unix User" and "Unix Group" domain our handled by
1514 return find_domain_from_name_noinit( get_global_sam_name() );
1517 if (strequal(domain_name, "BUILTIN") ||
1518 strequal(domain_name, get_global_sam_name())) {
1519 return find_domain_from_name_noinit(domain_name);
1523 struct winbindd_domain *domain = NULL;
1525 domain = find_domain_from_name_noinit(domain_name);
1526 if (domain == NULL) {
1530 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1534 return domain->routing_domain;
1537 return find_our_domain();
1540 /* Is this a domain which we may assume no DOMAIN\ prefix? */
1542 static bool assume_domain(const char *domain)
1544 /* never assume the domain on a standalone server */
1546 if ( lp_server_role() == ROLE_STANDALONE )
1549 /* domain member servers may possibly assume for the domain name */
1551 if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
1552 if ( !strequal(lp_workgroup(), domain) )
1555 if ( lp_winbind_use_default_domain() )
1559 /* only left with a domain controller */
1561 if ( strequal(get_global_sam_name(), domain) ) {
1568 /* Parse a DOMAIN\user or UPN string into a domain, namespace and a user */
1569 bool parse_domain_user(const char *domuser,
1576 if (strlen(domuser) == 0) {
1580 p = strchr(domuser, *lp_winbind_separator());
1582 fstrcpy(user, p + 1);
1583 fstrcpy(domain, domuser);
1584 domain[PTR_DIFF(p, domuser)] = '\0';
1585 fstrcpy(namespace, domain);
1587 fstrcpy(user, domuser);
1590 namespace[0] = '\0';
1591 p = strchr(domuser, '@');
1594 fstrcpy(namespace, p + 1);
1595 } else if (assume_domain(lp_workgroup())) {
1596 fstrcpy(domain, lp_workgroup());
1597 fstrcpy(namespace, domain);
1599 fstrcpy(namespace, lp_netbios_name());
1603 return strupper_m(domain);
1606 /* Ensure an incoming username from NSS is fully qualified. Replace the
1607 incoming fstring with DOMAIN <separator> user. Returns the same
1608 values as parse_domain_user() but also replaces the incoming username.
1609 Used to ensure all names are fully qualified within winbindd.
1610 Used by the NSS protocols of auth, chauthtok, logoff and ccache_ntlm_auth.
1611 The protocol definitions of auth_crap, chng_pswd_auth_crap
1612 really should be changed to use this instead of doing things
1615 bool canonicalize_username(fstring username_inout,
1622 ok = parse_domain_user(username_inout, namespace, domain, user);
1626 slprintf(username_inout, sizeof(fstring) - 1, "%s%c%s",
1627 domain, *lp_winbind_separator(),
1633 Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
1634 'winbind separator' options.
1636 - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
1639 If we are a PDC or BDC, and this is for our domain, do likewise.
1641 On an AD DC we always fill DOMAIN\\USERNAME.
1643 We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1646 * talloc version of fill_domain_username()
1647 * return NULL on talloc failure.
1649 char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
1654 char *tmp_user, *name;
1656 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1660 tmp_user = talloc_strdup(mem_ctx, user);
1661 if (!strlower_m(tmp_user)) {
1662 TALLOC_FREE(tmp_user);
1666 if (can_assume && assume_domain(domain)) {
1669 name = talloc_asprintf(mem_ctx, "%s%c%s",
1671 *lp_winbind_separator(),
1673 TALLOC_FREE(tmp_user);
1680 * Client list accessor functions
1683 static struct winbindd_cli_state *_client_list;
1684 static int _num_clients;
1686 /* Return list of all connected clients */
1688 struct winbindd_cli_state *winbindd_client_list(void)
1690 return _client_list;
1693 /* Return list-tail of all connected clients */
1695 struct winbindd_cli_state *winbindd_client_list_tail(void)
1697 return DLIST_TAIL(_client_list);
1700 /* Return previous (read:newer) client in list */
1702 struct winbindd_cli_state *
1703 winbindd_client_list_prev(struct winbindd_cli_state *cli)
1705 return DLIST_PREV(cli);
1708 /* Add a connection to the list */
1710 void winbindd_add_client(struct winbindd_cli_state *cli)
1712 cli->last_access = time(NULL);
1713 DLIST_ADD(_client_list, cli);
1717 /* Remove a client from the list */
1719 void winbindd_remove_client(struct winbindd_cli_state *cli)
1721 DLIST_REMOVE(_client_list, cli);
1725 /* Move a client to head or list */
1727 void winbindd_promote_client(struct winbindd_cli_state *cli)
1729 cli->last_access = time(NULL);
1730 DLIST_PROMOTE(_client_list, cli);
1733 /* Return number of open clients */
1735 int winbindd_num_clients(void)
1737 return _num_clients;
1740 NTSTATUS lookup_usergroups_cached(TALLOC_CTX *mem_ctx,
1741 const struct dom_sid *user_sid,
1742 uint32_t *p_num_groups, struct dom_sid **user_sids)
1744 struct netr_SamInfo3 *info3 = NULL;
1745 NTSTATUS status = NT_STATUS_NO_MEMORY;
1746 uint32_t num_groups = 0;
1748 DEBUG(3,(": lookup_usergroups_cached\n"));
1753 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1755 if (info3 == NULL) {
1756 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1760 * Before bug #7843 the "Domain Local" groups were added with a
1761 * lookupuseraliases call, but this isn't done anymore for our domain
1762 * so we need to resolve resource groups here.
1764 * When to use Resource Groups:
1765 * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
1767 status = sid_array_from_info3(mem_ctx, info3,
1772 if (!NT_STATUS_IS_OK(status)) {
1778 *p_num_groups = num_groups;
1779 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1781 DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1786 /*********************************************************************
1787 We use this to remove spaces from user and group names
1788 ********************************************************************/
1790 NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
1791 const char *domain_name,
1795 struct winbindd_domain *domain = NULL;
1798 if (!name || !normalized) {
1799 return NT_STATUS_INVALID_PARAMETER;
1802 if (!lp_winbind_normalize_names()) {
1803 return NT_STATUS_PROCEDURE_NOT_FOUND;
1806 domain = find_domain_from_name_noinit(domain_name);
1807 if (domain == NULL) {
1808 DBG_ERR("Failed to find domain '%s'\n", domain_name);
1809 return NT_STATUS_NO_SUCH_DOMAIN;
1812 /* Alias support and whitespace replacement are mutually
1815 nt_status = resolve_username_to_alias(mem_ctx, domain,
1817 if (NT_STATUS_IS_OK(nt_status)) {
1818 /* special return code to let the caller know we
1819 mapped to an alias */
1820 return NT_STATUS_FILE_RENAMED;
1823 /* check for an unreachable domain */
1825 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1826 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1828 set_domain_offline(domain);
1832 /* deal with whitespace */
1834 *normalized = talloc_strdup(mem_ctx, name);
1835 if (!(*normalized)) {
1836 return NT_STATUS_NO_MEMORY;
1839 all_string_sub( *normalized, " ", "_", 0 );
1841 return NT_STATUS_OK;
1844 /*********************************************************************
1845 We use this to do the inverse of normalize_name_map()
1846 ********************************************************************/
1848 NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
1853 struct winbindd_domain *domain = find_our_domain();
1855 if (!name || !normalized) {
1856 return NT_STATUS_INVALID_PARAMETER;
1859 if (!lp_winbind_normalize_names()) {
1860 return NT_STATUS_PROCEDURE_NOT_FOUND;
1863 /* Alias support and whitespace replacement are mutally
1866 /* When mapping from an alias to a username, we don't know the
1867 domain. But we only need a domain structure to cache
1868 a successful lookup , so just our own domain structure for
1871 nt_status = resolve_alias_to_username(mem_ctx, domain,
1873 if (NT_STATUS_IS_OK(nt_status)) {
1874 /* Special return code to let the caller know we mapped
1876 return NT_STATUS_FILE_RENAMED;
1879 /* check for an unreachable domain */
1881 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1882 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1884 set_domain_offline(domain);
1888 /* deal with whitespace */
1890 *normalized = talloc_strdup(mem_ctx, name);
1891 if (!(*normalized)) {
1892 return NT_STATUS_NO_MEMORY;
1895 all_string_sub(*normalized, "_", " ", 0);
1897 return NT_STATUS_OK;
1900 /*********************************************************************
1901 ********************************************************************/
1903 bool winbindd_can_contact_domain(struct winbindd_domain *domain)
1905 struct winbindd_tdc_domain *tdc = NULL;
1906 TALLOC_CTX *frame = talloc_stackframe();
1909 /* We can contact the domain if it is our primary domain */
1911 if (domain->primary) {
1916 /* Trust the TDC cache and not the winbindd_domain flags */
1918 if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
1919 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
1925 /* Can always contact a domain that is in out forest */
1927 if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1933 * On a _member_ server, we cannot contact the domain if it
1934 * is running AD and we have no inbound trust.
1938 domain->active_directory &&
1939 ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
1941 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
1942 "and we have no inbound trust.\n", domain->name));
1946 /* Assume everything else is ok (probably not true but what
1952 talloc_destroy(frame);
1957 #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
1959 /*********************************************************************
1960 ********************************************************************/
1962 static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
1965 char addr[INET6_ADDRSTRLEN];
1966 const char *kdc = NULL;
1969 if (!domain || !domain->alt_name || !*domain->alt_name) {
1973 if (domain->initialized && !domain->active_directory) {
1974 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
1979 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
1982 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
1984 kdc = domain->dcname;
1987 if (!kdc || !*kdc) {
1988 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
1993 if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
1994 domain->alt_name) == -1) {
1998 DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
2001 setenv(var, kdc, 1);
2005 /*********************************************************************
2006 ********************************************************************/
2008 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2010 struct winbindd_domain *our_dom = find_our_domain();
2012 winbindd_set_locator_kdc_env(domain);
2014 if (domain != our_dom) {
2015 winbindd_set_locator_kdc_env(our_dom);
2019 /*********************************************************************
2020 ********************************************************************/
2022 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2026 if (!domain || !domain->alt_name || !*domain->alt_name) {
2030 if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
2031 domain->alt_name) == -1) {
2040 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2045 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2050 #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
2052 void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
2054 resp->data.auth.nt_status = NT_STATUS_V(result);
2055 fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
2057 /* we might have given a more useful error above */
2058 if (*resp->data.auth.error_string == '\0')
2059 fstrcpy(resp->data.auth.error_string,
2060 get_friendly_nt_error_msg(result));
2061 resp->data.auth.pam_error = nt_status_to_pam(result);
2064 bool is_domain_offline(const struct winbindd_domain *domain)
2066 if (get_global_winbindd_state_offline()) {
2069 return !domain->online;
2072 bool is_domain_online(const struct winbindd_domain *domain)
2074 return !is_domain_offline(domain);
2078 * Parse an char array into a list of sids.
2080 * The input sidstr should consist of 0-terminated strings
2081 * representing sids, separated by newline characters '\n'.
2082 * The list is terminated by an empty string, i.e.
2083 * character '\0' directly following a character '\n'
2084 * (or '\0' right at the start of sidstr).
2086 bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
2087 struct dom_sid **sids, uint32_t *num_sids)
2095 while (p[0] != '\0') {
2097 const char *q = NULL;
2099 if (!dom_sid_parse_endp(p, &sid, &q)) {
2100 DEBUG(1, ("Could not parse sid %s\n", p));
2104 DEBUG(1, ("Got invalid sidstr: %s\n", p));
2107 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
2117 bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
2118 struct unixid **pxids, uint32_t *pnum_xids)
2121 struct unixid *xids = NULL;
2122 uint32_t num_xids = 0;
2129 while (p[0] != '\0') {
2132 unsigned long long id;
2137 xid = (struct unixid) { .type = ID_TYPE_UID };
2140 xid = (struct unixid) { .type = ID_TYPE_GID };
2148 id = strtoull(p, &endp, 10);
2149 if ((id == ULLONG_MAX) && (errno == ERANGE)) {
2152 if (*endp != '\n') {
2158 if ((unsigned long long)xid.id != id) {
2162 tmp = talloc_realloc(mem_ctx, xids, struct unixid, num_xids+1);
2168 xids[num_xids] = xid;
2173 *pnum_xids = num_xids;