On Thu, May 10, 2012 at 10:57:23PM +0200, Jan Zeleny wrote:
Simo Sorce <simo(a)redhat.com> wrote:
> On Fri, 2012-05-04 at 14:30 +0200, Jan Zelený wrote:
> > Done. We have to proceed with the approach now, as the basic concept
> > of ghost
> > members shifted a little bit in coparison with the original patch set.
> > Ghost
> > attribute now co-exists with the memberuid, they don't overlap on any
> > level
> > whatsoever.
>
> One comment here.
> With either the previous or current code I am having some difficulty
> determining if the ghost attributes (ane memberuid with the previous
> approach) of groups are appropriately handled if ghost groups should
> change after a new group lookup.
>
> Assume a user is never actually resolved, but is deleted or renamed in
> the LDAP server. Are we properly handling updating the relative ghost
> group all around ?
>
> It would be nice to see a unit test to check this behavior.
>
> The issue is connected to the way you implemented removing the ghost
> attribute for the user name (and its aliases) in patch 120.
> I have the impression that if by the time the real user is looked up it
> has changed (say it has one more alias) that the operation may fail as
> not ghost entry with the 'new' alias is found so the delete operation
> may fail due to the value not being in there.
>
> The delete operation in that case may need to be split into a
> looks/match/delete operation as a fallback (doing it by default would
> probably kill a bit performances so perhaps a fallback case is better).
>
> Simo.
Ok, here goes another set. This issue should be addressed now. I didn't make
the test suite part but I tested the behavior and it works as expected.
The other issue (member count returned to client) is addressed as well.
Jan
Sorry it took so long to get back to the patchset.
Can you rebase the patches on top of current master?
Can you move the src/providers/ldap/sdap_async_groups.c hunk from the
last patch to the LDAP patch? The LDAP patch doesn't compile without it
(I tried to do a partial review but couldn't compile the patches unless
the last one was applied)
From 48a09ace701e3de727912accd399187e052e795b Mon Sep 17 00:00:00
2001
From: Jan Zeleny <jzeleny(a)redhat.com>
Date: Mon, 23 Apr 2012 04:45:29 -0400
Subject: [PATCH 01/10] Ghost members - add the ghost attribute to sysdb
---
src/db/sysdb.h | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index a0d176ec7f9c04b467caf7b2c38ffc6fb263497b..9e7d3c5ca2b584ac306891cbec34d63132649e0f
100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -68,6 +68,7 @@
#define SYSDB_MEMBER "member"
#define SYSDB_MEMBERUID "memberUid"
+#define SYSDB_GHOST "ghost"
#define SYSDB_POSIX "isPosix"
#define SYSDB_USER_CATEGORY "userCategory"
#define SYSDB_HOST_CATEGORY "hostCategory"
@@ -167,6 +168,7 @@
NULL}
#define SYSDB_GRSRC_ATTRS {SYSDB_NAME, SYSDB_GIDNUM, \
SYSDB_MEMBERUID, \
+ SYSDB_GHOST, \
SYSDB_DEFAULT_ATTRS, \
NULL}
#define SYSDB_GRPW_ATTRS {SYSDB_NAME, SYSDB_UIDNUM, \
--
1.7.7.6
From 96039ae40cd4c61bd2f78f8a23c3b706cbf90749 Mon Sep 17 00:00:00
2001
From: Jan Zeleny <jzeleny(a)redhat.com>
Date: Mon, 23 Apr 2012 04:46:33 -0400
Subject: [PATCH 02/10] Ghost members - support in LDAP provider
The original approach was to store name and original DN in an object in
sysdb. When later referenced as member of a group, it was retrieved by
its original DN and the correct information about its sysdb DN was
stored in the group object which referenced it.
The new approach doesn't use fake user objects, therefore this
information has to be reached differently when constructing group
memberships. The approach is to store all users to a hash table where
original DN is used as the key and username as value. When constructing
group memberships, the name is retrieved from this hash table instead of
sysdb. This hash table is constructed when retrieving user objects from
LDAP server - if the user is not present in sysdb, it is automatically
stored in the hash table.
Another situation is for rfc2307. Because there is no nesting there, we
can construct the SYSDB_GHOST attribute directly and therefore don't
need a hash table of ghost users.
---
src/providers/ldap/sdap_async_groups.c | 472 +++++++++++++++++++-------------
1 files changed, 287 insertions(+), 185 deletions(-)
diff --git a/src/providers/ldap/sdap_async_groups.c
b/src/providers/ldap/sdap_async_groups.c
index 361525037eb270462251fe03d0c5e1df63de73f4..a3cf4d05606559409f3bd9ab20aeae76438a508d
100644
--- a/src/providers/ldap/sdap_async_groups.c
+++ b/src/providers/ldap/sdap_async_groups.c
@@ -96,12 +96,17 @@ static int sdap_fill_memberships(struct sysdb_attrs *group_attrs,
struct sysdb_ctx *ctx,
struct sdap_options *opts,
struct sss_domain_info *domain,
+ hash_table_t *ghosts,
struct ldb_val *values,
int num_values)
{
struct ldb_message_element *el;
- int i, j;
+ struct ldb_message_element *ghostel;
+ int i, j, k;
int ret;
+ errno_t hret;
+ hash_key_t key;
+ hash_value_t value;
ret = sysdb_attrs_get_el(group_attrs, SYSDB_MEMBER, &el);
if (ret) {
@@ -116,29 +121,76 @@ static int sdap_fill_memberships(struct sysdb_attrs *group_attrs,
goto done;
}
- for (i = 0, j = el->num_values; i < num_values; i++) {
+ ret = sysdb_attrs_get_el(group_attrs, SYSDB_GHOST, &ghostel);
+ if (ret) {
+ goto done;
+ }
- /* sync search entry with this as origDN */
- ret = sdap_find_entry_by_origDN(el->values, ctx, domain,
- (char *)values[i].data,
- (char **)&el->values[j].data);
+ if (ghostel->num_values == 0) {
+ /* Element was probably newly created, look for "member" again */
+ ret = sysdb_attrs_get_el(group_attrs, SYSDB_MEMBER, &el);
if (ret != EOK) {
- if (ret != ENOENT) {
+ goto done;
+ }
+ }
+
+
+ /* Just allocate both big enough to contain all members for now */
+ ghostel->values = talloc_realloc(group_attrs, ghostel->values, struct
ldb_val,
+ ghostel->num_values + num_values);
+ if (!ghostel->values) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ j = el->num_values;
+ k = ghostel->num_values;
+ for (i = 0; i < num_values; i++) {
+ if (ghosts == NULL) {
+ hret = HASH_ERROR_KEY_NOT_FOUND;
+ } else {
+ key.type = HASH_KEY_STRING;
+ key.str = (char *)values[i].data;
+ hret = hash_lookup(ghosts, &key, &value);
+ }
+
+ if (hret == HASH_ERROR_KEY_NOT_FOUND) {
+ /* sync search entry with this as origDN */
+ ret = sdap_find_entry_by_origDN(el->values, ctx, domain,
+ (char *)values[i].data,
+ (char **)&el->values[j].data);
+ if (ret != EOK) {
+ /* This should never return ENOENT
+ * -> fail if it does
+ */
goto done;
}
- DEBUG(7, (" member #%d (%s): not found!\n",
- i, (char *)values[i].data));
- } else {
DEBUG(7, (" member #%d (%s): [%s]\n",
i, (char *)values[i].data,
(char *)el->values[j].data));
el->values[j].length = strlen((char *)el->values[j].data);
j++;
+ } else if (hret != HASH_SUCCESS) {
+ ret = EFAULT;
+ goto done;
+ } else {
+ DEBUG(SSSDBG_TRACE_FUNC, (" member #%d (%s): ghost!\n",
+ i, (char *)values[i].data));
+ ghostel->values[k].data = (uint8_t *)talloc_strdup(ghostel->values,
+ value.ptr);
+ if (ghostel->values[k].data == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ ghostel->values[k].length = strlen((char *)ghostel->values[k].data);
+ k++;
}
}
el->num_values = j;
+ ghostel->num_values = k;
+
ret = EOK;
done:
@@ -186,6 +238,7 @@ static int sdap_save_group(TALLOC_CTX *memctx,
struct sss_domain_info *dom,
struct sysdb_attrs *attrs,
bool populate_members,
+ hash_table_t *ghosts,
char **_usn_value,
time_t now)
{
@@ -193,12 +246,14 @@ static int sdap_save_group(TALLOC_CTX *memctx,
struct sysdb_attrs *group_attrs;
const char *name = NULL;
gid_t gid;
- int ret;
+ int ret, cnt, i;
char *usn_value = NULL;
TALLOC_CTX *tmpctx = NULL;
bool posix_group;
bool use_id_mapping = dp_opt_get_bool(opts->basic, SDAP_ID_MAPPING);
char *sid_str;
+ hash_key_t key;
+ hash_value_t value;
tmpctx = talloc_new(memctx);
if (!tmpctx) {
@@ -321,16 +376,58 @@ static int sdap_save_group(TALLOC_CTX *memctx,
if (populate_members) {
struct ldb_message_element *el1;
+ struct ldb_message_element *gh;
ret = sysdb_attrs_get_el(attrs,
opts->group_map[SDAP_AT_GROUP_MEMBER].sys_name, &el1);
if (ret != EOK) {
goto fail;
}
+
ret = sysdb_attrs_get_el(group_attrs, SYSDB_MEMBER, &el);
if (ret != EOK) {
goto fail;
}
el->values = el1->values;
el->num_values = el1->num_values;
+
+ ret = sysdb_attrs_get_el(attrs, SYSDB_GHOST, &gh);
+ if (ret != EOK) {
+ goto fail;
+ }
+ ret = sysdb_attrs_get_el(group_attrs, SYSDB_GHOST, &el);
+ if (ret != EOK) {
+ goto fail;
+ }
+ el->values = gh->values;
+ el->num_values = gh->num_values;
+
+ /* Now process RFC2307bis ghost hash table */
+ if (ghosts != NULL) {
+ cnt = el->num_values + el1->num_values;
+ el->values = talloc_realloc(attrs, el->values, struct ldb_val,
+ cnt);
+ if (el->values == NULL) {
+ ret = ENOMEM;
+ goto fail;
+ }
+ for (i = 0; i < el1->num_values; i++) {
+ key.type = HASH_KEY_STRING;
+ key.str = (char *)el1->values[i].data;
+ ret = hash_lookup(ghosts, &key, &value);
+ if (ret == HASH_ERROR_KEY_NOT_FOUND) {
+ continue;
+ } else if (ret != HASH_SUCCESS) {
+ ret = EFAULT;
+ goto fail;
+ }
+ el->values[el->num_values].data = (uint8_t
*)talloc_strdup(el->values, value.ptr);
+ if (el->values[el->num_values].data == NULL) {
+ ret = ENOMEM;
+ goto fail;
+ }
+ el->values[el->num_values].length = strlen(value.ptr)+1;
+ el->num_values++;
+ }
+ }
}
ret = sdap_save_all_names(name, attrs, !dom->case_sensitive, group_attrs);
@@ -373,6 +470,7 @@ static int sdap_save_grpmem(TALLOC_CTX *memctx,
struct sdap_options *opts,
struct sss_domain_info *dom,
struct sysdb_attrs *attrs,
+ hash_table_t *ghosts,
time_t now)
{
struct ldb_message_element *el;
@@ -405,6 +503,7 @@ static int sdap_save_grpmem(TALLOC_CTX *memctx,
}
ret = sdap_fill_memberships(group_attrs, ctx, opts, dom,
+ ghosts,
el->values, el->num_values);
if (ret) {
goto fail;
@@ -434,6 +533,7 @@ static int sdap_save_groups(TALLOC_CTX *memctx,
struct sysdb_attrs **groups,
int num_groups,
bool populate_members,
+ hash_table_t *ghosts,
char **_usn_value)
{
TALLOC_CTX *tmpctx;
@@ -487,7 +587,8 @@ static int sdap_save_groups(TALLOC_CTX *memctx,
/* if 2 pass savemembers = false */
ret = sdap_save_group(tmpctx, sysdb,
opts, dom, groups[i],
- populate_members, &usn_value, now);
+ populate_members, ghosts,
+ &usn_value, now);
/* Do not fail completely on errors.
* Just report the failure to save and go on */
@@ -520,7 +621,8 @@ static int sdap_save_groups(TALLOC_CTX *memctx,
for (i = 0; i < nsaved_groups; i++) {
- ret = sdap_save_grpmem(tmpctx, sysdb, opts, dom, saved_groups[i], now);
+ ret = sdap_save_grpmem(tmpctx, sysdb, opts, dom, saved_groups[i],
+ ghosts, now);
/* Do not fail completely on errors.
* Just report the failure to save and go on */
if (ret) {
@@ -557,13 +659,12 @@ struct sdap_process_group_state {
struct sysdb_ctx *sysdb;
struct sysdb_attrs *group;
- struct sysdb_attrs **new_members;
struct ldb_message_element* sysdb_dns;
+ struct ldb_message_element* ghost_dns;
char **queued_members;
int queue_len;
const char **attrs;
const char *filter;
- size_t member_idx;
size_t queue_idx;
size_t count;
size_t check_count;
@@ -578,7 +679,32 @@ static int sdap_process_group_members_2307bis(struct tevent_req
*req,
struct sdap_process_group_state *state,
struct ldb_message_element *memberel);
static int sdap_process_group_members_2307(struct sdap_process_group_state *state,
- struct ldb_message_element *memberel);
+ struct ldb_message_element *memberel,
+ struct ldb_message_element *ghostel);
+
+static errno_t sdap_process_group_create_dns(TALLOC_CTX *mem_ctx,
+ size_t num_values,
+ struct ldb_message_element **_dns)
+{
+ struct ldb_message_element *dns;
+
+ dns = talloc(mem_ctx, struct ldb_message_element);
+ if (dns == NULL) {
+ return ENOMEM;
+ }
+
+ dns->num_values = 0;
+ dns->values = talloc_array(dns, struct ldb_val,
+ num_values);
+ if (dns->values == NULL) {
+ talloc_zfree(dns);
+ return ENOMEM;
+ }
+
+ *_dns = dns;
+
+ return EOK;
+}
struct tevent_req *sdap_process_group_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
@@ -590,6 +716,7 @@ struct tevent_req *sdap_process_group_send(TALLOC_CTX *memctx,
bool enumeration)
{
struct ldb_message_element *el;
+ struct ldb_message_element *ghostel;
struct sdap_process_group_state *grp_state;
struct tevent_req *req = NULL;
const char **attrs;
@@ -621,8 +748,6 @@ struct tevent_req *sdap_process_group_send(TALLOC_CTX *memctx,
grp_state->sysdb = sysdb;
grp_state->group = group;
grp_state->check_count = 0;
- grp_state->new_members = NULL;
- grp_state->member_idx = 0;
grp_state->queue_idx = 0;
grp_state->queued_members = NULL;
grp_state->queue_len = 0;
@@ -644,27 +769,47 @@ struct tevent_req *sdap_process_group_send(TALLOC_CTX *memctx,
goto done;
}
- grp_state->sysdb_dns = talloc(grp_state, struct ldb_message_element);
- if (!grp_state->sysdb_dns) {
- talloc_zfree(req);
- return NULL;
- }
- grp_state->sysdb_dns->values = talloc_array(grp_state, struct ldb_val,
- el->num_values);
- if (!grp_state->sysdb_dns->values) {
- talloc_zfree(req);
- return NULL;
- }
- grp_state->sysdb_dns->num_values = 0;
+ ret = sysdb_attrs_get_el(group,
+ SYSDB_GHOST,
+ &ghostel);
+ if (ret) {
+ goto done;
+ }
+
+ if (ghostel->num_values == 0) {
+ /* Element was probably newly created, look for "member" again */
+ ret = sysdb_attrs_get_el(group,
+ opts->group_map[SDAP_AT_GROUP_MEMBER].sys_name,
+ &el);
+ if (ret != EOK) {
+ goto done;
+ }
+ }
+
+
+ ret = sdap_process_group_create_dns(grp_state, el->num_values,
+ &grp_state->sysdb_dns);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ ret = sdap_process_group_create_dns(grp_state, el->num_values,
+ &grp_state->ghost_dns);
+ if (ret != EOK) {
+ goto done;
+ }
switch (opts->schema_type) {
case SDAP_SCHEMA_RFC2307:
- ret = sdap_process_group_members_2307(grp_state, el);
+ ret = sdap_process_group_members_2307(grp_state, el, ghostel);
break;
case SDAP_SCHEMA_IPA_V1:
case SDAP_SCHEMA_AD:
case SDAP_SCHEMA_RFC2307BIS:
+ /* Note that this code branch will be used only if
+ * ldap_nesting_level = 0 is set in config file
+ */
ret = sdap_process_group_members_2307bis(req, grp_state, el);
break;
@@ -815,12 +960,6 @@ sdap_process_group_members_2307bis(struct tevent_req *req,
memberel->num_values = state->sysdb_dns->num_values;
} else {
state->count = state->check_count;
- state->new_members = talloc_zero_array(state,
- struct sysdb_attrs *,
- state->count + 1);
- if (!state->new_members) {
- return ENOMEM;
- }
ret = EBUSY;
}
@@ -828,41 +967,35 @@ sdap_process_group_members_2307bis(struct tevent_req *req,
}
static int
-sdap_add_group_member_2307(struct sdap_process_group_state *state,
+sdap_add_group_member_2307(struct ldb_message_element *sysdb_dns,
+ struct sss_domain_info *dom,
const char *username)
{
- char *strdn;
-
- strdn = sysdb_user_strdn(state->sysdb_dns->values,
- state->dom->name, username);
- if (!strdn) {
+ sysdb_dns->values[sysdb_dns->num_values].data =
+ (uint8_t *) talloc_strdup(sysdb_dns->values, username);
+ if (sysdb_dns->values[sysdb_dns->num_values].data == NULL) {
return ENOMEM;
}
-
- state->sysdb_dns->values[state->sysdb_dns->num_values].data =
- (uint8_t *) strdn;
- state->sysdb_dns->values[state->sysdb_dns->num_values].length =
- strlen(strdn);
- state->sysdb_dns->num_values++;
+ sysdb_dns->values[sysdb_dns->num_values].length =
+ strlen(username);
+ sysdb_dns->num_values++;
return EOK;
}
static int
sdap_process_missing_member_2307(struct sdap_process_group_state *state,
- char *member_name, bool *in_transaction,
- time_t now)
+ char *member_name, time_t now)
{
- int ret, sret;
+ int ret;
TALLOC_CTX *tmp_ctx;
const char *filter;
const char *username;
+ const char *user_dn;
size_t count;
struct ldb_message **msgs = NULL;
static const char *attrs[] = { SYSDB_NAME, NULL };
- if (!in_transaction) return EINVAL;
-
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) return ENOMEM;
@@ -870,7 +1003,7 @@ sdap_process_missing_member_2307(struct sdap_process_group_state
*state,
filter = talloc_asprintf(tmp_ctx, "(%s=%s)", SYSDB_NAME_ALIAS,
member_name);
if (!filter) {
ret = ENOMEM;
- goto fail;
+ goto done;
}
ret = sysdb_search_users(tmp_ctx, state->sysdb, filter,
@@ -881,74 +1014,51 @@ sdap_process_missing_member_2307(struct sdap_process_group_state
*state,
if (count != 1) {
DEBUG(1, ("More than one entry with this alias?\n"));
ret = EIO;
- goto fail;
+ goto done;
}
/* fill username with primary name */
username = ldb_msg_find_attr_as_string(msgs[0], SYSDB_NAME, NULL);
- goto done;
- } else if (ret != EOK && ret != ENOENT) {
+ if (username == NULL) {
+ ret = EINVAL;
+ DEBUG(SSSDBG_MINOR_FAILURE, ("Inconsistent sysdb: user "
+ "without primary name?\n"));
+ goto done;
+ }
+ user_dn = sysdb_user_strdn(tmp_ctx, state->dom->name, username);
+ if (username == NULL) {
+ return ENOMEM;
+ }
+
+ ret = sdap_add_group_member_2307(state->sysdb_dns, state->dom, user_dn);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Could not add group member %s\n",
username));
+ }
+ } else if (ret == ENOENT || count == 0) {
+ /* The entry really does not exist, add a ghost */
+ DEBUG(SSSDBG_TRACE_FUNC, ("Adding a ghost entry\n"));
+ ret = sdap_add_group_member_2307(state->ghost_dns, state->dom,
member_name);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Could not add group member %s\n",
member_name));
+ }
+ } else {
ret = EIO;
- goto fail;
}
- username = member_name;
- /* The entry really does not exist, add a fake entry */
- DEBUG(7, ("Adding a dummy entry\n"));
-
- if (!*in_transaction) {
- ret = sysdb_transaction_start(state->sysdb);
- if (ret != EOK) {
- DEBUG(1, ("Cannot start sysdb transaction: [%d]: %s\n",
- ret, strerror(ret)));
- return ret;
- }
- *in_transaction = true;
- }
-
- ret = sysdb_add_fake_user(state->sysdb, username, NULL, now);
- if (ret != EOK) {
- DEBUG(1, ("Cannot store fake user entry: [%d]: %s\n",
- ret, strerror(ret)));
- goto fail;
- }
-
- /*
- * Convert the just received DN into the corresponding sysdb DN
- * for saving into member attribute of the group
- */
done:
- ret = sdap_add_group_member_2307(state, username);
- if (ret != EOK) {
- DEBUG(1, ("Could not add group member %s\n", username));
- goto fail;
- }
-
talloc_free(tmp_ctx);
- return EOK;
-fail:
- talloc_free(tmp_ctx);
- if (*in_transaction) {
- sret = sysdb_transaction_cancel(state->sysdb);
- if (sret == EOK) {
- *in_transaction = false;
- } else {
- DEBUG(0, ("Unable to cancel transaction! [%d][%s]\n",
- sret, strerror(sret)));
- }
- }
return ret;
}
static int
sdap_process_group_members_2307(struct sdap_process_group_state *state,
- struct ldb_message_element *memberel)
+ struct ldb_message_element *memberel,
+ struct ldb_message_element *ghostel)
{
struct ldb_message *msg;
- bool in_transaction = false;
char *member_name;
+ char *userdn;
int ret;
- errno_t sret;
time_t now;
int i;
@@ -968,7 +1078,12 @@ sdap_process_group_members_2307(struct sdap_process_group_state
*state,
*/
DEBUG(7, ("Member already cached in sysdb: %s\n", member_name));
- ret = sdap_add_group_member_2307(state, member_name);
+ userdn = sysdb_user_strdn(state->sysdb_dns, state->dom->name,
member_name);
+ if (userdn == NULL) {
+ return ENOMEM;
+ }
+
+ ret = sdap_add_group_member_2307(state->sysdb_dns, state->dom,
userdn);
if (ret != EOK) {
DEBUG(1, ("Could not add member %s into sysdb\n",
member_name));
goto done;
@@ -978,8 +1093,7 @@ sdap_process_group_members_2307(struct sdap_process_group_state
*state,
DEBUG(7, ("member #%d (%s): not found in sysdb\n",
i, member_name));
- ret = sdap_process_missing_member_2307(state, member_name,
- &in_transaction, now);
+ ret = sdap_process_missing_member_2307(state, member_name, now);
if (ret != EOK) {
DEBUG(1, ("Error processing missing member #%d (%s):\n",
i, member_name));
@@ -992,30 +1106,15 @@ sdap_process_group_members_2307(struct sdap_process_group_state
*state,
}
}
- /* sdap_process_missing_member_2307 starts transaction */
- if (in_transaction) {
- ret = sysdb_transaction_commit(state->sysdb);
- if (ret) {
- DEBUG(2, ("Cannot commit sysdb transaction\n"));
- goto done;
- }
- in_transaction = false;
- }
-
ret = EOK;
talloc_free(memberel->values);
memberel->values = talloc_steal(state->group,
state->sysdb_dns->values);
memberel->num_values = state->sysdb_dns->num_values;
+ talloc_free(ghostel->values);
+ ghostel->values = talloc_steal(state->group, state->ghost_dns->values);
+ ghostel->num_values = state->ghost_dns->num_values;
done:
- if (in_transaction) {
- /* If the transaction is still active here, we need to cancel it */
- sret = sysdb_transaction_cancel(state->sysdb);
- if (sret != EOK) {
- DEBUG(0, ("Unable to cancel transaction! [%d][%s]\n",
- sret, strerror(sret)));
- }
- }
return ret;
}
@@ -1029,8 +1128,7 @@ static void sdap_process_group_members(struct tevent_req *subreq)
struct sdap_process_group_state *state =
tevent_req_data(req, struct sdap_process_group_state);
struct ldb_message_element *el;
- struct ldb_dn *dn;
- char* dn_string;
+ uint8_t* name_string;
state->check_count--;
DEBUG(9, ("Members remaining: %d\n", state->check_count));
@@ -1055,31 +1153,12 @@ static void sdap_process_group_members(struct tevent_req
*subreq)
goto next;
}
- /*
- * Convert the just received DN into the corresponding sysdb DN
- * for later usage by sdap_save_groups()
- */
- dn = sysdb_user_dn(state->sysdb, state, state->dom->name,
- (char*)el[0].values[0].data);
- if (!dn) {
- tevent_req_error(req, ENOMEM);
- return;
- }
-
- dn_string = ldb_dn_alloc_linearized(state->group, dn);
- if (!dn_string) {
- tevent_req_error(req, ENOMEM);
- return;
- }
-
- state->sysdb_dns->values[state->sysdb_dns->num_values].data =
- (uint8_t*)dn_string;
- state->sysdb_dns->values[state->sysdb_dns->num_values].length =
- strlen(dn_string);
- state->sysdb_dns->num_values++;
-
- state->new_members[state->member_idx] = usr_attrs[0];
- state->member_idx++;
+ name_string = el[0].values[0].data;
+ state->ghost_dns->values[state->ghost_dns->num_values].data =
+ talloc_steal(state->ghost_dns->values, name_string);
+ state->ghost_dns->values[state->ghost_dns->num_values].length =
+ strlen((char *)name_string);
+ state->ghost_dns->num_values++;
next:
if (ret) {
@@ -1110,21 +1189,13 @@ next:
}
if (state->check_count == 0) {
- ret = sdap_save_users(state, state->sysdb,
- state->dom, state->opts,
- state->new_members, state->count, NULL);
- if (ret) {
- DEBUG(2, ("Failed to store users.\n"));
- tevent_req_error(req, ret);
- return;
- }
-
/*
* To avoid redundant sysdb lookups, populate the "member" attribute
* of the group entry with the sysdb DNs of the members.
*/
ret = sysdb_attrs_get_el(state->group,
- state->opts->group_map[SDAP_AT_GROUP_MEMBER].sys_name, &el);
+ state->opts->group_map[SDAP_AT_GROUP_MEMBER].sys_name,
+ &el);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
("Failed to get the group member attribute [%d]: %s\n",
@@ -1134,6 +1205,14 @@ next:
}
el->values = talloc_steal(state->group, state->sysdb_dns->values);
el->num_values = state->sysdb_dns->num_values;
+
+ ret = sysdb_attrs_get_el(state->group, SYSDB_GHOST, &el);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+ el->values = talloc_steal(state->group, state->ghost_dns->values);
+ el->num_values = state->ghost_dns->num_values;
DEBUG(9, ("Processed Group - Done\n"));
tevent_req_done(req);
}
@@ -1446,7 +1525,8 @@ static void sdap_get_groups_process(struct tevent_req *subreq)
DEBUG(9, ("Saving groups without members first "
"to allow unrolling of nested groups.\n"));
ret = sdap_save_groups(state, state->sysdb, state->dom, state->opts,
- state->groups, state->count, false, NULL);
+ state->groups, state->count, false,
+ NULL, NULL);
if (ret) {
DEBUG(2, ("Failed to store groups.\n"));
tevent_req_error(req, ret);
@@ -1497,7 +1577,7 @@ static void sdap_get_groups_done(struct tevent_req *subreq)
DEBUG(9, ("All groups processed\n"));
ret = sdap_save_groups(state, state->sysdb, state->dom, state->opts,
- state->groups, state->count, true,
+ state->groups, state->count, true, NULL,
&state->higher_usn);
if (ret) {
DEBUG(2, ("Failed to store groups.\n"));
@@ -1530,10 +1610,12 @@ int sdap_get_groups_recv(struct tevent_req *req,
return EOK;
}
-static errno_t sdap_nested_group_populate_users(struct sysdb_ctx *sysdb,
+static errno_t sdap_nested_group_populate_users(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
struct sdap_options *opts,
struct sysdb_attrs **users,
- int num_users);
+ int num_users,
+ hash_table_t **_ghosts);
static void sdap_nested_done(struct tevent_req *subreq)
{
@@ -1546,6 +1628,7 @@ static void sdap_nested_done(struct tevent_req *subreq)
bool in_transaction = false;
struct sysdb_attrs **users = NULL;
struct sysdb_attrs **groups = NULL;
+ hash_table_t *ghosts;
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
struct sdap_get_groups_state *state = tevent_req_data(req,
@@ -1608,14 +1691,15 @@ static void sdap_nested_done(struct tevent_req *subreq)
}
in_transaction = true;
- ret = sdap_nested_group_populate_users(state->sysdb, state->opts,
- users, user_count);
+ ret = sdap_nested_group_populate_users(state, state->sysdb, state->opts,
+ users, user_count, &ghosts);
if (ret != EOK) {
goto fail;
}
ret = sdap_save_groups(state, state->sysdb, state->dom, state->opts,
- groups, group_count, false, &state->higher_usn);
+ groups, group_count, false, ghosts,
+ &state->higher_usn);
if (ret != EOK) {
goto fail;
}
@@ -1641,10 +1725,12 @@ fail:
tevent_req_error(req, ret);
}
-static errno_t sdap_nested_group_populate_users(struct sysdb_ctx *sysdb,
+static errno_t sdap_nested_group_populate_users(TALLOC_CTX *mem_ctx,
+ struct sysdb_ctx *sysdb,
struct sdap_options *opts,
struct sysdb_attrs **users,
- int num_users)
+ int num_users,
+ hash_table_t **_ghosts)
{
int i;
errno_t ret, sret;
@@ -1659,24 +1745,36 @@ static errno_t sdap_nested_group_populate_users(struct sysdb_ctx
*sysdb,
const char *sysdb_name;
struct sysdb_attrs *attrs;
static const char *search_attrs[] = { SYSDB_NAME, NULL };
+ hash_table_t *ghosts;
+ hash_key_t key;
+ hash_value_t value;
size_t count;
- time_t now;
+
+ if (_ghosts == NULL) {
+ return EINVAL;
+ }
if (num_users == 0) {
/* Nothing to do if there are no users */
+ *_ghosts = NULL;
return EOK;
}
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) return ENOMEM;
+ ret = sss_hash_create(tmp_ctx, num_users, &ghosts);
+ if (ret != HASH_SUCCESS) {
+ ret = ENOMEM;
+ goto done;
+ }
+
ret = sysdb_transaction_start(sysdb);
if (ret) {
DEBUG(1, ("Failed to start transaction!\n"));
goto done;
}
- now = time(NULL);
for (i = 0; i < num_users; i++) {
ret = sysdb_attrs_primary_name(sysdb, users[i],
opts->user_map[SDAP_AT_USER_NAME].name,
@@ -1744,15 +1842,17 @@ static errno_t sdap_nested_group_populate_users(struct sysdb_ctx
*sysdb,
ret = sysdb_set_user_attr(sysdb, sysdb_name, attrs, SYSDB_MOD_REP);
if (ret != EOK) goto done;
}
-
- /* If the entry does not exist add a fake user record */
- ret = sysdb_add_fake_user(sysdb, username, original_dn, now);
- if (ret != EOK) {
- DEBUG(1, ("Cannot store fake user entry, ignoring: [%d]: %s\n",
- ret, strerror(ret)));
- continue;
- } else {
- DEBUG(9, ("Added incomplete user %s!\n", username));
+ else
+ {
+ key.type = HASH_KEY_STRING;
+ key.str = discard_const(original_dn);
+ value.type = HASH_VALUE_PTR;
+ value.ptr = discard_const(username);
+ ret = hash_enter(ghosts, &key, &value);
+ if (ret != HASH_SUCCESS) {
+ ret = ENOMEM;
+ goto done;
+ }
}
}
@@ -1764,13 +1864,16 @@ static errno_t sdap_nested_group_populate_users(struct sysdb_ctx
*sysdb,
ret = EOK;
done:
- talloc_zfree(tmp_ctx);
if (ret != EOK) {
sret = sysdb_transaction_cancel(sysdb);
if (sret != EOK) {
DEBUG(2, ("Could not cancel transaction\n"));
}
+ *_ghosts = NULL;
+ } else {
+ *_ghosts = talloc_steal(mem_ctx, ghosts);
}
+ talloc_zfree(tmp_ctx);
return ret;
}
@@ -2242,7 +2345,6 @@ sdap_nested_group_check_cache(TALLOC_CTX *mem_ctx,
struct ldb_message **msgs = NULL;
char *member_dn;
uint64_t expiration;
- uint64_t create_time;
uid_t user_uid;
time_t now = time(NULL);
static const char *attrs[] = { SYSDB_CACHE_EXPIRE, SYSDB_UIDNUM,
--
1.7.7.6
From dd53be03778ab9e804d286752375292b65dc0f69 Mon Sep 17 00:00:00
2001
From: Jan Zeleny <jzeleny(a)redhat.com>
Date: Mon, 23 Apr 2012 04:47:23 -0400
Subject: [PATCH 03/10] Ghost members - support in proxy provider
---
src/providers/proxy/proxy_id.c | 14 ++++++++------
1 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/src/providers/proxy/proxy_id.c b/src/providers/proxy/proxy_id.c
index 8a8c7ca80d1b24e53c3d55d06564e719a069642a..6c78848267ff76aa1b7e1eca9fbc36ded58ca3b0
100644
--- a/src/providers/proxy/proxy_id.c
+++ b/src/providers/proxy/proxy_id.c
@@ -489,6 +489,7 @@ done:
static errno_t proxy_process_missing_users(struct sysdb_ctx *sysdb,
+ struct sysdb_attrs *group_attrs,
struct group *grp,
time_t now);
static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info *dom,
@@ -530,8 +531,8 @@ static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info
*dom,
goto done;
}
- /* Create fake users if they don't already exist */
- ret = proxy_process_missing_users(sysdb, grp, now);
+ /* Create ghost users */
+ ret = proxy_process_missing_users(sysdb, attrs, grp, now);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("Could not add missing members\n"));
goto done;
@@ -612,6 +613,7 @@ done:
}
static errno_t proxy_process_missing_users(struct sysdb_ctx *sysdb,
+ struct sysdb_attrs *group_attrs,
struct group *grp,
time_t now)
{
@@ -636,15 +638,15 @@ static errno_t proxy_process_missing_users(struct sysdb_ctx
*sysdb,
talloc_zfree(msg);
continue;
} else if (ret == ENOENT) {
- /* No entry for this user. Create a fake user */
+ /* No entry for this user. Create a ghost user */
DEBUG(SSSDBG_TRACE_LIBS,
- ("Member [%s] not cached, creating fake user entry\n",
+ ("Member [%s] not cached, creating ghost user entry\n",
grp->gr_mem[i]));
- ret = sysdb_add_fake_user(sysdb, grp->gr_mem[i], NULL, now);
+ ret = sysdb_attrs_add_string(group_attrs, SYSDB_GHOST, grp->gr_mem[i]);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE,
- ("Cannot store fake user entry: [%d]: %s\n",
+ ("Cannot store ghost user entry: [%d]: %s\n",
ret, strerror(ret)));
goto done;
}
--
1.7.7.6
From c75d6a16569fe6250b3b3659bc96961c2fdcde8e Mon Sep 17 00:00:00
2001
From: Jan Zeleny <jzeleny(a)redhat.com>
Date: Mon, 23 Apr 2012 04:49:16 -0400
Subject: [PATCH 04/10] Ghost members - modifications in sysdb
Deleted sysdb_add_fake_user():
This function is no longer used.
Modified sysdb_add_user():
When user object is added to sysdb, it is important to iterate over all
groups that might have its name or any of its aliases as ghost member
and replace this ghost membership by a real one. This will eliminate
duplicite memberships.
---
src/db/sysdb.h | 5 -
src/db/sysdb_ops.c | 256 ++++++++++++++++++++++++++++++++++------------------
2 files changed, 167 insertions(+), 94 deletions(-)
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 9e7d3c5ca2b584ac306891cbec34d63132649e0f..85dde2c4908b9c502921a82558ff09329c4052ca
100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -583,11 +583,6 @@ int sysdb_add_user(struct sysdb_ctx *sysdb,
int cache_timeout,
time_t now);
-int sysdb_add_fake_user(struct sysdb_ctx *sysdb,
- const char *name,
- const char *original_dn,
- time_t now);
-
/* Add group (only basic attrs and w/o checks) */
int sysdb_add_basic_group(struct sysdb_ctx *sysdb,
const char *name, gid_t gid);
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index bedd8cfa292cfdab2ba20260ff641730a41610b5..1bfb6c926ca73530be34d9cb6b2713a6f1e1a0d6
100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -866,9 +866,16 @@ int sysdb_add_user(struct sysdb_ctx *sysdb,
{
TALLOC_CTX *tmp_ctx;
struct ldb_message *msg;
+ struct ldb_message **groups;
+ struct ldb_message_element *alias_el;
+ size_t group_count = 0;
struct sysdb_attrs *id_attrs;
+ const char *group_attrs[] = {SYSDB_NAME, SYSDB_GHOST, NULL};
+ struct ldb_dn *tmpdn;
+ const char *userdn;
+ char *filter;
uint32_t id;
- int ret;
+ int ret, i, j;
struct sss_domain_info *domain = sysdb->domain;
@@ -977,6 +984,105 @@ int sysdb_add_user(struct sysdb_ctx *sysdb,
ret = sysdb_set_user_attr(sysdb, name, attrs, SYSDB_MOD_REP);
+ /* remove all ghost users */
+ filter = talloc_asprintf(tmp_ctx, "(|(%s=%s)", SYSDB_GHOST, name);
+ if (!filter) {
+ ret = ENOMEM;
+ goto done;
+ }
+ ret = sysdb_attrs_get_el(attrs, SYSDB_NAME_ALIAS, &alias_el);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ for (i = 0; i < alias_el->num_values; i++) {
+ filter = talloc_asprintf_append(filter, "(%s=%s)",
+ SYSDB_GHOST, alias_el->values[i].data);
+ if (filter == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ filter = talloc_asprintf_append(filter, ")");
+ if (filter == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tmpdn = sysdb_user_dn(sysdb, tmp_ctx, sysdb->domain->name, name);
+ if (!tmpdn) {
+ ERROR_OUT(ret, ENOMEM, done);
+ }
+
+ userdn = ldb_dn_get_linearized(tmpdn);
+ if (!userdn) {
+ ERROR_OUT(ret, EINVAL, done);
+ }
+
+ tmpdn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
+ SYSDB_TMPL_GROUP_BASE, sysdb->domain->name);
+ if (!tmpdn) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ /* We need to find all groups that contain this object as a ghost user
+ * and replace the ghost user there by actual member record
+ * Note that this object can be referred to either by its name or any
+ * of its aliases
+ */
+ ret = sysdb_search_entry(tmp_ctx, sysdb, tmpdn, LDB_SCOPE_SUBTREE, filter,
+ group_attrs, &group_count, &groups);
+ if (ret != EOK && ret != ENOENT) {
+ goto done;
+ }
+
+ for (i = 0; i < group_count; i++) {
+ msg = ldb_msg_new(tmp_ctx);
+ if (!msg) {
+ ERROR_OUT(ret, ENOMEM, done);
+ }
+
+ msg->dn = groups[i]->dn;
+ ret = ldb_msg_add_empty(msg, SYSDB_MEMBER, SYSDB_MOD_ADD, NULL);
+ if (ret != LDB_SUCCESS) {
+ ERROR_OUT(ret, ENOMEM, done);
+ }
+
+ ret = ldb_msg_add_fmt(msg, SYSDB_MEMBER, "%s", userdn);
+ if (ret != LDB_SUCCESS) {
+ ERROR_OUT(ret, EINVAL, done);
+ }
+
+ ret = ldb_msg_add_empty(msg, SYSDB_GHOST, SYSDB_MOD_DEL, NULL);
+ if (ret != LDB_SUCCESS) {
+ ERROR_OUT(ret, ENOMEM, done);
+ }
+ ret = ldb_msg_add_fmt(msg, SYSDB_GHOST, "%s", name);
+ if (ret != LDB_SUCCESS) {
+ ERROR_OUT(ret, EINVAL, done);
+ }
+ /* Delete aliases from the ghost attribute as well */
+ for (j = 0; j < alias_el->num_values; j++) {
+ ret = ldb_msg_add_fmt(msg, SYSDB_GHOST, "%s",
+ (char *)alias_el->values[j].data);
+ if (ret != LDB_SUCCESS) {
+ ERROR_OUT(ret, EINVAL, done);
+ }
+ }
+
+ ret = ldb_modify(sysdb->ldb, msg);
+ ret = sysdb_error_to_errno(ret);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ talloc_zfree(msg);
+ }
+
+ ret = EOK;
+
done:
if (ret == EOK) {
ret = ldb_transaction_commit(sysdb->ldb);
@@ -989,76 +1095,6 @@ done:
return ret;
}
-int sysdb_add_fake_user(struct sysdb_ctx *sysdb,
- const char *name,
- const char *original_dn,
- time_t now)
-{
- TALLOC_CTX *tmp_ctx;
- struct ldb_message *msg;
- int ret;
-
- tmp_ctx = talloc_new(NULL);
- if (!tmp_ctx) {
- return ENOMEM;
- }
-
- msg = ldb_msg_new(tmp_ctx);
- if (!msg) {
- ERROR_OUT(ret, ENOMEM, done);
- }
-
- /* user dn */
- msg->dn = sysdb_user_dn(sysdb, msg, sysdb->domain->name, name);
- if (!msg->dn) {
- ERROR_OUT(ret, ENOMEM, done);
- }
-
- ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_OBJECTCLASS, SYSDB_USER_CLASS);
- if (ret) goto done;
-
- ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, name);
- if (ret) goto done;
-
- if (!now) {
- now = time(NULL);
- }
-
- ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME,
- (unsigned long) now);
- if (ret) goto done;
-
- /* set last login so that the fake entry does not get cleaned up
- * immediately */
- ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_LAST_LOGIN,
- (unsigned long) now);
- if (ret) return ret;
-
- ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_LAST_UPDATE,
- (unsigned long) now);
- if (ret) goto done;
-
- ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CACHE_EXPIRE,
- (unsigned long) now-1);
- if (ret) goto done;
-
- if (original_dn) {
- ret = add_string(msg, LDB_FLAG_MOD_ADD,
- SYSDB_ORIG_DN, original_dn);
- if (ret) goto done;
- }
-
- ret = ldb_add(sysdb->ldb, msg);
- ret = sysdb_error_to_errno(ret);
-
-done:
- if (ret != EOK) {
- DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
- }
- talloc_zfree(tmp_ctx);
- return ret;
-}
-
/* =Add-Basic-Group-NO-CHECKS============================================= */
int sysdb_add_basic_group(struct sysdb_ctx *sysdb,
@@ -2213,8 +2249,13 @@ int sysdb_delete_user(struct sysdb_ctx *sysdb,
const char *name, uid_t uid)
{
TALLOC_CTX *tmp_ctx;
+ const char *attrs[] = {SYSDB_GHOST, NULL};
+ size_t msg_count;
+ char *filter;
+ struct ldb_message **msgs;
struct ldb_message *msg;
int ret;
+ int i;
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) {
@@ -2228,34 +2269,71 @@ int sysdb_delete_user(struct sysdb_ctx *sysdb,
ret = sysdb_search_user_by_uid(tmp_ctx, sysdb,
uid, NULL, &msg);
}
- if (ret) {
- goto fail;
- }
+ if (ret == EOK) {
+ if (name && uid) {
+ /* verify name/gid match */
+ const char *c_name;
+ uint64_t c_uid;
- if (name && uid) {
- /* verify name/gid match */
- const char *c_name;
- uint64_t c_uid;
+ c_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
+ c_uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
+ if (c_name == NULL || c_uid == 0) {
+ DEBUG(2, ("Attribute is missing but this should never
happen!\n"));
+ ret = EFAULT;
+ goto fail;
+ }
+ if (strcmp(name, c_name) || uid != c_uid) {
+ /* this is not the entry we are looking for */
+ ret = EINVAL;
+ goto fail;
+ }
+ }
- c_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
- c_uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
- if (c_name == NULL || c_uid == 0) {
- DEBUG(2, ("Attribute is missing but this should never
happen!\n"));
- ret = EFAULT;
+ ret = sysdb_delete_entry(sysdb, msg->dn, false);
+ if (ret) {
goto fail;
}
- if (strcmp(name, c_name) || uid != c_uid) {
- /* this is not the entry we are looking for */
- ret = EINVAL;
+ } else if (ret == ENOENT && name != NULL) {
+ /* Perhaps a ghost user? */
+ filter = talloc_asprintf(tmp_ctx, "(%s=%s)", SYSDB_GHOST, name);
+ if (filter == NULL) {
+ ret = ENOMEM;
goto fail;
}
- }
- ret = sysdb_delete_entry(sysdb, msg->dn, false);
- if (ret) {
+ ret = sysdb_search_groups(tmp_ctx, sysdb, filter, attrs, &msg_count,
&msgs);
+ if (ret != EOK) {
+ goto fail;
+ }
+
+ for (i = 0; i < msg_count; i++) {
+ msg = ldb_msg_new(tmp_ctx);
+ if (!msg) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+
+ msg->dn = msgs[i]->dn;
+ ret = ldb_msg_add_empty(msg, SYSDB_GHOST, SYSDB_MOD_DEL, NULL);
+ if (ret != LDB_SUCCESS) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ ret = ldb_msg_add_fmt(msg, SYSDB_GHOST, "%s", name);
+ if (ret != LDB_SUCCESS) {
+ ERROR_OUT(ret, EINVAL, fail);
+ }
+ ret = ldb_modify(sysdb->ldb, msg);
+ ret = sysdb_error_to_errno(ret);
+ if (ret != EOK) {
+ goto fail;
+ }
+
+ talloc_zfree(msg);
+ }
+ } else {
goto fail;
}
+
talloc_zfree(tmp_ctx);
return EOK;
--
1.7.7.6
From cf117c91cb64d05d8b2958d185e96a39772b23f4 Mon Sep 17 00:00:00
2001
From: Jan Zeleny <jzeleny(a)redhat.com>
Date: Mon, 23 Apr 2012 04:50:36 -0400
Subject: [PATCH 05/10] Ghost members - modifications in memberof plugin
---
src/ldb_modules/memberof.c | 47 ++++++++++++++++++++++++++++++++++++++-----
1 files changed, 41 insertions(+), 6 deletions(-)
diff --git a/src/ldb_modules/memberof.c b/src/ldb_modules/memberof.c
index 4fc46fa84529ac1850cdb588ddf69be0f60e8238..f0b5b72ed11ce71aec8ccb6e7a7cbd2d02e9566e
100644
--- a/src/ldb_modules/memberof.c
+++ b/src/ldb_modules/memberof.c
@@ -28,6 +28,7 @@
#include "dhash.h"
#define DB_MEMBER "member"
+#define DB_GHOST "ghost"
#define DB_MEMBEROF "memberof"
#define DB_MEMBERUID "memberuid"
#define DB_NAME "name"
@@ -191,7 +192,8 @@ static int mbof_append_muop(TALLOC_CTX *memctx,
int *_num_muops,
int flags,
struct ldb_dn *parent,
- const char *name)
+ const char *name,
+ const char *element_name)
{
struct mbof_memberuid_op *muops = *_muops;
int num_muops = *_num_muops;
@@ -229,7 +231,7 @@ static int mbof_append_muop(TALLOC_CTX *memctx,
if (!op->el) {
return LDB_ERR_OPERATIONS_ERROR;
}
- op->el->name = talloc_strdup(op->el, DB_MEMBERUID);
+ op->el->name = talloc_strdup(op->el, element_name);
if (!op->el->name) {
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -534,7 +536,8 @@ static int mbof_add_callback(struct ldb_request *req,
static int mbof_next_add(struct mbof_add_operation *addop)
{
static const char *attrs[] = { DB_OC, DB_NAME,
- DB_MEMBER, DB_MEMBEROF, NULL };
+ DB_MEMBER, DB_GHOST,
+ DB_MEMBEROF, NULL };
struct ldb_context *ldb;
struct ldb_request *req;
struct mbof_add_ctx *add_ctx;
@@ -789,7 +792,8 @@ static int mbof_add_operation(struct mbof_add_operation *addop)
ret = mbof_append_muop(add_ctx, &add_ctx->muops,
&add_ctx->num_muops,
LDB_FLAG_MOD_ADD,
- parents->dns[i], name);
+ parents->dns[i], name,
+ DB_MEMBERUID);
if (ret != LDB_SUCCESS) {
return ret;
}
@@ -806,6 +810,35 @@ static int mbof_add_operation(struct mbof_add_operation *addop)
return ret;
}
+ el = ldb_msg_find_element(addop->entry, DB_GHOST);
+ if (el) {
+ for (i = 0; i < el->num_values; i++) {
+ /* add memberuid to all group's parents */
+ for (j = 0; j < parents->num; j++) {
+ ret = mbof_append_muop(add_ctx, &add_ctx->muops,
+ &add_ctx->num_muops,
+ LDB_FLAG_MOD_ADD,
+ parents->dns[j],
+ (char *)el->values[i].data,
+ DB_GHOST);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+
+ /* now add memberuid to the group itself */
+ ret = mbof_append_muop(add_ctx, &add_ctx->muops,
+ &add_ctx->num_muops,
+ LDB_FLAG_MOD_ADD,
+ addop->entry_dn,
+ (char *)el->values[i].data,
+ DB_GHOST);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+ }
+
/* we are done with the entry now */
talloc_free(addop->entry);
addop->entry = NULL;
@@ -2071,7 +2104,8 @@ static int mbof_del_mod_entry(struct mbof_del_operation *delop)
ret = mbof_append_muop(del_ctx, &del_ctx->muops,
&del_ctx->num_muops,
LDB_FLAG_MOD_DELETE,
- diff[i], name);
+ diff[i], name,
+ DB_MEMBERUID);
if (ret != LDB_SUCCESS) {
return ret;
}
@@ -2311,7 +2345,8 @@ static int mbof_del_fill_muop(struct mbof_del_ctx *del_ctx,
ret = mbof_append_muop(del_ctx, &del_ctx->muops,
&del_ctx->num_muops,
LDB_FLAG_MOD_DELETE,
- valdn, name);
+ valdn, name,
+ DB_MEMBERUID);
if (ret != LDB_SUCCESS) {
return ret;
}
--
1.7.7.6
From 169772136d2c1f9cafdcec2dd30e5ad144e0834d Mon Sep 17 00:00:00
2001
From: Jan Zeleny <jzeleny(a)redhat.com>
Date: Mon, 23 Apr 2012 14:08:00 -0400
Subject: [PATCH 06/10] Ghost members - sysdb upgrade routine
It is remotely possible to have sysdb in an inconsistent state that
might need upgrade. Consider scenario when user asks for group
information. Some fake users are added as a part of this operation.
Before users can be fully resolved and stored properly, SSSD is shut
down and upgrade is performed.
In this case we need to go over all fake user records (uidNumber=0) and
replace each of them with ghost record in all group objects that are stated in
its memberof attribute.
---
src/db/sysdb.c | 7 ++
src/db/sysdb_private.h | 4 +-
src/db/sysdb_upgrade.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 157 insertions(+), 1 deletions(-)
diff --git a/src/db/sysdb.c b/src/db/sysdb.c
index 41c677d7e5fe16ed2799384c5c5744f92d13d64c..fd76f73c3d4f48fbaff362477aa207e3ac260eba
100644
--- a/src/db/sysdb.c
+++ b/src/db/sysdb.c
@@ -1061,6 +1061,13 @@ int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx,
}
}
+ if (strcmp(version, SYSDB_VERSION_0_10) == 0) {
+ ret = sysdb_upgrade_10(sysdb, &version);
+ if (ret != EOK) {
+ goto done;
+ }
+ }
+
/* The version should now match SYSDB_VERSION.
* If not, it means we didn't match any of the
* known older versions. The DB might be
diff --git a/src/db/sysdb_private.h b/src/db/sysdb_private.h
index a162cbba82bba8fef1e57ab2774d156307ead2cd..0fb7316b48b5c53be0198f719673080275c34b81
100644
--- a/src/db/sysdb_private.h
+++ b/src/db/sysdb_private.h
@@ -23,6 +23,7 @@
#ifndef __INT_SYS_DB_H__
#define __INT_SYS_DB_H__
+#define SYSDB_VERSION_0_11 "0.11"
#define SYSDB_VERSION_0_10 "0.10"
#define SYSDB_VERSION_0_9 "0.9"
#define SYSDB_VERSION_0_8 "0.8"
@@ -34,7 +35,7 @@
#define SYSDB_VERSION_0_2 "0.2"
#define SYSDB_VERSION_0_1 "0.1"
-#define SYSDB_VERSION SYSDB_VERSION_0_10
+#define SYSDB_VERSION SYSDB_VERSION_0_11
#define SYSDB_BASE_LDIF \
"dn: @ATTRIBUTES\n" \
@@ -104,6 +105,7 @@ int sysdb_upgrade_06(struct sysdb_ctx *sysdb, const char **ver);
int sysdb_upgrade_07(struct sysdb_ctx *sysdb, const char **ver);
int sysdb_upgrade_08(struct sysdb_ctx *sysdb, const char **ver);
int sysdb_upgrade_09(struct sysdb_ctx *sysdb, const char **ver);
+int sysdb_upgrade_10(struct sysdb_ctx *sysdb, const char **ver);
int add_string(struct ldb_message *msg, int flags,
const char *attr, const char *value);
diff --git a/src/db/sysdb_upgrade.c b/src/db/sysdb_upgrade.c
index 4fe6afb3e49e9dbc4d459338d198b4d2a715997d..d9b68d4aa6e0398189d8f272d7ac0104c8f347ab
100644
--- a/src/db/sysdb_upgrade.c
+++ b/src/db/sysdb_upgrade.c
@@ -1169,3 +1169,150 @@ done:
talloc_free(tmp_ctx);
return ret;
}
+
+int sysdb_upgrade_10(struct sysdb_ctx *sysdb, const char **ver)
+{
+
+ TALLOC_CTX *tmp_ctx;
+ int ret;
+ struct ldb_result *res;
+ struct ldb_message *msg;
+ struct ldb_message *user;
+ struct ldb_message_element *memberof_el;
+ const char *name;
+ struct ldb_dn *basedn;
+ const char *filter = "(&(objectClass=user)(!(uidNumber=*)))";
+ const char *attrs[] = { "name", "memberof", NULL };
+ int i, j;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ return ENOMEM;
+ }
+
+ basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_USER_BASE,
+ sysdb->domain->name);
+ if (basedn == NULL) {
+ ret = EIO;
+ goto done;
+ }
+
+ DEBUG(SSSDBG_CRIT_FAILURE, ("UPGRADING DB TO VERSION %s\n",
SYSDB_VERSION_0_11));
+
+ ret = ldb_transaction_start(sysdb->ldb);
+ if (ret != LDB_SUCCESS) {
+ ret = EIO;
+ goto done;
+ }
+
+ ret = ldb_search(sysdb->ldb, tmp_ctx, &res, basedn, LDB_SCOPE_SUBTREE,
+ attrs, "%s", filter);
+ if (ret != LDB_SUCCESS) {
+ ret = EIO;
+ goto done;
+ }
+
+ for (i = 0; i < res->count; i++) {
+ user = res->msgs[i];
+ memberof_el = ldb_msg_find_element(user, "memberof");
+ name = ldb_msg_find_attr_as_string(user, "name", NULL);
+ if (name == NULL) {
+ ret = EIO;
+ goto done;
+ }
+
+ for (j = 0; j < memberof_el->num_values; j++) {
+ msg = ldb_msg_new(tmp_ctx);
+ if (msg == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ msg->dn = ldb_dn_from_ldb_val(tmp_ctx, sysdb->ldb,
&memberof_el->values[j]);
+ if (msg->dn == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ if (!ldb_dn_validate(msg->dn)) {
+ DEBUG(SSSDBG_MINOR_FAILURE, ("DN validation failed during "
+ "upgrade: [%s]\n",
+ memberof_el->values[j].data));
+ talloc_zfree(msg);
+ continue;
+ }
+
+ ret = ldb_msg_add_empty(msg, "ghost", LDB_FLAG_MOD_ADD, NULL);
+ if (ret != LDB_SUCCESS) {
+ ret = ENOMEM;
+ goto done;
+ }
+ ret = ldb_msg_add_string(msg, "ghost", name);
+ if (ret != LDB_SUCCESS) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = ldb_msg_add_empty(msg, "member", LDB_FLAG_MOD_DELETE,
NULL);
+ if (ret != LDB_SUCCESS) {
+ ret = ENOMEM;
+ goto done;
+ }
+ ret = ldb_msg_add_string(msg, "member",
ldb_dn_get_linearized(user->dn));
+ if (ret != LDB_SUCCESS) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = ldb_modify(sysdb->ldb, msg);
+ talloc_zfree(msg);
+ if (ret != LDB_SUCCESS) {
+ ret = sysdb_error_to_errno(ret);
+ goto done;
+ }
+ }
+
+ ret = ldb_delete(sysdb->ldb, user->dn);
+ if (ret != LDB_SUCCESS) {
+ ret = sysdb_error_to_errno(ret);
+ goto done;
+ }
+
+ /* conversion done, upgrade version number */
+ msg = ldb_msg_new(tmp_ctx);
+ if (!msg) {
+ ret = ENOMEM;
+ goto done;
+ }
+ msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE);
+ if (!msg->dn) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL);
+ if (ret != LDB_SUCCESS) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_11);
+ if (ret != LDB_SUCCESS) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = ldb_modify(sysdb->ldb, msg);
+ if (ret != LDB_SUCCESS) {
+ ret = sysdb_error_to_errno(ret);
+ goto done;
+ }
+ }
+
+ ret = EOK;
+
+done:
+ ret = finish_upgrade(ret, sysdb->ldb, SYSDB_VERSION_0_11, ver);
+ talloc_free(tmp_ctx);
+ return ret;
+}
--
1.7.7.6
From ea12ef7f52ec959f83370b22a1b108a342461fe0 Mon Sep 17 00:00:00
2001
From: Jan Zeleny <jzeleny(a)redhat.com>
Date: Mon, 23 Apr 2012 04:51:08 -0400
Subject: [PATCH 07/10] Ghost members - NSS responder changes
Since there are two attributes storing information about user
memberships of the group we have to include both of them in results.
This will apply only for objects that have ghost members (i.e. they
contain the SYSDB_GHOST attribute). If an object has this attribute,
values of this attribute are not projected to the memberuid attribute.
---
src/responder/nss/nsssrv_cmd.c | 238 +++++++++++++++++++++++++---------------
1 files changed, 149 insertions(+), 89 deletions(-)
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index f36a9a322ab92144c93b8cb9041d7a28515cc85d..22ee617daf1968fa8ef0fd310e609db142fdb16a
100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -1667,6 +1667,136 @@ done:
#define MNUM_ROFFSET sizeof(uint32_t)
#define STRS_ROFFSET 2*sizeof(uint32_t)
+static int fill_members(struct sss_packet *packet,
+ struct sss_domain_info *dom,
+ struct nss_ctx *nctx,
+ struct ldb_message_element *el,
+ size_t *_rzero,
+ size_t *_rsize,
+ int *_memnum)
+{
+ int i, ret = EOK;
+ int memnum = *_memnum;
+ size_t rzero= *_rzero;
+ size_t rsize = *_rsize;
+ char *tmpstr;
+ struct sized_string name;
+ const char *namefmt = nctx->rctx->names->fq_fmt;
+ TALLOC_CTX *tmp_ctx = NULL;
+
+ size_t delim;
+ size_t dom_len;
+
+ uint8_t *body;
+ size_t blen;
+
+ const char *domain = dom->name;
+ bool add_domain = dom->fqnames;
+
+ if (add_domain) {
+ delim = 1;
+ dom_len = strlen(domain);
+ } else {
+ delim = 0;
+ dom_len = 0;
+ }
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ return ENOMEM;
+ }
+
+ sss_packet_get_body(packet, &body, &blen);
+ for (i = 0; i < el->num_values; i++) {
+ tmpstr = sss_get_cased_name(tmp_ctx, (char *)el->values[i].data,
+ dom->case_sensitive);
+ if (tmpstr == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("sss_get_cased_name failed, skipping\n"));
+ continue;
+ }
+
+ if (nctx->filter_users_in_groups) {
+ ret = sss_ncache_check_user(nctx->ncache,
+ nctx->neg_timeout,
+ dom, tmpstr);
+ if (ret == EEXIST) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("Group [%s] member [%s@%s] filtered
out!"
+ " (negative cache)\n",
+ (char *)&body[rzero+STRS_ROFFSET],
+ tmpstr, domain));
+ continue;
+ }
+ }
+
+ to_sized_string(&name, tmpstr);
+
+ if (add_domain) {
+ ret = sss_packet_grow(packet, name.len + delim + dom_len);
+ } else {
+ ret = sss_packet_grow(packet, name.len);
+ }
+ if (ret != EOK) {
+ goto done;
+ }
+ sss_packet_get_body(packet, &body, &blen);
+
+ if (add_domain) {
+ ret = snprintf((char *)&body[rzero + rsize],
+ name.len + delim + dom_len,
+ namefmt, name, domain);
+ if (ret >= (name.len + delim + dom_len)) {
+ /* need more space,
+ * got creative with the print format ? */
+ int t = ret - name.len + delim + dom_len + 1;
+ ret = sss_packet_grow(packet, t);
+ if (ret != EOK) {
+ goto done;
+ }
+ sss_packet_get_body(packet, &body, &blen);
+ delim += t;
+
+ /* retry */
+ ret = snprintf((char *)&body[rzero + rsize],
+ name.len + delim + dom_len,
+ namefmt, name, domain);
+ }
+
+ if (ret != name.len + delim + dom_len - 1) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Failed to generate a fully qualified
name"
+ " for member [%s@%s] of group [%s]!"
+ " Skipping\n", name.str, domain,
+ (char *)&body[rzero+STRS_ROFFSET]));
+ /* reclaim space */
+ ret = sss_packet_shrink(packet,
+ name.len + delim + dom_len);
+ if (ret != EOK) {
+ goto done;
+ }
+ continue;
+ }
+
+ } else {
+ memcpy(&body[rzero + rsize], name.str, name.len);
+ }
+
+ if (add_domain) {
+ rsize += name.len + delim + dom_len;
+ } else {
+ rsize += name.len;
+ }
+
+ memnum++;
+ }
+
+done:
+ *_memnum = memnum;
+ *_rzero = rzero;
+ *_rsize = rsize;
+ talloc_zfree(tmp_ctx);
+ return ret;
+}
+
static int fill_grent(struct sss_packet *packet,
struct sss_domain_info *dom,
struct nss_ctx *nctx,
@@ -1687,7 +1817,6 @@ static int fill_grent(struct sss_packet *packet,
size_t delim;
size_t dom_len;
int i = 0;
- int j = 0;
int ret, num, memnum;
size_t rzero, rsize;
bool add_domain = dom->fqnames;
@@ -1821,99 +1950,30 @@ static int fill_grent(struct sss_packet *packet,
memcpy(&body[rzero+STRS_ROFFSET + fullname.len],
pwfield.str, pwfield.len);
+ memnum = 0;
el = ldb_msg_find_element(msg, SYSDB_MEMBERUID);
if (el) {
- memnum = 0;
- for (j = 0; j < el->num_values; j++) {
- tmpstr = sss_get_cased_name(tmp_ctx, (char *)el->values[j].data,
- dom->case_sensitive);
- if (tmpstr == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("sss_get_cased_name failed, skipping\n"));
- continue;
- }
-
- if (nctx->filter_users_in_groups) {
- ret = sss_ncache_check_user(nctx->ncache,
- nctx->neg_timeout,
- dom, tmpstr);
- if (ret == EEXIST) {
- DEBUG(6, ("Group [%s] member [%s@%s] filtered out!"
- " (negative cache)\n",
- (char *)&body[rzero+STRS_ROFFSET],
- tmpstr, domain));
- continue;
- }
- }
-
- to_sized_string(&name, tmpstr);
-
- if (add_domain) {
- ret = sss_packet_grow(packet, name.len + delim + dom_len);
- } else {
- ret = sss_packet_grow(packet, name.len);
- }
- if (ret != EOK) {
- num = 0;
- goto done;
- }
- sss_packet_get_body(packet, &body, &blen);
-
- if (add_domain) {
- ret = snprintf((char *)&body[rzero + rsize],
- name.len + delim + dom_len,
- namefmt, name, domain);
- if (ret >= (name.len + delim + dom_len)) {
- /* need more space,
- * got creative with the print format ? */
- int t = ret - name.len + delim + dom_len + 1;
- ret = sss_packet_grow(packet, t);
- if (ret != EOK) {
- num = 0;
- goto done;
- }
- sss_packet_get_body(packet, &body, &blen);
- delim += t;
-
- /* retry */
- ret = snprintf((char *)&body[rzero + rsize],
- name.len + delim + dom_len,
- namefmt, name, domain);
- }
-
- if (ret != name.len + delim + dom_len - 1) {
- DEBUG(1, ("Failed to generate a fully qualified name"
- " for member [%s@%s] of group [%s]!"
- " Skipping\n", name.str, domain,
- (char *)&body[rzero+STRS_ROFFSET]));
- /* reclaim space */
- ret = sss_packet_shrink(packet,
- name.len + delim + dom_len);
- if (ret != EOK) {
- num = 0;
- goto done;
- }
- continue;
- }
-
- } else {
- memcpy(&body[rzero + rsize], name.str, name.len);
- }
-
- if (add_domain) {
- rsize += name.len + delim + dom_len;
- } else {
- rsize += name.len;
- }
-
- memnum++;
+ ret = fill_members(packet, dom, nctx, el, &rzero, &rsize,
&memnum);
+ if (ret != EOK) {
+ num = 0;
+ goto done;
}
-
- if (memnum) {
- /* set num of members */
- SAFEALIGN_SET_UINT32(&body[rzero+MNUM_ROFFSET], memnum, NULL);
+ sss_packet_get_body(packet, &body, &blen);
+ }
+
+ el = ldb_msg_find_element(msg, SYSDB_GHOST);
+ if (el) {
+ ret = fill_members(packet, dom, nctx, el, &rzero, &rsize,
&memnum);
+ if (ret != EOK) {
+ num = 0;
+ goto done;
}
+ sss_packet_get_body(packet, &body, &blen);
+ }
+ if (memnum) {
+ /* set num of members */
+ SAFEALIGN_SET_UINT32(&body[rzero+MNUM_ROFFSET], memnum, NULL);
}
num++;
--
1.7.7.6
From 92857f4e0366a9626eaf501d7331e8c633ee5f28 Mon Sep 17 00:00:00
2001
From: Jan Zeleny <jzeleny(a)redhat.com>
Date: Mon, 23 Apr 2012 05:13:48 -0400
Subject: [PATCH 08/10] Ghost members - removed sdap_check_aliases()
This function is no longer necessary because we don't have fake user
entries any more. The original purpose of this function was to check if
there are fake user entries for particular user and, if yes, to update
its membership.
---
src/providers/ldap/sdap_async.c | 108 ----------------------------
src/providers/ldap/sdap_async.h | 6 --
src/providers/ldap/sdap_async_initgroups.c | 7 --
src/providers/ldap/sdap_async_users.c | 6 --
4 files changed, 0 insertions(+), 127 deletions(-)
diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c
index a8a12c3d390a4ebee0dca81d6610be9fe240a4a6..b59f8e9f11209f911057ec981ad69f0a8cab5f4e
100644
--- a/src/providers/ldap/sdap_async.c
+++ b/src/providers/ldap/sdap_async.c
@@ -2100,114 +2100,6 @@ bool sdap_has_deref_support(struct sdap_handle *sh, struct
sdap_options *opts)
return false;
}
-errno_t sdap_check_aliases(struct sysdb_ctx *sysdb,
- struct sysdb_attrs *user_attrs,
- struct sss_domain_info *dom,
- struct sdap_options *opts,
- bool steal_memberships)
-{
- errno_t ret;
- const char **aliases = NULL;
- const char *name = NULL;
- struct ldb_message *msg;
- TALLOC_CTX *tmp_ctx = NULL;
- char **parents;
- uid_t alias_uid, uid;
- int i;
-
- tmp_ctx = talloc_new(NULL);
- if (!tmp_ctx) return ENOMEM;
-
- ret = sysdb_attrs_primary_name(sysdb, user_attrs,
- opts->user_map[SDAP_AT_USER_NAME].sys_name,
- &name);
- if (ret != EOK) {
- DEBUG(SSSDBG_TRACE_INTERNAL, ("Could not get the primary name\n"));
- goto done;
- }
-
- ret = sysdb_attrs_get_uint32_t(user_attrs,
- opts->user_map[SDAP_AT_USER_UID].sys_name,
- &uid);
- if (ret != EOK) {
- DEBUG(SSSDBG_TRACE_INTERNAL, ("Could not get UID\n"));
- goto done;
- }
-
- ret = sysdb_attrs_get_aliases(tmp_ctx, user_attrs, name,
- !dom->case_sensitive, &aliases);
- if (ret != EOK) {
- DEBUG(SSSDBG_TRACE_INTERNAL, ("Failed to get the alias list\n"));
- goto done;
- }
-
- for (i = 0; aliases[i]; i++) {
- /* In RFC2307 schema, another group might be referencing user
- * using secondary name, so there might be fake users in the cache
- * from a previous getgr call */
- ret = sysdb_search_user_by_name(tmp_ctx, sysdb,
- aliases[i], NULL, &msg);
- if (ret && ret != ENOENT) {
- DEBUG(SSSDBG_TRACE_INTERNAL, ("Error searching the cache\n"));
- goto done;
- } else if (ret == ENOENT) {
- DEBUG(SSSDBG_TRACE_INTERNAL,
- ("No user with primary name same as alias %s\n",
aliases[i]));
- continue;
- }
-
- alias_uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
- if (alias_uid) {
- if (alias_uid == uid) {
- DEBUG(SSSDBG_TRACE_INTERNAL,
- ("User already cached, skipping\n"));
- continue;
- }
- DEBUG(SSSDBG_FATAL_FAILURE,
- ("Cache contains non-fake user with same name "
- "as alias %s\n", aliases[i]));
- ret = EIO;
- goto done;
- }
- DEBUG(SSSDBG_TRACE_FUNC, ("%s is a fake user\n", aliases[i]));
-
- if (steal_memberships) {
- /* Get direct sysdb parents */
- ret = sysdb_get_direct_parents(tmp_ctx, sysdb, dom,
- SYSDB_MEMBER_USER,
- aliases[i], &parents);
- if (ret) {
- DEBUG(SSSDBG_FATAL_FAILURE,
- ("Could not get direct parents for %s: %d [%s]\n",
- aliases[i], ret, strerror(ret)));
- goto done;
- }
-
- ret = sysdb_update_members(sysdb, name, SYSDB_MEMBER_USER,
- (const char *const *) parents,
- NULL);
- if (ret != EOK) {
- DEBUG(SSSDBG_FATAL_FAILURE,
- ("Membership update failed [%d]: %s\n",
- ret, strerror(ret)));
- goto done;
- }
- }
-
- ret = sysdb_delete_user(sysdb, aliases[i], alias_uid);
- if (ret) {
- DEBUG(SSSDBG_FATAL_FAILURE,
- ("Error deleting fake user %s\n", aliases[i]));
- goto done;
- }
- }
-
- ret = EOK;
-done:
- talloc_free(tmp_ctx);
- return ret;
-}
-
errno_t
sdap_attrs_add_ldap_attr(struct sysdb_attrs *ldap_attrs,
const char *attr_name,
diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
index 870f153107d91ba7fa32a6c59a9c9a20907a989d..34fb40daed5830aa9b1adae8ad7b62bb2c429bca
100644
--- a/src/providers/ldap/sdap_async.h
+++ b/src/providers/ldap/sdap_async.h
@@ -195,12 +195,6 @@ int sdap_deref_search_recv(struct tevent_req *req,
size_t *reply_count,
struct sdap_deref_attrs ***reply);
-errno_t sdap_check_aliases(struct sysdb_ctx *sysdb,
- struct sysdb_attrs *user_attrs,
- struct sss_domain_info *dom,
- struct sdap_options *opts,
- bool steal_memberships);
-
errno_t
sdap_attrs_add_ldap_attr(struct sysdb_attrs *ldap_attrs,
const char *attr_name,
diff --git a/src/providers/ldap/sdap_async_initgroups.c
b/src/providers/ldap/sdap_async_initgroups.c
index b883ccf938348f9f5dda4ed43bf714973072c9f9..861176000423e07b57ed3e135b717ea9ecaebbac
100644
--- a/src/providers/ldap/sdap_async_initgroups.c
+++ b/src/providers/ldap/sdap_async_initgroups.c
@@ -2646,13 +2646,6 @@ static void sdap_get_initgr_user(struct tevent_req *subreq)
switch (state->opts->schema_type) {
case SDAP_SCHEMA_RFC2307:
- ret = sdap_check_aliases(state->sysdb, state->orig_user, state->dom,
- state->opts, false);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
subreq = sdap_initgr_rfc2307_send(state, state->ev, state->opts,
state->sysdb, state->sh,
cname);
diff --git a/src/providers/ldap/sdap_async_users.c
b/src/providers/ldap/sdap_async_users.c
index bc9e5551be32847b45eb87ff4b17572a9b44b584..dfce319b231a84bdbcded041b7e64cc0fbad942e
100644
--- a/src/providers/ldap/sdap_async_users.c
+++ b/src/providers/ldap/sdap_async_users.c
@@ -411,12 +411,6 @@ int sdap_save_users(TALLOC_CTX *memctx,
DEBUG(9, ("User %d processed!\n", i));
}
- ret = sdap_check_aliases(sysdb, users[i], dom,
- opts, true);
- if (ret) {
- DEBUG(2, ("Failed to check aliases for user %d. Ignoring.\n",
i));
- }
-
if (usn_value) {
if (higher_usn) {
if ((strlen(usn_value) > strlen(higher_usn)) ||
--
1.7.7.6
From 1c48c0d6c301ba7ca337503aadb26e7eb9fb08e8 Mon Sep 17 00:00:00
2001
From: Jan Zeleny <jzeleny(a)redhat.com>
Date: Mon, 23 Apr 2012 05:22:46 -0400
Subject: [PATCH 09/10] Ghost members - modified sss_groupshow
---
src/tools/sss_groupshow.c | 44 ++++++++++++++++++++++++++++++++++++++++----
1 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/src/tools/sss_groupshow.c b/src/tools/sss_groupshow.c
index 764e32416b046dfc6ff2a47de37627e40b0109f0..8c15171c86b15bc63649254b61254617391bbe19
100644
--- a/src/tools/sss_groupshow.c
+++ b/src/tools/sss_groupshow.c
@@ -31,7 +31,7 @@
#define PADDING_SPACES 4
#define GROUP_SHOW_ATTRS { SYSDB_MEMBEROF, SYSDB_GIDNUM, \
- SYSDB_MEMBER, SYSDB_NAME, \
+ SYSDB_MEMBER, SYSDB_GHOST, SYSDB_NAME, \
NULL }
#define GROUP_SHOW_MPG_ATTRS { SYSDB_MEMBEROF, SYSDB_UIDNUM, \
SYSDB_NAME, NULL }
@@ -189,8 +189,8 @@ static int parse_members(TALLOC_CTX *mem_ctx,
}
*user_members = um;
- *group_members = gm;
- *num_group_members = gm_index;
+ if (group_members) *group_members = gm;
+ if (num_group_members) *num_group_members = gm_index;
talloc_zfree(tmp_ctx);
return EOK;
@@ -211,8 +211,10 @@ static int process_group(TALLOC_CTX *mem_ctx,
int *num_group_members)
{
struct ldb_message_element *el;
- int ret;
+ int ret, i, j;
+ int count = 0;
struct group_info *gi = NULL;
+ const char **user_members;
DEBUG(6, ("Found entry %s\n", ldb_dn_get_linearized(msg->dn)));
@@ -245,6 +247,40 @@ static int process_group(TALLOC_CTX *mem_ctx,
if (ret != EOK) {
goto done;
}
+ if (gi->user_members == NULL) {
+ count = 0;
+ } else {
+ for (count = 0; gi->user_members[count]; count++) ;
+ }
+ }
+ el = ldb_msg_find_element(msg, SYSDB_GHOST);
+ if (el) {
+ ret = parse_members(gi, ldb, domain, el,
+ parent_name,
+ &user_members,
+ NULL, NULL);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ if (user_members != NULL) {
+ i = count;
+ for (count = 0; user_members[count]; count++) ;
+ gi->user_members = talloc_realloc(gi, gi->user_members,
+ const char *,
+ i + count + 1);
+ if (gi->user_members == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ for (j = 0; j < count; j++, i++) {
+ gi->user_members[i] = talloc_steal(gi->user_members,
+ user_members[j]);
+ }
+ gi->user_members[i] = NULL;
+
+ talloc_zfree(user_members);
+ }
}
/* list memberofs */
--
1.7.7.6
From b684bacc88a827ff9316295231b8808fd6090ef2 Mon Sep 17 00:00:00
2001
From: Jan Zeleny <jzeleny(a)redhat.com>
Date: Mon, 23 Apr 2012 05:23:15 -0400
Subject: [PATCH 10/10] Ghost members - various small changes
---
src/providers/ldap/ldap_id_cleanup.c | 2 +-
src/providers/ldap/sdap_async_groups.c | 8 +++-----
src/responder/nss/nsssrv_cmd.c | 2 +-
src/tests/sysdb-tests.c | 2 +-
4 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/src/providers/ldap/ldap_id_cleanup.c b/src/providers/ldap/ldap_id_cleanup.c
index 27a86b9f676a65bb7a0e4f4f10820564f3d2c0e9..3460b8cc605c9bec7b93d0a35ce295bae108865f
100644
--- a/src/providers/ldap/ldap_id_cleanup.c
+++ b/src/providers/ldap/ldap_id_cleanup.c
@@ -356,7 +356,7 @@ static int cleanup_users_logged_in(hash_table_t *table,
uid = ldb_msg_find_attr_as_uint64(msg,
SYSDB_UIDNUM, 0);
if (!uid) {
- DEBUG(2, ("Entry %s has no UID Attribute, fake user perhaps?\n",
+ DEBUG(SSSDBG_OP_FAILURE, ("Entry %s has no UID Attribute!\n",
ldb_dn_get_linearized(msg->dn)));
return ENOENT;
}
diff --git a/src/providers/ldap/sdap_async_groups.c
b/src/providers/ldap/sdap_async_groups.c
index a3cf4d05606559409f3bd9ab20aeae76438a508d..32e79c32c6068c69e27d54850f13cad26eee24cf
100644
--- a/src/providers/ldap/sdap_async_groups.c
+++ b/src/providers/ldap/sdap_async_groups.c
@@ -2390,11 +2390,9 @@ sdap_nested_group_check_cache(TALLOC_CTX *mem_ctx,
user_uid = ldb_msg_find_attr_as_uint64(msgs[0], SYSDB_UIDNUM, 0);
if (!user_uid) {
- /* Refresh the fake user if he was created before cache_timeout */
- create_time = ldb_msg_find_attr_as_uint64(msgs[0],
- SYSDB_CREATE_TIME,
- 0);
- expiration = create_time + dom->user_timeout;
+ DEBUG(SSSDBG_OP_FAILURE, ("User with no UID? Skipping\n"));
+ ret = EIO;
+ goto fail;
} else {
/* Regular user, check if we need a refresh */
expiration = ldb_msg_find_attr_as_uint64(msgs[0],
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index 22ee617daf1968fa8ef0fd310e609db142fdb16a..360f3698c1281a67de311dfc28f46c3724e78ad9
100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -258,7 +258,7 @@ static int fill_pwent(struct sss_packet *packet,
gid = get_gid_override(msg, dom);
if (!orig_name || !uid || !gid) {
- DEBUG(2, ("Incomplete or fake user object for %s[%llu]!
Skipping\n",
+ DEBUG(SSSDBG_OP_FAILURE, ("Incomplete user object for %s[%llu]!
Skipping\n",
orig_name?orig_name:"<NULL>", (unsigned long long
int)uid));
continue;
}
diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index bcf3f732be6f172324b0d1b455c28076a2355128..dd053b3a35265aea2ef056ded628051b10dcee74
100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -2726,7 +2726,7 @@ START_TEST(test_odd_characters)
odd_username,
10000, 10000,
"","","");
- fail_unless(ret == EOK, "sysdb_add_fake_user error [%d][%s]",
+ fail_unless(ret == EOK, "sysdb_add_basic_user error [%d][%s]",
ret, strerror(ret));
/* Retrieve */
--
1.7.7.6
_______________________________________________
sssd-devel mailing list
sssd-devel(a)lists.fedorahosted.org
https://fedorahosted.org/mailman/listinfo/sssd-devel