[SSSD] [PATCHES] Support for ghost users

Jan Zelený jzeleny at redhat.com
Wed May 23 10:03:51 UTC 2012


> On Thu, May 10, 2012 at 10:57:23PM +0200, Jan Zeleny wrote:
> > Simo Sorce <simo at 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)

I rebased the patchset, I just forgot to send it. This one also contains the 
change you requested.

Jan

> 
> > From 48a09ace701e3de727912accd399187e052e795b Mon Sep 17 00:00:00 2001
> > From: Jan Zeleny <jzeleny at 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..9e7d3c5ca2b584ac306891cbec34d6
> > 3132649e0f 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, \
> > 
> > From 96039ae40cd4c61bd2f78f8a23c3b706cbf90749 Mon Sep 17 00:00:00 2001
> > From: Jan Zeleny <jzeleny at 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..a3cf4d05606559409f3bd9ab20aeae
> > 76438a508d 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].na
> >                                      me,
> > 
> > @@ -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,
> > 
> > From dd53be03778ab9e804d286752375292b65dc0f69 Mon Sep 17 00:00:00 2001
> > From: Jan Zeleny <jzeleny at 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..6c78848267ff76aa1b7e1eca9fbc36
> > ded58ca3b0 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;
> >              
> >              }
> > 
> > From c75d6a16569fe6250b3b3659bc96961c2fdcde8e Mon Sep 17 00:00:00 2001
> > From: Jan Zeleny <jzeleny at 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..85dde2c4908b9c502921a82558ff09
> > 329c4052ca 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..1bfb6c926ca73530be34d9cb6b2713
> > a6f1e1a0d6 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;
> > 
> > From cf117c91cb64d05d8b2958d185e96a39772b23f4 Mon Sep 17 00:00:00 2001
> > From: Jan Zeleny <jzeleny at 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..f0b5b72ed11ce71aec8ccb6e7a7cbd
> > 2d02e9566e 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;
> >          
> >          }
> > 
> > From 169772136d2c1f9cafdcec2dd30e5ad144e0834d Mon Sep 17 00:00:00 2001
> > From: Jan Zeleny <jzeleny at 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..fd76f73c3d4f48fbaff362477aa207
> > e3ac260eba 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..0fb7316b48b5c53be0198f71967308
> > 0275c34b81 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..d9b68d4aa6e0398189d8f272d7ac01
> > 04c8f347ab 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;
> > +}
> > 
> > From ea12ef7f52ec959f83370b22a1b108a342461fe0 Mon Sep 17 00:00:00 2001
> > From: Jan Zeleny <jzeleny at 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..22ee617daf1968fa8ef0fd310e609d
> > b142fdb16a 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++;
> > 
> > From 92857f4e0366a9626eaf501d7331e8c633ee5f28 Mon Sep 17 00:00:00 2001
> > From: Jan Zeleny <jzeleny at 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..b59f8e9f11209f911057ec981ad69f
> > 0a8cab5f4e 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..34fb40daed5830aa9b1adae8ad7b62
> > bb2c429bca 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..861176000423e07b57ed3e135b717e
> > a9ecaebbac 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..dfce319b231a84bdbcded041b7e64c
> > c0fbad942e 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)) ||
> > 
> > From 1c48c0d6c301ba7ca337503aadb26e7eb9fb08e8 Mon Sep 17 00:00:00 2001
> > From: Jan Zeleny <jzeleny at 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..8c15171c86b15bc63649254b612546
> > 17391bbe19 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 */
> > 
> > From b684bacc88a827ff9316295231b8808fd6090ef2 Mon Sep 17 00:00:00 2001
> > From: Jan Zeleny <jzeleny at 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..3460b8cc605c9bec7b93d0a35ce295
> > bae108865f 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..32e79c32c6068c69e27d54850f13ca
> > d26eee24cf 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..360f3698c1281a67de311dfc28f46c
> > 3724e78ad9 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..dd053b3a35265aea2ef056ded62805
> > 1b10dcee74 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 */
> > 
> > _______________________________________________
> > sssd-devel mailing list
> > sssd-devel at lists.fedorahosted.org
> > https://fedorahosted.org/mailman/listinfo/sssd-devel
> 
> _______________________________________________
> sssd-devel mailing list
> sssd-devel at lists.fedorahosted.org
> https://fedorahosted.org/mailman/listinfo/sssd-devel

-- 
Thank you
Jan Zeleny

Red Hat Software Engineer
Brno, Czech Republic
-------------- next part --------------
A non-text attachment was scrubbed...
Name: jzeleny-117-6-ghost-members-add-the-ghost-attribute-to-sysdb.patch
Type: text/x-patch
Size: 1070 bytes
Desc: not available
URL: <https://lists.fedorahosted.org/pipermail/sssd-devel/attachments/20120523/689a9e50/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: jzeleny-118-6-ghost-members-support-in-ldap-provider.patch
Type: text/x-patch
Size: 33572 bytes
Desc: not available
URL: <https://lists.fedorahosted.org/pipermail/sssd-devel/attachments/20120523/689a9e50/attachment-0001.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: jzeleny-119-6-ghost-members-support-in-proxy-provider.patch
Type: text/x-patch
Size: 2733 bytes
Desc: not available
URL: <https://lists.fedorahosted.org/pipermail/sssd-devel/attachments/20120523/689a9e50/attachment-0002.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: jzeleny-120-6-ghost-members-modifications-in-sysdb.patch
Type: text/x-patch
Size: 10714 bytes
Desc: not available
URL: <https://lists.fedorahosted.org/pipermail/sssd-devel/attachments/20120523/689a9e50/attachment-0003.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: jzeleny-121-6-ghost-members-modifications-in-memberof-plugin.patch
Type: text/x-patch
Size: 4921 bytes
Desc: not available
URL: <https://lists.fedorahosted.org/pipermail/sssd-devel/attachments/20120523/689a9e50/attachment-0004.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: jzeleny-122-6-ghost-members-sysdb-upgrade-routine.patch
Type: text/x-patch
Size: 7315 bytes
Desc: not available
URL: <https://lists.fedorahosted.org/pipermail/sssd-devel/attachments/20120523/689a9e50/attachment-0005.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: jzeleny-123-6-ghost-members-nss-responder-changes.patch
Type: text/x-patch
Size: 10466 bytes
Desc: not available
URL: <https://lists.fedorahosted.org/pipermail/sssd-devel/attachments/20120523/689a9e50/attachment-0006.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: jzeleny-124-6-ghost-members-removed-sdap_check_aliases.patch
Type: text/x-patch
Size: 7618 bytes
Desc: not available
URL: <https://lists.fedorahosted.org/pipermail/sssd-devel/attachments/20120523/689a9e50/attachment-0007.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: jzeleny-125-6-ghost-members-modified-sss_groupshow.patch
Type: text/x-patch
Size: 3005 bytes
Desc: not available
URL: <https://lists.fedorahosted.org/pipermail/sssd-devel/attachments/20120523/689a9e50/attachment-0008.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: jzeleny-126-5-ghost-members-various-small-changes.patch
Type: text/x-patch
Size: 2424 bytes
Desc: not available
URL: <https://lists.fedorahosted.org/pipermail/sssd-devel/attachments/20120523/689a9e50/attachment-0009.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <https://lists.fedorahosted.org/pipermail/sssd-devel/attachments/20120523/689a9e50/attachment.sig>


More information about the sssd-devel mailing list