Blame nss/netgroup.c

Packit 6bd9ab
/*
Packit 6bd9ab
   netgroup.c - NSS lookup functions for netgroup entries
Packit 6bd9ab
Packit 6bd9ab
   Copyright (C) 2006 West Consulting
Packit 6bd9ab
   Copyright (C) 2006-2015 Arthur de Jong
Packit 6bd9ab
   Copyright (C) 2010 Symas Corporation
Packit 6bd9ab
Packit 6bd9ab
   This library is free software; you can redistribute it and/or
Packit 6bd9ab
   modify it under the terms of the GNU Lesser General Public
Packit 6bd9ab
   License as published by the Free Software Foundation; either
Packit 6bd9ab
   version 2.1 of the License, or (at your option) any later version.
Packit 6bd9ab
Packit 6bd9ab
   This library is distributed in the hope that it will be useful,
Packit 6bd9ab
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6bd9ab
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6bd9ab
   Lesser General Public License for more details.
Packit 6bd9ab
Packit 6bd9ab
   You should have received a copy of the GNU Lesser General Public
Packit 6bd9ab
   License along with this library; if not, write to the Free Software
Packit 6bd9ab
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit 6bd9ab
   02110-1301 USA
Packit 6bd9ab
*/
Packit 6bd9ab
Packit 6bd9ab
#include "config.h"
Packit 6bd9ab
Packit 6bd9ab
#include <stdlib.h>
Packit 6bd9ab
#include <string.h>
Packit 6bd9ab
#include <errno.h>
Packit 6bd9ab
Packit 6bd9ab
#include "prototypes.h"
Packit 6bd9ab
#include "common.h"
Packit 6bd9ab
#include "compat/attrs.h"
Packit 6bd9ab
#include "common/set.h"
Packit 6bd9ab
Packit 6bd9ab
/* function for reading a single result entry */
Packit 6bd9ab
static nss_status_t read_netgrent_line(TFILE *fp, struct __netgrent *result,
Packit 6bd9ab
                                       char *buffer, size_t buflen, int *errnop)
Packit 6bd9ab
{
Packit 6bd9ab
  int32_t tmpint32;
Packit 6bd9ab
  int type;
Packit 6bd9ab
  size_t bufptr = 0;
Packit 6bd9ab
  /* read netgroup type */
Packit 6bd9ab
  READ_INT32(fp, type);
Packit 6bd9ab
  if (type == NSLCD_NETGROUP_TYPE_NETGROUP)
Packit 6bd9ab
  {
Packit 6bd9ab
    /* the response is a reference to another netgroup */
Packit 6bd9ab
    result->type = group_val;
Packit 6bd9ab
    READ_BUF_STRING(fp, result->val.group);
Packit 6bd9ab
    return NSS_STATUS_SUCCESS;
Packit 6bd9ab
  }
Packit 6bd9ab
  else if (type == NSLCD_NETGROUP_TYPE_TRIPLE)
Packit 6bd9ab
  {
Packit 6bd9ab
    /* the response is a host/user/domain triple */
Packit 6bd9ab
    result->type = triple_val;
Packit 6bd9ab
    /* read host and revert to NULL on empty string */
Packit 6bd9ab
    READ_BUF_STRING(fp, result->val.triple.host);
Packit 6bd9ab
#ifdef NSS_FLAVOUR_GLIBC
Packit 6bd9ab
    if (result->val.triple.host[0] == '\0')
Packit 6bd9ab
    {
Packit 6bd9ab
      result->val.triple.host = NULL;
Packit 6bd9ab
      bufptr--; /* free unused space */
Packit 6bd9ab
    }
Packit 6bd9ab
#endif /* NSS_FLAVOUR_GLIBC */
Packit 6bd9ab
    /* read user and revert to NULL on empty string */
Packit 6bd9ab
    READ_BUF_STRING(fp, result->val.triple.user);
Packit 6bd9ab
#ifdef NSS_FLAVOUR_GLIBC
Packit 6bd9ab
    if (result->val.triple.user[0] == '\0')
Packit 6bd9ab
    {
Packit 6bd9ab
      result->val.triple.user = NULL;
Packit 6bd9ab
      bufptr--; /* free unused space */
Packit 6bd9ab
    }
Packit 6bd9ab
#endif /* NSS_FLAVOUR_GLIBC */
Packit 6bd9ab
    /* read domain and revert to NULL on empty string */
Packit 6bd9ab
    READ_BUF_STRING(fp, result->val.triple.domain);
Packit 6bd9ab
#ifdef NSS_FLAVOUR_GLIBC
Packit 6bd9ab
    if (result->val.triple.domain[0] == '\0')
Packit 6bd9ab
    {
Packit 6bd9ab
      result->val.triple.domain = NULL;
Packit 6bd9ab
      bufptr--; /* free unused space */
Packit 6bd9ab
    }
Packit 6bd9ab
#endif /* NSS_FLAVOUR_GLIBC */
Packit 6bd9ab
    return NSS_STATUS_SUCCESS;
Packit 6bd9ab
  }
Packit 6bd9ab
  else if (type == NSLCD_NETGROUP_TYPE_END)
Packit 6bd9ab
    /* make NSS_NAME(getnetgrent_r)() indicate the end of the netgroup */
Packit 6bd9ab
    return NSS_STATUS_RETURN;
Packit 6bd9ab
  /* we got something unexpected */
Packit 6bd9ab
  ERROR_OUT_NOSUCCESS(fp);
Packit 6bd9ab
  return NSS_STATUS_UNAVAIL;
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
#ifdef NSS_FLAVOUR_GLIBC
Packit 6bd9ab
Packit 6bd9ab
/* thread-local file pointer to an ongoing request */
Packit 6bd9ab
static TLS TFILE *netgrentfp;
Packit 6bd9ab
Packit 6bd9ab
/* start a request to get a netgroup by name */
Packit 6bd9ab
nss_status_t NSS_NAME(setnetgrent)(const char *group,
Packit 6bd9ab
                                   struct __netgrent UNUSED(*result))
Packit 6bd9ab
{
Packit 6bd9ab
  /* we cannot use NSS_SETENT() here because we have a parameter that is only
Packit 6bd9ab
     available in this function */
Packit 6bd9ab
  int32_t tmpint32;
Packit 6bd9ab
  int errnocp;
Packit 6bd9ab
  int *errnop = &errnocp;
Packit 6bd9ab
  NSS_EXTRA_DEFS
Packit 6bd9ab
  NSS_AVAILCHECK;
Packit 6bd9ab
  /* check parameter */
Packit 6bd9ab
  if ((group == NULL) || (group[0] == '\0'))
Packit 6bd9ab
    return NSS_STATUS_UNAVAIL;
Packit 6bd9ab
  /* open a new stream and write the request */
Packit 6bd9ab
  NSLCD_REQUEST(netgrentfp, NSLCD_ACTION_NETGROUP_BYNAME,
Packit 6bd9ab
                WRITE_STRING(netgrentfp, group));
Packit 6bd9ab
  /* read response code */
Packit 6bd9ab
  READ_RESPONSE_CODE(netgrentfp);
Packit 6bd9ab
  SKIP_STRING(netgrentfp); /* netgroup name */
Packit 6bd9ab
  return NSS_STATUS_SUCCESS;
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
/* get a single netgroup tuple from the stream */
Packit 6bd9ab
nss_status_t NSS_NAME(getnetgrent_r)(struct __netgrent *result,
Packit 6bd9ab
                                     char *buffer, size_t buflen, int *errnop)
Packit 6bd9ab
{
Packit 6bd9ab
  nss_status_t retv;
Packit 6bd9ab
  NSS_EXTRA_DEFS;
Packit 6bd9ab
  NSS_AVAILCHECK;
Packit 6bd9ab
  NSS_BUFCHECK;
Packit 6bd9ab
  /* check that we have a valid file descriptor */
Packit 6bd9ab
  if (netgrentfp == NULL)
Packit 6bd9ab
    return NSS_STATUS_UNAVAIL;
Packit 6bd9ab
  /* prepare for buffer errors */
Packit 6bd9ab
  tio_mark(netgrentfp);
Packit 6bd9ab
  /* read a response */
Packit 6bd9ab
  retv = read_netgrent_line(netgrentfp, result, buffer, buflen, errnop);
Packit 6bd9ab
  /* check read result */
Packit 6bd9ab
  if (retv == NSS_STATUS_TRYAGAIN)
Packit 6bd9ab
  {
Packit 6bd9ab
    /* if we have a full buffer try to reset the stream */
Packit 6bd9ab
    if (tio_reset(netgrentfp))
Packit 6bd9ab
    {
Packit 6bd9ab
      /* reset failed, we close and give up with a permanent error
Packit 6bd9ab
         because we cannot retry just the getent() call because it
Packit 6bd9ab
         may not be only the first entry that failed */
Packit 6bd9ab
      tio_close(netgrentfp);
Packit 6bd9ab
      netgrentfp = NULL;
Packit 6bd9ab
      *errnop = EINVAL;
Packit 6bd9ab
      return NSS_STATUS_UNAVAIL;
Packit 6bd9ab
    }
Packit 6bd9ab
  }
Packit 6bd9ab
  else if ((retv != NSS_STATUS_SUCCESS) && (retv != NSS_STATUS_RETURN))
Packit 6bd9ab
    netgrentfp = NULL; /* file should be closed by now */
Packit 6bd9ab
  return retv;
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
/* close the stream opened with setnetgrent() above */
Packit 6bd9ab
nss_status_t NSS_NAME(endnetgrent)(struct __netgrent UNUSED(*result))
Packit 6bd9ab
{
Packit 6bd9ab
  NSS_ENDENT(netgrentfp);
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
#endif /* NSS_FLAVOUR_GLIBC */
Packit 6bd9ab
Packit 6bd9ab
#ifdef NSS_FLAVOUR_SOLARIS
Packit 6bd9ab
Packit 6bd9ab
/* this is the custom backend structure for the {set,get,end}ent() functions */
Packit 6bd9ab
struct setnetgrent_backend {
Packit 6bd9ab
  nss_backend_op_t *ops; /* function-pointer table */
Packit 6bd9ab
  int n_ops;             /* number of function pointers */
Packit 6bd9ab
  TFILE *fp;             /* the file pointer for {set,get,end}ent() functions */
Packit 6bd9ab
  SET *seen_groups;      /* netgroups seen, for loop detection */
Packit 6bd9ab
  SET *unseen_groups;    /* netgroups that need to be chased */
Packit 6bd9ab
};
Packit 6bd9ab
Packit 6bd9ab
/* easy way to get sets from back-end */
Packit 6bd9ab
#define NETGROUP_BE(be) ((struct setnetgrent_backend*)(be))
Packit 6bd9ab
Packit 6bd9ab
/* access arguments */
Packit 6bd9ab
#define SETNETGRENT_ARGS(args) ((struct nss_setnetgrent_args *)(args))
Packit 6bd9ab
#define GETNETGRENT_ARGS(args) ((struct nss_getnetgrent_args *)(args))
Packit 6bd9ab
#define INNETGR_ARGS(ARGS)     ((struct nss_innetgr_args *)(args))
Packit 6bd9ab
Packit 6bd9ab
/* return a netgroup that has not been traversed (the caller should use
Packit 6bd9ab
   free() to free it) */
Packit 6bd9ab
static char *find_unseen_netgroup(struct setnetgrent_backend *be)
Packit 6bd9ab
{
Packit 6bd9ab
  char *group;
Packit 6bd9ab
  while (1)
Packit 6bd9ab
  {
Packit 6bd9ab
    group = set_pop(be->unseen_groups);
Packit 6bd9ab
    if (group == NULL)
Packit 6bd9ab
      return NULL;
Packit 6bd9ab
    if (!set_contains(be->seen_groups, group))
Packit 6bd9ab
      return group;
Packit 6bd9ab
    free(group);
Packit 6bd9ab
  }
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
static nss_status_t start_netgroup_request(struct setnetgrent_backend *be,
Packit 6bd9ab
                                           const char *group)
Packit 6bd9ab
{
Packit 6bd9ab
  /* we cannot use NSS_SETENT() here because we have a parameter that is only
Packit 6bd9ab
     available in this function */
Packit 6bd9ab
  int32_t tmpint32;
Packit 6bd9ab
  int *errnop = &errno;
Packit 6bd9ab
  /* check parameter */
Packit 6bd9ab
  if ((group == NULL) || (group[0] == '\0'))
Packit 6bd9ab
    return NSS_STATUS_UNAVAIL;
Packit 6bd9ab
  set_add(be->seen_groups, group);
Packit 6bd9ab
  /* open a new stream and write the request */
Packit 6bd9ab
  NSLCD_REQUEST(NETGROUP_BE(be)->fp, NSLCD_ACTION_NETGROUP_BYNAME,
Packit 6bd9ab
                WRITE_STRING(NETGROUP_BE(be)->fp, group));
Packit 6bd9ab
  /* read response code */
Packit 6bd9ab
  READ_RESPONSE_CODE(NETGROUP_BE(be)->fp);
Packit 6bd9ab
  SKIP_STRING(NETGROUP_BE(be)->fp); /* netgroup name */
Packit 6bd9ab
  return NSS_STATUS_SUCCESS;
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
static nss_status_t netgroup_setnetgrent_setnetgrent(nss_backend_t UNUSED(*be),
Packit 6bd9ab
                                                     void UNUSED(*args))
Packit 6bd9ab
{
Packit 6bd9ab
  return NSS_STATUS_SUCCESS;
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
static nss_status_t netgroup_setnetgrent_getnetgrent(nss_backend_t *be,
Packit 6bd9ab
                                                     void *args)
Packit 6bd9ab
{
Packit 6bd9ab
  struct __netgrent result;
Packit 6bd9ab
  nss_status_t retv;
Packit 6bd9ab
  /* check that we have a valid file descriptor */
Packit 6bd9ab
  if (NETGROUP_BE(be)->fp == NULL)
Packit 6bd9ab
    return NSS_STATUS_UNAVAIL;
Packit 6bd9ab
  /* go over the result lines */
Packit 6bd9ab
  while (1)
Packit 6bd9ab
  {
Packit 6bd9ab
    /* prepare for buffer errors */
Packit 6bd9ab
    tio_mark(NETGROUP_BE(be)->fp);
Packit 6bd9ab
    /* read single line from the netgroup information */
Packit 6bd9ab
    retv = read_netgrent_line(NETGROUP_BE(be)->fp, &result, GETNETGRENT_ARGS(args)->buffer,
Packit 6bd9ab
                              GETNETGRENT_ARGS(args)->buflen, &errno);
Packit 6bd9ab
    /* check read result */
Packit 6bd9ab
    if ((retv == NSS_STATUS_SUCCESS) && (result.type == group_val))
Packit 6bd9ab
    {
Packit 6bd9ab
      /* a netgroup nested within the current netgroup */
Packit 6bd9ab
      set_add(NETGROUP_BE(be)->unseen_groups, result.val.group);
Packit 6bd9ab
    }
Packit 6bd9ab
    else if ((retv == NSS_STATUS_SUCCESS) && (result.type == triple_val))
Packit 6bd9ab
    {
Packit 6bd9ab
      /* a netgroup line we can return */
Packit 6bd9ab
      GETNETGRENT_ARGS(args)->status = NSS_NETGR_FOUND;
Packit 6bd9ab
      GETNETGRENT_ARGS(args)->retp[NSS_NETGR_MACHINE] = (char *)result.val.triple.host;
Packit 6bd9ab
      GETNETGRENT_ARGS(args)->retp[NSS_NETGR_USER] = (char *)result.val.triple.user;
Packit 6bd9ab
      GETNETGRENT_ARGS(args)->retp[NSS_NETGR_DOMAIN] = (char *)result.val.triple.domain;
Packit 6bd9ab
      return NSS_STATUS_SUCCESS;
Packit 6bd9ab
    }
Packit 6bd9ab
    else if (retv == NSS_STATUS_TRYAGAIN)
Packit 6bd9ab
    {
Packit 6bd9ab
      /* we have a full buffer, try to reset the stream */
Packit 6bd9ab
      if (tio_reset(NETGROUP_BE(be)->fp))
Packit 6bd9ab
      {
Packit 6bd9ab
        /* reset failed, we close and give up with a permanent error
Packit 6bd9ab
           because we cannot retry just the getent() call because it
Packit 6bd9ab
           may not be only the first entry that failed */
Packit 6bd9ab
        tio_close(NETGROUP_BE(be)->fp);
Packit 6bd9ab
        NETGROUP_BE(be)->fp = NULL;
Packit 6bd9ab
        return NSS_STATUS_UNAVAIL;
Packit 6bd9ab
      }
Packit 6bd9ab
      GETNETGRENT_ARGS(args)->status = NSS_NETGR_NOMEM;
Packit 6bd9ab
      return NSS_STATUS_TRYAGAIN;
Packit 6bd9ab
    }
Packit 6bd9ab
    else if (retv == NSS_STATUS_RETURN)
Packit 6bd9ab
    {
Packit 6bd9ab
      /* done with the current netgroup */
Packit 6bd9ab
      tio_close(NETGROUP_BE(be)->fp);
Packit 6bd9ab
      NETGROUP_BE(be)->fp = NULL;
Packit 6bd9ab
      /* explore nested netgroups, if any */
Packit 6bd9ab
      while (retv != NSS_STATUS_SUCCESS)
Packit 6bd9ab
      {
Packit 6bd9ab
        /* find a nested netgroup to pursue further */
Packit 6bd9ab
        char *group = find_unseen_netgroup(NETGROUP_BE(be));
Packit 6bd9ab
        if (group == NULL)
Packit 6bd9ab
        {
Packit 6bd9ab
          /* no more netgroups to explore */
Packit 6bd9ab
          GETNETGRENT_ARGS(args)->status = NSS_NETGR_NO;
Packit 6bd9ab
          return NSS_STATUS_SUCCESS;
Packit 6bd9ab
        }
Packit 6bd9ab
        /* start a new search with this netgroup */
Packit 6bd9ab
        retv = start_netgroup_request(NETGROUP_BE(be), group);
Packit 6bd9ab
        free(group);
Packit 6bd9ab
      }
Packit 6bd9ab
    }
Packit 6bd9ab
    else
Packit 6bd9ab
    {
Packit 6bd9ab
      /* some error occurred when reading the line (stream should be closed by now) */
Packit 6bd9ab
      NETGROUP_BE(be)->fp = NULL;
Packit 6bd9ab
      GETNETGRENT_ARGS(args)->status = NSS_NETGR_NO;
Packit 6bd9ab
      return retv;
Packit 6bd9ab
    }
Packit 6bd9ab
  }
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
static nss_status_t netgroup_setnetgrent_endnetgrent(nss_backend_t *be,
Packit 6bd9ab
                                                     void UNUSED(*args))
Packit 6bd9ab
{
Packit 6bd9ab
  NSS_ENDENT(NETGROUP_BE(be)->fp);
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
static nss_status_t netgroup_setnetgrent_destructor(nss_backend_t *be,
Packit 6bd9ab
                                                    void *UNUSED(args))
Packit 6bd9ab
{
Packit 6bd9ab
  struct setnetgrent_backend *ngbe = (struct setnetgrent_backend *)be;
Packit 6bd9ab
  if (ngbe->fp != NULL)
Packit 6bd9ab
    (void)tio_close(ngbe->fp);
Packit 6bd9ab
  set_free(ngbe->seen_groups);
Packit 6bd9ab
  set_free(ngbe->unseen_groups);
Packit 6bd9ab
  free(ngbe);
Packit 6bd9ab
  return NSS_STATUS_SUCCESS;
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
static nss_backend_op_t netgroup_setnetgrent_ops[] = {
Packit 6bd9ab
  netgroup_setnetgrent_destructor,
Packit 6bd9ab
  netgroup_setnetgrent_endnetgrent,
Packit 6bd9ab
  netgroup_setnetgrent_setnetgrent,
Packit 6bd9ab
  netgroup_setnetgrent_getnetgrent,
Packit 6bd9ab
};
Packit 6bd9ab
Packit 6bd9ab
static nss_status_t netgroup_setnetgrent_constructor(nss_backend_t UNUSED(*be),
Packit 6bd9ab
                                                     void *args)
Packit 6bd9ab
{
Packit 6bd9ab
  struct setnetgrent_backend *ngbe;
Packit 6bd9ab
  nss_status_t retv;
Packit 6bd9ab
  NSS_AVAILCHECK;
Packit 6bd9ab
  SETNETGRENT_ARGS(args)->iterator = NULL; /* initialize */
Packit 6bd9ab
  /* allocate a back-end specific to this request */
Packit 6bd9ab
  ngbe = (struct setnetgrent_backend *)malloc(sizeof(struct setnetgrent_backend));
Packit 6bd9ab
  if (ngbe == NULL)
Packit 6bd9ab
    return NSS_STATUS_UNAVAIL;
Packit 6bd9ab
  ngbe->ops = netgroup_setnetgrent_ops;
Packit 6bd9ab
  ngbe->n_ops = sizeof(netgroup_setnetgrent_ops) / sizeof(nss_backend_op_t);
Packit 6bd9ab
  ngbe->fp = NULL;
Packit 6bd9ab
  ngbe->seen_groups = set_new();
Packit 6bd9ab
  ngbe->unseen_groups = set_new();
Packit 6bd9ab
  /* start the first search */
Packit 6bd9ab
  retv = start_netgroup_request(ngbe, SETNETGRENT_ARGS(args)->netgroup);
Packit 6bd9ab
  if (retv != NSS_STATUS_SUCCESS)
Packit 6bd9ab
  {
Packit 6bd9ab
    netgroup_setnetgrent_destructor((nss_backend_t *)ngbe, args);
Packit 6bd9ab
    return retv;
Packit 6bd9ab
  }
Packit 6bd9ab
  /* return the new back-end */
Packit 6bd9ab
  SETNETGRENT_ARGS(args)->iterator = (nss_backend_t *)ngbe;
Packit 6bd9ab
  return NSS_STATUS_SUCCESS;
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
static nss_status_t netgroup_innetgr(nss_backend_t UNUSED(*be),
Packit 6bd9ab
                                     void *args)
Packit 6bd9ab
{
Packit 6bd9ab
  unsigned int i;
Packit 6bd9ab
  nss_status_t res = NSS_SUCCESS;
Packit 6bd9ab
  struct nss_setnetgrent_args set_args;
Packit 6bd9ab
  struct nss_getnetgrent_args get_args;
Packit 6bd9ab
  const char *host = NULL, *user = NULL, *domain = NULL;
Packit 6bd9ab
  /* get the host, user and domain arguments */
Packit 6bd9ab
  if ((args == NULL) ||
Packit 6bd9ab
      (INNETGR_ARGS(args)->arg[NSS_NETGR_MACHINE].argc > 1) ||
Packit 6bd9ab
      (INNETGR_ARGS(args)->arg[NSS_NETGR_USER].argc > 1) ||
Packit 6bd9ab
      (INNETGR_ARGS(args)->arg[NSS_NETGR_DOMAIN].argc > 1))
Packit 6bd9ab
    return NSS_STATUS_UNAVAIL;
Packit 6bd9ab
  if (INNETGR_ARGS(args)->arg[NSS_NETGR_MACHINE].argc == 1)
Packit 6bd9ab
    host = INNETGR_ARGS(args)->arg[NSS_NETGR_MACHINE].argv[0];
Packit 6bd9ab
  if (INNETGR_ARGS(args)->arg[NSS_NETGR_USER].argc == 1)
Packit 6bd9ab
    user = INNETGR_ARGS(args)->arg[NSS_NETGR_USER].argv[0];
Packit 6bd9ab
  if (INNETGR_ARGS(args)->arg[NSS_NETGR_DOMAIN].argc == 1)
Packit 6bd9ab
    domain = INNETGR_ARGS(args)->arg[NSS_NETGR_DOMAIN].argv[0];
Packit 6bd9ab
  /* go over the list of provided groups */
Packit 6bd9ab
  INNETGR_ARGS(args)->status = NSS_NETGR_NO;
Packit 6bd9ab
  for (i = 0; i < INNETGR_ARGS(args)->groups.argc; i++)
Packit 6bd9ab
  {
Packit 6bd9ab
    /* prepare calling {set,get,end}netgrent() */
Packit 6bd9ab
    set_args.netgroup = INNETGR_ARGS(args)->groups.argv[i];
Packit 6bd9ab
    res = netgroup_setnetgrent_constructor(NULL, &set_args);
Packit 6bd9ab
    if (res != NSS_SUCCESS)
Packit 6bd9ab
      break;
Packit 6bd9ab
    /* we skip setnetgrent because it does nothing in our case */
Packit 6bd9ab
    /* call getnetgrent until we find an error, no more or a match */
Packit 6bd9ab
    while (1)
Packit 6bd9ab
    {
Packit 6bd9ab
      res = netgroup_setnetgrent_getnetgrent(set_args.iterator, &get_args);
Packit 6bd9ab
      /* see if we have an error or are at the end of the results */
Packit 6bd9ab
      if ((res != NSS_SUCCESS) || (get_args.status != NSS_NETGR_FOUND))
Packit 6bd9ab
        break;
Packit 6bd9ab
      /* see if we have a match */
Packit 6bd9ab
      if (((host == NULL) || (strcmp(host, get_args.retp[NSS_NETGR_MACHINE]) == 0)) &&
Packit 6bd9ab
          ((user == NULL) || (strcmp(user, get_args.retp[NSS_NETGR_USER]) == 0)) &&
Packit 6bd9ab
          ((domain == NULL) || (strcmp(domain, get_args.retp[NSS_NETGR_DOMAIN]) == 0)))
Packit 6bd9ab
      {
Packit 6bd9ab
        INNETGR_ARGS(args)->status = NSS_NETGR_FOUND;
Packit 6bd9ab
        break;
Packit 6bd9ab
      }
Packit 6bd9ab
    }
Packit 6bd9ab
    (void)netgroup_setnetgrent_endnetgrent(set_args.iterator, NULL);
Packit 6bd9ab
    (void)netgroup_setnetgrent_destructor(set_args.iterator, NULL);
Packit 6bd9ab
    if (res != NSS_SUCCESS)
Packit 6bd9ab
      break;
Packit 6bd9ab
    /* check if we have a match */
Packit 6bd9ab
    if (INNETGR_ARGS(args)->status == NSS_NETGR_FOUND)
Packit 6bd9ab
      break;
Packit 6bd9ab
  }
Packit 6bd9ab
  return res;
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
static nss_backend_op_t netgroup_ops[] = {
Packit 6bd9ab
  nss_ldap_destructor,
Packit 6bd9ab
  NULL,
Packit 6bd9ab
  NULL,
Packit 6bd9ab
  NULL,
Packit 6bd9ab
  netgroup_innetgr,
Packit 6bd9ab
  netgroup_setnetgrent_constructor
Packit 6bd9ab
};
Packit 6bd9ab
Packit 6bd9ab
nss_backend_t *NSS_NAME(netgroup_constr)(const char UNUSED(*db_name),
Packit 6bd9ab
                                         const char UNUSED(*src_name),
Packit 6bd9ab
                                         const char UNUSED(*cfg_args))
Packit 6bd9ab
{
Packit 6bd9ab
  return nss_ldap_constructor(netgroup_ops, sizeof(netgroup_ops));
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
#endif /* NSS_FLAVOUR_SOLARIS */