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 * 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 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 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 /*ARGSUSED*/ 390 static nss_status_t 391 nss_pack_key2str(void *buffer, size_t length, nss_XbyY_args_t *arg, 392 const char *dbname, int dbop, size_t *rlen, const char *typestr) 393 { 394 int i, j; 395 size_t len, len2, len3, len4, len5, slop; 396 nssuint_t *uptr, offv, offc; 397 struct nss_setnetgrent_args *sng; 398 struct nss_innetgr_args *ing; 399 struct nss_groupsbymem *gbm; 400 char **cv, *dptr; 401 nss_pnetgr_t *pptr; 402 _priv_execattr *pe; 403 404 if (buffer == NULL || length == 0 || arg == NULL || 405 dbname == NULL || rlen == NULL || typestr == NULL) 406 return (NSS_ERROR); 407 408 while (typestr && *typestr) { 409 switch (*typestr++) { 410 case 'n': 411 if (arg->key.name == NULL) 412 return (NSS_NOTFOUND); 413 len = strlen(arg->key.name) + 1; 414 if (len >= length) 415 return (NSS_ERROR); 416 (void) strlcpy(buffer, arg->key.name, len); 417 *rlen = len; 418 break; 419 case 'N': 420 len = sizeof (nssuint_t); 421 if (len >= length) 422 return (NSS_ERROR); 423 *(nssuint_t *)buffer = (nssuint_t)arg->key.number; 424 *rlen = len; 425 break; 426 case 'u': 427 len = sizeof (nssuint_t); 428 if (len >= length) 429 return (NSS_ERROR); 430 *(nssuint_t *)buffer = (nssuint_t)arg->key.uid; 431 *rlen = len; 432 break; 433 case 'g': 434 len = sizeof (nssuint_t); 435 if (len >= length) 436 return (NSS_ERROR); 437 *(nssuint_t *)buffer = (nssuint_t)arg->key.gid; 438 *rlen = len; 439 break; 440 case 'h': 441 if (arg->key.hostaddr.addr == NULL) 442 return (-1); 443 len = arg->key.hostaddr.len; 444 len = ROUND_UP(len, sizeof (nssuint_t)); 445 len2 = (sizeof (nssuint_t) * 2) + len; 446 if (len2 >= length) 447 return (NSS_ERROR); 448 *(nssuint_t *)buffer = 449 (nssuint_t)arg->key.hostaddr.len; 450 buffer = (void *)((char *)buffer + sizeof (nssuint_t)); 451 *(nssuint_t *)buffer = 452 (nssuint_t)arg->key.hostaddr.type; 453 buffer = (void *)((char *)buffer + sizeof (nssuint_t)); 454 (void) memcpy(buffer, arg->key.hostaddr.addr, 455 arg->key.hostaddr.len); 456 *rlen = len2; 457 break; 458 case 'i': 459 if (arg->key.ipnode.name == NULL) 460 return (NSS_NOTFOUND); 461 len = strlen(arg->key.ipnode.name) + 1; 462 len = ROUND_UP(len, sizeof (nssuint_t)); 463 len2 = (sizeof (nssuint_t) * 2) + len; 464 if (len2 >= length) 465 return (NSS_ERROR); 466 *(nssuint_t *)buffer = 467 (nssuint_t)arg->key.ipnode.af_family; 468 buffer = (void *)((char *)buffer + sizeof (nssuint_t)); 469 *(nssuint_t *)buffer = 470 (nssuint_t)arg->key.ipnode.flags; 471 buffer = (void *)((char *)buffer + sizeof (nssuint_t)); 472 (void) strlcpy(buffer, arg->key.ipnode.name, len); 473 *rlen = len2; 474 break; 475 case 'p': 476 len = sizeof (nssuint_t); 477 if (len >= length) 478 return (NSS_ERROR); 479 *(nssuint_t *)buffer = (nssuint_t)arg->key.projid; 480 *rlen = len; 481 break; 482 case 's': 483 if (arg->key.serv.serv.name == NULL) 484 return (NSS_NOTFOUND); 485 len = strlen(arg->key.serv.serv.name) + 1; 486 len2 = 1; 487 if (arg->key.serv.proto != NULL) 488 len2 += strlen(arg->key.serv.proto); 489 len3 = len + len2; 490 len3 = ROUND_UP(len3, sizeof (nssuint_t)); 491 if (len3 >= length) 492 return (NSS_ERROR); 493 (void) strlcpy(buffer, arg->key.serv.serv.name, len); 494 buffer = (void *)((char *)buffer + len); 495 if (len2 > 1) 496 (void) strlcpy(buffer, arg->key.serv.proto, 497 len2); 498 else 499 *(char *)buffer = '\0'; 500 *rlen = len3; 501 break; 502 case 'S': 503 len2 = 0; 504 if (arg->key.serv.proto != NULL) 505 len2 = strlen(arg->key.serv.proto) + 1; 506 len = sizeof (nssuint_t) + len2; 507 if (len >= length) 508 return (NSS_ERROR); 509 uptr = (nssuint_t *)buffer; 510 *uptr++ = (nssuint_t)arg->key.serv.serv.port; 511 if (len2) { 512 (void) strlcpy((char *)uptr, 513 arg->key.serv.proto, len2); 514 } 515 *rlen = len; 516 break; 517 case 'e': 518 if (arg->key.ether == NULL) 519 return (NSS_NOTFOUND); 520 len = sizeof (struct ether_addr); 521 len = ROUND_UP(len, sizeof (nssuint_t)); 522 if (len >= length) 523 return (NSS_ERROR); 524 *(struct ether_addr *)buffer = 525 *(struct ether_addr *)arg->key.ether; 526 *rlen = len; 527 break; 528 case 'k': 529 if (arg->key.pkey.name == NULL || 530 arg->key.pkey.keytype == NULL) 531 return (NSS_NOTFOUND); 532 len = strlen(arg->key.pkey.name) + 1; 533 len2 = strlen(arg->key.pkey.keytype) + 1; 534 len3 = len + len2; 535 len3 = ROUND_UP(len3, sizeof (nssuint_t)); 536 if (len3 >= length) 537 return (NSS_ERROR); 538 (void) strlcpy(buffer, arg->key.pkey.name, len); 539 buffer = (void *)((char *)buffer + len); 540 (void) strlcpy(buffer, arg->key.pkey.keytype, len2); 541 *rlen = len3; 542 break; 543 case 'a': 544 uptr = (nssuint_t *)buffer; 545 len = sizeof (nssuint_t) * 2; 546 if (len >= length) 547 return (NSS_ERROR); 548 *uptr++ = (nssuint_t)arg->key.netaddr.net; 549 *uptr++ = (nssuint_t)arg->key.netaddr.type; 550 *rlen = len; 551 break; 552 case 'A': 553 pe = (_priv_execattr *)(arg->key.attrp); 554 if (pe == NULL) 555 return (NSS_NOTFOUND); 556 /* for search flag */ 557 len = sizeof (nssuint_t); 558 /* for sizeof (_priv_execattr) static buffer */ 559 /* Plus lots of slop just in case... */ 560 slop = sizeof (nssuint_t) * 16; 561 len += slop; 562 563 len2 = len3 = len4 = len5 = 1; 564 if (pe->name != NULL) 565 len2 = strlen(pe->name) + 1; 566 if (pe->type != NULL) 567 len3 = strlen(pe->type) + 1; 568 if (pe->id != NULL) 569 len4 = strlen(pe->id) + 1; 570 if (pe->policy != NULL) 571 len5 = strlen(pe->policy) + 1; 572 /* head_exec, prev_exec - are client side only... */ 573 len += len2 + len3 + len4 + len5; 574 len = ROUND_UP(len, sizeof (nssuint_t)); 575 if (len >= length) 576 return (NSS_ERROR); 577 (void) memset((void *)buffer, 0, slop); 578 uptr = (nssuint_t *)((void *)((char *)buffer + slop)); 579 *uptr++ = (nssuint_t)pe->search_flag; 580 dptr = (char *)uptr; 581 if (len2 == 1) 582 *dptr++ = '\0'; 583 else { 584 (void) strlcpy(dptr, pe->name, len2); 585 dptr += len2; 586 } 587 if (len3 == 1) 588 *dptr++ = '\0'; 589 else { 590 (void) strlcpy(dptr, pe->type, len3); 591 dptr += len3; 592 } 593 if (len4 == 1) 594 *dptr++ = '\0'; 595 else { 596 (void) strlcpy(dptr, pe->id, len4); 597 dptr += len4; 598 } 599 if (len5 == 1) 600 *dptr++ = '\0'; 601 else 602 (void) strlcpy(dptr, pe->policy, len5); 603 *rlen = len; 604 break; 605 case 'I': 606 gbm = (struct nss_groupsbymem *)arg; 607 if (gbm->username == NULL) 608 return (NSS_NOTFOUND); 609 len = strlen(gbm->username) + 1; 610 len2 = sizeof (nssuint_t) * 4; 611 len2 += ROUND_UP(len, sizeof (nssuint_t)); 612 if (len2 >= length) 613 return (NSS_ERROR); 614 uptr = (nssuint_t *)buffer; 615 *uptr++ = (nssuint_t)gbm->force_slow_way; 616 *uptr++ = (nssuint_t)gbm->maxgids; 617 *uptr++ = (nssuint_t)gbm->numgids; 618 if (gbm->numgids == 1) { 619 *uptr++ = (nssuint_t)gbm->gid_array[0]; 620 } else { 621 *uptr++ = (nssuint_t)0; 622 } 623 (void) strlcpy((void *)uptr, gbm->username, len); 624 *rlen = len2; 625 break; 626 case 't': 627 pptr = (nss_pnetgr_t *)buffer; 628 ing = (struct nss_innetgr_args *)arg; 629 len = sizeof (nss_pnetgr_t); 630 len2 = ing->arg[NSS_NETGR_MACHINE].argc + 631 ing->arg[NSS_NETGR_USER].argc + 632 ing->arg[NSS_NETGR_DOMAIN].argc + 633 ing->groups.argc; 634 len2 *= sizeof (nssuint_t); 635 len3 = 0; 636 for (j = 0; j < NSS_NETGR_N; j++) { 637 cv = ing->arg[j].argv; 638 for (i = ing->arg[j].argc; --i >= 0; ) { 639 if (*cv) 640 len3 += strlen(*cv++) + 1; 641 } 642 } 643 cv = ing->groups.argv; 644 for (i = ing->groups.argc; --i >= 0; ) { 645 if (*cv) 646 len3 += strlen(*cv++) + 1; 647 } 648 len3 = ROUND_UP(len3, sizeof (nssuint_t)); 649 /* 650 * Double argv space. Reason: 651 * First 1/2 offsets 652 * Second 1/2 for client side pointer arrays 653 * resolves malloc/free issues with unpacked argvs 654 */ 655 if ((len + (len2 << 1) + len3) >= length) 656 return (NSS_ERROR); 657 *rlen = len + (len2 << 1) + len3; 658 659 pptr->machine_argc = ing->arg[NSS_NETGR_MACHINE].argc; 660 pptr->user_argc = ing->arg[NSS_NETGR_USER].argc; 661 pptr->domain_argc = ing->arg[NSS_NETGR_DOMAIN].argc; 662 pptr->groups_argc = ing->groups.argc; 663 offv = len; 664 uptr = (nssuint_t *)((void *)((char *)buffer + offv)); 665 offc = len + (len2 << 1); 666 dptr = (char *)buffer + offc; 667 if (pptr->machine_argc == 0) { 668 pptr->machine_offv = (nssuint_t)0; 669 } else { 670 pptr->machine_offv = offv; 671 cv = ing->arg[NSS_NETGR_MACHINE].argv; 672 i = pptr->machine_argc; 673 offv += sizeof (nssuint_t) * i; 674 for (; --i >= 0; ) { 675 *uptr++ = offc; 676 len3 = strlen(*cv) + 1; 677 (void) strlcpy(dptr, *cv++, len3); 678 offc += len3; 679 dptr += len3; 680 } 681 } 682 if (pptr->user_argc == 0) { 683 pptr->user_offv = (nssuint_t)0; 684 } else { 685 pptr->user_offv = offv; 686 cv = ing->arg[NSS_NETGR_USER].argv; 687 i = pptr->user_argc; 688 offv += sizeof (nssuint_t) * i; 689 for (; --i >= 0; ) { 690 *uptr++ = offc; 691 len3 = strlen(*cv) + 1; 692 (void) strlcpy(dptr, *cv++, len3); 693 offc += len3; 694 dptr += len3; 695 } 696 } 697 if (pptr->domain_argc == 0) { 698 pptr->domain_offv = (nssuint_t)0; 699 } else { 700 pptr->domain_offv = offv; 701 cv = ing->arg[NSS_NETGR_DOMAIN].argv; 702 i = pptr->domain_argc; 703 offv += sizeof (nssuint_t) * i; 704 for (; --i >= 0; ) { 705 *uptr++ = offc; 706 len3 = strlen(*cv) + 1; 707 (void) strlcpy(dptr, *cv++, len3); 708 offc += len3; 709 dptr += len3; 710 } 711 } 712 if (pptr->groups_argc == 0) { 713 pptr->groups_offv = (nssuint_t)0; 714 } else { 715 pptr->groups_offv = offv; 716 cv = ing->groups.argv; 717 i = pptr->groups_argc; 718 offv += sizeof (nssuint_t) * i; 719 for (; --i >= 0; ) { 720 *uptr++ = offc; 721 len3 = strlen(*cv) + 1; 722 (void) strlcpy(dptr, *cv++, len3); 723 offc += len3; 724 dptr += len3; 725 } 726 } 727 break; 728 case 'T': 729 sng = (struct nss_setnetgrent_args *)arg; 730 if (sng->netgroup == NULL) 731 return (NSS_NOTFOUND); 732 len = strlen(sng->netgroup) + 1; 733 if (len >= length) 734 return (NSS_ERROR); 735 (void) strlcpy(buffer, sng->netgroup, len); 736 *rlen = len; 737 break; 738 default: 739 return (NSS_ERROR); 740 } 741 } 742 return (NSS_SUCCESS); 743 } 744 745 nss_status_t 746 nss_default_key2str(void *buffer, size_t length, nss_XbyY_args_t *arg, 747 const char *dbname, int dbop, size_t *rlen) 748 { 749 int index; 750 751 if (buffer == NULL || length == 0 || arg == NULL || 752 dbname == NULL || rlen == NULL) 753 return (NSS_ERROR); 754 755 /* 756 * If this is not one of the well known getXbyYs 757 * (IE _printers special processing etc.) use a 758 * local (non-nscd) getXbyY lookup. 759 */ 760 if ((index = nss_dbop_search(dbname, (uint32_t)dbop)) < 0) 761 return (NSS_TRYLOCAL); 762 763 return (nss_pack_key2str(buffer, length, arg, dbname, 764 dbop, rlen, getXbyY_to_dbop[index].tostr)); 765 } 766 767 /*ARGSUSED*/ 768 void 769 nss_packed_set_status(void *buffer, size_t length, nss_status_t status, 770 nss_XbyY_args_t *arg) 771 { 772 nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 773 nss_dbd_t *pdbd; 774 char *dbn; 775 776 /* sidestep odd cases */ 777 pdbd = (nss_dbd_t *)((void *)((char *)buffer + pbuf->dbd_off)); 778 dbn = (char *)pdbd + pdbd->o_name; 779 if (pbuf->nss_dbop == NSS_DBOP_GROUP_BYMEMBER) { 780 if (strcmp(dbn, NSS_DBNAM_GROUP) == 0) { 781 struct nss_groupsbymem *in = 782 (struct nss_groupsbymem *)arg; 783 784 if (in->numgids >= 0) { 785 pbuf->p_status = NSS_SUCCESS; 786 pbuf->data_len = in->numgids * 787 sizeof (gid_t); 788 pbuf->p_herrno = 0; 789 } else { 790 pbuf->p_status = status; 791 pbuf->p_errno = errno; 792 pbuf->data_len = 0; 793 pbuf->p_herrno = (uint32_t)arg->h_errno; 794 } 795 return; 796 } 797 } 798 if (pbuf->nss_dbop == NSS_DBOP_NETGROUP_IN) { 799 if (strcmp(dbn, NSS_DBNAM_NETGROUP) == 0) { 800 struct nss_innetgr_args *in = 801 (struct nss_innetgr_args *)arg; 802 803 /* tell nss_unpack() operation is successful */ 804 pbuf->data_len = 1; 805 806 if (status != NSS_SUCCESS && status != NSS_NOTFOUND) { 807 pbuf->p_status = status; 808 pbuf->p_errno = errno; 809 return; 810 } 811 812 if (in->status == NSS_NETGR_FOUND) { 813 pbuf->p_status = NSS_SUCCESS; 814 } else { 815 pbuf->p_status = NSS_NOTFOUND; 816 pbuf->p_errno = errno; 817 } 818 return; 819 } 820 } 821 822 /* process normal cases */ 823 if ((pbuf->p_status = status) != NSS_SUCCESS) { 824 if (arg->erange == 1) 825 pbuf->p_errno = ERANGE; 826 else 827 pbuf->p_errno = errno; 828 } else 829 pbuf->p_errno = 0; 830 if (arg != NULL) { 831 pbuf->p_herrno = (uint32_t)arg->h_errno; 832 pbuf->data_len = (nssuint_t)arg->returnlen; 833 } else { 834 pbuf->p_herrno = 0; 835 pbuf->data_len = 0; 836 } 837 } 838 839 /* 840 * nss_upack_key2arg 841 * Private string to key unpacking function for getXbyY routines 842 * This routine performs a scanf/printf like parse over the packed 843 * string, to uppack and re-assemble the key in the args structure. 844 * 845 * buffer - Start of the key buffer location [in packed buffer] 846 * length - Length of key buffer component 847 * Key offsets are relative to start of key buffer location. 848 * 849 * Unpack fields Key 850 * key.name n 851 * key.number N 852 * key.uid u 853 * key.gid g 854 * key.hostaddr h 855 * key.ipnode i 856 * key.projid p 857 * key.serv(name) s 858 * key.serv(port) S 859 * key.ether e 860 * key.pkey k 861 * key.netaddr a 862 * key.attrp A 863 * groupsbymember I 864 * innetgr_args t 865 * setnetgr_args T 866 * Assumes arguments are all valid 867 */ 868 869 /*ARGSUSED*/ 870 static nss_status_t 871 nss_upack_key2arg(void *buffer, size_t length, char **dbname, 872 int *dbop, nss_XbyY_args_t *arg, int index) 873 { 874 nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 875 const char *strtype = NULL; 876 nssuint_t off, *uptr, keysize; 877 size_t len, slop; 878 int i, j; 879 char **cv, *bptr; 880 struct nss_setnetgrent_args *sng; 881 struct nss_innetgr_args *ing; 882 struct nss_groupsbymem *gbm; 883 nss_pnetgr_t *pptr; 884 _priv_execattr *pe; 885 886 /* keysize is length of the key area */ 887 keysize = pbuf->data_off - pbuf->key_off; 888 889 off = pbuf->key_off; 890 bptr = (char *)buffer + off; 891 uptr = (nssuint_t *)((void *)bptr); 892 strtype = getXbyY_to_dbop[index].tostr; 893 if (strtype == NULL) 894 return (NSS_ERROR); 895 while (*strtype) { 896 switch (*strtype++) { 897 case 'n': 898 arg->key.name = (const char *)bptr; 899 break; 900 case 'N': 901 arg->key.number = (int)(*uptr); 902 break; 903 case 'u': 904 arg->key.uid = (uid_t)(*uptr); 905 break; 906 case 'g': 907 arg->key.gid = (gid_t)(*uptr); 908 break; 909 case 'h': 910 arg->key.hostaddr.len = (int)(*uptr++); 911 arg->key.hostaddr.type = (int)(*uptr++); 912 arg->key.hostaddr.addr = (const char *)uptr; 913 break; 914 case 'i': 915 arg->key.ipnode.af_family = (int)(*uptr++); 916 arg->key.ipnode.flags = (int)(*uptr++); 917 arg->key.ipnode.name = (const char *)uptr; 918 break; 919 case 'p': 920 arg->key.projid = (projid_t)(*uptr); 921 break; 922 case 's': 923 arg->key.serv.serv.name = (const char *)bptr; 924 len = strlen(arg->key.serv.serv.name) + 1; 925 bptr += len; 926 if (*(const char *)bptr == '\0') 927 arg->key.serv.proto = NULL; 928 else 929 arg->key.serv.proto = (const char *)bptr; 930 break; 931 case 'S': 932 arg->key.serv.serv.port = (int)(*uptr++); 933 if (pbuf->key_len == sizeof (nssuint_t)) { 934 arg->key.serv.proto = NULL; 935 } else { 936 bptr += sizeof (nssuint_t); 937 arg->key.serv.proto = (const char *)bptr; 938 } 939 break; 940 case 'e': 941 arg->key.ether = bptr; 942 break; 943 case 'k': 944 arg->key.pkey.name = (const char *)bptr; 945 len = strlen(arg->key.pkey.name) + 1; 946 bptr += len; 947 arg->key.pkey.keytype = (const char *)bptr; 948 break; 949 case 'a': 950 arg->key.netaddr.net = (uint32_t)(*uptr++); 951 arg->key.netaddr.type = (int)(*uptr++); 952 break; 953 case 'A': 954 pe = (_priv_execattr *)((void *)bptr); 955 /* use slop space as priv_execattr structure */ 956 arg->key.attrp = (void *)pe; 957 /* skip over slop ... */ 958 slop = sizeof (nssuint_t) * 16; 959 uptr = (nssuint_t *)((void *)((char *)bptr + slop)); 960 pe->search_flag = (int)*uptr++; 961 bptr = (char *)uptr; 962 if (*bptr == '\0') { 963 pe->name = NULL; 964 bptr++; 965 } else { 966 pe->name = (char *)bptr; 967 bptr += strlen(pe->name) + 1; 968 } 969 if (*bptr == '\0') { 970 pe->type = NULL; 971 bptr++; 972 } else { 973 pe->type = (char *)bptr; 974 bptr += strlen(pe->type) + 1; 975 } 976 if (*bptr == '\0') { 977 pe->id = NULL; 978 bptr++; 979 } else { 980 pe->id = (char *)bptr; 981 bptr += strlen(pe->id) + 1; 982 } 983 if (*bptr == '\0') { 984 pe->policy = NULL; 985 } else { 986 pe->policy = (char *)bptr; 987 } 988 pe->head_exec = NULL; 989 pe->prev_exec = NULL; 990 break; 991 case 'I': 992 gbm = (struct nss_groupsbymem *)arg; 993 gbm->gid_array = (gid_t *) 994 ((void *)((char *)pbuf + pbuf->data_off)); 995 gbm->force_slow_way = (int)(*uptr++); 996 gbm->maxgids = (int)(*uptr++); 997 gbm->numgids = (int)(*uptr++); 998 if (gbm->numgids == 1) { 999 /* insert initial group into data area */ 1000 gbm->gid_array[0] = (gid_t)(*uptr++); 1001 } else 1002 uptr++; 1003 gbm->username = (const char *)uptr; 1004 break; 1005 case 't': 1006 pptr = (nss_pnetgr_t *)((void *)bptr); 1007 ing = (struct nss_innetgr_args *)arg; 1008 ing->arg[NSS_NETGR_MACHINE].argc = pptr->machine_argc; 1009 ing->arg[NSS_NETGR_USER].argc = pptr->user_argc; 1010 ing->arg[NSS_NETGR_DOMAIN].argc = pptr->domain_argc; 1011 ing->groups.argc = pptr->groups_argc; 1012 1013 /* 1014 * Start of argv pointer storage 1015 */ 1016 off = ing->arg[NSS_NETGR_MACHINE].argc + 1017 ing->arg[NSS_NETGR_USER].argc + 1018 ing->arg[NSS_NETGR_DOMAIN].argc + 1019 ing->groups.argc; 1020 off *= sizeof (nssuint_t); 1021 off += sizeof (nss_pnetgr_t); 1022 1023 cv = (char **)((void *)(bptr + off)); 1024 uptr = (nssuint_t *) 1025 ((void *)(bptr + sizeof (nss_pnetgr_t))); 1026 for (j = 0; j < NSS_NETGR_N; j++) { 1027 ing->arg[j].argv = cv; 1028 for (i = 0; i < ing->arg[j].argc; i++) { 1029 if (*uptr >= keysize) 1030 return (NSS_ERROR); 1031 *cv++ = (bptr + *uptr++); 1032 } 1033 } 1034 ing->groups.argv = cv; 1035 for (i = 0; i < ing->groups.argc; i++) { 1036 if (*uptr >= keysize) 1037 return (NSS_ERROR); 1038 *cv++ = (bptr + *uptr++); 1039 } 1040 break; 1041 case 'T': 1042 sng = (struct nss_setnetgrent_args *)arg; 1043 sng->netgroup = (const char *)bptr; 1044 sng->iterator = 0; 1045 break; 1046 1047 default: 1048 return (NSS_ERROR); 1049 } 1050 } 1051 return (NSS_SUCCESS); 1052 } 1053 1054 static nss_status_t 1055 nss_pinit_funcs(int index, nss_db_initf_t *initf, nss_str2ent_t *s2e) 1056 { 1057 const char *name; 1058 void *htmp = NULL; 1059 void *sym; 1060 static void *handle = NULL; 1061 static mutex_t handle_lock = DEFAULTMUTEX; 1062 static mutex_t initf_lock = DEFAULTMUTEX; 1063 static mutex_t s2e_lock = DEFAULTMUTEX; 1064 1065 if (handle == NULL) { 1066 htmp = dlopen((const char *)0, RTLD_LAZY); 1067 1068 lmutex_lock(&handle_lock); 1069 if (handle == NULL) { 1070 if (htmp == NULL) { 1071 lmutex_unlock(&handle_lock); 1072 return (NSS_ERROR); 1073 } else { 1074 membar_producer(); 1075 handle = htmp; 1076 htmp = NULL; 1077 } 1078 } 1079 lmutex_unlock(&handle_lock); 1080 if (htmp) 1081 (void) dlclose(htmp); 1082 } 1083 membar_consumer(); 1084 1085 if (initf) { 1086 if (getXbyY_to_dbop[index].initfnp == NULL) { 1087 name = getXbyY_to_dbop[index].initfn; 1088 if ((sym = dlsym(handle, name)) == NULL) 1089 return (NSS_ERROR); 1090 lmutex_lock(&initf_lock); 1091 if (getXbyY_to_dbop[index].initfnp == NULL) 1092 getXbyY_to_dbop[index].initfnp = sym; 1093 membar_producer(); 1094 lmutex_unlock(&initf_lock); 1095 } 1096 membar_consumer(); 1097 *initf = (nss_db_initf_t)getXbyY_to_dbop[index].initfnp; 1098 } 1099 if (s2e) { 1100 if (getXbyY_to_dbop[index].strfnp == NULL) { 1101 name = getXbyY_to_dbop[index].strfn; 1102 if ((sym = dlsym(handle, name)) == NULL) 1103 return (NSS_ERROR); 1104 lmutex_lock(&s2e_lock); 1105 if (getXbyY_to_dbop[index].strfnp == NULL) 1106 getXbyY_to_dbop[index].strfnp = sym; 1107 membar_producer(); 1108 lmutex_unlock(&s2e_lock); 1109 } 1110 membar_consumer(); 1111 *s2e = (nss_str2ent_t)getXbyY_to_dbop[index].strfnp; 1112 } 1113 1114 return (NSS_SUCCESS); 1115 } 1116 1117 nss_status_t 1118 nss_packed_getkey(void *buffer, size_t length, char **dbname, 1119 int *dbop, nss_XbyY_args_t *arg) 1120 { 1121 nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 1122 nss_dbd_t *pdbd; 1123 nssuint_t off, dbdsize; 1124 int index; 1125 1126 if (buffer == NULL || length == 0 || dbop == NULL || 1127 arg == NULL || dbname == NULL) 1128 return (NSS_ERROR); 1129 1130 *dbop = pbuf->nss_dbop; 1131 off = pbuf->dbd_off; 1132 pdbd = (nss_dbd_t *)((void *)((char *)buffer + off)); 1133 dbdsize = pbuf->key_off - pbuf->dbd_off; 1134 if (pdbd->o_name >= dbdsize || pdbd->o_config_name >= dbdsize || 1135 pdbd->o_default_config >= dbdsize) 1136 return (NSS_ERROR); 1137 *dbname = (char *)buffer + off + pdbd->o_name; 1138 if ((index = nss_dbop_search(*dbname, (uint32_t)*dbop)) < 0) 1139 return (NSS_ERROR); 1140 return (nss_upack_key2arg(buffer, length, dbname, dbop, arg, index)); 1141 } 1142 1143 1144 /* 1145 * str2packent: Standard format interposed str2X function for normal APIs 1146 * 1147 * Return values: 0 = success, 1 = parse error, 2 = erange ... 1148 * 1149 * The structure pointer is ignored since this is a nscd side packed request. 1150 * The client side routine does all the real parsing; we just check limits and 1151 * store the entry in the buffer we were passed by the caller. 1152 */ 1153 1154 /*ARGSUSED*/ 1155 static int 1156 str2packent( 1157 const char *instr, 1158 int lenstr, 1159 void *ent, /* really (char *) */ 1160 char *buffer, 1161 int buflen 1162 ) 1163 { 1164 if (buflen <= lenstr) { /* not enough buffer */ 1165 return (NSS_STR_PARSE_ERANGE); 1166 } 1167 (void) memmove(buffer, instr, lenstr); 1168 buffer[lenstr] = '\0'; 1169 1170 return (NSS_STR_PARSE_SUCCESS); 1171 } 1172 1173 /* 1174 * Initialize db_root, initf, dbop and arg from a packed buffer 1175 */ 1176 1177 /*ARGSUSED*/ 1178 nss_status_t 1179 nss_packed_arg_init(void *buffer, size_t length, nss_db_root_t *db_root, 1180 nss_db_initf_t *initf, int *dbop, nss_XbyY_args_t *arg) 1181 { 1182 nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 1183 nss_str2ent_t s2e = str2packent; 1184 nss_str2ent_t real_s2e = NULL; 1185 nss_dbd_t *pdbd; 1186 nssuint_t off, dbdsize; 1187 char *dbname, *bptr; 1188 size_t len; 1189 int index; 1190 1191 if (buffer == NULL || length == 0 || 1192 dbop == NULL || arg == NULL) 1193 return (NSS_ERROR); 1194 1195 /* init dbop */ 1196 *dbop = pbuf->nss_dbop; 1197 off = pbuf->dbd_off; 1198 pdbd = (nss_dbd_t *)((void *)((char *)buffer + off)); 1199 dbdsize = pbuf->key_off - pbuf->dbd_off; 1200 if (pdbd->o_name >= dbdsize || pdbd->o_config_name >= dbdsize || 1201 pdbd->o_default_config >= dbdsize) 1202 return (NSS_ERROR); 1203 dbname = (char *)buffer + off + pdbd->o_name; 1204 if ((index = nss_dbop_search(dbname, (uint32_t)*dbop)) < 0) 1205 return (NSS_ERROR); 1206 1207 /* db_root is initialized by nscd's based on door info */ 1208 /* do nothing here */ 1209 1210 /* init key information - (and get dbname dbop etc...) */ 1211 if (nss_upack_key2arg(buffer, length, &dbname, 1212 dbop, arg, index) != NSS_SUCCESS) 1213 return (NSS_ERROR); 1214 1215 /* possible audituser init */ 1216 if (strcmp(dbname, NSS_DBNAM_AUTHATTR) == 0) 1217 arg->h_errno = (int)pbuf->p_herrno; 1218 1219 bptr = (char *)buffer + pbuf->data_off; 1220 len = (size_t)pbuf->data_len; 1221 1222 /* sidestep odd arg cases */ 1223 if (*dbop == NSS_DBOP_GROUP_BYMEMBER && 1224 strcmp(dbname, NSS_DBNAM_GROUP) == 0) { 1225 /* get initf and str2ent functions */ 1226 if (nss_pinit_funcs(index, initf, &real_s2e) != NSS_SUCCESS) 1227 return (NSS_ERROR); 1228 ((struct nss_groupsbymem *)arg)->str2ent = real_s2e; 1229 ((struct nss_groupsbymem *)arg)->process_cstr = process_cstr; 1230 return (NSS_SUCCESS); 1231 } 1232 if (pbuf->nss_dbop == NSS_DBOP_NETGROUP_IN && 1233 strcmp(dbname, NSS_DBNAM_NETGROUP) == 0) { 1234 return (NSS_SUCCESS); 1235 } 1236 1237 /* get initf and str2ent functions */ 1238 if (nss_pinit_funcs(index, initf, NULL) != NSS_SUCCESS) 1239 return (NSS_ERROR); 1240 1241 /* init normal arg cases */ 1242 NSS_XbyY_INIT(arg, NULL, bptr, len, s2e); 1243 arg->h_errno = 0; 1244 1245 return (NSS_SUCCESS); 1246 } 1247 1248 /* 1249 * Initialize db_root, initf, dbop, contextp and arg from a packed buffer 1250 */ 1251 1252 /*ARGSUSED*/ 1253 nss_status_t 1254 nss_packed_context_init(void *buffer, size_t length, nss_db_root_t *db_root, 1255 nss_db_initf_t *initf, nss_getent_t **contextp, 1256 nss_XbyY_args_t *arg) 1257 { 1258 nss_pheader_t *pbuf = (nss_pheader_t *)buffer; 1259 nss_str2ent_t s2e = str2packent; 1260 char *bptr; 1261 size_t len; 1262 1263 /* init arg */ 1264 if (arg != NULL) { 1265 bptr = (char *)buffer + pbuf->data_off; 1266 len = (size_t)pbuf->data_len; 1267 NSS_XbyY_INIT(arg, NULL, bptr, len, s2e); 1268 } 1269 1270 return (NSS_SUCCESS); 1271 } 1272