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 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 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 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 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 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 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 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 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 * 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