Back to index

openldap  2.4.31
group.c
Go to the documentation of this file.
00001 /* group.c - group lookup routines */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 
00004  *
00005  * Copyright 2008-2012 The OpenLDAP Foundation.
00006  * Portions Copyright 2008-2009 by Howard Chu, Symas Corp.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted only as authorized by the OpenLDAP
00011  * Public License.
00012  *
00013  * A copy of this license is available in the file LICENSE in the
00014  * top-level directory of the distribution or, alternatively, at
00015  * <http://www.OpenLDAP.org/license.html>.
00016  */
00017 /* ACKNOWLEDGEMENTS:
00018  * This code references portions of the nss-ldapd package
00019  * written by Arthur de Jong. The nss-ldapd code was forked
00020  * from the nss-ldap library written by Luke Howard.
00021  */
00022 
00023 #include "nssov.h"
00024 
00025 /* for gid_t */
00026 #include <grp.h>
00027 
00028 /* ( nisSchema.2.2 NAME 'posixGroup' SUP top STRUCTURAL
00029  *   DESC 'Abstraction of a group of accounts'
00030  *   MUST ( cn $ gidNumber )
00031  *   MAY ( userPassword $ memberUid $ description ) )
00032  *
00033  * apart from that the above the uniqueMember attributes may be
00034  * supported in a coming release (they map to DNs, which is an extra
00035  * lookup step)
00036  *
00037  * using nested groups (groups that are member of a group) is currently
00038  * not supported, this may be added in a later release
00039  */
00040 
00041 /* the basic search filter for searches */
00042 static struct berval group_filter = BER_BVC("(objectClass=posixGroup)");
00043 
00044 /* the attributes to request with searches */
00045 static struct berval group_keys[] = {
00046        BER_BVC("cn"),
00047        BER_BVC("userPassword"),
00048        BER_BVC("gidNumber"),
00049        BER_BVC("memberUid"),
00050        BER_BVC("uniqueMember"),
00051        BER_BVNULL
00052 };
00053 
00054 #define       CN_KEY 0
00055 #define       PWD_KEY       1
00056 #define       GID_KEY       2
00057 #define       UID_KEY       3
00058 #define       MEM_KEY       4
00059 
00060 /* default values for attributes */
00061 static struct berval default_group_userPassword     = BER_BVC("*"); /* unmatchable */
00062 
00063 NSSOV_CBPRIV(group,
00064        nssov_info *ni;
00065        char buf[256];
00066        struct berval name;
00067        struct berval gidnum;
00068        struct berval user;
00069        int wantmembers;);
00070 
00071 /* create a search filter for searching a group entry
00072         by member uid, return -1 on errors */
00073 static int mkfilter_group_bymember(nssov_group_cbp *cbp,struct berval *buf)
00074 {
00075        struct berval dn;
00076        /* try to translate uid to DN */
00077        nssov_uid2dn(cbp->op,cbp->ni,&cbp->user,&dn);
00078        if (BER_BVISNULL(&dn)) {
00079               if (cbp->user.bv_len + cbp->mi->mi_filter.bv_len + cbp->mi->mi_attrs[UID_KEY].an_desc->ad_cname.bv_len + 6 >
00080                      buf->bv_len )
00081                      return -1;
00082               buf->bv_len = snprintf(buf->bv_val, buf->bv_len, "(&%s(%s=%s))",
00083                      cbp->mi->mi_filter.bv_val, cbp->mi->mi_attrs[UID_KEY].an_desc->ad_cname.bv_val,
00084                      cbp->user.bv_val );
00085        } else { /* also lookup using user DN */
00086               if (cbp->user.bv_len + cbp->mi->mi_filter.bv_len + cbp->mi->mi_attrs[UID_KEY].an_desc->ad_cname.bv_len +
00087                      dn.bv_len + cbp->mi->mi_attrs[MEM_KEY].an_desc->ad_cname.bv_len + 12 > buf->bv_len )
00088                      return -1;
00089               buf->bv_len = snprintf(buf->bv_val, buf->bv_len, "(&%s(|(%s=%s)(%s=%s)))",
00090                      cbp->mi->mi_filter.bv_val,
00091                      cbp->mi->mi_attrs[UID_KEY].an_desc->ad_cname.bv_val, cbp->user.bv_val,
00092                      cbp->mi->mi_attrs[MEM_KEY].an_desc->ad_cname.bv_val, dn.bv_val );
00093        }
00094        return 0;
00095 }
00096 
00097 NSSOV_INIT(group)
00098 
00099 /*
00100         Checks to see if the specified name is a valid group name.
00101 
00102         This test is based on the definition from POSIX (IEEE Std 1003.1, 2004,
00103         3.189 Group Name and 3.276 Portable Filename Character Set):
00104         http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_189
00105         http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_276
00106 
00107         The standard defines group names valid if they only contain characters from
00108         the set [A-Za-z0-9._-] where the hyphen should not be used as first
00109         character.
00110 */
00111 static int isvalidgroupname(struct berval *name)
00112 {
00113        int i;
00114 
00115        if ( !name->bv_val || !name->bv_len )
00116               return 0;
00117        /* check first character */
00118        if ( ! ( (name->bv_val[0]>='A' && name->bv_val[0] <= 'Z') ||
00119                                     (name->bv_val[0]>='a' && name->bv_val[0] <= 'z') ||
00120                                     (name->bv_val[0]>='0' && name->bv_val[0] <= '9') ||
00121                                     name->bv_val[0]=='.' || name->bv_val[0]=='_' ) )
00122               return 0;
00123        /* check other characters */
00124        for (i=1;i<name->bv_len;i++)
00125        {
00126 #ifndef STRICT_GROUPS
00127               /* allow spaces too */
00128               if (name->bv_val[i] == ' ') continue;
00129 #endif
00130               if ( ! ( (name->bv_val[i]>='A' && name->bv_val[i] <= 'Z') ||
00131                                            (name->bv_val[i]>='a' && name->bv_val[i] <= 'z') ||
00132                                            (name->bv_val[i]>='0' && name->bv_val[i] <= '9') ||
00133                                            name->bv_val[i]=='.' || name->bv_val[i]=='_' || name->bv_val[i]=='-') )
00134                      return 0;
00135        }
00136        /* no test failed so it must be good */
00137        return -1;
00138 }
00139 
00140 static int write_group(nssov_group_cbp *cbp,Entry *entry)
00141 {
00142        struct berval tmparr[2], tmpgid[2];
00143        struct berval *names,*gids,*members;
00144        struct berval passwd = {0};
00145        Attribute *a;
00146        int i,j,nummembers,rc;
00147 
00148        /* get group name (cn) */
00149        if (BER_BVISNULL(&cbp->name))
00150        {
00151               a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[CN_KEY].an_desc);
00152               if ( !a )
00153               {
00154                      Debug(LDAP_DEBUG_ANY,"group entry %s does not contain %s value\n",
00155                                    entry->e_name.bv_val, cbp->mi->mi_attrs[CN_KEY].an_desc->ad_cname.bv_val,0);
00156                      return 0;
00157               }
00158               names = a->a_vals;
00159        }
00160        else
00161        {
00162               names=tmparr;
00163               names[0]=cbp->name;
00164               BER_BVZERO(&names[1]);
00165        }
00166        /* get the group id(s) */
00167        if (BER_BVISNULL(&cbp->gidnum))
00168        {
00169               a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[GID_KEY].an_desc);
00170               if ( !a )
00171               {
00172                      Debug(LDAP_DEBUG_ANY,"group entry %s does not contain %s value\n",
00173                                    entry->e_name.bv_val, cbp->mi->mi_attrs[GID_KEY].an_desc->ad_cname.bv_val,0);
00174                      return 0;
00175               }
00176               gids = a->a_vals;
00177        }
00178        else
00179        {
00180               gids=tmpgid;
00181               gids[0]=cbp->gidnum;
00182               BER_BVZERO(&gids[1]);
00183        }
00184        /* get group passwd (userPassword) (use only first entry) */
00185        a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[PWD_KEY].an_desc);
00186        if (a)
00187               get_userpassword(&a->a_vals[0], &passwd);
00188        if (BER_BVISNULL(&passwd))
00189               passwd=default_group_userPassword;
00190        /* get group members (memberUid&uniqueMember) */
00191        if (cbp->wantmembers) {
00192               Attribute *b;
00193               i = 0; j = 0;
00194               a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[UID_KEY].an_desc);
00195               b = attr_find(entry->e_attrs, cbp->mi->mi_attrs[MEM_KEY].an_desc);
00196               if ( a )
00197                      i += a->a_numvals;
00198               if ( b )
00199                      i += b->a_numvals;
00200               if ( i ) {
00201                      members = cbp->op->o_tmpalloc( (i+1) * sizeof(struct berval), cbp->op->o_tmpmemctx );
00202                      
00203                      if ( a ) {
00204                             for (i=0; i<a->a_numvals; i++) {
00205                                    if (isvalidusername(&a->a_vals[i])) {
00206                                           ber_dupbv_x(&members[j],&a->a_vals[i],cbp->op->o_tmpmemctx);
00207                                           j++;
00208                                    }
00209                             }
00210                      }
00211                      a = b;
00212                      if ( a ) {
00213                             for (i=0; i<a->a_numvals; i++) {
00214                                    if (nssov_dn2uid(cbp->op,cbp->ni,&a->a_nvals[i],&members[j]))
00215                                           j++;
00216                             }
00217                      }
00218                      nummembers = j;
00219                      BER_BVZERO(&members[j]);
00220               } else {
00221                      members=NULL;
00222                      nummembers = 0;
00223               }
00224 
00225        } else {
00226               members=NULL;
00227               nummembers = 0;
00228        }
00229        /* write entries for all names and gids */
00230        for (i=0;!BER_BVISNULL(&names[i]);i++)
00231        {
00232               if (!isvalidgroupname(&names[i]))
00233               {
00234                      Debug(LDAP_DEBUG_ANY,"nssov: group entry %s contains invalid group name: \"%s\"\n",
00235                                                                                            entry->e_name.bv_val,names[i].bv_val,0);
00236               }
00237               else
00238               {
00239                      for (j=0;!BER_BVISNULL(&gids[j]);j++)
00240                      {
00241                             char *tmp;
00242                             int tmpint32;
00243                             gid_t gid;
00244                             gid = strtol(gids[j].bv_val, &tmp, 0);
00245                             if ( *tmp ) {
00246                                    Debug(LDAP_DEBUG_ANY,"nssov: group entry %s contains non-numeric %s value: \"%s\"\n",
00247                                           entry->e_name.bv_val, cbp->mi->mi_attrs[GID_KEY].an_desc->ad_cname.bv_val,
00248                                           names[i].bv_val);
00249                                    continue;
00250                             }
00251                             WRITE_INT32(cbp->fp,NSLCD_RESULT_BEGIN);
00252                             WRITE_BERVAL(cbp->fp,&names[i]);
00253                             WRITE_BERVAL(cbp->fp,&passwd);
00254                             WRITE_TYPE(cbp->fp,gid,gid_t);
00255                             /* write a list of values */
00256                             WRITE_INT32(cbp->fp,nummembers);
00257                             if (nummembers)
00258                             {
00259                                    int k;
00260                                    for (k=0;k<nummembers;k++) {
00261                                           WRITE_BERVAL(cbp->fp,&members[k]);
00262                                    }
00263                             }
00264                      }
00265               }
00266        }
00267        /* free and return */
00268        if (members!=NULL)
00269               ber_bvarray_free_x( members, cbp->op->o_tmpmemctx );
00270        return rc;
00271 }
00272 
00273 NSSOV_CB(group)
00274 
00275 NSSOV_HANDLE(
00276        group,byname,
00277        char fbuf[1024];
00278        struct berval filter = {sizeof(fbuf)};
00279        filter.bv_val = fbuf;
00280        READ_STRING(fp,cbp.buf);
00281        cbp.name.bv_len = tmpint32;
00282        cbp.name.bv_val = cbp.buf;
00283        if (!isvalidgroupname(&cbp.name)) {
00284               Debug(LDAP_DEBUG_ANY,"nssov_group_byname(%s): invalid group name\n",cbp.name.bv_val,0,0);
00285               return -1;
00286        }
00287        cbp.wantmembers = 1;
00288        cbp.ni = ni;
00289        BER_BVZERO(&cbp.gidnum);
00290        BER_BVZERO(&cbp.user);,
00291        Debug(LDAP_DEBUG_TRACE,"nslcd_group_byname(%s)\n",cbp.name.bv_val,0,0);,
00292        NSLCD_ACTION_GROUP_BYNAME,
00293        nssov_filter_byname(cbp.mi,CN_KEY,&cbp.name,&filter)
00294 )
00295 
00296 NSSOV_HANDLE(
00297        group,bygid,
00298        gid_t gid;
00299        char fbuf[1024];
00300        struct berval filter = {sizeof(fbuf)};
00301        filter.bv_val = fbuf;
00302        READ_TYPE(fp,gid,gid_t);
00303        cbp.gidnum.bv_val = cbp.buf;
00304        cbp.gidnum.bv_len = snprintf(cbp.buf,sizeof(cbp.buf),"%d",gid);
00305        cbp.wantmembers = 1;
00306        cbp.ni = ni;
00307        BER_BVZERO(&cbp.name);
00308        BER_BVZERO(&cbp.user);,
00309        Debug(LDAP_DEBUG_TRACE,"nssov_group_bygid(%s)\n",cbp.gidnum.bv_val,0,0);,
00310        NSLCD_ACTION_GROUP_BYGID,
00311        nssov_filter_byid(cbp.mi,GID_KEY,&cbp.gidnum,&filter)
00312 )
00313 
00314 NSSOV_HANDLE(
00315        group,bymember,
00316        char fbuf[1024];
00317        struct berval filter = {sizeof(fbuf)};
00318        filter.bv_val = fbuf;
00319        READ_STRING(fp,cbp.buf);
00320        cbp.user.bv_len = tmpint32;
00321        cbp.user.bv_val = cbp.buf;
00322        if (!isvalidusername(&cbp.user)) {
00323               Debug(LDAP_DEBUG_ANY,"nssov_group_bymember(%s): invalid user name\n",cbp.user.bv_val,0,0);
00324               return -1;
00325        }
00326        cbp.wantmembers = 0;
00327        cbp.ni = ni;
00328        BER_BVZERO(&cbp.name);
00329        BER_BVZERO(&cbp.gidnum);,
00330        Debug(LDAP_DEBUG_TRACE,"nssov_group_bymember(%s)\n",cbp.user.bv_val,0,0);,
00331        NSLCD_ACTION_GROUP_BYMEMBER,
00332        mkfilter_group_bymember(&cbp,&filter)
00333 )
00334 
00335 NSSOV_HANDLE(
00336        group,all,
00337        struct berval filter;
00338        /* no parameters to read */
00339        cbp.wantmembers = 1;
00340        cbp.ni = ni;
00341        BER_BVZERO(&cbp.name);
00342        BER_BVZERO(&cbp.gidnum);,
00343        Debug(LDAP_DEBUG_TRACE,"nssov_group_all()\n",0,0,0);,
00344        NSLCD_ACTION_GROUP_ALL,
00345        (filter=cbp.mi->mi_filter,0)
00346 )