Implement an NSS backend for netgroups and add getnetgrent_r(3).
This support appears to have been documented in nsswitch.conf(5) for some time. The implementation adds two NSS netgroup providers to libc. The default, compat, provides the behaviour documented in netgroup(5), so this change does not make any user-visible behaviour changes. A files provider is also implemented. innetgr(3) is implemented as an optional NSS method so that providers such as NIS which are able to implement efficient reverse lookup can do so. A fallback implementation is used otherwise. getnetgrent_r(3) is added for convenience and to provide compatibility with glibc and Solaris. With a small patch to net/nss_ldap, it's possible to specify an ldap netgroup provider, allowing one to query nisNetgroupTriple entries. Sponsored by: EMC / Isilon Storage Division
This commit is contained in:
parent
03ad7e450a
commit
714ac00292
@ -5,6 +5,7 @@
|
|||||||
group: compat
|
group: compat
|
||||||
group_compat: nis
|
group_compat: nis
|
||||||
hosts: files dns
|
hosts: files dns
|
||||||
|
netgroup: compat
|
||||||
networks: files
|
networks: files
|
||||||
passwd: compat
|
passwd: compat
|
||||||
passwd_compat: nis
|
passwd_compat: nis
|
||||||
|
@ -275,6 +275,7 @@ int getnetbyname_r(const char *, struct netent *, char *, size_t,
|
|||||||
int getnetent_r(struct netent *, char *, size_t, struct netent **,
|
int getnetent_r(struct netent *, char *, size_t, struct netent **,
|
||||||
int *);
|
int *);
|
||||||
int getnetgrent(char **, char **, char **);
|
int getnetgrent(char **, char **, char **);
|
||||||
|
int getnetgrent_r(char **, char **, char **, char *, size_t);
|
||||||
int getprotobyname_r(const char *, struct protoent *, char *,
|
int getprotobyname_r(const char *, struct protoent *, char *,
|
||||||
size_t, struct protoent **);
|
size_t, struct protoent **);
|
||||||
int getprotobynumber_r(int, struct protoent *, char *, size_t,
|
int getprotobynumber_r(int, struct protoent *, char *, size_t,
|
||||||
|
@ -410,6 +410,7 @@ FBSD_1.3 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
FBSD_1.4 {
|
FBSD_1.4 {
|
||||||
|
getnetgrent_r;
|
||||||
pthread_mutex_consistent;
|
pthread_mutex_consistent;
|
||||||
pthread_mutexattr_getrobust;
|
pthread_mutexattr_getrobust;
|
||||||
pthread_mutexattr_setrobust;
|
pthread_mutexattr_setrobust;
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
.\" @(#)getnetgrent.3 8.1 (Berkeley) 6/4/93
|
.\" @(#)getnetgrent.3 8.1 (Berkeley) 6/4/93
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd June 4, 1993
|
.Dd June 5, 2016
|
||||||
.Dt GETNETGRENT 3
|
.Dt GETNETGRENT 3
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -44,6 +44,8 @@
|
|||||||
.Ft int
|
.Ft int
|
||||||
.Fn getnetgrent "char **host" "char **user" "char **domain"
|
.Fn getnetgrent "char **host" "char **user" "char **domain"
|
||||||
.Ft int
|
.Ft int
|
||||||
|
.Fn getnetgrent_r "char **host" "char **user" "char **domain" "char *buf" "size_t bufsize"
|
||||||
|
.Ft int
|
||||||
.Fn innetgr "const char *netgroup" "const char *host" "const char *user" "const char *domain"
|
.Fn innetgr "const char *netgroup" "const char *host" "const char *user" "const char *domain"
|
||||||
.Ft void
|
.Ft void
|
||||||
.Fn setnetgrent "const char *netgroup"
|
.Fn setnetgrent "const char *netgroup"
|
||||||
|
@ -36,12 +36,21 @@ static char sccsid[] = "@(#)getnetgrent.c 8.2 (Berkeley) 4/27/95";
|
|||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include "namespace.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <nsswitch.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <pthread_np.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "nss_tls.h"
|
||||||
|
|
||||||
#ifdef YP
|
#ifdef YP
|
||||||
/*
|
/*
|
||||||
* Notes:
|
* Notes:
|
||||||
@ -98,6 +107,16 @@ static int _yp_innetgr;
|
|||||||
#define _PATH_NETGROUP "/etc/netgroup"
|
#define _PATH_NETGROUP "/etc/netgroup"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum constants {
|
||||||
|
NGRP_STORAGE_INITIAL = 1 << 10, /* 1 KByte */
|
||||||
|
NGRP_STORAGE_MAX = 1 << 20, /* 1 MByte */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const ns_src defaultsrc[] = {
|
||||||
|
{ NSSRC_COMPAT, NS_SUCCESS },
|
||||||
|
{ NULL, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Static Variables and functions used by setnetgrent(), getnetgrent() and
|
* Static Variables and functions used by setnetgrent(), getnetgrent() and
|
||||||
* endnetgrent().
|
* endnetgrent().
|
||||||
@ -117,51 +136,212 @@ struct netgrp {
|
|||||||
struct netgrp *ng_next; /* Chain ptr */
|
struct netgrp *ng_next; /* Chain ptr */
|
||||||
char *ng_str[3]; /* Field pointers, see below */
|
char *ng_str[3]; /* Field pointers, see below */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct netgr_state {
|
||||||
|
FILE *st_netf;
|
||||||
|
struct linelist *st_linehead;
|
||||||
|
struct netgrp *st_nextgrp;
|
||||||
|
struct netgrp *st_gr;
|
||||||
|
char *st_grname;
|
||||||
|
};
|
||||||
|
|
||||||
#define NG_HOST 0 /* Host name */
|
#define NG_HOST 0 /* Host name */
|
||||||
#define NG_USER 1 /* User name */
|
#define NG_USER 1 /* User name */
|
||||||
#define NG_DOM 2 /* and Domain name */
|
#define NG_DOM 2 /* and Domain name */
|
||||||
|
|
||||||
static struct linelist *linehead = (struct linelist *)0;
|
static void netgr_endstate(void *);
|
||||||
static struct netgrp *nextgrp = (struct netgrp *)0;
|
NSS_TLS_HANDLING(netgr);
|
||||||
static struct {
|
|
||||||
struct netgrp *gr;
|
|
||||||
char *grname;
|
|
||||||
} grouphead = {
|
|
||||||
(struct netgrp *)0,
|
|
||||||
(char *)0,
|
|
||||||
};
|
|
||||||
static FILE *netf = (FILE *)0;
|
|
||||||
|
|
||||||
static int parse_netgrp(const char *);
|
static int files_endnetgrent(void *, void *, va_list);
|
||||||
static struct linelist *read_for_group(const char *);
|
static int files_getnetgrent_r(void *, void *, va_list);
|
||||||
void setnetgrent(const char *);
|
static int files_setnetgrent(void *, void *, va_list);
|
||||||
void endnetgrent(void);
|
|
||||||
int getnetgrent(char **, char **, char **);
|
static int compat_endnetgrent(void *, void *, va_list);
|
||||||
int innetgr(const char *, const char *, const char *, const char *);
|
static int compat_innetgr(void *, void *, va_list);
|
||||||
|
static int compat_getnetgrent_r(void *, void *, va_list);
|
||||||
|
static int compat_setnetgrent(void *, void *, va_list);
|
||||||
|
|
||||||
|
static void _compat_clearstate(void);
|
||||||
|
static int _getnetgrent_r(char **, char **, char **, char *, size_t, int *,
|
||||||
|
struct netgr_state *);
|
||||||
|
static int _innetgr_fallback(void *, void *, const char *, const char *,
|
||||||
|
const char *, const char *);
|
||||||
|
static int innetgr_fallback(void *, void *, va_list);
|
||||||
|
static int parse_netgrp(const char *, struct netgr_state *, int);
|
||||||
|
static struct linelist *read_for_group(const char *, struct netgr_state *, int);
|
||||||
|
|
||||||
#define LINSIZ 1024 /* Length of netgroup file line */
|
#define LINSIZ 1024 /* Length of netgroup file line */
|
||||||
|
|
||||||
|
static const ns_dtab getnetgrent_dtab[] = {
|
||||||
|
NS_FILES_CB(files_getnetgrent_r, NULL)
|
||||||
|
NS_COMPAT_CB(compat_getnetgrent_r, NULL)
|
||||||
|
{ NULL, NULL, NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const ns_dtab setnetgrent_dtab[] = {
|
||||||
|
NS_FILES_CB(files_setnetgrent, NULL)
|
||||||
|
NS_COMPAT_CB(compat_setnetgrent, NULL)
|
||||||
|
{ NULL, NULL, NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const ns_dtab endnetgrent_dtab[] = {
|
||||||
|
NS_FILES_CB(files_endnetgrent, NULL)
|
||||||
|
NS_COMPAT_CB(compat_endnetgrent, NULL)
|
||||||
|
{ NULL, NULL, NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct netgr_state compat_state;
|
||||||
|
|
||||||
|
static void
|
||||||
|
netgr_endstate(void *arg)
|
||||||
|
{
|
||||||
|
struct linelist *lp, *olp;
|
||||||
|
struct netgrp *gp, *ogp;
|
||||||
|
struct netgr_state *st;
|
||||||
|
|
||||||
|
st = (struct netgr_state *)arg;
|
||||||
|
lp = st->st_linehead;
|
||||||
|
while (lp != NULL) {
|
||||||
|
olp = lp;
|
||||||
|
lp = lp->l_next;
|
||||||
|
free(olp->l_groupname);
|
||||||
|
free(olp->l_line);
|
||||||
|
free(olp);
|
||||||
|
}
|
||||||
|
st->st_linehead = NULL;
|
||||||
|
if (st->st_grname != NULL) {
|
||||||
|
free(st->st_grname);
|
||||||
|
st->st_grname = NULL;
|
||||||
|
}
|
||||||
|
gp = st->st_gr;
|
||||||
|
while (gp != NULL) {
|
||||||
|
ogp = gp;
|
||||||
|
gp = gp->ng_next;
|
||||||
|
free(ogp->ng_str[NG_HOST]);
|
||||||
|
free(ogp->ng_str[NG_USER]);
|
||||||
|
free(ogp->ng_str[NG_DOM]);
|
||||||
|
free(ogp);
|
||||||
|
}
|
||||||
|
st->st_gr = NULL;
|
||||||
|
st->st_nextgrp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
files_getnetgrent_r(void *retval, void *mdata, va_list ap)
|
||||||
|
{
|
||||||
|
struct netgr_state *st;
|
||||||
|
char **hostp, **userp, **domp, *buf;
|
||||||
|
size_t bufsize;
|
||||||
|
int *errnop;
|
||||||
|
|
||||||
|
hostp = va_arg(ap, char **);
|
||||||
|
userp = va_arg(ap, char **);
|
||||||
|
domp = va_arg(ap, char **);
|
||||||
|
buf = va_arg(ap, char *);
|
||||||
|
bufsize = va_arg(ap, size_t);
|
||||||
|
errnop = va_arg(ap, int *);
|
||||||
|
|
||||||
|
if (netgr_getstate(&st) != 0)
|
||||||
|
return (NS_UNAVAIL);
|
||||||
|
|
||||||
|
return (_getnetgrent_r(hostp, userp, domp, buf, bufsize, errnop, st));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
files_setnetgrent(void *retval, void *mdata, va_list ap)
|
||||||
|
{
|
||||||
|
const ns_src src[] = {
|
||||||
|
{ NSSRC_FILES, NS_SUCCESS },
|
||||||
|
{ NULL, 0 },
|
||||||
|
};
|
||||||
|
struct netgr_state *st;
|
||||||
|
const char *group;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
group = va_arg(ap, const char *);
|
||||||
|
|
||||||
|
if (group == NULL || group[0] == '\0')
|
||||||
|
return (NS_RETURN);
|
||||||
|
|
||||||
|
rv = netgr_getstate(&st);
|
||||||
|
if (rv != 0)
|
||||||
|
return (NS_UNAVAIL);
|
||||||
|
|
||||||
|
if (st->st_gr == NULL || strcmp(group, st->st_grname) != 0) {
|
||||||
|
(void)_nsdispatch(NULL, endnetgrent_dtab, NSDB_NETGROUP,
|
||||||
|
"endnetgrent", src);
|
||||||
|
if ((st->st_netf = fopen(_PATH_NETGROUP, "re")) != NULL) {
|
||||||
|
if (parse_netgrp(group, st, 0) != 0)
|
||||||
|
(void)_nsdispatch(NULL, endnetgrent_dtab,
|
||||||
|
NSDB_NETGROUP, "endnetgrent", src);
|
||||||
|
else
|
||||||
|
st->st_grname = strdup(group);
|
||||||
|
(void)fclose(st->st_netf);
|
||||||
|
st->st_netf = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
st->st_nextgrp = st->st_gr;
|
||||||
|
return (st->st_grname != NULL ? NS_SUCCESS : NS_NOTFOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
files_endnetgrent(void *retval, void *mdata, va_list ap)
|
||||||
|
{
|
||||||
|
struct netgr_state *st;
|
||||||
|
|
||||||
|
if (netgr_getstate(&st) != 0)
|
||||||
|
return (NS_UNAVAIL);
|
||||||
|
netgr_endstate(st);
|
||||||
|
return (NS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
compat_getnetgrent_r(void *retval, void *mdata, va_list ap)
|
||||||
|
{
|
||||||
|
char **hostp, **userp, **domp, *buf;
|
||||||
|
size_t bufsize;
|
||||||
|
int *errnop;
|
||||||
|
#ifdef YP
|
||||||
|
_yp_innetgr = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
hostp = va_arg(ap, char **);
|
||||||
|
userp = va_arg(ap, char **);
|
||||||
|
domp = va_arg(ap, char **);
|
||||||
|
buf = va_arg(ap, char *);
|
||||||
|
bufsize = va_arg(ap, size_t);
|
||||||
|
errnop = va_arg(ap, int *);
|
||||||
|
|
||||||
|
return (_getnetgrent_r(hostp, userp, domp, buf, bufsize, errnop,
|
||||||
|
&compat_state));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* setnetgrent()
|
* compat_setnetgrent()
|
||||||
* Parse the netgroup file looking for the netgroup and build the list
|
* Parse the netgroup file looking for the netgroup and build the list
|
||||||
* of netgrp structures. Let parse_netgrp() and read_for_group() do
|
* of netgrp structures. Let parse_netgrp() and read_for_group() do
|
||||||
* most of the work.
|
* most of the work.
|
||||||
*/
|
*/
|
||||||
void
|
static int
|
||||||
setnetgrent(const char *group)
|
compat_setnetgrent(void *retval, void *mdata, va_list ap)
|
||||||
{
|
{
|
||||||
|
FILE *netf;
|
||||||
|
const char *group;
|
||||||
#ifdef YP
|
#ifdef YP
|
||||||
struct stat _yp_statp;
|
struct stat _yp_statp;
|
||||||
char _yp_plus;
|
char _yp_plus;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
group = va_arg(ap, const char *);
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
|
|
||||||
if (group == NULL || !strlen(group))
|
if (group == NULL || !strlen(group))
|
||||||
return;
|
return (NS_RETURN);
|
||||||
|
|
||||||
|
if (compat_state.st_gr == NULL ||
|
||||||
|
strcmp(group, compat_state.st_grname) != 0) {
|
||||||
|
_compat_clearstate();
|
||||||
|
|
||||||
if (grouphead.gr == NULL || strcmp(group, grouphead.grname)) {
|
|
||||||
endnetgrent();
|
|
||||||
#ifdef YP
|
#ifdef YP
|
||||||
/* Presumed guilty until proven innocent. */
|
/* Presumed guilty until proven innocent. */
|
||||||
_use_only_yp = 0;
|
_use_only_yp = 0;
|
||||||
@ -173,6 +353,7 @@ setnetgrent(const char *group)
|
|||||||
errno == ENOENT) || _yp_statp.st_size == 0)
|
errno == ENOENT) || _yp_statp.st_size == 0)
|
||||||
_use_only_yp = _netgr_yp_enabled = 1;
|
_use_only_yp = _netgr_yp_enabled = 1;
|
||||||
if ((netf = fopen(_PATH_NETGROUP,"re")) != NULL ||_use_only_yp){
|
if ((netf = fopen(_PATH_NETGROUP,"re")) != NULL ||_use_only_yp){
|
||||||
|
compat_state.st_netf = netf;
|
||||||
/*
|
/*
|
||||||
* Icky: grab the first character of the netgroup file
|
* Icky: grab the first character of the netgroup file
|
||||||
* and turn on NIS if it's a '+'. rewind the stream
|
* and turn on NIS if it's a '+'. rewind the stream
|
||||||
@ -193,79 +374,81 @@ setnetgrent(const char *group)
|
|||||||
/* dohw! */
|
/* dohw! */
|
||||||
if (netf != NULL)
|
if (netf != NULL)
|
||||||
fclose(netf);
|
fclose(netf);
|
||||||
return;
|
return (NS_RETURN);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if ((netf = fopen(_PATH_NETGROUP, "re"))) {
|
if ((netf = fopen(_PATH_NETGROUP, "re"))) {
|
||||||
|
compat_state.st_netf = netf;
|
||||||
#endif
|
#endif
|
||||||
if (parse_netgrp(group))
|
if (parse_netgrp(group, &compat_state, 1)) {
|
||||||
endnetgrent();
|
_compat_clearstate();
|
||||||
else {
|
} else {
|
||||||
grouphead.grname = strdup(group);
|
compat_state.st_grname = strdup(group);
|
||||||
}
|
}
|
||||||
if (netf)
|
if (netf)
|
||||||
fclose(netf);
|
fclose(netf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nextgrp = grouphead.gr;
|
compat_state.st_nextgrp = compat_state.st_gr;
|
||||||
|
return (NS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static void
|
||||||
* Get the next netgroup off the list.
|
_compat_clearstate(void)
|
||||||
*/
|
|
||||||
int
|
|
||||||
getnetgrent(char **hostp, char **userp, char **domp)
|
|
||||||
{
|
{
|
||||||
#ifdef YP
|
|
||||||
_yp_innetgr = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (nextgrp) {
|
|
||||||
*hostp = nextgrp->ng_str[NG_HOST];
|
|
||||||
*userp = nextgrp->ng_str[NG_USER];
|
|
||||||
*domp = nextgrp->ng_str[NG_DOM];
|
|
||||||
nextgrp = nextgrp->ng_next;
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* endnetgrent() - cleanup
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
endnetgrent(void)
|
|
||||||
{
|
|
||||||
struct linelist *lp, *olp;
|
|
||||||
struct netgrp *gp, *ogp;
|
|
||||||
|
|
||||||
lp = linehead;
|
|
||||||
while (lp) {
|
|
||||||
olp = lp;
|
|
||||||
lp = lp->l_next;
|
|
||||||
free(olp->l_groupname);
|
|
||||||
free(olp->l_line);
|
|
||||||
free(olp);
|
|
||||||
}
|
|
||||||
linehead = NULL;
|
|
||||||
if (grouphead.grname) {
|
|
||||||
free(grouphead.grname);
|
|
||||||
grouphead.grname = NULL;
|
|
||||||
}
|
|
||||||
gp = grouphead.gr;
|
|
||||||
while (gp) {
|
|
||||||
ogp = gp;
|
|
||||||
gp = gp->ng_next;
|
|
||||||
free(ogp->ng_str[NG_HOST]);
|
|
||||||
free(ogp->ng_str[NG_USER]);
|
|
||||||
free(ogp->ng_str[NG_DOM]);
|
|
||||||
free(ogp);
|
|
||||||
}
|
|
||||||
grouphead.gr = NULL;
|
|
||||||
nextgrp = NULL;
|
|
||||||
#ifdef YP
|
#ifdef YP
|
||||||
_netgr_yp_enabled = 0;
|
_netgr_yp_enabled = 0;
|
||||||
#endif
|
#endif
|
||||||
|
netgr_endstate(&compat_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* compat_endnetgrent() - cleanup
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
compat_endnetgrent(void *retval, void *mdata, va_list ap)
|
||||||
|
{
|
||||||
|
|
||||||
|
_compat_clearstate();
|
||||||
|
return (NS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_getnetgrent_r(char **hostp, char **userp, char **domp, char *buf,
|
||||||
|
size_t bufsize, int *errnop, struct netgr_state *st)
|
||||||
|
{
|
||||||
|
char *p, *src;
|
||||||
|
size_t len;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
#define COPY_NG_ELEM(dstp, i) do { \
|
||||||
|
src = st->st_nextgrp->ng_str[(i)]; \
|
||||||
|
if (src == NULL) \
|
||||||
|
src = ""; \
|
||||||
|
len = strlcpy(p, src, bufsize); \
|
||||||
|
if (len >= bufsize) { \
|
||||||
|
*errnop = ERANGE; \
|
||||||
|
return (NS_RETURN); \
|
||||||
|
} \
|
||||||
|
*(dstp) = p; \
|
||||||
|
p += len + 1; \
|
||||||
|
bufsize -= len + 1; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
p = buf;
|
||||||
|
if (st->st_nextgrp != NULL) {
|
||||||
|
COPY_NG_ELEM(hostp, NG_HOST);
|
||||||
|
COPY_NG_ELEM(userp, NG_USER);
|
||||||
|
COPY_NG_ELEM(domp, NG_DOM);
|
||||||
|
st->st_nextgrp = st->st_nextgrp->ng_next;
|
||||||
|
rv = NS_SUCCESS;
|
||||||
|
} else {
|
||||||
|
rv = NS_NOTFOUND;
|
||||||
|
}
|
||||||
|
#undef COPY_NG_ELEM
|
||||||
|
|
||||||
|
return (rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef YP
|
#ifdef YP
|
||||||
@ -343,20 +526,29 @@ _revnetgr_lookup(char* lookupdom, char* map, const char* str,
|
|||||||
/*
|
/*
|
||||||
* Search for a match in a netgroup.
|
* Search for a match in a netgroup.
|
||||||
*/
|
*/
|
||||||
int
|
static int
|
||||||
innetgr(const char *group, const char *host, const char *user, const char *dom)
|
compat_innetgr(void *retval, void *mdata, va_list ap)
|
||||||
{
|
{
|
||||||
char *hst, *usr, *dm;
|
#ifdef YP
|
||||||
/* Sanity check */
|
const ns_src src[] = {
|
||||||
|
{ mdata, NS_SUCCESS },
|
||||||
|
{ NULL, 0 },
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
const char *group, *host, *user, *dom;
|
||||||
|
|
||||||
|
group = va_arg(ap, const char *);
|
||||||
|
host = va_arg(ap, const char *);
|
||||||
|
user = va_arg(ap, const char *);
|
||||||
|
dom = va_arg(ap, const char *);
|
||||||
|
|
||||||
if (group == NULL || !strlen(group))
|
if (group == NULL || !strlen(group))
|
||||||
return (0);
|
return (NS_RETURN);
|
||||||
|
|
||||||
#ifdef YP
|
#ifdef YP
|
||||||
_yp_innetgr = 1;
|
_yp_innetgr = 1;
|
||||||
#endif
|
(void)_nsdispatch(NULL, setnetgrent_dtab, NSDB_NETGROUP, "setnetgrent",
|
||||||
setnetgrent(group);
|
src, group);
|
||||||
#ifdef YP
|
|
||||||
_yp_innetgr = 0;
|
_yp_innetgr = 0;
|
||||||
/*
|
/*
|
||||||
* If we're in NIS-only mode, do the search using
|
* If we're in NIS-only mode, do the search using
|
||||||
@ -384,38 +576,105 @@ innetgr(const char *group, const char *host, const char *user, const char *dom)
|
|||||||
if (_use_only_yp && (host == NULL) != (user == NULL)) {
|
if (_use_only_yp && (host == NULL) != (user == NULL)) {
|
||||||
int ret;
|
int ret;
|
||||||
if(yp_get_default_domain(&_netgr_yp_domain))
|
if(yp_get_default_domain(&_netgr_yp_domain))
|
||||||
return (0);
|
return (NS_NOTFOUND);
|
||||||
ret = _revnetgr_lookup(_netgr_yp_domain,
|
ret = _revnetgr_lookup(_netgr_yp_domain,
|
||||||
host?"netgroup.byhost":"netgroup.byuser",
|
host?"netgroup.byhost":"netgroup.byuser",
|
||||||
host?host:user, dom, group);
|
host?host:user, dom, group);
|
||||||
if (ret == 1)
|
if (ret == 1) {
|
||||||
return (1);
|
*(int *)retval = 1;
|
||||||
else if (ret == 0 && dom != NULL)
|
return (NS_SUCCESS);
|
||||||
return (0);
|
} else if (ret == 0 && dom != NULL) {
|
||||||
|
*(int *)retval = 0;
|
||||||
|
return (NS_SUCCESS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setnetgrent(group);
|
|
||||||
#endif /* YP */
|
#endif /* YP */
|
||||||
|
|
||||||
while (getnetgrent(&hst, &usr, &dm))
|
return (_innetgr_fallback(retval, mdata, group, host, user, dom));
|
||||||
if ((host == NULL || hst == NULL || !strcmp(host, hst)) &&
|
|
||||||
(user == NULL || usr == NULL || !strcmp(user, usr)) &&
|
|
||||||
( dom == NULL || dm == NULL || !strcmp(dom, dm))) {
|
|
||||||
endnetgrent();
|
|
||||||
return (1);
|
|
||||||
}
|
}
|
||||||
endnetgrent();
|
|
||||||
return (0);
|
static int
|
||||||
|
_innetgr_fallback(void *retval, void *mdata, const char *group, const char *host,
|
||||||
|
const char *user, const char *dom)
|
||||||
|
{
|
||||||
|
const ns_src src[] = {
|
||||||
|
{ mdata, NS_SUCCESS },
|
||||||
|
{ NULL, 0 },
|
||||||
|
};
|
||||||
|
char *h, *u, *d;
|
||||||
|
char *buf;
|
||||||
|
size_t bufsize;
|
||||||
|
int rv, ret_errno;
|
||||||
|
|
||||||
|
if (group == NULL || group[0] == '\0')
|
||||||
|
return (NS_RETURN);
|
||||||
|
|
||||||
|
bufsize = NGRP_STORAGE_INITIAL;
|
||||||
|
buf = malloc(bufsize);
|
||||||
|
if (buf == NULL)
|
||||||
|
return (NS_UNAVAIL);
|
||||||
|
|
||||||
|
*(int *)retval = 0;
|
||||||
|
|
||||||
|
(void)_nsdispatch(NULL, setnetgrent_dtab, NSDB_NETGROUP, "setnetgrent",
|
||||||
|
src, group);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
do {
|
||||||
|
ret_errno = 0;
|
||||||
|
rv = _nsdispatch(NULL, getnetgrent_dtab, NSDB_NETGROUP,
|
||||||
|
"getnetgrent_r", src, &h, &u, &d, buf, bufsize,
|
||||||
|
&ret_errno);
|
||||||
|
if (rv != NS_SUCCESS && ret_errno == ERANGE) {
|
||||||
|
bufsize *= 2;
|
||||||
|
if (bufsize > NGRP_STORAGE_MAX ||
|
||||||
|
(buf = reallocf(buf, bufsize)) == NULL)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
} while (rv != NS_SUCCESS && ret_errno == ERANGE);
|
||||||
|
|
||||||
|
if (rv != NS_SUCCESS) {
|
||||||
|
if (rv == NS_NOTFOUND && ret_errno == 0)
|
||||||
|
rv = NS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((host == NULL || h == NULL || strcmp(host, h) == 0) &&
|
||||||
|
(user == NULL || u == NULL || strcmp(user, u) == 0) &&
|
||||||
|
(dom == NULL || d == NULL || strcmp(dom, d) == 0)) {
|
||||||
|
*(int *)retval = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
free(buf);
|
||||||
|
(void)_nsdispatch(NULL, endnetgrent_dtab, NSDB_NETGROUP, "endnetgrent",
|
||||||
|
src);
|
||||||
|
return (rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
innetgr_fallback(void *retval, void *mdata, va_list ap)
|
||||||
|
{
|
||||||
|
const char *group, *host, *user, *dom;
|
||||||
|
|
||||||
|
group = va_arg(ap, const char *);
|
||||||
|
host = va_arg(ap, const char *);
|
||||||
|
user = va_arg(ap, const char *);
|
||||||
|
dom = va_arg(ap, const char *);
|
||||||
|
|
||||||
|
return (_innetgr_fallback(retval, mdata, group, host, user, dom));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse the netgroup file setting up the linked lists.
|
* Parse the netgroup file setting up the linked lists.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
parse_netgrp(const char *group)
|
parse_netgrp(const char *group, struct netgr_state *st, int niscompat)
|
||||||
{
|
{
|
||||||
struct netgrp *grp;
|
struct netgrp *grp;
|
||||||
struct linelist *lp = linehead;
|
struct linelist *lp = st->st_linehead;
|
||||||
char **ng;
|
char **ng;
|
||||||
char *epos, *gpos, *pos, *spos;
|
char *epos, *gpos, *pos, *spos;
|
||||||
int freepos, len, strpos;
|
int freepos, len, strpos;
|
||||||
@ -431,7 +690,7 @@ parse_netgrp(const char *group)
|
|||||||
break;
|
break;
|
||||||
lp = lp->l_next;
|
lp = lp->l_next;
|
||||||
}
|
}
|
||||||
if (lp == NULL && (lp = read_for_group(group)) == NULL)
|
if (lp == NULL && (lp = read_for_group(group, st, niscompat)) == NULL)
|
||||||
return (1);
|
return (1);
|
||||||
if (lp->l_parsed) {
|
if (lp->l_parsed) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -493,8 +752,8 @@ parse_netgrp(const char *group)
|
|||||||
}
|
}
|
||||||
bcopy(spos, ng[strpos], len + 1);
|
bcopy(spos, ng[strpos], len + 1);
|
||||||
}
|
}
|
||||||
grp->ng_next = grouphead.gr;
|
grp->ng_next = st->st_gr;
|
||||||
grouphead.gr = grp;
|
st->st_gr = grp;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
/*
|
/*
|
||||||
* Note: on other platforms, malformed netgroup
|
* Note: on other platforms, malformed netgroup
|
||||||
@ -515,7 +774,7 @@ parse_netgrp(const char *group)
|
|||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
spos = strsep(&pos, ", \t");
|
spos = strsep(&pos, ", \t");
|
||||||
if (parse_netgrp(spos))
|
if (parse_netgrp(spos, st, niscompat))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (pos == NULL)
|
if (pos == NULL)
|
||||||
@ -531,19 +790,22 @@ parse_netgrp(const char *group)
|
|||||||
* is found. Return 1 if eof is encountered.
|
* is found. Return 1 if eof is encountered.
|
||||||
*/
|
*/
|
||||||
static struct linelist *
|
static struct linelist *
|
||||||
read_for_group(const char *group)
|
read_for_group(const char *group, struct netgr_state *st, int niscompat)
|
||||||
{
|
{
|
||||||
char *linep, *olinep, *pos, *spos;
|
char *linep, *olinep, *pos, *spos;
|
||||||
int len, olen;
|
int len, olen;
|
||||||
int cont;
|
int cont;
|
||||||
struct linelist *lp;
|
struct linelist *lp;
|
||||||
char line[LINSIZ + 2];
|
char line[LINSIZ + 2];
|
||||||
|
FILE *netf;
|
||||||
#ifdef YP
|
#ifdef YP
|
||||||
char *result;
|
char *result;
|
||||||
int resultlen;
|
int resultlen;
|
||||||
linep = NULL;
|
linep = NULL;
|
||||||
|
|
||||||
while (_netgr_yp_enabled || fgets(line, LINSIZ, netf) != NULL) {
|
netf = st->st_netf;
|
||||||
|
while ((_netgr_yp_enabled && niscompat) ||
|
||||||
|
fgets(line, LINSIZ, netf) != NULL) {
|
||||||
if (_netgr_yp_enabled) {
|
if (_netgr_yp_enabled) {
|
||||||
if(!_netgr_yp_domain)
|
if(!_netgr_yp_domain)
|
||||||
if(yp_get_default_domain(&_netgr_yp_domain))
|
if(yp_get_default_domain(&_netgr_yp_domain))
|
||||||
@ -571,7 +833,7 @@ read_for_group(const char *group)
|
|||||||
#endif
|
#endif
|
||||||
pos = (char *)&line;
|
pos = (char *)&line;
|
||||||
#ifdef YP
|
#ifdef YP
|
||||||
if (*pos == '+') {
|
if (niscompat && *pos == '+') {
|
||||||
_netgr_yp_enabled = 1;
|
_netgr_yp_enabled = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -588,11 +850,11 @@ read_for_group(const char *group)
|
|||||||
while (*pos == ' ' || *pos == '\t')
|
while (*pos == ' ' || *pos == '\t')
|
||||||
pos++;
|
pos++;
|
||||||
if (*pos != '\n' && *pos != '\0') {
|
if (*pos != '\n' && *pos != '\0') {
|
||||||
lp = (struct linelist *)malloc(sizeof (*lp));
|
lp = malloc(sizeof (*lp));
|
||||||
if (lp == NULL)
|
if (lp == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
lp->l_parsed = 0;
|
lp->l_parsed = 0;
|
||||||
lp->l_groupname = (char *)malloc(len + 1);
|
lp->l_groupname = malloc(len + 1);
|
||||||
if (lp->l_groupname == NULL) {
|
if (lp->l_groupname == NULL) {
|
||||||
free(lp);
|
free(lp);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@ -640,8 +902,8 @@ read_for_group(const char *group)
|
|||||||
}
|
}
|
||||||
} while (cont);
|
} while (cont);
|
||||||
lp->l_line = linep;
|
lp->l_line = linep;
|
||||||
lp->l_next = linehead;
|
lp->l_next = st->st_linehead;
|
||||||
linehead = lp;
|
st->st_linehead = lp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this is the one we wanted, we are done.
|
* If this is the one we wanted, we are done.
|
||||||
@ -662,3 +924,93 @@ read_for_group(const char *group)
|
|||||||
#endif
|
#endif
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
getnetgrent_r(char **hostp, char **userp, char **domp, char *buf, size_t bufsize)
|
||||||
|
{
|
||||||
|
int rv, ret_errno;
|
||||||
|
|
||||||
|
ret_errno = 0;
|
||||||
|
rv = _nsdispatch(NULL, getnetgrent_dtab, NSDB_NETGROUP, "getnetgrent_r",
|
||||||
|
defaultsrc, hostp, userp, domp, buf, bufsize, &ret_errno);
|
||||||
|
if (rv == NS_SUCCESS) {
|
||||||
|
return (1);
|
||||||
|
} else {
|
||||||
|
errno = ret_errno;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
getnetgrent(char **hostp, char **userp, char **domp)
|
||||||
|
{
|
||||||
|
static char *ngrp_storage;
|
||||||
|
static size_t ngrp_storage_size;
|
||||||
|
int ret_errno, rv;
|
||||||
|
|
||||||
|
if (ngrp_storage == NULL) {
|
||||||
|
ngrp_storage_size = NGRP_STORAGE_INITIAL;
|
||||||
|
ngrp_storage = malloc(ngrp_storage_size);
|
||||||
|
if (ngrp_storage == NULL)
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret_errno = 0;
|
||||||
|
rv = _nsdispatch(NULL, getnetgrent_dtab, NSDB_NETGROUP,
|
||||||
|
"getnetgrent_r", defaultsrc, hostp, userp, domp,
|
||||||
|
ngrp_storage, ngrp_storage_size, &ret_errno);
|
||||||
|
if (rv != NS_SUCCESS && ret_errno == ERANGE) {
|
||||||
|
ngrp_storage_size *= 2;
|
||||||
|
if (ngrp_storage_size > NGRP_STORAGE_MAX) {
|
||||||
|
free(ngrp_storage);
|
||||||
|
ngrp_storage = NULL;
|
||||||
|
errno = ERANGE;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
ngrp_storage = reallocf(ngrp_storage,
|
||||||
|
ngrp_storage_size);
|
||||||
|
if (ngrp_storage == NULL)
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
} while (rv != NS_SUCCESS && ret_errno == ERANGE);
|
||||||
|
|
||||||
|
if (rv == NS_SUCCESS) {
|
||||||
|
return (1);
|
||||||
|
} else {
|
||||||
|
errno = ret_errno;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
setnetgrent(const char *netgroup)
|
||||||
|
{
|
||||||
|
|
||||||
|
(void)_nsdispatch(NULL, setnetgrent_dtab, NSDB_NETGROUP, "setnetgrent",
|
||||||
|
defaultsrc, netgroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
endnetgrent(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
(void)_nsdispatch(NULL, endnetgrent_dtab, NSDB_NETGROUP, "endnetgrent",
|
||||||
|
defaultsrc);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
innetgr(const char *netgroup, const char *host, const char *user,
|
||||||
|
const char *domain)
|
||||||
|
{
|
||||||
|
static const ns_dtab dtab[] = {
|
||||||
|
NS_COMPAT_CB(compat_innetgr, NULL)
|
||||||
|
NS_FALLBACK_CB(innetgr_fallback)
|
||||||
|
{ NULL, NULL, NULL },
|
||||||
|
};
|
||||||
|
int result, rv;
|
||||||
|
|
||||||
|
rv = _nsdispatch(&result, dtab, NSDB_NETGROUP, "innetgr", defaultsrc,
|
||||||
|
netgroup, host, user, domain);
|
||||||
|
return (rv == NS_SUCCESS ? result : 0);
|
||||||
|
}
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd December 25, 2013
|
.Dd June 6, 2016
|
||||||
.Dt NSSWITCH.CONF 5
|
.Dt NSSWITCH.CONF 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -148,7 +148,9 @@ The following databases are used by the following C library functions:
|
|||||||
.Xr getprotoent 3
|
.Xr getprotoent 3
|
||||||
.It netgroup
|
.It netgroup
|
||||||
.Xr getnetgrent 3 ,
|
.Xr getnetgrent 3 ,
|
||||||
|
.Xr getnetgrent_r 3 ,
|
||||||
.Xr setnetgrent 3 ,
|
.Xr setnetgrent 3 ,
|
||||||
|
.Xr endnetgrent 3 ,
|
||||||
.Xr innetgr 3
|
.Xr innetgr 3
|
||||||
.El
|
.El
|
||||||
.Ss Status codes
|
.Ss Status codes
|
||||||
|
Loading…
x
Reference in New Issue
Block a user