/* Authors: Fabiano FidĂȘncio Copyright (C) 2017 Red Hat This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "responder/common/cache_req/cache_req_domain.h" struct cache_req_domain * cache_req_domain_get_domain_by_name(struct cache_req_domain *domains, const char *name) { struct cache_req_domain *dom; struct cache_req_domain *ret = NULL; DLIST_FOR_EACH(dom, domains) { if (sss_domain_get_state(dom->domain) == DOM_DISABLED) { continue; } if (strcasecmp(dom->domain->name, name) == 0 || (dom->domain->flat_name != NULL && strcasecmp(dom->domain->flat_name, name) == 0)) { ret = dom; break; } } if (ret == NULL) { DEBUG(SSSDBG_OP_FAILURE, "Unknown domains [%s].\n", name); } return ret; } void cache_req_domain_list_zfree(struct cache_req_domain **cr_domains) { struct cache_req_domain *p, *q, *r; DLIST_FOR_EACH_SAFE(p, q, *cr_domains) { r = p; DLIST_REMOVE(*cr_domains, p); talloc_zfree(r); } *cr_domains = NULL; } static bool cache_req_domain_use_fqnames(struct sss_domain_info *domain, bool enforce_non_fqnames) { struct sss_domain_info *head; head = get_domains_head(domain); /* * In order to decide whether fully_qualified_names must be used on the * lookups we have to take into consideration: * - use_fully_qualified_name value of the head of the domains; * (head->fqnames) * - the presence of a domains' resolution order list; * (non_fqnames_enforced) * * The relationship between those two can be described by: * - head->fqnames: * - true: in this case doesn't matter whether it's enforced or not, * fully-qualified-names will _always_ be used * - false: in this case (which is also the default case), the usage * depends on it being enforced; * * - enforce_non_fqnames: * - true: in this case, the usage of fully-qualified-names is not * needed; * - false: in this case, the usage of fully-qualified-names will be * done accordingly to what's set for the domain itself. */ if (head->fqnames) { return true; } else if (enforce_non_fqnames) { return false; } else { return domain->fqnames; } } static struct cache_req_domain * cache_req_domain_new_list_from_string_list(TALLOC_CTX *mem_ctx, struct sss_domain_info *domains, char **resolution_order) { struct cache_req_domain *cr_domains = NULL; struct cache_req_domain *cr_domain; struct sss_domain_info *dom; char *name; int flag = SSS_GND_ALL_DOMAINS; int i; bool enforce_non_fqnames = false; errno_t ret; /* Firstly, in case a domains' resolution order is passed ... iterate over * the list adding its domains to the flatten cache req domains' list */ if (resolution_order != NULL) { enforce_non_fqnames = true; for (i = 0; resolution_order[i] != NULL; i++) { name = resolution_order[i]; for (dom = domains; dom; dom = get_next_domain(dom, flag)) { if (strcasecmp(name, dom->name) != 0) { continue; } cr_domain = talloc_zero(mem_ctx, struct cache_req_domain); if (cr_domain == NULL) { ret = ENOMEM; goto done; } cr_domain->domain = dom; cr_domain->fqnames = cache_req_domain_use_fqnames(dom, enforce_non_fqnames); /* when using the domain resolution order, using shortnames as * input is allowed by default. However, we really want to use * the fully qualified name as output in order to avoid * conflicts whith users who have the very same name. */ sss_domain_info_set_output_fqnames(cr_domain->domain, true); DLIST_ADD_END(cr_domains, cr_domain, struct cache_req_domain *); break; } } } /* Then iterate through all the other domains (and subdomains) and add them * to the flatten cache req domains' list */ for (dom = domains; dom; dom = get_next_domain(dom, flag)) { if (string_in_list(dom->name, resolution_order, false)) { continue; } cr_domain = talloc_zero(mem_ctx, struct cache_req_domain); if (cr_domain == NULL) { ret = ENOMEM; goto done; } cr_domain->domain = dom; cr_domain->fqnames = cache_req_domain_use_fqnames(dom, enforce_non_fqnames); /* when using the domain resolution order, using shortnames as input * is allowed by default. However, we really want to use the fully * qualified name as output in order to avoid conflicts whith users * who have the very same name. */ if (resolution_order != NULL) { sss_domain_info_set_output_fqnames(cr_domain->domain, true); } DLIST_ADD_END(cr_domains, cr_domain, struct cache_req_domain *); } ret = EOK; done: if (ret != EOK) { cache_req_domain_list_zfree(&cr_domains); } return cr_domains; } errno_t cache_req_domain_new_list_from_domain_resolution_order( TALLOC_CTX *mem_ctx, struct sss_domain_info *domains, const char *domain_resolution_order, struct cache_req_domain **_cr_domains) { TALLOC_CTX *tmp_ctx; struct cache_req_domain *cr_domains; char **list = NULL; errno_t ret; tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { return ENOMEM; } if (domain_resolution_order != NULL) { if (strcmp(domain_resolution_order, ":") != 0) { DEBUG(SSSDBG_TRACE_FUNC, "Domain resolution order list (split by ':'): \"%s\"\n", domain_resolution_order); ret = split_on_separator(tmp_ctx, domain_resolution_order, ':', true, true, &list, NULL); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "split_on_separator() failed [%d]: [%s].\n", ret, sss_strerror(ret)); goto done; } } else { DEBUG(SSSDBG_TRACE_FUNC, "Domain resolution order list: ':' " "(do not use any specific order)\n"); } } else { DEBUG(SSSDBG_TRACE_FUNC, "Domain resolution order list: not set\n"); } cr_domains = cache_req_domain_new_list_from_string_list(mem_ctx, domains, list); if (cr_domains == NULL) { ret = ENOMEM; DEBUG(SSSDBG_OP_FAILURE, "cache_req_domain_new_list_from_domain_resolution_order() " "failed [%d]: [%s].\n", ret, sss_strerror(ret)); goto done; } *_cr_domains = cr_domains; ret = EOK; done: talloc_free(tmp_ctx); return ret; }