Back to index

glibc  2.9
nisplus-initgroups.c
Go to the documentation of this file.
00001 /* Copyright (C) 1997, 2001, 2002, 2003, 2005, 2006
00002    Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <atomic.h>
00021 #include <nss.h>
00022 #include <grp.h>
00023 #include <ctype.h>
00024 #include <errno.h>
00025 #include <string.h>
00026 #include <bits/libc-lock.h>
00027 #include <rpcsvc/nis.h>
00028 
00029 #include "nss-nisplus.h"
00030 #include "nisplus-parser.h"
00031 #include <libnsl.h>
00032 #include <nis_intern.h>
00033 #include <nis_xdr.h>
00034 
00035 #define NISOBJVAL(col, obj) \
00036   ((obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
00037 
00038 #define NISOBJLEN(col, obj) \
00039   ((obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
00040 
00041 extern nis_name grp_tablename_val attribute_hidden;
00042 extern size_t grp_tablename_len attribute_hidden;
00043 extern enum nss_status _nss_grp_create_tablename (int *errnop);
00044 
00045 
00046 enum nss_status
00047 _nss_nisplus_initgroups_dyn (const char *user, gid_t group, long int *start,
00048                           long int *size, gid_t **groupsp, long int limit,
00049                           int *errnop)
00050 {
00051   if (grp_tablename_val == NULL)
00052     {
00053       enum nss_status status = _nss_grp_create_tablename (errnop);
00054 
00055       if (status != NSS_STATUS_SUCCESS)
00056        return status;
00057     }
00058 
00059   nis_result *result;
00060   char buf[strlen (user) + 12 + grp_tablename_len];
00061 
00062   snprintf (buf, sizeof (buf), "[members=%s],%s", user, grp_tablename_val);
00063 
00064   result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH | ALL_RESULTS, NULL, NULL);
00065 
00066   if (result == NULL)
00067     {
00068       *errnop = ENOMEM;
00069       return NSS_STATUS_TRYAGAIN;
00070     }
00071 
00072   if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
00073     {
00074       enum nss_status status = niserr2nss (result->status);
00075 
00076       nis_freeresult (result);
00077       return status;
00078     }
00079 
00080   if (NIS_RES_NUMOBJ (result) == 0)
00081     {
00082     errout:
00083       nis_freeresult (result);
00084       return NSS_STATUS_NOTFOUND;
00085     }
00086 
00087   gid_t *groups = *groupsp;
00088   nis_object *obj = NIS_RES_OBJECT (result);
00089   for (unsigned int cnt = 0; cnt < NIS_RES_NUMOBJ (result); ++cnt, ++obj)
00090     {
00091       if (__type_of (obj) != NIS_ENTRY_OBJ
00092          || strcmp (obj->EN_data.en_type, "group_tbl") != 0
00093          || obj->EN_data.en_cols.en_cols_len < 4)
00094        continue;
00095 
00096       char *numstr = NISOBJVAL (2, obj);
00097       size_t len = NISOBJLEN (2, obj);
00098       if (len == 0 || numstr[0] == '\0')
00099        continue;
00100 
00101       gid_t gid;
00102       char *endp;
00103       if (__builtin_expect (numstr[len - 1] != '\0', 0))
00104        {
00105          char numstrbuf[len + 1];
00106          memcpy (numstrbuf, numstr, len);
00107          numstrbuf[len] = '\0';
00108          gid = strtoul (numstrbuf, &endp, 10);
00109          if (*endp)
00110            continue;
00111        }
00112       else
00113        {
00114          gid = strtoul (numstr, &endp, 10);
00115          if (*endp)
00116            continue;
00117        }
00118 
00119       if (gid == group)
00120        continue;
00121 
00122       /* Insert this group.  */
00123       if (*start == *size)
00124        {
00125          /* Need a bigger buffer.  */
00126          long int newsize;
00127 
00128          if (limit > 0 && *size == limit)
00129            /* We reached the maximum.  */
00130            break;
00131 
00132          if (limit <= 0)
00133            newsize = 2 * *size;
00134          else
00135            newsize = MIN (limit, 2 * *size);
00136 
00137          gid_t *newgroups = realloc (groups, newsize * sizeof (*groups));
00138          if (newgroups == NULL)
00139            goto errout;
00140          *groupsp = groups = newgroups;
00141          *size = newsize;
00142        }
00143 
00144       groups[*start] = gid;
00145       *start += 1;
00146     }
00147 
00148   nis_freeresult (result);
00149   return NSS_STATUS_SUCCESS;
00150 }