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
5*2830Sdjl  * Common Development and Distribution License (the "License").
6*2830Sdjl  * 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*2830Sdjl  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*2830Sdjl  * Use is subject to license terms.
240Sstevel@tonic-gate  *
25*2830Sdjl  * files/getgrent.c -- "files" backend for nsswitch "group" database
260Sstevel@tonic-gate  */
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #include <grp.h>
310Sstevel@tonic-gate #include <unistd.h>		/* for GF_PATH */
32*2830Sdjl #include <stdlib.h>		/* for GF_PATH */
330Sstevel@tonic-gate #include "files_common.h"
340Sstevel@tonic-gate #include <strings.h>
350Sstevel@tonic-gate 
36*2830Sdjl static uint_t
37*2830Sdjl hash_grname(nss_XbyY_args_t *argp, int keyhash, const char *line,
38*2830Sdjl 	int linelen)
390Sstevel@tonic-gate {
40*2830Sdjl 	const char 	*name;
41*2830Sdjl 	int		namelen, i;
42*2830Sdjl 	uint_t		hash = 0;
430Sstevel@tonic-gate 
44*2830Sdjl 	if (keyhash) {
45*2830Sdjl 		name = argp->key.name;
46*2830Sdjl 		namelen = strlen(name);
47*2830Sdjl 	} else {
48*2830Sdjl 		name = line;
49*2830Sdjl 		namelen = 0;
50*2830Sdjl 		while (linelen-- && *line++ != ':')
51*2830Sdjl 			namelen++;
52*2830Sdjl 	}
530Sstevel@tonic-gate 
54*2830Sdjl 	for (i = 0; i < namelen; i++)
55*2830Sdjl 		hash = hash * 15 + name[i];
560Sstevel@tonic-gate 	return (hash);
570Sstevel@tonic-gate }
580Sstevel@tonic-gate 
59*2830Sdjl static uint_t
60*2830Sdjl hash_grgid(nss_XbyY_args_t *argp, int keyhash, const char *line,
61*2830Sdjl 	int linelen)
620Sstevel@tonic-gate {
63*2830Sdjl 	uint_t		id;
64*2830Sdjl 	const char	*linep, *limit, *end;
65*2830Sdjl 
66*2830Sdjl 	linep = line;
67*2830Sdjl 	limit = line + linelen;
68*2830Sdjl 
69*2830Sdjl 	if (keyhash)
70*2830Sdjl 		return ((uint_t)argp->key.gid);
71*2830Sdjl 
72*2830Sdjl 	/* skip groupname */
73*2830Sdjl 	while (linep < limit && *linep++ != ':');
74*2830Sdjl 	/* skip password */
75*2830Sdjl 	while (linep < limit && *linep++ != ':');
76*2830Sdjl 	if (linep == limit)
77*2830Sdjl 		return (GID_NOBODY);
78*2830Sdjl 
79*2830Sdjl 	/* gid */
80*2830Sdjl 	end = linep;
81*2830Sdjl 	id = (uint_t)strtol(linep, (char **)&end, 10);
82*2830Sdjl 	/* empty gid */
83*2830Sdjl 	if (linep == end)
84*2830Sdjl 		return (GID_NOBODY);
85*2830Sdjl 
86*2830Sdjl 	return (id);
870Sstevel@tonic-gate }
880Sstevel@tonic-gate 
890Sstevel@tonic-gate static files_hash_func hash_gr[2] = { hash_grname, hash_grgid };
900Sstevel@tonic-gate 
910Sstevel@tonic-gate static files_hash_t hashinfo = {
920Sstevel@tonic-gate 	DEFAULTMUTEX,
930Sstevel@tonic-gate 	sizeof (struct group),
940Sstevel@tonic-gate 	NSS_BUFLEN_GROUP,
950Sstevel@tonic-gate 	2,
960Sstevel@tonic-gate 	hash_gr
970Sstevel@tonic-gate };
980Sstevel@tonic-gate 
990Sstevel@tonic-gate static int
100*2830Sdjl check_grname(nss_XbyY_args_t *argp, const char *line, int linelen)
1010Sstevel@tonic-gate {
102*2830Sdjl 	const char *linep, *limit;
103*2830Sdjl 	const char *keyp = argp->key.name;
104*2830Sdjl 
105*2830Sdjl 	linep = line;
106*2830Sdjl 	limit = line + linelen;
1070Sstevel@tonic-gate 
108*2830Sdjl 	/* +/- entries valid for compat source only */
109*2830Sdjl 	if (linelen == 0 || *line == '+' || *line == '-')
1100Sstevel@tonic-gate 		return (0);
111*2830Sdjl 	while (*keyp && linep < limit && *keyp == *linep) {
112*2830Sdjl 		keyp++;
113*2830Sdjl 		linep++;
114*2830Sdjl 	}
115*2830Sdjl 	return (linep < limit && *keyp == '\0' && *linep == ':');
1160Sstevel@tonic-gate }
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate static nss_status_t
1190Sstevel@tonic-gate getbyname(be, a)
1200Sstevel@tonic-gate 	files_backend_ptr_t	be;
1210Sstevel@tonic-gate 	void			*a;
1220Sstevel@tonic-gate {
1230Sstevel@tonic-gate 	return (_nss_files_XY_hash(be, a, 0, &hashinfo, 0, check_grname));
1240Sstevel@tonic-gate }
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate static int
127*2830Sdjl check_grgid(nss_XbyY_args_t *argp, const char *line, int linelen)
1280Sstevel@tonic-gate {
129*2830Sdjl 	const char	*linep, *limit, *end;
130*2830Sdjl 	gid_t		gr_gid;
131*2830Sdjl 
132*2830Sdjl 	linep = line;
133*2830Sdjl 	limit = line + linelen;
134*2830Sdjl 
135*2830Sdjl 	/* +/- entries valid for compat source only */
136*2830Sdjl 	if (linelen == 0 || *line == '+' || *line == '-')
137*2830Sdjl 		return (0);
1380Sstevel@tonic-gate 
139*2830Sdjl 	/* skip username */
140*2830Sdjl 	while (linep < limit && *linep++ != ':');
141*2830Sdjl 	/* skip password */
142*2830Sdjl 	while (linep < limit && *linep++ != ':');
143*2830Sdjl 	if (linep == limit)
1440Sstevel@tonic-gate 		return (0);
145*2830Sdjl 
146*2830Sdjl 	/* uid */
147*2830Sdjl 	end = linep;
148*2830Sdjl 	gr_gid = (gid_t)strtol(linep, (char **)&end, 10);
149*2830Sdjl 
150*2830Sdjl 	/* empty gid is not valid */
151*2830Sdjl 	if (linep == end)
152*2830Sdjl 		return (0);
153*2830Sdjl 
154*2830Sdjl 	return (gr_gid == argp->key.gid);
1550Sstevel@tonic-gate }
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate static nss_status_t
1580Sstevel@tonic-gate getbygid(be, a)
1590Sstevel@tonic-gate 	files_backend_ptr_t	be;
1600Sstevel@tonic-gate 	void			*a;
1610Sstevel@tonic-gate {
1620Sstevel@tonic-gate 	return (_nss_files_XY_hash(be, a, 0, &hashinfo, 1, check_grgid));
1630Sstevel@tonic-gate }
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate static nss_status_t
1660Sstevel@tonic-gate getbymember(be, a)
1670Sstevel@tonic-gate 	files_backend_ptr_t	be;
1680Sstevel@tonic-gate 	void			*a;
1690Sstevel@tonic-gate {
170*2830Sdjl 	struct nss_groupsbymem	*argp = (struct nss_groupsbymem *)a;
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 	return (_nss_files_do_all(be, argp, argp->username,
1730Sstevel@tonic-gate 				(files_do_all_func_t)argp->process_cstr));
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate static files_backend_op_t group_ops[] = {
1770Sstevel@tonic-gate 	_nss_files_destr,
1780Sstevel@tonic-gate 	_nss_files_endent,
1790Sstevel@tonic-gate 	_nss_files_setent,
1800Sstevel@tonic-gate 	_nss_files_getent_rigid,
1810Sstevel@tonic-gate 	getbyname,
1820Sstevel@tonic-gate 	getbygid,
1830Sstevel@tonic-gate 	getbymember
1840Sstevel@tonic-gate };
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate /*ARGSUSED*/
1870Sstevel@tonic-gate nss_backend_t *
1880Sstevel@tonic-gate _nss_files_group_constr(dummy1, dummy2, dummy3)
1890Sstevel@tonic-gate 	const char	*dummy1, *dummy2, *dummy3;
1900Sstevel@tonic-gate {
1910Sstevel@tonic-gate 	return (_nss_files_constr(group_ops,
1920Sstevel@tonic-gate 				sizeof (group_ops) / sizeof (group_ops[0]),
1930Sstevel@tonic-gate 				GF_PATH,
1940Sstevel@tonic-gate 				NSS_LINELEN_GROUP,
1950Sstevel@tonic-gate 				&hashinfo));
1960Sstevel@tonic-gate }
197