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 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
32 * - name-service switch frontend routines for the netgroup API.
35 * If netgroup A refers to netgroup B, both must occur in the same
36 * source (any other choice gives very confusing semantics). This
37 * assumption is deeply embedded in the code below and in the backends.
39 * innetgr() is implemented on top of something called __multi_innetgr(),
40 * which replaces each (char *) argument of innetgr() with a counted vector
41 * of (char *). The semantics are the same as an OR of the results of
42 * innetgr() operations on each possible 4-tuple picked from the arguments,
43 * but it's possible to implement some cases more efficiently. This is
44 * important for mountd, which used to read YP netgroup.byhost directly in
45 * order to determine efficiently whether a given host belonged to any one
46 * of a long list of netgroups. Wildcarded arguments are indicated by a
53 #include <nss_dbdefs.h>
57 static DEFINE_NSS_DB_ROOT(db_root
);
60 _nss_initf_netgroup(p
)
63 p
->name
= NSS_DBNAM_NETGROUP
;
64 p
->default_config
= NSS_DEFCONF_NETGROUP
;
68 * The netgroup routines aren't quite like the majority of the switch clients.
69 * innetgr() more-or-less fits the getXXXbyYYY mould, but for the others:
70 * - setnetgrent("netgroup") is really a getXXXbyYYY routine, i.e. it
71 * searches the sources until it finds an entry with the given name.
72 * Rather than returning the (potentially large) entry, it simply
73 * initializes a cursor, and then...
74 * - getnetgrent(...) is repeatedly invoked by the user to extract the
75 * contents of the entry found by setnetgrent().
76 * - endnetgrent() is almost like a real endXXXent routine.
77 * The behaviour in NSS was:
78 * If we were certain that all the backends could provide netgroup information
79 * in a common form, we could make the setnetgrent() backend return the entire
80 * entry to the frontend, then implement getnetgrent() and endnetgrent()
81 * strictly in the frontend (aka here). But we're not certain, so we won't.
83 * Since nscd returns the results, and it is nscd that accumulates
84 * the results, then we can return the entire result on the setnetgrent.
87 * In the SunOS 4.x (YP) version of this code, innetgr() did not
88 * affect the state of {set,get,end}netgrent(). Somewhere out
89 * there probably lurks a program that depends on this behaviour,
90 * so this version (both frontend and backends) had better
91 * behave the same way.
94 /* ===> ?? fix "__" name */
96 __multi_innetgr(ngroup
, pgroup
,
100 nss_innetgr_argc ngroup
, nhost
, nuser
, ndomain
;
101 nss_innetgr_argv pgroup
, phost
, puser
, pdomain
;
103 struct nss_innetgr_args ia
;
106 return (0); /* One thing fewer to worry backends */
109 ia
.groups
.argc
= ngroup
;
110 ia
.groups
.argv
= pgroup
;
111 ia
.arg
[NSS_NETGR_MACHINE
].argc
= nhost
;
112 ia
.arg
[NSS_NETGR_MACHINE
].argv
= phost
;
113 ia
.arg
[NSS_NETGR_USER
].argc
= nuser
;
114 ia
.arg
[NSS_NETGR_USER
].argv
= puser
;
115 ia
.arg
[NSS_NETGR_DOMAIN
].argc
= ndomain
;
116 ia
.arg
[NSS_NETGR_DOMAIN
].argv
= pdomain
;
117 ia
.status
= NSS_NETGR_NO
;
119 (void) nss_search(&db_root
, _nss_initf_netgroup
,
120 NSS_DBOP_NETGROUP_IN
, &ia
);
121 return (ia
.status
== NSS_NETGR_FOUND
);
125 innetgr(group
, host
, user
, domain
)
126 const char *group
, *host
, *user
, *domain
;
129 (nss_innetgr_argc)((charp) != 0), (nss_innetgr_argv)(&(charp))
131 return (__multi_innetgr(IA(group
), IA(host
), IA(user
), IA(domain
)));
135 * Context for setnetgrent()/getnetgrent(). If the user is being sensible
136 * the requests will be serialized anyway, but let's play safe and
137 * serialize them ourselves (anything to prevent a coredump)...
138 * We can't use lmutex_lock() here because we don't know what the backends
139 * that we call may call in turn. They might call malloc()/free().
140 * So we use the brute-force callout_lock_enter() instead.
142 static nss_backend_t
*getnetgrent_backend
;
145 setnetgrent(const char *netgroup
)
149 if (netgroup
== NULL
) {
150 /* Prevent coredump, otherwise don't do anything profound */
154 callout_lock_enter();
155 be
= getnetgrent_backend
;
156 if (be
!= NULL
&& NSS_INVOKE_DBOP(be
, NSS_DBOP_SETENT
,
157 (void *)netgroup
) != NSS_SUCCESS
) {
158 (void) NSS_INVOKE_DBOP(be
, NSS_DBOP_DESTRUCTOR
, 0);
162 struct nss_setnetgrent_args args
;
164 args
.netgroup
= netgroup
;
166 (void) nss_search(&db_root
, _nss_initf_netgroup
,
167 NSS_DBOP_NETGROUP_SET
, &args
);
170 getnetgrent_backend
= be
;
176 getnetgrent_r(machinep
, namep
, domainp
, buffer
, buflen
)
183 struct nss_getnetgrent_args args
;
185 args
.buffer
= buffer
;
186 args
.buflen
= buflen
;
187 args
.status
= NSS_NETGR_NO
;
189 callout_lock_enter();
190 if (getnetgrent_backend
!= 0) {
191 (void) NSS_INVOKE_DBOP(getnetgrent_backend
,
192 NSS_DBOP_GETENT
, &args
);
196 if (args
.status
== NSS_NETGR_FOUND
) {
197 *machinep
= args
.retp
[NSS_NETGR_MACHINE
];
198 *namep
= args
.retp
[NSS_NETGR_USER
];
199 *domainp
= args
.retp
[NSS_NETGR_DOMAIN
];
206 static nss_XbyY_buf_t
*buf
;
209 getnetgrent(machinep
, namep
, domainp
)
214 (void) NSS_XbyY_ALLOC(&buf
, 0, NSS_BUFLEN_NETGROUP
);
215 return (getnetgrent_r(machinep
, namep
, domainp
,
216 buf
->buffer
, buf
->buflen
));
222 callout_lock_enter();
223 if (getnetgrent_backend
!= 0) {
224 (void) NSS_INVOKE_DBOP(getnetgrent_backend
,
225 NSS_DBOP_DESTRUCTOR
, 0);
226 getnetgrent_backend
= 0;
229 nss_delete(&db_root
); /* === ? */