1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 2009, Sun Microsystems, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * - Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * - Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * - Neither the name of Sun Microsystems, Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND 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 COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 /* 32 * netname utility routines convert from unix names to network names and 33 * vice-versa This module is operating system dependent! What we define here 34 * will work with any unix system that has adopted the sun NIS domain 35 * architecture. 36 */ 37 #include "namespace.h" 38 #include <sys/param.h> 39 #include <rpc/rpc.h> 40 #include <rpc/rpc_com.h> 41 #ifdef YP 42 #include <rpcsvc/yp_prot.h> 43 #include <rpcsvc/ypclnt.h> 44 #endif 45 #include <ctype.h> 46 #include <stdio.h> 47 #include <grp.h> 48 #include <pwd.h> 49 #include <string.h> 50 #include <stdlib.h> 51 #include <unistd.h> 52 #include "un-namespace.h" 53 54 static char *OPSYS = "unix"; 55 #ifdef YP 56 static char *NETID = "netid.byname"; 57 #endif 58 static char *NETIDFILE = "/etc/netid"; 59 60 static int getnetid( char *, char * ); 61 static int _getgroups( char *, gid_t [NGRPS] ); 62 63 /* 64 * Convert network-name into unix credential 65 */ 66 int 67 netname2user(char netname[MAXNETNAMELEN + 1], uid_t *uidp, gid_t *gidp, 68 int *gidlenp, gid_t *gidlist) 69 { 70 char *p; 71 int gidlen; 72 uid_t uid; 73 long luid; 74 struct passwd *pwd; 75 char val[1024]; 76 char *val1, *val2; 77 char *domain; 78 int vallen; 79 int err; 80 81 if (getnetid(netname, val)) { 82 char *res = val; 83 84 p = strsep(&res, ":"); 85 if (p == NULL) 86 return (0); 87 *uidp = (uid_t) atol(p); 88 p = strsep(&res, "\n,"); 89 if (p == NULL) { 90 return (0); 91 } 92 *gidp = (gid_t) atol(p); 93 for (gidlen = 0; gidlen < NGRPS; gidlen++) { 94 p = strsep(&res, "\n,"); 95 if (p == NULL) 96 break; 97 gidlist[gidlen] = (gid_t) atol(p); 98 } 99 *gidlenp = gidlen; 100 101 return (1); 102 } 103 val1 = strchr(netname, '.'); 104 if (val1 == NULL) 105 return (0); 106 if (strncmp(netname, OPSYS, (val1-netname))) 107 return (0); 108 val1++; 109 val2 = strchr(val1, '@'); 110 if (val2 == NULL) 111 return (0); 112 vallen = val2 - val1; 113 if (vallen > (1024 - 1)) 114 vallen = 1024 - 1; 115 (void) strncpy(val, val1, 1024); 116 val[vallen] = 0; 117 118 err = __rpc_get_default_domain(&domain); /* change to rpc */ 119 if (err) 120 return (0); 121 122 if (strcmp(val2 + 1, domain)) 123 return (0); /* wrong domain */ 124 125 if (sscanf(val, "%ld", &luid) != 1) 126 return (0); 127 uid = luid; 128 129 /* use initgroups method */ 130 pwd = getpwuid(uid); 131 if (pwd == NULL) 132 return (0); 133 *uidp = pwd->pw_uid; 134 *gidp = pwd->pw_gid; 135 *gidlenp = _getgroups(pwd->pw_name, gidlist); 136 return (1); 137 } 138 139 /* 140 * initgroups 141 */ 142 143 static int 144 _getgroups(char *uname, gid_t groups[NGRPS]) 145 { 146 gid_t ngroups = 0; 147 struct group *grp; 148 int i; 149 int j; 150 int filter; 151 152 setgrent(); 153 while ((grp = getgrent())) { 154 for (i = 0; grp->gr_mem[i]; i++) 155 if (!strcmp(grp->gr_mem[i], uname)) { 156 if (ngroups == NGRPS) { 157 #ifdef DEBUG 158 fprintf(stderr, 159 "initgroups: %s is in too many groups\n", uname); 160 #endif 161 goto toomany; 162 } 163 /* filter out duplicate group entries */ 164 filter = 0; 165 for (j = 0; j < ngroups; j++) 166 if (groups[j] == grp->gr_gid) { 167 filter++; 168 break; 169 } 170 if (!filter) 171 groups[ngroups++] = grp->gr_gid; 172 } 173 } 174 toomany: 175 endgrent(); 176 return (ngroups); 177 } 178 179 /* 180 * Convert network-name to hostname 181 */ 182 int 183 netname2host(char netname[MAXNETNAMELEN + 1], char *hostname, int hostlen) 184 { 185 int err; 186 char valbuf[1024]; 187 char *val; 188 char *val2; 189 int vallen; 190 char *domain; 191 192 if (getnetid(netname, valbuf)) { 193 val = valbuf; 194 if ((*val == '0') && (val[1] == ':')) { 195 (void) strncpy(hostname, val + 2, hostlen); 196 return (1); 197 } 198 } 199 val = strchr(netname, '.'); 200 if (val == NULL) 201 return (0); 202 if (strncmp(netname, OPSYS, (val - netname))) 203 return (0); 204 val++; 205 val2 = strchr(val, '@'); 206 if (val2 == NULL) 207 return (0); 208 vallen = val2 - val; 209 if (vallen > (hostlen - 1)) 210 vallen = hostlen - 1; 211 (void) strncpy(hostname, val, vallen); 212 hostname[vallen] = 0; 213 214 err = __rpc_get_default_domain(&domain); /* change to rpc */ 215 if (err) 216 return (0); 217 218 if (strcmp(val2 + 1, domain)) 219 return (0); /* wrong domain */ 220 else 221 return (1); 222 } 223 224 /* 225 * reads the file /etc/netid looking for a + to optionally go to the 226 * network information service. 227 */ 228 int 229 getnetid(char *key, char *ret) 230 { 231 char buf[1024]; /* big enough */ 232 char *res; 233 char *mkey; 234 char *mval; 235 FILE *fd; 236 #ifdef YP 237 char *domain; 238 int err; 239 char *lookup; 240 int len; 241 #endif 242 int rv; 243 244 rv = 0; 245 246 fd = fopen(NETIDFILE, "r"); 247 if (fd == NULL) { 248 #ifdef YP 249 res = "+"; 250 goto getnetidyp; 251 #else 252 return (0); 253 #endif 254 } 255 while (fd != NULL) { 256 res = fgets(buf, sizeof(buf), fd); 257 if (res == NULL) { 258 rv = 0; 259 goto done; 260 } 261 if (res[0] == '#') 262 continue; 263 else if (res[0] == '+') { 264 #ifdef YP 265 getnetidyp: 266 err = yp_get_default_domain(&domain); 267 if (err) { 268 continue; 269 } 270 lookup = NULL; 271 err = yp_match(domain, NETID, key, 272 strlen(key), &lookup, &len); 273 if (err) { 274 #ifdef DEBUG 275 fprintf(stderr, "match failed error %d\n", err); 276 #endif 277 continue; 278 } 279 lookup[len] = 0; 280 strcpy(ret, lookup); 281 free(lookup); 282 rv = 2; 283 goto done; 284 #else /* YP */ 285 #ifdef DEBUG 286 fprintf(stderr, 287 "Bad record in %s '+' -- NIS not supported in this library copy\n", 288 NETIDFILE); 289 #endif 290 continue; 291 #endif /* YP */ 292 } else { 293 mkey = strsep(&res, "\t "); 294 if (mkey == NULL) { 295 fprintf(stderr, 296 "Bad record in %s -- %s", NETIDFILE, buf); 297 continue; 298 } 299 do { 300 mval = strsep(&res, " \t#\n"); 301 } while (mval != NULL && !*mval); 302 if (mval == NULL) { 303 fprintf(stderr, 304 "Bad record in %s val problem - %s", NETIDFILE, buf); 305 continue; 306 } 307 if (strcmp(mkey, key) == 0) { 308 strcpy(ret, mval); 309 rv = 1; 310 goto done; 311 } 312 } 313 } 314 315 done: 316 if (fd != NULL) 317 fclose(fd); 318 return (rv); 319 } 320