home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1998 February
/
CHIP_2_98.iso
/
misc
/
src
/
rpm
/
lib
/
verify.c
< prev
Wrap
C/C++ Source or Header
|
1997-09-17
|
8KB
|
301 lines
#include "config.h"
#include "miscfn.h"
#if HAVE_ALLOCA_H
# include <alloca.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include "md5.h"
#include "misc.h"
#include "messages.h"
#include "rpmlib.h"
#define S_ISDEV(m) (S_ISBLK((m)) || S_ISCHR((m)))
static char * SCRIPT_PATH = "PATH=/sbin:/bin:/usr/sbin:/usr/bin:"
"/usr/X11R6/bin\nexport PATH\n";
int rpmVerifyFile(char * prefix, Header h, int filenum, int * result,
int omitMask) {
char ** fileList, ** md5List, ** linktoList;
int_32 * verifyFlags, flags;
int_32 * sizeList, * mtimeList;
unsigned short * modeList, * rdevList;
char * fileStatesList;
char * filespec;
char * name;
int type, count, rc;
struct stat sb;
unsigned char md5sum[40];
int_32 * uidList, * gidList;
char linkto[1024];
int size;
char ** unameList, ** gnameList;
int_32 useBrokenMd5;
#if WORDS_BIGENDIAN
int_32 * brokenPtr;
#endif
#if WORDS_BIGENDIAN
if (!headerGetEntry(h, RPMTAG_BROKENMD5, NULL, (void **) &brokenPtr, NULL)) {
char * rpmVersion;
if (headerGetEntry(h, RPMTAG_RPMVERSION, NULL, (void **) &rpmVersion,
NULL)) {
useBrokenMd5 = ((rpmvercmp(rpmVersion, "2.3.3") >= 0) &&
(rpmvercmp(rpmVersion, "2.3.8") <= 0));
} else {
useBrokenMd5 = 1;
}
headerAddEntry(h, RPMTAG_BROKENMD5, RPM_INT32_TYPE, &useBrokenMd5, 1);
} else {
useBrokenMd5 = *brokenPtr;
}
#else
useBrokenMd5 = 0;
#endif
headerGetEntry(h, RPMTAG_FILEMODES, &type, (void **) &modeList, &count);
if (headerGetEntry(h, RPMTAG_FILEVERIFYFLAGS, &type, (void **) &verifyFlags,
&count)) {
flags = verifyFlags[filenum];
} else {
flags = RPMVERIFY_ALL;
}
headerGetEntry(h, RPMTAG_FILENAMES, &type, (void **) &fileList, &count);
filespec = alloca(strlen(fileList[filenum]) + strlen(prefix) + 5);
strcpy(filespec, prefix);
strcat(filespec, "/");
strcat(filespec, fileList[filenum]);
free(fileList);
*result = 0;
/* Check to see if the file was installed - if not pretend all is OK */
if (headerGetEntry(h, RPMTAG_FILESTATES, &type,
(void **) &fileStatesList, &count) && fileStatesList) {
if (fileStatesList[filenum] == RPMFILE_STATE_NOTINSTALLED)
return 0;
}
if (lstat(filespec, &sb))
return 1;
if (S_ISDIR(sb.st_mode))
flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
RPMVERIFY_LINKTO);
else if (S_ISLNK(sb.st_mode)) {
flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME);
#if CHOWN_FOLLOWS_SYMLINK
flags &= ~(RPMVERIFY_USER | RPMVERIFY_GROUP);
#endif
}
else if (S_ISFIFO(sb.st_mode))
flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
RPMVERIFY_LINKTO);
else if (S_ISCHR(sb.st_mode))
flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
RPMVERIFY_LINKTO);
else if (S_ISBLK(sb.st_mode))
flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
RPMVERIFY_LINKTO);
else
flags &= ~(RPMVERIFY_LINKTO);
/* Don't verify any features in omitMask */
flags &= ~omitMask;
if (flags & RPMVERIFY_MD5) {
headerGetEntry(h, RPMTAG_FILEMD5S, &type, (void **) &md5List, &count);
if (useBrokenMd5) {
rc = mdfileBroken(filespec, md5sum);
} else {
rc = mdfile(filespec, md5sum);
}
if (rc || strcmp(md5sum, md5List[filenum]))
*result |= RPMVERIFY_MD5;
free(md5List);
}
if (flags & RPMVERIFY_LINKTO) {
headerGetEntry(h, RPMTAG_FILELINKTOS, &type, (void **) &linktoList, &count);
size = readlink(filespec, linkto, sizeof(linkto));
if (size == -1)
*result |= RPMVERIFY_LINKTO;
else
linkto[size] = '\0';
if (strcmp(linkto, linktoList[filenum]))
*result |= RPMVERIFY_LINKTO;
free(linktoList);
}
if (flags & RPMVERIFY_FILESIZE) {
headerGetEntry(h, RPMTAG_FILESIZES, &type, (void **) &sizeList, &count);
if (sizeList[filenum] != sb.st_size)
*result |= RPMVERIFY_FILESIZE;
}
if (flags & RPMVERIFY_MODE) {
if (modeList[filenum] != sb.st_mode)
*result |= RPMVERIFY_MODE;
}
if (flags & RPMVERIFY_RDEV) {
if (S_ISCHR(modeList[filenum]) != S_ISCHR(sb.st_mode) ||
S_ISBLK(modeList[filenum]) != S_ISBLK(sb.st_mode)) {
*result |= RPMVERIFY_RDEV;
} else if (S_ISDEV(modeList[filenum]) && S_ISDEV(sb.st_mode)) {
headerGetEntry(h, RPMTAG_FILERDEVS, NULL, (void **) &rdevList,
NULL);
if (rdevList[filenum] != sb.st_rdev)
*result |= RPMVERIFY_RDEV;
}
}
if (flags & RPMVERIFY_MTIME) {
headerGetEntry(h, RPMTAG_FILEMTIMES, NULL, (void **) &mtimeList, NULL);
if (mtimeList[filenum] != sb.st_mtime)
*result |= RPMVERIFY_MTIME;
}
if (flags & RPMVERIFY_USER) {
if (headerGetEntry(h, RPMTAG_FILEUSERNAME, NULL, (void **) &unameList,
NULL)) {
name = uidToUname(sb.st_uid);
if (!name || strcmp(unameList[filenum], name))
*result |= RPMVERIFY_USER;
free(unameList);
} else if (headerGetEntry(h, RPMTAG_FILEUIDS, NULL, (void **) &uidList,
&count)) {
if (uidList[filenum] != sb.st_uid)
*result |= RPMVERIFY_GROUP;
} else {
rpmError(RPMERR_INTERNAL, "package lacks both user name and id "
"lists (this should never happen)");
*result |= RPMVERIFY_GROUP;
}
}
if (flags & RPMVERIFY_GROUP) {
if (headerGetEntry(h, RPMTAG_FILEGROUPNAME, NULL, (void **) &gnameList,
NULL)) {
name = gidToGname(sb.st_gid);
if (!name || strcmp(gnameList[filenum], name))
*result |= RPMVERIFY_GROUP;
free(gnameList);
} else if (headerGetEntry(h, RPMTAG_FILEGIDS, NULL, (void **) &gidList,
&count)) {
if (gidList[filenum] != sb.st_gid)
*result |= RPMVERIFY_GROUP;
} else {
rpmError(RPMERR_INTERNAL, "package lacks both group name and id "
"lists (this should never happen)");
*result |= RPMVERIFY_GROUP;
}
}
return 0;
}
int rpmVerifyScript(char * root, Header h, int err) {
int out, fd;
char * script;
char * fn;
char * tmpdir = rpmGetVar(RPMVAR_TMPPATH);
int status;
char * installPrefixEnv = NULL;
char * installPrefix;
if (!headerGetEntry(h, RPMTAG_VERIFYSCRIPT, NULL, (void **) &script,
NULL)) {
return 0;
}
if (rpmIsVerbose()) {
out = err;
} else {
out = open("/dev/null", O_APPEND);
if (out < 0) {
out = err;
}
}
fn = alloca(strlen(tmpdir) + 20);
sprintf(fn, "%s/rpm-%d.vscript", tmpdir, (int) getpid());
rpmMessage(RPMMESS_DEBUG, "verify script found - "
"running from file %s\n", fn);
fd = open(fn, O_CREAT | O_RDWR);
unlink(fn);
if (fd < 0) {
rpmError(RPMERR_SCRIPT, "error creating file for verify script");
return 1;
}
write(fd, SCRIPT_PATH, strlen(SCRIPT_PATH));
write(fd, script, strlen(script));
lseek(fd, 0, SEEK_SET);
if (headerGetEntry(h, RPMTAG_INSTALLPREFIX, NULL, (void **) &installPrefix,
NULL)) {
installPrefixEnv = alloca(strlen(installPrefix) + 30);
strcpy(installPrefixEnv, "RPM_INSTALL_PREFIX=");
strcat(installPrefixEnv, installPrefix);
}
if (!fork()) {
if (installPrefixEnv) {
doputenv(installPrefixEnv);
}
dup2(fd, 0);
close(fd);
if (err != 2) dup2(err, 2);
if (out != 1) dup2(out, 1);
/* make sure we don't close stdin/stderr/stdout by mistake! */
if (err > 2) close (err);
if (out > 2 && out != err) close (out);
if (strcmp(root, "/")) {
rpmMessage(RPMMESS_DEBUG, "performing chroot(%s)\n", root);
chroot(root);
chdir("/");
}
if (rpmIsDebug())
execl("/bin/sh", "/bin/sh", "-x", "-s", NULL);
else
execl("/bin/sh", "/bin/sh", "-s", NULL);
exit(-1);
}
if (out > 2) close(out);
if (err > 2) close(err);
close(fd);
if (!rpmIsVerbose()) close(out);
wait(&status);
if (!WIFEXITED(status) || WEXITSTATUS(status)) {
rpmError(RPMERR_SCRIPT, "execution of verify script failed");
return 1;
}
return 0;
}