00001
00006 #include "system.h"
00007
00008 #include <rpmio.h>
00009 #define _RPMFI_INTERNAL
00010 #define _RPMPS_INTERNAL
00011 #include <rpmcli.h>
00012
00013 #define _RPMSQ_INTERNAL
00014 #include "psm.h"
00015
00016 #include "legacy.h"
00017 #include "ugid.h"
00018 #include "debug.h"
00019
00020
00021
00022
00023
00024 #define S_ISDEV(m) (S_ISBLK((m)) || S_ISCHR((m)))
00025
00026
00027 extern int _rpmds_unspecified_epoch_noise;
00028
00029 int rpmVerifyFile(const rpmts ts, const rpmfi fi,
00030 rpmVerifyAttrs * res, rpmVerifyAttrs omitMask)
00031 {
00032 unsigned short fmode = rpmfiFMode(fi);
00033 rpmfileAttrs fileAttrs = rpmfiFFlags(fi);
00034 rpmVerifyAttrs flags = rpmfiVFlags(fi);
00035 const char * fn = rpmfiFN(fi);
00036 const char * rootDir = rpmtsRootDir(ts);
00037 struct stat sb;
00038 int rc;
00039
00040
00041 if (rootDir && *rootDir != '\0'
00042 && !(rootDir[0] == '/' && rootDir[1] == '\0'))
00043 {
00044 int nb = strlen(fn) + strlen(rootDir) + 1;
00045 char * tb = alloca(nb);
00046 char * t;
00047
00048 t = tb;
00049 *t = '\0';
00050 t = stpcpy(t, rootDir);
00051 while (t > tb && t[-1] == '/') {
00052 --t;
00053 *t = '\0';
00054 }
00055 t = stpcpy(t, fn);
00056 fn = tb;
00057 }
00058
00059 *res = RPMVERIFY_NONE;
00060
00061
00062
00063
00064 switch (rpmfiFState(fi)) {
00065 case RPMFILE_STATE_NETSHARED:
00066 case RPMFILE_STATE_REPLACED:
00067 case RPMFILE_STATE_NOTINSTALLED:
00068 case RPMFILE_STATE_WRONGCOLOR:
00069 return 0;
00070 break;
00071 case RPMFILE_STATE_NORMAL:
00072 break;
00073 }
00074
00075 if (fn == NULL || Lstat(fn, &sb) != 0) {
00076 *res |= RPMVERIFY_LSTATFAIL;
00077 return 1;
00078 }
00079
00080
00081
00082
00083 if (S_ISDIR(sb.st_mode))
00084 flags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
00085 RPMVERIFY_LINKTO);
00086 else if (S_ISLNK(sb.st_mode)) {
00087 flags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
00088 RPMVERIFY_MODE);
00089 #if CHOWN_FOLLOWS_SYMLINK
00090 flags &= ~(RPMVERIFY_USER | RPMVERIFY_GROUP);
00091 #endif
00092 }
00093 else if (S_ISFIFO(sb.st_mode))
00094 flags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
00095 RPMVERIFY_LINKTO);
00096 else if (S_ISCHR(sb.st_mode))
00097 flags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
00098 RPMVERIFY_LINKTO);
00099 else if (S_ISBLK(sb.st_mode))
00100 flags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
00101 RPMVERIFY_LINKTO);
00102 else
00103 flags &= ~(RPMVERIFY_LINKTO);
00104
00105
00106
00107
00108 if (fileAttrs & RPMFILE_GHOST)
00109 flags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
00110 RPMVERIFY_LINKTO);
00111
00112
00113
00114
00115 flags &= ~(omitMask | RPMVERIFY_FAILURES);
00116
00117
00118 if (flags & RPMVERIFY_FDIGEST) {
00119 int dalgo = 0;
00120 size_t dlen = 0;
00121 const unsigned char * digest = rpmfiDigest(fi, &dalgo, &dlen);
00122
00123 if (digest == NULL)
00124 *res |= RPMVERIFY_FDIGEST;
00125 else {
00126
00127 unsigned char * fdigest = memset(alloca(dlen), 0, dlen);
00128 size_t fsize;
00129 rc = dodigest(dalgo, fn, fdigest, 0, &fsize);
00130 sb.st_size = fsize;
00131 if (rc)
00132 *res |= (RPMVERIFY_READFAIL|RPMVERIFY_FDIGEST);
00133 else
00134 if (memcmp(fdigest, digest, dlen))
00135 *res |= RPMVERIFY_FDIGEST;
00136 }
00137 }
00138
00139 if (flags & RPMVERIFY_LINKTO) {
00140 char linkto[1024+1];
00141 int size = 0;
00142
00143 if ((size = Readlink(fn, linkto, sizeof(linkto)-1)) == -1)
00144 *res |= (RPMVERIFY_READLINKFAIL|RPMVERIFY_LINKTO);
00145 else {
00146 const char * flink = rpmfiFLink(fi);
00147 linkto[size] = '\0';
00148 if (flink == NULL || strcmp(linkto, flink))
00149 *res |= RPMVERIFY_LINKTO;
00150 }
00151 }
00152
00153 if (flags & RPMVERIFY_FILESIZE) {
00154 if (sb.st_size != rpmfiFSize(fi))
00155 *res |= RPMVERIFY_FILESIZE;
00156 }
00157
00158 if (flags & RPMVERIFY_MODE) {
00159 unsigned short metamode = fmode;
00160 unsigned short filemode;
00161
00162
00163
00164
00165
00166 filemode = (unsigned short)sb.st_mode;
00167
00168
00169
00170
00171 if (fileAttrs & RPMFILE_GHOST) {
00172 metamode &= ~0xf000;
00173 filemode &= ~0xf000;
00174 }
00175
00176 if (metamode != filemode)
00177 *res |= RPMVERIFY_MODE;
00178 }
00179
00180 if (flags & RPMVERIFY_RDEV) {
00181 if (S_ISCHR(fmode) != S_ISCHR(sb.st_mode)
00182 || S_ISBLK(fmode) != S_ISBLK(sb.st_mode))
00183 {
00184 *res |= RPMVERIFY_RDEV;
00185 } else if (S_ISDEV(fmode) && S_ISDEV(sb.st_mode)) {
00186 uint16_t st_rdev = (sb.st_rdev & 0xffff);
00187 uint16_t frdev = (rpmfiFRdev(fi) & 0xffff);
00188 if (st_rdev != frdev)
00189 *res |= RPMVERIFY_RDEV;
00190 }
00191 }
00192
00193 if (flags & RPMVERIFY_MTIME) {
00194 if (sb.st_mtime != rpmfiFMtime(fi))
00195 *res |= RPMVERIFY_MTIME;
00196 }
00197
00198 if (flags & RPMVERIFY_USER) {
00199 const char * name = uidToUname(sb.st_uid);
00200 const char * fuser = rpmfiFUser(fi);
00201 if (name == NULL || fuser == NULL || strcmp(name, fuser))
00202 *res |= RPMVERIFY_USER;
00203 }
00204
00205 if (flags & RPMVERIFY_GROUP) {
00206 const char * name = gidToGname(sb.st_gid);
00207 const char * fgroup = rpmfiFGroup(fi);
00208 if (name == NULL || fgroup == NULL || strcmp(name, fgroup))
00209 *res |= RPMVERIFY_GROUP;
00210 }
00211
00212 return 0;
00213 }
00214
00224 static int rpmVerifyScript( QVA_t qva, rpmts ts,
00225 rpmfi fi, FD_t scriptFd)
00226
00227
00228
00229 {
00230 rpmpsm psm = rpmpsmNew(ts, NULL, fi);
00231 int rc = 0;
00232
00233 if (psm == NULL)
00234 return rc;
00235
00236 if (scriptFd != NULL)
00237 rpmtsSetScriptFd(psm->ts, scriptFd);
00238
00239 psm->stepName = "verify";
00240 psm->scriptTag = RPMTAG_VERIFYSCRIPT;
00241 psm->progTag = RPMTAG_VERIFYSCRIPTPROG;
00242 rc = rpmpsmStage(psm, PSM_SCRIPT);
00243
00244 psm->stepName = "sanitycheck";
00245 psm->scriptTag = RPMTAG_SANITYCHECK;
00246 psm->progTag = RPMTAG_SANITYCHECKPROG;
00247 rc = rpmpsmStage(psm, PSM_SCRIPT);
00248
00249 if (scriptFd != NULL)
00250 rpmtsSetScriptFd(psm->ts, NULL);
00251
00252 psm = rpmpsmFree(psm);
00253
00254 return rc;
00255 }
00256
00264 static int verifyHeader(QVA_t qva, const rpmts ts, rpmfi fi)
00265
00266
00267 {
00268 rpmVerifyAttrs verifyResult = 0;
00269
00270 rpmVerifyAttrs omitMask = ((qva->qva_flags & VERIFY_ATTRS) ^ VERIFY_ATTRS);
00271
00272 int ec = 0;
00273 char * t, * te;
00274 char buf[BUFSIZ];
00275 int i;
00276
00277 te = t = buf;
00278 *te = '\0';
00279
00280 fi = rpmfiLink(fi, "verifyHeader");
00281 fi = rpmfiInit(fi, 0);
00282 if (fi != NULL)
00283 while ((i = rpmfiNext(fi)) >= 0) {
00284 rpmfileAttrs fflags;
00285 int rc;
00286
00287 fflags = rpmfiFFlags(fi);
00288
00289
00290 if ((qva->qva_fflags & RPMFILE_CONFIG) && (fflags & RPMFILE_CONFIG))
00291 continue;
00292
00293
00294 if ((qva->qva_fflags & RPMFILE_DOC) && (fflags & RPMFILE_DOC))
00295 continue;
00296
00297
00298
00299 if (!(qva->qva_fflags & RPMFILE_GHOST) && (fflags & RPMFILE_GHOST))
00300 continue;
00301
00302 rc = rpmVerifyFile(ts, fi, &verifyResult, omitMask);
00303 if (rc) {
00304 if (!(fflags & (RPMFILE_MISSINGOK|RPMFILE_GHOST)) || rpmIsVerbose()) {
00305 sprintf(te, _("missing %c %s"),
00306 ((fflags & RPMFILE_CONFIG) ? 'c' :
00307 (fflags & RPMFILE_DOC) ? 'd' :
00308 (fflags & RPMFILE_GHOST) ? 'g' :
00309 (fflags & RPMFILE_LICENSE) ? 'l' :
00310 (fflags & RPMFILE_PUBKEY) ? 'P' :
00311 (fflags & RPMFILE_README) ? 'r' : ' '),
00312 rpmfiFN(fi));
00313 te += strlen(te);
00314 if ((verifyResult & RPMVERIFY_LSTATFAIL) != 0 && errno != ENOENT) {
00315 sprintf(te, " (%s)", strerror(errno));
00316 te += strlen(te);
00317 }
00318 ec = rc;
00319 }
00320 } else if (verifyResult || rpmIsVerbose()) {
00321 const char * size, * digest, * link, * mtime, * mode;
00322 const char * group, * user, * rdev;
00323 static const char *const aok = ".";
00324 static const char *const unknown = "?";
00325
00326 ec = 1;
00327
00328 #define _verify(_RPMVERIFY_F, _C) \
00329 ((verifyResult & _RPMVERIFY_F) ? _C : aok)
00330 #define _verifylink(_RPMVERIFY_F, _C) \
00331 ((verifyResult & RPMVERIFY_READLINKFAIL) ? unknown : \
00332 (verifyResult & _RPMVERIFY_F) ? _C : aok)
00333 #define _verifyfile(_RPMVERIFY_F, _C) \
00334 ((verifyResult & RPMVERIFY_READFAIL) ? unknown : \
00335 (verifyResult & _RPMVERIFY_F) ? _C : aok)
00336
00337 digest = _verifyfile(RPMVERIFY_FDIGEST, "5");
00338 size = _verify(RPMVERIFY_FILESIZE, "S");
00339 link = _verifylink(RPMVERIFY_LINKTO, "L");
00340 mtime = _verify(RPMVERIFY_MTIME, "T");
00341 rdev = _verify(RPMVERIFY_RDEV, "D");
00342 user = _verify(RPMVERIFY_USER, "U");
00343 group = _verify(RPMVERIFY_GROUP, "G");
00344 mode = _verify(RPMVERIFY_MODE, "M");
00345
00346 #undef _verifyfile
00347 #undef _verifylink
00348 #undef _verify
00349
00350 sprintf(te, "%s%s%s%s%s%s%s%s %c %s",
00351 size, mode, digest, rdev, link, user, group, mtime,
00352 ((fflags & RPMFILE_CONFIG) ? 'c' :
00353 (fflags & RPMFILE_DOC) ? 'd' :
00354 (fflags & RPMFILE_GHOST) ? 'g' :
00355 (fflags & RPMFILE_LICENSE) ? 'l' :
00356 (fflags & RPMFILE_PUBKEY) ? 'P' :
00357 (fflags & RPMFILE_README) ? 'r' : ' '),
00358 rpmfiFN(fi));
00359 te += strlen(te);
00360 }
00361
00362 if (te > t) {
00363 *te++ = '\n';
00364 *te = '\0';
00365 rpmlog(RPMLOG_NOTICE, "%s", t);
00366 te = t = buf;
00367 *t = '\0';
00368 }
00369 }
00370 fi = rpmfiUnlink(fi, "verifyHeader");
00371
00372 return ec;
00373 }
00374
00382 static int verifyDependencies( QVA_t qva, rpmts ts,
00383 Header h)
00384
00385
00386 {
00387 #ifdef NOTYET
00388 int instance = headerGetInstance(h);
00389 #endif
00390 rpmps ps;
00391 int rc = 0;
00392 int xx;
00393
00394 rpmtsEmpty(ts);
00395 #ifdef NOTYET
00396 if (instance > 0)
00397 (void) rpmtsAddEraseElement(ts, h, instance);
00398 else
00399 #endif
00400 (void) rpmtsAddInstallElement(ts, h, NULL, 0, NULL);
00401
00402 xx = rpmtsCheck(ts);
00403 ps = rpmtsProblems(ts);
00404
00405 if (rpmpsNumProblems(ps) > 0) {
00406 const char * altNEVR;
00407 const char * pkgNEVR = NULL;
00408 rpmpsi psi;
00409 rpmProblem p;
00410 char * t, * te;
00411 int nb = 512;
00412
00413 psi = rpmpsInitIterator(ps);
00414 while (rpmpsNextIterator(psi) >= 0) {
00415 p = rpmpsProblem(psi);
00416 if (pkgNEVR == NULL)
00417 pkgNEVR = rpmProblemGetPkgNEVR(p);
00418
00419 altNEVR = rpmProblemGetAltNEVR(p);
00420 if (altNEVR[0] == 'R' && altNEVR[1] == ' ')
00421 nb += sizeof("\tRequires: ")-1;
00422 if (altNEVR[0] == 'C' && altNEVR[1] == ' ')
00423 nb += sizeof("\tConflicts: ")-1;
00424 nb += strlen(altNEVR+2) + sizeof("\n") - 1;
00425
00426 }
00427 psi = rpmpsFreeIterator(psi);
00428
00429 te = t = alloca(nb);
00430 *te = '\0';
00431 sprintf(te, _("Unsatisfied dependencies for %s:\n"), pkgNEVR);
00432 te += strlen(te);
00433
00434 psi = rpmpsInitIterator(ps);
00435 while (rpmpsNextIterator(psi) >= 0) {
00436 p = rpmpsProblem(psi);
00437
00438 altNEVR = (p->altNEVR ? p->altNEVR : "? ?altNEVR?");
00439 if (altNEVR[0] == 'R' && altNEVR[1] == ' ')
00440 te = stpcpy(te, "\tRequires: ");
00441 if (altNEVR[0] == 'C' && altNEVR[1] == ' ')
00442 te = stpcpy(te, "\tConflicts: ");
00443 te = stpcpy( stpcpy(te, altNEVR+2), "\n");
00444
00445 rc++;
00446 }
00447 psi = rpmpsFreeIterator(psi);
00448
00449 if (te > t) {
00450 *te++ = '\n';
00451 *te = '\0';
00452 rpmlog(RPMLOG_NOTICE, "%s", t);
00453 te = t;
00454 *t = '\0';
00455 }
00456 }
00457
00458 ps = rpmpsFree(ps);
00459
00460 rpmtsEmpty(ts);
00461
00462 return rc;
00463 }
00464
00465 int showVerifyPackage(QVA_t qva, rpmts ts, Header h)
00466 {
00467 int scareMem = 0;
00468 rpmfi fi = NULL;
00469 int ec = 0;
00470 int rc;
00471
00472 fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
00473 if (fi != NULL) {
00474 if (qva->qva_flags & VERIFY_DEPS) {
00475 int save_noise = _rpmds_unspecified_epoch_noise;
00476
00477 if (rpmIsVerbose())
00478 _rpmds_unspecified_epoch_noise = 1;
00479 if ((rc = verifyDependencies(qva, ts, h)) != 0)
00480 ec = rc;
00481 _rpmds_unspecified_epoch_noise = save_noise;
00482
00483 }
00484 if (qva->qva_flags & VERIFY_FILES) {
00485 if ((rc = verifyHeader(qva, ts, fi)) != 0)
00486 ec = rc;
00487 }
00488 if ((qva->qva_flags & VERIFY_SCRIPT)
00489 && (headerIsEntry(h, RPMTAG_VERIFYSCRIPT) ||
00490 headerIsEntry(h, RPMTAG_SANITYCHECK)))
00491 {
00492 FD_t fdo = fdDup(STDOUT_FILENO);
00493
00494
00495 if (fi->h == NULL) fi->h = headerLink(h);
00496 if ((rc = rpmVerifyScript(qva, ts, fi, fdo)) != 0)
00497 ec = rc;
00498 if (fdo != NULL)
00499 rc = Fclose(fdo);
00500 fi->h = headerFree(fi->h);
00501 }
00502
00503 fi = rpmfiFree(fi);
00504 }
00505
00506 return ec;
00507 }
00508
00509 int rpmcliVerify(rpmts ts, QVA_t qva, const char ** argv)
00510 {
00511 rpmdepFlags depFlags = qva->depFlags, odepFlags;
00512 rpmtransFlags transFlags = qva->transFlags, otransFlags;
00513 rpmVSFlags vsflags, ovsflags;
00514 int ec = 0;
00515
00516 if (qva->qva_showPackage == NULL)
00517 qva->qva_showPackage = showVerifyPackage;
00518
00519
00520 vsflags = rpmExpandNumeric("%{?_vsflags_verify}");
00521 if (!(qva->qva_flags & VERIFY_DIGEST))
00522 vsflags |= _RPMVSF_NODIGESTS;
00523 if (!(qva->qva_flags & VERIFY_SIGNATURE))
00524 vsflags |= _RPMVSF_NOSIGNATURES;
00525 if (!(qva->qva_flags & VERIFY_HDRCHK))
00526 vsflags |= RPMVSF_NOHDRCHK;
00527 vsflags &= ~RPMVSF_NEEDPAYLOAD;
00528
00529 odepFlags = rpmtsSetDFlags(ts, depFlags);
00530 otransFlags = rpmtsSetFlags(ts, transFlags);
00531 ovsflags = rpmtsSetVSFlags(ts, vsflags);
00532 ec = rpmcliArgIter(ts, qva, argv);
00533 vsflags = rpmtsSetVSFlags(ts, ovsflags);
00534 transFlags = rpmtsSetFlags(ts, otransFlags);
00535 depFlags = rpmtsSetDFlags(ts, odepFlags);
00536
00537 if (qva->qva_showPackage == showVerifyPackage)
00538 qva->qva_showPackage = NULL;
00539
00540 rpmtsEmpty(ts);
00541
00542 return ec;
00543 }