xref: /onnv-gate/usr/src/lib/nsswitch/files/common/getgrent.c (revision 8040:42abce45ef67)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52830Sdjl  * Common Development and Distribution License (the "License").
62830Sdjl  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*8040SBaban.Kenkre@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
232830Sdjl  * Use is subject to license terms.
240Sstevel@tonic-gate  *
252830Sdjl  * files/getgrent.c -- "files" backend for nsswitch "group" database
260Sstevel@tonic-gate  */
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <grp.h>
290Sstevel@tonic-gate #include <unistd.h>		/* for GF_PATH */
302830Sdjl #include <stdlib.h>		/* for GF_PATH */
310Sstevel@tonic-gate #include "files_common.h"
320Sstevel@tonic-gate #include <strings.h>
330Sstevel@tonic-gate 
342830Sdjl static uint_t
hash_grname(nss_XbyY_args_t * argp,int keyhash,const char * line,int linelen)352830Sdjl hash_grname(nss_XbyY_args_t *argp, int keyhash, const char *line,
362830Sdjl 	int linelen)
370Sstevel@tonic-gate {
382830Sdjl 	const char 	*name;
392830Sdjl 	int		namelen, i;
402830Sdjl 	uint_t		hash = 0;
410Sstevel@tonic-gate 
422830Sdjl 	if (keyhash) {
432830Sdjl 		name = argp->key.name;
442830Sdjl 		namelen = strlen(name);
452830Sdjl 	} else {
462830Sdjl 		name = line;
472830Sdjl 		namelen = 0;
482830Sdjl 		while (linelen-- && *line++ != ':')
492830Sdjl 			namelen++;
502830Sdjl 	}
510Sstevel@tonic-gate 
522830Sdjl 	for (i = 0; i < namelen; i++)
532830Sdjl 		hash = hash * 15 + name[i];
540Sstevel@tonic-gate 	return (hash);
550Sstevel@tonic-gate }
560Sstevel@tonic-gate 
572830Sdjl static uint_t
hash_grgid(nss_XbyY_args_t * argp,int keyhash,const char * line,int linelen)582830Sdjl hash_grgid(nss_XbyY_args_t *argp, int keyhash, const char *line,
592830Sdjl 	int linelen)
600Sstevel@tonic-gate {
612830Sdjl 	uint_t		id;
622830Sdjl 	const char	*linep, *limit, *end;
632830Sdjl 
642830Sdjl 	linep = line;
652830Sdjl 	limit = line + linelen;
662830Sdjl 
672830Sdjl 	if (keyhash)
682830Sdjl 		return ((uint_t)argp->key.gid);
692830Sdjl 
70*8040SBaban.Kenkre@Sun.COM 	while (linep < limit && *linep++ != ':') /* skip groupname */
71*8040SBaban.Kenkre@Sun.COM 		continue;
72*8040SBaban.Kenkre@Sun.COM 	while (linep < limit && *linep++ != ':') /* skip password */
73*8040SBaban.Kenkre@Sun.COM 		continue;
742830Sdjl 	if (linep == limit)
752830Sdjl 		return (GID_NOBODY);
762830Sdjl 
772830Sdjl 	/* gid */
782830Sdjl 	end = linep;
79*8040SBaban.Kenkre@Sun.COM 	id = (uint_t)strtoul(linep, (char **)&end, 10);
802830Sdjl 	/* empty gid */
812830Sdjl 	if (linep == end)
822830Sdjl 		return (GID_NOBODY);
832830Sdjl 
842830Sdjl 	return (id);
850Sstevel@tonic-gate }
860Sstevel@tonic-gate 
870Sstevel@tonic-gate static files_hash_func hash_gr[2] = { hash_grname, hash_grgid };
880Sstevel@tonic-gate 
890Sstevel@tonic-gate static files_hash_t hashinfo = {
900Sstevel@tonic-gate 	DEFAULTMUTEX,
910Sstevel@tonic-gate 	sizeof (struct group),
920Sstevel@tonic-gate 	NSS_BUFLEN_GROUP,
930Sstevel@tonic-gate 	2,
940Sstevel@tonic-gate 	hash_gr
950Sstevel@tonic-gate };
960Sstevel@tonic-gate 
970Sstevel@tonic-gate static int
check_grname(nss_XbyY_args_t * argp,const char * line,int linelen)982830Sdjl check_grname(nss_XbyY_args_t *argp, const char *line, int linelen)
990Sstevel@tonic-gate {
1002830Sdjl 	const char *linep, *limit;
1012830Sdjl 	const char *keyp = argp->key.name;
1022830Sdjl 
1032830Sdjl 	linep = line;
1042830Sdjl 	limit = line + linelen;
1050Sstevel@tonic-gate 
1062830Sdjl 	/* +/- entries valid for compat source only */
1072830Sdjl 	if (linelen == 0 || *line == '+' || *line == '-')
1080Sstevel@tonic-gate 		return (0);
1092830Sdjl 	while (*keyp && linep < limit && *keyp == *linep) {
1102830Sdjl 		keyp++;
1112830Sdjl 		linep++;
1122830Sdjl 	}
1132830Sdjl 	return (linep < limit && *keyp == '\0' && *linep == ':');
1140Sstevel@tonic-gate }
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate static nss_status_t
getbyname(be,a)1170Sstevel@tonic-gate getbyname(be, a)
1180Sstevel@tonic-gate 	files_backend_ptr_t	be;
1190Sstevel@tonic-gate 	void			*a;
1200Sstevel@tonic-gate {
1210Sstevel@tonic-gate 	return (_nss_files_XY_hash(be, a, 0, &hashinfo, 0, check_grname));
1220Sstevel@tonic-gate }
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate static int
check_grgid(nss_XbyY_args_t * argp,const char * line,int linelen)1252830Sdjl check_grgid(nss_XbyY_args_t *argp, const char *line, int linelen)
1260Sstevel@tonic-gate {
1272830Sdjl 	const char	*linep, *limit, *end;
128*8040SBaban.Kenkre@Sun.COM 	ulong_t		gr_gid;
1292830Sdjl 
1302830Sdjl 	linep = line;
1312830Sdjl 	limit = line + linelen;
1322830Sdjl 
1332830Sdjl 	/* +/- entries valid for compat source only */
1342830Sdjl 	if (linelen == 0 || *line == '+' || *line == '-')
1352830Sdjl 		return (0);
1360Sstevel@tonic-gate 
137*8040SBaban.Kenkre@Sun.COM 	while (linep < limit && *linep++ != ':') /* skip groupname */
138*8040SBaban.Kenkre@Sun.COM 		continue;
139*8040SBaban.Kenkre@Sun.COM 	while (linep < limit && *linep++ != ':') /* skip password */
140*8040SBaban.Kenkre@Sun.COM 		continue;
1412830Sdjl 	if (linep == limit)
1420Sstevel@tonic-gate 		return (0);
1432830Sdjl 
144*8040SBaban.Kenkre@Sun.COM 	/* gid */
1452830Sdjl 	end = linep;
146*8040SBaban.Kenkre@Sun.COM 	gr_gid = strtoul(linep, (char **)&end, 10);
1472830Sdjl 
148*8040SBaban.Kenkre@Sun.COM 	/* check if gid is empty or overflows */
149*8040SBaban.Kenkre@Sun.COM 	if (linep == end || gr_gid > UINT32_MAX)
1502830Sdjl 		return (0);
1512830Sdjl 
152*8040SBaban.Kenkre@Sun.COM 	return ((gid_t)gr_gid == argp->key.gid);
1530Sstevel@tonic-gate }
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate static nss_status_t
getbygid(be,a)1560Sstevel@tonic-gate getbygid(be, a)
1570Sstevel@tonic-gate 	files_backend_ptr_t	be;
1580Sstevel@tonic-gate 	void			*a;
1590Sstevel@tonic-gate {
160*8040SBaban.Kenkre@Sun.COM 	nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
161*8040SBaban.Kenkre@Sun.COM 
162*8040SBaban.Kenkre@Sun.COM 	if (argp->key.gid > MAXUID)
163*8040SBaban.Kenkre@Sun.COM 		return (NSS_NOTFOUND);
164*8040SBaban.Kenkre@Sun.COM 	return (_nss_files_XY_hash(be, argp, 0, &hashinfo, 1, check_grgid));
165*8040SBaban.Kenkre@Sun.COM }
166*8040SBaban.Kenkre@Sun.COM 
167*8040SBaban.Kenkre@Sun.COM /*
168*8040SBaban.Kenkre@Sun.COM  * Validates group entry replacing gid > MAXUID by GID_NOBODY.
169*8040SBaban.Kenkre@Sun.COM  */
170*8040SBaban.Kenkre@Sun.COM int
validate_group_ids(char * line,int * linelenp,int buflen,int extra_chars,files_XY_check_func check)171*8040SBaban.Kenkre@Sun.COM validate_group_ids(char *line, int *linelenp, int buflen, int extra_chars,
172*8040SBaban.Kenkre@Sun.COM 		files_XY_check_func check)
173*8040SBaban.Kenkre@Sun.COM {
174*8040SBaban.Kenkre@Sun.COM 	char	*linep, *limit, *gidp;
175*8040SBaban.Kenkre@Sun.COM 	ulong_t	gid;
176*8040SBaban.Kenkre@Sun.COM 	int	oldgidlen, idlen;
177*8040SBaban.Kenkre@Sun.COM 	int	linelen = *linelenp, newlinelen;
178*8040SBaban.Kenkre@Sun.COM 
179*8040SBaban.Kenkre@Sun.COM 	/*
180*8040SBaban.Kenkre@Sun.COM 	 * getbygid() rejects searching by ephemeral gid therefore
181*8040SBaban.Kenkre@Sun.COM 	 * no need to validate because the matched entry won't have
182*8040SBaban.Kenkre@Sun.COM 	 * an ephemeral gid.
183*8040SBaban.Kenkre@Sun.COM 	 */
184*8040SBaban.Kenkre@Sun.COM 	if (check != NULL && check == check_grgid)
185*8040SBaban.Kenkre@Sun.COM 		return (NSS_STR_PARSE_SUCCESS);
186*8040SBaban.Kenkre@Sun.COM 
187*8040SBaban.Kenkre@Sun.COM 	/* +/- entries valid for compat source only */
188*8040SBaban.Kenkre@Sun.COM 	if (linelen == 0 || *line == '+' || *line == '-')
189*8040SBaban.Kenkre@Sun.COM 		return (NSS_STR_PARSE_SUCCESS);
190*8040SBaban.Kenkre@Sun.COM 
191*8040SBaban.Kenkre@Sun.COM 	linep = line;
192*8040SBaban.Kenkre@Sun.COM 	limit = line + linelen;
193*8040SBaban.Kenkre@Sun.COM 
194*8040SBaban.Kenkre@Sun.COM 	while (linep < limit && *linep++ != ':') /* skip groupname */
195*8040SBaban.Kenkre@Sun.COM 		continue;
196*8040SBaban.Kenkre@Sun.COM 	while (linep < limit && *linep++ != ':') /* skip password */
197*8040SBaban.Kenkre@Sun.COM 		continue;
198*8040SBaban.Kenkre@Sun.COM 	if (linep == limit)
199*8040SBaban.Kenkre@Sun.COM 		return (NSS_STR_PARSE_PARSE);
200*8040SBaban.Kenkre@Sun.COM 
201*8040SBaban.Kenkre@Sun.COM 	gidp = linep;
202*8040SBaban.Kenkre@Sun.COM 	gid = strtoul(gidp, (char **)&linep, 10); /* grab gid */
203*8040SBaban.Kenkre@Sun.COM 	oldgidlen = linep - gidp;
204*8040SBaban.Kenkre@Sun.COM 	if (linep >= limit || oldgidlen == 0)
205*8040SBaban.Kenkre@Sun.COM 		return (NSS_STR_PARSE_PARSE);
206*8040SBaban.Kenkre@Sun.COM 
207*8040SBaban.Kenkre@Sun.COM 	if (gid <= MAXUID)
208*8040SBaban.Kenkre@Sun.COM 		return (NSS_STR_PARSE_SUCCESS);
209*8040SBaban.Kenkre@Sun.COM 
210*8040SBaban.Kenkre@Sun.COM 	idlen = snprintf(NULL, 0, "%u", GID_NOBODY);
211*8040SBaban.Kenkre@Sun.COM 	newlinelen = linelen + idlen - oldgidlen;
212*8040SBaban.Kenkre@Sun.COM 	if (newlinelen + extra_chars > buflen)
213*8040SBaban.Kenkre@Sun.COM 		return (NSS_STR_PARSE_ERANGE);
214*8040SBaban.Kenkre@Sun.COM 
215*8040SBaban.Kenkre@Sun.COM 	(void) bcopy(linep, gidp + idlen, limit - linep + extra_chars);
216*8040SBaban.Kenkre@Sun.COM 	(void) snprintf(gidp, idlen + 1, "%u", GID_NOBODY);
217*8040SBaban.Kenkre@Sun.COM 	*(gidp + idlen) = ':';
218*8040SBaban.Kenkre@Sun.COM 	*linelenp = newlinelen;
219*8040SBaban.Kenkre@Sun.COM 	return (NSS_STR_PARSE_SUCCESS);
2200Sstevel@tonic-gate }
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate static nss_status_t
getbymember(be,a)2230Sstevel@tonic-gate getbymember(be, a)
2240Sstevel@tonic-gate 	files_backend_ptr_t	be;
2250Sstevel@tonic-gate 	void			*a;
2260Sstevel@tonic-gate {
2272830Sdjl 	struct nss_groupsbymem	*argp = (struct nss_groupsbymem *)a;
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate 	return (_nss_files_do_all(be, argp, argp->username,
2300Sstevel@tonic-gate 				(files_do_all_func_t)argp->process_cstr));
2310Sstevel@tonic-gate }
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate static files_backend_op_t group_ops[] = {
2340Sstevel@tonic-gate 	_nss_files_destr,
2350Sstevel@tonic-gate 	_nss_files_endent,
2360Sstevel@tonic-gate 	_nss_files_setent,
2370Sstevel@tonic-gate 	_nss_files_getent_rigid,
2380Sstevel@tonic-gate 	getbyname,
2390Sstevel@tonic-gate 	getbygid,
2400Sstevel@tonic-gate 	getbymember
2410Sstevel@tonic-gate };
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate /*ARGSUSED*/
2440Sstevel@tonic-gate nss_backend_t *
_nss_files_group_constr(dummy1,dummy2,dummy3)2450Sstevel@tonic-gate _nss_files_group_constr(dummy1, dummy2, dummy3)
2460Sstevel@tonic-gate 	const char	*dummy1, *dummy2, *dummy3;
2470Sstevel@tonic-gate {
2480Sstevel@tonic-gate 	return (_nss_files_constr(group_ops,
2490Sstevel@tonic-gate 				sizeof (group_ops) / sizeof (group_ops[0]),
2500Sstevel@tonic-gate 				GF_PATH,
2510Sstevel@tonic-gate 				NSS_LINELEN_GROUP,
2520Sstevel@tonic-gate 				&hashinfo));
2530Sstevel@tonic-gate }
254