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