/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * netname utility routines convert from unix names to network names and * vice-versa This module is operating system dependent! What we define here * will work with any unix system that has adopted the sun NIS domain * architecture. */ #include #ifndef _WIN32 #include #include #include "rpc_com.h" #ifdef YP #include #include #endif #include #include #include #include #include #include #include static char *OPSYS = "unix"; static char *NETID = "netid.byname"; static char *NETIDFILE = "/etc/netid"; static int getnetid( char *, char * ); static int _getgroups( char *, gid_t * ); #ifndef NGROUPS #define NGROUPS 16 #endif /* * Convert network-name into unix credential */ int netname2user(netname, uidp, gidp, gidlenp, gidlist) char netname[MAXNETNAMELEN + 1]; uid_t *uidp; gid_t *gidp; int *gidlenp; gid_t *gidlist; { char *p; int gidlen; uid_t uid; long luid; struct passwd *pwd; char val[1024]; char *val1, *val2; char *domain; int vallen; int err; if (getnetid(netname, val)) { char *res = val; p = strsep(&res, ":"); if (p == NULL) return (0); *uidp = (uid_t) atol(p); p = strsep(&res, "\n,"); if (p == NULL) { return (0); } *gidp = (gid_t) atol(p); gidlen = 0; for (gidlen = 0; gidlen < NGROUPS; gidlen++) { p = strsep(&res, "\n,"); if (p == NULL) break; gidlist[gidlen] = (gid_t) atol(p); } *gidlenp = gidlen; return (1); } val1 = strchr(netname, '.'); if (val1 == NULL) return (0); if (strncmp(netname, OPSYS, (val1-netname))) return (0); val1++; val2 = strchr(val1, '@'); if (val2 == NULL) return (0); vallen = val2 - val1; if (vallen > (1024 - 1)) vallen = 1024 - 1; (void) strncpy(val, val1, 1024); val[vallen] = 0; err = __rpc_get_default_domain(&domain); /* change to rpc */ if (err) return (0); if (strcmp(val2 + 1, domain)) return (0); /* wrong domain */ if (sscanf(val, "%ld", &luid) != 1) return (0); uid = luid; /* use initgroups method */ pwd = getpwuid(uid); if (pwd == NULL) return (0); *uidp = pwd->pw_uid; *gidp = pwd->pw_gid; *gidlenp = _getgroups(pwd->pw_name, gidlist); return (1); } /* * initgroups */ static int _getgroups(uname, groups) char *uname; gid_t groups[NGROUPS]; { gid_t ngroups = 0; struct group *grp; int i; int j; int filter; setgrent(); while ((grp = getgrent())) { for (i = 0; grp->gr_mem[i]; i++) if (!strcmp(grp->gr_mem[i], uname)) { if (ngroups == NGROUPS) { #ifdef DEBUG fprintf(stderr, "initgroups: %s is in too many groups\n", uname); #endif goto toomany; } /* filter out duplicate group entries */ filter = 0; for (j = 0; j < ngroups; j++) if (groups[j] == grp->gr_gid) { filter++; break; } if (!filter) groups[ngroups++] = grp->gr_gid; } } toomany: endgrent(); return (ngroups); } /* * Convert network-name to hostname */ int netname2host(netname, hostname, hostlen) char netname[MAXNETNAMELEN + 1]; char *hostname; int hostlen; { int err; char valbuf[1024]; char *val; char *val2; int vallen; char *domain; if (getnetid(netname, valbuf)) { val = valbuf; if ((*val == '0') && (val[1] == ':')) { (void) strncpy(hostname, val + 2, hostlen); return (1); } } val = strchr(netname, '.'); if (val == NULL) return (0); if (strncmp(netname, OPSYS, (val - netname))) return (0); val++; val2 = strchr(val, '@'); if (val2 == NULL) return (0); vallen = val2 - val; if (vallen > (hostlen - 1)) vallen = hostlen - 1; (void) strncpy(hostname, val, vallen); hostname[vallen] = 0; err = __rpc_get_default_domain(&domain); /* change to rpc */ if (err) return (0); if (strcmp(val2 + 1, domain)) return (0); /* wrong domain */ else return (1); } /* * reads the file /etc/netid looking for a + to optionally go to the * network information service. */ int getnetid(key, ret) char *key, *ret; { char buf[1024]; /* big enough */ char *res; char *mkey; char *mval; FILE *fd; #ifdef YP char *domain; int err; char *lookup; int len; #endif fd = fopen(NETIDFILE, "r"); if (fd == NULL) { #ifdef YP res = "+"; goto getnetidyp; #else return (0); #endif } for (;;) { if (fd == NULL) return (0); /* getnetidyp brings us here */ res = fgets(buf, sizeof(buf), fd); if (res == NULL) { fclose(fd); return (0); } if (res[0] == '#') continue; else if (res[0] == '+') { #ifdef YP getnetidyp: err = yp_get_default_domain(&domain); if (err) { continue; } lookup = NULL; err = yp_match(domain, NETID, key, strlen(key), &lookup, &len); if (err) { #ifdef DEBUG fprintf(stderr, "match failed error %d\n", err); #endif continue; } lookup[len] = 0; strcpy(ret, lookup); free(lookup); if (fd != NULL) fclose(fd); return (2); #else /* YP */ #ifdef DEBUG fprintf(stderr, "Bad record in %s '+' -- NIS not supported in this library copy\n", NETIDFILE); #endif continue; #endif /* YP */ } else { mkey = strsep(&res, "\t "); if (mkey == NULL) { fprintf(stderr, "Bad record in %s -- %s", NETIDFILE, buf); continue; } do { mval = strsep(&res, " \t#\n"); } while (mval != NULL && !*mval); if (mval == NULL) { fprintf(stderr, "Bad record in %s val problem - %s", NETIDFILE, buf); continue; } if (strcmp(mkey, key) == 0) { strcpy(ret, mval); fclose(fd); return (1); } } } } #endif /* !_WIN32 */