diff -urN nss-pam-ldapd-0.8.12.vanilla/nslcd/group.c nss-pam-ldapd-0.8.12/nslcd/group.c --- nss-pam-ldapd-0.8.12.vanilla/nslcd/group.c 2012-09-14 13:25:51.000000000 +0100 +++ nss-pam-ldapd-0.8.12/nslcd/group.c 2013-03-20 14:48:14.000000000 +0000 @@ -145,6 +145,22 @@ attmap_group_member,safedn); } +static int mkfilter_group_bymemberdn(MYLDAP_SESSION *session, + const char *dn, + char *buffer,size_t buflen) +{ + char safeuid[300]; + char safedn[300]; + + /* escape DN */ + if(myldap_escape(dn,safedn,sizeof(safedn))) + return -1; + return mysnprintf(buffer,buflen, + "(&%s(%s=%s))", + group_filter, + attmap_group_member,safedn); +} + void group_init(void) { int i; @@ -202,16 +218,15 @@ return 0; } -/* return the list of members */ -static const char **getmembers(MYLDAP_ENTRY *entry,MYLDAP_SESSION *session) +static void getmembers_set(MYLDAP_ENTRY *entry,MYLDAP_SESSION *session, SET *set) { char buf[256]; int i; const char **values; - SET *set; - set=set_new(); - if (set==NULL) - return NULL; + int j; + int rc; + MYLDAP_SEARCH * search; + MYLDAP_ENTRY * entry2; /* add the memberUid values */ values=myldap_get_values(entry,attmap_group_memberUid); if (values!=NULL) @@ -229,7 +244,26 @@ /* transform the DN into a uid (dn2uid() already checks validity) */ if (dn2uid(session,values[i],buf,sizeof(buf))!=NULL) set_add(set,buf); + /* Wasn't a UID - try handling it as a nested group */ + else if ((search=myldap_search(session,values[i],LDAP_SCOPE_BASE,group_filter,group_attrs,NULL)) != NULL) + { + while ((entry2=myldap_get_entry(search,&rc))!=NULL) + getmembers_set(entry2, session, set); + } } +} + +/* return the list of members */ +static const char **getmembers(MYLDAP_ENTRY *entry,MYLDAP_SESSION *session) +{ + char buf[20]; + int i; + const char **values; + SET *set; + set=set_new(); + if (set==NULL) + return NULL; + getmembers_set(entry, session, set); /* return the members */ values=set_tolist(set); set_free(set); @@ -315,6 +349,40 @@ return rc; } +static int write_group_and_parents(TFILE *fp,MYLDAP_ENTRY *entry, MYLDAP_SESSION *session) { + const char * dn; + int rc; + int rc2; + int i; + MYLDAP_SEARCH * search; + MYLDAP_ENTRY * entry2; + const char * base; + char filter[1024]; + + rc = write_group(fp,entry,NULL,NULL,0,session); + if (! rc) + { + dn = myldap_get_dn(entry); + log_log(LOG_DEBUG, "dn = %s", dn); + + // Make filter + mkfilter_group_bymemberdn(session, dn, filter, sizeof(filter)); + for (i=0; (base=group_bases[i])!=NULL; i++) + { + /* do the LDAP search */ \ + if ((search=myldap_search(session,base,group_scope,filter,group_attrs,NULL))==NULL) + return -1; + /* go over results */ + while ((entry2=myldap_get_entry(search,&rc2))!=NULL) + { + if (write_group_and_parents(fp,entry2,session)) + return -1; + } + } + } + return rc; +} + NSLCD_HANDLE( group,byname, char name[256]; @@ -364,7 +432,7 @@ }, NSLCD_ACTION_GROUP_BYMEMBER, mkfilter_group_bymember(session,name,filter,sizeof(filter)), - write_group(fp,entry,NULL,NULL,0,session) + write_group_and_parents(fp,entry,session) ) NSLCD_HANDLE(