1 /* $OpenBSD: getgrouplist.c,v 1.15 2008/08/23 10:08:02 chl Exp $ */ 2 /* 3 * Copyright (c) 1991, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the University nor the names of its contributors 15 * may be used to endorse or promote products derived from this software 16 * without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 /* 32 * get credential 33 */ 34 #include <sys/types.h> 35 #include <sys/limits.h> 36 #include <string.h> 37 #include <unistd.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <grp.h> 41 #include <pwd.h> 42 43 #include <rpc/rpc.h> 44 #include <rpcsvc/yp.h> 45 #include <rpcsvc/ypclnt.h> 46 47 int 48 getgrouplist(const char *uname, gid_t agroup, gid_t *groups, int *grpcnt) 49 { 50 int i, ngroups = 0, ret = 0, maxgroups = *grpcnt, bail; 51 int needyp = 0, foundyp = 0; 52 extern struct group *_getgrent_yp(int *); 53 struct group *grp; 54 55 /* 56 * install primary group 57 */ 58 if (ngroups >= maxgroups) { 59 *grpcnt = ngroups; 60 return (-1); 61 } 62 groups[ngroups++] = agroup; 63 64 /* 65 * Scan the group file to find additional groups. 66 */ 67 setgrent(); 68 while ((grp = _getgrent_yp(&foundyp)) || foundyp) { 69 if (foundyp) { 70 needyp = 1; 71 foundyp = 0; 72 continue; 73 } 74 if (grp->gr_gid == agroup) 75 continue; 76 for (bail = 0, i = 0; bail == 0 && i < ngroups; i++) 77 if (groups[i] == grp->gr_gid) 78 bail = 1; 79 if (bail) 80 continue; 81 for (i = 0; grp->gr_mem[i]; i++) { 82 if (!strcmp(grp->gr_mem[i], uname)) { 83 if (ngroups >= maxgroups) { 84 ret = -1; 85 goto out; 86 } 87 groups[ngroups++] = grp->gr_gid; 88 break; 89 } 90 } 91 } 92 93 #ifdef YP 94 /* 95 * If we were told that there is a YP marker, look there now. 96 */ 97 if (needyp) { 98 char buf[1024], *ypdata = NULL, *key, *p; 99 const char *errstr = NULL; 100 static char *__ypdomain; 101 struct passwd pwstore; 102 int r, ypdatalen; 103 gid_t gid; 104 uid_t uid; 105 106 if (!__ypdomain) { 107 if (_yp_check(&__ypdomain) == 0) { 108 goto ypout; 109 } 110 } 111 112 if (getpwnam_r(uname, &pwstore, buf, sizeof buf, NULL)) 113 goto ypout; 114 115 asprintf(&key, "unix.%u@%s", pwstore.pw_uid, __ypdomain); 116 if (key == NULL) 117 goto ypout; 118 r = yp_match(__ypdomain, "netid.byname", key, 119 (int)strlen(key), &ypdata, &ypdatalen); 120 free(key); 121 if (r != 0) 122 goto ypout; 123 124 /* Parse the "uid:gid[,gid,gid[,...]]" string. */ 125 p = strchr(ypdata, ':'); 126 if (!p) 127 goto ypout; 128 *p++ = '\0'; 129 uid = (uid_t)strtonum(ypdata, 0, UID_MAX, &errstr); 130 if (errstr || uid != pwstore.pw_uid) 131 goto ypout; 132 while (p && *p) { 133 char *start = p; 134 135 p = strchr(start, ','); 136 if (p) 137 *p++ = '\0'; 138 gid = (uid_t)strtonum(start, 0, GID_MAX, &errstr); 139 if (errstr) 140 goto ypout; 141 142 /* Add new groups to the group list */ 143 for (i = 0; i < ngroups; i++) { 144 if (groups[i] == gid) 145 break; 146 } 147 if (i == ngroups) { 148 if (ngroups >= maxgroups) { 149 ret = -1; 150 goto ypout; 151 } 152 groups[ngroups++] = gid; 153 } 154 } 155 ypout: 156 if (ypdata) 157 free(ypdata); 158 goto out; 159 } 160 #endif /* YP */ 161 162 out: 163 endgrent(); 164 *grpcnt = ngroups; 165 return (ret); 166 } 167