From 67c0583a5e18c27880e2785536be3e66ff1c4bdd Mon Sep 17 00:00:00 2001 From: Timo Teräs Date: Mon, 10 Apr 2023 20:33:24 +0300 Subject: audit: implement detail records --- src/app_audit.c | 74 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/app_audit.c b/src/app_audit.c index 52dbc73..694d8b5 100644 --- a/src/app_audit.c +++ b/src/app_audit.c @@ -35,11 +35,13 @@ struct audit_ctx { unsigned check_permissions : 1; unsigned packages_only : 1; unsigned ignore_busybox_symlinks : 1; + unsigned details : 1; }; #define AUDIT_OPTIONS(OPT) \ OPT(OPT_AUDIT_backup, "backup") \ OPT(OPT_AUDIT_check_permissions, "check-permissions") \ + OPT(OPT_AUDIT_details, "details") \ OPT(OPT_AUDIT_full, "full") \ OPT(OPT_AUDIT_ignore_busybox_symlinks, "ignore-busybox-symlinks") \ OPT(OPT_AUDIT_packages, "packages") \ @@ -82,6 +84,9 @@ static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt case OPT_AUDIT_check_permissions: actx->check_permissions = 1; break; + case OPT_AUDIT_details: + actx->details = 1; + break; case OPT_AUDIT_ignore_busybox_symlinks: actx->ignore_busybox_symlinks = 1; break; @@ -120,9 +125,9 @@ struct audit_tree_ctx { static int audit_file(struct audit_ctx *actx, struct apk_database *db, struct apk_db_file *dbf, - int dirfd, const char *name) + int dirfd, const char *name, + struct apk_file_info *fi) { - struct apk_file_info fi; int rv = 0; if (!dbf) return 'A'; @@ -131,24 +136,23 @@ static int audit_file(struct audit_ctx *actx, APK_FI_NOFOLLOW | APK_FI_XATTR_CSUM(dbf->acl->xattr_csum.type ?: APK_CHECKSUM_DEFAULT) | APK_FI_CSUM(dbf->csum.type), - &fi, &db->atoms) != 0) + fi, &db->atoms) != 0) return 'e'; if (dbf->csum.type != APK_CHECKSUM_NONE && - apk_checksum_compare(&fi.csum, &dbf->csum) != 0) + apk_checksum_compare(&fi->csum, &dbf->csum) != 0) rv = 'U'; - else if (!S_ISLNK(fi.mode) && !dbf->diri->pkg->ipkg->broken_xattr && - apk_checksum_compare(&fi.xattr_csum, &dbf->acl->xattr_csum) != 0) + else if (!S_ISLNK(fi->mode) && !dbf->diri->pkg->ipkg->broken_xattr && + apk_checksum_compare(&fi->xattr_csum, &dbf->acl->xattr_csum) != 0) rv = 'x'; - else if (S_ISLNK(fi.mode) && dbf->csum.type == APK_CHECKSUM_NONE) + else if (S_ISLNK(fi->mode) && dbf->csum.type == APK_CHECKSUM_NONE) rv = 'U'; else if (actx->check_permissions) { - if ((fi.mode & 07777) != (dbf->acl->mode & 07777)) + if ((fi->mode & 07777) != (dbf->acl->mode & 07777)) rv = 'M'; - else if (fi.uid != dbf->acl->uid || fi.gid != dbf->acl->gid) + else if (fi->uid != dbf->acl->uid || fi->gid != dbf->acl->gid) rv = 'M'; } - apk_fileinfo_free(&fi); return rv; } @@ -174,15 +178,29 @@ static int audit_directory(struct audit_ctx *actx, return 0; } +static const char *format_checksum(const apk_blob_t csum, apk_blob_t b) +{ + const char *ret = b.ptr; + if (csum.len == 0) return ""; + apk_blob_push_blob(&b, APK_BLOB_STR(" hash=")); + apk_blob_push_hexdump(&b, csum); + apk_blob_push_blob(&b, APK_BLOB_PTR_LEN("", 1)); + return ret; +} + static void report_audit(struct audit_ctx *actx, - char reason, apk_blob_t bfull, struct apk_package *pkg) + char reason, apk_blob_t bfull, + struct apk_db_dir *dir, + struct apk_db_file *file, + struct apk_file_info *fi) { - if (!reason) - return; + struct apk_package *pkg = file ? file->diri->pkg : NULL; + char csum_buf[8+APK_BLOB_CHECKSUM_BUF]; + + if (!reason) return; if (actx->packages_only) { - if (pkg == NULL || pkg->state_int != 0) - return; + if (!pkg || pkg->state_int != 0) return; pkg->state_int = 1; if (apk_verbosity < 1) printf("%s\n", pkg->name->name); @@ -190,8 +208,21 @@ static void report_audit(struct audit_ctx *actx, printf(PKG_VER_FMT "\n", PKG_VER_PRINTF(pkg)); } else if (apk_verbosity < 1) { printf(BLOB_FMT "\n", BLOB_PRINTF(bfull)); - } else + } else { + if (actx->details) { + if (file) + printf("- mode=%o uid=%d gid=%d%s\n", + file->acl->mode & 07777, file->acl->uid, file->acl->gid, + format_checksum(APK_BLOB_CSUM(file->csum), APK_BLOB_BUF(csum_buf))); + else if (dir && reason != 'D' && reason != 'd') + printf("- mode=%o uid=%d gid=%d\n", + dir->mode & 07777, dir->uid, dir->gid); + if (fi) printf("+ mode=%o uid=%d gid=%d%s\n", + fi->mode & 07777, fi->uid, fi->gid, + format_checksum(APK_BLOB_CSUM(fi->csum), APK_BLOB_BUF(csum_buf))); + } printf("%c " BLOB_FMT "\n", reason, BLOB_PRINTF(bfull)); + } } static int determine_file_protect_mode(struct apk_db_dir *dir, const char *name) @@ -233,7 +264,7 @@ static int audit_directory_tree_item(void *ctx, int dirfd, const char *name) if (apk_fileinfo_get(dirfd, name, APK_FI_NOFOLLOW, &fi, &db->atoms) < 0) { dbf = apk_db_file_query(db, bdir, bent); if (dbf) dbf->audited = 1; - report_audit(actx, 'e', bfull, dbf ? dbf->diri->pkg : NULL); + report_audit(actx, 'e', bfull, NULL, dbf, NULL); goto done; } @@ -264,7 +295,7 @@ static int audit_directory_tree_item(void *ctx, int dirfd, const char *name) recurse_check: atctx->path[atctx->pathlen++] = '/'; bfull.len++; - report_audit(actx, reason, bfull, NULL); + report_audit(actx, reason, bfull, dir, NULL, &fi); if (reason != 'D' && recurse) { atctx->dir = child; reason = apk_dir_foreach_file( @@ -326,8 +357,9 @@ recurse_check: if (n == 11 && memcmp(target, "/bin/bbsuid", 11) == 0) goto done; } - if (!reason) reason = audit_file(actx, db, dbf, dirfd, name); - report_audit(actx, reason, bfull, dbf ? dbf->diri->pkg : NULL); + if (!reason) reason = audit_file(actx, db, dbf, dirfd, name, &fi); + report_audit(actx, reason, bfull, NULL, dbf, &fi); + apk_fileinfo_free(&fi); } done: @@ -370,7 +402,7 @@ static int audit_missing_files(apk_hash_item item, void *pctx) if (determine_file_protect_mode(dir, file->name) == APK_PROTECT_IGNORE) return 0; len = snprintf(path, sizeof(path), DIR_FILE_FMT, DIR_FILE_PRINTF(dir, file)); - report_audit(actx, 'X', APK_BLOB_PTR_LEN(path, len), file->diri->pkg); + report_audit(actx, 'X', APK_BLOB_PTR_LEN(path, len), NULL, file, NULL); return 0; } -- cgit v1.2.3-70-g09d2