1*a7fe1d5bSAndy Stormont /* 2*a7fe1d5bSAndy Stormont * CDDL HEADER START 3*a7fe1d5bSAndy Stormont * 4*a7fe1d5bSAndy Stormont * The contents of this file are subject to the terms of the 5*a7fe1d5bSAndy Stormont * Common Development and Distribution License (the "License"). 6*a7fe1d5bSAndy Stormont * You may not use this file except in compliance with the License. 7*a7fe1d5bSAndy Stormont * 8*a7fe1d5bSAndy Stormont * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*a7fe1d5bSAndy Stormont * or http://www.opensolaris.org/os/licensing. 10*a7fe1d5bSAndy Stormont * See the License for the specific language governing permissions 11*a7fe1d5bSAndy Stormont * and limitations under the License. 12*a7fe1d5bSAndy Stormont * 13*a7fe1d5bSAndy Stormont * When distributing Covered Code, include this CDDL HEADER in each 14*a7fe1d5bSAndy Stormont * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*a7fe1d5bSAndy Stormont * If applicable, add the following below this CDDL HEADER, with the 16*a7fe1d5bSAndy Stormont * fields enclosed by brackets "[]" replaced with your own identifying 17*a7fe1d5bSAndy Stormont * information: Portions Copyright [yyyy] [name of copyright owner] 18*a7fe1d5bSAndy Stormont * 19*a7fe1d5bSAndy Stormont * CDDL HEADER END 20*a7fe1d5bSAndy Stormont */ 21*a7fe1d5bSAndy Stormont /* 22*a7fe1d5bSAndy Stormont * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*a7fe1d5bSAndy Stormont * Use is subject to license terms. 24*a7fe1d5bSAndy Stormont */ 25*a7fe1d5bSAndy Stormont 26*a7fe1d5bSAndy Stormont /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27*a7fe1d5bSAndy Stormont /* All Rights Reserved */ 28*a7fe1d5bSAndy Stormont 29*a7fe1d5bSAndy Stormont /* 30*a7fe1d5bSAndy Stormont * Copyright (c) 2013 RackTop Systems. 31*a7fe1d5bSAndy Stormont */ 32*a7fe1d5bSAndy Stormont 33*a7fe1d5bSAndy Stormont #include <errno.h> 34*a7fe1d5bSAndy Stormont #include <sys/types.h> 35*a7fe1d5bSAndy Stormont #include <stdio.h> 36*a7fe1d5bSAndy Stormont #include <userdefs.h> 37*a7fe1d5bSAndy Stormont #include <grp.h> 38*a7fe1d5bSAndy Stormont #include <libcmdutils.h> 39*a7fe1d5bSAndy Stormont 40*a7fe1d5bSAndy Stormont static int findunusedgid(gid_t start, gid_t stop, gid_t *ret); 41*a7fe1d5bSAndy Stormont static boolean_t isreservedgid(gid_t gid); 42*a7fe1d5bSAndy Stormont 43*a7fe1d5bSAndy Stormont /* 44*a7fe1d5bSAndy Stormont * Find the highest unused uid. If the highest unused gid is "stop", 45*a7fe1d5bSAndy Stormont * then attempt to find a hole in the range. Returns 0 on success. 46*a7fe1d5bSAndy Stormont */ 47*a7fe1d5bSAndy Stormont int 48*a7fe1d5bSAndy Stormont findnextgid(gid_t start, gid_t stop, gid_t *ret) 49*a7fe1d5bSAndy Stormont { 50*a7fe1d5bSAndy Stormont gid_t gid = start; 51*a7fe1d5bSAndy Stormont struct group *grp; 52*a7fe1d5bSAndy Stormont boolean_t overflow = B_FALSE; 53*a7fe1d5bSAndy Stormont 54*a7fe1d5bSAndy Stormont setgrent(); 55*a7fe1d5bSAndy Stormont for (grp = getgrent(); grp != NULL; grp = getgrent()) { 56*a7fe1d5bSAndy Stormont if (isreservedgid(grp->gr_gid)) /* Skip reserved IDs */ 57*a7fe1d5bSAndy Stormont continue; 58*a7fe1d5bSAndy Stormont if (grp->gr_gid >= gid) { 59*a7fe1d5bSAndy Stormont if (grp->gr_gid == stop) { /* Overflow check */ 60*a7fe1d5bSAndy Stormont overflow = B_TRUE; 61*a7fe1d5bSAndy Stormont break; 62*a7fe1d5bSAndy Stormont } 63*a7fe1d5bSAndy Stormont gid = grp->gr_gid + 1; 64*a7fe1d5bSAndy Stormont } 65*a7fe1d5bSAndy Stormont } 66*a7fe1d5bSAndy Stormont if (grp == NULL && errno != 0) { 67*a7fe1d5bSAndy Stormont endgrent(); 68*a7fe1d5bSAndy Stormont return (-1); 69*a7fe1d5bSAndy Stormont } 70*a7fe1d5bSAndy Stormont endgrent(); 71*a7fe1d5bSAndy Stormont if (overflow == B_TRUE) /* Find a hole */ 72*a7fe1d5bSAndy Stormont return (findunusedgid(start, stop, ret)); 73*a7fe1d5bSAndy Stormont while (isreservedgid(gid) && gid < stop) /* Skip reserved IDs */ 74*a7fe1d5bSAndy Stormont gid++; 75*a7fe1d5bSAndy Stormont *ret = gid; 76*a7fe1d5bSAndy Stormont return (0); 77*a7fe1d5bSAndy Stormont } 78*a7fe1d5bSAndy Stormont 79*a7fe1d5bSAndy Stormont /* 80*a7fe1d5bSAndy Stormont * Check to see whether the gid is a reserved gid 81*a7fe1d5bSAndy Stormont * -- nobody, noaccess or nogroup 82*a7fe1d5bSAndy Stormont */ 83*a7fe1d5bSAndy Stormont static boolean_t 84*a7fe1d5bSAndy Stormont isreservedgid(gid_t gid) 85*a7fe1d5bSAndy Stormont { 86*a7fe1d5bSAndy Stormont return (gid == 60001 || gid == 60002 || gid == 65534); 87*a7fe1d5bSAndy Stormont } 88*a7fe1d5bSAndy Stormont 89*a7fe1d5bSAndy Stormont /* 90*a7fe1d5bSAndy Stormont * findunusedgid() attempts to return the next valid usable id between the 91*a7fe1d5bSAndy Stormont * supplied upper and lower limits. Returns 0 on success. 92*a7fe1d5bSAndy Stormont */ 93*a7fe1d5bSAndy Stormont static int 94*a7fe1d5bSAndy Stormont findunusedgid(gid_t start, gid_t stop, gid_t *ret) 95*a7fe1d5bSAndy Stormont { 96*a7fe1d5bSAndy Stormont gid_t gid; 97*a7fe1d5bSAndy Stormont 98*a7fe1d5bSAndy Stormont for (gid = start; gid <= stop; gid++) { 99*a7fe1d5bSAndy Stormont if (isreservedgid(gid)) 100*a7fe1d5bSAndy Stormont continue; 101*a7fe1d5bSAndy Stormont if (getgrgid(gid) == NULL) { 102*a7fe1d5bSAndy Stormont if (errno != 0) 103*a7fe1d5bSAndy Stormont return (-1); 104*a7fe1d5bSAndy Stormont break; 105*a7fe1d5bSAndy Stormont } 106*a7fe1d5bSAndy Stormont } 107*a7fe1d5bSAndy Stormont if (gid > stop) 108*a7fe1d5bSAndy Stormont return (-1); 109*a7fe1d5bSAndy Stormont *ret = gid; 110*a7fe1d5bSAndy Stormont return (0); 111*a7fe1d5bSAndy Stormont } 112