10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
52830Sdjl * Common Development and Distribution License (the "License").
62830Sdjl * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
213864Sraf
220Sstevel@tonic-gate /*
238765SMilan.Jurik@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
276812Sraf #include "lint.h"
282830Sdjl #include <mtlib.h>
290Sstevel@tonic-gate #include <ctype.h>
300Sstevel@tonic-gate #include <stdio.h>
310Sstevel@tonic-gate #include <stdlib.h>
320Sstevel@tonic-gate #include <string.h>
330Sstevel@tonic-gate #include <nss_dbdefs.h>
340Sstevel@tonic-gate #include <limits.h>
352830Sdjl #include <dlfcn.h>
362830Sdjl #include <link.h>
372830Sdjl #include <thread.h>
383864Sraf #include <atomic.h>
392830Sdjl /* headers for key2str/str2key routines */
402830Sdjl #include <sys/ethernet.h>
412830Sdjl #include <exec_attr.h>
422830Sdjl #include <grp.h>
432830Sdjl
442830Sdjl /*
452830Sdjl * functions in nss_dbdefs.c deal more with the mechanics of
462830Sdjl * the data structures like nss_XbyY_args_t and the interaction
472830Sdjl * with the packed buffers etc. versus the mechanics of the
482830Sdjl * actual policy component operations such as nss_search sequencing.
492830Sdjl */
500Sstevel@tonic-gate
510Sstevel@tonic-gate /*
520Sstevel@tonic-gate * ALIGN? is there an official definition of this?
530Sstevel@tonic-gate * We use sizeof(long) to cover what we want
540Sstevel@tonic-gate * for both the 32-bit world and 64-bit world.
550Sstevel@tonic-gate */
560Sstevel@tonic-gate
570Sstevel@tonic-gate #define ALIGN(x) ((((long)(x)) + sizeof (long) - 1) & ~(sizeof (long) - 1))
580Sstevel@tonic-gate
590Sstevel@tonic-gate nss_XbyY_buf_t *
_nss_XbyY_buf_alloc(int struct_size,int buffer_size)600Sstevel@tonic-gate _nss_XbyY_buf_alloc(int struct_size, int buffer_size)
610Sstevel@tonic-gate {
620Sstevel@tonic-gate nss_XbyY_buf_t *b;
630Sstevel@tonic-gate
640Sstevel@tonic-gate /* Use one malloc for dbargs, result struct and buffer */
650Sstevel@tonic-gate b = (nss_XbyY_buf_t *)
665477Sandra malloc(ALIGN(sizeof (*b)) + struct_size + buffer_size);
670Sstevel@tonic-gate if (b == 0) {
680Sstevel@tonic-gate return (0);
690Sstevel@tonic-gate }
700Sstevel@tonic-gate b->result = (void *)ALIGN(&b[1]);
710Sstevel@tonic-gate b->buffer = (char *)(b->result) + struct_size;
720Sstevel@tonic-gate b->buflen = buffer_size;
730Sstevel@tonic-gate return (b);
740Sstevel@tonic-gate }
750Sstevel@tonic-gate
760Sstevel@tonic-gate void
_nss_XbyY_buf_free(nss_XbyY_buf_t * b)770Sstevel@tonic-gate _nss_XbyY_buf_free(nss_XbyY_buf_t *b)
780Sstevel@tonic-gate {
790Sstevel@tonic-gate if (b != 0) {
800Sstevel@tonic-gate free(b);
810Sstevel@tonic-gate }
820Sstevel@tonic-gate }
830Sstevel@tonic-gate
840Sstevel@tonic-gate /* === Comment: used by fget{gr,pw,sp}ent */
850Sstevel@tonic-gate /* ==== Should do ye olde syslog()ing of suspiciously long lines */
860Sstevel@tonic-gate
870Sstevel@tonic-gate void
_nss_XbyY_fgets(FILE * f,nss_XbyY_args_t * b)880Sstevel@tonic-gate _nss_XbyY_fgets(FILE *f, nss_XbyY_args_t *b)
890Sstevel@tonic-gate {
900Sstevel@tonic-gate char buf[LINE_MAX];
910Sstevel@tonic-gate int len, parsestat;
920Sstevel@tonic-gate
930Sstevel@tonic-gate if (fgets(buf, LINE_MAX, f) == 0) {
940Sstevel@tonic-gate /* End of file */
950Sstevel@tonic-gate b->returnval = 0;
960Sstevel@tonic-gate b->erange = 0;
970Sstevel@tonic-gate return;
980Sstevel@tonic-gate }
990Sstevel@tonic-gate len = (int)strlen(buf);
1000Sstevel@tonic-gate /* len >= 0 (otherwise we would have got EOF) */
1010Sstevel@tonic-gate if (buf[len - 1] != '\n') {
1020Sstevel@tonic-gate if ((len + 1) == LINE_MAX) {
1030Sstevel@tonic-gate /* Line too long for buffer; too bad */
1040Sstevel@tonic-gate while (fgets(buf, LINE_MAX, f) != 0 &&
1050Sstevel@tonic-gate buf[strlen(buf) - 1] != '\n') {
1060Sstevel@tonic-gate ;
1070Sstevel@tonic-gate }
1080Sstevel@tonic-gate b->returnval = 0;
1090Sstevel@tonic-gate b->erange = 1;
1100Sstevel@tonic-gate return;
1110Sstevel@tonic-gate }
1120Sstevel@tonic-gate /* case where the file is not terminated with a Newline */
1130Sstevel@tonic-gate len++;
1140Sstevel@tonic-gate }
1150Sstevel@tonic-gate parsestat = (*b->str2ent)(buf, (len - 1), b->buf.result, b->buf.buffer,
1165477Sandra b->buf.buflen);
1170Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_ERANGE) {
1180Sstevel@tonic-gate b->returnval = 0;
1190Sstevel@tonic-gate b->erange = 1;
1200Sstevel@tonic-gate } else if (parsestat == NSS_STR_PARSE_SUCCESS) {
1210Sstevel@tonic-gate b->returnval = b->buf.result;
1220Sstevel@tonic-gate }
1230Sstevel@tonic-gate }
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate /*
1260Sstevel@tonic-gate * parse the aliases string into the buffer and if successful return
1270Sstevel@tonic-gate * a char ** pointer to the beginning of the aliases.
1280Sstevel@tonic-gate *
1290Sstevel@tonic-gate * CAUTION: (instr, instr+lenstr) and (buffer, buffer+buflen) are
1300Sstevel@tonic-gate * non-intersecting memory areas. Since this is an internal interface,
1310Sstevel@tonic-gate * we should be able to live with that.
1320Sstevel@tonic-gate */
1330Sstevel@tonic-gate char **
_nss_netdb_aliases(const char * instr,int lenstr,char * buffer,int buflen)1340Sstevel@tonic-gate _nss_netdb_aliases(const char *instr, int lenstr, char *buffer, int buflen)
1350Sstevel@tonic-gate /* "instr" is the beginning of the aliases string */
1360Sstevel@tonic-gate /* "buffer" has the return val for success */
1370Sstevel@tonic-gate /* "buflen" is the length of the buffer available for aliases */
1380Sstevel@tonic-gate {
1390Sstevel@tonic-gate /*
1400Sstevel@tonic-gate * Build the alias-list in the start of the buffer, and copy
1410Sstevel@tonic-gate * the strings to the end of the buffer.
1420Sstevel@tonic-gate */
1430Sstevel@tonic-gate const char
1440Sstevel@tonic-gate *instr_limit = instr + lenstr;
1450Sstevel@tonic-gate char *copyptr = buffer + buflen;
1460Sstevel@tonic-gate char **aliasp = (char **)ROUND_UP(buffer, sizeof (*aliasp));
1470Sstevel@tonic-gate char **alias_start = aliasp;
1480Sstevel@tonic-gate int nstrings = 0;
1490Sstevel@tonic-gate
1500Sstevel@tonic-gate for (;;) {
1510Sstevel@tonic-gate const char *str_start;
1520Sstevel@tonic-gate size_t str_len;
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate while (instr < instr_limit && isspace(*instr)) {
1550Sstevel@tonic-gate instr++;
1560Sstevel@tonic-gate }
1570Sstevel@tonic-gate if (instr >= instr_limit || *instr == '#') {
1580Sstevel@tonic-gate break;
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate str_start = instr;
1610Sstevel@tonic-gate while (instr < instr_limit && !isspace(*instr)) {
1620Sstevel@tonic-gate instr++;
1630Sstevel@tonic-gate }
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate ++nstrings;
1660Sstevel@tonic-gate
1670Sstevel@tonic-gate str_len = instr - str_start;
1680Sstevel@tonic-gate copyptr -= str_len + 1;
1690Sstevel@tonic-gate if (copyptr <= (char *)(&aliasp[nstrings + 1])) {
1700Sstevel@tonic-gate /* Has to be room for the pointer to */
1710Sstevel@tonic-gate /* the alias we're about to add, */
1720Sstevel@tonic-gate /* as well as the final NULL ptr. */
1730Sstevel@tonic-gate return (0);
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate *aliasp++ = copyptr;
1760Sstevel@tonic-gate (void) memcpy(copyptr, str_start, str_len);
1770Sstevel@tonic-gate copyptr[str_len] = '\0';
1780Sstevel@tonic-gate }
1790Sstevel@tonic-gate *aliasp++ = 0;
1800Sstevel@tonic-gate return (alias_start);
1810Sstevel@tonic-gate }
1822830Sdjl
1832830Sdjl
1843099Smichen extern nss_status_t process_cstr(const char *, int, struct nss_groupsbymem *);
1853099Smichen
1862830Sdjl /*
1872830Sdjl * pack well known getXbyY keys to packed buffer prior to the door_call
1882830Sdjl * to nscd. Some consideration is given to ordering the tests based on
1892830Sdjl * usage. Note: buf is nssuint_t aligned.
1902830Sdjl */
1912830Sdjl
1922830Sdjl typedef struct {
1932830Sdjl const char *name; /* NSS_DBNAM_* */
1942830Sdjl const char *defconf; /* NSS_DEFCONF_* */
1952830Sdjl const char *initfn; /* init function name */
1962830Sdjl const char *strfn; /* str2X function name */
1972830Sdjl const char *cstrfn; /* cstr2X function name */
1984046Smichen void *initfnp; /* init function pointer */
1994046Smichen void *strfnp; /* str2X function pointer */
2002830Sdjl uint32_t dbop; /* NSS_DBOP_* */
2012830Sdjl const char *tostr; /* key2str cvt str */
2022830Sdjl } getXbyY_to_dbop_t;
2032830Sdjl
2042830Sdjl #define NSS_MK_GETXYDBOP(x, y, f, e) \
2052830Sdjl { NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, "str2" f, \
2064046Smichen NULL, NULL, NULL, NSS_DBOP_##x##_##y, (e) }
2072830Sdjl
2082830Sdjl #define NSS_MK_GETXYDBOPA(x, a, f, e) \
2092830Sdjl { NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, "str2" f, \
2104046Smichen NULL, NULL, NULL, NSS_DBOP_##a, (e) }
2112830Sdjl
2122830Sdjl #define NSS_MK_GETXYDBOPB(x, b, a, f, s, e) \
2132830Sdjl { NSS_DBNAM_##x, NSS_DEFCONF_##b, "_nss_initf_" f, s, \
2144046Smichen NULL, NULL, NULL, NSS_DBOP_##a, (e) }
2152830Sdjl
2162830Sdjl #define NSS_MK_GETXYDBOPC(x, a, f, s, e) \
2172830Sdjl { NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, s, \
2184046Smichen NULL, NULL, NULL, NSS_DBOP_##x##_##a, (e) }
2192830Sdjl
2202830Sdjl #define NSS_MK_GETXYDBOPD(x, y, i, f, e) \
2212830Sdjl { NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" i, "str2" f, \
2224046Smichen NULL, NULL, NULL, NSS_DBOP_##x##_##y, (e) }
2232830Sdjl
2242830Sdjl #define NSS_MK_GETXYDBOPCSTR(x, a, f, s, e) \
2252830Sdjl { NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, s, \
2264046Smichen "process_cstr", NULL, NULL, NSS_DBOP_##x##_##a, (e) }
2272830Sdjl
2282830Sdjl /*
2292830Sdjl * The getXbyY_to_dbop structure is hashed on first call in order to
2302830Sdjl * reduce the search time for the well known getXbyY operations.
2312830Sdjl * A binary search was not fast enough. There were on average
2322830Sdjl * 3-4 tests (strcmps) per getXbyY call.
2332830Sdjl *
2342830Sdjl * DBOP_PRIME_HASH must be a prime number (reasonably small) but that
2352830Sdjl * is sufficient to uniquely map the entries in the following table
2362830Sdjl * without collision.
2372830Sdjl *
2382830Sdjl * The DBOP_PRIME_HASH was selected as the smallest hash value
2392830Sdjl * for this table without collisions. Changing this table WILL
2402830Sdjl * necessitate re-testing for possible collisions.
2412830Sdjl */
2422830Sdjl
2438765SMilan.Jurik@Sun.COM #define DBOP_PRIME_HASH 227
2442830Sdjl #define DBOP_HASH_TAG 0xf0000000
2452830Sdjl static int getXbyYdbopHASH[DBOP_PRIME_HASH] = { 0 };
2462830Sdjl static mutex_t getXbydbop_hash_lock = DEFAULTMUTEX;
2472830Sdjl static int getXbyYdbop_hashed = 0;
2482830Sdjl
2498765SMilan.Jurik@Sun.COM /*
2508765SMilan.Jurik@Sun.COM * If the size of getXbyY_to_dbop[] is changed then hash function must be
2518765SMilan.Jurik@Sun.COM * corrected to be without collisions in nss_dbop_search().
2528765SMilan.Jurik@Sun.COM */
2532830Sdjl static getXbyY_to_dbop_t getXbyY_to_dbop[] = {
2542830Sdjl /* NSS_MK_GETXYDBOP(ALIASES, ?, ?), */
2552830Sdjl NSS_MK_GETXYDBOPD(AUDITUSER, BYNAME, "auuser", "audituser", "n"),
2562830Sdjl NSS_MK_GETXYDBOP(AUTHATTR, BYNAME, "authattr", "n"),
2572830Sdjl /* NSS_MK_GETXYDBOP(AUTOMOUNT, ?, ?), */
2582830Sdjl NSS_MK_GETXYDBOP(BOOTPARAMS, BYNAME, "bootparams", "n"),
2592830Sdjl NSS_MK_GETXYDBOPC(ETHERS, HOSTTON, "ethers", "str2ether", "n"),
2602830Sdjl NSS_MK_GETXYDBOPC(ETHERS, NTOHOST, "ethers", "str2ether", "e"),
2612830Sdjl NSS_MK_GETXYDBOP(EXECATTR, BYNAME, "execattr", "A"),
2622830Sdjl NSS_MK_GETXYDBOP(EXECATTR, BYID, "execattr", "A"),
2632830Sdjl NSS_MK_GETXYDBOP(EXECATTR, BYNAMEID, "execattr", "A"),
2642830Sdjl NSS_MK_GETXYDBOP(GROUP, BYNAME, "group", "n"),
2652830Sdjl NSS_MK_GETXYDBOP(GROUP, BYGID, "group", "g"),
2662830Sdjl NSS_MK_GETXYDBOPCSTR(GROUP, BYMEMBER, "group", "str2group", "I"),
2672830Sdjl NSS_MK_GETXYDBOPC(HOSTS, BYNAME, "hosts", "str2hostent", "n"),
2682830Sdjl NSS_MK_GETXYDBOPC(HOSTS, BYADDR, "hosts", "str2hostent", "h"),
2692830Sdjl NSS_MK_GETXYDBOPC(IPNODES, BYNAME, "ipnodes", "str2hostent", "i"),
2702830Sdjl NSS_MK_GETXYDBOPC(IPNODES, BYADDR, "ipnodes", "str2hostent", "h"),
2712830Sdjl NSS_MK_GETXYDBOP(NETGROUP, IN, "netgroup", "t"),
2722830Sdjl NSS_MK_GETXYDBOP(NETGROUP, SET, "netgroup", "T"),
2732830Sdjl NSS_MK_GETXYDBOPC(NETMASKS, BYNET, "netmasks", "str2addr", "n"),
2742830Sdjl NSS_MK_GETXYDBOPC(NETWORKS, BYNAME, "net", "str2netent", "n"),
2752830Sdjl NSS_MK_GETXYDBOPC(NETWORKS, BYADDR, "net", "str2netent", "a"),
2762830Sdjl NSS_MK_GETXYDBOP(PASSWD, BYNAME, "passwd", "n"),
2772830Sdjl NSS_MK_GETXYDBOP(PASSWD, BYUID, "passwd", "u"),
2782830Sdjl NSS_MK_GETXYDBOP(PRINTERS, BYNAME, "printers", "n"),
2792830Sdjl NSS_MK_GETXYDBOP(PROFATTR, BYNAME, "profattr", "n"),
2802830Sdjl NSS_MK_GETXYDBOP(PROJECT, BYNAME, "project", "n"),
2812830Sdjl NSS_MK_GETXYDBOP(PROJECT, BYID, "project", "p"),
2822830Sdjl NSS_MK_GETXYDBOPC(PROTOCOLS, BYNAME, "proto", "str2protoent", "n"),
2832830Sdjl NSS_MK_GETXYDBOPC(PROTOCOLS, BYNUMBER, "proto", "str2protoent", "N"),
2842830Sdjl NSS_MK_GETXYDBOPA(PUBLICKEY, KEYS_BYNAME, "publickey", "k"),
2852830Sdjl NSS_MK_GETXYDBOPC(RPC, BYNAME, "rpc", "str2rpcent", "n"),
2862830Sdjl NSS_MK_GETXYDBOPC(RPC, BYNUMBER, "rpc", "str2rpcent", "N"),
2872830Sdjl NSS_MK_GETXYDBOPC(SERVICES, BYNAME, "services", "str2servent", "s"),
2882830Sdjl NSS_MK_GETXYDBOPC(SERVICES, BYPORT, "services", "str2servent", "S"),
2892830Sdjl NSS_MK_GETXYDBOPB(SHADOW, PASSWD, PASSWD_BYNAME, "shadow",
2902830Sdjl "str2spwd", "n"),
2912830Sdjl NSS_MK_GETXYDBOPC(TSOL_RH, BYADDR, "tsol_rh", "str_to_rhstr", "h"),
2922830Sdjl NSS_MK_GETXYDBOPC(TSOL_TP, BYNAME, "tsol_tp", "str_to_tpstr", "n"),
2932830Sdjl NSS_MK_GETXYDBOPC(TSOL_ZC, BYNAME, "tsol_zc", "str_to_zcstr", "n"),
2942830Sdjl NSS_MK_GETXYDBOP(USERATTR, BYNAME, "userattr", "n"),
2952830Sdjl };
2962830Sdjl
2972830Sdjl static int
nss_dbop_search(const char * name,uint32_t dbop)2982830Sdjl nss_dbop_search(const char *name, uint32_t dbop)
2992830Sdjl {
3002830Sdjl getXbyY_to_dbop_t *hptr;
3012830Sdjl int count = (sizeof (getXbyY_to_dbop) / sizeof (getXbyY_to_dbop_t));
3022830Sdjl uint32_t hval, g;
3032830Sdjl const char *cp;
3042830Sdjl int i, idx;
3058765SMilan.Jurik@Sun.COM static const uint32_t hbits_tst = 0xf0000000;
3062830Sdjl
3072830Sdjl /* Uses a table size is known to have no collisions */
3082830Sdjl if (getXbyYdbop_hashed == 0) {
3092830Sdjl lmutex_lock(&getXbydbop_hash_lock);
3102830Sdjl if (getXbyYdbop_hashed == 0) {
3112830Sdjl for (i = 0; i < count; i++) {
3122830Sdjl cp = getXbyY_to_dbop[i].name;
3132830Sdjl hval = 0;
3142830Sdjl while (*cp) {
3152830Sdjl hval = (hval << 4) + *cp++;
3168765SMilan.Jurik@Sun.COM if ((g = (hval & hbits_tst)) != 0)
3172830Sdjl hval ^= g >> 24;
3182830Sdjl hval &= ~g;
3192830Sdjl }
3202830Sdjl hval += getXbyY_to_dbop[i].dbop;
3212830Sdjl hval %= DBOP_PRIME_HASH;
3222830Sdjl if (getXbyYdbopHASH[hval] != 0) {
3232830Sdjl /* hash table collision-see above */
3242830Sdjl lmutex_unlock(&getXbydbop_hash_lock);
3252830Sdjl return (-1);
3262830Sdjl }
3272830Sdjl getXbyYdbopHASH[hval] = i | DBOP_HASH_TAG;
3282830Sdjl }
3293864Sraf membar_producer();
3302830Sdjl getXbyYdbop_hashed = 1;
3312830Sdjl }
3322830Sdjl lmutex_unlock(&getXbydbop_hash_lock);
3332830Sdjl }
3343864Sraf membar_consumer();
3352830Sdjl cp = name;
3362830Sdjl hval = 0;
3372830Sdjl while (*cp) {
3382830Sdjl hval = (hval << 4) + *cp++;
3398765SMilan.Jurik@Sun.COM if ((g = (hval & hbits_tst)) != 0)
3402830Sdjl hval ^= g >> 24;
3412830Sdjl hval &= ~g;
3422830Sdjl }
3432830Sdjl hval += dbop;
3442830Sdjl hval %= DBOP_PRIME_HASH;
3452830Sdjl idx = getXbyYdbopHASH[hval];
3462830Sdjl if ((idx & DBOP_HASH_TAG) != DBOP_HASH_TAG)
3472830Sdjl return (-1);
3482830Sdjl idx &= ~DBOP_HASH_TAG;
3492830Sdjl if (idx >= count)
3502830Sdjl return (-1);
3512830Sdjl hptr = &getXbyY_to_dbop[idx];
3522830Sdjl if (hptr->dbop != dbop || strcmp(name, hptr->name) != 0)
3532830Sdjl return (-1);
3542830Sdjl return (idx);
3552830Sdjl }
3562830Sdjl
3572830Sdjl /*
3582830Sdjl * nss_pack_key2str
3592830Sdjl * Private key to string packing function for getXbyY routines
3602830Sdjl * This routine performs a printf like parse over the argument
3612830Sdjl * key, given a string of items to pack and assembles the key in
3622830Sdjl * the packed structure. This routine is called (currently) by
3632830Sdjl * nss_default_key2str, but will be used by other external
3642830Sdjl * APIs in the future.
3652830Sdjl *
3662830Sdjl * buffer - Start of the key buffer location [in packed buffer]
3672830Sdjl * length - Length of key buffer component
3682830Sdjl * Key offsets are relative to start of key buffer location.
3692830Sdjl *
3702830Sdjl * Pack fields Key
3712830Sdjl * key.name n
3722830Sdjl * key.number N
3732830Sdjl * key.uid u
3742830Sdjl * key.gid g
3752830Sdjl * key.hostaddr h
3762830Sdjl * key.ipnode i
3772830Sdjl * key.projid p
3782830Sdjl * key.serv(name) s
3792830Sdjl * key.serv(port) S
3802830Sdjl * key.ether e
3812830Sdjl * key.pkey k
3822830Sdjl * key.netaddr a
3832830Sdjl * key.attrp A
3842830Sdjl * groupsbymember I
3852830Sdjl * innetgr_args t
3862830Sdjl * setnetgr_args T
3872830Sdjl */
3882830Sdjl
3892830Sdjl /*ARGSUSED*/
3902830Sdjl static nss_status_t
nss_pack_key2str(void * buffer,size_t length,nss_XbyY_args_t * arg,const char * dbname,int dbop,size_t * rlen,const char * typestr)3912830Sdjl nss_pack_key2str(void *buffer, size_t length, nss_XbyY_args_t *arg,
3922830Sdjl const char *dbname, int dbop, size_t *rlen, const char *typestr)
3932830Sdjl {
3942830Sdjl int i, j;
3952830Sdjl size_t len, len2, len3, len4, len5, slop;
3962830Sdjl nssuint_t *uptr, offv, offc;
3972830Sdjl struct nss_setnetgrent_args *sng;
3982830Sdjl struct nss_innetgr_args *ing;
3992830Sdjl struct nss_groupsbymem *gbm;
4002830Sdjl char **cv, *dptr;
4012830Sdjl nss_pnetgr_t *pptr;
4022830Sdjl _priv_execattr *pe;
4032830Sdjl
4042830Sdjl if (buffer == NULL || length == 0 || arg == NULL ||
4052830Sdjl dbname == NULL || rlen == NULL || typestr == NULL)
4062830Sdjl return (NSS_ERROR);
4072830Sdjl
4082830Sdjl while (typestr && *typestr) {
4092830Sdjl switch (*typestr++) {
4102830Sdjl case 'n':
4112830Sdjl if (arg->key.name == NULL)
4122830Sdjl return (NSS_NOTFOUND);
4132830Sdjl len = strlen(arg->key.name) + 1;
4142830Sdjl if (len >= length)
4152830Sdjl return (NSS_ERROR);
4162830Sdjl (void) strlcpy(buffer, arg->key.name, len);
4172830Sdjl *rlen = len;
4182830Sdjl break;
4192830Sdjl case 'N':
4202830Sdjl len = sizeof (nssuint_t);
4212830Sdjl if (len >= length)
4222830Sdjl return (NSS_ERROR);
4232830Sdjl *(nssuint_t *)buffer = (nssuint_t)arg->key.number;
4242830Sdjl *rlen = len;
4252830Sdjl break;
4262830Sdjl case 'u':
4272830Sdjl len = sizeof (nssuint_t);
4282830Sdjl if (len >= length)
4292830Sdjl return (NSS_ERROR);
4302830Sdjl *(nssuint_t *)buffer = (nssuint_t)arg->key.uid;
4312830Sdjl *rlen = len;
4322830Sdjl break;
4332830Sdjl case 'g':
4342830Sdjl len = sizeof (nssuint_t);
4352830Sdjl if (len >= length)
4362830Sdjl return (NSS_ERROR);
4372830Sdjl *(nssuint_t *)buffer = (nssuint_t)arg->key.gid;
4382830Sdjl *rlen = len;
4392830Sdjl break;
4402830Sdjl case 'h':
4412830Sdjl if (arg->key.hostaddr.addr == NULL)
4422830Sdjl return (-1);
4432830Sdjl len = arg->key.hostaddr.len;
4442830Sdjl len = ROUND_UP(len, sizeof (nssuint_t));
4452830Sdjl len2 = (sizeof (nssuint_t) * 2) + len;
4462830Sdjl if (len2 >= length)
4472830Sdjl return (NSS_ERROR);
4482830Sdjl *(nssuint_t *)buffer =
4492830Sdjl (nssuint_t)arg->key.hostaddr.len;
4502830Sdjl buffer = (void *)((char *)buffer + sizeof (nssuint_t));
4512830Sdjl *(nssuint_t *)buffer =
4522830Sdjl (nssuint_t)arg->key.hostaddr.type;
4532830Sdjl buffer = (void *)((char *)buffer + sizeof (nssuint_t));
4542830Sdjl (void) memcpy(buffer, arg->key.hostaddr.addr,
4555477Sandra arg->key.hostaddr.len);
4562830Sdjl *rlen = len2;
4572830Sdjl break;
4582830Sdjl case 'i':
4592830Sdjl if (arg->key.ipnode.name == NULL)
4602830Sdjl return (NSS_NOTFOUND);
4612830Sdjl len = strlen(arg->key.ipnode.name) + 1;
4622830Sdjl len = ROUND_UP(len, sizeof (nssuint_t));
4632830Sdjl len2 = (sizeof (nssuint_t) * 2) + len;
4642830Sdjl if (len2 >= length)
4652830Sdjl return (NSS_ERROR);
4662830Sdjl *(nssuint_t *)buffer =
4672830Sdjl (nssuint_t)arg->key.ipnode.af_family;
4682830Sdjl buffer = (void *)((char *)buffer + sizeof (nssuint_t));
4692830Sdjl *(nssuint_t *)buffer =
4702830Sdjl (nssuint_t)arg->key.ipnode.flags;
4712830Sdjl buffer = (void *)((char *)buffer + sizeof (nssuint_t));
4722830Sdjl (void) strlcpy(buffer, arg->key.ipnode.name, len);
4732830Sdjl *rlen = len2;
4742830Sdjl break;
4752830Sdjl case 'p':
4762830Sdjl len = sizeof (nssuint_t);
4772830Sdjl if (len >= length)
4782830Sdjl return (NSS_ERROR);
4792830Sdjl *(nssuint_t *)buffer = (nssuint_t)arg->key.projid;
4802830Sdjl *rlen = len;
4812830Sdjl break;
4822830Sdjl case 's':
4832830Sdjl if (arg->key.serv.serv.name == NULL)
4842830Sdjl return (NSS_NOTFOUND);
4852830Sdjl len = strlen(arg->key.serv.serv.name) + 1;
4862830Sdjl len2 = 1;
4872830Sdjl if (arg->key.serv.proto != NULL)
4882830Sdjl len2 += strlen(arg->key.serv.proto);
4892830Sdjl len3 = len + len2;
4902830Sdjl len3 = ROUND_UP(len3, sizeof (nssuint_t));
4912830Sdjl if (len3 >= length)
4922830Sdjl return (NSS_ERROR);
4932830Sdjl (void) strlcpy(buffer, arg->key.serv.serv.name, len);
4942830Sdjl buffer = (void *)((char *)buffer + len);
4952830Sdjl if (len2 > 1)
4962830Sdjl (void) strlcpy(buffer, arg->key.serv.proto,
4975477Sandra len2);
4982830Sdjl else
4992830Sdjl *(char *)buffer = '\0';
5002830Sdjl *rlen = len3;
5012830Sdjl break;
5022830Sdjl case 'S':
5032830Sdjl len2 = 0;
5042830Sdjl if (arg->key.serv.proto != NULL)
5052830Sdjl len2 = strlen(arg->key.serv.proto) + 1;
5062830Sdjl len = sizeof (nssuint_t) + len2;
5072830Sdjl if (len >= length)
5082830Sdjl return (NSS_ERROR);
5092830Sdjl uptr = (nssuint_t *)buffer;
5102830Sdjl *uptr++ = (nssuint_t)arg->key.serv.serv.port;
5112830Sdjl if (len2) {
5122830Sdjl (void) strlcpy((char *)uptr,
5135477Sandra arg->key.serv.proto, len2);
5142830Sdjl }
5152830Sdjl *rlen = len;
5162830Sdjl break;
5172830Sdjl case 'e':
5182830Sdjl if (arg->key.ether == NULL)
5192830Sdjl return (NSS_NOTFOUND);
5202830Sdjl len = sizeof (struct ether_addr);
5212830Sdjl len = ROUND_UP(len, sizeof (nssuint_t));
5222830Sdjl if (len >= length)
5232830Sdjl return (NSS_ERROR);
5242830Sdjl *(struct ether_addr *)buffer =
5255477Sandra *(struct ether_addr *)arg->key.ether;
5262830Sdjl *rlen = len;
5272830Sdjl break;
5282830Sdjl case 'k':
5292830Sdjl if (arg->key.pkey.name == NULL ||
5302830Sdjl arg->key.pkey.keytype == NULL)
5312830Sdjl return (NSS_NOTFOUND);
5322830Sdjl len = strlen(arg->key.pkey.name) + 1;
5332830Sdjl len2 = strlen(arg->key.pkey.keytype) + 1;
5342830Sdjl len3 = len + len2;
5352830Sdjl len3 = ROUND_UP(len3, sizeof (nssuint_t));
5362830Sdjl if (len3 >= length)
5372830Sdjl return (NSS_ERROR);
5382830Sdjl (void) strlcpy(buffer, arg->key.pkey.name, len);
5392830Sdjl buffer = (void *)((char *)buffer + len);
5402830Sdjl (void) strlcpy(buffer, arg->key.pkey.keytype, len2);
5412830Sdjl *rlen = len3;
5422830Sdjl break;
5432830Sdjl case 'a':
5442830Sdjl uptr = (nssuint_t *)buffer;
5452830Sdjl len = sizeof (nssuint_t) * 2;
5462830Sdjl if (len >= length)
5472830Sdjl return (NSS_ERROR);
5482830Sdjl *uptr++ = (nssuint_t)arg->key.netaddr.net;
5492830Sdjl *uptr++ = (nssuint_t)arg->key.netaddr.type;
5502830Sdjl *rlen = len;
5512830Sdjl break;
5522830Sdjl case 'A':
5532830Sdjl pe = (_priv_execattr *)(arg->key.attrp);
5542830Sdjl if (pe == NULL)
5552830Sdjl return (NSS_NOTFOUND);
5562830Sdjl /* for search flag */
5572830Sdjl len = sizeof (nssuint_t);
5582830Sdjl /* for sizeof (_priv_execattr) static buffer */
5592830Sdjl /* Plus lots of slop just in case... */
5602830Sdjl slop = sizeof (nssuint_t) * 16;
5612830Sdjl len += slop;
5622830Sdjl
5632830Sdjl len2 = len3 = len4 = len5 = 1;
5642830Sdjl if (pe->name != NULL)
5652830Sdjl len2 = strlen(pe->name) + 1;
5662830Sdjl if (pe->type != NULL)
5672830Sdjl len3 = strlen(pe->type) + 1;
5682830Sdjl if (pe->id != NULL)
5692830Sdjl len4 = strlen(pe->id) + 1;
5702830Sdjl if (pe->policy != NULL)
5712830Sdjl len5 = strlen(pe->policy) + 1;
5722830Sdjl /* head_exec, prev_exec - are client side only... */
5732830Sdjl len += len2 + len3 + len4 + len5;
5742830Sdjl len = ROUND_UP(len, sizeof (nssuint_t));
5752830Sdjl if (len >= length)
5762830Sdjl return (NSS_ERROR);
5772830Sdjl (void) memset((void *)buffer, 0, slop);
5782830Sdjl uptr = (nssuint_t *)((void *)((char *)buffer + slop));
5792830Sdjl *uptr++ = (nssuint_t)pe->search_flag;
5802830Sdjl dptr = (char *)uptr;
5812830Sdjl if (len2 == 1)
5822830Sdjl *dptr++ = '\0';
5832830Sdjl else {
5842830Sdjl (void) strlcpy(dptr, pe->name, len2);
5852830Sdjl dptr += len2;
5862830Sdjl }
5872830Sdjl if (len3 == 1)
5882830Sdjl *dptr++ = '\0';
5892830Sdjl else {
5902830Sdjl (void) strlcpy(dptr, pe->type, len3);
5912830Sdjl dptr += len3;
5922830Sdjl }
5932830Sdjl if (len4 == 1)
5942830Sdjl *dptr++ = '\0';
5952830Sdjl else {
5962830Sdjl (void) strlcpy(dptr, pe->id, len4);
5972830Sdjl dptr += len4;
5982830Sdjl }
5992830Sdjl if (len5 == 1)
6002830Sdjl *dptr++ = '\0';
6012830Sdjl else
6022830Sdjl (void) strlcpy(dptr, pe->policy, len5);
6032830Sdjl *rlen = len;
6042830Sdjl break;
6052830Sdjl case 'I':
6062830Sdjl gbm = (struct nss_groupsbymem *)arg;
6072830Sdjl if (gbm->username == NULL)
6082830Sdjl return (NSS_NOTFOUND);
6092830Sdjl len = strlen(gbm->username) + 1;
6102830Sdjl len2 = sizeof (nssuint_t) * 4;
6112830Sdjl len2 += ROUND_UP(len, sizeof (nssuint_t));
6122830Sdjl if (len2 >= length)
6132830Sdjl return (NSS_ERROR);
6142830Sdjl uptr = (nssuint_t *)buffer;
6152830Sdjl *uptr++ = (nssuint_t)gbm->force_slow_way;
6162830Sdjl *uptr++ = (nssuint_t)gbm->maxgids;
6172830Sdjl *uptr++ = (nssuint_t)gbm->numgids;
6182830Sdjl if (gbm->numgids == 1) {
6192830Sdjl *uptr++ = (nssuint_t)gbm->gid_array[0];
6202830Sdjl } else {
6212830Sdjl *uptr++ = (nssuint_t)0;
6222830Sdjl }
6232830Sdjl (void) strlcpy((void *)uptr, gbm->username, len);
6242830Sdjl *rlen = len2;
6252830Sdjl break;
6262830Sdjl case 't':
6272830Sdjl pptr = (nss_pnetgr_t *)buffer;
6282830Sdjl ing = (struct nss_innetgr_args *)arg;
6292830Sdjl len = sizeof (nss_pnetgr_t);
6302830Sdjl len2 = ing->arg[NSS_NETGR_MACHINE].argc +
6315477Sandra ing->arg[NSS_NETGR_USER].argc +
6325477Sandra ing->arg[NSS_NETGR_DOMAIN].argc +
6335477Sandra ing->groups.argc;
6342830Sdjl len2 *= sizeof (nssuint_t);
6352830Sdjl len3 = 0;
6362830Sdjl for (j = 0; j < NSS_NETGR_N; j++) {
6372830Sdjl cv = ing->arg[j].argv;
6382830Sdjl for (i = ing->arg[j].argc; --i >= 0; ) {
6392830Sdjl if (*cv)
6402830Sdjl len3 += strlen(*cv++) + 1;
6412830Sdjl }
6422830Sdjl }
6432830Sdjl cv = ing->groups.argv;
6442830Sdjl for (i = ing->groups.argc; --i >= 0; ) {
6452830Sdjl if (*cv)
6462830Sdjl len3 += strlen(*cv++) + 1;
6472830Sdjl }
6482830Sdjl len3 = ROUND_UP(len3, sizeof (nssuint_t));
6492830Sdjl /*
6502830Sdjl * Double argv space. Reason:
6512830Sdjl * First 1/2 offsets
6522830Sdjl * Second 1/2 for client side pointer arrays
6532830Sdjl * resolves malloc/free issues with unpacked argvs
6542830Sdjl */
6552830Sdjl if ((len + (len2 << 1) + len3) >= length)
6562830Sdjl return (NSS_ERROR);
6572830Sdjl *rlen = len + (len2 << 1) + len3;
6582830Sdjl
6592830Sdjl pptr->machine_argc = ing->arg[NSS_NETGR_MACHINE].argc;
6602830Sdjl pptr->user_argc = ing->arg[NSS_NETGR_USER].argc;
6612830Sdjl pptr->domain_argc = ing->arg[NSS_NETGR_DOMAIN].argc;
6622830Sdjl pptr->groups_argc = ing->groups.argc;
6632830Sdjl offv = len;
6642830Sdjl uptr = (nssuint_t *)((void *)((char *)buffer + offv));
6652830Sdjl offc = len + (len2 << 1);
6662830Sdjl dptr = (char *)buffer + offc;
6672830Sdjl if (pptr->machine_argc == 0) {
6682830Sdjl pptr->machine_offv = (nssuint_t)0;
6692830Sdjl } else {
6702830Sdjl pptr->machine_offv = offv;
6712830Sdjl cv = ing->arg[NSS_NETGR_MACHINE].argv;
6722830Sdjl i = pptr->machine_argc;
6732830Sdjl offv += sizeof (nssuint_t) * i;
6742830Sdjl for (; --i >= 0; ) {
6752830Sdjl *uptr++ = offc;
6762830Sdjl len3 = strlen(*cv) + 1;
6772830Sdjl (void) strlcpy(dptr, *cv++, len3);
6782830Sdjl offc += len3;
6792830Sdjl dptr += len3;
6802830Sdjl }
6812830Sdjl }
6822830Sdjl if (pptr->user_argc == 0) {
6832830Sdjl pptr->user_offv = (nssuint_t)0;
6842830Sdjl } else {
6852830Sdjl pptr->user_offv = offv;
6862830Sdjl cv = ing->arg[NSS_NETGR_USER].argv;
6872830Sdjl i = pptr->user_argc;
6882830Sdjl offv += sizeof (nssuint_t) * i;
6892830Sdjl for (; --i >= 0; ) {
6902830Sdjl *uptr++ = offc;
6912830Sdjl len3 = strlen(*cv) + 1;
6922830Sdjl (void) strlcpy(dptr, *cv++, len3);
6932830Sdjl offc += len3;
6942830Sdjl dptr += len3;
6952830Sdjl }
6962830Sdjl }
6972830Sdjl if (pptr->domain_argc == 0) {
6982830Sdjl pptr->domain_offv = (nssuint_t)0;
6992830Sdjl } else {
7002830Sdjl pptr->domain_offv = offv;
7012830Sdjl cv = ing->arg[NSS_NETGR_DOMAIN].argv;
7022830Sdjl i = pptr->domain_argc;
7032830Sdjl offv += sizeof (nssuint_t) * i;
7042830Sdjl for (; --i >= 0; ) {
7052830Sdjl *uptr++ = offc;
7062830Sdjl len3 = strlen(*cv) + 1;
7072830Sdjl (void) strlcpy(dptr, *cv++, len3);
7082830Sdjl offc += len3;
7092830Sdjl dptr += len3;
7102830Sdjl }
7112830Sdjl }
7122830Sdjl if (pptr->groups_argc == 0) {
7132830Sdjl pptr->groups_offv = (nssuint_t)0;
7142830Sdjl } else {
7152830Sdjl pptr->groups_offv = offv;
7162830Sdjl cv = ing->groups.argv;
7172830Sdjl i = pptr->groups_argc;
7182830Sdjl offv += sizeof (nssuint_t) * i;
7192830Sdjl for (; --i >= 0; ) {
7202830Sdjl *uptr++ = offc;
7212830Sdjl len3 = strlen(*cv) + 1;
7222830Sdjl (void) strlcpy(dptr, *cv++, len3);
7232830Sdjl offc += len3;
7242830Sdjl dptr += len3;
7252830Sdjl }
7262830Sdjl }
7272830Sdjl break;
7282830Sdjl case 'T':
7292830Sdjl sng = (struct nss_setnetgrent_args *)arg;
7302830Sdjl if (sng->netgroup == NULL)
7312830Sdjl return (NSS_NOTFOUND);
7322830Sdjl len = strlen(sng->netgroup) + 1;
7332830Sdjl if (len >= length)
7342830Sdjl return (NSS_ERROR);
7352830Sdjl (void) strlcpy(buffer, sng->netgroup, len);
7362830Sdjl *rlen = len;
7372830Sdjl break;
7382830Sdjl default:
7392830Sdjl return (NSS_ERROR);
7402830Sdjl }
7412830Sdjl }
7422830Sdjl return (NSS_SUCCESS);
7432830Sdjl }
7442830Sdjl
7452830Sdjl nss_status_t
nss_default_key2str(void * buffer,size_t length,nss_XbyY_args_t * arg,const char * dbname,int dbop,size_t * rlen)7462830Sdjl nss_default_key2str(void *buffer, size_t length, nss_XbyY_args_t *arg,
7472830Sdjl const char *dbname, int dbop, size_t *rlen)
7482830Sdjl {
7492830Sdjl int index;
7502830Sdjl
7512830Sdjl if (buffer == NULL || length == 0 || arg == NULL ||
7522830Sdjl dbname == NULL || rlen == NULL)
7532830Sdjl return (NSS_ERROR);
7542830Sdjl
7552830Sdjl /*
7562830Sdjl * If this is not one of the well known getXbyYs
7572830Sdjl * (IE _printers special processing etc.) use a
7582830Sdjl * local (non-nscd) getXbyY lookup.
7592830Sdjl */
7602830Sdjl if ((index = nss_dbop_search(dbname, (uint32_t)dbop)) < 0)
7612830Sdjl return (NSS_TRYLOCAL);
7622830Sdjl
7632830Sdjl return (nss_pack_key2str(buffer, length, arg, dbname,
7645477Sandra dbop, rlen, getXbyY_to_dbop[index].tostr));
7652830Sdjl }
7662830Sdjl
7672830Sdjl /*ARGSUSED*/
7682830Sdjl void
nss_packed_set_status(void * buffer,size_t length,nss_status_t status,nss_XbyY_args_t * arg)7692830Sdjl nss_packed_set_status(void *buffer, size_t length, nss_status_t status,
7702830Sdjl nss_XbyY_args_t *arg)
7712830Sdjl {
7722830Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
7732830Sdjl nss_dbd_t *pdbd;
7742830Sdjl char *dbn;
7752830Sdjl
7762830Sdjl /* sidestep odd cases */
7772830Sdjl pdbd = (nss_dbd_t *)((void *)((char *)buffer + pbuf->dbd_off));
7782830Sdjl dbn = (char *)pdbd + pdbd->o_name;
7792830Sdjl if (pbuf->nss_dbop == NSS_DBOP_GROUP_BYMEMBER) {
7802830Sdjl if (strcmp(dbn, NSS_DBNAM_GROUP) == 0) {
7812830Sdjl struct nss_groupsbymem *in =
7825477Sandra (struct nss_groupsbymem *)arg;
7832830Sdjl
7842830Sdjl if (in->numgids >= 0) {
7852830Sdjl pbuf->p_status = NSS_SUCCESS;
7862830Sdjl pbuf->data_len = in->numgids *
7875477Sandra sizeof (gid_t);
7882830Sdjl pbuf->p_herrno = 0;
7892830Sdjl } else {
7902830Sdjl pbuf->p_status = status;
7912830Sdjl pbuf->p_errno = errno;
7922830Sdjl pbuf->data_len = 0;
7932830Sdjl pbuf->p_herrno = (uint32_t)arg->h_errno;
7942830Sdjl }
7952830Sdjl return;
7962830Sdjl }
7972830Sdjl }
7982830Sdjl if (pbuf->nss_dbop == NSS_DBOP_NETGROUP_IN) {
7992830Sdjl if (strcmp(dbn, NSS_DBNAM_NETGROUP) == 0) {
8002830Sdjl struct nss_innetgr_args *in =
8015477Sandra (struct nss_innetgr_args *)arg;
8022830Sdjl
8032830Sdjl /* tell nss_unpack() operation is successful */
8042830Sdjl pbuf->data_len = 1;
8052830Sdjl
8065477Sandra if (status != NSS_SUCCESS && status != NSS_NOTFOUND) {
8075477Sandra pbuf->p_status = status;
8085477Sandra pbuf->p_errno = errno;
8095477Sandra return;
8105477Sandra }
8115477Sandra
8122830Sdjl if (in->status == NSS_NETGR_FOUND) {
8132830Sdjl pbuf->p_status = NSS_SUCCESS;
8142830Sdjl } else {
8152830Sdjl pbuf->p_status = NSS_NOTFOUND;
8162830Sdjl pbuf->p_errno = errno;
8172830Sdjl }
8182830Sdjl return;
8192830Sdjl }
8202830Sdjl }
8212830Sdjl
8222830Sdjl /* process normal cases */
8232830Sdjl if ((pbuf->p_status = status) != NSS_SUCCESS) {
8242830Sdjl if (arg->erange == 1)
8252830Sdjl pbuf->p_errno = ERANGE;
8262830Sdjl else
8272830Sdjl pbuf->p_errno = errno;
8282830Sdjl } else
8292830Sdjl pbuf->p_errno = 0;
8302830Sdjl if (arg != NULL) {
8312830Sdjl pbuf->p_herrno = (uint32_t)arg->h_errno;
8322830Sdjl pbuf->data_len = (nssuint_t)arg->returnlen;
8332830Sdjl } else {
8342830Sdjl pbuf->p_herrno = 0;
8352830Sdjl pbuf->data_len = 0;
8362830Sdjl }
8372830Sdjl }
8382830Sdjl
8392830Sdjl /*
8402830Sdjl * nss_upack_key2arg
8412830Sdjl * Private string to key unpacking function for getXbyY routines
8422830Sdjl * This routine performs a scanf/printf like parse over the packed
8432830Sdjl * string, to uppack and re-assemble the key in the args structure.
8442830Sdjl *
8452830Sdjl * buffer - Start of the key buffer location [in packed buffer]
8462830Sdjl * length - Length of key buffer component
8472830Sdjl * Key offsets are relative to start of key buffer location.
8482830Sdjl *
8492830Sdjl * Unpack fields Key
8502830Sdjl * key.name n
8512830Sdjl * key.number N
8522830Sdjl * key.uid u
8532830Sdjl * key.gid g
8542830Sdjl * key.hostaddr h
8552830Sdjl * key.ipnode i
8562830Sdjl * key.projid p
8572830Sdjl * key.serv(name) s
8582830Sdjl * key.serv(port) S
8592830Sdjl * key.ether e
8602830Sdjl * key.pkey k
8612830Sdjl * key.netaddr a
8622830Sdjl * key.attrp A
8632830Sdjl * groupsbymember I
8642830Sdjl * innetgr_args t
8652830Sdjl * setnetgr_args T
8662830Sdjl * Assumes arguments are all valid
8672830Sdjl */
8682830Sdjl
8692830Sdjl /*ARGSUSED*/
8702830Sdjl static nss_status_t
nss_upack_key2arg(void * buffer,size_t length,char ** dbname,int * dbop,nss_XbyY_args_t * arg,int index)8712830Sdjl nss_upack_key2arg(void *buffer, size_t length, char **dbname,
8722830Sdjl int *dbop, nss_XbyY_args_t *arg, int index)
8732830Sdjl {
8742830Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
8752830Sdjl const char *strtype = NULL;
8764142Smichen nssuint_t off, *uptr, keysize;
8772830Sdjl size_t len, slop;
8782830Sdjl int i, j;
8792830Sdjl char **cv, *bptr;
8802830Sdjl struct nss_setnetgrent_args *sng;
8812830Sdjl struct nss_innetgr_args *ing;
8822830Sdjl struct nss_groupsbymem *gbm;
8832830Sdjl nss_pnetgr_t *pptr;
8842830Sdjl _priv_execattr *pe;
8852830Sdjl
8864142Smichen /* keysize is length of the key area */
8874142Smichen keysize = pbuf->data_off - pbuf->key_off;
8884142Smichen
8892830Sdjl off = pbuf->key_off;
8902830Sdjl bptr = (char *)buffer + off;
8912830Sdjl uptr = (nssuint_t *)((void *)bptr);
8922830Sdjl strtype = getXbyY_to_dbop[index].tostr;
8932830Sdjl if (strtype == NULL)
8942830Sdjl return (NSS_ERROR);
8952830Sdjl while (*strtype) {
8962830Sdjl switch (*strtype++) {
8972830Sdjl case 'n':
8982830Sdjl arg->key.name = (const char *)bptr;
8992830Sdjl break;
9002830Sdjl case 'N':
9012830Sdjl arg->key.number = (int)(*uptr);
9022830Sdjl break;
9032830Sdjl case 'u':
9042830Sdjl arg->key.uid = (uid_t)(*uptr);
9052830Sdjl break;
9062830Sdjl case 'g':
9072830Sdjl arg->key.gid = (gid_t)(*uptr);
9082830Sdjl break;
9092830Sdjl case 'h':
9102830Sdjl arg->key.hostaddr.len = (int)(*uptr++);
9112830Sdjl arg->key.hostaddr.type = (int)(*uptr++);
9122830Sdjl arg->key.hostaddr.addr = (const char *)uptr;
9132830Sdjl break;
9142830Sdjl case 'i':
9152830Sdjl arg->key.ipnode.af_family = (int)(*uptr++);
9162830Sdjl arg->key.ipnode.flags = (int)(*uptr++);
9172830Sdjl arg->key.ipnode.name = (const char *)uptr;
9182830Sdjl break;
9192830Sdjl case 'p':
9202830Sdjl arg->key.projid = (projid_t)(*uptr);
9212830Sdjl break;
9222830Sdjl case 's':
9232830Sdjl arg->key.serv.serv.name = (const char *)bptr;
9242830Sdjl len = strlen(arg->key.serv.serv.name) + 1;
9252830Sdjl bptr += len;
9262830Sdjl if (*(const char *)bptr == '\0')
9272830Sdjl arg->key.serv.proto = NULL;
9282830Sdjl else
9292830Sdjl arg->key.serv.proto = (const char *)bptr;
9302830Sdjl break;
9312830Sdjl case 'S':
9322830Sdjl arg->key.serv.serv.port = (int)(*uptr++);
9332830Sdjl if (pbuf->key_len == sizeof (nssuint_t)) {
9342830Sdjl arg->key.serv.proto = NULL;
9352830Sdjl } else {
9362830Sdjl bptr += sizeof (nssuint_t);
9372830Sdjl arg->key.serv.proto = (const char *)bptr;
9382830Sdjl }
9392830Sdjl break;
9402830Sdjl case 'e':
9412830Sdjl arg->key.ether = bptr;
9422830Sdjl break;
9432830Sdjl case 'k':
9442830Sdjl arg->key.pkey.name = (const char *)bptr;
9452830Sdjl len = strlen(arg->key.pkey.name) + 1;
9462830Sdjl bptr += len;
9472830Sdjl arg->key.pkey.keytype = (const char *)bptr;
9482830Sdjl break;
9492830Sdjl case 'a':
9502830Sdjl arg->key.netaddr.net = (uint32_t)(*uptr++);
9512830Sdjl arg->key.netaddr.type = (int)(*uptr++);
9522830Sdjl break;
9532830Sdjl case 'A':
9542830Sdjl pe = (_priv_execattr *)((void *)bptr);
9552830Sdjl /* use slop space as priv_execattr structure */
9562830Sdjl arg->key.attrp = (void *)pe;
9572830Sdjl /* skip over slop ... */
9582830Sdjl slop = sizeof (nssuint_t) * 16;
9592830Sdjl uptr = (nssuint_t *)((void *)((char *)bptr + slop));
9602830Sdjl pe->search_flag = (int)*uptr++;
9612830Sdjl bptr = (char *)uptr;
9622830Sdjl if (*bptr == '\0') {
9632830Sdjl pe->name = NULL;
9642830Sdjl bptr++;
9652830Sdjl } else {
9662830Sdjl pe->name = (char *)bptr;
9672830Sdjl bptr += strlen(pe->name) + 1;
9682830Sdjl }
9692830Sdjl if (*bptr == '\0') {
9702830Sdjl pe->type = NULL;
9712830Sdjl bptr++;
9722830Sdjl } else {
9732830Sdjl pe->type = (char *)bptr;
9742830Sdjl bptr += strlen(pe->type) + 1;
9752830Sdjl }
9762830Sdjl if (*bptr == '\0') {
9772830Sdjl pe->id = NULL;
9782830Sdjl bptr++;
9792830Sdjl } else {
9802830Sdjl pe->id = (char *)bptr;
9812830Sdjl bptr += strlen(pe->id) + 1;
9822830Sdjl }
9832830Sdjl if (*bptr == '\0') {
9842830Sdjl pe->policy = NULL;
9852830Sdjl } else {
9862830Sdjl pe->policy = (char *)bptr;
9872830Sdjl }
9882830Sdjl pe->head_exec = NULL;
9892830Sdjl pe->prev_exec = NULL;
9902830Sdjl break;
9912830Sdjl case 'I':
9922830Sdjl gbm = (struct nss_groupsbymem *)arg;
9932830Sdjl gbm->gid_array = (gid_t *)
9945477Sandra ((void *)((char *)pbuf + pbuf->data_off));
9952830Sdjl gbm->force_slow_way = (int)(*uptr++);
9962830Sdjl gbm->maxgids = (int)(*uptr++);
9972830Sdjl gbm->numgids = (int)(*uptr++);
9982830Sdjl if (gbm->numgids == 1) {
9992830Sdjl /* insert initial group into data area */
10003099Smichen gbm->gid_array[0] = (gid_t)(*uptr++);
10013099Smichen } else
10023099Smichen uptr++;
10032830Sdjl gbm->username = (const char *)uptr;
10042830Sdjl break;
10052830Sdjl case 't':
10062830Sdjl pptr = (nss_pnetgr_t *)((void *)bptr);
10072830Sdjl ing = (struct nss_innetgr_args *)arg;
10082830Sdjl ing->arg[NSS_NETGR_MACHINE].argc = pptr->machine_argc;
10092830Sdjl ing->arg[NSS_NETGR_USER].argc = pptr->user_argc;
10102830Sdjl ing->arg[NSS_NETGR_DOMAIN].argc = pptr->domain_argc;
10112830Sdjl ing->groups.argc = pptr->groups_argc;
10122830Sdjl
10132830Sdjl /*
10142830Sdjl * Start of argv pointer storage
10152830Sdjl */
10162830Sdjl off = ing->arg[NSS_NETGR_MACHINE].argc +
10175477Sandra ing->arg[NSS_NETGR_USER].argc +
10185477Sandra ing->arg[NSS_NETGR_DOMAIN].argc +
10195477Sandra ing->groups.argc;
10202830Sdjl off *= sizeof (nssuint_t);
10212830Sdjl off += sizeof (nss_pnetgr_t);
10222830Sdjl
10232830Sdjl cv = (char **)((void *)(bptr + off));
10242830Sdjl uptr = (nssuint_t *)
10255477Sandra ((void *)(bptr + sizeof (nss_pnetgr_t)));
10262830Sdjl for (j = 0; j < NSS_NETGR_N; j++) {
10272830Sdjl ing->arg[j].argv = cv;
10282830Sdjl for (i = 0; i < ing->arg[j].argc; i++) {
10294142Smichen if (*uptr >= keysize)
10304142Smichen return (NSS_ERROR);
10312830Sdjl *cv++ = (bptr + *uptr++);
10322830Sdjl }
10332830Sdjl }
10342830Sdjl ing->groups.argv = cv;
10352830Sdjl for (i = 0; i < ing->groups.argc; i++) {
10364142Smichen if (*uptr >= keysize)
10374142Smichen return (NSS_ERROR);
10382830Sdjl *cv++ = (bptr + *uptr++);
10392830Sdjl }
10402830Sdjl break;
10412830Sdjl case 'T':
10422830Sdjl sng = (struct nss_setnetgrent_args *)arg;
10432830Sdjl sng->netgroup = (const char *)bptr;
10442830Sdjl sng->iterator = 0;
10452830Sdjl break;
10462830Sdjl
10472830Sdjl default:
10482830Sdjl return (NSS_ERROR);
10492830Sdjl }
10502830Sdjl }
10512830Sdjl return (NSS_SUCCESS);
10522830Sdjl }
10532830Sdjl
10542830Sdjl static nss_status_t
nss_pinit_funcs(int index,nss_db_initf_t * initf,nss_str2ent_t * s2e)10552830Sdjl nss_pinit_funcs(int index, nss_db_initf_t *initf, nss_str2ent_t *s2e)
10562830Sdjl {
10572830Sdjl const char *name;
10584046Smichen void *htmp = NULL;
10594046Smichen void *sym;
10604046Smichen static void *handle = NULL;
10614046Smichen static mutex_t handle_lock = DEFAULTMUTEX;
10624046Smichen static mutex_t initf_lock = DEFAULTMUTEX;
10634046Smichen static mutex_t s2e_lock = DEFAULTMUTEX;
10642830Sdjl
10654046Smichen if (handle == NULL) {
10665914Sraf htmp = dlopen((const char *)0, RTLD_LAZY);
10675914Sraf
10684046Smichen lmutex_lock(&handle_lock);
10694046Smichen if (handle == NULL) {
10704046Smichen if (htmp == NULL) {
10714046Smichen lmutex_unlock(&handle_lock);
10722830Sdjl return (NSS_ERROR);
10732830Sdjl } else {
10744046Smichen membar_producer();
10754046Smichen handle = htmp;
10765914Sraf htmp = NULL;
10772830Sdjl }
10782830Sdjl }
10794046Smichen lmutex_unlock(&handle_lock);
10805914Sraf if (htmp)
1081*11411SSurya.Prakki@Sun.COM (void) dlclose(htmp);
10824046Smichen }
10834046Smichen membar_consumer();
10844046Smichen
10854046Smichen if (initf) {
10866515Sraf if (getXbyY_to_dbop[index].initfnp == NULL) {
10876515Sraf name = getXbyY_to_dbop[index].initfn;
10886515Sraf if ((sym = dlsym(handle, name)) == NULL)
10896515Sraf return (NSS_ERROR);
10904046Smichen lmutex_lock(&initf_lock);
10916515Sraf if (getXbyY_to_dbop[index].initfnp == NULL)
10924046Smichen getXbyY_to_dbop[index].initfnp = sym;
10934046Smichen membar_producer();
10944046Smichen lmutex_unlock(&initf_lock);
10952830Sdjl }
10966515Sraf membar_consumer();
10976515Sraf *initf = (nss_db_initf_t)getXbyY_to_dbop[index].initfnp;
10982830Sdjl }
10994046Smichen if (s2e) {
11006515Sraf if (getXbyY_to_dbop[index].strfnp == NULL) {
11016515Sraf name = getXbyY_to_dbop[index].strfn;
11026515Sraf if ((sym = dlsym(handle, name)) == NULL)
11036515Sraf return (NSS_ERROR);
11044046Smichen lmutex_lock(&s2e_lock);
11056515Sraf if (getXbyY_to_dbop[index].strfnp == NULL)
11064046Smichen getXbyY_to_dbop[index].strfnp = sym;
11074046Smichen membar_producer();
11084046Smichen lmutex_unlock(&s2e_lock);
11094046Smichen }
11106515Sraf membar_consumer();
11116515Sraf *s2e = (nss_str2ent_t)getXbyY_to_dbop[index].strfnp;
11124046Smichen }
11134046Smichen
11142830Sdjl return (NSS_SUCCESS);
11152830Sdjl }
11162830Sdjl
11172830Sdjl nss_status_t
nss_packed_getkey(void * buffer,size_t length,char ** dbname,int * dbop,nss_XbyY_args_t * arg)11182830Sdjl nss_packed_getkey(void *buffer, size_t length, char **dbname,
11192830Sdjl int *dbop, nss_XbyY_args_t *arg)
11202830Sdjl {
11212830Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
11222830Sdjl nss_dbd_t *pdbd;
11234142Smichen nssuint_t off, dbdsize;
11242830Sdjl int index;
11252830Sdjl
11262830Sdjl if (buffer == NULL || length == 0 || dbop == NULL ||
11275477Sandra arg == NULL || dbname == NULL)
11282830Sdjl return (NSS_ERROR);
11292830Sdjl
11302830Sdjl *dbop = pbuf->nss_dbop;
11312830Sdjl off = pbuf->dbd_off;
11322830Sdjl pdbd = (nss_dbd_t *)((void *)((char *)buffer + off));
11334142Smichen dbdsize = pbuf->key_off - pbuf->dbd_off;
11344142Smichen if (pdbd->o_name >= dbdsize || pdbd->o_config_name >= dbdsize ||
11355477Sandra pdbd->o_default_config >= dbdsize)
11364142Smichen return (NSS_ERROR);
11372830Sdjl *dbname = (char *)buffer + off + pdbd->o_name;
11382830Sdjl if ((index = nss_dbop_search(*dbname, (uint32_t)*dbop)) < 0)
11392830Sdjl return (NSS_ERROR);
11402830Sdjl return (nss_upack_key2arg(buffer, length, dbname, dbop, arg, index));
11412830Sdjl }
11422830Sdjl
11432830Sdjl
11442830Sdjl /*
11452830Sdjl * str2packent: Standard format interposed str2X function for normal APIs
11462830Sdjl *
11472830Sdjl * Return values: 0 = success, 1 = parse error, 2 = erange ...
11482830Sdjl *
11492830Sdjl * The structure pointer is ignored since this is a nscd side packed request.
11502830Sdjl * The client side routine does all the real parsing; we just check limits and
11512830Sdjl * store the entry in the buffer we were passed by the caller.
11522830Sdjl */
11532830Sdjl
11542830Sdjl /*ARGSUSED*/
11552830Sdjl static int
str2packent(const char * instr,int lenstr,void * ent,char * buffer,int buflen)11562830Sdjl str2packent(
11572830Sdjl const char *instr,
11582830Sdjl int lenstr,
11592830Sdjl void *ent, /* really (char *) */
11602830Sdjl char *buffer,
11612830Sdjl int buflen
11622830Sdjl )
11632830Sdjl {
11642830Sdjl if (buflen <= lenstr) { /* not enough buffer */
11652830Sdjl return (NSS_STR_PARSE_ERANGE);
11662830Sdjl }
11672830Sdjl (void) memmove(buffer, instr, lenstr);
11682830Sdjl buffer[lenstr] = '\0';
11692830Sdjl
11702830Sdjl return (NSS_STR_PARSE_SUCCESS);
11712830Sdjl }
11722830Sdjl
11732830Sdjl /*
11742830Sdjl * Initialize db_root, initf, dbop and arg from a packed buffer
11752830Sdjl */
11762830Sdjl
11772830Sdjl /*ARGSUSED*/
11782830Sdjl nss_status_t
nss_packed_arg_init(void * buffer,size_t length,nss_db_root_t * db_root,nss_db_initf_t * initf,int * dbop,nss_XbyY_args_t * arg)11792830Sdjl nss_packed_arg_init(void *buffer, size_t length, nss_db_root_t *db_root,
11802830Sdjl nss_db_initf_t *initf, int *dbop, nss_XbyY_args_t *arg)
11812830Sdjl {
11822830Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
11832830Sdjl nss_str2ent_t s2e = str2packent;
11842830Sdjl nss_str2ent_t real_s2e = NULL;
11852830Sdjl nss_dbd_t *pdbd;
11864142Smichen nssuint_t off, dbdsize;
11872830Sdjl char *dbname, *bptr;
11882830Sdjl size_t len;
11892830Sdjl int index;
11902830Sdjl
11912830Sdjl if (buffer == NULL || length == 0 ||
11925477Sandra dbop == NULL || arg == NULL)
11932830Sdjl return (NSS_ERROR);
11942830Sdjl
11952830Sdjl /* init dbop */
11962830Sdjl *dbop = pbuf->nss_dbop;
11972830Sdjl off = pbuf->dbd_off;
11982830Sdjl pdbd = (nss_dbd_t *)((void *)((char *)buffer + off));
11994142Smichen dbdsize = pbuf->key_off - pbuf->dbd_off;
12004142Smichen if (pdbd->o_name >= dbdsize || pdbd->o_config_name >= dbdsize ||
12015477Sandra pdbd->o_default_config >= dbdsize)
12024142Smichen return (NSS_ERROR);
12032830Sdjl dbname = (char *)buffer + off + pdbd->o_name;
12042830Sdjl if ((index = nss_dbop_search(dbname, (uint32_t)*dbop)) < 0)
12052830Sdjl return (NSS_ERROR);
12062830Sdjl
12072830Sdjl /* db_root is initialized by nscd's based on door info */
12082830Sdjl /* do nothing here */
12092830Sdjl
12102830Sdjl /* init key information - (and get dbname dbop etc...) */
12112830Sdjl if (nss_upack_key2arg(buffer, length, &dbname,
12125477Sandra dbop, arg, index) != NSS_SUCCESS)
12132830Sdjl return (NSS_ERROR);
12142830Sdjl
12152830Sdjl /* possible audituser init */
12162830Sdjl if (strcmp(dbname, NSS_DBNAM_AUTHATTR) == 0)
12172830Sdjl arg->h_errno = (int)pbuf->p_herrno;
12182830Sdjl
12192830Sdjl bptr = (char *)buffer + pbuf->data_off;
12202830Sdjl len = (size_t)pbuf->data_len;
12212830Sdjl
12222830Sdjl /* sidestep odd arg cases */
12232830Sdjl if (*dbop == NSS_DBOP_GROUP_BYMEMBER &&
12242830Sdjl strcmp(dbname, NSS_DBNAM_GROUP) == 0) {
12252830Sdjl /* get initf and str2ent functions */
12262830Sdjl if (nss_pinit_funcs(index, initf, &real_s2e) != NSS_SUCCESS)
12272830Sdjl return (NSS_ERROR);
12282830Sdjl ((struct nss_groupsbymem *)arg)->str2ent = real_s2e;
12293099Smichen ((struct nss_groupsbymem *)arg)->process_cstr = process_cstr;
12302830Sdjl return (NSS_SUCCESS);
12312830Sdjl }
12322830Sdjl if (pbuf->nss_dbop == NSS_DBOP_NETGROUP_IN &&
12335477Sandra strcmp(dbname, NSS_DBNAM_NETGROUP) == 0) {
12342830Sdjl return (NSS_SUCCESS);
12352830Sdjl }
12362830Sdjl
12372830Sdjl /* get initf and str2ent functions */
12382830Sdjl if (nss_pinit_funcs(index, initf, NULL) != NSS_SUCCESS)
12392830Sdjl return (NSS_ERROR);
12402830Sdjl
12412830Sdjl /* init normal arg cases */
12422830Sdjl NSS_XbyY_INIT(arg, NULL, bptr, len, s2e);
12432830Sdjl arg->h_errno = 0;
12442830Sdjl
12452830Sdjl return (NSS_SUCCESS);
12462830Sdjl }
12472830Sdjl
12482830Sdjl /*
12492830Sdjl * Initialize db_root, initf, dbop, contextp and arg from a packed buffer
12502830Sdjl */
12512830Sdjl
12522830Sdjl /*ARGSUSED*/
12532830Sdjl nss_status_t
nss_packed_context_init(void * buffer,size_t length,nss_db_root_t * db_root,nss_db_initf_t * initf,nss_getent_t ** contextp,nss_XbyY_args_t * arg)12542830Sdjl nss_packed_context_init(void *buffer, size_t length, nss_db_root_t *db_root,
12552830Sdjl nss_db_initf_t *initf, nss_getent_t **contextp,
12562830Sdjl nss_XbyY_args_t *arg)
12572830Sdjl {
12582830Sdjl nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
12592830Sdjl nss_str2ent_t s2e = str2packent;
12602830Sdjl char *bptr;
12612830Sdjl size_t len;
12622830Sdjl
12632830Sdjl /* init arg */
12642830Sdjl if (arg != NULL) {
12652830Sdjl bptr = (char *)buffer + pbuf->data_off;
12662830Sdjl len = (size_t)pbuf->data_len;
12672830Sdjl NSS_XbyY_INIT(arg, NULL, bptr, len, s2e);
12682830Sdjl }
12692830Sdjl
12702830Sdjl return (NSS_SUCCESS);
12712830Sdjl }
1272