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