enum nss_status
_nss_compat_initgroups_dyn (const char *user, gid_t group, long int *start,
			    long int *size, gid_t **groupsp, long int limit,
			    int *errnop)
{
  size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
  char *tmpbuf;
  enum nss_status status;
  ent_t intern = { TRUE, NULL, {NULL, 0, 0} };

  status = internal_setgrent (&intern);
  if (status != NSS_STATUS_SUCCESS)
    return status;

  tmpbuf = __alloca (buflen);

  do
    {
      while ((status = internal_getgrent_r (&intern, tmpbuf, buflen,
					    user, group, start, size,
					    groupsp, limit, errnop))
	     == NSS_STATUS_TRYAGAIN && *errnop == ERANGE)
	tmpbuf = extend_alloca (tmpbuf, buflen, 2 * buflen);
    }
  while (status == NSS_STATUS_SUCCESS);

  internal_endgrent (&intern);

  return NSS_STATUS_SUCCESS;
}
示例#2
0
文件: nss_group.c 项目: nguay/SSSD
enum nss_status _nss_sss_getgrent_r(struct group *result,
                                    char *buffer, size_t buflen, int *errnop)
{
    enum nss_status nret;

    sss_nss_lock();
    nret = internal_getgrent_r(result, buffer, buflen, errnop);
    sss_nss_unlock();

    return nret;
}
示例#3
0
enum nss_status
_nss_compat_initgroups_dyn (const char *user, gid_t group, long int *start,
			    long int *size, gid_t **groupsp, long int limit,
			    int *errnop)
{
  size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
  char *tmpbuf;
  enum nss_status status;
  ent_t intern = { true, false, false, NULL, {NULL, 0, 0} };
  bool use_malloc = false;

  status = internal_setgrent (&intern);
  if (status != NSS_STATUS_SUCCESS)
    return status;

  tmpbuf = __alloca (buflen);

  do
    {
      while ((status = internal_getgrent_r (&intern, tmpbuf, buflen,
					    user, group, start, size,
					    groupsp, limit, errnop))
	     == NSS_STATUS_TRYAGAIN && *errnop == ERANGE)
        if (__libc_use_alloca (buflen * 2))
          tmpbuf = extend_alloca (tmpbuf, buflen, 2 * buflen);
        else
          {
            buflen *= 2;
            char *newbuf = realloc (use_malloc ? tmpbuf : NULL, buflen);
            if (newbuf == NULL)
              {
                status = NSS_STATUS_TRYAGAIN;
                goto done;
              }
            use_malloc = true;
            tmpbuf = newbuf;
          }
    }
  while (status == NSS_STATUS_SUCCESS);

  status = NSS_STATUS_SUCCESS;

 done:
  if (use_malloc)
    free (tmpbuf);

  internal_endgrent (&intern);

  return status;
}
示例#4
0
enum nss_status
_nss_nis_initgroups_dyn (const char *user, gid_t group, long int *start,
			 long int *size, gid_t **groupsp, long int limit,
			 int *errnop)
{
  /* We always need the domain name.  */
  char *domainname;
  if (yp_get_default_domain (&domainname))
    return NSS_STATUS_UNAVAIL;

  /* Check whether we are supposed to use the netid.byname map.  */
  if (_nsl_default_nss () & NSS_FLAG_NETID_AUTHORITATIVE)
    {
      /* We need the user ID.  */
      uid_t uid;

      if (get_uid (user, &uid) == 0
	  && initgroups_netid (uid, group, start, size, groupsp, limit,
			       errnop, domainname) == NSS_STATUS_SUCCESS)
	return NSS_STATUS_SUCCESS;
    }

  struct group grpbuf, *g;
  size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
  char *tmpbuf;
  enum nss_status status;
  intern_t intern = { NULL, NULL, 0 };
  gid_t *groups = *groupsp;

  status = internal_setgrent (domainname, &intern);
  if (status != NSS_STATUS_SUCCESS)
    return status;

  tmpbuf = __alloca (buflen);

  while (1)
    {
      while ((status =
	      internal_getgrent_r (&grpbuf, tmpbuf, buflen, errnop,
				   &intern)) == NSS_STATUS_TRYAGAIN
             && *errnop == ERANGE)
	tmpbuf = extend_alloca (tmpbuf, buflen, 2 * buflen);

      if (status != NSS_STATUS_SUCCESS)
	{
	  if (status == NSS_STATUS_NOTFOUND)
	    status = NSS_STATUS_SUCCESS;
	  goto done;
	}

      g = &grpbuf;
      if (g->gr_gid != group)
        {
          char **m;

          for (m = g->gr_mem; *m != NULL; ++m)
            if (strcmp (*m, user) == 0)
              {
                /* Matches user.  Insert this group.  */
                if (*start == *size)
                  {
                    /* Need a bigger buffer.  */
		    gid_t *newgroups;
		    long int newsize;

		    if (limit > 0 && *size == limit)
		      /* We reached the maximum.  */
		      goto done;

		    if (limit <= 0)
		      newsize = 2 * *size;
		    else
		      newsize = MIN (limit, 2 * *size);

		    newgroups = realloc (groups, newsize * sizeof (*groups));
		    if (newgroups == NULL)
		      {
			status = NSS_STATUS_TRYAGAIN;
			*errnop = errno;
			goto done;
		      }
		    *groupsp = groups = newgroups;
                    *size = newsize;
                  }

                groups[*start] = g->gr_gid;
		*start += 1;

                break;
              }
        }
    }

done:
  while (intern.start != NULL)
    {
      intern.next = intern.start;
      intern.start = intern.start->next;
      free (intern.next);
    }

  return status;
}
示例#5
0
文件: nss_group.c 项目: nguay/SSSD
static enum nss_status internal_getgrent_r(struct group *result,
                                           char *buffer, size_t buflen,
                                           int *errnop)
{
    struct sss_cli_req_data rd;
    struct sss_nss_gr_rep grrep;
    uint8_t *repbuf;
    size_t replen;
    enum nss_status nret;
    uint32_t num_entries;
    int ret;

    /* Caught once glibc passing in buffer == 0x0 */
    if (!buffer || !buflen) return ERANGE;

    /* if there are leftovers return the next one */
    if (sss_nss_getgrent_data.data != NULL &&
        sss_nss_getgrent_data.ptr < sss_nss_getgrent_data.len) {

        repbuf = (uint8_t *)sss_nss_getgrent_data.data +
                    sss_nss_getgrent_data.ptr;
        replen = sss_nss_getgrent_data.len -
                    sss_nss_getgrent_data.ptr;

        grrep.result = result;
        grrep.buffer = buffer;
        grrep.buflen = buflen;

        ret = sss_nss_getgr_readrep(&grrep, repbuf, &replen);
        if (ret) {
            *errnop = ret;
            return NSS_STATUS_TRYAGAIN;
        }

        /* advance buffer pointer */
        sss_nss_getgrent_data.ptr = sss_nss_getgrent_data.len - replen;

        return NSS_STATUS_SUCCESS;
    }

    /* release memory if any */
    sss_nss_getgrent_data_clean();

    /* retrieve no more than SSS_NSS_MAX_ENTRIES at a time */
    num_entries = SSS_NSS_MAX_ENTRIES;
    rd.len = sizeof(uint32_t);
    rd.data = &num_entries;

    nret = sss_nss_make_request(SSS_NSS_GETGRENT, &rd,
                                &repbuf, &replen, errnop);
    if (nret != NSS_STATUS_SUCCESS) {
        return nret;
    }

    /* no results if not found */
    if ((((uint32_t *)repbuf)[0] == 0) || (replen - 8 == 0)) {
        free(repbuf);
        return NSS_STATUS_NOTFOUND;
    }

    sss_nss_getgrent_data.data = repbuf;
    sss_nss_getgrent_data.len = replen;
    sss_nss_getgrent_data.ptr = 8; /* skip metadata fields */

    /* call again ourselves, this will return the first result */
    return internal_getgrent_r(result, buffer, buflen, errnop);
}