Exemple #1
0
/* Set up NIP to run through the services.  Return nonzero if there are no
   services (left).  */
static int
setup (void **fctp, service_user **nipp)
{
  /* Remember the first service_entry, it's always the same.  */
  static bool startp_initialized;
  static service_user *startp;
  int no_more;

  if (!startp_initialized)
    {
      /* Executing this more than once at the same time must yield the
	 same result every time.  So we need no locking.  */
      no_more = __nss_netgroup_lookup (nipp, "setnetgrent", fctp);
      startp = no_more ? (service_user *) -1 : *nipp;
      PTR_MANGLE (startp);
      atomic_write_barrier ();
      startp_initialized = true;
    }
  else
    {
      service_user *nip = startp;
      PTR_DEMANGLE (nip);
      if (nip == (service_user *) -1)
	/* No services at all.  */
	return 1;

      /* Reset to the beginning of the service list.  */
      *nipp = nip;
      /* Look up the first function.  */
      no_more = __nss_lookup (nipp, "setnetgrent", NULL, fctp);
    }
  return no_more;
}
/* Set up NIP to run through the services.  If ALL is zero, use NIP's
   current location if it's not nil.  Return nonzero if there are no
   services (left).  */
static enum nss_status
setup (void **fctp, const char *func_name, int all, service_user **nipp)
{
  /* Remember the first service_entry, it's always the same.  */
  static service_user *startp;
  int no_more;

  if (startp == NULL)
    {
      /* Executing this more than once at the same time must yield the
	 same result every time.  So we need no locking.  */
      no_more = __nss_netgroup_lookup (nipp, func_name, fctp);
      startp = no_more ? (service_user *) -1 : *nipp;
    }
  else if (startp == (service_user *) -1)
    /* No services at all.  */
    return 1;
  else
    {
      if (all || *nipp == NULL)
	/* Reset to the beginning of the service list.  */
	*nipp = startp;
      /* Look up the first function.  */
      no_more = __nss_lookup (nipp, func_name, fctp);
    }
  return no_more;
}
int
internal_function
DB_LOOKUP_FCT (service_user **ni, const char *fct_name, const char *fct2_name,
	       void **fctp)
{
  if (DATABASE_NAME_SYMBOL == NULL
      && __nss_database_lookup (DATABASE_NAME_STRING, ALTERNATE_NAME_STRING,
				DEFAULT_CONFIG, &DATABASE_NAME_SYMBOL) < 0)
    return -1;

  *ni = DATABASE_NAME_SYMBOL;

  return __nss_lookup (ni, fct_name, fct2_name, fctp);
}
/* Test whether given (host,user,domain) triple is in NETGROUP.  */
int
innetgr (const char *netgroup, const char *host, const char *user,
	 const char *domain)
{
  union
  {
    int (*f) (const char *, struct __netgrent *);
    void *ptr;
  } setfct;
  union
  {
    void (*f) (struct __netgrent *);
    void *ptr;
  } endfct;
  union
  {
    int (*f) (struct __netgrent *, char *, size_t, int *);
    void *ptr;
  } getfct;
  struct __netgrent entry;
  int result = 0;
  const char *current_group = netgroup;
  int real_entry = 0;

  memset (&entry, '\0', sizeof (entry));

  /* Walk through the services until we found an answer or we shall
     not work further.  We can do some optimization here.  Since all
     services must provide the `setnetgrent' function we can do all
     the work during one walk through the service list.  */
  while (1)
    {
      int no_more = setup (&setfct.ptr, "setnetgrent", 1, &entry.nip);
      while (! no_more)
	{
	  /* Open netgroup.  */
	  enum nss_status status = (*setfct.f) (current_group, &entry);

	  if (status == NSS_STATUS_SUCCESS
	      && __nss_lookup (&entry.nip, "getnetgrent_r", &getfct.ptr) == 0)
	    {
	      char buffer[1024];

	      while ((*getfct.f) (&entry, buffer, sizeof buffer, &errno)
		     == NSS_STATUS_SUCCESS)
		{
		  if (entry.type == group_val)
		    {
		      /* Make sure we haven't seen the name before.  */
		      struct name_list *namep;

		      for (namep = entry.known_groups; namep != NULL;
			   namep = namep->next)
			if (strcmp (entry.val.group, namep->name) == 0)
			  break;
		      if (namep == NULL
			  && strcmp (netgroup, entry.val.group) != 0)
			{
			  size_t group_len = strlen (entry.val.group) + 1;
			  namep =
			    (struct name_list *) malloc (sizeof (*namep)
							 + group_len);
			  if (namep == NULL)
			    {
			      /* Out of memory, simply return.  */
			      result = -1;
			      break;
			    }

			  namep->next = entry.needed_groups;
			  memcpy (namep->name, entry.val.group, group_len);
			  entry.needed_groups = namep;
			}
		    }
		  else
		    {
		      real_entry = 1;

		      if ((entry.val.triple.host == NULL || host == NULL
			   || __strcasecmp (entry.val.triple.host, host) == 0)
			  && (entry.val.triple.user == NULL || user == NULL
			      || strcmp (entry.val.triple.user, user) == 0)
			  && (entry.val.triple.domain == NULL || domain == NULL
			      || __strcasecmp (entry.val.triple.domain,
					       domain) == 0))
			{
			  result = 1;
			  break;
			}
		    }
		}

	      if (result != 0)
		break;

	      /* If we found one service which does know the given
		 netgroup we don't try further.  */
	      status = NSS_STATUS_RETURN;
	    }

	  /* Free all resources of the service.  */
	  if (__nss_lookup (&entry.nip, "endnetgrent", &endfct.ptr) == 0)
	    (*endfct.f) (&entry);

	  /* Look for the next service.  */
	  no_more = __nss_next (&entry.nip, "setnetgrent",
				&setfct.ptr, status, 0);
	}

      if (result == 0 && entry.needed_groups != NULL)
	{
	  struct name_list *tmp = entry.needed_groups;
	  entry.needed_groups = tmp->next;
	  tmp->next = entry.known_groups;
	  entry.known_groups = tmp;
	  current_group = entry.known_groups->name;
	  continue;
	}

      /* No way out.  */
      break;
    }

  /* Free the memory.  */
  free_memory (&entry);

  return result;
}