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(netname, uidp, gidp, gidlenp, gidlist) 72 char netname[MAXNETNAMELEN + 1]; 73 uid_t *uidp; 74 gid_t *gidp; 75 int *gidlenp; 76 gid_t *gidlist; 77 { 78 char *p; 79 int gidlen; 80 uid_t uid; 81 long luid; 82 struct passwd *pwd; 83 char val[1024]; 84 char *val1, *val2; 85 char *domain; 86 int vallen; 87 int err; 88 89 if (getnetid(netname, val)) { 90 char *res = val; 91 92 p = strsep(&res, ":"); 93 if (p == NULL) 94 return (0); 95 *uidp = (uid_t) atol(p); 96 p = strsep(&res, "\n,"); 97 if (p == NULL) { 98 return (0); 99 } 100 *gidp = (gid_t) atol(p); 101 for (gidlen = 0; gidlen < NGRPS; gidlen++) { 102 p = strsep(&res, "\n,"); 103 if (p == NULL) 104 break; 105 gidlist[gidlen] = (gid_t) atol(p); 106 } 107 *gidlenp = gidlen; 108 109 return (1); 110 } 111 val1 = strchr(netname, '.'); 112 if (val1 == NULL) 113 return (0); 114 if (strncmp(netname, OPSYS, (val1-netname))) 115 return (0); 116 val1++; 117 val2 = strchr(val1, '@'); 118 if (val2 == NULL) 119 return (0); 120 vallen = val2 - val1; 121 if (vallen > (1024 - 1)) 122 vallen = 1024 - 1; 123 (void) strncpy(val, val1, 1024); 124 val[vallen] = 0; 125 126 err = __rpc_get_default_domain(&domain); /* change to rpc */ 127 if (err) 128 return (0); 129 130 if (strcmp(val2 + 1, domain)) 131 return (0); /* wrong domain */ 132 133 if (sscanf(val, "%ld", &luid) != 1) 134 return (0); 135 uid = luid; 136 137 /* use initgroups method */ 138 pwd = getpwuid(uid); 139 if (pwd == NULL) 140 return (0); 141 *uidp = pwd->pw_uid; 142 *gidp = pwd->pw_gid; 143 *gidlenp = _getgroups(pwd->pw_name, gidlist); 144 return (1); 145 } 146 147 /* 148 * initgroups 149 */ 150 151 static int 152 _getgroups(uname, groups) 153 char *uname; 154 gid_t groups[NGRPS]; 155 { 156 gid_t ngroups = 0; 157 struct group *grp; 158 int i; 159 int j; 160 int filter; 161 162 setgrent(); 163 while ((grp = getgrent())) { 164 for (i = 0; grp->gr_mem[i]; i++) 165 if (!strcmp(grp->gr_mem[i], uname)) { 166 if (ngroups == NGRPS) { 167 #ifdef DEBUG 168 fprintf(stderr, 169 "initgroups: %s is in too many groups\n", uname); 170 #endif 171 goto toomany; 172 } 173 /* filter out duplicate group entries */ 174 filter = 0; 175 for (j = 0; j < ngroups; j++) 176 if (groups[j] == grp->gr_gid) { 177 filter++; 178 break; 179 } 180 if (!filter) 181 groups[ngroups++] = grp->gr_gid; 182 } 183 } 184 toomany: 185 endgrent(); 186 return (ngroups); 187 } 188 189 /* 190 * Convert network-name to hostname 191 */ 192 int 193 netname2host(netname, hostname, hostlen) 194 char netname[MAXNETNAMELEN + 1]; 195 char *hostname; 196 int hostlen; 197 { 198 int err; 199 char valbuf[1024]; 200 char *val; 201 char *val2; 202 int vallen; 203 char *domain; 204 205 if (getnetid(netname, valbuf)) { 206 val = valbuf; 207 if ((*val == '0') && (val[1] == ':')) { 208 (void) strncpy(hostname, val + 2, hostlen); 209 return (1); 210 } 211 } 212 val = strchr(netname, '.'); 213 if (val == NULL) 214 return (0); 215 if (strncmp(netname, OPSYS, (val - netname))) 216 return (0); 217 val++; 218 val2 = strchr(val, '@'); 219 if (val2 == NULL) 220 return (0); 221 vallen = val2 - val; 222 if (vallen > (hostlen - 1)) 223 vallen = hostlen - 1; 224 (void) strncpy(hostname, val, vallen); 225 hostname[vallen] = 0; 226 227 err = __rpc_get_default_domain(&domain); /* change to rpc */ 228 if (err) 229 return (0); 230 231 if (strcmp(val2 + 1, domain)) 232 return (0); /* wrong domain */ 233 else 234 return (1); 235 } 236 237 /* 238 * reads the file /etc/netid looking for a + to optionally go to the 239 * network information service. 240 */ 241 int 242 getnetid(key, ret) 243 char *key, *ret; 244 { 245 char buf[1024]; /* big enough */ 246 char *res; 247 char *mkey; 248 char *mval; 249 FILE *fd; 250 #ifdef YP 251 char *domain; 252 int err; 253 char *lookup; 254 int len; 255 #endif 256 257 fd = fopen(NETIDFILE, "r"); 258 if (fd == NULL) { 259 #ifdef YP 260 res = "+"; 261 goto getnetidyp; 262 #else 263 return (0); 264 #endif 265 } 266 for (;;) { 267 if (fd == NULL) 268 return (0); /* getnetidyp brings us here */ 269 res = fgets(buf, sizeof(buf), fd); 270 if (res == NULL) { 271 fclose(fd); 272 return (0); 273 } 274 if (res[0] == '#') 275 continue; 276 else if (res[0] == '+') { 277 #ifdef YP 278 getnetidyp: 279 err = yp_get_default_domain(&domain); 280 if (err) { 281 continue; 282 } 283 lookup = NULL; 284 err = yp_match(domain, NETID, key, 285 strlen(key), &lookup, &len); 286 if (err) { 287 #ifdef DEBUG 288 fprintf(stderr, "match failed error %d\n", err); 289 #endif 290 continue; 291 } 292 lookup[len] = 0; 293 strcpy(ret, lookup); 294 free(lookup); 295 if (fd != NULL) 296 fclose(fd); 297 return (2); 298 #else /* YP */ 299 #ifdef DEBUG 300 fprintf(stderr, 301 "Bad record in %s '+' -- NIS not supported in this library copy\n", 302 NETIDFILE); 303 #endif 304 continue; 305 #endif /* YP */ 306 } else { 307 mkey = strsep(&res, "\t "); 308 if (mkey == NULL) { 309 fprintf(stderr, 310 "Bad record in %s -- %s", NETIDFILE, buf); 311 continue; 312 } 313 do { 314 mval = strsep(&res, " \t#\n"); 315 } while (mval != NULL && !*mval); 316 if (mval == NULL) { 317 fprintf(stderr, 318 "Bad record in %s val problem - %s", NETIDFILE, buf); 319 continue; 320 } 321 if (strcmp(mkey, key) == 0) { 322 strcpy(ret, mval); 323 fclose(fd); 324 return (1); 325 326 } 327 } 328 } 329 } 330