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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
33 #include <nss_dbdefs.h>
39 /* headers for key2str/str2key routines */
40 #include <sys/ethernet.h>
41 #include <exec_attr.h>
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.
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.
57 #define ALIGN(x) ((((long)(x)) + sizeof (long) - 1) & ~(sizeof (long) - 1))
60 _nss_XbyY_buf_alloc(int struct_size
, int buffer_size
)
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
);
70 b
->result
= (void *)ALIGN(&b
[1]);
71 b
->buffer
= (char *)(b
->result
) + struct_size
;
72 b
->buflen
= buffer_size
;
77 _nss_XbyY_buf_free(nss_XbyY_buf_t
*b
)
84 /* === Comment: used by fget{gr,pw,sp}ent */
85 /* ==== Should do ye olde syslog()ing of suspiciously long lines */
88 _nss_XbyY_fgets(FILE *f
, nss_XbyY_args_t
*b
)
93 if (fgets(buf
, LINE_MAX
, f
) == 0) {
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') {
112 /* case where the file is not terminated with a Newline */
115 parsestat
= (*b
->str2ent
)(buf
, (len
- 1), b
->buf
.result
, b
->buf
.buffer
,
117 if (parsestat
== NSS_STR_PARSE_ERANGE
) {
120 } else if (parsestat
== NSS_STR_PARSE_SUCCESS
) {
121 b
->returnval
= b
->buf
.result
;
126 * parse the aliases string into the buffer and if successful return
127 * a char ** pointer to the beginning of the aliases.
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.
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 */
140 * Build the alias-list in the start of the buffer, and copy
141 * the strings to the end of the buffer.
144 *instr_limit
= instr
+ lenstr
;
145 char *copyptr
= buffer
+ buflen
;
146 char **aliasp
= (char **)ROUND_UP(buffer
, sizeof (*aliasp
));
147 char **alias_start
= aliasp
;
151 const char *str_start
;
154 while (instr
< instr_limit
&& isspace(*instr
)) {
157 if (instr
>= instr_limit
|| *instr
== '#') {
161 while (instr
< instr_limit
&& !isspace(*instr
)) {
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. */
176 (void) memcpy(copyptr
, str_start
, str_len
);
177 copyptr
[str_len
] = '\0';
180 return (alias_start
);
184 extern nss_status_t
process_cstr(const char *, int, struct nss_groupsbymem
*);
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.
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 */
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) }
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) }
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) }
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) }
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) }
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) }
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.
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
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.
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;
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().
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",
291 NSS_MK_GETXYDBOP(USERATTR
, BYNAME
, "userattr", "n"),
295 nss_dbop_search(const char *name
, uint32_t dbop
)
297 getXbyY_to_dbop_t
*hptr
;
298 int count
= (sizeof (getXbyY_to_dbop
) / sizeof (getXbyY_to_dbop_t
));
302 static const uint32_t hbits_tst
= 0xf0000000;
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
;
312 hval
= (hval
<< 4) + *cp
++;
313 if ((g
= (hval
& hbits_tst
)) != 0)
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
);
324 getXbyYdbopHASH
[hval
] = i
| DBOP_HASH_TAG
;
327 getXbyYdbop_hashed
= 1;
329 lmutex_unlock(&getXbydbop_hash_lock
);
335 hval
= (hval
<< 4) + *cp
++;
336 if ((g
= (hval
& hbits_tst
)) != 0)
341 hval
%= DBOP_PRIME_HASH
;
342 idx
= getXbyYdbopHASH
[hval
];
343 if ((idx
& DBOP_HASH_TAG
) != DBOP_HASH_TAG
)
345 idx
&= ~DBOP_HASH_TAG
;
348 hptr
= &getXbyY_to_dbop
[idx
];
349 if (hptr
->dbop
!= dbop
|| strcmp(name
, hptr
->name
) != 0)
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.
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.
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
)
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
;
401 if (buffer
== NULL
|| length
== 0 || arg
== NULL
||
402 dbname
== NULL
|| rlen
== NULL
|| typestr
== NULL
)
405 while (typestr
&& *typestr
) {
406 switch (*typestr
++) {
408 if (arg
->key
.name
== NULL
)
409 return (NSS_NOTFOUND
);
410 len
= strlen(arg
->key
.name
) + 1;
413 (void) strlcpy(buffer
, arg
->key
.name
, len
);
417 len
= sizeof (nssuint_t
);
420 *(nssuint_t
*)buffer
= (nssuint_t
)arg
->key
.number
;
424 len
= sizeof (nssuint_t
);
427 *(nssuint_t
*)buffer
= (nssuint_t
)arg
->key
.uid
;
431 len
= sizeof (nssuint_t
);
434 *(nssuint_t
*)buffer
= (nssuint_t
)arg
->key
.gid
;
438 if (arg
->key
.hostaddr
.addr
== NULL
)
440 len
= arg
->key
.hostaddr
.len
;
441 len
= ROUND_UP(len
, sizeof (nssuint_t
));
442 len2
= (sizeof (nssuint_t
) * 2) + len
;
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
);
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
;
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
);
473 len
= sizeof (nssuint_t
);
476 *(nssuint_t
*)buffer
= (nssuint_t
)arg
->key
.projid
;
480 if (arg
->key
.serv
.serv
.name
== NULL
)
481 return (NSS_NOTFOUND
);
482 len
= strlen(arg
->key
.serv
.serv
.name
) + 1;
484 if (arg
->key
.serv
.proto
!= NULL
)
485 len2
+= strlen(arg
->key
.serv
.proto
);
487 len3
= ROUND_UP(len3
, sizeof (nssuint_t
));
490 (void) strlcpy(buffer
, arg
->key
.serv
.serv
.name
, len
);
491 buffer
= (void *)((char *)buffer
+ len
);
493 (void) strlcpy(buffer
, arg
->key
.serv
.proto
,
496 *(char *)buffer
= '\0';
501 if (arg
->key
.serv
.proto
!= NULL
)
502 len2
= strlen(arg
->key
.serv
.proto
) + 1;
503 len
= sizeof (nssuint_t
) + len2
;
506 uptr
= (nssuint_t
*)buffer
;
507 *uptr
++ = (nssuint_t
)arg
->key
.serv
.serv
.port
;
509 (void) strlcpy((char *)uptr
,
510 arg
->key
.serv
.proto
, len2
);
515 if (arg
->key
.ether
== NULL
)
516 return (NSS_NOTFOUND
);
517 len
= sizeof (struct ether_addr
);
518 len
= ROUND_UP(len
, sizeof (nssuint_t
));
521 *(struct ether_addr
*)buffer
=
522 *(struct ether_addr
*)arg
->key
.ether
;
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;
532 len3
= ROUND_UP(len3
, sizeof (nssuint_t
));
535 (void) strlcpy(buffer
, arg
->key
.pkey
.name
, len
);
536 buffer
= (void *)((char *)buffer
+ len
);
537 (void) strlcpy(buffer
, arg
->key
.pkey
.keytype
, len2
);
541 uptr
= (nssuint_t
*)buffer
;
542 len
= sizeof (nssuint_t
) * 2;
545 *uptr
++ = (nssuint_t
)arg
->key
.netaddr
.net
;
546 *uptr
++ = (nssuint_t
)arg
->key
.netaddr
.type
;
550 pe
= (_priv_execattr
*)(arg
->key
.attrp
);
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;
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;
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
));
574 (void) memset(buffer
, 0, slop
);
575 uptr
= (nssuint_t
*)((void *)((char *)buffer
+ slop
));
576 *uptr
++ = (nssuint_t
)pe
->search_flag
;
581 (void) strlcpy(dptr
, pe
->name
, len2
);
587 (void) strlcpy(dptr
, pe
->type
, len3
);
593 (void) strlcpy(dptr
, pe
->id
, len4
);
599 (void) strlcpy(dptr
, pe
->policy
, len5
);
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
));
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];
618 *uptr
++ = (nssuint_t
)0;
620 (void) strlcpy((void *)uptr
, gbm
->username
, len
);
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
+
631 len2
*= sizeof (nssuint_t
);
633 for (j
= 0; j
< NSS_NETGR_N
; j
++) {
634 cv
= ing
->arg
[j
].argv
;
635 for (i
= ing
->arg
[j
].argc
; --i
>= 0; ) {
637 len3
+= strlen(*cv
++) + 1;
640 cv
= ing
->groups
.argv
;
641 for (i
= ing
->groups
.argc
; --i
>= 0; ) {
643 len3
+= strlen(*cv
++) + 1;
645 len3
= ROUND_UP(len3
, sizeof (nssuint_t
));
647 * Double argv space. Reason:
649 * Second 1/2 for client side pointer arrays
650 * resolves malloc/free issues with unpacked argvs
652 if ((len
+ (len2
<< 1) + len3
) >= length
)
654 *rlen
= len
+ (len2
<< 1) + len3
;
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
;
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;
667 pptr
->machine_offv
= offv
;
668 cv
= ing
->arg
[NSS_NETGR_MACHINE
].argv
;
669 i
= pptr
->machine_argc
;
670 offv
+= sizeof (nssuint_t
) * i
;
673 len3
= strlen(*cv
) + 1;
674 (void) strlcpy(dptr
, *cv
++, len3
);
679 if (pptr
->user_argc
== 0) {
680 pptr
->user_offv
= (nssuint_t
)0;
682 pptr
->user_offv
= offv
;
683 cv
= ing
->arg
[NSS_NETGR_USER
].argv
;
685 offv
+= sizeof (nssuint_t
) * i
;
688 len3
= strlen(*cv
) + 1;
689 (void) strlcpy(dptr
, *cv
++, len3
);
694 if (pptr
->domain_argc
== 0) {
695 pptr
->domain_offv
= (nssuint_t
)0;
697 pptr
->domain_offv
= offv
;
698 cv
= ing
->arg
[NSS_NETGR_DOMAIN
].argv
;
699 i
= pptr
->domain_argc
;
700 offv
+= sizeof (nssuint_t
) * i
;
703 len3
= strlen(*cv
) + 1;
704 (void) strlcpy(dptr
, *cv
++, len3
);
709 if (pptr
->groups_argc
== 0) {
710 pptr
->groups_offv
= (nssuint_t
)0;
712 pptr
->groups_offv
= offv
;
713 cv
= ing
->groups
.argv
;
714 i
= pptr
->groups_argc
;
715 offv
+= sizeof (nssuint_t
) * i
;
718 len3
= strlen(*cv
) + 1;
719 (void) strlcpy(dptr
, *cv
++, len3
);
726 sng
= (struct nss_setnetgrent_args
*)arg
;
727 if (sng
->netgroup
== NULL
)
728 return (NSS_NOTFOUND
);
729 len
= strlen(sng
->netgroup
) + 1;
732 (void) strlcpy(buffer
, sng
->netgroup
, len
);
739 return (NSS_SUCCESS
);
743 nss_default_key2str(void *buffer
, size_t length
, nss_XbyY_args_t
*arg
,
744 const char *dbname
, int dbop
, size_t *rlen
)
748 if (buffer
== NULL
|| length
== 0 || arg
== NULL
||
749 dbname
== NULL
|| rlen
== NULL
)
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.
757 if ((index
= nss_dbop_search(dbname
, (uint32_t)dbop
)) < 0)
758 return (NSS_TRYLOCAL
);
760 return (nss_pack_key2str(buffer
, length
, arg
, dbname
,
761 dbop
, rlen
, getXbyY_to_dbop
[index
].tostr
));
766 nss_packed_set_status(void *buffer
, size_t length
, nss_status_t status
,
767 nss_XbyY_args_t
*arg
)
769 nss_pheader_t
*pbuf
= (nss_pheader_t
*)buffer
;
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
;
781 if (in
->numgids
>= 0) {
782 pbuf
->p_status
= NSS_SUCCESS
;
783 pbuf
->data_len
= in
->numgids
*
787 pbuf
->p_status
= status
;
788 pbuf
->p_errno
= errno
;
790 pbuf
->p_herrno
= (uint32_t)arg
->h_errno
;
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
;
800 /* tell nss_unpack() operation is successful */
803 if (status
!= NSS_SUCCESS
&& status
!= NSS_NOTFOUND
) {
804 pbuf
->p_status
= status
;
805 pbuf
->p_errno
= errno
;
809 if (in
->status
== NSS_NETGR_FOUND
) {
810 pbuf
->p_status
= NSS_SUCCESS
;
812 pbuf
->p_status
= NSS_NOTFOUND
;
813 pbuf
->p_errno
= errno
;
819 /* process normal cases */
820 if ((pbuf
->p_status
= status
) != NSS_SUCCESS
) {
821 if (arg
->erange
== 1)
822 pbuf
->p_errno
= ERANGE
;
824 pbuf
->p_errno
= errno
;
828 pbuf
->p_herrno
= (uint32_t)arg
->h_errno
;
829 pbuf
->data_len
= (nssuint_t
)arg
->returnlen
;
838 * Private string to key unpacking function for getXbyY routines
839 * This routine performs a scanf/printf like parse over the packed
840 * string, to uppack and re-assemble the key in the args structure.
842 * buffer - Start of the key buffer location [in packed buffer]
843 * length - Length of key buffer component
844 * Key offsets are relative to start of key buffer location.
863 * Assumes arguments are all valid
868 nss_upack_key2arg(void *buffer
, size_t length
, char **dbname
,
869 int *dbop
, nss_XbyY_args_t
*arg
, int index
)
871 nss_pheader_t
*pbuf
= (nss_pheader_t
*)buffer
;
872 const char *strtype
= NULL
;
873 nssuint_t off
, *uptr
, keysize
;
877 struct nss_setnetgrent_args
*sng
;
878 struct nss_innetgr_args
*ing
;
879 struct nss_groupsbymem
*gbm
;
883 /* keysize is length of the key area */
884 keysize
= pbuf
->data_off
- pbuf
->key_off
;
887 bptr
= (char *)buffer
+ off
;
888 uptr
= (nssuint_t
*)((void *)bptr
);
889 strtype
= getXbyY_to_dbop
[index
].tostr
;
893 switch (*strtype
++) {
895 arg
->key
.name
= (const char *)bptr
;
898 arg
->key
.number
= (int)(*uptr
);
901 arg
->key
.uid
= (uid_t
)(*uptr
);
904 arg
->key
.gid
= (gid_t
)(*uptr
);
907 arg
->key
.hostaddr
.len
= (int)(*uptr
++);
908 arg
->key
.hostaddr
.type
= (int)(*uptr
++);
909 arg
->key
.hostaddr
.addr
= (const char *)uptr
;
912 arg
->key
.ipnode
.af_family
= (int)(*uptr
++);
913 arg
->key
.ipnode
.flags
= (int)(*uptr
++);
914 arg
->key
.ipnode
.name
= (const char *)uptr
;
917 arg
->key
.projid
= (projid_t
)(*uptr
);
920 arg
->key
.serv
.serv
.name
= (const char *)bptr
;
921 len
= strlen(arg
->key
.serv
.serv
.name
) + 1;
923 if (*(const char *)bptr
== '\0')
924 arg
->key
.serv
.proto
= NULL
;
926 arg
->key
.serv
.proto
= (const char *)bptr
;
929 arg
->key
.serv
.serv
.port
= (int)(*uptr
++);
930 if (pbuf
->key_len
== sizeof (nssuint_t
)) {
931 arg
->key
.serv
.proto
= NULL
;
933 bptr
+= sizeof (nssuint_t
);
934 arg
->key
.serv
.proto
= (const char *)bptr
;
938 arg
->key
.ether
= bptr
;
941 arg
->key
.pkey
.name
= (const char *)bptr
;
942 len
= strlen(arg
->key
.pkey
.name
) + 1;
944 arg
->key
.pkey
.keytype
= (const char *)bptr
;
947 arg
->key
.netaddr
.net
= (uint32_t)(*uptr
++);
948 arg
->key
.netaddr
.type
= (int)(*uptr
++);
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
++;
963 pe
->name
= (char *)bptr
;
964 bptr
+= strlen(pe
->name
) + 1;
970 pe
->type
= (char *)bptr
;
971 bptr
+= strlen(pe
->type
) + 1;
977 pe
->id
= (char *)bptr
;
978 bptr
+= strlen(pe
->id
) + 1;
983 pe
->policy
= (char *)bptr
;
985 pe
->head_exec
= NULL
;
986 pe
->prev_exec
= NULL
;
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
++);
1000 gbm
->username
= (const char *)uptr
;
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
;
1011 * Start of argv pointer storage
1013 off
= ing
->arg
[NSS_NETGR_MACHINE
].argc
+
1014 ing
->arg
[NSS_NETGR_USER
].argc
+
1015 ing
->arg
[NSS_NETGR_DOMAIN
].argc
+
1017 off
*= sizeof (nssuint_t
);
1018 off
+= sizeof (nss_pnetgr_t
);
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
)
1028 *cv
++ = (bptr
+ *uptr
++);
1031 ing
->groups
.argv
= cv
;
1032 for (i
= 0; i
< ing
->groups
.argc
; i
++) {
1033 if (*uptr
>= keysize
)
1035 *cv
++ = (bptr
+ *uptr
++);
1039 sng
= (struct nss_setnetgrent_args
*)arg
;
1040 sng
->netgroup
= (const char *)bptr
;
1048 return (NSS_SUCCESS
);
1052 nss_pinit_funcs(int index
, nss_db_initf_t
*initf
, nss_str2ent_t
*s2e
)
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
;
1062 if (handle
== NULL
) {
1063 htmp
= dlopen((const char *)0, RTLD_LAZY
);
1065 lmutex_lock(&handle_lock
);
1066 if (handle
== NULL
) {
1068 lmutex_unlock(&handle_lock
);
1076 lmutex_unlock(&handle_lock
);
1078 (void) dlclose(htmp
);
1083 if (getXbyY_to_dbop
[index
].initfnp
== NULL
) {
1084 name
= getXbyY_to_dbop
[index
].initfn
;
1085 if ((sym
= dlsym(handle
, name
)) == NULL
)
1087 lmutex_lock(&initf_lock
);
1088 if (getXbyY_to_dbop
[index
].initfnp
== NULL
)
1089 getXbyY_to_dbop
[index
].initfnp
= sym
;
1091 lmutex_unlock(&initf_lock
);
1094 *initf
= (nss_db_initf_t
)getXbyY_to_dbop
[index
].initfnp
;
1097 if (getXbyY_to_dbop
[index
].strfnp
== NULL
) {
1098 name
= getXbyY_to_dbop
[index
].strfn
;
1099 if ((sym
= dlsym(handle
, name
)) == NULL
)
1101 lmutex_lock(&s2e_lock
);
1102 if (getXbyY_to_dbop
[index
].strfnp
== NULL
)
1103 getXbyY_to_dbop
[index
].strfnp
= sym
;
1105 lmutex_unlock(&s2e_lock
);
1108 *s2e
= (nss_str2ent_t
)getXbyY_to_dbop
[index
].strfnp
;
1111 return (NSS_SUCCESS
);
1115 nss_packed_getkey(void *buffer
, size_t length
, char **dbname
,
1116 int *dbop
, nss_XbyY_args_t
*arg
)
1118 nss_pheader_t
*pbuf
= (nss_pheader_t
*)buffer
;
1120 nssuint_t off
, dbdsize
;
1123 if (buffer
== NULL
|| length
== 0 || dbop
== NULL
||
1124 arg
== NULL
|| dbname
== NULL
)
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
)
1134 *dbname
= (char *)buffer
+ off
+ pdbd
->o_name
;
1135 if ((index
= nss_dbop_search(*dbname
, (uint32_t)*dbop
)) < 0)
1137 return (nss_upack_key2arg(buffer
, length
, dbname
, dbop
, arg
, index
));
1142 * str2packent: Standard format interposed str2X function for normal APIs
1144 * Return values: 0 = success, 1 = parse error, 2 = erange ...
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.
1156 void *ent
, /* really (char *) */
1161 if (buflen
<= lenstr
) { /* not enough buffer */
1162 return (NSS_STR_PARSE_ERANGE
);
1164 (void) memmove(buffer
, instr
, lenstr
);
1165 buffer
[lenstr
] = '\0';
1167 return (NSS_STR_PARSE_SUCCESS
);
1171 * Initialize db_root, initf, dbop and arg from a packed buffer
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
)
1179 nss_pheader_t
*pbuf
= (nss_pheader_t
*)buffer
;
1180 nss_str2ent_t s2e
= str2packent
;
1181 nss_str2ent_t real_s2e
= NULL
;
1183 nssuint_t off
, dbdsize
;
1184 char *dbname
, *bptr
;
1188 if (buffer
== NULL
|| length
== 0 ||
1189 dbop
== NULL
|| arg
== NULL
)
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
)
1200 dbname
= (char *)buffer
+ off
+ pdbd
->o_name
;
1201 if ((index
= nss_dbop_search(dbname
, (uint32_t)*dbop
)) < 0)
1204 /* db_root is initialized by nscd's based on door info */
1205 /* do nothing here */
1207 /* init key information - (and get dbname dbop etc...) */
1208 if (nss_upack_key2arg(buffer
, length
, &dbname
,
1209 dbop
, arg
, index
) != NSS_SUCCESS
)
1212 /* possible audituser init */
1213 if (strcmp(dbname
, NSS_DBNAM_AUTHATTR
) == 0)
1214 arg
->h_errno
= (int)pbuf
->p_herrno
;
1216 bptr
= (char *)buffer
+ pbuf
->data_off
;
1217 len
= (size_t)pbuf
->data_len
;
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
)
1225 ((struct nss_groupsbymem
*)arg
)->str2ent
= real_s2e
;
1226 ((struct nss_groupsbymem
*)arg
)->process_cstr
= process_cstr
;
1227 return (NSS_SUCCESS
);
1229 if (pbuf
->nss_dbop
== NSS_DBOP_NETGROUP_IN
&&
1230 strcmp(dbname
, NSS_DBNAM_NETGROUP
) == 0) {
1231 return (NSS_SUCCESS
);
1234 /* get initf and str2ent functions */
1235 if (nss_pinit_funcs(index
, initf
, NULL
) != NSS_SUCCESS
)
1238 /* init normal arg cases */
1239 NSS_XbyY_INIT(arg
, NULL
, bptr
, len
, s2e
);
1242 return (NSS_SUCCESS
);
1246 * Initialize db_root, initf, dbop, contextp and arg from a packed buffer
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
)
1255 nss_pheader_t
*pbuf
= (nss_pheader_t
*)buffer
;
1256 nss_str2ent_t s2e
= str2packent
;
1262 bptr
= (char *)buffer
+ pbuf
->data_off
;
1263 len
= (size_t)pbuf
->data_len
;
1264 NSS_XbyY_INIT(arg
, NULL
, bptr
, len
, s2e
);
1267 return (NSS_SUCCESS
);