/* SSSD IPA Backend Module -- configuration retrieval Authors: Jan Zeleny Copyright (C) 2012 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 "providers/ipa/ipa_config.h" #include "providers/ipa/ipa_common.h" #include "providers/ldap/sdap_async.h" struct ipa_get_config_state { char *base; const char **attrs; struct sysdb_attrs *config; struct sysdb_attrs *certmap_config; struct sysdb_attrs **certmap_rules; }; static void ipa_get_config_done(struct tevent_req *subreq); struct tevent_req * ipa_get_config_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sdap_handle *sh, struct sdap_options *opts, const char *domain, const char **attrs) { struct tevent_req *req; struct tevent_req *subreq; struct ipa_get_config_state *state; errno_t ret; char *ldap_basedn; const char *def_attrs[] = { OBJECTCLASS, IPA_CONFIG_MIGRATION_ENABLED, IPA_CONFIG_SELINUX_DEFAULT_USER_CTX, IPA_CONFIG_SELINUX_MAP_ORDER, IPA_CERTMAP_PROMPT_USERNAME, IPA_CERTMAP_PRIORITY, IPA_CERTMAP_MATCHRULE, IPA_CERTMAP_MAPRULE, IPA_ASSOCIATED_DOMAIN, IPA_ENABLED_FLAG, NULL}; req = tevent_req_create(mem_ctx, &state, struct ipa_get_config_state); if (req == NULL) { return NULL; } state->config = NULL; state->certmap_config = NULL; state->certmap_rules = NULL; if (attrs == NULL) { state->attrs = def_attrs; } else { state->attrs = attrs; } ret = domain_to_basedn(state, domain, &ldap_basedn); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "domain_to_basedn failed.\n"); goto done; } state->base = talloc_asprintf(state, IPA_CONFIG_SEARCH_BASE_TEMPLATE, ldap_basedn); if (state->base == NULL) { DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); ret = ENOMEM; goto done; } subreq = sdap_get_generic_send(state, ev, opts, sh, state->base, LDAP_SCOPE_SUBTREE, IPA_CONFIG_FILTER, state->attrs, NULL, 0, dp_opt_get_int(opts->basic, SDAP_ENUM_SEARCH_TIMEOUT), false); if (subreq == NULL) { ret = ENOMEM; goto done; } tevent_req_set_callback(subreq, ipa_get_config_done, req); ret = EOK; done: if (ret != EOK) { tevent_req_error(req, ret); tevent_req_post(req, ev); } return req; } static void ipa_get_config_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); struct ipa_get_config_state *state = tevent_req_data(req, struct ipa_get_config_state); size_t reply_count; struct sysdb_attrs **reply = NULL; errno_t ret; size_t c; size_t d; size_t r; const char **ocs; ret = sdap_get_generic_recv(subreq, state, &reply_count, &reply); talloc_zfree(subreq); if (ret) { goto done; } if (reply_count == 0) { DEBUG(SSSDBG_OP_FAILURE, "Missing IPA config options.\n"); ret = EINVAL; goto done; } for (c = 0; c < reply_count; c++) { ret = sysdb_attrs_get_string_array(reply[c], SYSDB_OBJECTCLASS, state, &ocs); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Missing objectclasses for config objects.\n"); ret = EINVAL; goto done; } for (d = 0; ocs[d] != NULL; d++) { if (strcasecmp(ocs[d], IPA_OC_CONFIG) == 0) { if (state->config == NULL) { state->config = reply[c]; } else { DEBUG(SSSDBG_CRIT_FAILURE, "Found more than 1 ipaConfig object.\n"); ret = EINVAL; goto done; } } else if (strcasecmp(ocs[d], IPA_OC_CERTMAP_CONFIG_OBJECT) == 0) { if (state->certmap_config == NULL) { state->certmap_config = reply[c]; } else { DEBUG(SSSDBG_CRIT_FAILURE, "Found more than 1 ipaCertMapConfigObject object.\n"); ret = EINVAL; goto done; } } else if (strcasecmp(ocs[d], IPA_OC_CERTMAP_RULE) == 0) { if (state->certmap_rules == NULL) { state->certmap_rules = talloc_zero_array(state, struct sysdb_attrs *, reply_count + 1); if (state->certmap_rules == NULL) { DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_array failed.\n"); ret = ENOMEM; goto done; } r = 0; } state->certmap_rules[r] = reply[c]; r++; } else { DEBUG(SSSDBG_TRACE_INTERNAL, "Ignoring objectclass [%s].\n", ocs[d]); } } } if (state->config == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "No ipaConfig object found.\n"); ret = EINVAL; goto done; } ret = EOK; done: if (ret != EOK) { tevent_req_error(req, ret); } else { tevent_req_done(req); } } errno_t ipa_get_config_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct sysdb_attrs **config, struct sysdb_attrs **certmap_config, struct sysdb_attrs ***certmap_rules) { struct ipa_get_config_state *state = tevent_req_data(req, struct ipa_get_config_state); TEVENT_REQ_RETURN_ON_ERROR(req); *config = talloc_steal(mem_ctx, state->config); if (certmap_config != NULL) { *certmap_config = talloc_steal(mem_ctx, state->certmap_config); } if (certmap_rules != NULL) { *certmap_rules = talloc_steal(mem_ctx, state->certmap_rules); } return EOK; }