/* * dpkg - main program for package management * verify.c - verify package integrity * * Copyright © 2012-2015 Guillem Jover * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include "filesdb.h" #include "infodb.h" #include "main.h" enum verify_result { VERIFY_NONE, VERIFY_PASS, VERIFY_FAIL, }; struct verify_checks { enum verify_result md5sum; }; typedef void verify_output_func(struct filenamenode *, struct verify_checks *); static int verify_result_rpm(enum verify_result result, int check) { switch (result) { case VERIFY_FAIL: return check; case VERIFY_PASS: return '.'; case VERIFY_NONE: default: return '?'; } } static void verify_output_rpm(struct filenamenode *namenode, struct verify_checks *checks) { char result[9]; int attr; memset(result, '?', sizeof(result)); result[2] = verify_result_rpm(checks->md5sum, '5'); if (namenode->flags & fnnf_old_conff) attr = 'c'; else attr = ' '; printf("%.9s %c %s\n", result, attr, namenode->name); } static verify_output_func *verify_output = verify_output_rpm; bool verify_set_output(const char *name) { if (strcmp(name, "rpm") == 0) verify_output = verify_output_rpm; else return false; return true; } static void verify_package(struct pkginfo *pkg) { struct fileinlist *file; struct varbuf filename = VARBUF_INIT; ensure_packagefiles_available(pkg); parse_filehash(pkg, &pkg->installed); pkg_conffiles_mark_old(pkg); for (file = pkg->clientdata->files; file; file = file->next) { struct verify_checks checks; struct filenamenode *fnn; char hash[MD5HASHLEN + 1]; int failures = 0; fnn = namenodetouse(file->namenode, pkg, &pkg->installed); if (strcmp(fnn->newhash, EMPTYHASHFLAG) == 0) { if (fnn->oldhash == NULL) continue; else fnn->newhash = fnn->oldhash; } varbuf_reset(&filename); varbuf_add_str(&filename, instdir); varbuf_add_str(&filename, fnn->name); varbuf_end_str(&filename); memset(&checks, 0, sizeof(checks)); md5hash(pkg, hash, filename.buf); if (strcmp(hash, fnn->newhash) != 0) { checks.md5sum = VERIFY_FAIL; failures++; } if (failures) verify_output(fnn, &checks); } varbuf_destroy(&filename); } int verify(const char *const *argv) { struct pkginfo *pkg; int rc = 0; modstatdb_open(msdbrw_readonly); ensure_diversions(); if (!*argv) { struct pkgiterator *iter; iter = pkg_db_iter_new(); while ((pkg = pkg_db_iter_next_pkg(iter))) verify_package(pkg); pkg_db_iter_free(iter); } else { const char *thisarg; while ((thisarg = *argv++)) { pkg = dpkg_options_parse_pkgname(cipaction, thisarg); if (pkg->status == PKG_STAT_NOTINSTALLED) { notice(_("package '%s' is not installed"), pkg_name(pkg, pnaw_nonambig)); rc = 1; continue; } verify_package(pkg); } } modstatdb_shutdown(); m_output(stdout, _("")); return rc; }