1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  *
25  * files/getgrent.c -- "files" backend for nsswitch "group" database
26  */
27 
28 #pragma ident	"%Z%%M%	%I%	%E% SMI"
29 
30 #include <grp.h>
31 #include <unistd.h>		/* for GF_PATH */
32 #include <stdlib.h>		/* for GF_PATH */
33 #include "files_common.h"
34 #include <strings.h>
35 
36 static uint_t
37 hash_grname(nss_XbyY_args_t *argp, int keyhash, const char *line,
38 	int linelen)
39 {
40 	const char 	*name;
41 	int		namelen, i;
42 	uint_t		hash = 0;
43 
44 	if (keyhash) {
45 		name = argp->key.name;
46 		namelen = strlen(name);
47 	} else {
48 		name = line;
49 		namelen = 0;
50 		while (linelen-- && *line++ != ':')
51 			namelen++;
52 	}
53 
54 	for (i = 0; i < namelen; i++)
55 		hash = hash * 15 + name[i];
56 	return (hash);
57 }
58 
59 static uint_t
60 hash_grgid(nss_XbyY_args_t *argp, int keyhash, const char *line,
61 	int linelen)
62 {
63 	uint_t		id;
64 	const char	*linep, *limit, *end;
65 
66 	linep = line;
67 	limit = line + linelen;
68 
69 	if (keyhash)
70 		return ((uint_t)argp->key.gid);
71 
72 	/* skip groupname */
73 	while (linep < limit && *linep++ != ':');
74 	/* skip password */
75 	while (linep < limit && *linep++ != ':');
76 	if (linep == limit)
77 		return (GID_NOBODY);
78 
79 	/* gid */
80 	end = linep;
81 	id = (uint_t)strtol(linep, (char **)&end, 10);
82 	/* empty gid */
83 	if (linep == end)
84 		return (GID_NOBODY);
85 
86 	return (id);
87 }
88 
89 static files_hash_func hash_gr[2] = { hash_grname, hash_grgid };
90 
91 static files_hash_t hashinfo = {
92 	DEFAULTMUTEX,
93 	sizeof (struct group),
94 	NSS_BUFLEN_GROUP,
95 	2,
96 	hash_gr
97 };
98 
99 static int
100 check_grname(nss_XbyY_args_t *argp, const char *line, int linelen)
101 {
102 	const char *linep, *limit;
103 	const char *keyp = argp->key.name;
104 
105 	linep = line;
106 	limit = line + linelen;
107 
108 	/* +/- entries valid for compat source only */
109 	if (linelen == 0 || *line == '+' || *line == '-')
110 		return (0);
111 	while (*keyp && linep < limit && *keyp == *linep) {
112 		keyp++;
113 		linep++;
114 	}
115 	return (linep < limit && *keyp == '\0' && *linep == ':');
116 }
117 
118 static nss_status_t
119 getbyname(be, a)
120 	files_backend_ptr_t	be;
121 	void			*a;
122 {
123 	return (_nss_files_XY_hash(be, a, 0, &hashinfo, 0, check_grname));
124 }
125 
126 static int
127 check_grgid(nss_XbyY_args_t *argp, const char *line, int linelen)
128 {
129 	const char	*linep, *limit, *end;
130 	gid_t		gr_gid;
131 
132 	linep = line;
133 	limit = line + linelen;
134 
135 	/* +/- entries valid for compat source only */
136 	if (linelen == 0 || *line == '+' || *line == '-')
137 		return (0);
138 
139 	/* skip username */
140 	while (linep < limit && *linep++ != ':');
141 	/* skip password */
142 	while (linep < limit && *linep++ != ':');
143 	if (linep == limit)
144 		return (0);
145 
146 	/* uid */
147 	end = linep;
148 	gr_gid = (gid_t)strtol(linep, (char **)&end, 10);
149 
150 	/* empty gid is not valid */
151 	if (linep == end)
152 		return (0);
153 
154 	return (gr_gid == argp->key.gid);
155 }
156 
157 static nss_status_t
158 getbygid(be, a)
159 	files_backend_ptr_t	be;
160 	void			*a;
161 {
162 	return (_nss_files_XY_hash(be, a, 0, &hashinfo, 1, check_grgid));
163 }
164 
165 static nss_status_t
166 getbymember(be, a)
167 	files_backend_ptr_t	be;
168 	void			*a;
169 {
170 	struct nss_groupsbymem	*argp = (struct nss_groupsbymem *)a;
171 
172 	return (_nss_files_do_all(be, argp, argp->username,
173 				(files_do_all_func_t)argp->process_cstr));
174 }
175 
176 static files_backend_op_t group_ops[] = {
177 	_nss_files_destr,
178 	_nss_files_endent,
179 	_nss_files_setent,
180 	_nss_files_getent_rigid,
181 	getbyname,
182 	getbygid,
183 	getbymember
184 };
185 
186 /*ARGSUSED*/
187 nss_backend_t *
188 _nss_files_group_constr(dummy1, dummy2, dummy3)
189 	const char	*dummy1, *dummy2, *dummy3;
190 {
191 	return (_nss_files_constr(group_ops,
192 				sizeof (group_ops) / sizeof (group_ops[0]),
193 				GF_PATH,
194 				NSS_LINELEN_GROUP,
195 				&hashinfo));
196 }
197