/* @(#)idcache.c 1.30 15/05/01 Copyright 1993, 1995-2015 J. Schilling */ #include #ifndef lint static UConst char sccsid[] = "@(#)idcache.c 1.30 15/05/01 Copyright 1993, 1995-2015 J. Schilling"; #endif /* * UID/GID caching functions * * Copyright (c) 1993, 1995-2015 J. Schilling */ /* * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * See the file CDDL.Schily.txt in this distribution for details. * A copy of the CDDL is also available via the Internet at * http://www.opensource.org/licenses/cddl1.txt * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file CDDL.Schily.txt from this distribution. */ #include #include #include #include #include #include #include #define TUNMLEN 32 /* Max. UID name len (POSIX) */ #define TGNMLEN 32 /* Max. GID name len (POSIX) */ #define C_SIZE 16 /* Cache size (cache is static) */ typedef struct u_id { uid_t uid; char name[TUNMLEN+1]; char valid; } uidc_t; typedef struct g_id { gid_t gid; char name[TGNMLEN+1]; char valid; } gidc_t; LOCAL uidc_t uidcache[C_SIZE]; LOCAL int lastuidx; /* Last index for new entry */ LOCAL gidc_t gidcache[C_SIZE]; LOCAL int lastgidx; /* Last index for new entry */ LOCAL uid_t _uid_nobody; /* Uid for user "nobody" */ LOCAL gid_t _gid_nobody; /* Gid for user "nobody" */ LOCAL BOOL name_init = FALSE; EXPORT BOOL ic_nameuid __PR((char *name, int namelen, uid_t uid)); EXPORT BOOL ic_uidname __PR((char *name, int namelen, uid_t *uidp)); EXPORT BOOL ic_namegid __PR((char *name, int namelen, gid_t gid)); EXPORT BOOL ic_gidname __PR((char *name, int namelen, gid_t *gidp)); LOCAL void nameinit __PR((void)); EXPORT uid_t ic_uid_nobody __PR((void)); EXPORT gid_t ic_gid_nobody __PR((void)); /* * Get name from uid */ #ifdef PROTOTYPES EXPORT BOOL ic_nameuid(char *name, int namelen, uid_t uid) #else EXPORT BOOL ic_nameuid(name, namelen, uid) char *name; int namelen; uid_t uid; #endif { struct passwd *pw; register int i; register uidc_t *idp; for (i = 0, idp = uidcache; i < C_SIZE; i++, idp++) { if (idp->valid == 0) /* Entry not yet filled */ break; if (idp->uid == uid) goto out; } idp = &uidcache[lastuidx++]; /* Round robin fill next ent */ if (lastuidx >= C_SIZE) lastuidx = 0; idp->uid = uid; idp->name[0] = '\0'; idp->valid = 1; if ((pw = getpwuid(uid)) != NULL) strlcpy(idp->name, pw->pw_name, sizeof (idp->name)); out: strlcpy(name, idp->name, namelen); return (name[0] != '\0'); } /* * Get uid from name */ EXPORT BOOL ic_uidname(name, namelen, uidp) char *name; int namelen; uid_t *uidp; { struct passwd *pw; register int len = namelen > TUNMLEN?TUNMLEN:namelen; register int i; register uidc_t *idp; if (name[0] == '\0') { *uidp = ic_uid_nobody(); /* Return UID_NOBODY */ return (FALSE); } for (i = 0, idp = uidcache; i < C_SIZE; i++, idp++) { if (idp->valid == 0) /* Entry not yet filled */ break; if (name[0] == idp->name[0] && strncmp(name, idp->name, len) == 0) { *uidp = idp->uid; if (idp->valid == 2) { /* Name not found */ *uidp = ic_uid_nobody(); /* Return UID_NOBODY */ return (FALSE); } return (TRUE); } } idp = &uidcache[lastuidx++]; /* Round robin fill next ent */ if (lastuidx >= C_SIZE) lastuidx = 0; idp->uid = 0; idp->name[0] = '\0'; strlcpy(idp->name, name, len+1); /* uidc_t.name is TUNMLEN+1 */ idp->valid = 1; if ((pw = getpwnam(idp->name)) != NULL) { idp->uid = pw->pw_uid; *uidp = idp->uid; return (TRUE); } else { idp->valid = 2; /* Mark name as not found */ *uidp = ic_uid_nobody(); /* Return UID_NOBODY */ return (FALSE); } } /* * Get name from gid */ #ifdef PROTOTYPES EXPORT BOOL ic_namegid(char *name, int namelen, gid_t gid) #else EXPORT BOOL ic_namegid(name, namelen, gid) char *name; int namelen; gid_t gid; #endif { struct group *gr; register int i; register gidc_t *idp; for (i = 0, idp = gidcache; i < C_SIZE; i++, idp++) { if (idp->valid == 0) /* Entry not yet filled */ break; if (idp->gid == gid) goto out; } idp = &gidcache[lastgidx++]; /* Round robin fill next ent */ if (lastgidx >= C_SIZE) lastgidx = 0; idp->gid = gid; idp->name[0] = '\0'; idp->valid = 1; if ((gr = getgrgid(gid)) != NULL) strlcpy(idp->name, gr->gr_name, sizeof (idp->name)); out: strlcpy(name, idp->name, namelen); return (name[0] != '\0'); } /* * Get gid from name */ EXPORT BOOL ic_gidname(name, namelen, gidp) char *name; int namelen; gid_t *gidp; { struct group *gr; register int len = namelen > TGNMLEN?TGNMLEN:namelen; register int i; register gidc_t *idp; if (name[0] == '\0') { *gidp = ic_gid_nobody(); /* Return GID_NOBODY */ return (FALSE); } for (i = 0, idp = gidcache; i < C_SIZE; i++, idp++) { if (idp->valid == 0) /* Entry not yet filled */ break; if (name[0] == idp->name[0] && strncmp(name, idp->name, len) == 0) { *gidp = idp->gid; if (idp->valid == 2) { /* Name not found */ *gidp = ic_gid_nobody(); /* Return GID_NOBODY */ return (FALSE); } return (TRUE); } } idp = &gidcache[lastgidx++]; /* Round robin fill next ent */ if (lastgidx >= C_SIZE) lastgidx = 0; idp->gid = 0; idp->name[0] = '\0'; strlcpy(idp->name, name, len+1); /* gidc_t.name is TGNMLEN+1 */ idp->valid = 1; if ((gr = getgrnam(idp->name)) != NULL) { idp->gid = gr->gr_gid; *gidp = idp->gid; return (TRUE); } else { idp->valid = 2; /* Mark name as not found */ *gidp = ic_gid_nobody(); /* Return GID_NOBODY */ return (FALSE); } } #include #ifndef UID_NOBODY #define UID_NOBODY 65534 /* The old SunOS-4.x and *BSD value */ #endif #ifndef GID_NOBODY #define GID_NOBODY 65534 /* The old SunOS-4.x and *BSD value */ #endif LOCAL void nameinit() { char *name; int namelen; uid_t uid; gid_t gid; /* * Make sure that uidname()/gidname() do not call nameinit(). */ name_init = TRUE; name = "nobody"; namelen = strlen(name); if (!ic_uidname(name, namelen, &uid)) uid = UID_NOBODY; _uid_nobody = uid; if (!ic_gidname(name, namelen, &gid)) gid = GID_NOBODY; _gid_nobody = gid; } EXPORT uid_t ic_uid_nobody() { if (!name_init) nameinit(); return (_uid_nobody); } EXPORT gid_t ic_gid_nobody() { if (!name_init) nameinit(); return (_gid_nobody); }