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