Skip to content

Commit

Permalink
rewrite nss_mcdb* based on prototypes in The GNU C Library documentation
Browse files Browse the repository at this point in the history
"Internals of the NSS Module Functions"
(note that GNU NSS is not compatible with Solaris NSS)
  • Loading branch information
gstrauss committed May 31, 2010
1 parent 244897a commit ecf7731
Show file tree
Hide file tree
Showing 6 changed files with 252 additions and 261 deletions.
10 changes: 8 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@

.PHONY: all other_objects
all: mcdbctl testzero nss libmcdb.a
all: mcdbctl testzero nss libmcdb.a libnss_mcdb.so.2

CC=gcc
CFLAGS+=-pipe -Wall -Winline -pedantic -ansi -std=c99 -D_THREAD_SAFE -O3 -g -I.
CFLAGS+=-pipe -Wall -Winline -pedantic -ansi -std=c99 -D_THREAD_SAFE \
-fpic -O3 -g -I.

# heavy handed dependencies
_DEPENDENCIES_ON_ALL_HEADERS_Makefile:= $(wildcard *.h) Makefile
Expand All @@ -14,6 +15,11 @@ _DEPENDENCIES_ON_ALL_HEADERS_Makefile:= $(wildcard *.h) Makefile
libmcdb.a: mcdb.o mcdb_error.o mcdb_make.o mcdb_makefmt.o nointr.o uint32.o
$(AR) -r $@ $^

# (nointr.o, uint32.o need not be included when fully inlined; adds 10K to .so)
libnss_mcdb.so.2: mcdb.o \
nss_mcdb.o nss_mcdb_acct.o nss_mcdb_misc.o nss_mcdb_netdb.o
$(CC) -shared -fpic -Wl,-soname,$(@F) -o $@ $^

mcdbctl: mcdbctl.o libmcdb.a
$(CC) -o $@ $(CFLAGS) $^
testzero: testzero.o libmcdb.a
Expand Down
36 changes: 20 additions & 16 deletions nss_mcdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,11 @@
/*
* man nsswitch.conf
* /etc/nsswitch.conf
* /lib/libnss_XXXXX.so, e.g. /lib/libnss_files.so
* /lib/libnss_XXXXX.so.2, e.g. /lib/libnss_files.so.2
* rpm -qil nss_db nss_ldap
* The GNU C Library (manual)
* http://www.delorie.com/gnu/docs/glibc/libc_602.html
* 28.4.2 Internals of the NSS Module Functions
*/

/* compile-time setting for security */
Expand Down Expand Up @@ -118,6 +121,7 @@ _nss_mcdb_db_openshared(const enum nss_dbtype dbtype)
if (dfd != -1) /* caller must have open STDIN, STDOUT, STDERR */
(void) nointr_close(dfd);
pthread_mutex_unlock(&_nss_mcdb_global_mutex);
errno = EBADF;
return false;
}
}
Expand All @@ -127,6 +131,7 @@ _nss_mcdb_db_openshared(const enum nss_dbtype dbtype)
if (snprintf(map->fname, sizeof(map->fname), "%s%s",
NSS_DBPATH, _nss_dbnames[dbtype]) >= sizeof(map->fname)) {
pthread_mutex_unlock(&_nss_mcdb_global_mutex);
errno = ENAMETOOLONG;
return false;
}
#endif
Expand Down Expand Up @@ -210,7 +215,7 @@ _nss_mcdb_endent(const enum nss_dbtype dbtype)
MCDB_REGISTER_DONE | MCDB_REGISTER_MUNMAP_SKIP;
return (m->map == NULL || _nss_mcdb_db_relshared(m->map, mcdb_flags))
? NSS_STATUS_SUCCESS
: NSS_STATUS_TRYAGAIN; /* (fails only if obtaining mutex fails) */
: NSS_STATUS_RETURN; /* (fails only if obtaining mutex fails) */
}

/* mcdb get*ent() walks db returning successive keys with '=' tag char */
Expand All @@ -223,8 +228,10 @@ _nss_mcdb_getent(const enum nss_dbtype dbtype,
uint32_t eod;
uint32_t klen;
if (__builtin_expect(m->map == NULL, false)
&& _nss_mcdb_setent(dbtype) != NSS_STATUS_SUCCESS)
&& _nss_mcdb_setent(dbtype) != NSS_STATUS_SUCCESS) {
*vinfo->errnop = errno;
return NSS_STATUS_UNAVAIL;
}
map = m->map->ptr;
eod = uint32_strunpack_bigendian_aligned_macro(map) - 7;
while (m->hpos < eod) {
Expand All @@ -236,6 +243,7 @@ _nss_mcdb_getent(const enum nss_dbtype dbtype,
/* valid data in mcdb_datapos() mcdb_datalen() mcdb_dataptr() */
return vinfo->decode(m, NULL, vinfo);
}
*vinfo->errnop = errno = ENOENT;
return NSS_STATUS_NOTFOUND;
}

Expand All @@ -254,8 +262,10 @@ _nss_mcdb_get_generic(const enum nss_dbtype dbtype,
* grab/release mutex to register, then grab/release mutex to unregister */

m.map = _nss_mcdb_db_getshared(dbtype, mcdb_flags_lock);
if (__builtin_expect(m.map == NULL, false))
if (__builtin_expect(m.map == NULL, false)) {
*vinfo->errnop = errno;
return NSS_STATUS_UNAVAIL;
}

if ( mcdb_findtagstart(&m, kinfo->key, kinfo->klen, kinfo->tagc)
&& mcdb_findtagnext(&m, kinfo->key, kinfo->klen, kinfo->tagc) )
Expand Down Expand Up @@ -285,6 +295,7 @@ _nss_mcdb_decode_buf(struct mcdb * const restrict m,
vinfo->buf[dlen] = '\0';
return NSS_STATUS_SUCCESS;
}
*vinfo->errnop = errno = ERANGE;
return NSS_STATUS_TRYAGAIN;
}

Expand All @@ -303,21 +314,14 @@ TODO: split each set of nss database access routines into a separate .c file
/* GPS: verify what nss passes in and what it wants as exit values
* It probably always wants enum nss_status
*
* If gethost* buffer sizes are not large enough, man page says return ERANGE ?
* in errno? not in enum nss_status ? Return NSS_STATUS_TRYAGAIN?
* If gethost* buffer sizes are not large enough:
* Set errno = ERANGE; return NSS_STATUS_TRYAGAIN;
*/

_nss_files_parse_etherent
_nss_files_parse_grent@@GLIBC_PRIVATE
_nss_files_parse_netent
_nss_files_parse_protoent
_nss_files_parse_pwent@@GLIBC_PRIVATE
_nss_files_parse_rpcent
_nss_files_parse_servent
_nss_files_parse_spent@@GLIBC_PRIVATE
_nss_netgroup_parseline

GPS: how about a mcdb for /etc/nsswitch.conf ?
(would need to modify glibc to support it)
(see if glibc can be modified to use mmap and not do extra read() calls)
(check latest versions before working on patch)
GPS: where does nscd socket get plugged in to all this?
and should I add something to nscd.conf to implicitly use mcdb
before its cache?
Expand Down
2 changes: 1 addition & 1 deletion nss_mcdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ struct _nss_vinfo {
void * restrict vstruct;
char * restrict buf;
size_t buflen;
void * vstructp;
int * errnop;
};


Expand Down
106 changes: 46 additions & 60 deletions nss_mcdb_acct.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,33 +39,32 @@ _nss_mcdb_decode_spwd(struct mcdb * restrict,
__attribute_nonnull_x__((1,3)) __attribute_warn_unused_result__;


void _nss_files_setpwent(void) { _nss_mcdb_setent(NSS_DBTYPE_PASSWD); }
void _nss_files_endpwent(void) { _nss_mcdb_endent(NSS_DBTYPE_PASSWD); }
void _nss_files_setgrent(void) { _nss_mcdb_setent(NSS_DBTYPE_GROUP); }
void _nss_files_endgrent(void) { _nss_mcdb_endent(NSS_DBTYPE_GROUP); }
void _nss_files_setspent(void) { _nss_mcdb_setent(NSS_DBTYPE_SHADOW); }
void _nss_files_endspent(void) { _nss_mcdb_endent(NSS_DBTYPE_SHADOW); }
void _nss_mcdb_setpwent(void) { _nss_mcdb_setent(NSS_DBTYPE_PASSWD); }
void _nss_mcdb_endpwent(void) { _nss_mcdb_endent(NSS_DBTYPE_PASSWD); }
void _nss_mcdb_setgrent(void) { _nss_mcdb_setent(NSS_DBTYPE_GROUP); }
void _nss_mcdb_endgrent(void) { _nss_mcdb_endent(NSS_DBTYPE_GROUP); }
void _nss_mcdb_setspent(void) { _nss_mcdb_setent(NSS_DBTYPE_SHADOW); }
void _nss_mcdb_endspent(void) { _nss_mcdb_endent(NSS_DBTYPE_SHADOW); }


enum nss_status
_nss_files_getpwent_r(struct passwd * const restrict pwbuf,
char * const restrict buf, const size_t buflen,
struct passwd ** const restrict pwbufp)
_nss_mcdb_getpwent_r(struct passwd * const restrict pwbuf,
char * const restrict buf, const size_t buflen,
int * const restrict errnop)
{
const struct _nss_vinfo vinfo = { .decode = _nss_mcdb_decode_passwd,
.vstruct = pwbuf,
.buf = buf,
.buflen = buflen,
.vstructp= pwbufp };
*pwbufp = NULL;
.errnop = errnop };
return _nss_mcdb_getent(NSS_DBTYPE_PASSWD, &vinfo);
}

enum nss_status
_nss_files_getpwnam_r(const char * const restrict name,
struct passwd * const restrict pwbuf,
char * const restrict buf, const size_t buflen,
struct passwd ** const restrict pwbufp)
_nss_mcdb_getpwnam_r(const char * const restrict name,
struct passwd * const restrict pwbuf,
char * const restrict buf, const size_t buflen,
int * const restrict errnop)
{
const struct _nss_kinfo kinfo = { .key = name,
.klen = strlen(name),
Expand All @@ -74,16 +73,15 @@ _nss_files_getpwnam_r(const char * const restrict name,
.vstruct = pwbuf,
.buf = buf,
.buflen = buflen,
.vstructp= pwbufp };
*pwbufp = NULL;
.errnop = errnop };
return _nss_mcdb_get_generic(NSS_DBTYPE_PASSWD, &kinfo, &vinfo);
}

enum nss_status
_nss_files_getpwuid_r(const uid_t uid,
struct passwd * const restrict pwbuf,
char * const restrict buf, const size_t buflen,
struct passwd ** const restrict pwbufp)
_nss_mcdb_getpwuid_r(const uid_t uid,
struct passwd * const restrict pwbuf,
char * const restrict buf, const size_t buflen,
int * const restrict errnop)
{
char hexstr[8];
const struct _nss_kinfo kinfo = { .key = hexstr,
Expand All @@ -93,32 +91,30 @@ _nss_files_getpwuid_r(const uid_t uid,
.vstruct = pwbuf,
.buf = buf,
.buflen = buflen,
.vstructp= pwbufp };
*pwbufp = NULL;
.errnop = errnop };
uint32_to_ascii8uphex((uint32_t)uid, hexstr);
return _nss_mcdb_get_generic(NSS_DBTYPE_PASSWD, &kinfo, &vinfo);
}


enum nss_status
_nss_files_getgrent_r(struct group * const restrict grbuf,
char * const restrict buf, const size_t buflen,
struct group ** const restrict grbufp)
_nss_mcdb_getgrent_r(struct group * const restrict grbuf,
char * const restrict buf, const size_t buflen,
int * const restrict errnop)
{
const struct _nss_vinfo vinfo = { .decode = _nss_mcdb_decode_group,
.vstruct = grbuf,
.buf = buf,
.buflen = buflen,
.vstructp= grbufp };
*grbufp = NULL;
.errnop = errnop };
return _nss_mcdb_getent(NSS_DBTYPE_GROUP, &vinfo);
}

enum nss_status
_nss_files_getgrnam_r(const char * const restrict name,
struct group * const restrict grbuf,
char * const restrict buf, const size_t buflen,
struct group ** const restrict grbufp)
_nss_mcdb_getgrnam_r(const char * const restrict name,
struct group * const restrict grbuf,
char * const restrict buf, const size_t buflen,
int * const restrict errnop)
{
const struct _nss_kinfo kinfo = { .key = name,
.klen = strlen(name),
Expand All @@ -127,16 +123,15 @@ _nss_files_getgrnam_r(const char * const restrict name,
.vstruct = grbuf,
.buf = buf,
.buflen = buflen,
.vstructp= grbufp };
*grbufp = NULL;
.errnop = errnop };
return _nss_mcdb_get_generic(NSS_DBTYPE_GROUP, &kinfo, &vinfo);
}

enum nss_status
_nss_files_getgrgid_r(const gid_t gid,
struct group * const restrict grbuf,
char * const restrict buf, const size_t buflen,
struct group ** const restrict grbufp)
_nss_mcdb_getgrgid_r(const gid_t gid,
struct group * const restrict grbuf,
char * const restrict buf, const size_t buflen,
int * const restrict errnop)
{
char hexstr[8];
const struct _nss_kinfo kinfo = { .key = hexstr,
Expand All @@ -146,32 +141,30 @@ _nss_files_getgrgid_r(const gid_t gid,
.vstruct = grbuf,
.buf = buf,
.buflen = buflen,
.vstructp= grbufp };
*grbufp = NULL;
.errnop = errnop };
uint32_to_ascii8uphex((uint32_t)gid, hexstr);
return _nss_mcdb_get_generic(NSS_DBTYPE_GROUP, &kinfo, &vinfo);
}


enum nss_status
_nss_files_getspent_r(struct spwd * const restrict spbuf,
char * const restrict buf, const size_t buflen,
struct spwd ** const restrict spbufp)
_nss_mcdb_getspent_r(struct spwd * const restrict spbuf,
char * const restrict buf, const size_t buflen,
int * const restrict errnop)
{
const struct _nss_vinfo vinfo = { .decode = _nss_mcdb_decode_spwd,
.vstruct = spbuf,
.buf = buf,
.buflen = buflen,
.vstructp= spbufp };
*spbufp = NULL;
.errnop = errnop };
return _nss_mcdb_getent(NSS_DBTYPE_SHADOW, &vinfo);
}

enum nss_status
_nss_files_getspnam_r(const char * const restrict name,
struct spwd * const restrict spbuf,
char * const restrict buf, const size_t buflen,
struct spwd ** const restrict spbufp)
_nss_mcdb_getspnam_r(const char * const restrict name,
struct spwd * const restrict spbuf,
char * const restrict buf, const size_t buflen,
int * const restrict errnop)
{
const struct _nss_kinfo kinfo = { .key = name,
.klen = strlen(name),
Expand All @@ -180,8 +173,7 @@ _nss_files_getspnam_r(const char * const restrict name,
.vstruct = spbuf,
.buf = buf,
.buflen = buflen,
.vstructp= spbufp };
*spbufp = NULL;
.errnop = errnop };
return _nss_mcdb_get_generic(NSS_DBTYPE_SHADOW, &kinfo, &vinfo);
}

Expand Down Expand Up @@ -216,7 +208,6 @@ _nss_mcdb_decode_passwd(struct mcdb * const restrict m,
pw->pw_dir = buf+idx_pw_dir;
pw->pw_shell = buf+idx_pw_shell;
if (dlen < vinfo->buflen) {
*((struct passwd **)vinfo->vstructp) = pw;
memcpy(buf, dptr+IDX_PW_HDRSZ, dlen);
/* terminate strings; replace ':' separator in data with '\0' */
buf[idx_pw_passwd-1] = '\0'; /* terminate pw_name */
Expand All @@ -227,8 +218,7 @@ _nss_mcdb_decode_passwd(struct mcdb * const restrict m,
return NSS_STATUS_SUCCESS;
}
else {
*((struct passwd **)vinfo->vstructp) = NULL;
errno = ERANGE;
*vinfo->errnop = errno = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
}
Expand Down Expand Up @@ -260,7 +250,6 @@ _nss_mcdb_decode_group(struct mcdb * const restrict m,
* more space and might take just as long to parse as scan for ','
* (assume data consistent, gr_mem_num correct) */
if (((char *)gr_mem)-buf+((gr_mem_num+1)<<3) <= vinfo->buflen) {
*((struct group **)vinfo->vstructp) = gr;
memcpy(buf, dptr+IDX_GR_HDRSZ, mcdb_datalen(m)-IDX_GR_HDRSZ);
/* terminate strings; replace ':' separator in data with '\0'. */
buf[idx_gr_passwd-1] = '\0'; /* terminate gr_name */
Expand All @@ -277,8 +266,7 @@ _nss_mcdb_decode_group(struct mcdb * const restrict m,
return NSS_STATUS_SUCCESS;
}
else {
*((struct group **)vinfo->vstructp) = NULL;
errno = ERANGE;
*vinfo->errnop = errno = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
}
Expand Down Expand Up @@ -306,16 +294,14 @@ _nss_mcdb_decode_spwd(struct mcdb * const restrict m,
sp->sp_namp = buf;
sp->sp_pwdp = buf+idx_sp_pwdp;
if (dlen < vinfo->buflen) {
*((struct spwd **)vinfo->vstructp) = sp;
memcpy(buf, dptr+IDX_SP_HDRSZ, dlen);
/* terminate strings; replace ':' separator in data with '\0' */
buf[idx_sp_pwdp-1] = '\0'; /* terminate sp_namp */
buf[dlen] = '\0'; /* terminate sp_pwdp */
return NSS_STATUS_SUCCESS;
}
else {
*((struct spwd **)vinfo->vstructp) = NULL;
errno = ERANGE;
*vinfo->errnop = errno = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
}
Loading

0 comments on commit ecf7731

Please sign in to comment.