summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2013-06-10 11:55:16 +0200
committerJakub Hrozek <jhrozek@redhat.com>2013-06-28 18:57:23 +0200
commit95a08a0c02281b28bd1914e0727b40ae25b4e16a (patch)
tree11b185a2f3aedb7b601782203a11b3c113f8c5b8
parentb618590bcde5b05f149ba10072b3197670a38185 (diff)
downloadsssd-95a08a0c02281b28bd1914e0727b40ae25b4e16a.tar.gz
sssd-95a08a0c02281b28bd1914e0727b40ae25b4e16a.tar.bz2
sssd-95a08a0c02281b28bd1914e0727b40ae25b4e16a.zip
idmap: allow first RID to be set
Currently libss_idmap implicitly assumes that the RID 0 is always mapped to the first ID of the given range. This is not the case anymore when multiple ranges are used e.g. for trusted domains in FreeIPA. A new call sss_idmap_add_domain_ex() was added which can take the first RID as an argument. This new call will get more options with other patches hence I didn't change the library version with this patch. Fixes https://fedorahosted.org/sssd/ticket/1938
-rw-r--r--src/lib/idmap/sss_idmap.c99
-rw-r--r--src/lib/idmap/sss_idmap.h30
2 files changed, 109 insertions, 20 deletions
diff --git a/src/lib/idmap/sss_idmap.c b/src/lib/idmap/sss_idmap.c
index 3a39aaef..122f62f5 100644
--- a/src/lib/idmap/sss_idmap.c
+++ b/src/lib/idmap/sss_idmap.c
@@ -38,6 +38,7 @@ struct idmap_domain_info {
char *sid;
struct sss_idmap_range *range;
struct idmap_domain_info *next;
+ uint32_t first_rid;
};
static void *default_alloc(size_t size, void *pvt)
@@ -90,16 +91,16 @@ static struct sss_idmap_range *idmap_range_dup(struct sss_idmap_ctx *ctx,
return new;
}
-static bool id_is_in_range(uint32_t id, struct sss_idmap_range *range,
+static bool id_is_in_range(uint32_t id, struct idmap_domain_info *dom,
uint32_t *rid)
{
- if (id == 0 || range == NULL) {
+ if (id == 0 || dom == NULL || dom->range == NULL) {
return false;
}
- if (id >= range->min && id <= range->max) {
+ if (id >= dom->range->min && id <= dom->range->max) {
if (rid != NULL) {
- *rid = id - range->min;
+ *rid = dom->first_rid + (id - dom->range->min);
}
return true;
@@ -330,12 +331,51 @@ enum idmap_error_code sss_idmap_calculate_range(struct sss_idmap_ctx *ctx,
return IDMAP_SUCCESS;
}
-enum idmap_error_code sss_idmap_add_domain(struct sss_idmap_ctx *ctx,
- const char *domain_name,
- const char *domain_sid,
- struct sss_idmap_range *range)
+static enum idmap_error_code dom_check_collision(
+ struct idmap_domain_info *dom_list,
+ struct idmap_domain_info *new_dom)
+{
+ struct idmap_domain_info *dom;
+
+ for (dom = dom_list; dom != NULL; dom = dom->next) {
+
+ /* check if ID ranges overlap */
+ if ((new_dom->range->min >= dom->range->min
+ && new_dom->range->min <= dom->range->max)
+ || (new_dom->range->max >= dom->range->min
+ && new_dom->range->max <= dom->range->max)) {
+ return IDMAP_COLLISION;
+ }
+
+ /* check if domain name and SID are consistent */
+ if ((strcasecmp(new_dom->name, dom->name) == 0
+ && strcasecmp(new_dom->sid, dom->sid) != 0)
+ || (strcasecmp(new_dom->name, dom->name) != 0
+ && strcasecmp(new_dom->sid, dom->sid) == 0)) {
+ return IDMAP_COLLISION;
+ }
+
+ /* check if RID ranges overlap */
+ if (strcasecmp(new_dom->name, dom->name) == 0
+ && strcasecmp(new_dom->sid, dom->sid) == 0
+ && new_dom->first_rid >= dom->first_rid
+ && new_dom->first_rid <=
+ dom->first_rid + (dom->range->max - dom->range->min)) {
+ return IDMAP_COLLISION;
+ }
+ }
+
+ return IDMAP_SUCCESS;
+}
+
+enum idmap_error_code sss_idmap_add_domain_ex(struct sss_idmap_ctx *ctx,
+ const char *domain_name,
+ const char *domain_sid,
+ struct sss_idmap_range *range,
+ uint32_t rid)
{
struct idmap_domain_info *dom = NULL;
+ enum idmap_error_code err;
CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);
@@ -372,6 +412,14 @@ enum idmap_error_code sss_idmap_add_domain(struct sss_idmap_ctx *ctx,
goto fail;
}
+ dom->first_rid = rid;
+
+ err = dom_check_collision(ctx->idmap_domain_info, dom);
+ if (err != IDMAP_SUCCESS) {
+ ctx->free_func(dom, ctx->alloc_pvt);
+ return err;
+ }
+
dom->next = ctx->idmap_domain_info;
ctx->idmap_domain_info = dom;
@@ -385,6 +433,14 @@ fail:
return IDMAP_OUT_OF_MEMORY;
}
+enum idmap_error_code sss_idmap_add_domain(struct sss_idmap_ctx *ctx,
+ const char *domain_name,
+ const char *domain_sid,
+ struct sss_idmap_range *range)
+{
+ return sss_idmap_add_domain_ex(ctx, domain_name, domain_sid, range, 0);
+}
+
static bool sss_idmap_sid_is_builtin(const char *sid)
{
if (strncmp(sid, "S-1-5-32-", 9) == 0) {
@@ -396,14 +452,16 @@ static bool sss_idmap_sid_is_builtin(const char *sid)
enum idmap_error_code sss_idmap_sid_to_unix(struct sss_idmap_ctx *ctx,
const char *sid,
- uint32_t *id)
+ uint32_t *_id)
{
struct idmap_domain_info *idmap_domain_info;
size_t dom_len;
long long rid;
char *endptr;
+ uint32_t id;
+ bool no_range = false;
- if (sid == NULL || id == NULL) {
+ if (sid == NULL || _id == NULL) {
return IDMAP_ERROR;
}
@@ -417,27 +475,30 @@ enum idmap_error_code sss_idmap_sid_to_unix(struct sss_idmap_ctx *ctx,
while (idmap_domain_info != NULL) {
dom_len = strlen(idmap_domain_info->sid);
- if (strlen(sid) > dom_len && sid[dom_len] == '-' &&
- strncmp(sid, idmap_domain_info->sid, dom_len) == 0) {
+ if (strlen(sid) > dom_len && sid[dom_len] == '-'
+ && strncmp(sid, idmap_domain_info->sid, dom_len) == 0) {
errno = 0;
rid = strtoull(sid + dom_len + 1, &endptr, 10);
if (errno != 0 || rid > UINT32_MAX || *endptr != '\0') {
return IDMAP_SID_INVALID;
}
- if (rid + idmap_domain_info->range->min >
- idmap_domain_info->range->max) {
- return IDMAP_NO_RANGE;
+ if (rid >= idmap_domain_info->first_rid) {
+ id = idmap_domain_info->range->min
+ + (rid - idmap_domain_info->first_rid);
+ if (id <= idmap_domain_info->range->max) {
+ *_id = id;
+ return IDMAP_SUCCESS;
+ }
}
- *id = rid + idmap_domain_info->range->min;
- return IDMAP_SUCCESS;
+ no_range = true;
}
idmap_domain_info = idmap_domain_info->next;
}
- return IDMAP_NO_DOMAIN;
+ return no_range ? IDMAP_NO_RANGE : IDMAP_NO_DOMAIN;
}
enum idmap_error_code sss_idmap_unix_to_sid(struct sss_idmap_ctx *ctx,
@@ -455,7 +516,7 @@ enum idmap_error_code sss_idmap_unix_to_sid(struct sss_idmap_ctx *ctx,
idmap_domain_info = ctx->idmap_domain_info;
while (idmap_domain_info != NULL) {
- if (id_is_in_range(id, idmap_domain_info->range, &rid)) {
+ if (id_is_in_range(id, idmap_domain_info, &rid)) {
len = snprintf(NULL, 0, SID_FMT, idmap_domain_info->sid, rid);
if (len <= 0 || len > SID_STR_MAX_LEN) {
return IDMAP_ERROR;
diff --git a/src/lib/idmap/sss_idmap.h b/src/lib/idmap/sss_idmap.h
index 9710501b..3beeca11 100644
--- a/src/lib/idmap/sss_idmap.h
+++ b/src/lib/idmap/sss_idmap.h
@@ -74,7 +74,10 @@ enum idmap_error_code {
IDMAP_BUILTIN_SID,
/** No more free slices */
- IDMAP_OUT_OF_SLICES
+ IDMAP_OUT_OF_SLICES,
+
+ /** New domain collides with existing one */
+ IDMAP_COLLISION
};
/**
@@ -237,6 +240,7 @@ enum idmap_error_code sss_idmap_calculate_range(struct sss_idmap_ctx *ctx,
* context
* - #IDMAP_SID_INVALID: Invalid SID provided
* - #IDMAP_NO_DOMAIN: No domain domain name given
+ * - #IDMAP_COLLISION: New domain collides with existing one
*/
enum idmap_error_code sss_idmap_add_domain(struct sss_idmap_ctx *ctx,
const char *domain_name,
@@ -244,6 +248,30 @@ enum idmap_error_code sss_idmap_add_domain(struct sss_idmap_ctx *ctx,
struct sss_idmap_range *range);
/**
+ * @brief Add a domain with the first mappable RID to the idmap context
+ *
+ * @param[in] ctx Idmap context
+ * @param[in] domain_name Zero-terminated string with the domain name
+ * @param[in] domain_sid Zero-terminated string representation of the domain
+ * SID (S-1-15-.....)
+ * @param[in] range TBD Some information about the id ranges of this
+ * domain
+ * @param[in] rid The RID that should be mapped to the first ID of the
+ * given range.
+ *
+ * @return
+ * - #IDMAP_OUT_OF_MEMORY: Insufficient memory to store the data in the idmap
+ * context
+ * - #IDMAP_SID_INVALID: Invalid SID provided
+ * - #IDMAP_NO_DOMAIN: No domain domain name given
+ * - #IDMAP_COLLISION: New domain collides with existing one
+ */
+enum idmap_error_code sss_idmap_add_domain_ex(struct sss_idmap_ctx *ctx,
+ const char *domain_name,
+ const char *domain_sid,
+ struct sss_idmap_range *range,
+ uint32_t rid);
+/**
* @brief Translate SID to a unix UID or GID
*
* @param[in] ctx Idmap context