xref: /onnv-gate/usr/src/lib/nsswitch/ldap/common/getgrent.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <grp.h>
30*0Sstevel@tonic-gate #include "ldap_common.h"
31*0Sstevel@tonic-gate 
32*0Sstevel@tonic-gate /* String which may need to be removed from beginning of group password */
33*0Sstevel@tonic-gate #define	_CRYPT		"{CRYPT}"
34*0Sstevel@tonic-gate #define	_NO_PASSWD_VAL	""
35*0Sstevel@tonic-gate 
36*0Sstevel@tonic-gate /* Group attributes filters */
37*0Sstevel@tonic-gate #define	_G_NAME		"cn"
38*0Sstevel@tonic-gate #define	_G_GID		"gidnumber"
39*0Sstevel@tonic-gate #define	_G_PASSWD	"userpassword"
40*0Sstevel@tonic-gate #define	_G_MEM		"memberuid"
41*0Sstevel@tonic-gate 
42*0Sstevel@tonic-gate #define	_F_GETGRNAM	"(&(objectClass=posixGroup)(cn=%s))"
43*0Sstevel@tonic-gate #define	_F_GETGRNAM_SSD	"(&(%%s)(cn=%s))"
44*0Sstevel@tonic-gate #define	_F_GETGRGID	"(&(objectClass=posixGroup)(gidNumber=%ld))"
45*0Sstevel@tonic-gate #define	_F_GETGRGID_SSD	"(&(%%s)(gidNumber=%ld))"
46*0Sstevel@tonic-gate #define	_F_GETGRMEM	"(&(objectClass=posixGroup)(memberUid=%s))"
47*0Sstevel@tonic-gate #define	_F_GETGRMEM_SSD	"(&(%%s)(memberUid=%s))"
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate static const char *gr_attrs[] = {
50*0Sstevel@tonic-gate 	_G_NAME,
51*0Sstevel@tonic-gate 	_G_GID,
52*0Sstevel@tonic-gate 	_G_PASSWD,
53*0Sstevel@tonic-gate 	_G_MEM,
54*0Sstevel@tonic-gate 	(char *)NULL
55*0Sstevel@tonic-gate };
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate /*
59*0Sstevel@tonic-gate  * _nss_ldap_group2ent is the data marshaling method for the group getXbyY
60*0Sstevel@tonic-gate  * (e.g., getgrnam(), getgrgid(), getgrent()) backend processes. This method
61*0Sstevel@tonic-gate  * is called after a successful ldap search has been performed. This method
62*0Sstevel@tonic-gate  * will parse the ldap search values into struct group = argp->buf.buffer
63*0Sstevel@tonic-gate  * which the frontend process expects. Three error conditions are expected
64*0Sstevel@tonic-gate  * and returned to nsswitch.
65*0Sstevel@tonic-gate  */
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate static int
68*0Sstevel@tonic-gate _nss_ldap_group2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
69*0Sstevel@tonic-gate {
70*0Sstevel@tonic-gate 	int		i, j;
71*0Sstevel@tonic-gate 	int		nss_result;
72*0Sstevel@tonic-gate 	int		buflen = (int)0;
73*0Sstevel@tonic-gate 	int		firstime = (int)1;
74*0Sstevel@tonic-gate 	unsigned long	len = 0L;
75*0Sstevel@tonic-gate 	char		**mp = NULL;
76*0Sstevel@tonic-gate 	char		*val = (char *)NULL;
77*0Sstevel@tonic-gate 	char		*buffer = (char *)NULL;
78*0Sstevel@tonic-gate 	char		*ceiling = (char *)NULL;
79*0Sstevel@tonic-gate 	struct group	*grp = (struct group *)NULL;
80*0Sstevel@tonic-gate 	ns_ldap_result_t	*result = be->result;
81*0Sstevel@tonic-gate 	ns_ldap_attr_t	*attrptr;
82*0Sstevel@tonic-gate 
83*0Sstevel@tonic-gate 	buffer = argp->buf.buffer;
84*0Sstevel@tonic-gate 	buflen = (size_t)argp->buf.buflen;
85*0Sstevel@tonic-gate 	if (!argp->buf.result) {
86*0Sstevel@tonic-gate 		nss_result = (int)NSS_STR_PARSE_ERANGE;
87*0Sstevel@tonic-gate 		goto result_grp2ent;
88*0Sstevel@tonic-gate 	}
89*0Sstevel@tonic-gate 	grp = (struct group *)argp->buf.result;
90*0Sstevel@tonic-gate 	ceiling = buffer + buflen;
91*0Sstevel@tonic-gate 	mp = grp->gr_mem = (char **)NULL;
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate 	/* initialize no group password */
94*0Sstevel@tonic-gate 	grp->gr_passwd = (char *)NULL;
95*0Sstevel@tonic-gate 	nss_result = (int)NSS_STR_PARSE_SUCCESS;
96*0Sstevel@tonic-gate 	(void) memset(argp->buf.buffer, 0, buflen);
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate 	attrptr = getattr(result, 0);
99*0Sstevel@tonic-gate 	if (attrptr == NULL) {
100*0Sstevel@tonic-gate 		nss_result = (int)NSS_STR_PARSE_PARSE;
101*0Sstevel@tonic-gate 		goto result_grp2ent;
102*0Sstevel@tonic-gate 	}
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate 	for (i = 0; i < result->entry->attr_count; i++) {
105*0Sstevel@tonic-gate 		attrptr = getattr(result, i);
106*0Sstevel@tonic-gate 		if (attrptr == NULL) {
107*0Sstevel@tonic-gate 			nss_result = (int)NSS_STR_PARSE_PARSE;
108*0Sstevel@tonic-gate 			goto result_grp2ent;
109*0Sstevel@tonic-gate 		}
110*0Sstevel@tonic-gate 		if (strcasecmp(attrptr->attrname, _G_NAME) == 0) {
111*0Sstevel@tonic-gate 			if ((attrptr->attrvalue[0] == NULL) ||
112*0Sstevel@tonic-gate 			    (len = strlen(attrptr->attrvalue[0])) < 1) {
113*0Sstevel@tonic-gate 				nss_result = (int)NSS_STR_PARSE_PARSE;
114*0Sstevel@tonic-gate 				goto result_grp2ent;
115*0Sstevel@tonic-gate 			}
116*0Sstevel@tonic-gate 			grp->gr_name = buffer;
117*0Sstevel@tonic-gate 			buffer += len + 1;
118*0Sstevel@tonic-gate 			if (buffer > ceiling) {
119*0Sstevel@tonic-gate 				nss_result = (int)NSS_STR_PARSE_ERANGE;
120*0Sstevel@tonic-gate 				goto result_grp2ent;
121*0Sstevel@tonic-gate 			}
122*0Sstevel@tonic-gate 			(void) strcpy(grp->gr_name, attrptr->attrvalue[0]);
123*0Sstevel@tonic-gate 			continue;
124*0Sstevel@tonic-gate 		}
125*0Sstevel@tonic-gate 		if (strcasecmp(attrptr->attrname, _G_PASSWD) == 0) {
126*0Sstevel@tonic-gate 			val = attrptr->attrvalue[0];
127*0Sstevel@tonic-gate 			/*
128*0Sstevel@tonic-gate 			 * Preen "{crypt}" if necessary.
129*0Sstevel@tonic-gate 			 * If the password does not include the {crypt} prefix
130*0Sstevel@tonic-gate 			 * then the password may be plain text.  And thus
131*0Sstevel@tonic-gate 			 * perhaps crypt(3c) should be used to encrypt it.
132*0Sstevel@tonic-gate 			 * Currently the password is copied verbatim.
133*0Sstevel@tonic-gate 			 */
134*0Sstevel@tonic-gate 			if (strncasecmp(val, _CRYPT,
135*0Sstevel@tonic-gate 			    (sizeof (_CRYPT) - 1)) == 0)
136*0Sstevel@tonic-gate 				val += (sizeof (_CRYPT) - 1);
137*0Sstevel@tonic-gate 			len = strlen(val);
138*0Sstevel@tonic-gate 			grp->gr_passwd = buffer;
139*0Sstevel@tonic-gate 			buffer += len + 1;
140*0Sstevel@tonic-gate 			if (buffer > ceiling) {
141*0Sstevel@tonic-gate 				nss_result = (int)NSS_STR_PARSE_ERANGE;
142*0Sstevel@tonic-gate 				goto result_grp2ent;
143*0Sstevel@tonic-gate 			}
144*0Sstevel@tonic-gate 			(void) strcpy(grp->gr_passwd, val);
145*0Sstevel@tonic-gate 			continue;
146*0Sstevel@tonic-gate 		}
147*0Sstevel@tonic-gate 		if (strcasecmp(attrptr->attrname, _G_GID) == 0) {
148*0Sstevel@tonic-gate 			if (strlen(attrptr->attrvalue[0]) == 0) {
149*0Sstevel@tonic-gate 				nss_result = (int)NSS_STR_PARSE_PARSE;
150*0Sstevel@tonic-gate 				goto result_grp2ent;
151*0Sstevel@tonic-gate 			}
152*0Sstevel@tonic-gate 			errno = 0;
153*0Sstevel@tonic-gate 			grp->gr_gid = (gid_t)strtol(attrptr->attrvalue[0],
154*0Sstevel@tonic-gate 						    (char **)NULL, 10);
155*0Sstevel@tonic-gate 			if (errno != 0) {
156*0Sstevel@tonic-gate 				nss_result = (int)NSS_STR_PARSE_PARSE;
157*0Sstevel@tonic-gate 				goto result_grp2ent;
158*0Sstevel@tonic-gate 			}
159*0Sstevel@tonic-gate 			continue;
160*0Sstevel@tonic-gate 		}
161*0Sstevel@tonic-gate 		if (strcasecmp(attrptr->attrname, _G_MEM) == 0) {
162*0Sstevel@tonic-gate 			for (j = 0; j < attrptr->value_count; j++) {
163*0Sstevel@tonic-gate 				if (firstime) {
164*0Sstevel@tonic-gate 					mp = grp->gr_mem =
165*0Sstevel@tonic-gate 						    (char **)ROUND_UP(buffer,
166*0Sstevel@tonic-gate 						    sizeof (char **));
167*0Sstevel@tonic-gate 					buffer = (char *)grp->gr_mem +
168*0Sstevel@tonic-gate 						    sizeof (char *) *
169*0Sstevel@tonic-gate 						    (attrptr->value_count + 1);
170*0Sstevel@tonic-gate 					buffer = (char *)ROUND_UP(buffer,
171*0Sstevel@tonic-gate 						    sizeof (char **));
172*0Sstevel@tonic-gate 					if (buffer > ceiling) {
173*0Sstevel@tonic-gate 						nss_result =
174*0Sstevel@tonic-gate 						    (int)NSS_STR_PARSE_ERANGE;
175*0Sstevel@tonic-gate 						goto result_grp2ent;
176*0Sstevel@tonic-gate 					}
177*0Sstevel@tonic-gate 					firstime = (int)0;
178*0Sstevel@tonic-gate 				}
179*0Sstevel@tonic-gate 				if (attrptr->attrvalue[j] == NULL) {
180*0Sstevel@tonic-gate 					nss_result = (int)NSS_STR_PARSE_PARSE;
181*0Sstevel@tonic-gate 					goto result_grp2ent;
182*0Sstevel@tonic-gate 				}
183*0Sstevel@tonic-gate 				len = strlen(attrptr->attrvalue[j]);
184*0Sstevel@tonic-gate 				if (len == 0)
185*0Sstevel@tonic-gate 					continue;
186*0Sstevel@tonic-gate 				*mp = buffer;
187*0Sstevel@tonic-gate 				buffer += len + 1;
188*0Sstevel@tonic-gate 				if (buffer > ceiling) {
189*0Sstevel@tonic-gate 					nss_result = (int)NSS_STR_PARSE_ERANGE;
190*0Sstevel@tonic-gate 					goto result_grp2ent;
191*0Sstevel@tonic-gate 				}
192*0Sstevel@tonic-gate 				(void) strcpy(*mp++, attrptr->attrvalue[j]);
193*0Sstevel@tonic-gate 				continue;
194*0Sstevel@tonic-gate 			}
195*0Sstevel@tonic-gate 		}
196*0Sstevel@tonic-gate 	}
197*0Sstevel@tonic-gate 	/* Don't leave password as null */
198*0Sstevel@tonic-gate 	if (grp->gr_passwd == (char *)NULL) {
199*0Sstevel@tonic-gate 		/*
200*0Sstevel@tonic-gate 		 * The password may be missing; rfc2307bis defines
201*0Sstevel@tonic-gate 		 * the 'posixGroup' attributes 'authPassword' and
202*0Sstevel@tonic-gate 		 * 'userPassword' as being optional.  Or a directory
203*0Sstevel@tonic-gate 		 * access control may be preventing us from reading
204*0Sstevel@tonic-gate 		 * the password.  Currently we don't know which it is.
205*0Sstevel@tonic-gate 		 * If it's an access problem then perhaps the password
206*0Sstevel@tonic-gate 		 * should be set to "*NP*".  But for now a simple empty
207*0Sstevel@tonic-gate 		 * string is returned.
208*0Sstevel@tonic-gate 		 */
209*0Sstevel@tonic-gate 		grp->gr_passwd = buffer;
210*0Sstevel@tonic-gate 		buffer += sizeof (_NO_PASSWD_VAL);
211*0Sstevel@tonic-gate 		if (buffer > ceiling) {
212*0Sstevel@tonic-gate 			nss_result = (int)NSS_STR_PARSE_ERANGE;
213*0Sstevel@tonic-gate 			goto result_grp2ent;
214*0Sstevel@tonic-gate 		}
215*0Sstevel@tonic-gate 		(void) strcpy(grp->gr_passwd, _NO_PASSWD_VAL);
216*0Sstevel@tonic-gate 	}
217*0Sstevel@tonic-gate 	if (mp == NULL) {
218*0Sstevel@tonic-gate 		mp = grp->gr_mem = (char **)ROUND_UP(buffer, sizeof (char **));
219*0Sstevel@tonic-gate 		buffer = (char *)grp->gr_mem + sizeof (char *);
220*0Sstevel@tonic-gate 		buffer = (char *)ROUND_UP(buffer, sizeof (char **));
221*0Sstevel@tonic-gate 		if (buffer > ceiling) {
222*0Sstevel@tonic-gate 			nss_result = (int)NSS_STR_PARSE_ERANGE;
223*0Sstevel@tonic-gate 			goto result_grp2ent;
224*0Sstevel@tonic-gate 		}
225*0Sstevel@tonic-gate 	}
226*0Sstevel@tonic-gate 	*mp = NULL;
227*0Sstevel@tonic-gate 
228*0Sstevel@tonic-gate #ifdef DEBUG
229*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getgrent.c: _nss_ldap_group2ent]\n");
230*0Sstevel@tonic-gate 	(void) fprintf(stdout, "       gr_name: [%s]\n", grp->gr_name);
231*0Sstevel@tonic-gate 	if (grp->gr_passwd != (char *)NULL)
232*0Sstevel@tonic-gate 		(void) fprintf(stdout, "     gr_passwd: [%s]\n",
233*0Sstevel@tonic-gate 			    grp->gr_passwd);
234*0Sstevel@tonic-gate 	(void) fprintf(stdout, "        gr_gid: [%ld]\n", grp->gr_gid);
235*0Sstevel@tonic-gate 	if (mp != NULL) {
236*0Sstevel@tonic-gate 		for (mp = grp->gr_mem; *mp != NULL; mp++)
237*0Sstevel@tonic-gate 			(void) fprintf(stdout, "        gr_mem: [%s]\n", *mp);
238*0Sstevel@tonic-gate 	}
239*0Sstevel@tonic-gate #endif /* DEBUG */
240*0Sstevel@tonic-gate 
241*0Sstevel@tonic-gate result_grp2ent:
242*0Sstevel@tonic-gate 
243*0Sstevel@tonic-gate 	(void) __ns_ldap_freeResult(&be->result);
244*0Sstevel@tonic-gate 	return ((int)nss_result);
245*0Sstevel@tonic-gate }
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate 
248*0Sstevel@tonic-gate /*
249*0Sstevel@tonic-gate  * getbynam gets a group entry by name. This function constructs an ldap
250*0Sstevel@tonic-gate  * search filter using the name invocation parameter and the getgrnam search
251*0Sstevel@tonic-gate  * filter defined. Once the filter is constructed, we searche for a matching
252*0Sstevel@tonic-gate  * entry and marshal the data results into struct group for the frontend
253*0Sstevel@tonic-gate  * process. The function _nss_ldap_group2ent performs the data marshaling.
254*0Sstevel@tonic-gate  */
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate static nss_status_t
257*0Sstevel@tonic-gate getbynam(ldap_backend_ptr be, void *a)
258*0Sstevel@tonic-gate {
259*0Sstevel@tonic-gate 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
260*0Sstevel@tonic-gate 	char		searchfilter[SEARCHFILTERLEN];
261*0Sstevel@tonic-gate 	char		userdata[SEARCHFILTERLEN];
262*0Sstevel@tonic-gate 	char		groupname[SEARCHFILTERLEN];
263*0Sstevel@tonic-gate 	int		ret;
264*0Sstevel@tonic-gate 
265*0Sstevel@tonic-gate #ifdef DEBUG
266*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getgrent.c: getbyname]\n");
267*0Sstevel@tonic-gate #endif /* DBEUG */
268*0Sstevel@tonic-gate 	if (_ldap_filter_name(groupname, argp->key.name, sizeof (groupname))
269*0Sstevel@tonic-gate 			!= 0)
270*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
271*0Sstevel@tonic-gate 
272*0Sstevel@tonic-gate 	ret = snprintf(searchfilter, sizeof (searchfilter),
273*0Sstevel@tonic-gate 	    _F_GETGRNAM, groupname);
274*0Sstevel@tonic-gate 	if (ret >= sizeof (searchfilter) || ret < 0)
275*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
276*0Sstevel@tonic-gate 
277*0Sstevel@tonic-gate 	ret = snprintf(userdata, sizeof (userdata), _F_GETGRNAM_SSD, groupname);
278*0Sstevel@tonic-gate 	if (ret >= sizeof (userdata) || ret < 0)
279*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
280*0Sstevel@tonic-gate 
281*0Sstevel@tonic-gate 	return ((nss_status_t)_nss_ldap_lookup(be, argp,
282*0Sstevel@tonic-gate 		_GROUP, searchfilter, NULL,
283*0Sstevel@tonic-gate 		_merge_SSD_filter, userdata));
284*0Sstevel@tonic-gate }
285*0Sstevel@tonic-gate 
286*0Sstevel@tonic-gate 
287*0Sstevel@tonic-gate /*
288*0Sstevel@tonic-gate  * getbygid gets a group entry by number. This function constructs an ldap
289*0Sstevel@tonic-gate  * search filter using the name invocation parameter and the getgrgid search
290*0Sstevel@tonic-gate  * filter defined. Once the filter is constructed, we searche for a matching
291*0Sstevel@tonic-gate  * entry and marshal the data results into struct group for the frontend
292*0Sstevel@tonic-gate  * process. The function _nss_ldap_group2ent performs the data marshaling.
293*0Sstevel@tonic-gate  */
294*0Sstevel@tonic-gate 
295*0Sstevel@tonic-gate static nss_status_t
296*0Sstevel@tonic-gate getbygid(ldap_backend_ptr be, void *a)
297*0Sstevel@tonic-gate {
298*0Sstevel@tonic-gate 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
299*0Sstevel@tonic-gate 	char searchfilter[SEARCHFILTERLEN];
300*0Sstevel@tonic-gate 	char userdata[SEARCHFILTERLEN];
301*0Sstevel@tonic-gate 	int ret;
302*0Sstevel@tonic-gate 
303*0Sstevel@tonic-gate #ifdef DEBUG
304*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getgrent.c: getbygid]\n");
305*0Sstevel@tonic-gate #endif /* DBEUG */
306*0Sstevel@tonic-gate 	ret = snprintf(searchfilter, sizeof (searchfilter),
307*0Sstevel@tonic-gate 	    _F_GETGRGID, (long)argp->key.uid);
308*0Sstevel@tonic-gate 	if (ret >= sizeof (searchfilter) || ret < 0)
309*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
310*0Sstevel@tonic-gate 
311*0Sstevel@tonic-gate 	ret = snprintf(userdata, sizeof (userdata),
312*0Sstevel@tonic-gate 	    _F_GETGRGID_SSD, (long)argp->key.uid);
313*0Sstevel@tonic-gate 	if (ret >= sizeof (userdata) || ret < 0)
314*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
315*0Sstevel@tonic-gate 
316*0Sstevel@tonic-gate 	return ((nss_status_t)_nss_ldap_lookup(be, argp,
317*0Sstevel@tonic-gate 		_GROUP, searchfilter, NULL,
318*0Sstevel@tonic-gate 		_merge_SSD_filter, userdata));
319*0Sstevel@tonic-gate 
320*0Sstevel@tonic-gate }
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate 
323*0Sstevel@tonic-gate /*
324*0Sstevel@tonic-gate  * getbymember returns all groups a user is defined in. This function
325*0Sstevel@tonic-gate  * uses different architectural procedures than the other group backend
326*0Sstevel@tonic-gate  * system calls because it's a private interface. This function constructs
327*0Sstevel@tonic-gate  * an ldap search filter using the name invocation parameter. Once the
328*0Sstevel@tonic-gate  * filter is constructed, we search for all matching groups counting
329*0Sstevel@tonic-gate  * and storing each group name, gid, etc. Data marshaling is used for
330*0Sstevel@tonic-gate  * group processing. The function _nss_ldap_group2ent() performs the
331*0Sstevel@tonic-gate  * data marshaling.
332*0Sstevel@tonic-gate  *
333*0Sstevel@tonic-gate  * (const char *)argp->username;	(size_t)strlen(argp->username);
334*0Sstevel@tonic-gate  * (gid_t)argp->gid_array;		(int)argp->maxgids;
335*0Sstevel@tonic-gate  * (int)argp->numgids;
336*0Sstevel@tonic-gate  */
337*0Sstevel@tonic-gate 
338*0Sstevel@tonic-gate static nss_status_t
339*0Sstevel@tonic-gate getbymember(ldap_backend_ptr be, void *a)
340*0Sstevel@tonic-gate {
341*0Sstevel@tonic-gate 	int			i, j, k;
342*0Sstevel@tonic-gate 	int			gcnt = (int)0;
343*0Sstevel@tonic-gate 	char			**groupvalue, **membervalue;
344*0Sstevel@tonic-gate 	nss_status_t		lstat;
345*0Sstevel@tonic-gate 	nss_XbyY_args_t		argb;
346*0Sstevel@tonic-gate 	static nss_XbyY_buf_t	*gb;
347*0Sstevel@tonic-gate 	struct nss_groupsbymem	*argp = (struct nss_groupsbymem *)a;
348*0Sstevel@tonic-gate 	char			searchfilter[SEARCHFILTERLEN];
349*0Sstevel@tonic-gate 	char			userdata[SEARCHFILTERLEN];
350*0Sstevel@tonic-gate 	char			name[SEARCHFILTERLEN];
351*0Sstevel@tonic-gate 	ns_ldap_result_t	*result;
352*0Sstevel@tonic-gate 	ns_ldap_entry_t		*curEntry;
353*0Sstevel@tonic-gate 	char			*username;
354*0Sstevel@tonic-gate 	gid_t			gid;
355*0Sstevel@tonic-gate 	int			ret;
356*0Sstevel@tonic-gate 
357*0Sstevel@tonic-gate #ifdef DEBUG
358*0Sstevel@tonic-gate 	(void) fprintf(stdout, "\n[getgrent.c: getbymember]\n");
359*0Sstevel@tonic-gate #endif /* DBEUG */
360*0Sstevel@tonic-gate 
361*0Sstevel@tonic-gate 	NSS_XbyY_ALLOC(&gb, sizeof (struct group), NSS_BUFLEN_GROUP);
362*0Sstevel@tonic-gate 	NSS_XbyY_INIT(&argb, gb->result, gb->buffer, gb->buflen, 0);
363*0Sstevel@tonic-gate 
364*0Sstevel@tonic-gate 	if (strcmp(argp->username, "") == 0 ||
365*0Sstevel@tonic-gate 	    strcmp(argp->username, "root") == 0)
366*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
367*0Sstevel@tonic-gate 
368*0Sstevel@tonic-gate 	if (_ldap_filter_name(name, argp->username, sizeof (name)) != 0)
369*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
370*0Sstevel@tonic-gate 
371*0Sstevel@tonic-gate 	ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETGRMEM, name);
372*0Sstevel@tonic-gate 	if (ret >= sizeof (searchfilter) || ret < 0)
373*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
374*0Sstevel@tonic-gate 
375*0Sstevel@tonic-gate 	ret = snprintf(userdata, sizeof (userdata), _F_GETGRMEM_SSD, name);
376*0Sstevel@tonic-gate 	if (ret >= sizeof (userdata) || ret < 0)
377*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
378*0Sstevel@tonic-gate 
379*0Sstevel@tonic-gate 	gcnt = (int)argp->numgids;
380*0Sstevel@tonic-gate 	lstat = (nss_status_t)_nss_ldap_nocb_lookup(be, &argb,
381*0Sstevel@tonic-gate 		_GROUP, searchfilter, NULL,
382*0Sstevel@tonic-gate 		_merge_SSD_filter, userdata);
383*0Sstevel@tonic-gate 	if (lstat != (nss_status_t)NS_LDAP_SUCCESS)
384*0Sstevel@tonic-gate 		return ((nss_status_t)lstat);
385*0Sstevel@tonic-gate 	if (be->result == NULL)
386*0Sstevel@tonic-gate 		return (NSS_NOTFOUND);
387*0Sstevel@tonic-gate 	username = (char *)argp->username;
388*0Sstevel@tonic-gate 	result = (ns_ldap_result_t *)be->result;
389*0Sstevel@tonic-gate 	curEntry = (ns_ldap_entry_t *)result->entry;
390*0Sstevel@tonic-gate 	for (i = 0; i < result->entries_count; i++) {
391*0Sstevel@tonic-gate 		membervalue = __ns_ldap_getAttr(curEntry, "memberUid");
392*0Sstevel@tonic-gate 		if (membervalue) {
393*0Sstevel@tonic-gate 			for (j = 0; membervalue[j]; j++) {
394*0Sstevel@tonic-gate 				if (strcmp(membervalue[j], username) == NULL) {
395*0Sstevel@tonic-gate 					groupvalue = __ns_ldap_getAttr(curEntry,
396*0Sstevel@tonic-gate 						"gidnumber");
397*0Sstevel@tonic-gate 					gid = (gid_t)strtol(groupvalue[0],
398*0Sstevel@tonic-gate 						(char **)NULL, 10);
399*0Sstevel@tonic-gate 					if (argp->numgids < argp->maxgids) {
400*0Sstevel@tonic-gate 					    for (k = 0; k < argp->numgids;
401*0Sstevel@tonic-gate 							k++) {
402*0Sstevel@tonic-gate 						if (argp->gid_array[k] == gid)
403*0Sstevel@tonic-gate 						    /* already exists */
404*0Sstevel@tonic-gate 						    break;
405*0Sstevel@tonic-gate 					    }
406*0Sstevel@tonic-gate 					    if (k == argp->numgids)
407*0Sstevel@tonic-gate 						argp->gid_array[argp->numgids++]
408*0Sstevel@tonic-gate 						    = gid;
409*0Sstevel@tonic-gate 					}
410*0Sstevel@tonic-gate 					break;
411*0Sstevel@tonic-gate 				}
412*0Sstevel@tonic-gate 			}
413*0Sstevel@tonic-gate 		}
414*0Sstevel@tonic-gate 		curEntry = curEntry->next;
415*0Sstevel@tonic-gate 	}
416*0Sstevel@tonic-gate 
417*0Sstevel@tonic-gate 	__ns_ldap_freeResult((ns_ldap_result_t **)&be->result);
418*0Sstevel@tonic-gate 	NSS_XbyY_FREE(&gb);
419*0Sstevel@tonic-gate 	if (gcnt == argp->numgids)
420*0Sstevel@tonic-gate 		return ((nss_status_t)NSS_NOTFOUND);
421*0Sstevel@tonic-gate 
422*0Sstevel@tonic-gate 	return ((nss_status_t)NSS_SUCCESS);
423*0Sstevel@tonic-gate }
424*0Sstevel@tonic-gate 
425*0Sstevel@tonic-gate static ldap_backend_op_t gr_ops[] = {
426*0Sstevel@tonic-gate 	_nss_ldap_destr,
427*0Sstevel@tonic-gate 	_nss_ldap_endent,
428*0Sstevel@tonic-gate 	_nss_ldap_setent,
429*0Sstevel@tonic-gate 	_nss_ldap_getent,
430*0Sstevel@tonic-gate 	getbynam,
431*0Sstevel@tonic-gate 	getbygid,
432*0Sstevel@tonic-gate 	getbymember
433*0Sstevel@tonic-gate };
434*0Sstevel@tonic-gate 
435*0Sstevel@tonic-gate 
436*0Sstevel@tonic-gate /*ARGSUSED0*/
437*0Sstevel@tonic-gate nss_backend_t *
438*0Sstevel@tonic-gate _nss_ldap_group_constr(const char *dummy1, const char *dummy2,
439*0Sstevel@tonic-gate 			const char *dummy3)
440*0Sstevel@tonic-gate {
441*0Sstevel@tonic-gate 
442*0Sstevel@tonic-gate 	return ((nss_backend_t *)_nss_ldap_constr(gr_ops,
443*0Sstevel@tonic-gate 		sizeof (gr_ops)/sizeof (gr_ops[0]), _GROUP, gr_attrs,
444*0Sstevel@tonic-gate 		_nss_ldap_group2ent));
445*0Sstevel@tonic-gate }
446