summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am1
-rw-r--r--src/config/SSSDConfig/__init__.py.in1
-rw-r--r--src/config/etc/sssd.api.d/sssd-ipa.conf1
-rw-r--r--src/db/sysdb.h39
-rw-r--r--src/db/sysdb_ranges.c345
-rw-r--r--src/providers/ipa/ipa_common.c26
-rw-r--r--src/providers/ipa/ipa_common.h2
-rw-r--r--src/providers/ipa/ipa_init.c1
-rw-r--r--src/providers/ipa/ipa_opts.h1
-rw-r--r--src/providers/ipa/ipa_subdomains.c176
-rw-r--r--src/providers/ipa/ipa_subdomains.h1
11 files changed, 584 insertions, 10 deletions
diff --git a/Makefile.am b/Makefile.am
index 445492e22..9d328184d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -462,6 +462,7 @@ libsss_util_la_SOURCES = \
src/db/sysdb_services.c \
src/db/sysdb_autofs.c \
src/db/sysdb_subdomains.c \
+ src/db/sysdb_ranges.c \
src/db/sysdb_idmap.c \
src/monitor/monitor_sbus.c \
src/providers/dp_auth_util.c \
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 <sbose@redhat.com>
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+#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;
};