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_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"),
298 nss_dbop_search(const char *name
, uint32_t dbop
)
300 getXbyY_to_dbop_t
*hptr
;
301 int count
= (sizeof (getXbyY_to_dbop
) / sizeof (getXbyY_to_dbop_t
));
305 static const uint32_t hbits_tst
= 0xf0000000;
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
;
315 hval
= (hval
<< 4) + *cp
++;
316 if ((g
= (hval
& hbits_tst
)) != 0)
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
);
327 getXbyYdbopHASH
[hval
] = i
| DBOP_HASH_TAG
;
330 getXbyYdbop_hashed
= 1;
332 lmutex_unlock(&getXbydbop_hash_lock
);
338 hval
= (hval
<< 4) + *cp
++;
339 if ((g
= (hval
& hbits_tst
)) != 0)
344 hval
%= DBOP_PRIME_HASH
;
345 idx
= getXbyYdbopHASH
[hval
];
346 if ((idx
& DBOP_HASH_TAG
) != DBOP_HASH_TAG
)
348 idx
&= ~DBOP_HASH_TAG
;
351 hptr
= &getXbyY_to_dbop
[idx
];
352 if (hptr
->dbop
!= dbop
|| strcmp(name
, hptr
->name
) != 0)
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.
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.
391 nss_pack_key2str(void *buffer
, size_t length
, nss_XbyY_args_t
*arg
,
392 const char *dbname
, int dbop
, size_t *rlen
, const char *typestr
)
395 size_t len
, len2
, len3
, len4
, len5
, slop
;
396 nssuint_t
*uptr
, offv
, offc
;
397 struct nss_setnetgrent_args
*sng
;
398 struct nss_innetgr_args
*ing
;
399 struct nss_groupsbymem
*gbm
;
404 if (buffer
== NULL
|| length
== 0 || arg
== NULL
||
405 dbname
== NULL
|| rlen
== NULL
|| typestr
== NULL
)
408 while (typestr
&& *typestr
) {
409 switch (*typestr
++) {
411 if (arg
->key
.name
== NULL
)
412 return (NSS_NOTFOUND
);
413 len
= strlen(arg
->key
.name
) + 1;
416 (void) strlcpy(buffer
, arg
->key
.name
, len
);
420 len
= sizeof (nssuint_t
);
423 *(nssuint_t
*)buffer
= (nssuint_t
)arg
->key
.number
;
427 len
= sizeof (nssuint_t
);
430 *(nssuint_t
*)buffer
= (nssuint_t
)arg
->key
.uid
;
434 len
= sizeof (nssuint_t
);
437 *(nssuint_t
*)buffer
= (nssuint_t
)arg
->key
.gid
;
441 if (arg
->key
.hostaddr
.addr
== NULL
)
443 len
= arg
->key
.hostaddr
.len
;
444 len
= ROUND_UP(len
, sizeof (nssuint_t
));
445 len2
= (sizeof (nssuint_t
) * 2) + len
;
448 *(nssuint_t
*)buffer
=
449 (nssuint_t
)arg
->key
.hostaddr
.len
;
450 buffer
= (void *)((char *)buffer
+ sizeof (nssuint_t
));
451 *(nssuint_t
*)buffer
=
452 (nssuint_t
)arg
->key
.hostaddr
.type
;
453 buffer
= (void *)((char *)buffer
+ sizeof (nssuint_t
));
454 (void) memcpy(buffer
, arg
->key
.hostaddr
.addr
,
455 arg
->key
.hostaddr
.len
);
459 if (arg
->key
.ipnode
.name
== NULL
)
460 return (NSS_NOTFOUND
);
461 len
= strlen(arg
->key
.ipnode
.name
) + 1;
462 len
= ROUND_UP(len
, sizeof (nssuint_t
));
463 len2
= (sizeof (nssuint_t
) * 2) + len
;
466 *(nssuint_t
*)buffer
=
467 (nssuint_t
)arg
->key
.ipnode
.af_family
;
468 buffer
= (void *)((char *)buffer
+ sizeof (nssuint_t
));
469 *(nssuint_t
*)buffer
=
470 (nssuint_t
)arg
->key
.ipnode
.flags
;
471 buffer
= (void *)((char *)buffer
+ sizeof (nssuint_t
));
472 (void) strlcpy(buffer
, arg
->key
.ipnode
.name
, len
);
476 len
= sizeof (nssuint_t
);
479 *(nssuint_t
*)buffer
= (nssuint_t
)arg
->key
.projid
;
483 if (arg
->key
.serv
.serv
.name
== NULL
)
484 return (NSS_NOTFOUND
);
485 len
= strlen(arg
->key
.serv
.serv
.name
) + 1;
487 if (arg
->key
.serv
.proto
!= NULL
)
488 len2
+= strlen(arg
->key
.serv
.proto
);
490 len3
= ROUND_UP(len3
, sizeof (nssuint_t
));
493 (void) strlcpy(buffer
, arg
->key
.serv
.serv
.name
, len
);
494 buffer
= (void *)((char *)buffer
+ len
);
496 (void) strlcpy(buffer
, arg
->key
.serv
.proto
,
499 *(char *)buffer
= '\0';
504 if (arg
->key
.serv
.proto
!= NULL
)
505 len2
= strlen(arg
->key
.serv
.proto
) + 1;
506 len
= sizeof (nssuint_t
) + len2
;
509 uptr
= (nssuint_t
*)buffer
;
510 *uptr
++ = (nssuint_t
)arg
->key
.serv
.serv
.port
;
512 (void) strlcpy((char *)uptr
,
513 arg
->key
.serv
.proto
, len2
);
518 if (arg
->key
.ether
== NULL
)
519 return (NSS_NOTFOUND
);
520 len
= sizeof (struct ether_addr
);
521 len
= ROUND_UP(len
, sizeof (nssuint_t
));
524 *(struct ether_addr
*)buffer
=
525 *(struct ether_addr
*)arg
->key
.ether
;
529 if (arg
->key
.pkey
.name
== NULL
||
530 arg
->key
.pkey
.keytype
== NULL
)
531 return (NSS_NOTFOUND
);
532 len
= strlen(arg
->key
.pkey
.name
) + 1;
533 len2
= strlen(arg
->key
.pkey
.keytype
) + 1;
535 len3
= ROUND_UP(len3
, sizeof (nssuint_t
));
538 (void) strlcpy(buffer
, arg
->key
.pkey
.name
, len
);
539 buffer
= (void *)((char *)buffer
+ len
);
540 (void) strlcpy(buffer
, arg
->key
.pkey
.keytype
, len2
);
544 uptr
= (nssuint_t
*)buffer
;
545 len
= sizeof (nssuint_t
) * 2;
548 *uptr
++ = (nssuint_t
)arg
->key
.netaddr
.net
;
549 *uptr
++ = (nssuint_t
)arg
->key
.netaddr
.type
;
553 pe
= (_priv_execattr
*)(arg
->key
.attrp
);
555 return (NSS_NOTFOUND
);
556 /* for search flag */
557 len
= sizeof (nssuint_t
);
558 /* for sizeof (_priv_execattr) static buffer */
559 /* Plus lots of slop just in case... */
560 slop
= sizeof (nssuint_t
) * 16;
563 len2
= len3
= len4
= len5
= 1;
564 if (pe
->name
!= NULL
)
565 len2
= strlen(pe
->name
) + 1;
566 if (pe
->type
!= NULL
)
567 len3
= strlen(pe
->type
) + 1;
569 len4
= strlen(pe
->id
) + 1;
570 if (pe
->policy
!= NULL
)
571 len5
= strlen(pe
->policy
) + 1;
572 /* head_exec, prev_exec - are client side only... */
573 len
+= len2
+ len3
+ len4
+ len5
;
574 len
= ROUND_UP(len
, sizeof (nssuint_t
));
577 (void) memset((void *)buffer
, 0, slop
);
578 uptr
= (nssuint_t
*)((void *)((char *)buffer
+ slop
));
579 *uptr
++ = (nssuint_t
)pe
->search_flag
;
584 (void) strlcpy(dptr
, pe
->name
, len2
);
590 (void) strlcpy(dptr
, pe
->type
, len3
);
596 (void) strlcpy(dptr
, pe
->id
, len4
);
602 (void) strlcpy(dptr
, pe
->policy
, len5
);
606 gbm
= (struct nss_groupsbymem
*)arg
;
607 if (gbm
->username
== NULL
)
608 return (NSS_NOTFOUND
);
609 len
= strlen(gbm
->username
) + 1;
610 len2
= sizeof (nssuint_t
) * 4;
611 len2
+= ROUND_UP(len
, sizeof (nssuint_t
));
614 uptr
= (nssuint_t
*)buffer
;
615 *uptr
++ = (nssuint_t
)gbm
->force_slow_way
;
616 *uptr
++ = (nssuint_t
)gbm
->maxgids
;
617 *uptr
++ = (nssuint_t
)gbm
->numgids
;
618 if (gbm
->numgids
== 1) {
619 *uptr
++ = (nssuint_t
)gbm
->gid_array
[0];
621 *uptr
++ = (nssuint_t
)0;
623 (void) strlcpy((void *)uptr
, gbm
->username
, len
);
627 pptr
= (nss_pnetgr_t
*)buffer
;
628 ing
= (struct nss_innetgr_args
*)arg
;
629 len
= sizeof (nss_pnetgr_t
);
630 len2
= ing
->arg
[NSS_NETGR_MACHINE
].argc
+
631 ing
->arg
[NSS_NETGR_USER
].argc
+
632 ing
->arg
[NSS_NETGR_DOMAIN
].argc
+
634 len2
*= sizeof (nssuint_t
);
636 for (j
= 0; j
< NSS_NETGR_N
; j
++) {
637 cv
= ing
->arg
[j
].argv
;
638 for (i
= ing
->arg
[j
].argc
; --i
>= 0; ) {
640 len3
+= strlen(*cv
++) + 1;
643 cv
= ing
->groups
.argv
;
644 for (i
= ing
->groups
.argc
; --i
>= 0; ) {
646 len3
+= strlen(*cv
++) + 1;
648 len3
= ROUND_UP(len3
, sizeof (nssuint_t
));
650 * Double argv space. Reason:
652 * Second 1/2 for client side pointer arrays
653 * resolves malloc/free issues with unpacked argvs
655 if ((len
+ (len2
<< 1) + len3
) >= length
)
657 *rlen
= len
+ (len2
<< 1) + len3
;
659 pptr
->machine_argc
= ing
->arg
[NSS_NETGR_MACHINE
].argc
;
660 pptr
->user_argc
= ing
->arg
[NSS_NETGR_USER
].argc
;
661 pptr
->domain_argc
= ing
->arg
[NSS_NETGR_DOMAIN
].argc
;
662 pptr
->groups_argc
= ing
->groups
.argc
;
664 uptr
= (nssuint_t
*)((void *)((char *)buffer
+ offv
));
665 offc
= len
+ (len2
<< 1);
666 dptr
= (char *)buffer
+ offc
;
667 if (pptr
->machine_argc
== 0) {
668 pptr
->machine_offv
= (nssuint_t
)0;
670 pptr
->machine_offv
= offv
;
671 cv
= ing
->arg
[NSS_NETGR_MACHINE
].argv
;
672 i
= pptr
->machine_argc
;
673 offv
+= sizeof (nssuint_t
) * i
;
676 len3
= strlen(*cv
) + 1;
677 (void) strlcpy(dptr
, *cv
++, len3
);
682 if (pptr
->user_argc
== 0) {
683 pptr
->user_offv
= (nssuint_t
)0;
685 pptr
->user_offv
= offv
;
686 cv
= ing
->arg
[NSS_NETGR_USER
].argv
;
688 offv
+= sizeof (nssuint_t
) * i
;
691 len3
= strlen(*cv
) + 1;
692 (void) strlcpy(dptr
, *cv
++, len3
);
697 if (pptr
->domain_argc
== 0) {
698 pptr
->domain_offv
= (nssuint_t
)0;
700 pptr
->domain_offv
= offv
;
701 cv
= ing
->arg
[NSS_NETGR_DOMAIN
].argv
;
702 i
= pptr
->domain_argc
;
703 offv
+= sizeof (nssuint_t
) * i
;
706 len3
= strlen(*cv
) + 1;
707 (void) strlcpy(dptr
, *cv
++, len3
);
712 if (pptr
->groups_argc
== 0) {
713 pptr
->groups_offv
= (nssuint_t
)0;
715 pptr
->groups_offv
= offv
;
716 cv
= ing
->groups
.argv
;
717 i
= pptr
->groups_argc
;
718 offv
+= sizeof (nssuint_t
) * i
;
721 len3
= strlen(*cv
) + 1;
722 (void) strlcpy(dptr
, *cv
++, len3
);
729 sng
= (struct nss_setnetgrent_args
*)arg
;
730 if (sng
->netgroup
== NULL
)
731 return (NSS_NOTFOUND
);
732 len
= strlen(sng
->netgroup
) + 1;
735 (void) strlcpy(buffer
, sng
->netgroup
, len
);
742 return (NSS_SUCCESS
);
746 nss_default_key2str(void *buffer
, size_t length
, nss_XbyY_args_t
*arg
,
747 const char *dbname
, int dbop
, size_t *rlen
)
751 if (buffer
== NULL
|| length
== 0 || arg
== NULL
||
752 dbname
== NULL
|| rlen
== NULL
)
756 * If this is not one of the well known getXbyYs
757 * (IE _printers special processing etc.) use a
758 * local (non-nscd) getXbyY lookup.
760 if ((index
= nss_dbop_search(dbname
, (uint32_t)dbop
)) < 0)
761 return (NSS_TRYLOCAL
);
763 return (nss_pack_key2str(buffer
, length
, arg
, dbname
,
764 dbop
, rlen
, getXbyY_to_dbop
[index
].tostr
));
769 nss_packed_set_status(void *buffer
, size_t length
, nss_status_t status
,
770 nss_XbyY_args_t
*arg
)
772 nss_pheader_t
*pbuf
= (nss_pheader_t
*)buffer
;
776 /* sidestep odd cases */
777 pdbd
= (nss_dbd_t
*)((void *)((char *)buffer
+ pbuf
->dbd_off
));
778 dbn
= (char *)pdbd
+ pdbd
->o_name
;
779 if (pbuf
->nss_dbop
== NSS_DBOP_GROUP_BYMEMBER
) {
780 if (strcmp(dbn
, NSS_DBNAM_GROUP
) == 0) {
781 struct nss_groupsbymem
*in
=
782 (struct nss_groupsbymem
*)arg
;
784 if (in
->numgids
>= 0) {
785 pbuf
->p_status
= NSS_SUCCESS
;
786 pbuf
->data_len
= in
->numgids
*
790 pbuf
->p_status
= status
;
791 pbuf
->p_errno
= errno
;
793 pbuf
->p_herrno
= (uint32_t)arg
->h_errno
;
798 if (pbuf
->nss_dbop
== NSS_DBOP_NETGROUP_IN
) {
799 if (strcmp(dbn
, NSS_DBNAM_NETGROUP
) == 0) {
800 struct nss_innetgr_args
*in
=
801 (struct nss_innetgr_args
*)arg
;
803 /* tell nss_unpack() operation is successful */
806 if (status
!= NSS_SUCCESS
&& status
!= NSS_NOTFOUND
) {
807 pbuf
->p_status
= status
;
808 pbuf
->p_errno
= errno
;
812 if (in
->status
== NSS_NETGR_FOUND
) {
813 pbuf
->p_status
= NSS_SUCCESS
;
815 pbuf
->p_status
= NSS_NOTFOUND
;
816 pbuf
->p_errno
= errno
;
822 /* process normal cases */
823 if ((pbuf
->p_status
= status
) != NSS_SUCCESS
) {
824 if (arg
->erange
== 1)
825 pbuf
->p_errno
= ERANGE
;
827 pbuf
->p_errno
= errno
;
831 pbuf
->p_herrno
= (uint32_t)arg
->h_errno
;
832 pbuf
->data_len
= (nssuint_t
)arg
->returnlen
;
841 * Private string to key unpacking function for getXbyY routines
842 * This routine performs a scanf/printf like parse over the packed
843 * string, to uppack and re-assemble the key in the args structure.
845 * buffer - Start of the key buffer location [in packed buffer]
846 * length - Length of key buffer component
847 * Key offsets are relative to start of key buffer location.
866 * Assumes arguments are all valid
871 nss_upack_key2arg(void *buffer
, size_t length
, char **dbname
,
872 int *dbop
, nss_XbyY_args_t
*arg
, int index
)
874 nss_pheader_t
*pbuf
= (nss_pheader_t
*)buffer
;
875 const char *strtype
= NULL
;
876 nssuint_t off
, *uptr
, keysize
;
880 struct nss_setnetgrent_args
*sng
;
881 struct nss_innetgr_args
*ing
;
882 struct nss_groupsbymem
*gbm
;
886 /* keysize is length of the key area */
887 keysize
= pbuf
->data_off
- pbuf
->key_off
;
890 bptr
= (char *)buffer
+ off
;
891 uptr
= (nssuint_t
*)((void *)bptr
);
892 strtype
= getXbyY_to_dbop
[index
].tostr
;
896 switch (*strtype
++) {
898 arg
->key
.name
= (const char *)bptr
;
901 arg
->key
.number
= (int)(*uptr
);
904 arg
->key
.uid
= (uid_t
)(*uptr
);
907 arg
->key
.gid
= (gid_t
)(*uptr
);
910 arg
->key
.hostaddr
.len
= (int)(*uptr
++);
911 arg
->key
.hostaddr
.type
= (int)(*uptr
++);
912 arg
->key
.hostaddr
.addr
= (const char *)uptr
;
915 arg
->key
.ipnode
.af_family
= (int)(*uptr
++);
916 arg
->key
.ipnode
.flags
= (int)(*uptr
++);
917 arg
->key
.ipnode
.name
= (const char *)uptr
;
920 arg
->key
.projid
= (projid_t
)(*uptr
);
923 arg
->key
.serv
.serv
.name
= (const char *)bptr
;
924 len
= strlen(arg
->key
.serv
.serv
.name
) + 1;
926 if (*(const char *)bptr
== '\0')
927 arg
->key
.serv
.proto
= NULL
;
929 arg
->key
.serv
.proto
= (const char *)bptr
;
932 arg
->key
.serv
.serv
.port
= (int)(*uptr
++);
933 if (pbuf
->key_len
== sizeof (nssuint_t
)) {
934 arg
->key
.serv
.proto
= NULL
;
936 bptr
+= sizeof (nssuint_t
);
937 arg
->key
.serv
.proto
= (const char *)bptr
;
941 arg
->key
.ether
= bptr
;
944 arg
->key
.pkey
.name
= (const char *)bptr
;
945 len
= strlen(arg
->key
.pkey
.name
) + 1;
947 arg
->key
.pkey
.keytype
= (const char *)bptr
;
950 arg
->key
.netaddr
.net
= (uint32_t)(*uptr
++);
951 arg
->key
.netaddr
.type
= (int)(*uptr
++);
954 pe
= (_priv_execattr
*)((void *)bptr
);
955 /* use slop space as priv_execattr structure */
956 arg
->key
.attrp
= (void *)pe
;
957 /* skip over slop ... */
958 slop
= sizeof (nssuint_t
) * 16;
959 uptr
= (nssuint_t
*)((void *)((char *)bptr
+ slop
));
960 pe
->search_flag
= (int)*uptr
++;
966 pe
->name
= (char *)bptr
;
967 bptr
+= strlen(pe
->name
) + 1;
973 pe
->type
= (char *)bptr
;
974 bptr
+= strlen(pe
->type
) + 1;
980 pe
->id
= (char *)bptr
;
981 bptr
+= strlen(pe
->id
) + 1;
986 pe
->policy
= (char *)bptr
;
988 pe
->head_exec
= NULL
;
989 pe
->prev_exec
= NULL
;
992 gbm
= (struct nss_groupsbymem
*)arg
;
993 gbm
->gid_array
= (gid_t
*)
994 ((void *)((char *)pbuf
+ pbuf
->data_off
));
995 gbm
->force_slow_way
= (int)(*uptr
++);
996 gbm
->maxgids
= (int)(*uptr
++);
997 gbm
->numgids
= (int)(*uptr
++);
998 if (gbm
->numgids
== 1) {
999 /* insert initial group into data area */
1000 gbm
->gid_array
[0] = (gid_t
)(*uptr
++);
1003 gbm
->username
= (const char *)uptr
;
1006 pptr
= (nss_pnetgr_t
*)((void *)bptr
);
1007 ing
= (struct nss_innetgr_args
*)arg
;
1008 ing
->arg
[NSS_NETGR_MACHINE
].argc
= pptr
->machine_argc
;
1009 ing
->arg
[NSS_NETGR_USER
].argc
= pptr
->user_argc
;
1010 ing
->arg
[NSS_NETGR_DOMAIN
].argc
= pptr
->domain_argc
;
1011 ing
->groups
.argc
= pptr
->groups_argc
;
1014 * Start of argv pointer storage
1016 off
= ing
->arg
[NSS_NETGR_MACHINE
].argc
+
1017 ing
->arg
[NSS_NETGR_USER
].argc
+
1018 ing
->arg
[NSS_NETGR_DOMAIN
].argc
+
1020 off
*= sizeof (nssuint_t
);
1021 off
+= sizeof (nss_pnetgr_t
);
1023 cv
= (char **)((void *)(bptr
+ off
));
1024 uptr
= (nssuint_t
*)
1025 ((void *)(bptr
+ sizeof (nss_pnetgr_t
)));
1026 for (j
= 0; j
< NSS_NETGR_N
; j
++) {
1027 ing
->arg
[j
].argv
= cv
;
1028 for (i
= 0; i
< ing
->arg
[j
].argc
; i
++) {
1029 if (*uptr
>= keysize
)
1031 *cv
++ = (bptr
+ *uptr
++);
1034 ing
->groups
.argv
= cv
;
1035 for (i
= 0; i
< ing
->groups
.argc
; i
++) {
1036 if (*uptr
>= keysize
)
1038 *cv
++ = (bptr
+ *uptr
++);
1042 sng
= (struct nss_setnetgrent_args
*)arg
;
1043 sng
->netgroup
= (const char *)bptr
;
1051 return (NSS_SUCCESS
);
1055 nss_pinit_funcs(int index
, nss_db_initf_t
*initf
, nss_str2ent_t
*s2e
)
1060 static void *handle
= NULL
;
1061 static mutex_t handle_lock
= DEFAULTMUTEX
;
1062 static mutex_t initf_lock
= DEFAULTMUTEX
;
1063 static mutex_t s2e_lock
= DEFAULTMUTEX
;
1065 if (handle
== NULL
) {
1066 htmp
= dlopen((const char *)0, RTLD_LAZY
);
1068 lmutex_lock(&handle_lock
);
1069 if (handle
== NULL
) {
1071 lmutex_unlock(&handle_lock
);
1079 lmutex_unlock(&handle_lock
);
1081 (void) dlclose(htmp
);
1086 if (getXbyY_to_dbop
[index
].initfnp
== NULL
) {
1087 name
= getXbyY_to_dbop
[index
].initfn
;
1088 if ((sym
= dlsym(handle
, name
)) == NULL
)
1090 lmutex_lock(&initf_lock
);
1091 if (getXbyY_to_dbop
[index
].initfnp
== NULL
)
1092 getXbyY_to_dbop
[index
].initfnp
= sym
;
1094 lmutex_unlock(&initf_lock
);
1097 *initf
= (nss_db_initf_t
)getXbyY_to_dbop
[index
].initfnp
;
1100 if (getXbyY_to_dbop
[index
].strfnp
== NULL
) {
1101 name
= getXbyY_to_dbop
[index
].strfn
;
1102 if ((sym
= dlsym(handle
, name
)) == NULL
)
1104 lmutex_lock(&s2e_lock
);
1105 if (getXbyY_to_dbop
[index
].strfnp
== NULL
)
1106 getXbyY_to_dbop
[index
].strfnp
= sym
;
1108 lmutex_unlock(&s2e_lock
);
1111 *s2e
= (nss_str2ent_t
)getXbyY_to_dbop
[index
].strfnp
;
1114 return (NSS_SUCCESS
);
1118 nss_packed_getkey(void *buffer
, size_t length
, char **dbname
,
1119 int *dbop
, nss_XbyY_args_t
*arg
)
1121 nss_pheader_t
*pbuf
= (nss_pheader_t
*)buffer
;
1123 nssuint_t off
, dbdsize
;
1126 if (buffer
== NULL
|| length
== 0 || dbop
== NULL
||
1127 arg
== NULL
|| dbname
== NULL
)
1130 *dbop
= pbuf
->nss_dbop
;
1131 off
= pbuf
->dbd_off
;
1132 pdbd
= (nss_dbd_t
*)((void *)((char *)buffer
+ off
));
1133 dbdsize
= pbuf
->key_off
- pbuf
->dbd_off
;
1134 if (pdbd
->o_name
>= dbdsize
|| pdbd
->o_config_name
>= dbdsize
||
1135 pdbd
->o_default_config
>= dbdsize
)
1137 *dbname
= (char *)buffer
+ off
+ pdbd
->o_name
;
1138 if ((index
= nss_dbop_search(*dbname
, (uint32_t)*dbop
)) < 0)
1140 return (nss_upack_key2arg(buffer
, length
, dbname
, dbop
, arg
, index
));
1145 * str2packent: Standard format interposed str2X function for normal APIs
1147 * Return values: 0 = success, 1 = parse error, 2 = erange ...
1149 * The structure pointer is ignored since this is a nscd side packed request.
1150 * The client side routine does all the real parsing; we just check limits and
1151 * store the entry in the buffer we were passed by the caller.
1159 void *ent
, /* really (char *) */
1164 if (buflen
<= lenstr
) { /* not enough buffer */
1165 return (NSS_STR_PARSE_ERANGE
);
1167 (void) memmove(buffer
, instr
, lenstr
);
1168 buffer
[lenstr
] = '\0';
1170 return (NSS_STR_PARSE_SUCCESS
);
1174 * Initialize db_root, initf, dbop and arg from a packed buffer
1179 nss_packed_arg_init(void *buffer
, size_t length
, nss_db_root_t
*db_root
,
1180 nss_db_initf_t
*initf
, int *dbop
, nss_XbyY_args_t
*arg
)
1182 nss_pheader_t
*pbuf
= (nss_pheader_t
*)buffer
;
1183 nss_str2ent_t s2e
= str2packent
;
1184 nss_str2ent_t real_s2e
= NULL
;
1186 nssuint_t off
, dbdsize
;
1187 char *dbname
, *bptr
;
1191 if (buffer
== NULL
|| length
== 0 ||
1192 dbop
== NULL
|| arg
== NULL
)
1196 *dbop
= pbuf
->nss_dbop
;
1197 off
= pbuf
->dbd_off
;
1198 pdbd
= (nss_dbd_t
*)((void *)((char *)buffer
+ off
));
1199 dbdsize
= pbuf
->key_off
- pbuf
->dbd_off
;
1200 if (pdbd
->o_name
>= dbdsize
|| pdbd
->o_config_name
>= dbdsize
||
1201 pdbd
->o_default_config
>= dbdsize
)
1203 dbname
= (char *)buffer
+ off
+ pdbd
->o_name
;
1204 if ((index
= nss_dbop_search(dbname
, (uint32_t)*dbop
)) < 0)
1207 /* db_root is initialized by nscd's based on door info */
1208 /* do nothing here */
1210 /* init key information - (and get dbname dbop etc...) */
1211 if (nss_upack_key2arg(buffer
, length
, &dbname
,
1212 dbop
, arg
, index
) != NSS_SUCCESS
)
1215 /* possible audituser init */
1216 if (strcmp(dbname
, NSS_DBNAM_AUTHATTR
) == 0)
1217 arg
->h_errno
= (int)pbuf
->p_herrno
;
1219 bptr
= (char *)buffer
+ pbuf
->data_off
;
1220 len
= (size_t)pbuf
->data_len
;
1222 /* sidestep odd arg cases */
1223 if (*dbop
== NSS_DBOP_GROUP_BYMEMBER
&&
1224 strcmp(dbname
, NSS_DBNAM_GROUP
) == 0) {
1225 /* get initf and str2ent functions */
1226 if (nss_pinit_funcs(index
, initf
, &real_s2e
) != NSS_SUCCESS
)
1228 ((struct nss_groupsbymem
*)arg
)->str2ent
= real_s2e
;
1229 ((struct nss_groupsbymem
*)arg
)->process_cstr
= process_cstr
;
1230 return (NSS_SUCCESS
);
1232 if (pbuf
->nss_dbop
== NSS_DBOP_NETGROUP_IN
&&
1233 strcmp(dbname
, NSS_DBNAM_NETGROUP
) == 0) {
1234 return (NSS_SUCCESS
);
1237 /* get initf and str2ent functions */
1238 if (nss_pinit_funcs(index
, initf
, NULL
) != NSS_SUCCESS
)
1241 /* init normal arg cases */
1242 NSS_XbyY_INIT(arg
, NULL
, bptr
, len
, s2e
);
1245 return (NSS_SUCCESS
);
1249 * Initialize db_root, initf, dbop, contextp and arg from a packed buffer
1254 nss_packed_context_init(void *buffer
, size_t length
, nss_db_root_t
*db_root
,
1255 nss_db_initf_t
*initf
, nss_getent_t
**contextp
,
1256 nss_XbyY_args_t
*arg
)
1258 nss_pheader_t
*pbuf
= (nss_pheader_t
*)buffer
;
1259 nss_str2ent_t s2e
= str2packent
;
1265 bptr
= (char *)buffer
+ pbuf
->data_off
;
1266 len
= (size_t)pbuf
->data_len
;
1267 NSS_XbyY_INIT(arg
, NULL
, bptr
, len
, s2e
);
1270 return (NSS_SUCCESS
);