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 * "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 ** 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 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 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 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 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 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 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 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 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 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 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