From 386a66b1aa18a176e6a06fa126556c9590c373b6 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Thu, 14 Jun 2012 10:18:44 +0200 Subject: Add support for ID ranges --- src/config/SSSDConfig/__init__.py.in | 1 + src/config/etc/sssd.api.d/sssd-ipa.conf | 1 + src/db/sysdb.h | 39 ++++ src/db/sysdb_ranges.c | 345 ++++++++++++++++++++++++++++++++ src/providers/ipa/ipa_common.c | 26 +++ src/providers/ipa/ipa_common.h | 2 + src/providers/ipa/ipa_init.c | 1 + src/providers/ipa/ipa_opts.h | 1 + src/providers/ipa/ipa_subdomains.c | 176 +++++++++++++++- src/providers/ipa/ipa_subdomains.h | 1 + 10 files changed, 583 insertions(+), 10 deletions(-) create mode 100644 src/db/sysdb_ranges.c (limited to 'src') diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in index b90f505d1..23784fdc0 100644 --- a/src/config/SSSDConfig/__init__.py.in +++ b/src/config/SSSDConfig/__init__.py.in @@ -131,6 +131,7 @@ option_strings = { 'ipa_hbac_support_srchost' : _("If set to false, host argument given by PAM will be ignored"), 'ipa_automount_location' : _("The automounter location this IPA client is using"), 'ipa_master_domain_search_base': _("Search base for object containing info about IPA domain"), + 'ipa_ranges_search_base': _("Search base for objects containing info about ID ranges"), # [provider/krb5] 'krb5_kdcip' : _('Kerberos server address'), diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf index 24f3c6885..27573cbfe 100644 --- a/src/config/etc/sssd.api.d/sssd-ipa.conf +++ b/src/config/etc/sssd.api.d/sssd-ipa.conf @@ -8,6 +8,7 @@ ipa_hbac_search_base = str, None, false ipa_host_search_base = str, None, false ipa_subdomains_search_base = str, None, false ipa_master_domain_search_base = str, None, false +ipa_ranges_search_base = str, None, false ldap_uri = str, None, false ldap_search_base = str, None, false ldap_schema = str, None, false diff --git a/src/db/sysdb.h b/src/db/sysdb.h index 5867b19c1..f0ff6f5a8 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -36,12 +36,15 @@ #define SYSDB_GROUPS_CONTAINER "cn=groups" #define SYSDB_CUSTOM_CONTAINER "cn=custom" #define SYSDB_NETGROUP_CONTAINER "cn=Netgroups" +#define SYSDB_RANGE_CONTAINER "cn=ranges" #define SYSDB_TMPL_USER_BASE SYSDB_USERS_CONTAINER",cn=%s,"SYSDB_BASE #define SYSDB_TMPL_GROUP_BASE SYSDB_GROUPS_CONTAINER",cn=%s,"SYSDB_BASE #define SYSDB_TMPL_CUSTOM_BASE SYSDB_CUSTOM_CONTAINER",cn=%s,"SYSDB_BASE #define SYSDB_TMPL_NETGROUP_BASE SYSDB_NETGROUP_CONTAINER",cn=%s,"SYSDB_BASE +#define SYSDB_TMPL_RANGE_BASE SYSDB_RANGE_CONTAINER",cn=%s,"SYSDB_BASE #define SYSDB_SUBDOMAIN_CLASS "subdomain" +#define SYSDB_RANGE_CLASS "idrange" #define SYSDB_USER_CLASS "user" #define SYSDB_GROUP_CLASS "group" #define SYSDB_NETGROUP_CLASS "netgroup" @@ -49,6 +52,19 @@ #define SYSDB_HOSTGROUP_CLASS "hostgroup" #define SYSDB_SELINUX_USERMAP_CLASS "selinuxusermap" #define SYSDB_SELINUX_CLASS "selinux" +#define SYSDB_ID_RANGE_CLASS "idRange" +#define SYSDB_DOMAIN_ID_RANGE_CLASS "domainIDRange" +#define SYSDB_TRUSTED_AD_DOMAIN_RANGE_CLASS "TrustedADDomainRange" + +#define SYSDB_NAME "name" +#define SYSDB_NAME_ALIAS "nameAlias" +#define SYSDB_OBJECTCLASS "objectClass" + +#define SYSDB_NEXTID "nextID" +#define SYSDB_UIDNUM "uidNumber" +#define SYSDB_GIDNUM "gidNumber" +#define SYSDB_CREATE_TIME "createTimestamp" + #define SYSDB_NAME "name" #define SYSDB_NAME_ALIAS "nameAlias" @@ -128,6 +144,12 @@ #define SYSDB_SUBDOMAIN_FLAT "flatName" #define SYSDB_SUBDOMAIN_ID "domainID" +#define SYSDB_BASE_ID "baseID" +#define SYSDB_ID_RANGE_SIZE "idRangeSize" +#define SYSDB_BASE_RID "baseRID" +#define SYSDB_SECONDARY_BASE_RID "secondaryBaseRID" +#define SYSDB_DOMAIN_ID "domainID" + #define SYSDB_NEXTID_FILTER "("SYSDB_NEXTID"=*)" #define SYSDB_UC "objectclass="SYSDB_USER_CLASS @@ -193,6 +215,7 @@ #define SYSDB_TMPL_NETGROUP SYSDB_NAME"=%s,"SYSDB_TMPL_NETGROUP_BASE #define SYSDB_TMPL_CUSTOM_SUBTREE "cn=%s,"SYSDB_TMPL_CUSTOM_BASE #define SYSDB_TMPL_CUSTOM SYSDB_NAME"=%s,cn=%s,"SYSDB_TMPL_CUSTOM_BASE +#define SYSDB_TMPL_RANGE SYSDB_NAME"=%s,"SYSDB_TMPL_RANGE_BASE #define SYSDB_MOD_ADD LDB_FLAG_MOD_ADD #define SYSDB_MOD_DEL LDB_FLAG_MOD_DELETE @@ -222,6 +245,15 @@ struct subdomain_info { char *id; }; +struct range_info { + char *name; + uint32_t base_id; + uint32_t id_range_size; + uint32_t base_rid; + uint32_t secondary_base_rid; + char *trusted_dom_sid; +}; + /* values are copied in the structure, allocated on "attrs" */ int sysdb_attrs_add_val(struct sysdb_attrs *attrs, @@ -392,6 +424,13 @@ errno_t sysdb_store_domgroup(struct sss_domain_info *domain, errno_t sysdb_delete_domgroup(struct sss_domain_info *domain, const char *name, gid_t gid); +errno_t sysdb_get_ranges(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, + size_t *range_count, + struct range_info ***range_list); +errno_t sysdb_range_create(struct sysdb_ctx *sysdb, struct range_info *range); +errno_t sysdb_update_ranges(struct sysdb_ctx *sysdb, + struct range_info **ranges); + /* Sysdb initialization. * call this function *only* once to initialize the database and get * the sysdb ctx */ diff --git a/src/db/sysdb_ranges.c b/src/db/sysdb_ranges.c new file mode 100644 index 000000000..99518a28f --- /dev/null +++ b/src/db/sysdb_ranges.c @@ -0,0 +1,345 @@ +/* + SSSD + + System Database - ID ranges related calls + + Copyright (C) 2012 Sumit Bose + + 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 "util/util.h" +#include "db/sysdb_private.h" + +static errno_t find_attr_as_uint32_t(const struct ldb_message *msg, + const char *attr_name, uint32_t *result) +{ + uint64_t val; + + val = ldb_msg_find_attr_as_uint64(msg, attr_name, UINT64_MAX); + + if (val == UINT64_MAX) { + return ENOENT; + } else if (val >= UINT32_MAX) { + return EINVAL; + } + + *result = val; + return EOK; +} + +errno_t sysdb_get_ranges(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, + size_t *range_count, + struct range_info ***range_list) +{ + size_t c; + errno_t ret; + TALLOC_CTX *tmp_ctx; + struct ldb_result *res; + const char *attrs[] = {SYSDB_NAME, + SYSDB_BASE_ID, + SYSDB_ID_RANGE_SIZE, + SYSDB_BASE_RID, + SYSDB_SECONDARY_BASE_RID, + SYSDB_DOMAIN_ID, + NULL}; + struct range_info **list; + struct ldb_dn *basedn; + const char *tmp_str; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + ret = ENOMEM; + goto done; + } + + basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_RANGE_BASE, + sysdb->domain->name); + if (basedn == NULL) { + ret = EIO; + goto done; + } + ret = ldb_search(sysdb->ldb, tmp_ctx, &res, + basedn, LDB_SCOPE_ONELEVEL, + attrs, "objectclass=%s", SYSDB_RANGE_CLASS); + if (ret != LDB_SUCCESS) { + ret = EIO; + goto done; + } + + list = talloc_zero_array(tmp_ctx, struct range_info *, res->count); + if (list == NULL) { + ret = ENOMEM; + goto done; + } + + for (c = 0; c < res->count; c++) { + list[c] = talloc_zero(list, struct range_info); + if (list[c] == NULL) { + ret = ENOMEM; + goto done; + } + tmp_str = ldb_msg_find_attr_as_string(res->msgs[c], SYSDB_NAME, NULL); + if (tmp_str == NULL) { + DEBUG(SSSDBG_MINOR_FAILURE, ("The object [%s] doesn't have a name.\n", + ldb_dn_get_linearized(res->msgs[c]->dn))); + ret = EINVAL; + goto done; + } + + list[c]->name = talloc_strdup(list, tmp_str); + if (list[c]->name == NULL) { + ret = ENOMEM; + goto done; + } + + tmp_str = ldb_msg_find_attr_as_string(res->msgs[c], SYSDB_DOMAIN_ID, + NULL); + if (tmp_str != NULL) { + list[c]->trusted_dom_sid = talloc_strdup(list, tmp_str); + if (list[c]->trusted_dom_sid == NULL) { + ret = ENOMEM; + goto done; + } + } + + ret = find_attr_as_uint32_t(res->msgs[c], SYSDB_BASE_ID, + &list[c]->base_id); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_MINOR_FAILURE, ("find_attr_as_uint32_t failed.\n")); + goto done; + } + + ret = find_attr_as_uint32_t(res->msgs[c], SYSDB_ID_RANGE_SIZE, + &list[c]->id_range_size); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_MINOR_FAILURE, ("find_attr_as_uint32_t failed.\n")); + goto done; + } + + ret = find_attr_as_uint32_t(res->msgs[c], SYSDB_BASE_RID, + &list[c]->base_rid); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_MINOR_FAILURE, ("find_attr_as_uint32_t failed.\n")); + goto done; + } + + ret = find_attr_as_uint32_t(res->msgs[c], SYSDB_SECONDARY_BASE_RID, + &list[c]->secondary_base_rid); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_MINOR_FAILURE, ("find_attr_as_uint32_t failed.\n")); + goto done; + } + } + + *range_count = res->count; + *range_list = talloc_steal(mem_ctx, list); + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +errno_t sysdb_range_create(struct sysdb_ctx *sysdb, struct range_info *range) +{ + struct ldb_message *msg; + int ret; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + msg = ldb_msg_new(tmp_ctx); + if (!msg) { + ret = ENOMEM; + goto done; + } + + msg->dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_RANGE, + range->name, sysdb->domain->name); + if (!msg->dn) { + ret = ENOMEM; + goto done; + } + + ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_OBJECTCLASS, + SYSDB_ID_RANGE_CLASS); + if (ret) goto done; + + if (range->trusted_dom_sid == NULL && range->secondary_base_rid != 0) { + ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_OBJECTCLASS, + SYSDB_DOMAIN_ID_RANGE_CLASS); + if (ret) goto done; + + ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_SECONDARY_BASE_RID, + (unsigned long) range->secondary_base_rid); + if (ret) goto done; + } else if (range->trusted_dom_sid != NULL && + range->secondary_base_rid == 0) { + ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_OBJECTCLASS, + SYSDB_TRUSTED_AD_DOMAIN_RANGE_CLASS); + if (ret) goto done; + + ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_DOMAIN_ID, + range->trusted_dom_sid); + if (ret) goto done; + } else { + DEBUG(SSSDBG_OP_FAILURE, ("Invalid range, expected that either " + "the secondary base rid or the SID of the " + "trusted domain is set, but not both or " + "none of them.\n")); + ret = EINVAL; + goto done; + } + + ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, range->name); + if (ret) goto done; + + ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_BASE_ID, + (unsigned long) range->base_id); + if (ret) goto done; + + ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_ID_RANGE_SIZE, + (unsigned long) range->id_range_size); + if (ret) goto done; + + ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_BASE_RID, + (unsigned long) range->base_rid); + if (ret) goto done; + + ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME, + (unsigned long)time(NULL)); + if (ret) goto done; + + ret = ldb_add(sysdb->ldb, msg); + if (ret) goto done; + + ret = sysdb_error_to_errno(ret); + +done: + if (ret) { + DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); + } + talloc_zfree(tmp_ctx); + return ret; +} + +errno_t sysdb_update_ranges(struct sysdb_ctx *sysdb, + struct range_info **ranges) +{ + int ret; + int sret; + size_t c; + size_t d; + TALLOC_CTX *tmp_ctx = NULL; + size_t cur_range_count; + struct range_info **cur_ranges; + struct ldb_dn *dn; + bool in_transaction = false; + bool *keep_range; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + ret = ENOMEM; + goto done; + } + + /* Retrieve all ranges that are currently in sysdb */ + ret = sysdb_get_ranges(tmp_ctx, sysdb, &cur_range_count, + &cur_ranges); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("sysdb_get_ranges failed.\n")); + goto done; + } + + keep_range = talloc_zero_array(tmp_ctx, bool, cur_range_count); + if (keep_range == NULL) { + ret = ENOMEM; + DEBUG(SSSDBG_OP_FAILURE, ("talloc_zero_array failed.\n")); + goto done; + } + + ret = sysdb_transaction_start(sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("sysdb_transaction_start failed.\n")); + goto done; + } + in_transaction = true; + + /* Go through a list of retrieved ranges and: + * - if a range already exists in sysdb, mark it for preservation + * - if the range doesn't exist in sysdb, create it + */ + for (c = 0; ranges[c] != NULL; c++) { + for (d = 0; d < cur_range_count; d++) { + if (strcasecmp(ranges[c]->name, cur_ranges[d]->name) == 0) { + keep_range[d] = true; + /* range already in cache, nothing to do */ + break; + } + } + + if (d == cur_range_count) { + DEBUG(SSSDBG_TRACE_FUNC, ("Adding range [%s].\n", ranges[c]->name)); + ret = sysdb_range_create(sysdb, ranges[c]); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("sysdb_range_create failed.\n")); + goto done; + } + } + } + + /* Now delete all ranges that have been in sysdb prior to + * refreshing the list and are not marked for preservation + * (i.e. they are not in the new list of ranges) + */ + for (d = 0; d < cur_range_count; d++) { + if (!keep_range[d]) { + DEBUG(SSSDBG_TRACE_FUNC, ("Removing range [%s].\n", + cur_ranges[d]->name)); + dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_RANGE, + cur_ranges[d]->name, sysdb->domain->name); + if (dn == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sysdb_delete_entry(sysdb, dn, true); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("sysdb_delete_entry failed.\n")); + goto done; + } + } + } + + ret = sysdb_transaction_commit(sysdb); + if (ret == EOK) { + in_transaction = false; + } else { + DEBUG(SSSDBG_MINOR_FAILURE, ("Could not commit transaction\n")); + } + +done: + if (in_transaction) { + sret = sysdb_transaction_cancel(sysdb); + if (sret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction\n")); + } + } + talloc_free(tmp_ctx); + return ret; +} diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c index 09fbeadc0..b816f9977 100644 --- a/src/providers/ipa/ipa_common.c +++ b/src/providers/ipa/ipa_common.c @@ -149,6 +149,9 @@ static errno_t ipa_parse_search_base(TALLOC_CTX *mem_ctx, case IPA_MASTER_DOMAIN_SEARCH_BASE: class_name = "IPA_MASTER_DOMAIN"; break; + case IPA_RANGES_SEARCH_BASE: + class_name = "IPA_RANGES"; + break; default: DEBUG(SSSDBG_CONF_SETTINGS, ("Unknown search base type: [%d]\n", class)); @@ -539,6 +542,29 @@ int ipa_get_id_options(struct ipa_options *ipa_opts, &ipa_opts->master_domain_search_bases); if (ret != EOK) goto done; + if (NULL == dp_opt_get_string(ipa_opts->basic, + IPA_RANGES_SEARCH_BASE)) { + value = talloc_asprintf(tmpctx, "cn=ranges,cn=etc,%s", basedn); + if (value == NULL) { + ret = ENOMEM; + goto done; + } + + ret = dp_opt_set_string(ipa_opts->basic, IPA_RANGES_SEARCH_BASE, value); + if (ret != EOK) { + goto done; + } + + DEBUG(SSSDBG_CONF_SETTINGS, ("Option %s set to %s\n", + ipa_opts->basic[IPA_RANGES_SEARCH_BASE].opt_name, + dp_opt_get_string(ipa_opts->basic, + IPA_RANGES_SEARCH_BASE))); + } + ret = ipa_parse_search_base(ipa_opts, ipa_opts->basic, + IPA_RANGES_SEARCH_BASE, + &ipa_opts->ranges_search_bases); + if (ret != EOK) goto done; + ret = sdap_get_map(ipa_opts->id, cdb, conf_path, ipa_attr_map, SDAP_AT_GENERAL, diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h index 0a18ec1b1..3e2ef2843 100644 --- a/src/providers/ipa/ipa_common.h +++ b/src/providers/ipa/ipa_common.h @@ -48,6 +48,7 @@ enum ipa_basic_opt { IPA_HBAC_DENY_METHOD, IPA_HBAC_SUPPORT_SRCHOST, IPA_AUTOMOUNT_LOCATION, + IPA_RANGES_SEARCH_BASE, IPA_OPTS_BASIC /* opts counter */ }; @@ -127,6 +128,7 @@ struct ipa_options { struct sdap_search_base **selinux_search_bases; struct sdap_search_base **subdomains_search_bases; struct sdap_search_base **master_domain_search_bases; + struct sdap_search_base **ranges_search_bases; struct ipa_service *service; /* id provider */ diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c index b58058a8e..0524ddfa6 100644 --- a/src/providers/ipa/ipa_init.c +++ b/src/providers/ipa/ipa_init.c @@ -542,6 +542,7 @@ int sssm_ipa_subdomains_init(struct be_ctx *bectx, subdomains_ctx->sdap_id_ctx = id_ctx->sdap_id_ctx; subdomains_ctx->search_bases = id_ctx->ipa_options->subdomains_search_bases; subdomains_ctx->master_search_bases = id_ctx->ipa_options->master_domain_search_bases; + subdomains_ctx->ranges_search_bases = id_ctx->ipa_options->ranges_search_bases; *ops = &ipa_subdomains_ops; *pvt_data = subdomains_ctx; diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h index 4366a12c2..2a901bdad 100644 --- a/src/providers/ipa/ipa_opts.h +++ b/src/providers/ipa/ipa_opts.h @@ -45,6 +45,7 @@ struct dp_option ipa_basic_opts[] = { { "ipa_hbac_treat_deny_as", DP_OPT_STRING, { "DENY_ALL" }, NULL_STRING }, { "ipa_hbac_support_srchost", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, { "ipa_automount_location", DP_OPT_STRING, { "default" }, NULL_STRING }, + { "ipa_ranges_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING }, DP_OPTION_TERMINATOR }; diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c index 185b3c523..55ecea043 100644 --- a/src/providers/ipa/ipa_subdomains.c +++ b/src/providers/ipa/ipa_subdomains.c @@ -28,14 +28,23 @@ #define SUBDOMAINS_FILTER "objectclass=ipaNTTrustedDomain" #define MASTER_DOMAIN_FILTER "objectclass=ipaNTDomainAttrs" +#define RANGE_FILTER "objectclass=ipaIDRange" #define IPA_CN "cn" #define IPA_FLATNAME "ipaNTFlatName" -#define IPA_SID "ipaNTTrustedDomainSID" +#define IPA_SID "ipaNTSecurityIdentifier" +#define IPA_TRUSTED_DOMAIN_SID "ipaNTTrustedDomainSID" + +#define IPA_BASE_ID "ipaBaseID" +#define IPA_ID_RANGE_SIZE "ipaIDRangeSize" +#define IPA_BASE_RID "ipaBaseRID" +#define IPA_SECONDARY_BASE_RID "ipaSecondaryBaseRID" +#define OBJECTCLASS "objectClass" enum ipa_subdomains_req_type { IPA_SUBDOMAINS_MASTER, IPA_SUBDOMAINS_SLAVE, + IPA_SUBDOMAINS_RANGES, IPA_SUBDOMAINS_MAX /* Counter */ }; @@ -43,6 +52,7 @@ enum ipa_subdomains_req_type { struct ipa_subdomains_req_params { const char *filter; tevent_req_fn cb; + const char *attrs[8]; }; static void ipa_subdomains_reply(struct be_req *be_req, int dp_err, int result) @@ -50,6 +60,97 @@ static void ipa_subdomains_reply(struct be_req *be_req, int dp_err, int result) be_req->fn(be_req, dp_err, result, NULL); } +static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx, + size_t count, + struct sysdb_attrs **reply, + struct range_info ***_range_list) +{ + struct range_info **range_list = NULL; + const char *value; + size_t c; + int ret; + + range_list = talloc_array(mem_ctx, struct range_info *, count + 1); + if (range_list == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("talloc_array failed.\n")); + return ENOMEM; + } + + for (c = 0; c < count; c++) { + range_list[c] = talloc_zero(range_list, struct range_info); + if (range_list[c] == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("talloc_zero failed.\n")); + ret = ENOMEM; + goto done; + } + + ret = sysdb_attrs_get_string(reply[c], IPA_CN, &value); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); + goto done; + } + range_list[c]->name = talloc_strdup(range_list[c], value); + if (range_list[c]->name == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); + ret = ENOMEM; + goto done; + } + + ret = sysdb_attrs_get_string(reply[c], IPA_TRUSTED_DOMAIN_SID, &value); + if (ret == EOK) { + range_list[c]->trusted_dom_sid = talloc_strdup(range_list[c], + value); + if (range_list[c]->trusted_dom_sid == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); + ret = ENOMEM; + goto done; + } + } else if (ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); + goto done; + } + + ret = sysdb_attrs_get_uint32_t(reply[c], IPA_BASE_ID, + &range_list[c]->base_id); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); + goto done; + } + + ret = sysdb_attrs_get_uint32_t(reply[c], IPA_ID_RANGE_SIZE, + &range_list[c]->id_range_size); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); + goto done; + } + + ret = sysdb_attrs_get_uint32_t(reply[c], IPA_BASE_RID, + &range_list[c]->base_rid); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); + goto done; + } + + ret = sysdb_attrs_get_uint32_t(reply[c], IPA_SECONDARY_BASE_RID, + &range_list[c]->secondary_base_rid); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); + goto done; + } + } + range_list[c] = NULL; + + *_range_list = range_list; + ret = EOK; + +done: + if (ret != EOK) { + talloc_free(range_list); + } + + return ret; +} + static errno_t ipa_subdomains_parse_results( struct be_get_subdomains_req *sd_data, size_t count, @@ -101,7 +202,7 @@ static errno_t ipa_subdomains_parse_results( goto done; } - ret = sysdb_attrs_get_string(reply[c], IPA_SID, &value); + ret = sysdb_attrs_get_string(reply[c], IPA_TRUSTED_DOMAIN_SID, &value); if (ret == EOK) { new_domain_list[c]->id = talloc_strdup(new_domain_list[c], value); if (new_domain_list[c]->id == NULL) { @@ -150,10 +251,16 @@ ipa_subdomains_handler_get(struct ipa_subdomains_req_ctx *ctx, enum ipa_subdomains_req_type type); static void ipa_subdomains_handler_done(struct tevent_req *req); static void ipa_subdomains_handler_master_done(struct tevent_req *req); +static void ipa_subdomains_handler_ranges_done(struct tevent_req *req); static struct ipa_subdomains_req_params subdomain_requests[] = { - { MASTER_DOMAIN_FILTER, ipa_subdomains_handler_master_done }, - { SUBDOMAINS_FILTER, ipa_subdomains_handler_done } + { MASTER_DOMAIN_FILTER, ipa_subdomains_handler_master_done, + {IPA_CN, IPA_FLATNAME, IPA_SID, NULL }}, + { SUBDOMAINS_FILTER, ipa_subdomains_handler_done, + {IPA_CN, IPA_FLATNAME, IPA_TRUSTED_DOMAIN_SID, NULL }}, + { RANGE_FILTER, ipa_subdomains_handler_ranges_done, + {OBJECTCLASS, IPA_CN, IPA_BASE_ID, IPA_ID_RANGE_SIZE, IPA_BASE_RID, + IPA_SECONDARY_BASE_RID, IPA_TRUSTED_DOMAIN_SID, NULL }} }; void ipa_subdomains_handler(struct be_req *be_req) @@ -250,10 +357,6 @@ ipa_subdomains_handler_get(struct ipa_subdomains_req_ctx *ctx, struct tevent_req *req; struct sdap_search_base *base; struct ipa_subdomains_req_params *params; - const char *attrs[] = {IPA_CN, - IPA_FLATNAME, - IPA_SID, - NULL}; if (type >= IPA_SUBDOMAINS_MAX) { return EINVAL; @@ -276,7 +379,7 @@ ipa_subdomains_handler_get(struct ipa_subdomains_req_ctx *ctx, ctx->sd_ctx->sdap_id_ctx->opts, sdap_id_op_handle(ctx->sdap_op), base->basedn, base->scope, - ctx->current_filter, attrs, NULL, 0, + ctx->current_filter, params->attrs, NULL, 0, dp_opt_get_int(ctx->sd_ctx->sdap_id_ctx->opts->basic, SDAP_SEARCH_TIMEOUT), false); @@ -299,7 +402,6 @@ static void ipa_subdomains_handler_done(struct tevent_req *req) struct ipa_subdomains_req_ctx); struct be_req *be_req = ctx->be_req; struct sysdb_ctx *sysdb; - struct subdomain_info *domain_info; sysdb = (be_req->sysdb)?be_req->sysdb:be_req->be_ctx->sysdb; @@ -342,6 +444,60 @@ static void ipa_subdomains_handler_done(struct tevent_req *req) goto done; } + + ctx->search_base_iter = 0; + ctx->search_bases = ctx->sd_ctx->ranges_search_bases; + ret = ipa_subdomains_handler_get(ctx, IPA_SUBDOMAINS_RANGES); + if (ret == EAGAIN) { + return; + } else if (ret != EOK) { + goto done; + } + + DEBUG(SSSDBG_OP_FAILURE, ("No search base for ranges available.\n")); + ret = EINVAL; + +done: + talloc_free(ctx); + ipa_subdomains_reply(be_req, (ret == EOK ? DP_ERR_OK : DP_ERR_FATAL), ret); +} + + +static void ipa_subdomains_handler_ranges_done(struct tevent_req *req) +{ + errno_t ret; + size_t reply_count; + struct sysdb_attrs **reply = NULL; + struct ipa_subdomains_req_ctx *ctx = tevent_req_callback_data(req, + struct ipa_subdomains_req_ctx); + struct be_req *be_req = ctx->be_req; + struct subdomain_info *domain_info; + struct range_info **range_list = NULL; + struct sysdb_ctx *sysdb; + + sysdb = (be_req->sysdb)?be_req->sysdb:be_req->be_ctx->sysdb; + + ret = sdap_get_generic_recv(req, ctx, &reply_count, &reply); + talloc_zfree(req); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("sdap_get_generic_send request failed.\n")); + goto done; + } + + ret = ipa_ranges_parse_results(ctx, reply_count, reply, &range_list); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("ipa_ranges_parse_results request failed.\n")); + goto done; + } + + ret = sysdb_update_ranges(sysdb, range_list); + talloc_free(range_list); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("sysdb_update_ranges failed.\n")); + goto done; + } + + ret = sysdb_master_domain_get_info(ctx, sysdb, &domain_info); if (ret != EOK) { goto done; diff --git a/src/providers/ipa/ipa_subdomains.h b/src/providers/ipa/ipa_subdomains.h index 76406f122..895ba29f5 100644 --- a/src/providers/ipa/ipa_subdomains.h +++ b/src/providers/ipa/ipa_subdomains.h @@ -32,6 +32,7 @@ struct ipa_subdomains_ctx { struct sdap_id_ctx *sdap_id_ctx; struct sdap_search_base **search_bases; struct sdap_search_base **master_search_bases; + struct sdap_search_base **ranges_search_bases; }; -- cgit