summaryrefslogtreecommitdiff
path: root/lib/verify.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/verify.c')
-rw-r--r--lib/verify.c200
1 files changed, 140 insertions, 60 deletions
diff --git a/lib/verify.c b/lib/verify.c
index 3dcec10f7..5528ba95e 100644
--- a/lib/verify.c
+++ b/lib/verify.c
@@ -53,25 +53,22 @@ static int cap_compare(cap_t acap, cap_t bcap)
}
#endif
-int rpmVerifyFile(const rpmts ts, const rpmfi fi,
- rpmVerifyAttrs * res, rpmVerifyAttrs omitMask)
+rpmVerifyAttrs rpmfilesVerify(rpmfiles fi, int ix, rpmVerifyAttrs omitMask)
{
- rpm_mode_t fmode = rpmfiFMode(fi);
- rpmfileAttrs fileAttrs = rpmfiFFlags(fi);
- rpmVerifyAttrs flags = rpmfiVFlags(fi);
- const char * fn = rpmfiFN(fi);
+ rpm_mode_t fmode = rpmfilesFMode(fi, ix);
+ rpmfileAttrs fileAttrs = rpmfilesFFlags(fi, ix);
+ rpmVerifyAttrs flags = rpmfilesVFlags(fi, ix);
+ const char * fn = rpmfilesFN(fi, ix);
struct stat sb;
- int rc;
-
- *res = RPMVERIFY_NONE;
+ rpmVerifyAttrs vfy = RPMVERIFY_NONE;
/*
* Check to see if the file was installed - if not pretend all is OK.
*/
- switch (rpmfiFState(fi)) {
+ switch (rpmfilesFState(fi, ix)) {
case RPMFILE_STATE_NETSHARED:
case RPMFILE_STATE_NOTINSTALLED:
- return 0;
+ goto exit;
break;
case RPMFILE_STATE_REPLACED:
/* For replaced files we can only verify if it exists at all */
@@ -92,8 +89,23 @@ int rpmVerifyFile(const rpmts ts, const rpmfi fi,
}
if (fn == NULL || lstat(fn, &sb) != 0) {
- *res |= RPMVERIFY_LSTATFAIL;
- return 1;
+ vfy |= RPMVERIFY_LSTATFAIL;
+ goto exit;
+ }
+
+ /* If we expected a directory but got a symlink to one, follow the link */
+ if (S_ISDIR(fmode) && S_ISLNK(sb.st_mode)) {
+ struct stat dsb;
+ /* ...if it actually points to a directory */
+ if (stat(fn, &dsb) == 0 && S_ISDIR(dsb.st_mode)) {
+ uid_t fuid;
+ /* ...and is by a legit user, to match fsmVerify() behavior */
+ if (sb.st_uid == 0 ||
+ (rpmugUid(rpmfilesFUser(fi, ix), &fuid) == 0 &&
+ sb.st_uid == fuid)) {
+ sb = dsb; /* struct assignment */
+ }
+ }
}
/* Links have no mode, other types have no linkto */
@@ -122,19 +134,19 @@ int rpmVerifyFile(const rpmts ts, const rpmfi fi,
size_t diglen;
/* XXX If --nomd5, then prelinked library sizes are not corrected. */
- if ((digest = rpmfiFDigest(fi, &algo, &diglen))) {
+ if ((digest = rpmfilesFDigest(fi, ix, &algo, &diglen))) {
unsigned char fdigest[diglen];
rpm_loff_t fsize;
- rc = rpmDoDigest(algo, fn, 0, fdigest, &fsize);
- sb.st_size = fsize;
- if (rc) {
- *res |= (RPMVERIFY_READFAIL|RPMVERIFY_FILEDIGEST);
- } else if (memcmp(fdigest, digest, diglen)) {
- *res |= RPMVERIFY_FILEDIGEST;
+ if (rpmDoDigest(algo, fn, 0, fdigest, &fsize)) {
+ vfy |= (RPMVERIFY_READFAIL|RPMVERIFY_FILEDIGEST);
+ } else {
+ sb.st_size = fsize;
+ if (memcmp(fdigest, digest, diglen))
+ vfy |= RPMVERIFY_FILEDIGEST;
}
} else {
- *res |= RPMVERIFY_FILEDIGEST;
+ vfy |= RPMVERIFY_FILEDIGEST;
}
}
@@ -143,18 +155,18 @@ int rpmVerifyFile(const rpmts ts, const rpmfi fi,
int size = 0;
if ((size = readlink(fn, linkto, sizeof(linkto)-1)) == -1)
- *res |= (RPMVERIFY_READLINKFAIL|RPMVERIFY_LINKTO);
+ vfy |= (RPMVERIFY_READLINKFAIL|RPMVERIFY_LINKTO);
else {
- const char * flink = rpmfiFLink(fi);
+ const char * flink = rpmfilesFLink(fi, ix);
linkto[size] = '\0';
if (flink == NULL || !rstreq(linkto, flink))
- *res |= RPMVERIFY_LINKTO;
+ vfy |= RPMVERIFY_LINKTO;
}
}
if (flags & RPMVERIFY_FILESIZE) {
- if (sb.st_size != rpmfiFSize(fi))
- *res |= RPMVERIFY_FILESIZE;
+ if (sb.st_size != rpmfilesFSize(fi, ix))
+ vfy |= RPMVERIFY_FILESIZE;
}
if (flags & RPMVERIFY_MODE) {
@@ -176,7 +188,7 @@ int rpmVerifyFile(const rpmts ts, const rpmfi fi,
}
if (metamode != filemode)
- *res |= RPMVERIFY_MODE;
+ vfy |= RPMVERIFY_MODE;
#if WITH_ACL
/*
@@ -186,7 +198,7 @@ int rpmVerifyFile(const rpmts ts, const rpmfi fi,
acl_t facl = acl_get_file(fn, ACL_TYPE_ACCESS);
if (facl) {
if (acl_equiv_mode(facl, NULL) == 1) {
- *res |= RPMVERIFY_MODE;
+ vfy |= RPMVERIFY_MODE;
}
acl_free(facl);
}
@@ -197,12 +209,12 @@ int rpmVerifyFile(const rpmts ts, const rpmfi fi,
if (S_ISCHR(fmode) != S_ISCHR(sb.st_mode)
|| S_ISBLK(fmode) != S_ISBLK(sb.st_mode))
{
- *res |= RPMVERIFY_RDEV;
+ vfy |= RPMVERIFY_RDEV;
} else if (S_ISDEV(fmode) && S_ISDEV(sb.st_mode)) {
rpm_rdev_t st_rdev = (sb.st_rdev & 0xffff);
- rpm_rdev_t frdev = (rpmfiFRdev(fi) & 0xffff);
+ rpm_rdev_t frdev = (rpmfilesFRdev(fi, ix) & 0xffff);
if (st_rdev != frdev)
- *res |= RPMVERIFY_RDEV;
+ vfy |= RPMVERIFY_RDEV;
}
}
@@ -213,7 +225,7 @@ int rpmVerifyFile(const rpmts ts, const rpmfi fi,
* capabilities at all but suffices for now...
*/
cap_t cap, fcap;
- cap = cap_from_text(rpmfiFCaps(fi));
+ cap = cap_from_text(rpmfilesFCaps(fi, ix));
if (!cap) {
cap = cap_from_text("=");
}
@@ -223,32 +235,71 @@ int rpmVerifyFile(const rpmts ts, const rpmfi fi,
}
if (cap_compare(cap, fcap) != 0)
- *res |= RPMVERIFY_CAPS;
+ vfy |= RPMVERIFY_CAPS;
cap_free(fcap);
cap_free(cap);
}
#endif
- if ((flags & RPMVERIFY_MTIME) && (sb.st_mtime != rpmfiFMtime(fi))) {
- *res |= RPMVERIFY_MTIME;
+ if ((flags & RPMVERIFY_MTIME) && (sb.st_mtime != rpmfilesFMtime(fi, ix))) {
+ vfy |= RPMVERIFY_MTIME;
}
if (flags & RPMVERIFY_USER) {
const char * name = rpmugUname(sb.st_uid);
- const char * fuser = rpmfiFUser(fi);
- if (name == NULL || fuser == NULL || !rstreq(name, fuser))
- *res |= RPMVERIFY_USER;
+ const char * fuser = rpmfilesFUser(fi, ix);
+ uid_t uid;
+ int namematch = 0;
+ int idmatch = 0;
+
+ if (name && fuser)
+ namematch = rstreq(name, fuser);
+ if (fuser && rpmugUid(fuser, &uid) == 0)
+ idmatch = (uid == sb.st_uid);
+
+ if (namematch != idmatch) {
+ rpmlog(RPMLOG_WARNING,
+ _("Duplicate username or UID for user %s\n"), fuser);
+ }
+
+ if (!(namematch || idmatch))
+ vfy |= RPMVERIFY_USER;
}
if (flags & RPMVERIFY_GROUP) {
const char * name = rpmugGname(sb.st_gid);
- const char * fgroup = rpmfiFGroup(fi);
- if (name == NULL || fgroup == NULL || !rstreq(name, fgroup))
- *res |= RPMVERIFY_GROUP;
+ const char * fgroup = rpmfilesFGroup(fi, ix);
+ gid_t gid;
+ int namematch = 0;
+ int idmatch = 0;
+
+ if (name && fgroup)
+ namematch = rstreq(name, fgroup);
+ if (fgroup && rpmugGid(fgroup, &gid) == 0)
+ idmatch = (gid == sb.st_gid);
+
+ if (namematch != idmatch) {
+ rpmlog(RPMLOG_WARNING,
+ _("Duplicate groupname or GID for group %s\n"), fgroup);
+ }
+
+ if (!(namematch || idmatch))
+ vfy |= RPMVERIFY_GROUP;
}
- return 0;
+exit:
+ return vfy;
+}
+
+int rpmVerifyFile(const rpmts ts, const rpmfi fi,
+ rpmVerifyAttrs * res, rpmVerifyAttrs omitMask)
+{
+ rpmVerifyAttrs vfy = rpmfiVerify(fi, omitMask);
+ if (res)
+ *res = vfy;
+
+ return (vfy & RPMVERIFY_LSTATFAIL) ? 1 : 0;
}
/**
@@ -314,7 +365,7 @@ char * rpmVerifyString(uint32_t verifyResult, const char *pad)
char * rpmFFlagsString(uint32_t fflags, const char *pad)
{
char *fmt = NULL;
- rasprintf(&fmt, "%s%s%s%s%s%s%s%s",
+ rasprintf(&fmt, "%s%s%s%s%s%s%s%s%s",
(fflags & RPMFILE_DOC) ? "d" : pad,
(fflags & RPMFILE_CONFIG) ? "c" : pad,
(fflags & RPMFILE_SPECFILE) ? "s" : pad,
@@ -322,22 +373,43 @@ char * rpmFFlagsString(uint32_t fflags, const char *pad)
(fflags & RPMFILE_NOREPLACE) ? "n" : pad,
(fflags & RPMFILE_GHOST) ? "g" : pad,
(fflags & RPMFILE_LICENSE) ? "l" : pad,
- (fflags & RPMFILE_README) ? "r" : pad);
+ (fflags & RPMFILE_README) ? "r" : pad,
+ (fflags & RPMFILE_ARTIFACT) ? "a" : pad);
return fmt;
}
+static const char * stateStr(rpmfileState fstate)
+{
+ switch (fstate) {
+ case RPMFILE_STATE_NORMAL:
+ return NULL;
+ case RPMFILE_STATE_NOTINSTALLED:
+ return rpmIsVerbose() ? _("not installed") : NULL;
+ case RPMFILE_STATE_NETSHARED:
+ return rpmIsVerbose() ? _("net shared") : NULL;
+ case RPMFILE_STATE_WRONGCOLOR:
+ return rpmIsVerbose() ? _("wrong color") : NULL;
+ case RPMFILE_STATE_REPLACED:
+ return _("replaced");
+ case RPMFILE_STATE_MISSING:
+ return _("no state");
+ }
+ return _("unknown state");
+}
+
/**
* Check file info from header against what's actually installed.
* @param ts transaction set
* @param h header to verify
* @param omitMask bits to disable verify checks
- * @param ghosts should ghosts be verified?
+ * @param skipAttr skip files with these attrs (eg %ghost)
* @return 0 no problems, 1 problems found
*/
-static int verifyHeader(rpmts ts, Header h, rpmVerifyAttrs omitMask, int ghosts)
+static int verifyHeader(rpmts ts, Header h, rpmVerifyAttrs omitMask,
+ rpmfileAttrs skipAttrs)
{
rpmVerifyAttrs verifyResult = 0;
- int ec = 0; /* assume no problems */
+ rpmVerifyAttrs verifyAll = 0; /* assume no problems */
rpmfi fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, RPMFI_FLAGS_VERIFY);
if (fi == NULL)
@@ -347,17 +419,17 @@ static int verifyHeader(rpmts ts, Header h, rpmVerifyAttrs omitMask, int ghosts)
while (rpmfiNext(fi) >= 0) {
rpmfileAttrs fileAttrs = rpmfiFFlags(fi);
char *buf = NULL, *attrFormat;
+ const char *fstate = NULL;
char ac;
- int rc;
- /* If not verifying %ghost, skip ghost files. */
- if ((fileAttrs & RPMFILE_GHOST) && !ghosts)
+ /* Skip on attributes (eg from --noghost) */
+ if (skipAttrs & fileAttrs)
continue;
- rc = rpmVerifyFile(ts, fi, &verifyResult, omitMask);
+ verifyResult = rpmfiVerify(fi, omitMask);
/* Filter out timestamp differences of shared files */
- if (rc == 0 && (verifyResult & RPMVERIFY_MTIME)) {
+ if (verifyResult & RPMVERIFY_MTIME) {
rpmdbMatchIterator mi;
mi = rpmtsInitIterator(ts, RPMDBI_BASENAMES, rpmfiFN(fi), 0);
if (rpmdbGetIteratorCount(mi) > 1)
@@ -365,9 +437,13 @@ static int verifyHeader(rpmts ts, Header h, rpmVerifyAttrs omitMask, int ghosts)
rpmdbFreeIterator(mi);
}
+ /* State is only meaningful for installed packages */
+ if (headerGetInstance(h))
+ fstate = stateStr(rpmfiFState(fi));
+
attrFormat = rpmFFlagsString(fileAttrs, "");
ac = rstreq(attrFormat, "") ? ' ' : attrFormat[0];
- if (rc) {
+ if (verifyResult & RPMVERIFY_LSTATFAIL) {
if (!(fileAttrs & (RPMFILE_MISSINGOK|RPMFILE_GHOST)) || rpmIsVerbose()) {
rasprintf(&buf, _("missing %c %s"), ac, rpmfiFN(fi));
if ((verifyResult & RPMVERIFY_LSTATFAIL) != 0 &&
@@ -377,25 +453,30 @@ static int verifyHeader(rpmts ts, Header h, rpmVerifyAttrs omitMask, int ghosts)
rstrcat(&buf, app);
free(app);
}
- ec = rc;
}
- } else if (verifyResult || rpmIsVerbose()) {
+ } else if (verifyResult || fstate || rpmIsVerbose()) {
char *verifyFormat = rpmVerifyString(verifyResult, ".");
rasprintf(&buf, "%s %c %s", verifyFormat, ac, rpmfiFN(fi));
free(verifyFormat);
-
- if (verifyResult) ec = 1;
}
free(attrFormat);
if (buf) {
+ if (fstate)
+ buf = rstrscat(&buf, " (", fstate, ")", NULL);
rpmlog(RPMLOG_NOTICE, "%s\n", buf);
buf = _free(buf);
}
+
+ /* Filter out missing %ghost/%missingok errors from final result */
+ if (fileAttrs & (RPMFILE_MISSINGOK|RPMFILE_GHOST))
+ verifyResult &= ~RPMVERIFY_LSTATFAIL;
+
+ verifyAll |= verifyResult;
}
rpmfiFree(fi);
- return ec;
+ return (verifyAll != 0) ? 1 : 0;
}
/**
@@ -440,7 +521,6 @@ static int verifyDependencies(rpmts ts, Header h)
int showVerifyPackage(QVA_t qva, rpmts ts, Header h)
{
rpmVerifyAttrs omitMask = ((qva->qva_flags & VERIFY_ATTRS) ^ VERIFY_ATTRS);
- int ghosts = (qva->qva_fflags & RPMFILE_GHOST);
int ec = 0;
int rc;
@@ -449,7 +529,7 @@ int showVerifyPackage(QVA_t qva, rpmts ts, Header h)
ec = rc;
}
if (qva->qva_flags & VERIFY_FILES) {
- if ((rc = verifyHeader(ts, h, omitMask, ghosts)) != 0)
+ if ((rc = verifyHeader(ts, h, omitMask, qva->qva_fflags)) != 0)
ec = rc;
}
if (qva->qva_flags & VERIFY_SCRIPT) {