summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2011-03-16 12:34:26 -0400
committerStephen Gallagher <sgallagh@redhat.com>2011-03-23 05:05:00 -0400
commitf33d34ea282b151518cd9befb9cd281aaccfa966 (patch)
treefb0ac9c93aaf0b65d21a74db06ad693816d055f6 /src
parent2fb62d06da345b5adb3357373c29ce9e212c5640 (diff)
downloadsssd-f33d34ea282b151518cd9befb9cd281aaccfa966.tar.gz
sssd-f33d34ea282b151518cd9befb9cd281aaccfa966.tar.xz
sssd-f33d34ea282b151518cd9befb9cd281aaccfa966.zip
Ignore alternate names for users and groups
Create sysdb_get_rdn() function This function takes a DN formatted string and returns the RDN value from it. Add sysdb_attrs_primary_name() This function will check a sysdb_attrs struct for the primary name of the entity it represents. If there are multiple entries, it will pick the one that matches the RDN. If none match, it will throw an error. Ignore aliases for users Users in ldap with multiple values for their username attribute will now be compared against the RDN of the entry to determine the "primary" username. We will save only this primary name to the ldb cache. RFC2307: Ignore aliases for groups Groups in ldap with multiple values for their groupname attribute will now be compared against the RDN of the entry to determine the "primary" group name. We will save only this primary group name to the ldb cache. RFC2307bis: Ignore aliases for groups Groups in ldap with multiple values for their groupname attribute will now be compared against the RDN of the entry to determine the "primary" group name. We will save only this primary group name to the ldb cache.
Diffstat (limited to 'src')
-rw-r--r--src/db/sysdb.c163
-rw-r--r--src/db/sysdb.h6
-rw-r--r--src/providers/ldap/sdap_async_accounts.c144
3 files changed, 243 insertions, 70 deletions
diff --git a/src/db/sysdb.c b/src/db/sysdb.c
index 8806fe05f..dd70d5c74 100644
--- a/src/db/sysdb.c
+++ b/src/db/sysdb.c
@@ -165,33 +165,68 @@ struct ldb_dn *sysdb_netgroup_base_dn(struct sysdb_ctx *ctx, void *memctx,
return ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_TMPL_NETGROUP_BASE, domain);
}
-errno_t sysdb_group_dn_name(struct sysdb_ctx *ctx, void *memctx,
- const char *_dn, char **_name)
+errno_t sysdb_get_rdn(struct sysdb_ctx *ctx, void *memctx,
+ const char *_dn, char **_name, char **_val)
{
+ errno_t ret;
struct ldb_dn *dn;
+ const char *attr_name = NULL;
const struct ldb_val *val;
- *_name = NULL;
+ TALLOC_CTX *tmpctx;
- dn = ldb_dn_new_fmt(memctx, ctx->ldb, "%s", _dn);
- if (dn == NULL) {
+ /* We have to create a tmpctx here because
+ * ldb_dn_new_fmt() fails if memctx is NULL
+ */
+ tmpctx = talloc_new(NULL);
+ if (!tmpctx) {
return ENOMEM;
}
+ dn = ldb_dn_new_fmt(tmpctx, ctx->ldb, "%s", _dn);
+ if (dn == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ if (_name) {
+ attr_name = ldb_dn_get_rdn_name(dn);
+ if (attr_name == NULL) {
+ ret = EINVAL;
+ goto done;
+ }
+
+ *_name = talloc_strdup(memctx, attr_name);
+ if (!_name) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
val = ldb_dn_get_rdn_val(dn);
if (val == NULL) {
- talloc_zfree(dn);
- return EINVAL;
+ ret = EINVAL;
+ talloc_free(*_name);
+ goto done;
}
- *_name = talloc_strndup(memctx, (char *) val->data, val->length);
- if (!*_name) {
- talloc_zfree(dn);
- return ENOMEM;
+ *_val = talloc_strndup(memctx, (char *) val->data, val->length);
+ if (!*_val) {
+ ret = ENOMEM;
+ talloc_free(*_name);
+ goto done;
}
- talloc_zfree(dn);
+ ret = EOK;
- return EOK;
+done:
+ talloc_zfree(tmpctx);
+ return ret;
+}
+
+errno_t sysdb_group_dn_name(struct sysdb_ctx *ctx, void *memctx,
+ const char *_dn, char **_name)
+{
+ return sysdb_get_rdn(ctx, memctx, _dn, NULL, _name);
}
struct ldb_dn *sysdb_domain_dn(struct sysdb_ctx *ctx, void *memctx,
@@ -2005,3 +2040,105 @@ done:
talloc_free(tmp_ctx);
return ret;
}
+
+errno_t sysdb_attrs_primary_name(struct sysdb_ctx *sysdb,
+ struct sysdb_attrs *attrs,
+ const char *ldap_attr,
+ const char **_primary)
+{
+ errno_t ret;
+ char *rdn_attr = NULL;
+ char *rdn_val = NULL;
+ struct ldb_message_element *sysdb_name_el;
+ struct ldb_message_element *orig_dn_el;
+ size_t i;
+ TALLOC_CTX *tmpctx = NULL;
+
+ tmpctx = talloc_new(NULL);
+ if (!tmpctx) {
+ return ENOMEM;
+ }
+
+ ret = sysdb_attrs_get_el(attrs,
+ SYSDB_NAME,
+ &sysdb_name_el);
+ if (sysdb_name_el->num_values == 0) {
+ ret = EINVAL;
+ goto done;
+ }
+
+ if (sysdb_name_el->num_values == 1) {
+ /* Entry contains only one name. Just return that */
+ *_primary = (const char *)sysdb_name_el->values[0].data;
+ ret = EOK;
+ goto done;
+ }
+
+ /* Multiple values for name. Check whether one matches the RDN */
+
+ ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &orig_dn_el);
+ if (ret) {
+ goto done;
+ }
+ if (orig_dn_el->num_values == 0) {
+ DEBUG(7, ("Original DN is not available.\n"));
+ } else if (orig_dn_el->num_values == 1) {
+ ret = sysdb_get_rdn(sysdb, tmpctx,
+ (const char *) orig_dn_el->values[0].data,
+ &rdn_attr,
+ &rdn_val);
+ if (ret != EOK) {
+ DEBUG(1, ("Could not get rdn from [%s]\n",
+ (const char *) orig_dn_el->values[0].data));
+ goto done;
+ }
+ } else {
+ DEBUG(1, ("Should not have more than one origDN\n"));
+ ret = EINVAL;
+ goto done;
+ }
+
+ /* First check whether the attribute name matches */
+ DEBUG(8, ("Comparing attribute names [%s] and [%s]\n",
+ rdn_attr, ldap_attr));
+ if (strcasecmp(rdn_attr, ldap_attr) != 0) {
+ /* Multiple entries, and the RDN attribute doesn't match.
+ * We have no way of resolving this deterministically,
+ * so we'll punt.
+ */
+ DEBUG(1, ("Cannot save entry. It has multiple names and the RDN "
+ "attribute does not match\n"));
+ ret = EINVAL;
+ goto done;
+ }
+
+ for (i = 0; i < sysdb_name_el->num_values; i++) {
+ if (strcasecmp(rdn_val,
+ (const char *)sysdb_name_el->values[i].data) == 0) {
+ /* This name matches the RDN. Use it */
+ break;
+ }
+ }
+ if (i < sysdb_name_el->num_values) {
+ /* Match was found */
+ *_primary = (const char *)sysdb_name_el->values[i].data;
+ } else {
+ /* If we can't match the name to the RDN, we just have to
+ * throw up our hands. There's no deterministic way to
+ * decide which name is correct.
+ */
+ DEBUG(1, ("Cannot save entry. Unable to determine groupname\n"));
+ ret = EINVAL;
+ goto done;
+ }
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ DEBUG(1, ("Could not determine primary name: [%d][%s]\n",
+ ret, strerror(ret)));
+ }
+ talloc_free(tmpctx);
+ return ret;
+}
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index ae0b33ce1..e98426551 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -215,11 +215,17 @@ int sysdb_attrs_users_from_ldb_vals(struct sysdb_attrs *attrs,
const char *domain,
struct ldb_val *values,
int num_values);
+errno_t sysdb_attrs_primary_name(struct sysdb_ctx *sysdb,
+ struct sysdb_attrs *attrs,
+ const char *ldap_attr,
+ const char **_primary);
/* convert an ldb error into an errno error */
int sysdb_error_to_errno(int ldberr);
/* DNs related helper functions */
+errno_t sysdb_get_rdn(struct sysdb_ctx *ctx, void *memctx,
+ const char *_dn, char **_name, char **_val);
struct ldb_dn *sysdb_user_dn(struct sysdb_ctx *ctx, void *memctx,
const char *domain, const char *name);
struct ldb_dn *sysdb_group_dn(struct sysdb_ctx *ctx, void *memctx,
diff --git a/src/providers/ldap/sdap_async_accounts.c b/src/providers/ldap/sdap_async_accounts.c
index 5c2078e7d..0784965ac 100644
--- a/src/providers/ldap/sdap_async_accounts.c
+++ b/src/providers/ldap/sdap_async_accounts.c
@@ -40,7 +40,7 @@ static int sdap_save_user(TALLOC_CTX *memctx,
{
struct ldb_message_element *el;
int ret;
- const char *name;
+ const char *name = NULL;
const char *pwd;
const char *gecos;
const char *homedir;
@@ -49,25 +49,35 @@ static int sdap_save_user(TALLOC_CTX *memctx,
gid_t gid;
struct sysdb_attrs *user_attrs;
char *upn = NULL;
- int i;
+ size_t i;
char *val = NULL;
int cache_timeout;
char *usn_value = NULL;
size_t c;
char **missing = NULL;
+ TALLOC_CTX *tmpctx = NULL;
DEBUG(9, ("Save user\n"));
- ret = sysdb_attrs_get_el(attrs,
- opts->user_map[SDAP_AT_USER_NAME].sys_name, &el);
- if (el->num_values == 0) {
- ret = EINVAL;
+ tmpctx = talloc_new(memctx);
+ if (!tmpctx) {
+ ret = ENOMEM;
+ goto fail;
}
- if (ret) {
+
+ user_attrs = sysdb_new_attrs(tmpctx);
+ if (user_attrs == NULL) {
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ ret = sysdb_attrs_primary_name(ctx, attrs,
+ opts->user_map[SDAP_AT_USER_NAME].name,
+ &name);
+ if (ret != EOK) {
DEBUG(1, ("Failed to save the user - entry has no name attribute\n"));
- return ret;
+ goto fail;
}
- name = (const char *)el->values[0].data;
ret = sysdb_attrs_get_el(attrs,
opts->user_map[SDAP_AT_USER_PWD].sys_name, &el);
@@ -129,12 +139,6 @@ static int sdap_save_user(TALLOC_CTX *memctx,
goto fail;
}
- user_attrs = sysdb_new_attrs(memctx);
- if (user_attrs == NULL) {
- ret = ENOMEM;
- goto fail;
- }
-
ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &el);
if (ret) {
goto fail;
@@ -271,7 +275,7 @@ static int sdap_save_user(TALLOC_CTX *memctx,
/* Make sure that any attributes we requested from LDAP that we
* did not receive are also removed from the sysdb
*/
- ret = list_missing_attrs(NULL, opts->user_map, SDAP_OPTS_USER,
+ ret = list_missing_attrs(user_attrs, opts->user_map, SDAP_OPTS_USER,
ldap_attrs, attrs, &missing);
if (ret != EOK) {
goto fail;
@@ -285,21 +289,23 @@ static int sdap_save_user(TALLOC_CTX *memctx,
DEBUG(6, ("Storing info for user %s\n", name));
- ret = sysdb_store_user(memctx, ctx, dom,
+ ret = sysdb_store_user(user_attrs, ctx, dom,
name, pwd, uid, gid, gecos, homedir, shell,
user_attrs, missing, cache_timeout);
if (ret) goto fail;
- talloc_zfree(missing);
if (_usn_value) {
*_usn_value = usn_value;
}
+ talloc_steal(memctx, user_attrs);
+ talloc_free(tmpctx);
return EOK;
fail:
- DEBUG(2, ("Failed to save user %s\n", name));
- talloc_free(missing);
+ DEBUG(2, ("Failed to save user [%s]\n",
+ name ? name : "Unknown"));
+ talloc_free(tmpctx);
return ret;
}
@@ -663,15 +669,27 @@ static int sdap_save_group(TALLOC_CTX *memctx,
gid_t gid;
int ret;
char *usn_value = NULL;
+ TALLOC_CTX *tmpctx = NULL;
- ret = sysdb_attrs_get_el(attrs,
- opts->group_map[SDAP_AT_GROUP_NAME].sys_name, &el);
- if (ret) goto fail;
- if (el->num_values == 0) {
- ret = EINVAL;
+ tmpctx = talloc_new(memctx);
+ if (!tmpctx) {
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ group_attrs = sysdb_new_attrs(tmpctx);
+ if (group_attrs == NULL) {
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ ret = sysdb_attrs_primary_name(ctx, attrs,
+ opts->group_map[SDAP_AT_GROUP_NAME].name,
+ &name);
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to save the group - entry has no name attribute\n"));
goto fail;
}
- name = (const char *)el->values[0].data;
ret = sysdb_attrs_get_uint32_t(attrs,
opts->group_map[SDAP_AT_GROUP_GID].sys_name,
@@ -691,12 +709,6 @@ static int sdap_save_group(TALLOC_CTX *memctx,
goto fail;
}
- group_attrs = sysdb_new_attrs(memctx);
- if (!group_attrs) {
- ret = ENOMEM;
- goto fail;
- }
-
ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &el);
if (ret) {
goto fail;
@@ -707,7 +719,7 @@ static int sdap_save_group(TALLOC_CTX *memctx,
DEBUG(7, ("Adding original DN [%s] to attributes of [%s].\n",
el->values[0].data, name));
ret = sysdb_attrs_add_string(group_attrs, SYSDB_ORIG_DN,
- (const char *)el->values[0].data);
+ (const char *) el->values[0].data);
if (ret) {
goto fail;
}
@@ -745,7 +757,7 @@ static int sdap_save_group(TALLOC_CTX *memctx,
if (ret) {
goto fail;
}
- usn_value = talloc_strdup(memctx, (const char*)el->values[0].data);
+ usn_value = talloc_strdup(tmpctx, (const char*)el->values[0].data);
if (!usn_value) {
ret = ENOMEM;
goto fail;
@@ -786,20 +798,24 @@ static int sdap_save_group(TALLOC_CTX *memctx,
DEBUG(6, ("Storing info for group %s\n", name));
- ret = sysdb_store_group(memctx, ctx, dom,
+ ret = sysdb_store_group(group_attrs, ctx, dom,
name, gid, group_attrs,
dp_opt_get_int(opts->basic,
SDAP_ENTRY_CACHE_TIMEOUT));
if (ret) goto fail;
if (_usn_value) {
- *_usn_value = usn_value;
+ *_usn_value = talloc_steal(memctx, usn_value);
}
+ talloc_steal(memctx, group_attrs);
+ talloc_free(tmpctx);
return EOK;
fail:
- DEBUG(2, ("Failed to save user %s\n", name));
+ DEBUG(2, ("Failed to save group [%s]\n",
+ name ? name : "Unknown"));
+ talloc_free(tmpctx);
return ret;
}
@@ -820,9 +836,9 @@ static int sdap_save_grpmem(TALLOC_CTX *memctx,
const char *name;
int ret;
- ret = sysdb_attrs_get_string(attrs,
- opts->group_map[SDAP_AT_GROUP_NAME].sys_name,
- &name);
+ ret = sysdb_attrs_primary_name(ctx, attrs,
+ opts->group_map[SDAP_AT_GROUP_NAME].name,
+ &name);
if (ret != EOK) {
goto fail;
}
@@ -1842,6 +1858,7 @@ static void sdap_nested_done(struct tevent_req *subreq)
/* ==Save-fake-group-list=====================================*/
static errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
+ struct sdap_options *opts,
struct sss_domain_info *dom,
char **groupnames,
struct sysdb_attrs **ldap_groups,
@@ -1905,10 +1922,10 @@ static errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
for (i=0; missing[i]; i++) {
/* The group is not in sysdb, need to add a fake entry */
for (ai=0; ai < ldap_groups_count; ai++) {
- ret = sysdb_attrs_get_string(ldap_groups[ai],
- SYSDB_NAME,
- &name);
- if (ret) {
+ ret = sysdb_attrs_primary_name(sysdb, ldap_groups[ai],
+ opts->group_map[SDAP_AT_GROUP_NAME].name,
+ &name);
+ if (ret != EOK) {
DEBUG(1, ("The group has no name attribute\n"));
goto fail;
}
@@ -2134,8 +2151,9 @@ static void sdap_initgr_rfc2307_process(struct tevent_req *subreq)
* member of but that are not cached in sysdb
*/
if (add_groups && add_groups[0]) {
- ret = sdap_add_incomplete_groups(state->sysdb, state->dom,
- add_groups, ldap_groups, count);
+ ret = sdap_add_incomplete_groups(state->sysdb, state->opts,
+ state->dom, add_groups,
+ ldap_groups, count);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
@@ -2214,7 +2232,9 @@ static struct tevent_req *sdap_initgr_nested_send(TALLOC_CTX *memctx,
state->grp_attrs = grp_attrs;
state->op = NULL;
- ret = sysdb_attrs_get_string(user, SYSDB_NAME, &state->username);
+ ret = sysdb_attrs_primary_name(sysdb, user,
+ opts->user_map[SDAP_AT_USER_NAME].name,
+ &state->username);
if (ret != EOK) {
DEBUG(1, ("User entry had no username\n"));
talloc_free(req);
@@ -2816,11 +2836,12 @@ static struct tevent_req *sdap_nested_group_process_send(
*/
key.type = HASH_KEY_STRING;
- ret = sysdb_attrs_get_string(
- group,
- opts->group_map[SDAP_AT_GROUP_NAME].sys_name,
- &groupname);
- if (ret != EOK) goto immediate;
+ ret = sysdb_attrs_primary_name(sysdb, group,
+ opts->group_map[SDAP_AT_GROUP_NAME].name,
+ &groupname);
+ if (ret != EOK) {
+ goto immediate;
+ }
key.str = talloc_strdup(state, groupname);
if (!key.str) {
@@ -3784,8 +3805,11 @@ static errno_t rfc2307bis_nested_groups_step(struct tevent_req *req)
goto error;
}
- ret = sysdb_attrs_get_string(state->groups[state->group_iter],
- SYSDB_NAME, &name);
+ ret = sysdb_attrs_primary_name(
+ state->sysdb,
+ state->groups[state->group_iter],
+ state->opts->group_map[SDAP_AT_GROUP_NAME].name,
+ &name);
if (ret != EOK) {
goto error;
}
@@ -3824,7 +3848,8 @@ static errno_t rfc2307bis_nested_groups_step(struct tevent_req *req)
DEBUG(6, ("Saving incomplete group [%s] to the sysdb\n",
groupnamelist[0]));
- ret = sdap_add_incomplete_groups(state->sysdb, state->dom, groupnamelist,
+ ret = sdap_add_incomplete_groups(state->sysdb, state->opts,
+ state->dom, groupnamelist,
grouplist, 1);
if (ret != EOK) {
goto error;
@@ -4033,12 +4058,17 @@ static errno_t rfc2307bis_nested_groups_update_sysdb(
}
in_transaction = true;
- ret = sysdb_attrs_get_string(state->groups[state->group_iter],
- SYSDB_NAME, &name);
+ ret = sysdb_attrs_primary_name(
+ state->sysdb,
+ state->groups[state->group_iter],
+ state->opts->group_map[SDAP_AT_GROUP_NAME].name,
+ &name);
if (ret != EOK) {
goto error;
}
+ DEBUG(6, ("Processing group [%s]\n", name));
+
attrs = talloc_array(tmp_ctx, const char *, 2);
if (!attrs) {
ret = ENOMEM;