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