1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include "lint.h"
28 #include <mtlib.h>
29 #include <ctype.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <nss_dbdefs.h>
34 #include <limits.h>
35 #include <dlfcn.h>
36 #include <link.h>
37 #include <thread.h>
38 #include <atomic.h>
39 /* headers for key2str/str2key routines */
40 #include <sys/ethernet.h>
41 #include <exec_attr.h>
42 #include <grp.h>
43
44 /*
45 * functions in nss_dbdefs.c deal more with the mechanics of
46 * the data structures like nss_XbyY_args_t and the interaction
47 * with the packed buffers etc. versus the mechanics of the
48 * actual policy component operations such as nss_search sequencing.
49 */
50
51 /*
52 * ALIGN? is there an official definition of this?
53 * We use sizeof(long) to cover what we want
54 * for both the 32-bit world and 64-bit world.
55 */
56
57 #define ALIGN(x) ((((long)(x)) + sizeof (long) - 1) & ~(sizeof (long) - 1))
58
59 nss_XbyY_buf_t *
_nss_XbyY_buf_alloc(int struct_size,int buffer_size)60 _nss_XbyY_buf_alloc(int struct_size, int buffer_size)
61 {
62 nss_XbyY_buf_t *b;
63
64 /* Use one malloc for dbargs, result struct and buffer */
65 b = (nss_XbyY_buf_t *)
66 malloc(ALIGN(sizeof (*b)) + struct_size + buffer_size);
67 if (b == 0) {
68 return (0);
69 }
70 b->result = (void *)ALIGN(&b[1]);
71 b->buffer = (char *)(b->result) + struct_size;
72 b->buflen = buffer_size;
73 return (b);
74 }
75
76 void
_nss_XbyY_buf_free(nss_XbyY_buf_t * b)77 _nss_XbyY_buf_free(nss_XbyY_buf_t *b)
78 {
79 if (b != 0) {
80 free(b);
81 }
82 }
83
84 /* === Comment: used by fget{gr,pw,sp}ent */
85 /* ==== Should do ye olde syslog()ing of suspiciously long lines */
86
87 void
_nss_XbyY_fgets(FILE * f,nss_XbyY_args_t * b)88 _nss_XbyY_fgets(FILE *f, nss_XbyY_args_t *b)
89 {
90 char buf[LINE_MAX];
91 int len, parsestat;
92
93 if (fgets(buf, LINE_MAX, f) == 0) {
94 /* End of file */
95 b->returnval = 0;
96 b->erange = 0;
97 return;
98 }
99 len = (int)strlen(buf);
100 /* len >= 0 (otherwise we would have got EOF) */
101 if (buf[len - 1] != '\n') {
102 if ((len + 1) == LINE_MAX) {
103 /* Line too long for buffer; too bad */
104 while (fgets(buf, LINE_MAX, f) != 0 &&
105 buf[strlen(buf) - 1] != '\n') {
106 ;
107 }
108 b->returnval = 0;
109 b->erange = 1;
110 return;
111 }
112 /* case where the file is not terminated with a Newline */
113 len++;
114 }
115 parsestat = (*b->str2ent)(buf, (len - 1), b->buf.result, b->buf.buffer,
116 b->buf.buflen);
117 if (parsestat == NSS_STR_PARSE_ERANGE) {
118 b->returnval = 0;
119 b->erange = 1;
120 } else if (parsestat == NSS_STR_PARSE_SUCCESS) {
121 b->returnval = b->buf.result;
122 }
123 }
124
125 /*
126 * parse the aliases string into the buffer and if successful return
127 * a char ** pointer to the beginning of the aliases.
128 *
129 * CAUTION: (instr, instr+lenstr) and (buffer, buffer+buflen) are
130 * non-intersecting memory areas. Since this is an internal interface,
131 * we should be able to live with that.
132 *
133 * "instr" is the beginning of the aliases string
134 * "buffer" has the return val for success
135 * "buflen" is the length of the buffer available for aliases
136 */
137 char **
_nss_netdb_aliases(const char * instr,int lenstr,char * buffer,int buflen)138 _nss_netdb_aliases(const char *instr, int lenstr, char *buffer, int buflen)
139 {
140 /*
141 * Build the alias-list in the start of the buffer, and copy
142 * the strings to the end of the buffer.
143 */
144 const char *instr_limit = instr + lenstr;
145 char *copyptr = buffer + buflen;
146 char **aliasp = (char **)ROUND_UP(buffer, sizeof (*aliasp));
147 char **alias_start = aliasp;
148 int nstrings = 0;
149
150 for (;;) {
151 const char *str_start;
152 size_t str_len;
153
154 while (instr < instr_limit && isspace(*instr)) {
155 instr++;
156 }
157 if (instr >= instr_limit || *instr == '#') {
158 break;
159 }
160 str_start = instr;
161 while (instr < instr_limit && !isspace(*instr)) {
162 instr++;
163 }
164
165 ++nstrings;
166
167 str_len = instr - str_start;
168 copyptr -= str_len + 1;
169 if (copyptr <= (char *)(&aliasp[nstrings + 1])) {
170 /* Has to be room for the pointer to */
171 /* the alias we're about to add, */
172 /* as well as the final NULL ptr. */
173 return (0);
174 }
175 *aliasp++ = copyptr;
176 (void) memcpy(copyptr, str_start, str_len);
177 copyptr[str_len] = '\0';
178 }
179 *aliasp++ = 0;
180 return (alias_start);
181 }
182
183
184 extern nss_status_t process_cstr(const char *, int, struct nss_groupsbymem *);
185
186 /*
187 * pack well known getXbyY keys to packed buffer prior to the door_call
188 * to nscd. Some consideration is given to ordering the tests based on
189 * usage. Note: buf is nssuint_t aligned.
190 */
191
192 typedef struct {
193 const char *name; /* NSS_DBNAM_* */
194 const char *defconf; /* NSS_DEFCONF_* */
195 const char *initfn; /* init function name */
196 const char *strfn; /* str2X function name */
197 const char *cstrfn; /* cstr2X function name */
198 void *initfnp; /* init function pointer */
199 void *strfnp; /* str2X function pointer */
200 uint32_t dbop; /* NSS_DBOP_* */
201 const char *tostr; /* key2str cvt str */
202 } getXbyY_to_dbop_t;
203
204 #define NSS_MK_GETXYDBOP(x, y, f, e) \
205 { NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, "str2" f, \
206 NULL, NULL, NULL, NSS_DBOP_##x##_##y, (e) }
207
208 #define NSS_MK_GETXYDBOPA(x, a, f, e) \
209 { NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, "str2" f, \
210 NULL, NULL, NULL, NSS_DBOP_##a, (e) }
211
212 #define NSS_MK_GETXYDBOPB(x, b, a, f, s, e) \
213 { NSS_DBNAM_##x, NSS_DEFCONF_##b, "_nss_initf_" f, s, \
214 NULL, NULL, NULL, NSS_DBOP_##a, (e) }
215
216 #define NSS_MK_GETXYDBOPC(x, a, f, s, e) \
217 { NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, s, \
218 NULL, NULL, NULL, NSS_DBOP_##x##_##a, (e) }
219
220 #define NSS_MK_GETXYDBOPD(x, y, i, f, e) \
221 { NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" i, "str2" f, \
222 NULL, NULL, NULL, NSS_DBOP_##x##_##y, (e) }
223
224 #define NSS_MK_GETXYDBOPCSTR(x, a, f, s, e) \
225 { NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, s, \
226 "process_cstr", NULL, NULL, NSS_DBOP_##x##_##a, (e) }
227
228 /*
229 * The getXbyY_to_dbop structure is hashed on first call in order to
230 * reduce the search time for the well known getXbyY operations.
231 * A binary search was not fast enough. There were on average
232 * 3-4 tests (strcmps) per getXbyY call.
233 *
234 * DBOP_PRIME_HASH must be a prime number (reasonably small) but that
235 * is sufficient to uniquely map the entries in the following table
236 * without collision.
237 *
238 * The DBOP_PRIME_HASH was selected as the smallest hash value
239 * for this table without collisions. Changing this table WILL
240 * necessitate re-testing for possible collisions.
241 */
242
243 #define DBOP_PRIME_HASH 227
244 #define DBOP_HASH_TAG 0xf0000000
245 static int getXbyYdbopHASH[DBOP_PRIME_HASH] = { 0 };
246 static mutex_t getXbydbop_hash_lock = DEFAULTMUTEX;
247 static int getXbyYdbop_hashed = 0;
248
249 /*
250 * If the size of getXbyY_to_dbop[] is changed then hash function must be
251 * corrected to be without collisions in nss_dbop_search().
252 */
253 static getXbyY_to_dbop_t getXbyY_to_dbop[] = {
254 /* NSS_MK_GETXYDBOP(ALIASES, ?, ?), */
255 NSS_MK_GETXYDBOPD(AUDITUSER, BYNAME, "auuser", "audituser", "n"),
256 NSS_MK_GETXYDBOP(AUTHATTR, BYNAME, "authattr", "n"),
257 /* NSS_MK_GETXYDBOP(AUTOMOUNT, ?, ?), */
258 NSS_MK_GETXYDBOP(BOOTPARAMS, BYNAME, "bootparams", "n"),
259 NSS_MK_GETXYDBOPC(ETHERS, HOSTTON, "ethers", "str2ether", "n"),
260 NSS_MK_GETXYDBOPC(ETHERS, NTOHOST, "ethers", "str2ether", "e"),
261 NSS_MK_GETXYDBOP(EXECATTR, BYNAME, "execattr", "A"),
262 NSS_MK_GETXYDBOP(EXECATTR, BYID, "execattr", "A"),
263 NSS_MK_GETXYDBOP(EXECATTR, BYNAMEID, "execattr", "A"),
264 NSS_MK_GETXYDBOP(GROUP, BYNAME, "group", "n"),
265 NSS_MK_GETXYDBOP(GROUP, BYGID, "group", "g"),
266 NSS_MK_GETXYDBOPCSTR(GROUP, BYMEMBER, "group", "str2group", "I"),
267 NSS_MK_GETXYDBOPC(HOSTS, BYNAME, "hosts", "str2hostent", "n"),
268 NSS_MK_GETXYDBOPC(HOSTS, BYADDR, "hosts", "str2hostent", "h"),
269 NSS_MK_GETXYDBOPC(IPNODES, BYNAME, "ipnodes", "str2hostent", "i"),
270 NSS_MK_GETXYDBOPC(IPNODES, BYADDR, "ipnodes", "str2hostent", "h"),
271 NSS_MK_GETXYDBOP(NETGROUP, IN, "netgroup", "t"),
272 NSS_MK_GETXYDBOP(NETGROUP, SET, "netgroup", "T"),
273 NSS_MK_GETXYDBOPC(NETMASKS, BYNET, "netmasks", "str2addr", "n"),
274 NSS_MK_GETXYDBOPC(NETWORKS, BYNAME, "net", "str2netent", "n"),
275 NSS_MK_GETXYDBOPC(NETWORKS, BYADDR, "net", "str2netent", "a"),
276 NSS_MK_GETXYDBOP(PASSWD, BYNAME, "passwd", "n"),
277 NSS_MK_GETXYDBOP(PASSWD, BYUID, "passwd", "u"),
278 NSS_MK_GETXYDBOP(PRINTERS, BYNAME, "printers", "n"),
279 NSS_MK_GETXYDBOP(PROFATTR, BYNAME, "profattr", "n"),
280 NSS_MK_GETXYDBOP(PROJECT, BYNAME, "project", "n"),
281 NSS_MK_GETXYDBOP(PROJECT, BYID, "project", "p"),
282 NSS_MK_GETXYDBOPC(PROTOCOLS, BYNAME, "proto", "str2protoent", "n"),
283 NSS_MK_GETXYDBOPC(PROTOCOLS, BYNUMBER, "proto", "str2protoent", "N"),
284 NSS_MK_GETXYDBOPA(PUBLICKEY, KEYS_BYNAME, "publickey", "k"),
285 NSS_MK_GETXYDBOPC(RPC, BYNAME, "rpc", "str2rpcent", "n"),
286 NSS_MK_GETXYDBOPC(RPC, BYNUMBER, "rpc", "str2rpcent", "N"),
287 NSS_MK_GETXYDBOPC(SERVICES, BYNAME, "services", "str2servent", "s"),
288 NSS_MK_GETXYDBOPC(SERVICES, BYPORT, "services", "str2servent", "S"),
289 NSS_MK_GETXYDBOPB(SHADOW, PASSWD, PASSWD_BYNAME, "shadow",
290 "str2spwd", "n"),
291 NSS_MK_GETXYDBOPC(TSOL_RH, BYADDR, "tsol_rh", "str_to_rhstr", "h"),
292 NSS_MK_GETXYDBOPC(TSOL_TP, BYNAME, "tsol_tp", "str_to_tpstr", "n"),
293 NSS_MK_GETXYDBOPC(TSOL_ZC, BYNAME, "tsol_zc", "str_to_zcstr", "n"),
294 NSS_MK_GETXYDBOP(USERATTR, BYNAME, "userattr", "n"),
295 };
296
297 static int
nss_dbop_search(const char * name,uint32_t dbop)298 nss_dbop_search(const char *name, uint32_t dbop)
299 {
300 getXbyY_to_dbop_t *hptr;
301 int count = (sizeof (getXbyY_to_dbop) / sizeof (getXbyY_to_dbop_t));
302 uint32_t hval, g;
303 const char *cp;
304 int i, idx;
305 static const uint32_t hbits_tst = 0xf0000000;
306
307 /* Uses a table size is known to have no collisions */
308 if (getXbyYdbop_hashed == 0) {
309 lmutex_lock(&getXbydbop_hash_lock);
310 if (getXbyYdbop_hashed == 0) {
311 for (i = 0; i < count; i++) {
312 cp = getXbyY_to_dbop[i].name;
313 hval = 0;
314 while (*cp) {
315 hval = (hval << 4) + *cp++;
316 if ((g = (hval & hbits_tst)) != 0)
317 hval ^= g >> 24;
318 hval &= ~g;
319 }
320 hval += getXbyY_to_dbop[i].dbop;
321 hval %= DBOP_PRIME_HASH;
322 if (getXbyYdbopHASH[hval] != 0) {
323 /* hash table collision-see above */
324 lmutex_unlock(&getXbydbop_hash_lock);
325 return (-1);
326 }
327 getXbyYdbopHASH[hval] = i | DBOP_HASH_TAG;
328 }
329 membar_producer();
330 getXbyYdbop_hashed = 1;
331 }
332 lmutex_unlock(&getXbydbop_hash_lock);
333 }
334 membar_consumer();
335 cp = name;
336 hval = 0;
337 while (*cp) {
338 hval = (hval << 4) + *cp++;
339 if ((g = (hval & hbits_tst)) != 0)
340 hval ^= g >> 24;
341 hval &= ~g;
342 }
343 hval += dbop;
344 hval %= DBOP_PRIME_HASH;
345 idx = getXbyYdbopHASH[hval];
346 if ((idx & DBOP_HASH_TAG) != DBOP_HASH_TAG)
347 return (-1);
348 idx &= ~DBOP_HASH_TAG;
349 if (idx >= count)
350 return (-1);
351 hptr = &getXbyY_to_dbop[idx];
352 if (hptr->dbop != dbop || strcmp(name, hptr->name) != 0)
353 return (-1);
354 return (idx);
355 }
356
357 /*
358 * nss_pack_key2str
359 * Private key to string packing function for getXbyY routines
360 * This routine performs a printf like parse over the argument
361 * key, given a string of items to pack and assembles the key in
362 * the packed structure. This routine is called (currently) by
363 * nss_default_key2str, but will be used by other external
364 * APIs in the future.
365 *
366 * buffer - Start of the key buffer location [in packed buffer]
367 * length - Length of key buffer component
368 * Key offsets are relative to start of key buffer location.
369 *
370 * Pack fields Key
371 * key.name n
372 * key.number N
373 * key.uid u
374 * key.gid g
375 * key.hostaddr h
376 * key.ipnode i
377 * key.projid p
378 * key.serv(name) s
379 * key.serv(port) S
380 * key.ether e
381 * key.pkey k
382 * key.netaddr a
383 * key.attrp A
384 * groupsbymember I
385 * innetgr_args t
386 * setnetgr_args T
387 */
388
389 static nss_status_t
nss_pack_key2str(void * buffer,size_t length,nss_XbyY_args_t * arg,const char * dbname,int dbop __unused,size_t * rlen,const char * typestr)390 nss_pack_key2str(void *buffer, size_t length, nss_XbyY_args_t *arg,
391 const char *dbname, int dbop __unused, size_t *rlen, const char *typestr)
392 {
393 int i, j;
394 size_t len, len2, len3, len4, len5, slop;
395 nssuint_t *uptr, offv, offc;
396 struct nss_setnetgrent_args *sng;
397 struct nss_innetgr_args *ing;
398 struct nss_groupsbymem *gbm;
399 char **cv, *dptr;
400 nss_pnetgr_t *pptr;
401 _priv_execattr *pe;
402
403 if (buffer == NULL || length == 0 || arg == NULL ||
404 dbname == NULL || rlen == NULL || typestr == NULL)
405 return (NSS_ERROR);
406
407 while (typestr && *typestr) {
408 switch (*typestr++) {
409 case 'n':
410 if (arg->key.name == NULL)
411 return (NSS_NOTFOUND);
412 len = strlen(arg->key.name) + 1;
413 if (len >= length)
414 return (NSS_ERROR);
415 (void) strlcpy(buffer, arg->key.name, len);
416 *rlen = len;
417 break;
418 case 'N':
419 len = sizeof (nssuint_t);
420 if (len >= length)
421 return (NSS_ERROR);
422 *(nssuint_t *)buffer = (nssuint_t)arg->key.number;
423 *rlen = len;
424 break;
425 case 'u':
426 len = sizeof (nssuint_t);
427 if (len >= length)
428 return (NSS_ERROR);
429 *(nssuint_t *)buffer = (nssuint_t)arg->key.uid;
430 *rlen = len;
431 break;
432 case 'g':
433 len = sizeof (nssuint_t);
434 if (len >= length)
435 return (NSS_ERROR);
436 *(nssuint_t *)buffer = (nssuint_t)arg->key.gid;
437 *rlen = len;
438 break;
439 case 'h':
440 if (arg->key.hostaddr.addr == NULL)
441 return (-1);
442 len = arg->key.hostaddr.len;
443 len = ROUND_UP(len, sizeof (nssuint_t));
444 len2 = (sizeof (nssuint_t) * 2) + len;
445 if (len2 >= length)
446 return (NSS_ERROR);
447 *(nssuint_t *)buffer =
448 (nssuint_t)arg->key.hostaddr.len;
449 buffer = (void *)((char *)buffer + sizeof (nssuint_t));
450 *(nssuint_t *)buffer =
451 (nssuint_t)arg->key.hostaddr.type;
452 buffer = (void *)((char *)buffer + sizeof (nssuint_t));
453 (void) memcpy(buffer, arg->key.hostaddr.addr,
454 arg->key.hostaddr.len);
455 *rlen = len2;
456 break;
457 case 'i':
458 if (arg->key.ipnode.name == NULL)
459 return (NSS_NOTFOUND);
460 len = strlen(arg->key.ipnode.name) + 1;
461 len = ROUND_UP(len, sizeof (nssuint_t));
462 len2 = (sizeof (nssuint_t) * 2) + len;
463 if (len2 >= length)
464 return (NSS_ERROR);
465 *(nssuint_t *)buffer =
466 (nssuint_t)arg->key.ipnode.af_family;
467 buffer = (void *)((char *)buffer + sizeof (nssuint_t));
468 *(nssuint_t *)buffer =
469 (nssuint_t)arg->key.ipnode.flags;
470 buffer = (void *)((char *)buffer + sizeof (nssuint_t));
471 (void) strlcpy(buffer, arg->key.ipnode.name, len);
472 *rlen = len2;
473 break;
474 case 'p':
475 len = sizeof (nssuint_t);
476 if (len >= length)
477 return (NSS_ERROR);
478 *(nssuint_t *)buffer = (nssuint_t)arg->key.projid;
479 *rlen = len;
480 break;
481 case 's':
482 if (arg->key.serv.serv.name == NULL)
483 return (NSS_NOTFOUND);
484 len = strlen(arg->key.serv.serv.name) + 1;
485 len2 = 1;
486 if (arg->key.serv.proto != NULL)
487 len2 += strlen(arg->key.serv.proto);
488 len3 = len + len2;
489 len3 = ROUND_UP(len3, sizeof (nssuint_t));
490 if (len3 >= length)
491 return (NSS_ERROR);
492 (void) strlcpy(buffer, arg->key.serv.serv.name, len);
493 buffer = (void *)((char *)buffer + len);
494 if (len2 > 1)
495 (void) strlcpy(buffer, arg->key.serv.proto,
496 len2);
497 else
498 *(char *)buffer = '\0';
499 *rlen = len3;
500 break;
501 case 'S':
502 len2 = 0;
503 if (arg->key.serv.proto != NULL)
504 len2 = strlen(arg->key.serv.proto) + 1;
505 len = sizeof (nssuint_t) + len2;
506 if (len >= length)
507 return (NSS_ERROR);
508 uptr = (nssuint_t *)buffer;
509 *uptr++ = (nssuint_t)arg->key.serv.serv.port;
510 if (len2) {
511 (void) strlcpy((char *)uptr,
512 arg->key.serv.proto, len2);
513 }
514 *rlen = len;
515 break;
516 case 'e':
517 if (arg->key.ether == NULL)
518 return (NSS_NOTFOUND);
519 len = sizeof (struct ether_addr);
520 len = ROUND_UP(len, sizeof (nssuint_t));
521 if (len >= length)
522 return (NSS_ERROR);
523 *(struct ether_addr *)buffer =
524 *(struct ether_addr *)arg->key.ether;
525 *rlen = len;
526 break;
527 case 'k':
528 if (arg->key.pkey.name == NULL ||
529 arg->key.pkey.keytype == NULL)
530 return (NSS_NOTFOUND);
531 len = strlen(arg->key.pkey.name) + 1;
532 len2 = strlen(arg->key.pkey.keytype) + 1;
533 len3 = len + len2;
534 len3 = ROUND_UP(len3, sizeof (nssuint_t));
535 if (len3 >= length)
536 return (NSS_ERROR);
537 (void) strlcpy(buffer, arg->key.pkey.name, len);
538 buffer = (void *)((char *)buffer + len);
539 (void) strlcpy(buffer, arg->key.pkey.keytype, len2);
540 *rlen = len3;
541 break;
542 case 'a':
543 uptr = (nssuint_t *)buffer;
544 len = sizeof (nssuint_t) * 2;
545 if (len >= length)
546 return (NSS_ERROR);
547 *uptr++ = (nssuint_t)arg->key.netaddr.net;
548 *uptr++ = (nssuint_t)arg->key.netaddr.type;
549 *rlen = len;
550 break;
551 case 'A':
552 pe = (_priv_execattr *)(arg->key.attrp);
553 if (pe == NULL)
554 return (NSS_NOTFOUND);
555 /* for search flag */
556 len = sizeof (nssuint_t);
557 /* for sizeof (_priv_execattr) static buffer */
558 /* Plus lots of slop just in case... */
559 slop = sizeof (nssuint_t) * 16;
560 len += slop;
561
562 len2 = len3 = len4 = len5 = 1;
563 if (pe->name != NULL)
564 len2 = strlen(pe->name) + 1;
565 if (pe->type != NULL)
566 len3 = strlen(pe->type) + 1;
567 if (pe->id != NULL)
568 len4 = strlen(pe->id) + 1;
569 if (pe->policy != NULL)
570 len5 = strlen(pe->policy) + 1;
571 /* head_exec, prev_exec - are client side only... */
572 len += len2 + len3 + len4 + len5;
573 len = ROUND_UP(len, sizeof (nssuint_t));
574 if (len >= length)
575 return (NSS_ERROR);
576 (void) memset((void *)buffer, 0, slop);
577 uptr = (nssuint_t *)((void *)((char *)buffer + slop));
578 *uptr++ = (nssuint_t)pe->search_flag;
579 dptr = (char *)uptr;
580 if (len2 == 1)
581 *dptr++ = '\0';
582 else {
583 (void) strlcpy(dptr, pe->name, len2);
584 dptr += len2;
585 }
586 if (len3 == 1)
587 *dptr++ = '\0';
588 else {
589 (void) strlcpy(dptr, pe->type, len3);
590 dptr += len3;
591 }
592 if (len4 == 1)
593 *dptr++ = '\0';
594 else {
595 (void) strlcpy(dptr, pe->id, len4);
596 dptr += len4;
597 }
598 if (len5 == 1)
599 *dptr++ = '\0';
600 else
601 (void) strlcpy(dptr, pe->policy, len5);
602 *rlen = len;
603 break;
604 case 'I':
605 gbm = (struct nss_groupsbymem *)arg;
606 if (gbm->username == NULL)
607 return (NSS_NOTFOUND);
608 len = strlen(gbm->username) + 1;
609 len2 = sizeof (nssuint_t) * 4;
610 len2 += ROUND_UP(len, sizeof (nssuint_t));
611 if (len2 >= length)
612 return (NSS_ERROR);
613 uptr = (nssuint_t *)buffer;
614 *uptr++ = (nssuint_t)gbm->force_slow_way;
615 *uptr++ = (nssuint_t)gbm->maxgids;
616 *uptr++ = (nssuint_t)gbm->numgids;
617 if (gbm->numgids == 1) {
618 *uptr++ = (nssuint_t)gbm->gid_array[0];
619 } else {
620 *uptr++ = (nssuint_t)0;
621 }
622 (void) strlcpy((void *)uptr, gbm->username, len);
623 *rlen = len2;
624 break;
625 case 't':
626 pptr = (nss_pnetgr_t *)buffer;
627 ing = (struct nss_innetgr_args *)arg;
628 len = sizeof (nss_pnetgr_t);
629 len2 = ing->arg[NSS_NETGR_MACHINE].argc +
630 ing->arg[NSS_NETGR_USER].argc +
631 ing->arg[NSS_NETGR_DOMAIN].argc +
632 ing->groups.argc;
633 len2 *= sizeof (nssuint_t);
634 len3 = 0;
635 for (j = 0; j < NSS_NETGR_N; j++) {
636 cv = ing->arg[j].argv;
637 for (i = ing->arg[j].argc; --i >= 0; ) {
638 if (*cv)
639 len3 += strlen(*cv++) + 1;
640 }
641 }
642 cv = ing->groups.argv;
643 for (i = ing->groups.argc; --i >= 0; ) {
644 if (*cv)
645 len3 += strlen(*cv++) + 1;
646 }
647 len3 = ROUND_UP(len3, sizeof (nssuint_t));
648 /*
649 * Double argv space. Reason:
650 * First 1/2 offsets
651 * Second 1/2 for client side pointer arrays
652 * resolves malloc/free issues with unpacked argvs
653 */
654 if ((len + (len2 << 1) + len3) >= length)
655 return (NSS_ERROR);
656 *rlen = len + (len2 << 1) + len3;
657
658 pptr->machine_argc = ing->arg[NSS_NETGR_MACHINE].argc;
659 pptr->user_argc = ing->arg[NSS_NETGR_USER].argc;
660 pptr->domain_argc = ing->arg[NSS_NETGR_DOMAIN].argc;
661 pptr->groups_argc = ing->groups.argc;
662 offv = len;
663 uptr = (nssuint_t *)((void *)((char *)buffer + offv));
664 offc = len + (len2 << 1);
665 dptr = (char *)buffer + offc;
666 if (pptr->machine_argc == 0) {
667 pptr->machine_offv = (nssuint_t)0;
668 } else {
669 pptr->machine_offv = offv;
670 cv = ing->arg[NSS_NETGR_MACHINE].argv;
671 i = pptr->machine_argc;
672 offv += sizeof (nssuint_t) * i;
673 for (; --i >= 0; ) {
674 *uptr++ = offc;
675 len3 = strlen(*cv) + 1;
676 (void) strlcpy(dptr, *cv++, len3);
677 offc += len3;
678 dptr += len3;
679 }
680 }
681 if (pptr->user_argc == 0) {
682 pptr->user_offv = (nssuint_t)0;
683 } else {
684 pptr->user_offv = offv;
685 cv = ing->arg[NSS_NETGR_USER].argv;
686 i = pptr->user_argc;
687 offv += sizeof (nssuint_t) * i;
688 for (; --i >= 0; ) {
689 *uptr++ = offc;
690 len3 = strlen(*cv) + 1;
691 (void) strlcpy(dptr, *cv++, len3);
692 offc += len3;
693 dptr += len3;
694 }
695 }
696 if (pptr->domain_argc == 0) {
697 pptr->domain_offv = (nssuint_t)0;
698 } else {
699 pptr->domain_offv = offv;
700 cv = ing->arg[NSS_NETGR_DOMAIN].argv;
701 i = pptr->domain_argc;
702 offv += sizeof (nssuint_t) * i;
703 for (; --i >= 0; ) {
704 *uptr++ = offc;
705 len3 = strlen(*cv) + 1;
706 (void) strlcpy(dptr, *cv++, len3);
707 offc += len3;
708 dptr += len3;
709 }
710 }
711 if (pptr->groups_argc == 0) {
712 pptr->groups_offv = (nssuint_t)0;
713 } else {
714 pptr->groups_offv = offv;
715 cv = ing->groups.argv;
716 i = pptr->groups_argc;
717 offv += sizeof (nssuint_t) * i;
718 for (; --i >= 0; ) {
719 *uptr++ = offc;
720 len3 = strlen(*cv) + 1;
721 (void) strlcpy(dptr, *cv++, len3);
722 offc += len3;
723 dptr += len3;
724 }
725 }
726 break;
727 case 'T':
728 sng = (struct nss_setnetgrent_args *)arg;
729 if (sng->netgroup == NULL)
730 return (NSS_NOTFOUND);
731 len = strlen(sng->netgroup) + 1;
732 if (len >= length)
733 return (NSS_ERROR);
734 (void) strlcpy(buffer, sng->netgroup, len);
735 *rlen = len;
736 break;
737 default:
738 return (NSS_ERROR);
739 }
740 }
741 return (NSS_SUCCESS);
742 }
743
744 nss_status_t
nss_default_key2str(void * buffer,size_t length,nss_XbyY_args_t * arg,const char * dbname,int dbop,size_t * rlen)745 nss_default_key2str(void *buffer, size_t length, nss_XbyY_args_t *arg,
746 const char *dbname, int dbop, size_t *rlen)
747 {
748 int index;
749
750 if (buffer == NULL || length == 0 || arg == NULL ||
751 dbname == NULL || rlen == NULL)
752 return (NSS_ERROR);
753
754 /*
755 * If this is not one of the well known getXbyYs
756 * (IE _printers special processing etc.) use a
757 * local (non-nscd) getXbyY lookup.
758 */
759 if ((index = nss_dbop_search(dbname, (uint32_t)dbop)) < 0)
760 return (NSS_TRYLOCAL);
761
762 return (nss_pack_key2str(buffer, length, arg, dbname,
763 dbop, rlen, getXbyY_to_dbop[index].tostr));
764 }
765
766 void
nss_packed_set_status(void * buffer,size_t length __unused,nss_status_t status,nss_XbyY_args_t * arg)767 nss_packed_set_status(void *buffer, size_t length __unused, nss_status_t status,
768 nss_XbyY_args_t *arg)
769 {
770 nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
771 nss_dbd_t *pdbd;
772 char *dbn;
773
774 /* sidestep odd cases */
775 pdbd = (nss_dbd_t *)((void *)((char *)buffer + pbuf->dbd_off));
776 dbn = (char *)pdbd + pdbd->o_name;
777 if (pbuf->nss_dbop == NSS_DBOP_GROUP_BYMEMBER) {
778 if (strcmp(dbn, NSS_DBNAM_GROUP) == 0) {
779 struct nss_groupsbymem *in =
780 (struct nss_groupsbymem *)arg;
781
782 if (in->numgids >= 0) {
783 pbuf->p_status = NSS_SUCCESS;
784 pbuf->data_len = in->numgids *
785 sizeof (gid_t);
786 pbuf->p_herrno = 0;
787 } else {
788 pbuf->p_status = status;
789 pbuf->p_errno = errno;
790 pbuf->data_len = 0;
791 pbuf->p_herrno = (uint32_t)arg->h_errno;
792 }
793 return;
794 }
795 }
796 if (pbuf->nss_dbop == NSS_DBOP_NETGROUP_IN) {
797 if (strcmp(dbn, NSS_DBNAM_NETGROUP) == 0) {
798 struct nss_innetgr_args *in =
799 (struct nss_innetgr_args *)arg;
800
801 /* tell nss_unpack() operation is successful */
802 pbuf->data_len = 1;
803
804 if (status != NSS_SUCCESS && status != NSS_NOTFOUND) {
805 pbuf->p_status = status;
806 pbuf->p_errno = errno;
807 return;
808 }
809
810 if (in->status == NSS_NETGR_FOUND) {
811 pbuf->p_status = NSS_SUCCESS;
812 } else {
813 pbuf->p_status = NSS_NOTFOUND;
814 pbuf->p_errno = errno;
815 }
816 return;
817 }
818 }
819
820 /* process normal cases */
821 if ((pbuf->p_status = status) != NSS_SUCCESS) {
822 if (arg->erange == 1)
823 pbuf->p_errno = ERANGE;
824 else
825 pbuf->p_errno = errno;
826 } else
827 pbuf->p_errno = 0;
828 if (arg != NULL) {
829 pbuf->p_herrno = (uint32_t)arg->h_errno;
830 pbuf->data_len = (nssuint_t)arg->returnlen;
831 } else {
832 pbuf->p_herrno = 0;
833 pbuf->data_len = 0;
834 }
835 }
836
837 /*
838 * nss_upack_key2arg
839 * Private string to key unpacking function for getXbyY routines
840 * This routine performs a scanf/printf like parse over the packed
841 * string, to uppack and re-assemble the key in the args structure.
842 *
843 * buffer - Start of the key buffer location [in packed buffer]
844 * length - Length of key buffer component
845 * Key offsets are relative to start of key buffer location.
846 *
847 * Unpack fields Key
848 * key.name n
849 * key.number N
850 * key.uid u
851 * key.gid g
852 * key.hostaddr h
853 * key.ipnode i
854 * key.projid p
855 * key.serv(name) s
856 * key.serv(port) S
857 * key.ether e
858 * key.pkey k
859 * key.netaddr a
860 * key.attrp A
861 * groupsbymember I
862 * innetgr_args t
863 * setnetgr_args T
864 * Assumes arguments are all valid
865 */
866
867 static nss_status_t
nss_upack_key2arg(void * buffer,size_t length __unused,char ** dbname __unused,int * dbop __unused,nss_XbyY_args_t * arg,int index)868 nss_upack_key2arg(void *buffer, size_t length __unused, char **dbname __unused,
869 int *dbop __unused, nss_XbyY_args_t *arg, int index)
870 {
871 nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
872 const char *strtype = NULL;
873 nssuint_t off, *uptr, keysize;
874 size_t len, slop;
875 int i, j;
876 char **cv, *bptr;
877 struct nss_setnetgrent_args *sng;
878 struct nss_innetgr_args *ing;
879 struct nss_groupsbymem *gbm;
880 nss_pnetgr_t *pptr;
881 _priv_execattr *pe;
882
883 /* keysize is length of the key area */
884 keysize = pbuf->data_off - pbuf->key_off;
885
886 off = pbuf->key_off;
887 bptr = (char *)buffer + off;
888 uptr = (nssuint_t *)((void *)bptr);
889 strtype = getXbyY_to_dbop[index].tostr;
890 if (strtype == NULL)
891 return (NSS_ERROR);
892 while (*strtype) {
893 switch (*strtype++) {
894 case 'n':
895 arg->key.name = (const char *)bptr;
896 break;
897 case 'N':
898 arg->key.number = (int)(*uptr);
899 break;
900 case 'u':
901 arg->key.uid = (uid_t)(*uptr);
902 break;
903 case 'g':
904 arg->key.gid = (gid_t)(*uptr);
905 break;
906 case 'h':
907 arg->key.hostaddr.len = (int)(*uptr++);
908 arg->key.hostaddr.type = (int)(*uptr++);
909 arg->key.hostaddr.addr = (const char *)uptr;
910 break;
911 case 'i':
912 arg->key.ipnode.af_family = (int)(*uptr++);
913 arg->key.ipnode.flags = (int)(*uptr++);
914 arg->key.ipnode.name = (const char *)uptr;
915 break;
916 case 'p':
917 arg->key.projid = (projid_t)(*uptr);
918 break;
919 case 's':
920 arg->key.serv.serv.name = (const char *)bptr;
921 len = strlen(arg->key.serv.serv.name) + 1;
922 bptr += len;
923 if (*(const char *)bptr == '\0')
924 arg->key.serv.proto = NULL;
925 else
926 arg->key.serv.proto = (const char *)bptr;
927 break;
928 case 'S':
929 arg->key.serv.serv.port = (int)(*uptr++);
930 if (pbuf->key_len == sizeof (nssuint_t)) {
931 arg->key.serv.proto = NULL;
932 } else {
933 bptr += sizeof (nssuint_t);
934 arg->key.serv.proto = (const char *)bptr;
935 }
936 break;
937 case 'e':
938 arg->key.ether = bptr;
939 break;
940 case 'k':
941 arg->key.pkey.name = (const char *)bptr;
942 len = strlen(arg->key.pkey.name) + 1;
943 bptr += len;
944 arg->key.pkey.keytype = (const char *)bptr;
945 break;
946 case 'a':
947 arg->key.netaddr.net = (uint32_t)(*uptr++);
948 arg->key.netaddr.type = (int)(*uptr++);
949 break;
950 case 'A':
951 pe = (_priv_execattr *)((void *)bptr);
952 /* use slop space as priv_execattr structure */
953 arg->key.attrp = (void *)pe;
954 /* skip over slop ... */
955 slop = sizeof (nssuint_t) * 16;
956 uptr = (nssuint_t *)((void *)((char *)bptr + slop));
957 pe->search_flag = (int)*uptr++;
958 bptr = (char *)uptr;
959 if (*bptr == '\0') {
960 pe->name = NULL;
961 bptr++;
962 } else {
963 pe->name = (char *)bptr;
964 bptr += strlen(pe->name) + 1;
965 }
966 if (*bptr == '\0') {
967 pe->type = NULL;
968 bptr++;
969 } else {
970 pe->type = (char *)bptr;
971 bptr += strlen(pe->type) + 1;
972 }
973 if (*bptr == '\0') {
974 pe->id = NULL;
975 bptr++;
976 } else {
977 pe->id = (char *)bptr;
978 bptr += strlen(pe->id) + 1;
979 }
980 if (*bptr == '\0') {
981 pe->policy = NULL;
982 } else {
983 pe->policy = (char *)bptr;
984 }
985 pe->head_exec = NULL;
986 pe->prev_exec = NULL;
987 break;
988 case 'I':
989 gbm = (struct nss_groupsbymem *)arg;
990 gbm->gid_array = (gid_t *)
991 ((void *)((char *)pbuf + pbuf->data_off));
992 gbm->force_slow_way = (int)(*uptr++);
993 gbm->maxgids = (int)(*uptr++);
994 gbm->numgids = (int)(*uptr++);
995 if (gbm->numgids == 1) {
996 /* insert initial group into data area */
997 gbm->gid_array[0] = (gid_t)(*uptr++);
998 } else
999 uptr++;
1000 gbm->username = (const char *)uptr;
1001 break;
1002 case 't':
1003 pptr = (nss_pnetgr_t *)((void *)bptr);
1004 ing = (struct nss_innetgr_args *)arg;
1005 ing->arg[NSS_NETGR_MACHINE].argc = pptr->machine_argc;
1006 ing->arg[NSS_NETGR_USER].argc = pptr->user_argc;
1007 ing->arg[NSS_NETGR_DOMAIN].argc = pptr->domain_argc;
1008 ing->groups.argc = pptr->groups_argc;
1009
1010 /*
1011 * Start of argv pointer storage
1012 */
1013 off = ing->arg[NSS_NETGR_MACHINE].argc +
1014 ing->arg[NSS_NETGR_USER].argc +
1015 ing->arg[NSS_NETGR_DOMAIN].argc +
1016 ing->groups.argc;
1017 off *= sizeof (nssuint_t);
1018 off += sizeof (nss_pnetgr_t);
1019
1020 cv = (char **)((void *)(bptr + off));
1021 uptr = (nssuint_t *)
1022 ((void *)(bptr + sizeof (nss_pnetgr_t)));
1023 for (j = 0; j < NSS_NETGR_N; j++) {
1024 ing->arg[j].argv = cv;
1025 for (i = 0; i < ing->arg[j].argc; i++) {
1026 if (*uptr >= keysize)
1027 return (NSS_ERROR);
1028 *cv++ = (bptr + *uptr++);
1029 }
1030 }
1031 ing->groups.argv = cv;
1032 for (i = 0; i < ing->groups.argc; i++) {
1033 if (*uptr >= keysize)
1034 return (NSS_ERROR);
1035 *cv++ = (bptr + *uptr++);
1036 }
1037 break;
1038 case 'T':
1039 sng = (struct nss_setnetgrent_args *)arg;
1040 sng->netgroup = (const char *)bptr;
1041 sng->iterator = 0;
1042 break;
1043
1044 default:
1045 return (NSS_ERROR);
1046 }
1047 }
1048 return (NSS_SUCCESS);
1049 }
1050
1051 static nss_status_t
nss_pinit_funcs(int index,nss_db_initf_t * initf,nss_str2ent_t * s2e)1052 nss_pinit_funcs(int index, nss_db_initf_t *initf, nss_str2ent_t *s2e)
1053 {
1054 const char *name;
1055 void *htmp = NULL;
1056 void *sym;
1057 static void *handle = NULL;
1058 static mutex_t handle_lock = DEFAULTMUTEX;
1059 static mutex_t initf_lock = DEFAULTMUTEX;
1060 static mutex_t s2e_lock = DEFAULTMUTEX;
1061
1062 if (handle == NULL) {
1063 htmp = dlopen((const char *)0, RTLD_LAZY);
1064
1065 lmutex_lock(&handle_lock);
1066 if (handle == NULL) {
1067 if (htmp == NULL) {
1068 lmutex_unlock(&handle_lock);
1069 return (NSS_ERROR);
1070 } else {
1071 membar_producer();
1072 handle = htmp;
1073 htmp = NULL;
1074 }
1075 }
1076 lmutex_unlock(&handle_lock);
1077 if (htmp)
1078 (void) dlclose(htmp);
1079 }
1080 membar_consumer();
1081
1082 if (initf) {
1083 if (getXbyY_to_dbop[index].initfnp == NULL) {
1084 name = getXbyY_to_dbop[index].initfn;
1085 if ((sym = dlsym(handle, name)) == NULL)
1086 return (NSS_ERROR);
1087 lmutex_lock(&initf_lock);
1088 if (getXbyY_to_dbop[index].initfnp == NULL)
1089 getXbyY_to_dbop[index].initfnp = sym;
1090 membar_producer();
1091 lmutex_unlock(&initf_lock);
1092 }
1093 membar_consumer();
1094 *initf = (nss_db_initf_t)getXbyY_to_dbop[index].initfnp;
1095 }
1096 if (s2e) {
1097 if (getXbyY_to_dbop[index].strfnp == NULL) {
1098 name = getXbyY_to_dbop[index].strfn;
1099 if ((sym = dlsym(handle, name)) == NULL)
1100 return (NSS_ERROR);
1101 lmutex_lock(&s2e_lock);
1102 if (getXbyY_to_dbop[index].strfnp == NULL)
1103 getXbyY_to_dbop[index].strfnp = sym;
1104 membar_producer();
1105 lmutex_unlock(&s2e_lock);
1106 }
1107 membar_consumer();
1108 *s2e = (nss_str2ent_t)getXbyY_to_dbop[index].strfnp;
1109 }
1110
1111 return (NSS_SUCCESS);
1112 }
1113
1114 nss_status_t
nss_packed_getkey(void * buffer,size_t length,char ** dbname,int * dbop,nss_XbyY_args_t * arg)1115 nss_packed_getkey(void *buffer, size_t length, char **dbname,
1116 int *dbop, nss_XbyY_args_t *arg)
1117 {
1118 nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
1119 nss_dbd_t *pdbd;
1120 nssuint_t off, dbdsize;
1121 int index;
1122
1123 if (buffer == NULL || length == 0 || dbop == NULL ||
1124 arg == NULL || dbname == NULL)
1125 return (NSS_ERROR);
1126
1127 *dbop = pbuf->nss_dbop;
1128 off = pbuf->dbd_off;
1129 pdbd = (nss_dbd_t *)((void *)((char *)buffer + off));
1130 dbdsize = pbuf->key_off - pbuf->dbd_off;
1131 if (pdbd->o_name >= dbdsize || pdbd->o_config_name >= dbdsize ||
1132 pdbd->o_default_config >= dbdsize)
1133 return (NSS_ERROR);
1134 *dbname = (char *)buffer + off + pdbd->o_name;
1135 if ((index = nss_dbop_search(*dbname, (uint32_t)*dbop)) < 0)
1136 return (NSS_ERROR);
1137 return (nss_upack_key2arg(buffer, length, dbname, dbop, arg, index));
1138 }
1139
1140
1141 /*
1142 * str2packent: Standard format interposed str2X function for normal APIs
1143 *
1144 * Return values: 0 = success, 1 = parse error, 2 = erange ...
1145 *
1146 * The structure pointer is ignored since this is a nscd side packed request.
1147 * The client side routine does all the real parsing; we just check limits and
1148 * store the entry in the buffer we were passed by the caller.
1149 */
1150
1151 static int
str2packent(const char * instr,int lenstr,void * ent __unused,char * buffer,int buflen)1152 str2packent(
1153 const char *instr,
1154 int lenstr,
1155 void *ent __unused, /* really (char *) */
1156 char *buffer,
1157 int buflen)
1158 {
1159 if (buflen <= lenstr) { /* not enough buffer */
1160 return (NSS_STR_PARSE_ERANGE);
1161 }
1162 (void) memmove(buffer, instr, lenstr);
1163 buffer[lenstr] = '\0';
1164
1165 return (NSS_STR_PARSE_SUCCESS);
1166 }
1167
1168 /*
1169 * Initialize db_root, initf, dbop and arg from a packed buffer
1170 */
1171
1172 nss_status_t
nss_packed_arg_init(void * buffer,size_t length,nss_db_root_t * db_root __unused,nss_db_initf_t * initf,int * dbop,nss_XbyY_args_t * arg)1173 nss_packed_arg_init(void *buffer, size_t length,
1174 nss_db_root_t *db_root __unused,
1175 nss_db_initf_t *initf, int *dbop, nss_XbyY_args_t *arg)
1176 {
1177 nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
1178 nss_str2ent_t s2e = str2packent;
1179 nss_str2ent_t real_s2e = NULL;
1180 nss_dbd_t *pdbd;
1181 nssuint_t off, dbdsize;
1182 char *dbname, *bptr;
1183 size_t len;
1184 int index;
1185
1186 if (buffer == NULL || length == 0 ||
1187 dbop == NULL || arg == NULL)
1188 return (NSS_ERROR);
1189
1190 /* init dbop */
1191 *dbop = pbuf->nss_dbop;
1192 off = pbuf->dbd_off;
1193 pdbd = (nss_dbd_t *)((void *)((char *)buffer + off));
1194 dbdsize = pbuf->key_off - pbuf->dbd_off;
1195 if (pdbd->o_name >= dbdsize || pdbd->o_config_name >= dbdsize ||
1196 pdbd->o_default_config >= dbdsize)
1197 return (NSS_ERROR);
1198 dbname = (char *)buffer + off + pdbd->o_name;
1199 if ((index = nss_dbop_search(dbname, (uint32_t)*dbop)) < 0)
1200 return (NSS_ERROR);
1201
1202 /* db_root is initialized by nscd's based on door info */
1203 /* do nothing here */
1204
1205 /* init key information - (and get dbname dbop etc...) */
1206 if (nss_upack_key2arg(buffer, length, &dbname,
1207 dbop, arg, index) != NSS_SUCCESS)
1208 return (NSS_ERROR);
1209
1210 /* possible audituser init */
1211 if (strcmp(dbname, NSS_DBNAM_AUTHATTR) == 0)
1212 arg->h_errno = (int)pbuf->p_herrno;
1213
1214 bptr = (char *)buffer + pbuf->data_off;
1215 len = (size_t)pbuf->data_len;
1216
1217 /* sidestep odd arg cases */
1218 if (*dbop == NSS_DBOP_GROUP_BYMEMBER &&
1219 strcmp(dbname, NSS_DBNAM_GROUP) == 0) {
1220 /* get initf and str2ent functions */
1221 if (nss_pinit_funcs(index, initf, &real_s2e) != NSS_SUCCESS)
1222 return (NSS_ERROR);
1223 ((struct nss_groupsbymem *)arg)->str2ent = real_s2e;
1224 ((struct nss_groupsbymem *)arg)->process_cstr = process_cstr;
1225 return (NSS_SUCCESS);
1226 }
1227 if (pbuf->nss_dbop == NSS_DBOP_NETGROUP_IN &&
1228 strcmp(dbname, NSS_DBNAM_NETGROUP) == 0) {
1229 return (NSS_SUCCESS);
1230 }
1231
1232 /* get initf and str2ent functions */
1233 if (nss_pinit_funcs(index, initf, NULL) != NSS_SUCCESS)
1234 return (NSS_ERROR);
1235
1236 /* init normal arg cases */
1237 NSS_XbyY_INIT(arg, NULL, bptr, len, s2e);
1238 arg->h_errno = 0;
1239
1240 return (NSS_SUCCESS);
1241 }
1242
1243 /*
1244 * Initialize db_root, initf, dbop, contextp and arg from a packed buffer
1245 */
1246
1247 nss_status_t
nss_packed_context_init(void * buffer,size_t length __unused,nss_db_root_t * db_root __unused,nss_db_initf_t * initf __unused,nss_getent_t ** contextp __unused,nss_XbyY_args_t * arg)1248 nss_packed_context_init(void *buffer, size_t length __unused,
1249 nss_db_root_t *db_root __unused,
1250 nss_db_initf_t *initf __unused, nss_getent_t **contextp __unused,
1251 nss_XbyY_args_t *arg)
1252 {
1253 nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
1254 nss_str2ent_t s2e = str2packent;
1255 char *bptr;
1256 size_t len;
1257
1258 /* init arg */
1259 if (arg != NULL) {
1260 bptr = (char *)buffer + pbuf->data_off;
1261 len = (size_t)pbuf->data_len;
1262 NSS_XbyY_INIT(arg, NULL, bptr, len, s2e);
1263 }
1264
1265 return (NSS_SUCCESS);
1266 }
1267