--- rpm-4.3.3/lib/psm.c.nss 2005-10-14 12:13:02.000000000 +0400 +++ rpm-4.3.3/lib/psm.c 2005-10-14 12:18:35.000000000 +0400 @@ -1828,20 +1828,6 @@ if (rootDir != NULL && !(rootDir[0] == '/' && rootDir[1] == '\0') && !rpmtsChrootDone(ts) && !psm->chrootDone) { - static int _pw_loaded = 0; - static int _gr_loaded = 0; - - if (!_pw_loaded) { - (void)getpwnam("root"); - endpwent(); - _pw_loaded++; - } - if (!_gr_loaded) { - (void)getgrnam("root"); - endgrent(); - _gr_loaded++; - } - xx = chdir("/"); /*@-superuser@*/ rc = chroot(rootDir); --- rpm-4.3.3/rpmio/ugid.c.nss 2005-10-14 12:13:17.000000000 +0400 +++ rpm-4.3.3/rpmio/ugid.c 2005-10-14 12:21:30.000000000 +0400 @@ -3,9 +3,313 @@ */ #include "system.h" +#include #include "ugid.h" #include "debug.h" +/* In-VPS password/group access routines */ + +struct passwd * vpsgetpwnam(const char * name) +{ + static struct passwd res; + FILE * vpspasswd; + static char buffer[MAXPATHLEN]; + int len = strlen(name); + char * uname, * passwd, * uid, * gid, * comment, * home, * shell; + + memset(&res,0,sizeof(struct passwd)); + memset(buffer,0,sizeof(buffer)); + + vpspasswd = fopen("/etc/passwd","r"); + + if(vpspasswd == NULL) + return NULL; + + while(fgets(buffer,sizeof(buffer),vpspasswd)) + { + if((strncmp(buffer,name,len) == 0) && (buffer[len] == ':')) + { /* Record for required user found */ + uname = buffer; + res.pw_name = uname; + + passwd = strchr(uname,':'); + if(!passwd) + { + fclose(vpspasswd); + return NULL; + } + + *passwd = 0; + passwd++; + res.pw_passwd = passwd; + + uid = strchr(passwd,':'); + if(!uid) + { + fclose(vpspasswd); + return NULL; + } + + *uid = 0; + uid++; + res.pw_uid = atoi(uid); + + gid = strchr(uid,':'); + if(!gid) + { + fclose(vpspasswd); + return &res; /* Actually dpkg need uid field. Leave others not filled */ + } + + *gid = 0; + gid++; + res.pw_gid = atoi(gid); + + comment = strchr(gid,':'); + if(!comment) + { + fclose(vpspasswd); + return &res; + } + + *comment = 0; + comment++; + res.pw_gecos = comment; + + home = strchr(comment,':'); + if(!home) + { + fclose(vpspasswd); + return &res; + } + + *home = 0; + home++; + res.pw_dir = home; + + shell = strchr(home,':'); + if(!shell) + { + fclose(vpspasswd); + return &res; + } + + *shell = 0; + shell++; + res.pw_shell = shell; + + fclose(vpspasswd); + return &res; + } + } + + fclose(vpspasswd); + + return NULL; +} + +struct passwd * vpsgetpwuid(uid_t id) +{ + static struct passwd res; + FILE * vpspasswd; + static char buffer[MAXPATHLEN]; + /**/ + char * uname, * passwd, * uid, * gid, * comment, * home, * shell; + + memset(&res,0,sizeof(struct passwd)); + memset(buffer,0,sizeof(buffer)); + + vpspasswd = fopen("/etc/passwd","r"); + + if(vpspasswd == NULL) + return NULL; + + while(fgets(buffer,sizeof(buffer),vpspasswd)) + { + uname = buffer; + + passwd = strchr(uname,':'); + if(!passwd) + continue; + + *passwd = 0; + passwd++; + + uid = strchr(passwd,':'); + if(!uid) + continue; + + *uid = 0; + uid++; + + if(id == atoi(uid)) + { /* Record for required user found */ + res.pw_name = uname; + + res.pw_passwd = passwd; + + res.pw_uid = id; + + gid = strchr(uid,':'); + if(!gid) + { + fclose(vpspasswd); + return &res; /* Actually dpkg need uid field. Leave others not filled */ + } + + *gid = 0; + gid++; + res.pw_gid = atoi(gid); + + comment = strchr(gid,':'); + if(!comment) + { + fclose(vpspasswd); + return &res; + } + + *comment = 0; + comment++; + res.pw_gecos = comment; + + home = strchr(comment,':'); + if(!home) + { + fclose(vpspasswd); + return &res; + } + + *home = 0; + home++; + res.pw_dir = home; + + shell = strchr(home,':'); + if(!shell) + { + fclose(vpspasswd); + return &res; + } + + *shell = 0; + shell++; + res.pw_shell = shell; + + fclose(vpspasswd); + return &res; + } + } + + fclose(vpspasswd); + + return NULL; +} + +struct group * vpsgetgrnam(const char * name) +{ + static struct group res; + FILE * vpsgroup; + static char buffer[MAXPATHLEN]; + int len = strlen(name); + char * gname,* passwd, * gid; + + memset(&res,0,sizeof(struct group)); + memset(buffer,0,sizeof(buffer)); + + vpsgroup = fopen("/etc/group","r"); + + if(vpsgroup == NULL) + return NULL; + + while(fgets(buffer,sizeof(buffer),vpsgroup)) + { + if((strncmp(buffer,name,len) == 0) && (buffer[len] == ':')) + { /* Record for required group found */ + gname = buffer; + res.gr_name = gname; + + passwd = strchr(gname,':'); + if(!passwd) + { + fclose(vpsgroup); + return NULL; + } + + *passwd = 0; + passwd++; + res.gr_passwd = passwd; + + gid = strchr(passwd,':'); + if(!gid) + { + fclose(vpsgroup); + return NULL; + } + + *gid = 0; + gid++; + res.gr_gid = atoi(gid); + + fclose(vpsgroup); + return &res; + } + } + + fclose(vpsgroup); + + return NULL; +} + +struct group * vpsgetgrgid(gid_t id) +{ + static struct group res; + FILE * vpsgroup; + static char buffer[MAXPATHLEN]; + /**/ + char * gname,* passwd, * gid; + + memset(&res,0,sizeof(struct group)); + memset(buffer,0,sizeof(buffer)); + + vpsgroup = fopen("/etc/group","r"); + + if(vpsgroup == NULL) + return NULL; + + while(fgets(buffer,sizeof(buffer),vpsgroup)) + { + gname = buffer; + + passwd = strchr(gname,':'); + if(!passwd) + continue; + *passwd = 0; + passwd++; + + gid = strchr(passwd,':'); + if(!gid) + continue; + *gid = 0; + gid++; + + if(id == atoi(gid)) + { /* Record for required group found */ + res.gr_name = gname; + + res.gr_passwd = passwd; + + res.gr_gid = id; + + fclose(vpsgroup); + + return &res; + } + } + + fclose(vpsgroup); + + return NULL; +} + /* unameToUid(), uidTouname() and the group variants are really poorly implemented. They really ought to use hash tables. I just made the guess that most files would be owned by root or the same person/group @@ -44,12 +348,12 @@ strcpy(lastUname, thisUname); /*@=boundswrite@*/ - pwent = getpwnam(thisUname); + pwent = vpsgetpwnam(thisUname); if (pwent == NULL) { /*@-internalglobs@*/ /* FIX: shrug */ - endpwent(); +/* endpwent();*/ /*@=internalglobs@*/ - pwent = getpwnam(thisUname); + pwent = vpsgetpwnam(thisUname); if (pwent == NULL) return -1; } @@ -94,12 +398,12 @@ strcpy(lastGname, thisGname); /*@=boundswrite@*/ - grent = getgrnam(thisGname); + grent = vpsgetgrnam(thisGname); if (grent == NULL) { /*@-internalglobs@*/ /* FIX: shrug */ - endgrent(); +/* endgrent();*/ /*@=internalglobs@*/ - grent = getgrnam(thisGname); + grent = vpsgetgrnam(thisGname); if (grent == NULL) { /* XXX The filesystem package needs group/lock w/o getgrnam. */ if (strcmp(thisGname, "lock") == 0) { @@ -137,7 +441,7 @@ } else if (uid == lastUid) { return lastUname; } else { - struct passwd * pwent = getpwuid(uid); + struct passwd * pwent = vpsgetpwuid(uid); size_t len; if (pwent == NULL) return NULL; @@ -170,7 +474,7 @@ } else if (gid == lastGid) { return lastGname; } else { - struct group * grent = getgrgid(gid); + struct group * grent = vpsgetgrgid(gid); size_t len; if (grent == NULL) return NULL;