|
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 */
|