/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#include "lint.h"
#include <mtlib.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <nss_dbdefs.h>
#include <limits.h>
#include <dlfcn.h>
#include <link.h>
#include <thread.h>
#include <atomic.h>
#include <sys/ethernet.h>
#include <exec_attr.h>
#include <grp.h>
/*
* functions in nss_dbdefs.c deal more with the mechanics of
* the data structures like nss_XbyY_args_t and the interaction
* with the packed buffers etc. versus the mechanics of the
* actual policy component operations such as nss_search sequencing.
*/
/*
* ALIGN? is there an official definition of this?
* We use sizeof(long) to cover what we want
* for both the 32-bit world and 64-bit world.
*/
{
nss_XbyY_buf_t *b;
/* Use one malloc for dbargs, result struct and buffer */
b = (nss_XbyY_buf_t *)
if (b == 0) {
return (0);
}
b->buflen = buffer_size;
return (b);
}
void
{
if (b != 0) {
free(b);
}
}
/* === Comment: used by fget{gr,pw,sp}ent */
/* ==== Should do ye olde syslog()ing of suspiciously long lines */
void
{
/* Allocate initial input buffer */
b->returnval = 0;
b->erange = 1;
return;
}
buf_offset = buffer;
len = 0;
/* Loop reading input until newline or end-of-file */
/* Break on newline or end-of-file */
break;
}
/* Allocate larger buffer to continue input */
if (new_buffer == NULL) {
b->returnval = 0;
b->erange = 1;
return;
}
buffer = new_buffer;
}
/* Check for end-of-file */
if (!len) {
b->returnval = 0;
b->erange = 0;
return;
}
/*
* The input line parser uses the length of valid characters
* to copy the buffer, appending a null terminator to the copy.
* Use this to remove any trailing newlines.
*/
len--;
}
/* Call the input line parser */
if (parsestat == NSS_STR_PARSE_ERANGE) {
b->returnval = 0;
b->erange = 1;
} else if (parsestat == NSS_STR_PARSE_SUCCESS) {
}
/* Release the input buffer */
}
/*
* parse the aliases string into the buffer and if successful return
* a char ** pointer to the beginning of the aliases.
*
* CAUTION: (instr, instr+lenstr) and (buffer, buffer+buflen) are
* non-intersecting memory areas. Since this is an internal interface,
* we should be able to live with that.
*/
char **
/* "instr" is the beginning of the aliases string */
/* "buffer" has the return val for success */
/* "buflen" is the length of the buffer available for aliases */
{
/*
* Build the alias-list in the start of the buffer, and copy
* the strings to the end of the buffer.
*/
const char
int nstrings = 0;
for (;;) {
const char *str_start;
instr++;
}
break;
}
instr++;
}
++nstrings;
/* Has to be room for the pointer to */
/* the alias we're about to add, */
/* as well as the final NULL ptr. */
return (0);
}
}
*aliasp++ = 0;
return (alias_start);
}
/*
* pack well known getXbyY keys to packed buffer prior to the door_call
* to nscd. Some consideration is given to ordering the tests based on
* usage. Note: buf is nssuint_t aligned.
*/
typedef struct {
#define NSS_MK_GETXYDBOP(x, y, f, e) \
#define NSS_MK_GETXYDBOPA(x, a, f, e) \
#define NSS_MK_GETXYDBOPB(x, b, a, f, s, e) \
#define NSS_MK_GETXYDBOPC(x, a, f, s, e) \
#define NSS_MK_GETXYDBOPD(x, y, i, f, e) \
#define NSS_MK_GETXYDBOPCSTR(x, a, f, s, e) \
/*
* The getXbyY_to_dbop structure is hashed on first call in order to
* reduce the search time for the well known getXbyY operations.
* A binary search was not fast enough. There were on average
* 3-4 tests (strcmps) per getXbyY call.
*
* DBOP_PRIME_HASH must be a prime number (reasonably small) but that
* is sufficient to uniquely map the entries in the following table
* without collision.
*
* The DBOP_PRIME_HASH was selected as the smallest hash value
* for this table without collisions. Changing this table WILL
* necessitate re-testing for possible collisions.
*/
static int getXbyYdbop_hashed = 0;
/*
* If the size of getXbyY_to_dbop[] is changed then hash function must be
* corrected to be without collisions in nss_dbop_search().
*/
/* NSS_MK_GETXYDBOP(ALIASES, ?, ?), */
/* NSS_MK_GETXYDBOP(AUTOMOUNT, ?, ?), */
"str2spwd", "n"),
};
static int
{
const char *cp;
int i, idx;
/* Uses a table size is known to have no collisions */
if (getXbyYdbop_hashed == 0) {
if (getXbyYdbop_hashed == 0) {
for (i = 0; i < count; i++) {
hval = 0;
while (*cp) {
hval ^= g >> 24;
hval &= ~g;
}
hval %= DBOP_PRIME_HASH;
if (getXbyYdbopHASH[hval] != 0) {
/* hash table collision-see above */
return (-1);
}
}
getXbyYdbop_hashed = 1;
}
}
hval = 0;
while (*cp) {
hval ^= g >> 24;
hval &= ~g;
}
hval %= DBOP_PRIME_HASH;
return (-1);
idx &= ~DBOP_HASH_TAG;
return (-1);
return (-1);
return (idx);
}
/*
* nss_pack_key2str
* Private key to string packing function for getXbyY routines
* This routine performs a printf like parse over the argument
* key, given a string of items to pack and assembles the key in
* the packed structure. This routine is called (currently) by
* nss_default_key2str, but will be used by other external
* APIs in the future.
*
* buffer - Start of the key buffer location [in packed buffer]
* length - Length of key buffer component
* Key offsets are relative to start of key buffer location.
*
* Pack fields Key
* key.name n
* key.number N
* key.uid u
* key.gid g
* key.hostaddr h
* key.ipnode i
* key.projid p
* key.serv(name) s
* key.serv(port) S
* key.ether e
* key.pkey k
* key.netaddr a
* key.attrp A
* groupsbymember I
* innetgr_args t
* setnetgr_args T
*/
/*ARGSUSED*/
static nss_status_t
{
int i, j;
return (NSS_ERROR);
switch (*typestr++) {
case 'n':
return (NSS_NOTFOUND);
return (NSS_ERROR);
break;
case 'N':
return (NSS_ERROR);
break;
case 'u':
return (NSS_ERROR);
break;
case 'g':
return (NSS_ERROR);
break;
case 'h':
return (-1);
return (NSS_ERROR);
break;
case 'i':
return (NSS_NOTFOUND);
return (NSS_ERROR);
break;
case 'p':
return (NSS_ERROR);
break;
case 's':
return (NSS_NOTFOUND);
len2 = 1;
return (NSS_ERROR);
if (len2 > 1)
len2);
else
*(char *)buffer = '\0';
break;
case 'S':
len2 = 0;
return (NSS_ERROR);
if (len2) {
}
break;
case 'e':
return (NSS_NOTFOUND);
len = sizeof (struct ether_addr);
return (NSS_ERROR);
*(struct ether_addr *)buffer =
break;
case 'k':
return (NSS_NOTFOUND);
return (NSS_ERROR);
break;
case 'a':
return (NSS_ERROR);
break;
case 'A':
return (NSS_NOTFOUND);
/* for search flag */
/* for sizeof (_priv_execattr) static buffer */
/* Plus lots of slop just in case... */
/* head_exec, prev_exec - are client side only... */
return (NSS_ERROR);
if (len2 == 1)
*dptr++ = '\0';
else {
}
if (len3 == 1)
*dptr++ = '\0';
else {
}
if (len4 == 1)
*dptr++ = '\0';
else {
}
if (len5 == 1)
*dptr++ = '\0';
else
break;
case 'I':
return (NSS_NOTFOUND);
return (NSS_ERROR);
} else {
}
break;
case 't':
len = sizeof (nss_pnetgr_t);
len3 = 0;
for (j = 0; j < NSS_NETGR_N; j++) {
if (*cv)
}
}
if (*cv)
}
/*
* Double argv space. Reason:
* First 1/2 offsets
* Second 1/2 for client side pointer arrays
*/
return (NSS_ERROR);
if (pptr->machine_argc == 0) {
} else {
i = pptr->machine_argc;
for (; --i >= 0; ) {
}
}
} else {
for (; --i >= 0; ) {
}
}
if (pptr->domain_argc == 0) {
} else {
i = pptr->domain_argc;
for (; --i >= 0; ) {
}
}
if (pptr->groups_argc == 0) {
} else {
i = pptr->groups_argc;
for (; --i >= 0; ) {
}
}
break;
case 'T':
return (NSS_NOTFOUND);
return (NSS_ERROR);
break;
default:
return (NSS_ERROR);
}
}
return (NSS_SUCCESS);
}
{
int index;
return (NSS_ERROR);
/*
* If this is not one of the well known getXbyYs
* (IE _printers special processing etc.) use a
* local (non-nscd) getXbyY lookup.
*/
return (NSS_TRYLOCAL);
}
/*ARGSUSED*/
void
{
char *dbn;
/* sidestep odd cases */
(struct nss_groupsbymem *)arg;
sizeof (gid_t);
} else {
}
return;
}
}
(struct nss_innetgr_args *)arg;
/* tell nss_unpack() operation is successful */
return;
}
} else {
}
return;
}
}
/* process normal cases */
else
} else
} else {
}
}
/*
* nss_upack_key2arg
* Private string to key unpacking function for getXbyY routines
* string, to uppack and re-assemble the key in the args structure.
*
* buffer - Start of the key buffer location [in packed buffer]
* length - Length of key buffer component
* Key offsets are relative to start of key buffer location.
*
* Unpack fields Key
* key.name n
* key.number N
* key.uid u
* key.gid g
* key.hostaddr h
* key.ipnode i
* key.projid p
* key.serv(name) s
* key.serv(port) S
* key.ether e
* key.pkey k
* key.netaddr a
* key.attrp A
* groupsbymember I
* innetgr_args t
* setnetgr_args T
* Assumes arguments are all valid
*/
/*ARGSUSED*/
static nss_status_t
{
int i, j;
/* keysize is length of the key area */
return (NSS_ERROR);
while (*strtype) {
switch (*strtype++) {
case 'n':
break;
case 'N':
break;
case 'u':
break;
case 'g':
break;
case 'h':
break;
case 'i':
break;
case 'p':
break;
case 's':
if (*(const char *)bptr == '\0')
else
break;
case 'S':
} else {
}
break;
case 'e':
break;
case 'k':
break;
case 'a':
break;
case 'A':
/* use slop space as priv_execattr structure */
/* skip over slop ... */
if (*bptr == '\0') {
bptr++;
} else {
}
if (*bptr == '\0') {
bptr++;
} else {
}
if (*bptr == '\0') {
bptr++;
} else {
}
if (*bptr == '\0') {
} else {
}
break;
case 'I':
/* insert initial group into data area */
} else
uptr++;
break;
case 't':
/*
* Start of argv pointer storage
*/
off += sizeof (nss_pnetgr_t);
((void *)(bptr + sizeof (nss_pnetgr_t)));
for (j = 0; j < NSS_NETGR_N; j++) {
return (NSS_ERROR);
}
}
return (NSS_ERROR);
}
break;
case 'T':
break;
default:
return (NSS_ERROR);
}
}
return (NSS_SUCCESS);
}
static nss_status_t
{
const char *name;
void *sym;
return (NSS_ERROR);
} else {
}
}
if (htmp)
}
if (initf) {
return (NSS_ERROR);
}
}
if (s2e) {
return (NSS_ERROR);
}
}
return (NSS_SUCCESS);
}
{
int index;
return (NSS_ERROR);
return (NSS_ERROR);
return (NSS_ERROR);
}
/*
* str2packent: Standard format interposed str2X function for normal APIs
*
* Return values: 0 = success, 1 = parse error, 2 = erange ...
*
* The structure pointer is ignored since this is a nscd side packed request.
* The client side routine does all the real parsing; we just check limits and
* store the entry in the buffer we were passed by the caller.
*/
/*ARGSUSED*/
int
const char *instr,
int lenstr,
void *ent, /* really (char *) */
char *buffer,
int buflen
)
{
return (NSS_STR_PARSE_ERANGE);
}
return (NSS_STR_PARSE_SUCCESS);
}
/*
* Initialize db_root, initf, dbop and arg from a packed buffer
*/
/*ARGSUSED*/
{
int index;
return (NSS_ERROR);
/* init dbop */
return (NSS_ERROR);
return (NSS_ERROR);
/* db_root is initialized by nscd's based on door info */
/* do nothing here */
/* init key information - (and get dbname dbop etc...) */
return (NSS_ERROR);
/* possible audituser init */
/* sidestep odd arg cases */
if (*dbop == NSS_DBOP_GROUP_BYMEMBER &&
/* get initf and str2ent functions */
return (NSS_ERROR);
return (NSS_SUCCESS);
}
return (NSS_SUCCESS);
}
/* get initf and str2ent functions */
return (NSS_ERROR);
/* init normal arg cases */
return (NSS_SUCCESS);
}
/*
* Initialize db_root, initf, dbop, contextp and arg from a packed buffer
*/
/*ARGSUSED*/
{
char *bptr;
/* init arg */
}
return (NSS_SUCCESS);
}