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