Beispiel #1
0
/* -1 == not found
    0 == function found
    1 == finished */
int
__nss_lookup (service_user **ni, const char *fct_name, void **fctp)
{
  *fctp = __nss_lookup_function (*ni, fct_name);

  while (*fctp == NULL
	 && nss_next_action (*ni, NSS_STATUS_UNAVAIL) == NSS_ACTION_CONTINUE
	 && (*ni)->next != NULL)
    {
      *ni = (*ni)->next;

      *fctp = __nss_lookup_function (*ni, fct_name);
    }

  return *fctp != NULL ? 0 : (*ni)->next == NULL ? 1 : -1;
}
Beispiel #2
0
/* -1 == not found
    0 == adjusted for next function
    1 == finished */
int
__nss_next2 (service_user **ni, const char *fct_name, const char *fct2_name,
	     void **fctp, int status, int all_values)
{
  if (all_values)
    {
      if (nss_next_action (*ni, NSS_STATUS_TRYAGAIN) == NSS_ACTION_RETURN
	  && nss_next_action (*ni, NSS_STATUS_UNAVAIL) == NSS_ACTION_RETURN
	  && nss_next_action (*ni, NSS_STATUS_NOTFOUND) == NSS_ACTION_RETURN
	  && nss_next_action (*ni, NSS_STATUS_SUCCESS) == NSS_ACTION_RETURN)
	return 1;
    }
  else
    {
      /* This is really only for debugging.  */
      if (__builtin_expect (NSS_STATUS_TRYAGAIN > status
			    || status > NSS_STATUS_RETURN, 0))
	 __libc_fatal ("illegal status in __nss_next");

       if (nss_next_action (*ni, status) == NSS_ACTION_RETURN)
	 return 1;
    }

  if ((*ni)->next == NULL)
    return -1;

  do
    {
      *ni = (*ni)->next;

      *fctp = __nss_lookup_function (*ni, fct_name);
      if (*fctp == NULL && fct2_name != NULL)
	*fctp = __nss_lookup_function (*ni, fct2_name);
    }
  while (*fctp == NULL
	 && nss_next_action (*ni, NSS_STATUS_UNAVAIL) == NSS_ACTION_CONTINUE
	 && (*ni)->next != NULL);

  return *fctp != NULL ? 0 : -1;
}
Beispiel #3
0
static int
internal_getgrouplist (const char *user, gid_t group, long int *size,
		       gid_t **groupsp, long int limit)
{
#ifdef USE_NSCD
  if (__nss_not_use_nscd_group > 0
      && ++__nss_not_use_nscd_group > NSS_NSCD_RETRY)
    __nss_not_use_nscd_group = 0;
  if (!__nss_not_use_nscd_group
      && !__nss_database_custom[NSS_DBSIDX_group])
    {
      int n = __nscd_getgrouplist (user, group, size, groupsp, limit);
      if (n >= 0)
	return n;

      /* nscd is not usable.  */
      __nss_not_use_nscd_group = 1;
    }
#endif

  enum nss_status status = NSS_STATUS_UNAVAIL;
  int no_more = 0;

  /* Never store more than the starting *SIZE number of elements.  */
  assert (*size > 0);
  (*groupsp)[0] = group;
  /* Start is one, because we have the first group as parameter.  */
  long int start = 1;

  if (__nss_initgroups_database == NULL)
    {
      if (__nss_database_lookup ("initgroups", NULL, "",
				 &__nss_initgroups_database) < 0)
	{
	  if (__nss_group_database == NULL)
	    no_more = __nss_database_lookup ("group", NULL, "compat files",
					     &__nss_group_database);

	  __nss_initgroups_database = __nss_group_database;
	}
      else
	use_initgroups_entry = true;
    }
  else
    /* __nss_initgroups_database might have been set through
       __nss_configure_lookup in which case use_initgroups_entry was
       not set here.  */
    use_initgroups_entry = __nss_initgroups_database != __nss_group_database;

  service_user *nip = __nss_initgroups_database;
  while (! no_more)
    {
      long int prev_start = start;

      initgroups_dyn_function fct = __nss_lookup_function (nip,
							   "initgroups_dyn");
      if (fct == NULL)
	status = compat_call (nip, user, group, &start, size, groupsp,
			      limit, &errno);
      else
	status = DL_CALL_FCT (fct, (user, group, &start, size, groupsp,
				    limit, &errno));

      /* Remove duplicates.  */
      long int cnt = prev_start;
      while (cnt < start)
	{
	  long int inner;
	  for (inner = 0; inner < prev_start; ++inner)
	    if ((*groupsp)[inner] == (*groupsp)[cnt])
	      break;

	  if (inner < prev_start)
	    (*groupsp)[cnt] = (*groupsp)[--start];
	  else
	    ++cnt;
	}

      /* This is really only for debugging.  */
      if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_RETURN)
	__libc_fatal ("illegal status in internal_getgrouplist");

      /* For compatibility reason we will continue to look for more
	 entries using the next service even though data has already
	 been found if the nsswitch.conf file contained only a 'groups'
	 line and no 'initgroups' line.  If the latter is available
	 we always respect the status.  This means that the default
	 for successful lookups is to return.  */
      if ((use_initgroups_entry || status != NSS_STATUS_SUCCESS)
	  && nss_next_action (nip, status) == NSS_ACTION_RETURN)
	 break;

      if (nip->next == NULL)
	no_more = -1;
      else
	nip = nip->next;
    }

  return start;
}