mirror of
https://git.FreeBSD.org/src.git
synced 2025-02-08 00:16:07 +00:00
= Implement name service switch modules (NSS modules). NSS modules
may be built into libc (`static NSS modules') or dynamically loaded via dlopen (`dynamic NSS modules'). Modules are loaded/initialized at configuration time (i.e. when nsdispatch is called and nsswitch.conf is read or re-read). = Make the nsdispatch(3) core thread-safe. = New status code for nsdispatch(3) `NS_RETURN', currently used to signal ERANGE-type issues. = syslog(3) problems, don't warn/err/abort. = Try harder to avoid namespace pollution. = Implement some shims to assist in porting NSS modules written for the GNU C Library nsswitch interface. Sponsored by: DARPA, Network Associates Laboratories
This commit is contained in:
parent
7f6bf1d8ce
commit
46d9306383
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=113595
@ -13,7 +13,8 @@ INCS= a.out.h ar.h assert.h bitstring.h complex.h cpio.h ctype.h db.h \
|
||||
fts.h getopt.h glob.h grp.h hesiod.h histedit.h ieeefp.h ifaddrs.h \
|
||||
inttypes.h iso646.h kenv.h langinfo.h libgen.h limits.h link.h \
|
||||
locale.h malloc.h memory.h monetary.h mpool.h ndbm.h netconfig.h \
|
||||
netdb.h nl_types.h nlist.h nsswitch.h objformat.h paths.h pthread.h \
|
||||
netdb.h nl_types.h nlist.h nss.h nsswitch.h objformat.h paths.h \
|
||||
pthread.h \
|
||||
pthread_np.h pwd.h ranlib.h readpassphrase.h regex.h regexp.h \
|
||||
resolv.h rune.h runetype.h search.h setjmp.h sgtty.h signal.h stab.h \
|
||||
stdbool.h stddef.h stdio.h stdlib.h strhash.h string.h stringlist.h \
|
||||
|
56
include/nss.h
Normal file
56
include/nss.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed for the FreeBSD Project by
|
||||
* Jacques A. Vidrine, Safeport Network Services, and Network
|
||||
* Associates Laboratories, the Security Research Division of Network
|
||||
* Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
|
||||
* ("CBOSS"), as part of the DARPA CHATS research program.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
* Compatibility header for the GNU C Library-style nsswitch interface.
|
||||
*/
|
||||
#ifndef _NSS_H_
|
||||
#define _NSS_H_
|
||||
|
||||
#include <nsswitch.h>
|
||||
|
||||
enum nss_status {
|
||||
NSS_STATUS_TRYAGAIN = -2,
|
||||
NSS_STATUS_UNAVAIL,
|
||||
NSS_STATUS_NOTFOUND,
|
||||
NSS_STATUS_SUCCESS,
|
||||
NSS_STATUS_RETURN
|
||||
};
|
||||
|
||||
#define __nss_compat_result(rv) \
|
||||
((rv == NSS_STATUS_TRYAGAIN) ? NS_TRYAGAIN : \
|
||||
(rv == NSS_STATUS_UNAVAIL) ? NS_UNAVAIL : \
|
||||
(rv == NSS_STATUS_NOTFOUND) ? NS_NOTFOUND : \
|
||||
(rv == NSS_STATUS_SUCCESS) ? NS_SUCCESS : \
|
||||
(rv == NSS_STATUS_RETURN) ? NS_RETURN : 0)
|
||||
|
||||
#endif
|
@ -41,20 +41,24 @@
|
||||
#define _NSSWITCH_H 1
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#define NSS_MODULE_INTERFACE_VERSION 1
|
||||
|
||||
#ifndef _PATH_NS_CONF
|
||||
#define _PATH_NS_CONF "/etc/nsswitch.conf"
|
||||
#endif
|
||||
|
||||
#define NS_CONTINUE 0
|
||||
#define NS_RETURN 1
|
||||
/* NSS source actions */
|
||||
#define NS_ACTION_CONTINUE 0 /* try the next source */
|
||||
#define NS_ACTION_RETURN 1 /* look no further */
|
||||
|
||||
#define NS_SUCCESS (1<<0) /* entry was found */
|
||||
#define NS_UNAVAIL (1<<1) /* source not responding, or corrupt */
|
||||
#define NS_NOTFOUND (1<<2) /* source responded 'no such entry' */
|
||||
#define NS_TRYAGAIN (1<<3) /* source busy, may respond to retrys */
|
||||
#define NS_TRYAGAIN (1<<3) /* source busy, may respond to retry */
|
||||
#define NS_RETURN (1<<4) /* stop search, e.g. for ERANGE */
|
||||
#define NS_TERMINATE (NS_SUCCESS|NS_RETURN) /* flags that end search */
|
||||
#define NS_STATUSMASK 0x000000ff /* bitmask to get the status flags */
|
||||
|
||||
/*
|
||||
@ -98,13 +102,26 @@
|
||||
#define NSDB_TTYS "ttys"
|
||||
|
||||
/*
|
||||
* ns_dtab - `nsswitch dispatch table'
|
||||
* contains an entry for each source and the appropriate function to call
|
||||
* ns_dtab `method' function signature.
|
||||
*/
|
||||
typedef int (*nss_method)(void *_retval, void *_mdata, va_list _ap);
|
||||
|
||||
/*
|
||||
* Macro for generating method prototypes.
|
||||
*/
|
||||
typedef struct {
|
||||
const char *src;
|
||||
int (*callback)(void *retval, void *cb_data, va_list ap);
|
||||
void *cb_data;
|
||||
#define NSS_METHOD_PROTOTYPE(method) \
|
||||
int method(void *, void *, va_list)
|
||||
|
||||
/*
|
||||
* ns_dtab - `nsswitch dispatch table'
|
||||
* Contains an entry for each source and the appropriate function to
|
||||
* call. ns_dtabs are used in the nsdispatch() API in order to allow
|
||||
* the application to override built-in actions.
|
||||
*/
|
||||
typedef struct _ns_dtab {
|
||||
const char *src; /* Source this entry implements */
|
||||
nss_method method; /* Method to be called */
|
||||
void *mdata; /* Data passed to method */
|
||||
} ns_dtab;
|
||||
|
||||
/*
|
||||
@ -130,7 +147,7 @@ typedef struct {
|
||||
* used by the nsparser routines to store a mapping between a source
|
||||
* and its dispatch control flags for a given database.
|
||||
*/
|
||||
typedef struct {
|
||||
typedef struct _ns_src {
|
||||
const char *name;
|
||||
u_int32_t flags;
|
||||
} ns_src;
|
||||
@ -142,6 +159,38 @@ typedef struct {
|
||||
*/
|
||||
extern const ns_src __nsdefaultsrc[];
|
||||
|
||||
/*
|
||||
* ns_mtab - NSS method table
|
||||
* An NSS module provides a mapping from (database name, method name)
|
||||
* tuples to the nss_method and associated data.
|
||||
*/
|
||||
typedef struct _ns_mtab {
|
||||
const char *database;
|
||||
const char *name;
|
||||
nss_method method;
|
||||
void *mdata;
|
||||
} ns_mtab;
|
||||
|
||||
/*
|
||||
* NSS module de-registration, called at module unload.
|
||||
*/
|
||||
typedef void (*nss_module_unregister_fn)(ns_mtab *, unsigned int);
|
||||
|
||||
/*
|
||||
* NSS module registration, called at module load.
|
||||
*/
|
||||
typedef ns_mtab *(*nss_module_register_fn)(const char *, unsigned int *,
|
||||
nss_module_unregister_fn *);
|
||||
|
||||
/*
|
||||
* Many NSS interfaces follow the getXXnam, getXXid, getXXent pattern.
|
||||
* Developers are encouraged to use nss_lookup_type where approriate.
|
||||
*/
|
||||
enum nss_lookup_type {
|
||||
nss_lt_name = 1,
|
||||
nss_lt_id = 2,
|
||||
nss_lt_all = 3
|
||||
};
|
||||
|
||||
#ifdef _NS_PRIVATE
|
||||
|
||||
@ -154,12 +203,23 @@ extern const ns_src __nsdefaultsrc[];
|
||||
* for each database in /etc/nsswitch.conf there is a ns_dbt, with its
|
||||
* name and a list of ns_src's containing the source information.
|
||||
*/
|
||||
typedef struct {
|
||||
typedef struct _ns_dbt {
|
||||
const char *name; /* name of database */
|
||||
ns_src *srclist; /* list of sources */
|
||||
int srclistsize; /* size of srclist */
|
||||
} ns_dbt;
|
||||
|
||||
/*
|
||||
* ns_mod - NSS module
|
||||
*/
|
||||
typedef struct _ns_mod {
|
||||
char *name; /* module name */
|
||||
void *handle; /* handle from dlopen */
|
||||
ns_mtab *mtab; /* method table */
|
||||
unsigned int mtabsize; /* count of entries in method table */
|
||||
nss_module_unregister_fn unregister; /* called to unload module */
|
||||
} ns_mod;
|
||||
|
||||
#endif /* _NS_PRIVATE */
|
||||
|
||||
|
||||
@ -171,12 +231,14 @@ extern int nsdispatch(void *, const ns_dtab [], const char *,
|
||||
|
||||
#ifdef _NS_PRIVATE
|
||||
extern void _nsdbtaddsrc(ns_dbt *, const ns_src *);
|
||||
extern void _nsdbtdump(const ns_dbt *);
|
||||
extern const ns_dbt *_nsdbtget(const char *);
|
||||
extern void _nsdbtput(const ns_dbt *);
|
||||
extern void _nsyyerror(const char *);
|
||||
extern int _nsyylex(void);
|
||||
extern int _nsyyparse(void);
|
||||
extern int _nsyylineno;
|
||||
#ifdef _NSS_DEBUG
|
||||
extern void _nsdbtdump(const ns_dbt *);
|
||||
#endif
|
||||
#endif /* _NS_PRIVATE */
|
||||
|
||||
__END_DECLS
|
||||
|
@ -93,7 +93,9 @@ MLINKS+=getnetgrent.3 endnetgrent.3 getnetgrent.3 innetgr.3 \
|
||||
getnetgrent.3 setnetgrent.3
|
||||
MLINKS+=getprogname.3 setprogname.3
|
||||
MLINKS+=getpwent.3 endpwent.3 getpwent.3 getpwnam.3 getpwent.3 getpwuid.3 \
|
||||
getpwent.3 setpassent.3 getpwent.3 setpwent.3 getpwent.3 setpwfile.3
|
||||
getpwent.3 setpassent.3 getpwent.3 setpwent.3 getpwent.3 setpwfile.3 \
|
||||
getpwent.3 getpwent_r.3 getpwent.3 getpwnam_r.3 \
|
||||
getpwent.3 getpwuid_r.3
|
||||
MLINKS+=getttyent.3 endttyent.3 getttyent.3 getttynam.3 \
|
||||
getttyent.3 isdialuptty.3 getttyent.3 isnettty.3 \
|
||||
getttyent.3 setttyent.3
|
||||
|
@ -42,6 +42,7 @@
|
||||
*/
|
||||
#define err _err
|
||||
#define warn _warn
|
||||
#define nsdispatch _nsdispatch
|
||||
|
||||
/*
|
||||
* Prototypes for syscalls/functions that need to be overridden
|
||||
|
80
lib/libc/include/nss_tls.h
Normal file
80
lib/libc/include/nss_tls.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed for the FreeBSD Project by
|
||||
* Jacques A. Vidrine, Safeport Network Services, and Network
|
||||
* Associates Laboratories, the Security Research Division of Network
|
||||
* Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
|
||||
* ("CBOSS"), as part of the DARPA CHATS research program.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
* Macros which generate thread local storage handling code in NSS modules.
|
||||
*/
|
||||
#ifndef _NSS_TLS_H_
|
||||
#define _NSS_TLS_H_
|
||||
|
||||
#define NSS_TLS_HANDLING(name) \
|
||||
static pthread_key_t name##_state_key; \
|
||||
static void name##_keyinit(void); \
|
||||
static int name##_getstate(struct name##_state **); \
|
||||
\
|
||||
static void \
|
||||
name##_keyinit(void) \
|
||||
{ \
|
||||
(void)_pthread_key_create(&name##_state_key, name##_endstate); \
|
||||
} \
|
||||
\
|
||||
static int \
|
||||
name##_getstate(struct name##_state **p) \
|
||||
{ \
|
||||
static struct name##_state st; \
|
||||
static pthread_once_t keyinit = PTHREAD_ONCE_INIT; \
|
||||
int rv; \
|
||||
\
|
||||
if (!__isthreaded || _pthread_main_np() != 0) { \
|
||||
*p = &st; \
|
||||
return (0); \
|
||||
} \
|
||||
rv = _pthread_once(&keyinit, name##_keyinit); \
|
||||
if (rv != 0) \
|
||||
return (rv); \
|
||||
*p = _pthread_getspecific(name##_state_key); \
|
||||
if (*p != NULL) \
|
||||
return (0); \
|
||||
*p = calloc(1, sizeof(*p)); \
|
||||
if (*p == NULL) \
|
||||
return (ENOMEM); \
|
||||
rv = _pthread_setspecific(name##_state_key, *p); \
|
||||
if (rv != 0) { \
|
||||
free(*p); \
|
||||
*p = NULL; \
|
||||
} \
|
||||
return (rv); \
|
||||
} \
|
||||
/* allow the macro invocation to end with a semicolon */ \
|
||||
typedef int _##name##_bmVjdGFy
|
||||
|
||||
#endif /* _NSS_TLS_H_ */
|
@ -148,5 +148,6 @@ int _flock(int, int);
|
||||
|
||||
#undef err
|
||||
#undef warn
|
||||
#undef nsdispatch
|
||||
|
||||
#endif /* _UN_NAMESPACE_H_ */
|
||||
|
@ -15,7 +15,7 @@ SRCS+= addr2ascii.c ascii2addr.c base64.c ether_addr.c getaddrinfo.c \
|
||||
inet_netof.c inet_network.c inet_ntoa.c inet_ntop.c \
|
||||
inet_pton.c ip6opt.c linkaddr.c map_v4v6.c name6.c \
|
||||
ns_name.c ns_netint.c ns_parse.c ns_print.c ns_ttl.c \
|
||||
nsdispatch.c nslexer.c nsparser.c \
|
||||
nsdispatch.c nslexer.c nsparser.c nss_compat.c \
|
||||
nsap_addr.c rcmd.c rcmdsh.c recv.c res_comp.c res_data.c res_debug.c \
|
||||
res_init.c res_mkquery.c res_mkupdate.c res_query.c res_send.c \
|
||||
res_update.c rthdr.c send.c sockatmark.c vars.c
|
||||
|
@ -35,7 +35,7 @@
|
||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd January 19, 1999
|
||||
.Dd April 16, 2003
|
||||
.Dt NSDISPATCH 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -44,98 +44,111 @@
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
.In stdarg.h
|
||||
.In nsswitch.h
|
||||
.Ft int
|
||||
.Fo nsdispatch
|
||||
.Fa "void *retval"
|
||||
.Fa "const ns_dtab dtab[]"
|
||||
.Fa "const char *database"
|
||||
.Fa "const char *method"
|
||||
.Fa "const char *method_name"
|
||||
.Fa "const ns_src defaults[]"
|
||||
.Fa "..."
|
||||
.Fc
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn nsdispatch
|
||||
function invokes the callback functions specified in
|
||||
function invokes the methods specified in
|
||||
.Va dtab
|
||||
in the order given in
|
||||
.Pa /etc/nsswitch.conf
|
||||
in the order given by
|
||||
.Xr nsswitch.conf 5
|
||||
for the database
|
||||
.Va database
|
||||
until a successful entry is found.
|
||||
.Pp
|
||||
.Va retval
|
||||
is passed to each callback function to modify as necessary
|
||||
(to pass back to the caller of
|
||||
.Fn nsdispatch )
|
||||
is passed to each method to modify as necessary, to pass back results to
|
||||
the caller of
|
||||
.Fn nsdispatch .
|
||||
.Pp
|
||||
Each method has the function signature described by the typedef:
|
||||
.Pp
|
||||
.Ft typedef "int \*(lp*nss_method\*(rp\*(lpvoid *retval, void *mdata, va_list *ap\*(rp" ;
|
||||
.Pp
|
||||
.Va dtab
|
||||
is an array of
|
||||
.Va ns_dtab
|
||||
structures, which have the following format:
|
||||
.Bd -literal -offset indent
|
||||
typedef struct {
|
||||
const char *src;
|
||||
int (*cb)(void *retval, void *cb_data, va_list ap);
|
||||
void *cb_data;
|
||||
typedef struct _ns_dtab {
|
||||
const char *src;
|
||||
nss_method method;
|
||||
void *mdata;
|
||||
} ns_dtab;
|
||||
.Ed
|
||||
.Pp
|
||||
.Bd -ragged -offset indent
|
||||
For each source type that is implemented, an entry with
|
||||
The
|
||||
.Fa dtab
|
||||
array should consist of one entry for each source type that is
|
||||
implemented, with
|
||||
.Va src
|
||||
set to the name of the source,
|
||||
.Va cb
|
||||
defined as a function which handles that source, and
|
||||
.Va cb_data
|
||||
is used to pass arbitrary data to the callback function.
|
||||
as the name of the source,
|
||||
.Va method
|
||||
as a function which handles that source, and
|
||||
.Va mdata
|
||||
as a handle on arbitrary data to be passed to the method.
|
||||
The last entry in
|
||||
.Va dtab
|
||||
should contain
|
||||
.Dv NULL
|
||||
values for
|
||||
.Va src ,
|
||||
.Va cb ,
|
||||
.Va method ,
|
||||
and
|
||||
.Va cb_data .
|
||||
.Va mdata .
|
||||
.Ed
|
||||
.Pp
|
||||
.Va method
|
||||
is usually the name of the function calling
|
||||
.Fn nsdispatch .
|
||||
When dynamic loading is supported, a symbol constructed from
|
||||
.Va database ,
|
||||
the current source, and
|
||||
.Va method
|
||||
will be used as the name to invoke the dynamically loaded function.
|
||||
Additionally, methods may be implemented in NSS modules, in
|
||||
which case they are selected using the
|
||||
.Fa database
|
||||
and
|
||||
.Fa method_name
|
||||
arguments along with the configured source.
|
||||
(The methods supplied via
|
||||
.Fa dtab
|
||||
take priority over those implemented in NSS modules in the event
|
||||
of a conflict.)
|
||||
.Pp
|
||||
.Va defaults
|
||||
contains a list of default sources to try in the case of
|
||||
a missing or corrupt
|
||||
.Xr nsswitch.conf 5 ,
|
||||
or if there isn't a relevant entry for
|
||||
contains a list of default sources to try if
|
||||
.Xr nsswitch.conf 5
|
||||
is missing or corrupted, or if there is no relevant entry for
|
||||
.Va database .
|
||||
It is an array of
|
||||
.Va ns_src
|
||||
structures, which have the following format:
|
||||
.Bd -literal -offset indent
|
||||
typedef struct {
|
||||
const char *src;
|
||||
u_int32_t flags;
|
||||
typedef struct _ns_src {
|
||||
const char *src;
|
||||
u_int32_t flags;
|
||||
} ns_src;
|
||||
.Ed
|
||||
.Pp
|
||||
.Bd -ragged -offset indent
|
||||
For each default source type, an entry with
|
||||
.Va src
|
||||
set to the name of the source, and
|
||||
The
|
||||
.Fa defaults
|
||||
array should consist of one entry for each source to be configured by
|
||||
default indicated by
|
||||
.Va src ,
|
||||
and
|
||||
.Va flags
|
||||
set to the relevant flags
|
||||
set to the criterion desired
|
||||
(usually
|
||||
.Dv NS_SUCCESS ;
|
||||
refer to
|
||||
.Sx Callback return values
|
||||
.Sx Method return values
|
||||
for more information).
|
||||
The last entry in
|
||||
.Va defaults
|
||||
@ -149,18 +162,18 @@ set to 0.
|
||||
.Pp
|
||||
For convenience, a global variable defined as:
|
||||
.Dl extern const ns_src __nsdefaultsrc[];
|
||||
exists which contains a single default entry for
|
||||
exists which contains a single default entry for the source
|
||||
.Sq files
|
||||
for use by callers which don't require complicated default rules.
|
||||
that may be used by callers which do not require complicated default
|
||||
rules.
|
||||
.Ed
|
||||
.Pp
|
||||
.Sq Va ...
|
||||
are optional extra arguments, which
|
||||
are passed to the appropriate callback function as a variable argument
|
||||
list of the type
|
||||
.Va va_list .
|
||||
are optional extra arguments, which are passed to the appropriate method
|
||||
as a variable argument list of the type
|
||||
.Vt va_list .
|
||||
.Ss Valid source types
|
||||
Whilst there is support for arbitrary sources, the following
|
||||
While there is support for arbitrary sources, the following
|
||||
#defines for commonly implemented sources are available:
|
||||
.Bl -column NS_COMPAT COMPAT -offset indent
|
||||
.It Sy "#define value"
|
||||
@ -174,29 +187,32 @@ Refer to
|
||||
.Xr nsswitch.conf 5
|
||||
for a complete description of what each source type is.
|
||||
.Pp
|
||||
.Ss Callback return values
|
||||
The callback functions should return one of the following values
|
||||
depending upon status of the lookup:
|
||||
.Bl -column NS_NOTFOUND -offset indent
|
||||
.Ss Method return values
|
||||
The
|
||||
.Vt nss_method
|
||||
functions must return one of the following values depending upon status
|
||||
of the lookup:
|
||||
.Bl -column "RETURN VALUE" "STATUS CODE"
|
||||
.It Sy "Return value Status code"
|
||||
.It "NS_SUCCESS success"
|
||||
.It "NS_NOTFOUND notfound"
|
||||
.It "NS_UNAVAIL unavail"
|
||||
.It "NS_TRYAGAIN tryagain"
|
||||
.It "NS_RETURN -none-"
|
||||
.El
|
||||
.Pp
|
||||
Refer to
|
||||
.Xr nsswitch.conf 5
|
||||
for a complete description of what each status code is.
|
||||
for a complete description of each status code.
|
||||
.Pp
|
||||
The
|
||||
.Fn nsdispatch
|
||||
function returns the value of the callback that caused the dispatcher to
|
||||
finish, or NS_NOTFOUND otherwise.
|
||||
function returns the value of the method that caused the dispatcher to
|
||||
terminate, or NS_NOTFOUND otherwise.
|
||||
.Sh SEE ALSO
|
||||
.Xr hesiod 3 ,
|
||||
.Xr stdarg 3 ,
|
||||
.Xr ypclnt 3 ,
|
||||
.Xr yp 8 ,
|
||||
.Xr nsswitch.conf 5
|
||||
.Sh HISTORY
|
||||
The
|
||||
@ -208,25 +224,22 @@ It was imported from the
|
||||
Project,
|
||||
where it appeared first in
|
||||
.Nx 1.4 .
|
||||
Support for NSS modules first appeared in
|
||||
.Fx 5.1 .
|
||||
.Sh AUTHORS
|
||||
Luke Mewburn
|
||||
.Aq lukem@netbsd.org
|
||||
wrote this freely distributable name-service switch implementation,
|
||||
wrote this freely-distributable name-service switch implementation,
|
||||
using ideas from the
|
||||
.Tn ULTRIX
|
||||
.Xr svc.conf 5
|
||||
"svc.conf\*(lp5\*(rp"
|
||||
and
|
||||
.Tn Solaris
|
||||
.Xr nsswitch.conf 4
|
||||
"nsswitch.conf\*(lp4\*(rp"
|
||||
manual pages.
|
||||
.Sh BUGS
|
||||
The
|
||||
.Fx Project
|
||||
added the support for threads and NSS modules, and normalized the uses
|
||||
of
|
||||
.Fn nsdispatch
|
||||
function is not thread safe.
|
||||
This will be rectified in the future.
|
||||
.Pp
|
||||
Currently there is no support for dynamically loadable dispatcher callback
|
||||
functions.
|
||||
It is anticipated that this will be added in the future in the back-end
|
||||
without requiring changes to code that invokes
|
||||
.Fn nsdispatch .
|
||||
within the standard C library.
|
||||
|
@ -35,25 +35,75 @@
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Portions of this software were developed for the FreeBSD Project by
|
||||
* Jacques A. Vidrine, Safeport Network Services, and Network
|
||||
* Associates Laboratories, the Security Research Division of Network
|
||||
* Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
|
||||
* ("CBOSS"), as part of the DARPA CHATS research program.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "namespace.h"
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "namespace.h"
|
||||
#include <err.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#define _NS_PRIVATE
|
||||
#include <nsswitch.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include "un-namespace.h"
|
||||
|
||||
enum _nss_constants {
|
||||
/* Number of elements allocated when we grow a vector */
|
||||
ELEMSPERCHUNK = 8
|
||||
};
|
||||
|
||||
/*
|
||||
* Global NSS data structures are mostly read-only, but we update
|
||||
* them when we read or re-read the nsswitch.conf.
|
||||
*/
|
||||
static pthread_rwlock_t nss_lock = PTHREAD_RWLOCK_INITIALIZER;
|
||||
|
||||
/*
|
||||
* Runtime determination of whether we are dynamically linked or not.
|
||||
*/
|
||||
extern int _DYNAMIC __attribute__ ((weak));
|
||||
#define is_dynamic() (&_DYNAMIC != NULL)
|
||||
|
||||
/*
|
||||
* default sourcelist: `files'
|
||||
*/
|
||||
@ -62,53 +112,178 @@ const ns_src __nsdefaultsrc[] = {
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
|
||||
static int _nsmapsize = 0;
|
||||
/* Database, source mappings. */
|
||||
static unsigned int _nsmapsize;
|
||||
static ns_dbt *_nsmap = NULL;
|
||||
|
||||
/* NSS modules. */
|
||||
static unsigned int _nsmodsize;
|
||||
static ns_mod *_nsmod;
|
||||
|
||||
/* Placeholder for builtin modules' dlopen `handle'. */
|
||||
static int __nss_builtin_handle;
|
||||
static void *nss_builtin_handle = &__nss_builtin_handle;
|
||||
|
||||
/*
|
||||
* size of dynamic array chunk for _nsmap and _nsmap[x].srclist
|
||||
* Attempt to spew relatively uniform messages to syslog.
|
||||
*/
|
||||
#define NSELEMSPERCHUNK 8
|
||||
#define nss_log(level, fmt, ...) \
|
||||
syslog((level), "NSSWITCH(%s): " fmt, __func__, __VA_ARGS__)
|
||||
#define nss_log_simple(level, s) \
|
||||
syslog((level), "NSSWITCH(%s): " s, __func__)
|
||||
|
||||
/*
|
||||
* Dynamically growable arrays are used for lists of databases, sources,
|
||||
* and modules. The following `vector' interface is used to isolate the
|
||||
* common operations.
|
||||
*/
|
||||
typedef int (*vector_comparison)(const void *, const void *);
|
||||
typedef void (*vector_free_elem)(void *);
|
||||
static void vector_sort(void *, unsigned int, size_t,
|
||||
vector_comparison);
|
||||
static void vector_free(void **, unsigned int *, size_t,
|
||||
vector_free_elem);
|
||||
static void *vector_ref(unsigned int, void *, unsigned int, size_t);
|
||||
static void *vector_search(const void *, void *, unsigned int, size_t,
|
||||
vector_comparison);
|
||||
static int vector_append(const void *, void **, unsigned int *, size_t);
|
||||
|
||||
|
||||
int _nscmp(const void *, const void *);
|
||||
/*
|
||||
* Internal interfaces.
|
||||
*/
|
||||
static int string_compare(const void *, const void *);
|
||||
static int mtab_compare(const void *, const void *);
|
||||
static int nss_configure(void);
|
||||
static void ns_dbt_free(ns_dbt *);
|
||||
static void ns_mod_free(ns_mod *);
|
||||
static void ns_src_free(ns_src **, int);
|
||||
static void nss_load_builtin_modules(void);
|
||||
static void nss_load_module(const char *, nss_module_register_fn);
|
||||
static void nss_atexit(void);
|
||||
/* nsparser */
|
||||
extern FILE *_nsyyin;
|
||||
|
||||
|
||||
int
|
||||
_nscmp(a, b)
|
||||
const void *a;
|
||||
const void *b;
|
||||
/*
|
||||
* The vector operations
|
||||
*/
|
||||
static void
|
||||
vector_sort(void *vec, unsigned int count, size_t esize,
|
||||
vector_comparison comparison)
|
||||
{
|
||||
return (strcasecmp(((const ns_dbt *)a)->name,
|
||||
((const ns_dbt *)b)->name));
|
||||
qsort(vec, count, esize, comparison);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_nsdbtaddsrc(dbt, src)
|
||||
ns_dbt *dbt;
|
||||
const ns_src *src;
|
||||
static void *
|
||||
vector_search(const void *key, void *vec, unsigned int count, size_t esize,
|
||||
vector_comparison comparison)
|
||||
{
|
||||
if ((dbt->srclistsize % NSELEMSPERCHUNK) == 0) {
|
||||
dbt->srclist = (ns_src *)realloc(dbt->srclist,
|
||||
(dbt->srclistsize + NSELEMSPERCHUNK) * sizeof(ns_src));
|
||||
if (dbt->srclist == NULL)
|
||||
_err(1, "nsdispatch: memory allocation failure");
|
||||
return (bsearch(key, vec, count, esize, comparison));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
vector_append(const void *elem, void **vec, unsigned int *count, size_t esize)
|
||||
{
|
||||
void *p;
|
||||
|
||||
if ((*count % ELEMSPERCHUNK) == 0) {
|
||||
p = realloc(*vec, (*count + ELEMSPERCHUNK) * esize);
|
||||
if (p == NULL) {
|
||||
nss_log_simple(LOG_ERR, "memory allocation failure");
|
||||
return (0);
|
||||
} else
|
||||
*vec = p;
|
||||
}
|
||||
memmove(&dbt->srclist[dbt->srclistsize++], src, sizeof(ns_src));
|
||||
memmove((void *)(((uintptr_t)*vec) + (*count * esize)),
|
||||
elem, esize);
|
||||
(*count)++;
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
vector_ref(unsigned int i, void *vec, unsigned int count, size_t esize)
|
||||
{
|
||||
if (i < count)
|
||||
return (void *)((uintptr_t)vec + (i * esize));
|
||||
else
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
vector_free(void **vec, unsigned int *count, size_t esize,
|
||||
vector_free_elem free_elem)
|
||||
{
|
||||
unsigned int i;
|
||||
void *elem;
|
||||
|
||||
for (i = 0; i < *count; i++) {
|
||||
elem = vector_ref(i, *vec, *count, esize);
|
||||
if (elem != NULL)
|
||||
free_elem(elem);
|
||||
}
|
||||
free(*vec);
|
||||
*vec = NULL;
|
||||
*count = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Comparison functions for vector_search.
|
||||
*/
|
||||
static int
|
||||
string_compare(const void *a, const void *b)
|
||||
{
|
||||
return (strcasecmp(*(const char * const *)a, *(const char * const *)b));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
mtab_compare(const void *a, const void *b)
|
||||
{
|
||||
int cmp;
|
||||
|
||||
cmp = strcmp(((const ns_mtab *)a)->name, ((const ns_mtab *)b)->name);
|
||||
if (cmp != 0)
|
||||
return (cmp);
|
||||
else
|
||||
return (strcmp(((const ns_mtab *)a)->database,
|
||||
((const ns_mtab *)b)->database));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* NSS nsmap management.
|
||||
*/
|
||||
void
|
||||
_nsdbtdump(dbt)
|
||||
const ns_dbt *dbt;
|
||||
_nsdbtaddsrc(ns_dbt *dbt, const ns_src *src)
|
||||
{
|
||||
const ns_mod *modp;
|
||||
|
||||
vector_append(src, (void **)&dbt->srclist, &dbt->srclistsize,
|
||||
sizeof(*src));
|
||||
modp = vector_search(&src->name, _nsmod, _nsmodsize, sizeof(*_nsmod),
|
||||
string_compare);
|
||||
if (modp == NULL)
|
||||
nss_load_module(src->name, NULL);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _NSS_DEBUG
|
||||
void
|
||||
_nsdbtdump(const ns_dbt *dbt)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("%s (%d source%s):", dbt->name, dbt->srclistsize,
|
||||
dbt->srclistsize == 1 ? "" : "s");
|
||||
for (i = 0; i < dbt->srclistsize; i++) {
|
||||
for (i = 0; i < (int)dbt->srclistsize; i++) {
|
||||
printf(" %s", dbt->srclist[i].name);
|
||||
if (!(dbt->srclist[i].flags &
|
||||
(NS_UNAVAIL|NS_NOTFOUND|NS_TRYAGAIN)) &&
|
||||
@ -127,103 +302,285 @@ _nsdbtdump(dbt)
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
const ns_dbt *
|
||||
_nsdbtget(name)
|
||||
const char *name;
|
||||
/*
|
||||
* The first time nsdispatch is called (during a process's lifetime,
|
||||
* or after nsswitch.conf has been updated), nss_configure will
|
||||
* prepare global data needed by NSS.
|
||||
*/
|
||||
static int
|
||||
nss_configure(void)
|
||||
{
|
||||
static time_t confmod;
|
||||
|
||||
static pthread_mutex_t conf_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static time_t confmod;
|
||||
struct stat statbuf;
|
||||
ns_dbt dbt;
|
||||
int result;
|
||||
const char *path;
|
||||
|
||||
extern FILE *_nsyyin;
|
||||
extern int _nsyyparse(void);
|
||||
|
||||
dbt.name = name;
|
||||
|
||||
if (confmod) {
|
||||
if (stat(_PATH_NS_CONF, &statbuf) == -1)
|
||||
return (NULL);
|
||||
if (confmod < statbuf.st_mtime) {
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < _nsmapsize; i++) {
|
||||
for (j = 0; j < _nsmap[i].srclistsize; j++) {
|
||||
if (_nsmap[i].srclist[j].name != NULL) {
|
||||
/*LINTED const cast*/
|
||||
free((void *)
|
||||
_nsmap[i].srclist[j].name);
|
||||
}
|
||||
}
|
||||
if (_nsmap[i].srclist)
|
||||
free(_nsmap[i].srclist);
|
||||
if (_nsmap[i].name) {
|
||||
/*LINTED const cast*/
|
||||
free((void *)_nsmap[i].name);
|
||||
}
|
||||
}
|
||||
if (_nsmap)
|
||||
free(_nsmap);
|
||||
_nsmap = NULL;
|
||||
_nsmapsize = 0;
|
||||
confmod = 0;
|
||||
}
|
||||
}
|
||||
if (!confmod) {
|
||||
if (stat(_PATH_NS_CONF, &statbuf) == -1)
|
||||
return (NULL);
|
||||
_nsyyin = fopen(_PATH_NS_CONF, "r");
|
||||
if (_nsyyin == NULL)
|
||||
return (NULL);
|
||||
_nsyyparse();
|
||||
(void)fclose(_nsyyin);
|
||||
qsort(_nsmap, (size_t)_nsmapsize, sizeof(ns_dbt), _nscmp);
|
||||
confmod = statbuf.st_mtime;
|
||||
}
|
||||
return (bsearch(&dbt, _nsmap, (size_t)_nsmapsize, sizeof(ns_dbt),
|
||||
_nscmp));
|
||||
#if defined(_NSS_DEBUG) && defined(_NSS_SHOOT_FOOT)
|
||||
/* NOTE WELL: THIS IS A SECURITY HOLE. This must only be built
|
||||
* for debugging purposes and MUST NEVER be used in production.
|
||||
*/
|
||||
path = getenv("NSSWITCH_CONF");
|
||||
if (path == NULL)
|
||||
#endif
|
||||
path = _PATH_NS_CONF;
|
||||
if (stat(path, &statbuf) != 0)
|
||||
return (0);
|
||||
if (statbuf.st_mtime <= confmod)
|
||||
return (0);
|
||||
result = _pthread_mutex_trylock(&conf_lock);
|
||||
if (result != 0)
|
||||
return (0);
|
||||
(void)_pthread_rwlock_unlock(&nss_lock);
|
||||
result = _pthread_rwlock_wrlock(&nss_lock);
|
||||
if (result != 0)
|
||||
goto fin2;
|
||||
_nsyyin = fopen(path, "r");
|
||||
if (_nsyyin == NULL)
|
||||
goto fin;
|
||||
vector_free((void **)&_nsmap, &_nsmapsize, sizeof(*_nsmap),
|
||||
(vector_free_elem)ns_dbt_free);
|
||||
vector_free((void **)&_nsmod, &_nsmodsize, sizeof(*_nsmod),
|
||||
(vector_free_elem)ns_mod_free);
|
||||
nss_load_builtin_modules();
|
||||
_nsyyparse();
|
||||
(void)fclose(_nsyyin);
|
||||
vector_sort(_nsmap, _nsmapsize, sizeof(*_nsmap), string_compare);
|
||||
if (confmod == 0)
|
||||
(void)atexit(nss_atexit);
|
||||
confmod = statbuf.st_mtime;
|
||||
fin:
|
||||
(void)_pthread_rwlock_unlock(&nss_lock);
|
||||
result = _pthread_rwlock_rdlock(&nss_lock);
|
||||
fin2:
|
||||
(void)_pthread_mutex_unlock(&conf_lock);
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_nsdbtput(dbt)
|
||||
const ns_dbt *dbt;
|
||||
_nsdbtput(const ns_dbt *dbt)
|
||||
{
|
||||
int i;
|
||||
unsigned int i;
|
||||
ns_dbt *p;
|
||||
|
||||
for (i = 0; i < _nsmapsize; i++) {
|
||||
if (_nscmp(dbt, &_nsmap[i]) == 0) {
|
||||
/* overwrite existing entry */
|
||||
if (_nsmap[i].srclist != NULL)
|
||||
free(_nsmap[i].srclist);
|
||||
memmove(&_nsmap[i], dbt, sizeof(ns_dbt));
|
||||
p = vector_ref(i, _nsmap, _nsmapsize, sizeof(*_nsmap));
|
||||
if (string_compare(&dbt->name, &p->name) == 0) {
|
||||
/* overwrite existing entry */
|
||||
if (p->srclist != NULL)
|
||||
ns_src_free(&p->srclist, p->srclistsize);
|
||||
memmove(p, dbt, sizeof(*dbt));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((_nsmapsize % NSELEMSPERCHUNK) == 0) {
|
||||
_nsmap = (ns_dbt *)realloc(_nsmap,
|
||||
(_nsmapsize + NSELEMSPERCHUNK) * sizeof(ns_dbt));
|
||||
if (_nsmap == NULL)
|
||||
_err(1, "nsdispatch: memory allocation failure");
|
||||
}
|
||||
memmove(&_nsmap[_nsmapsize++], dbt, sizeof(ns_dbt));
|
||||
vector_append(dbt, (void **)&_nsmap, &_nsmapsize, sizeof(*_nsmap));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ns_dbt_free(ns_dbt *dbt)
|
||||
{
|
||||
ns_src_free(&dbt->srclist, dbt->srclistsize);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ns_src_free(ns_src **src, int srclistsize)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < srclistsize; i++)
|
||||
if ((*src)[i].name != NULL)
|
||||
/* This one was allocated by nslexer. You'll just
|
||||
* have to trust me.
|
||||
*/
|
||||
free((void *)((*src)[i].name));
|
||||
free(*src);
|
||||
*src = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* NSS module management.
|
||||
*/
|
||||
/* The built-in NSS modules are all loaded at once. */
|
||||
#define NSS_BACKEND(name, reg) \
|
||||
ns_mtab *reg(unsigned int *, nss_module_unregister_fn *);
|
||||
#include "nss_backends.h"
|
||||
#undef NSS_BACKEND
|
||||
|
||||
static void
|
||||
nss_load_builtin_modules(void)
|
||||
{
|
||||
#define NSS_BACKEND(name, reg) nss_load_module(#name, reg);
|
||||
#include "nss_backends.h"
|
||||
#undef NSS_BACKEND
|
||||
}
|
||||
|
||||
|
||||
/* Load a built-in or dynamically linked module. If the `reg_fn'
|
||||
* argument is non-NULL, assume a built-in module and use reg_fn to
|
||||
* register it. Otherwise, search for a dynamic NSS module.
|
||||
*/
|
||||
static void
|
||||
nss_load_module(const char *source, nss_module_register_fn reg_fn)
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
ns_mod mod;
|
||||
nss_module_register_fn fn;
|
||||
|
||||
memset(&mod, 0, sizeof(mod));
|
||||
mod.name = strdup(source);
|
||||
if (mod.name == NULL) {
|
||||
nss_log_simple(LOG_ERR, "memory allocation failure");
|
||||
return;
|
||||
}
|
||||
if (reg_fn != NULL) {
|
||||
/* The placeholder is required, as a NULL handle
|
||||
* represents an invalid module.
|
||||
*/
|
||||
mod.handle = nss_builtin_handle;
|
||||
fn = reg_fn;
|
||||
} else if (!is_dynamic())
|
||||
goto fin;
|
||||
else {
|
||||
if (snprintf(buf, sizeof(buf), "nss_%s.so.%d", mod.name,
|
||||
NSS_MODULE_INTERFACE_VERSION) >= (int)sizeof(buf))
|
||||
goto fin;
|
||||
mod.handle = dlopen(buf, RTLD_LOCAL|RTLD_LAZY);
|
||||
if (mod.handle == NULL) {
|
||||
#ifdef _NSS_DEBUG
|
||||
/* This gets pretty annoying since the built-in
|
||||
* sources aren't modules yet.
|
||||
*/
|
||||
nss_log(LOG_DEBUG, "%s, %s", mod.name, dlerror());
|
||||
#endif
|
||||
goto fin;
|
||||
}
|
||||
fn = (nss_module_register_fn)dlfunc(mod.handle,
|
||||
"nss_module_register");
|
||||
if (fn == NULL) {
|
||||
(void)dlclose(mod.handle);
|
||||
mod.handle = NULL;
|
||||
nss_log(LOG_ERR, "%s, %s", mod.name, dlerror());
|
||||
goto fin;
|
||||
}
|
||||
}
|
||||
mod.mtab = fn(mod.name, &mod.mtabsize, &mod.unregister);
|
||||
if (mod.mtab == NULL || mod.mtabsize == 0) {
|
||||
if (mod.handle != nss_builtin_handle)
|
||||
(void)dlclose(mod.handle);
|
||||
mod.handle = NULL;
|
||||
nss_log(LOG_ERR, "%s, registration failed", mod.name);
|
||||
goto fin;
|
||||
}
|
||||
if (mod.mtabsize > 1)
|
||||
qsort(mod.mtab, mod.mtabsize, sizeof(mod.mtab[0]),
|
||||
mtab_compare);
|
||||
fin:
|
||||
vector_append(&mod, (void **)&_nsmod, &_nsmodsize, sizeof(*_nsmod));
|
||||
vector_sort(_nsmod, _nsmodsize, sizeof(*_nsmod), string_compare);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
ns_mod_free(ns_mod *mod)
|
||||
{
|
||||
|
||||
free(mod->name);
|
||||
if (mod->handle == NULL)
|
||||
return;
|
||||
if (mod->unregister != NULL)
|
||||
mod->unregister(mod->mtab, mod->mtabsize);
|
||||
if (mod->handle != nss_builtin_handle)
|
||||
(void)dlclose(mod->handle);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Cleanup
|
||||
*/
|
||||
static void
|
||||
nss_atexit(void)
|
||||
{
|
||||
(void)_pthread_rwlock_wrlock(&nss_lock);
|
||||
vector_free((void **)&_nsmap, &_nsmapsize, sizeof(*_nsmap),
|
||||
(vector_free_elem)ns_dbt_free);
|
||||
vector_free((void **)&_nsmod, &_nsmodsize, sizeof(*_nsmod),
|
||||
(vector_free_elem)ns_mod_free);
|
||||
(void)_pthread_rwlock_unlock(&nss_lock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Finally, the actual implementation.
|
||||
*/
|
||||
static nss_method
|
||||
nss_method_lookup(const char *source, const char *database,
|
||||
const char *method, const ns_dtab disp_tab[], void **mdata)
|
||||
{
|
||||
ns_mod *mod;
|
||||
ns_mtab *match, key;
|
||||
int i;
|
||||
|
||||
if (disp_tab != NULL)
|
||||
for (i = 0; disp_tab[i].src != NULL; i++)
|
||||
if (strcasecmp(source, disp_tab[i].src) == 0) {
|
||||
*mdata = disp_tab[i].mdata;
|
||||
return (disp_tab[i].method);
|
||||
}
|
||||
mod = vector_search(&source, _nsmod, _nsmodsize, sizeof(*_nsmod),
|
||||
string_compare);
|
||||
if (mod != NULL && mod->handle != NULL) {
|
||||
key.database = database;
|
||||
key.name = method;
|
||||
match = bsearch(&key, mod->mtab, mod->mtabsize,
|
||||
sizeof(mod->mtab[0]), mtab_compare);
|
||||
if (match != NULL) {
|
||||
*mdata = match->mdata;
|
||||
return (match->method);
|
||||
}
|
||||
}
|
||||
nss_log(LOG_DEBUG, "%s, %s, %s, not found", source, database, method);
|
||||
*mdata = NULL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
__weak_reference(_nsdispatch, nsdispatch);
|
||||
|
||||
int
|
||||
nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database,
|
||||
const char *method, const ns_src defaults[], ...)
|
||||
_nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database,
|
||||
const char *method_name, const ns_src defaults[], ...)
|
||||
{
|
||||
va_list ap;
|
||||
int i, curdisp, result;
|
||||
const ns_dbt *dbt;
|
||||
const ns_src *srclist;
|
||||
int srclistsize;
|
||||
nss_method method;
|
||||
void *mdata;
|
||||
int serrno, i, result, srclistsize;
|
||||
|
||||
dbt = _nsdbtget(database);
|
||||
serrno = errno;
|
||||
result = _pthread_rwlock_rdlock(&nss_lock);
|
||||
if (result != 0) {
|
||||
result = NS_UNAVAIL;
|
||||
goto fin;
|
||||
}
|
||||
result = nss_configure();
|
||||
if (result != 0) {
|
||||
result = NS_UNAVAIL;
|
||||
goto fin;
|
||||
}
|
||||
dbt = vector_search(&database, _nsmap, _nsmapsize, sizeof(*_nsmap),
|
||||
string_compare);
|
||||
if (dbt != NULL) {
|
||||
srclist = dbt->srclist;
|
||||
srclistsize = dbt->srclistsize;
|
||||
@ -233,23 +590,20 @@ nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database,
|
||||
while (srclist[srclistsize].name != NULL)
|
||||
srclistsize++;
|
||||
}
|
||||
result = 0;
|
||||
|
||||
for (i = 0; i < srclistsize; i++) {
|
||||
for (curdisp = 0; disp_tab[curdisp].src != NULL; curdisp++)
|
||||
if (strcasecmp(disp_tab[curdisp].src,
|
||||
srclist[i].name) == 0)
|
||||
break;
|
||||
result = 0;
|
||||
if (disp_tab[curdisp].callback) {
|
||||
result = NS_NOTFOUND;
|
||||
method = nss_method_lookup(srclist[i].name, database,
|
||||
method_name, disp_tab, &mdata);
|
||||
if (method != NULL) {
|
||||
va_start(ap, defaults);
|
||||
result = disp_tab[curdisp].callback(retval,
|
||||
disp_tab[curdisp].cb_data, ap);
|
||||
result = method(retval, mdata, ap);
|
||||
va_end(ap);
|
||||
if (result & srclist[i].flags) {
|
||||
if (result & (srclist[i].flags))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (result ? result : NS_NOTFOUND);
|
||||
(void)_pthread_rwlock_unlock(&nss_lock);
|
||||
fin:
|
||||
errno = serrno;
|
||||
return (result);
|
||||
}
|
||||
|
@ -45,10 +45,10 @@ static char *rcsid =
|
||||
|
||||
#include "namespace.h"
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#define _NS_PRIVATE
|
||||
#include <nsswitch.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include "un-namespace.h"
|
||||
|
||||
#include "nsparser.h"
|
||||
@ -85,10 +85,11 @@ STRING [a-zA-Z][a-zA-Z0-9_]*
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
if ((p = strdup(yytext)) == NULL)
|
||||
_err(1,
|
||||
"nsdispatch: memory allocation failure");
|
||||
|
||||
if ((p = strdup(yytext)) == NULL) {
|
||||
syslog(LOG_ERR,
|
||||
"NSSWITCH(nslexer): memory allocation failure");
|
||||
return ERRORTOKEN;
|
||||
}
|
||||
for (i = 0; i < strlen(p); i++) {
|
||||
if (isupper((unsigned char)p[i]))
|
||||
p[i] = tolower((unsigned char)p[i]);
|
||||
@ -113,5 +114,6 @@ _nsyyerror(msg)
|
||||
const char *msg;
|
||||
{
|
||||
|
||||
warnx("%s line %d: %s at '%s'", _PATH_NS_CONF, yylineno, msg, yytext);
|
||||
syslog(LOG_ERR, "NSSWITCH(nslexer): %s line %d: %s at '%s'",
|
||||
_PATH_NS_CONF, yylineno, msg, yytext);
|
||||
} /* _nsyyerror */
|
||||
|
@ -38,17 +38,15 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char *rcsid =
|
||||
"$FreeBSD$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <err.h>
|
||||
#include "namespace.h"
|
||||
#define _NS_PRIVATE
|
||||
#include <nsswitch.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <syslog.h>
|
||||
#include "un-namespace.h"
|
||||
|
||||
static void _nsaddsrctomap(const char *);
|
||||
|
||||
@ -64,6 +62,7 @@ static ns_src cursrc;
|
||||
%token NL
|
||||
%token SUCCESS UNAVAIL NOTFOUND TRYAGAIN
|
||||
%token RETURN CONTINUE
|
||||
%token ERRORTOKEN
|
||||
%token <str> STRING
|
||||
|
||||
%type <mapval> Status Action
|
||||
@ -110,7 +109,7 @@ Srclist
|
||||
Item
|
||||
: STRING
|
||||
{
|
||||
cursrc.flags = NS_SUCCESS;
|
||||
cursrc.flags = NS_TERMINATE;
|
||||
_nsaddsrctomap($1);
|
||||
}
|
||||
| STRING '[' { cursrc.flags = NS_SUCCESS; } Criteria ']'
|
||||
@ -127,9 +126,9 @@ Criteria
|
||||
Criterion
|
||||
: Status '=' Action
|
||||
{
|
||||
if ($3) /* if action == RETURN set RETURN bit */
|
||||
if ($3) /* if action == RETURN set RETURN bit */
|
||||
cursrc.flags |= $1;
|
||||
else /* else unset it */
|
||||
else /* else unset it */
|
||||
cursrc.flags &= ~$1;
|
||||
}
|
||||
;
|
||||
@ -142,8 +141,8 @@ Status
|
||||
;
|
||||
|
||||
Action
|
||||
: RETURN { $$ = 1L; }
|
||||
| CONTINUE { $$ = 0L; }
|
||||
: RETURN { $$ = NS_ACTION_RETURN; }
|
||||
| CONTINUE { $$ = NS_ACTION_CONTINUE; }
|
||||
;
|
||||
|
||||
%%
|
||||
@ -160,16 +159,16 @@ _nsaddsrctomap(elem)
|
||||
if (curdbt.srclistsize > 0) {
|
||||
if ((strcasecmp(elem, NSSRC_COMPAT) == 0) ||
|
||||
(strcasecmp(curdbt.srclist[0].name, NSSRC_COMPAT) == 0)) {
|
||||
/* XXX: syslog the following */
|
||||
warnx("%s line %d: 'compat' used with other sources",
|
||||
syslog(LOG_ERR,
|
||||
"NSSWITCH(nsparser): %s line %d: 'compat' used with other sources",
|
||||
_PATH_NS_CONF, lineno);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < curdbt.srclistsize; i++) {
|
||||
if (strcasecmp(curdbt.srclist[i].name, elem) == 0) {
|
||||
/* XXX: syslog the following */
|
||||
warnx("%s line %d: duplicate source '%s'",
|
||||
syslog(LOG_ERR,
|
||||
"NSSWITCH(nsparser): %s line %d: duplicate source '%s'",
|
||||
_PATH_NS_CONF, lineno, elem);
|
||||
return;
|
||||
}
|
||||
|
43
lib/libc/net/nss_backends.h
Normal file
43
lib/libc/net/nss_backends.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed for the FreeBSD Project by
|
||||
* Jacques A. Vidrine, Safeport Network Services, and Network
|
||||
* Associates Laboratories, the Security Research Division of Network
|
||||
* Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
|
||||
* ("CBOSS"), as part of the DARPA CHATS research program.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
/*
|
||||
* Eventually, the implementations of existing built-in NSS functions
|
||||
* may be moved into NSS modules and live here.
|
||||
*/
|
||||
#if 0
|
||||
NSS_BACKEND( files, _files_nss_module_register )
|
||||
NSS_BACKEND( dns, _dns_nss_module_register )
|
||||
NSS_BACKEND( nis, _nis_nss_module_register )
|
||||
NSS_BACKEND( compat, _compat_nss_module_register )
|
||||
#endif
|
270
lib/libc/net/nss_compat.c
Normal file
270
lib/libc/net/nss_compat.c
Normal file
@ -0,0 +1,270 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed for the FreeBSD Project by
|
||||
* Jacques A. Vidrine, Safeport Network Services, and Network
|
||||
* Associates Laboratories, the Security Research Division of Network
|
||||
* Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
|
||||
* ("CBOSS"), as part of the DARPA CHATS research program.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Compatibility shims for the GNU C Library-style nsswitch interface.
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "namespace.h"
|
||||
#include <sys/param.h>
|
||||
#include <nss.h>
|
||||
#include <pthread.h>
|
||||
#include <pthread_np.h>
|
||||
#include "un-namespace.h"
|
||||
|
||||
|
||||
struct group;
|
||||
struct passwd;
|
||||
|
||||
static int terminator;
|
||||
|
||||
#define DECLARE_TERMINATOR(x) \
|
||||
static pthread_key_t _term_key_##x; \
|
||||
static void \
|
||||
_term_create_##x(void) \
|
||||
{ \
|
||||
(void)_pthread_key_create(&_term_key_##x, NULL); \
|
||||
} \
|
||||
static void *_term_main_##x; \
|
||||
static pthread_once_t _term_once_##x = PTHREAD_ONCE_INIT
|
||||
|
||||
#define SET_TERMINATOR(x, y) \
|
||||
do { \
|
||||
if (_pthread_main_np()) \
|
||||
_term_main_##x = (y); \
|
||||
else { \
|
||||
(void)_pthread_once(&_term_once_##x, _term_create_##x); \
|
||||
(void)_pthread_setspecific(_term_key_##x, y); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CHECK_TERMINATOR(x) \
|
||||
(_pthread_main_np() ? \
|
||||
(_term_main_##x) : \
|
||||
((void)_pthread_once(&_term_once_##x, _term_create_##x), \
|
||||
_pthread_getspecific(_term_key_##x)))
|
||||
|
||||
|
||||
|
||||
DECLARE_TERMINATOR(group);
|
||||
|
||||
|
||||
int
|
||||
__nss_compat_getgrnam_r(void *retval, void *mdata, va_list ap)
|
||||
{
|
||||
int (*fn)(const char *, struct group *, char *, size_t, int *);
|
||||
const char *name;
|
||||
struct group *grp;
|
||||
char *buffer;
|
||||
int *errnop;
|
||||
size_t bufsize;
|
||||
enum nss_status status;
|
||||
|
||||
fn = mdata;
|
||||
name = va_arg(ap, const char *);
|
||||
grp = va_arg(ap, struct group *);
|
||||
buffer = va_arg(ap, char *);
|
||||
bufsize = va_arg(ap, size_t);
|
||||
errnop = va_arg(ap, int *);
|
||||
status = fn(name, grp, buffer, bufsize, errnop);
|
||||
if (status == NS_SUCCESS)
|
||||
*(struct group **)retval = grp;
|
||||
return (__nss_compat_result(status));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
__nss_compat_getgrgid_r(void *retval, void *mdata, va_list ap)
|
||||
{
|
||||
int (*fn)(gid_t, struct group *, char *, size_t, int *);
|
||||
gid_t gid;
|
||||
struct group *grp;
|
||||
char *buffer;
|
||||
int *errnop;
|
||||
size_t bufsize;
|
||||
enum nss_status status;
|
||||
|
||||
fn = mdata;
|
||||
gid = va_arg(ap, gid_t);
|
||||
grp = va_arg(ap, struct group *);
|
||||
buffer = va_arg(ap, char *);
|
||||
bufsize = va_arg(ap, size_t);
|
||||
errnop = va_arg(ap, int *);
|
||||
status = fn(gid, grp, buffer, bufsize, errnop);
|
||||
if (status == NS_SUCCESS)
|
||||
*(struct group **)retval = grp;
|
||||
return (__nss_compat_result(status));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
__nss_compat_getgrent_r(void *retval, void *mdata, va_list ap)
|
||||
{
|
||||
int (*fn)(struct group *, char *, size_t, int *);
|
||||
struct group *grp;
|
||||
char *buffer;
|
||||
int *errnop;
|
||||
size_t bufsize;
|
||||
enum nss_status status;
|
||||
|
||||
if (CHECK_TERMINATOR(group))
|
||||
return (NS_NOTFOUND);
|
||||
fn = mdata;
|
||||
grp = va_arg(ap, struct group *);
|
||||
buffer = va_arg(ap, char *);
|
||||
bufsize = va_arg(ap, size_t);
|
||||
errnop = va_arg(ap, int *);
|
||||
status = fn(grp, buffer, bufsize, errnop);
|
||||
if (status == NS_SUCCESS)
|
||||
*(struct group **)retval = grp;
|
||||
else
|
||||
SET_TERMINATOR(group, &terminator);
|
||||
return (__nss_compat_result(status));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
__nss_compat_setgrent(void *retval, void *mdata, va_list ap)
|
||||
{
|
||||
|
||||
SET_TERMINATOR(group, NULL);
|
||||
((int (*)(void))mdata)();
|
||||
return (NS_UNAVAIL);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
__nss_compat_endgrent(void *retval, void *mdata, va_list ap)
|
||||
{
|
||||
|
||||
SET_TERMINATOR(group, NULL);
|
||||
((int (*)(void))mdata)();
|
||||
return (NS_UNAVAIL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
DECLARE_TERMINATOR(passwd);
|
||||
|
||||
|
||||
int
|
||||
__nss_compat_getpwnam_r(void *retval, void *mdata, va_list ap)
|
||||
{
|
||||
int (*fn)(const char *, struct passwd *, char *, size_t, int *);
|
||||
const char *name;
|
||||
struct passwd *pwd;
|
||||
char *buffer;
|
||||
int *errnop;
|
||||
size_t bufsize;
|
||||
enum nss_status status;
|
||||
|
||||
fn = mdata;
|
||||
name = va_arg(ap, const char *);
|
||||
pwd = va_arg(ap, struct passwd *);
|
||||
buffer = va_arg(ap, char *);
|
||||
bufsize = va_arg(ap, size_t);
|
||||
errnop = va_arg(ap, int *);
|
||||
status = fn(name, pwd, buffer, bufsize, errnop);
|
||||
if (status == NS_SUCCESS)
|
||||
*(struct passwd **)retval = pwd;
|
||||
return (__nss_compat_result(status));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
__nss_compat_getpwuid_r(void *retval, void *mdata, va_list ap)
|
||||
{
|
||||
int (*fn)(uid_t, struct passwd *, char *, size_t, int *);
|
||||
uid_t uid;
|
||||
struct passwd *pwd;
|
||||
char *buffer;
|
||||
int *errnop;
|
||||
size_t bufsize;
|
||||
enum nss_status status;
|
||||
|
||||
fn = mdata;
|
||||
uid = va_arg(ap, uid_t);
|
||||
pwd = va_arg(ap, struct passwd *);
|
||||
buffer = va_arg(ap, char *);
|
||||
bufsize = va_arg(ap, size_t);
|
||||
errnop = va_arg(ap, int *);
|
||||
status = fn(uid, pwd, buffer, bufsize, errnop);
|
||||
if (status == NS_SUCCESS)
|
||||
*(struct passwd **)retval = pwd;
|
||||
return (__nss_compat_result(status));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
__nss_compat_getpwent_r(void *retval, void *mdata, va_list ap)
|
||||
{
|
||||
int (*fn)(struct passwd *, char *, size_t, int *);
|
||||
struct passwd *pwd;
|
||||
char *buffer;
|
||||
int *errnop;
|
||||
size_t bufsize;
|
||||
enum nss_status status;
|
||||
|
||||
if (CHECK_TERMINATOR(passwd))
|
||||
return (NS_NOTFOUND);
|
||||
fn = mdata;
|
||||
pwd = va_arg(ap, struct passwd *);
|
||||
buffer = va_arg(ap, char *);
|
||||
bufsize = va_arg(ap, size_t);
|
||||
errnop = va_arg(ap, int *);
|
||||
status = fn(pwd, buffer, bufsize, errnop);
|
||||
if (status == NS_SUCCESS)
|
||||
*(struct passwd **)retval = pwd;
|
||||
else
|
||||
SET_TERMINATOR(passwd, &terminator);
|
||||
return (__nss_compat_result(status));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
__nss_compat_setpwent(void *retval, void *mdata, va_list ap)
|
||||
{
|
||||
|
||||
SET_TERMINATOR(passwd, NULL);
|
||||
((int (*)(void))mdata)();
|
||||
return (NS_UNAVAIL);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
__nss_compat_endpwent(void *retval, void *mdata, va_list ap)
|
||||
{
|
||||
|
||||
SET_TERMINATOR(passwd, NULL);
|
||||
((int (*)(void))mdata)();
|
||||
return (NS_UNAVAIL);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user