From 4a5147ff425a29fba5ddcbf2a57ac7d8edaacb96 Mon Sep 17 00:00:00 2001 From: Timo Teras Date: Fri, 31 Jul 2009 19:35:45 +0300 Subject: audit: sanitize --system make the system audit compare only installed files, instead of scanning the whole file system. also make it print only package names with -q, so reinstalling modified packages becomes easy. --- src/audit.c | 111 ++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 79 insertions(+), 32 deletions(-) (limited to 'src/audit.c') diff --git a/src/audit.c b/src/audit.c index 6191a2c..a7cf2f6 100644 --- a/src/audit.c +++ b/src/audit.c @@ -18,31 +18,39 @@ #include "apk_applet.h" #include "apk_database.h" -#define AUDIT_BACKUP BIT(0) -#define AUDIT_SYSTEM BIT(1) - struct audit_ctx { - int type; - struct apk_database *db; + int (*audit)(struct apk_database *db); }; +static int audit_file(struct apk_database *db, struct apk_db_file *dbf, + const char *name) +{ + struct apk_file_info fi; + + if (apk_file_get_info(db->root_fd, name, dbf->csum.type, &fi) != 0) + return 1; + + if (dbf->csum.type != APK_CHECKSUM_NONE && + apk_checksum_compare(&fi.csum, &dbf->csum) == 0) + return 0; + + if (S_ISLNK(fi.mode) && dbf->csum.type == APK_CHECKSUM_NONE) + return 0; + + return 1; +} + static int audit_directory(apk_hash_item item, void *ctx) { + struct apk_database *db = (struct apk_database *) ctx; struct apk_db_dir *dbd = (struct apk_db_dir *) item; struct apk_db_file *dbf; - struct audit_ctx *actx = (struct audit_ctx *) ctx; - struct apk_database *db = actx->db; - struct dirent *de; struct apk_file_info fi; + struct dirent *de; apk_blob_t bdir = APK_BLOB_PTR_LEN(dbd->name, dbd->namelen); - char tmp[512], reason; + char tmp[PATH_MAX], reason; DIR *dir; - if (!(actx->type & AUDIT_SYSTEM) && !(dbd->flags & APK_DBDIRF_PROTECTED)) - return 0; - if (!(actx->type & AUDIT_BACKUP) && (dbd->flags & APK_DBDIRF_PROTECTED)) - return 0; - dir = fdopendir(openat(db->root_fd, dbd->name, O_RDONLY)); if (dir == NULL) return 0; @@ -57,8 +65,7 @@ static int audit_directory(apk_hash_item item, void *ctx) if (apk_file_get_info(db->root_fd, tmp, APK_CHECKSUM_NONE, &fi) < 0) continue; - if (!(actx->type & AUDIT_SYSTEM) && - (dbd->flags & APK_DBDIRF_SYMLINKS_ONLY) && + if ((dbd->flags & APK_DBDIRF_SYMLINKS_ONLY) && !S_ISLNK(fi.mode)) continue; @@ -70,23 +77,66 @@ static int audit_directory(apk_hash_item item, void *ctx) } else { dbf = apk_db_file_query(db, bdir, APK_BLOB_STR(de->d_name)); if (dbf != NULL) { - if (dbf->csum.type != APK_CHECKSUM_NONE && - apk_file_get_info(db->root_fd, tmp, dbf->csum.type, &fi) == 0 && - apk_checksum_compare(&fi.csum, &dbf->csum) == 0) + if (audit_file(db, dbf, tmp) == 0) continue; - reason = 'U'; } else { reason = 'A'; } } + if (apk_verbosity < 1) printf("%s\n", tmp); else printf("%c %s\n", reason, tmp); } - closedir(dir); + + return 0; +} + +static int audit_backup(struct apk_database *db) +{ + return apk_hash_foreach(&db->installed.dirs, audit_directory, &db); +} + +static int audit_system(struct apk_database *db) +{ + struct apk_package *pkg; + struct apk_db_dir_instance *diri; + struct apk_db_file *file; + struct hlist_node *dn, *fn; + char name[PATH_MAX]; + int done; + + list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list) { + hlist_for_each_entry(diri, dn, &pkg->owned_dirs, pkg_dirs_list) { + if (diri->dir->flags & APK_DBDIRF_PROTECTED) + continue; + + done = 0; + hlist_for_each_entry(file, fn, &diri->owned_files, + diri_files_list) { + + snprintf(name, sizeof(name), "%s/%s", + diri->dir->name, file->name); + + if (audit_file(db, file, name) == 0) + continue; + + if (apk_verbosity < 1) { + printf("%s\n", pkg->name->name); + done = 1; + break; + } + + printf("M %s\n", name); + } + if (done) + break; + } + } + return 0; } @@ -96,10 +146,10 @@ static int audit_parse(void *ctx, int optch, int optindex, const char *optarg) switch (optch) { case 0x10000: - actx->type |= AUDIT_BACKUP; + actx->audit = audit_backup; break; case 0x10001: - actx->type |= AUDIT_SYSTEM; + actx->audit = audit_system; break; default: return -1; @@ -113,28 +163,25 @@ static int audit_main(void *ctx, int argc, char **argv) struct apk_database db; int r; - if (actx->type == 0) + if (actx->audit == NULL) return -EINVAL; r = apk_db_open(&db, apk_root, APK_OPENF_READ); if (r != 0) { apk_error("APK database not present"); - return 1; + return r; } - - actx->db = &db; - - fchdir(db.root_fd); - r = apk_hash_foreach(&db.installed.dirs, audit_directory, actx); - + r = actx->audit(&db); apk_db_close(&db); + return r; } static struct apk_option audit_options[] = { { 0x10000, "backup", "List all modified configuration files that need to be backed up" }, - { 0x10001, "system", "List all modified non-protected files" }, + { 0x10001, "system", "Verify checksums of all installed files " + "(-q to print only modfied packages)" }, }; static struct apk_applet apk_audit = { -- cgit v1.2.3