home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / misc / src / rpm / lib / verify.c < prev   
C/C++ Source or Header  |  1997-09-17  |  8KB  |  301 lines

  1. #include "config.h"
  2. #include "miscfn.h"
  3.  
  4. #if HAVE_ALLOCA_H
  5. # include <alloca.h>
  6. #endif
  7.  
  8. #include <errno.h>
  9. #include <fcntl.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <sys/time.h>
  13. #include <sys/resource.h>
  14. #include <sys/stat.h>
  15. #include <sys/wait.h>
  16. #include <unistd.h>
  17.  
  18. #include "md5.h"
  19. #include "misc.h"
  20. #include "messages.h"
  21. #include "rpmlib.h"
  22.  
  23. #define S_ISDEV(m) (S_ISBLK((m)) || S_ISCHR((m)))
  24.  
  25. static char * SCRIPT_PATH = "PATH=/sbin:/bin:/usr/sbin:/usr/bin:"
  26.                              "/usr/X11R6/bin\nexport PATH\n";
  27.  
  28. int rpmVerifyFile(char * prefix, Header h, int filenum, int * result, 
  29.           int omitMask) {
  30.     char ** fileList, ** md5List, ** linktoList;
  31.     int_32 * verifyFlags, flags;
  32.     int_32 * sizeList, * mtimeList;
  33.     unsigned short * modeList, * rdevList;
  34.     char * fileStatesList;
  35.     char * filespec;
  36.     char * name;
  37.     int type, count, rc;
  38.     struct stat sb;
  39.     unsigned char md5sum[40];
  40.     int_32 * uidList, * gidList;
  41.     char linkto[1024];
  42.     int size;
  43.     char ** unameList, ** gnameList;
  44.     int_32 useBrokenMd5;
  45. #if WORDS_BIGENDIAN
  46.     int_32 * brokenPtr;
  47. #endif
  48.  
  49. #if WORDS_BIGENDIAN
  50.     if (!headerGetEntry(h, RPMTAG_BROKENMD5, NULL, (void **) &brokenPtr, NULL)) {
  51.     char * rpmVersion;
  52.  
  53.     if (headerGetEntry(h, RPMTAG_RPMVERSION, NULL, (void **) &rpmVersion, 
  54.                 NULL)) {
  55.         useBrokenMd5 = ((rpmvercmp(rpmVersion, "2.3.3") >= 0) &&
  56.                 (rpmvercmp(rpmVersion, "2.3.8") <= 0));
  57.     } else {
  58.         useBrokenMd5 = 1;
  59.     }
  60.     headerAddEntry(h, RPMTAG_BROKENMD5, RPM_INT32_TYPE, &useBrokenMd5, 1);
  61.     } else {
  62.     useBrokenMd5 = *brokenPtr;
  63.     }
  64. #else
  65.     useBrokenMd5 = 0;
  66. #endif
  67.  
  68.     headerGetEntry(h, RPMTAG_FILEMODES, &type, (void **) &modeList, &count);
  69.  
  70.     if (headerGetEntry(h, RPMTAG_FILEVERIFYFLAGS, &type, (void **) &verifyFlags, 
  71.          &count)) {
  72.     flags = verifyFlags[filenum];
  73.     } else {
  74.     flags = RPMVERIFY_ALL;
  75.     }
  76.  
  77.     headerGetEntry(h, RPMTAG_FILENAMES, &type, (void **) &fileList, &count);
  78.     filespec = alloca(strlen(fileList[filenum]) + strlen(prefix) + 5);
  79.     strcpy(filespec, prefix);
  80.     strcat(filespec, "/");
  81.     strcat(filespec, fileList[filenum]);
  82.  
  83.     free(fileList);
  84.     
  85.     *result = 0;
  86.  
  87.     /* Check to see if the file was installed - if not pretend all is OK */
  88.     if (headerGetEntry(h, RPMTAG_FILESTATES, &type, 
  89.          (void **) &fileStatesList, &count) && fileStatesList) {
  90.     if (fileStatesList[filenum] == RPMFILE_STATE_NOTINSTALLED)
  91.         return 0;
  92.     }
  93.  
  94.     if (lstat(filespec, &sb)) 
  95.     return 1;
  96.  
  97.     if (S_ISDIR(sb.st_mode))
  98.     flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME | 
  99.             RPMVERIFY_LINKTO);
  100.     else if (S_ISLNK(sb.st_mode)) {
  101.     flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME);
  102.         #if CHOWN_FOLLOWS_SYMLINK
  103.         flags &= ~(RPMVERIFY_USER | RPMVERIFY_GROUP);
  104.         #endif
  105.     }
  106.     else if (S_ISFIFO(sb.st_mode))
  107.     flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME | 
  108.             RPMVERIFY_LINKTO);
  109.     else if (S_ISCHR(sb.st_mode))
  110.     flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME | 
  111.             RPMVERIFY_LINKTO);
  112.     else if (S_ISBLK(sb.st_mode))
  113.     flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME | 
  114.             RPMVERIFY_LINKTO);
  115.     else 
  116.     flags &= ~(RPMVERIFY_LINKTO);
  117.  
  118.     /* Don't verify any features in omitMask */
  119.     flags &= ~omitMask;
  120.  
  121.     if (flags & RPMVERIFY_MD5) {
  122.     headerGetEntry(h, RPMTAG_FILEMD5S, &type, (void **) &md5List, &count);
  123.     if (useBrokenMd5) {
  124.         rc = mdfileBroken(filespec, md5sum);
  125.     } else {
  126.         rc = mdfile(filespec, md5sum);
  127.     }
  128.  
  129.     if (rc || strcmp(md5sum, md5List[filenum]))
  130.         *result |= RPMVERIFY_MD5;
  131.     free(md5List);
  132.     } 
  133.     if (flags & RPMVERIFY_LINKTO) {
  134.     headerGetEntry(h, RPMTAG_FILELINKTOS, &type, (void **) &linktoList, &count);
  135.     size = readlink(filespec, linkto, sizeof(linkto));
  136.     if (size == -1)
  137.         *result |= RPMVERIFY_LINKTO;
  138.     else 
  139.         linkto[size] = '\0';
  140.         if (strcmp(linkto, linktoList[filenum]))
  141.         *result |= RPMVERIFY_LINKTO;
  142.     free(linktoList);
  143.     } 
  144.  
  145.     if (flags & RPMVERIFY_FILESIZE) {
  146.     headerGetEntry(h, RPMTAG_FILESIZES, &type, (void **) &sizeList, &count);
  147.     if (sizeList[filenum] != sb.st_size)
  148.         *result |= RPMVERIFY_FILESIZE;
  149.     } 
  150.  
  151.     if (flags & RPMVERIFY_MODE) {
  152.     if (modeList[filenum] != sb.st_mode)
  153.         *result |= RPMVERIFY_MODE;
  154.     }
  155.  
  156.     if (flags & RPMVERIFY_RDEV) {
  157.     if (S_ISCHR(modeList[filenum]) != S_ISCHR(sb.st_mode) ||
  158.         S_ISBLK(modeList[filenum]) != S_ISBLK(sb.st_mode)) {
  159.         *result |= RPMVERIFY_RDEV;
  160.     } else if (S_ISDEV(modeList[filenum]) && S_ISDEV(sb.st_mode)) {
  161.         headerGetEntry(h, RPMTAG_FILERDEVS, NULL, (void **) &rdevList, 
  162.                NULL);
  163.         if (rdevList[filenum] != sb.st_rdev)
  164.         *result |= RPMVERIFY_RDEV;
  165.     } 
  166.     }
  167.  
  168.     if (flags & RPMVERIFY_MTIME) {
  169.     headerGetEntry(h, RPMTAG_FILEMTIMES, NULL, (void **) &mtimeList, NULL);
  170.     if (mtimeList[filenum] != sb.st_mtime)
  171.         *result |= RPMVERIFY_MTIME;
  172.     }
  173.  
  174.     if (flags & RPMVERIFY_USER) {
  175.     if (headerGetEntry(h, RPMTAG_FILEUSERNAME, NULL, (void **) &unameList, 
  176.                NULL)) {
  177.         name = uidToUname(sb.st_uid);
  178.         if (!name || strcmp(unameList[filenum], name))
  179.         *result |= RPMVERIFY_USER;
  180.         free(unameList);
  181.     } else if (headerGetEntry(h, RPMTAG_FILEUIDS, NULL, (void **) &uidList, 
  182.                   &count)) {
  183.         if (uidList[filenum] != sb.st_uid)
  184.         *result |= RPMVERIFY_GROUP;
  185.     } else {
  186.         rpmError(RPMERR_INTERNAL, "package lacks both user name and id "
  187.           "lists (this should never happen)");
  188.         *result |= RPMVERIFY_GROUP;
  189.     }
  190.     }
  191.  
  192.     if (flags & RPMVERIFY_GROUP) {
  193.     if (headerGetEntry(h, RPMTAG_FILEGROUPNAME, NULL, (void **) &gnameList, 
  194.             NULL)) {
  195.         name = gidToGname(sb.st_gid);
  196.         if (!name || strcmp(gnameList[filenum], name))
  197.         *result |= RPMVERIFY_GROUP;
  198.         free(gnameList);
  199.     } else if (headerGetEntry(h, RPMTAG_FILEGIDS, NULL, (void **) &gidList, 
  200.                   &count)) {
  201.         if (gidList[filenum] != sb.st_gid)
  202.         *result |= RPMVERIFY_GROUP;
  203.     } else {
  204.         rpmError(RPMERR_INTERNAL, "package lacks both group name and id "
  205.              "lists (this should never happen)");
  206.         *result |= RPMVERIFY_GROUP;
  207.     }
  208.     }
  209.  
  210.     return 0;
  211. }
  212.  
  213. int rpmVerifyScript(char * root, Header h, int err) {
  214.     int out, fd;
  215.     char * script;
  216.     char * fn;
  217.     char * tmpdir = rpmGetVar(RPMVAR_TMPPATH);
  218.     int status;
  219.     char * installPrefixEnv = NULL;
  220.     char * installPrefix;
  221.  
  222.     if (!headerGetEntry(h, RPMTAG_VERIFYSCRIPT, NULL, (void **) &script, 
  223.             NULL)) {
  224.     return 0;
  225.     }
  226.  
  227.     if (rpmIsVerbose()) {
  228.     out = err;
  229.     } else {
  230.     out = open("/dev/null", O_APPEND);
  231.     if (out < 0) {
  232.         out = err;
  233.     }
  234.     }
  235.  
  236.     fn = alloca(strlen(tmpdir) + 20);
  237.     sprintf(fn, "%s/rpm-%d.vscript", tmpdir, (int) getpid());
  238.  
  239.     rpmMessage(RPMMESS_DEBUG, "verify script found - "
  240.         "running from file %s\n", fn);
  241.  
  242.     fd = open(fn, O_CREAT | O_RDWR);
  243.     unlink(fn);
  244.     if (fd < 0) {
  245.     rpmError(RPMERR_SCRIPT, "error creating file for verify script");
  246.     return 1;
  247.     }
  248.     write(fd, SCRIPT_PATH, strlen(SCRIPT_PATH));
  249.     write(fd, script, strlen(script));
  250.     lseek(fd, 0, SEEK_SET);
  251.  
  252.     if (headerGetEntry(h, RPMTAG_INSTALLPREFIX, NULL, (void **) &installPrefix,
  253.          NULL)) {
  254.     installPrefixEnv = alloca(strlen(installPrefix) + 30);
  255.     strcpy(installPrefixEnv, "RPM_INSTALL_PREFIX=");
  256.     strcat(installPrefixEnv, installPrefix);
  257.     }
  258.  
  259.     if (!fork()) {
  260.     if (installPrefixEnv) {
  261.         doputenv(installPrefixEnv);
  262.     }
  263.  
  264.     dup2(fd, 0);
  265.     close(fd);
  266.  
  267.     if (err != 2) dup2(err, 2);
  268.         if (out != 1) dup2(out, 1);
  269.  
  270.     /* make sure we don't close stdin/stderr/stdout by mistake! */
  271.     if (err > 2) close (err);
  272.     if (out > 2 && out != err) close (out);
  273.  
  274.     if (strcmp(root, "/")) {
  275.         rpmMessage(RPMMESS_DEBUG, "performing chroot(%s)\n", root);
  276.         chroot(root);
  277.         chdir("/");
  278.     }
  279.  
  280.     if (rpmIsDebug())
  281.         execl("/bin/sh", "/bin/sh", "-x", "-s", NULL);
  282.     else
  283.         execl("/bin/sh", "/bin/sh", "-s", NULL);
  284.     exit(-1);
  285.     }
  286.  
  287.     if (out > 2) close(out);
  288.     if (err > 2) close(err);
  289.     close(fd);
  290.     if (!rpmIsVerbose()) close(out);
  291.  
  292.     wait(&status);
  293.  
  294.     if (!WIFEXITED(status) || WEXITSTATUS(status)) {
  295.     rpmError(RPMERR_SCRIPT, "execution of verify script failed");
  296.     return 1;
  297.     }
  298.  
  299.     return 0;
  300. }
  301.