Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Format the output of the audit system on the frontend
Baptiste Daroussin committed 5 years ago
commit fb130ef7d92278380db2ae7622d945171d9bd120
parent 534ffc2
4 files changed +127 -102
modified libpkg/pkg/audit.h
@@ -25,6 +25,12 @@
#ifndef _PKG_AUDIT_H
#define _PKG_AUDIT_H

+
#define EQ 1
+
#define LT 2
+
#define LTE 3
+
#define GT 4
+
#define GTE 5
+

struct pkg_audit_version {
	char *version;
	int type;
@@ -65,6 +71,16 @@ struct pkg_audit_entry {
	struct pkg_audit_entry *next;
};

+
struct pkg_audit_issue {
+
	const struct pkg_audit_entry *audit;
+
	struct pkg_audit_issue *next;
+
};
+

+
struct pkg_audit_issues {
+
	int count;
+
	struct pkg_audit_issue *issues;
+
};
+

/**
 * Creates new pkg_audit structure
 */
@@ -90,7 +106,6 @@ int pkg_audit_load(struct pkg_audit *audit, const char *fname);
 */
int pkg_audit_process(struct pkg_audit *audit);

-
#if defined(__XSTRING_H_)
/**
 * Check whether `pkg` is vulnerable against processed `audit` structure.
 * If a package is vulnerable, then `result` is set to sbuf describing the
@@ -99,9 +114,8 @@ int pkg_audit_process(struct pkg_audit *audit);
 * It's caller responsibility to free `result` after use
 * @return true and `*result` is set if a package is vulnerable
 */
-
bool pkg_audit_is_vulnerable(struct pkg_audit *audit, struct pkg *pkg,
-
		bool quiet, xstring **result, int *affected);
-
#endif
+
bool pkg_audit_is_vulnerable(struct pkg_audit *audit, struct pkg *pkg, struct pkg_audit_issues **issues, bool stop_quick);

void pkg_audit_free(struct pkg_audit *audit);
+
void pkg_audit_issues_free(struct pkg_audit_issues *issues);
#endif
modified libpkg/pkg_audit.c
@@ -45,21 +45,6 @@
#include "private/pkg.h"
#include "private/event.h"

-
#define EQ 1
-
#define LT 2
-
#define LTE 3
-
#define GT 4
-
#define GTE 5
-

-
static const char* vop_names[] = {
-
	[0] = "",
-
	[EQ] = "=",
-
	[LT] = "<",
-
	[LTE] = "<=",
-
	[GT] = ">",
-
	[GTE] = ">="
-
};
-

/*
 * The _sorted stuff.
 *
@@ -732,69 +717,24 @@ pkg_audit_version_match(const char *pkgversion, struct pkg_audit_version *v)
}

static void
-
pkg_audit_print_versions(struct pkg_audit_entry *e, xstring *sb)
+
pkg_audit_add_entry(struct pkg_audit_entry *e, struct pkg_audit_issues **ai)
{
-
	struct pkg_audit_versions_range *vers;
-

-
	fprintf(sb->fp, "%s", "Affected versions:\n");
-
	LL_FOREACH(e->versions, vers) {
-
		if (vers->v1.type > 0 && vers->v2.type > 0)
-
			fprintf(sb->fp, "%s %s : %s %s\n",
-
				vop_names[vers->v1.type], vers->v1.version,
-
				vop_names[vers->v2.type], vers->v2.version);
-
		else if (vers->v1.type > 0)
-
			fprintf(sb->fp, "%s %s\n",
-
				vop_names[vers->v1.type], vers->v1.version);
-
		else
-
			fprintf(sb->fp, "%s %s\n",
-
				vop_names[vers->v2.type], vers->v2.version);
-
	}
-
}
-

-
static void
-
pkg_audit_print_entry(struct pkg_audit_entry *e, xstring *sb,
-
	const char *pkgname, const char *pkgversion, bool quiet)
-
{
-
	struct pkg_audit_cve *cve;
-

-
	if (quiet) {
-
		if (pkgversion != NULL)
-
			fprintf(sb->fp, "%s-%s\n", pkgname, pkgversion);
-
		else
-
			fprintf(sb->fp, "%s\n", pkgname);
-
	} else {
-
		if (pkgversion != NULL)
-
			fprintf(sb->fp, "%s-%s is vulnerable:\n", pkgname, pkgversion);
-
		else {
-
			fprintf(sb->fp, "%s is vulnerable:\n", pkgname);
-
			pkg_audit_print_versions(e, sb);
-
		}
-

-
		fprintf(sb->fp, "%s\n", e->desc);
-
		/* XXX: for vulnxml we should use more clever approach indeed */
-
		if (e->cve) {
-
			cve = e->cve;
-
			while (cve) {
-
				fprintf(sb->fp, "CVE: %s\n", cve->cvename);
-
				cve = cve->next;
-
			}
-
		}
-
		if (e->url)
-
			fprintf(sb->fp, "WWW: %s\n\n", e->url);
-
		else if (e->id)
-
			fprintf(sb->fp,
-
				"WWW: https://vuxml.FreeBSD.org/freebsd/%s.html\n\n",
-
				e->id);
-
	}
+
	struct pkg_audit_issue *issue;
+

+
	if (*ai == NULL)
+
		*ai = xcalloc(1, sizeof(**ai));
+
	issue = xcalloc(1, sizeof(*issue));
+
	issue->audit = e;
+
	(*ai)->count++;
+
	LL_APPEND((*ai)->issues, issue);
}

bool
pkg_audit_is_vulnerable(struct pkg_audit *audit, struct pkg *pkg,
-
		bool quiet, xstring **result, int *affected)
+
    struct pkg_audit_issues **ai, bool stop_quick)
{
	struct pkg_audit_entry *e;
	struct pkg_audit_versions_range *vers;
-
	xstring *sb;
	struct pkg_audit_item *a;
	bool res = false, res1, res2;

@@ -803,7 +743,6 @@ pkg_audit_is_vulnerable(struct pkg_audit *audit, struct pkg *pkg,

	a = audit->items;
	a += audit_entry_first_byte_idx[(size_t)pkg->name[0]];
-
	sb = xstring_new();

	for (; (e = a->e) != NULL; a += a->next_pfx_incr) {
		int cmp;
@@ -830,10 +769,7 @@ pkg_audit_is_vulnerable(struct pkg_audit *audit, struct pkg *pkg,
				 * Assume that all versions should be checked
				 */
				res = true;
-
				pkg_audit_print_entry(e, sb, pkg->name, NULL, quiet);
-
				if (affected != NULL) {
-
					++*affected;
-
				}
+
				pkg_audit_add_entry(e, ai);
			}
			else {
				LL_FOREACH(e->versions, vers) {
@@ -842,27 +778,17 @@ pkg_audit_is_vulnerable(struct pkg_audit *audit, struct pkg *pkg,

					if (res1 && res2) {
						res = true;
-
						pkg_audit_print_entry(e, sb, pkg->name, pkg->version, quiet);
-
						if (affected != NULL) {
-
							++*affected;
-
						}
+
						pkg_audit_add_entry(e, ai);
						break;
					}
				}
			}

-
			if (res && quiet)
-
				goto out;
+
			if (res && stop_quick)
+
				return (res);
		}
	}

-
out:
-
	if (res) {
-
		*result = sb;
-
	} else {
-
		xstring_free(sb);
-
	}
-

	return (res);
}

@@ -943,3 +869,17 @@ pkg_audit_free (struct pkg_audit *audit)
		free(audit);
	}
}
+

+
void
+
pkg_audit_issues_free(struct pkg_audit_issues *issues)
+
{
+
	struct pkg_audit_issue *i, *issue;
+

+
	if (issues == NULL)
+
		return;
+

+
	LL_FOREACH_SAFE(issues->issues, issue, i) {
+
		LL_DELETE(issues->issues, issue);
+
		free(issue);
+
	}
+
}
modified src/audit.c
@@ -44,7 +44,7 @@
#include <string.h>
#include <unistd.h>
#include <khash.h>
-
#include <xstring.h>
+
#include <utlist.h>

#ifdef HAVE_SYS_CAPSICUM_H
#include <sys/capsicum.h>
@@ -58,6 +58,15 @@
#include <pkg/audit.h>
#include "pkgcli.h"

+
static const char* vop_names[] = {
+
	[0] = "",
+
	[EQ] = "=",
+
	[LT] = "<",
+
	[LTE] = "<=",
+
	[GT] = ">",
+
	[GTE] = ">="
+
};
+

void
usage_audit(void)
{
@@ -110,10 +119,50 @@ print_recursive_rdeps(kh_pkgs_t *head, struct pkg *p, kh_pkgs_t *seen, bool top)
	}
}

+
static void
+
print_issue(struct pkg *p, struct pkg_audit_issue *issue)
+
{
+
	const char *version;
+
	struct pkg_audit_versions_range *vers;
+
	const struct pkg_audit_entry *e;
+
	struct pkg_audit_cve *cve;
+

+
	pkg_get(p, PKG_VERSION, &version);
+

+
	e = issue->audit;
+
	if (version == NULL) {
+
		printf("  Affected versions:\n");
+
		LL_FOREACH(e->versions, vers) {
+
			if (vers->v1.type > 0 && vers->v2.type > 0)
+
				printf("  %s %s : %s %s\n",
+
				    vop_names[vers->v1.type], vers->v1.version,
+
				    vop_names[vers->v2.type], vers->v2.version);
+
			else if (vers->v1.type > 0)
+
				printf("  %s %s\n",
+
				    vop_names[vers->v1.type], vers->v1.version);
+
			else
+
				printf("  %s %s\n",
+
				    vop_names[vers->v2.type], vers->v2.version);
+
		}
+
	}
+
	printf("  %s\n", e->desc);
+
	if (e->cve) {
+
		LL_FOREACH(e->cve, cve) {
+
			printf("  CVE: %s\n", cve->cvename);
+
		}
+
	}
+
	if (e->url)
+
		printf("  WWW: %s\n\n", e->url);
+
	else if (e->id)
+
		printf("  WWW: https://vuxml.FreeBSD.org/freebsd/%s.html\n\n", e->id);
+
}
+

int
exec_audit(int argc, char **argv)
{
	struct pkg_audit	*audit;
+
	struct pkg_audit_issues	*issues;
+
	struct pkg_audit_issue	*issue;
	struct pkgdb		*db = NULL;
	struct pkgdb_it		*it = NULL;
	struct pkg		*pkg = NULL;
@@ -124,7 +173,6 @@ exec_audit(int argc, char **argv)
	bool			 fetch = false, recursive = false;
	int			 ch, i;
	int			 ret = EXIT_SUCCESS;
-
	xstring			*sb;
	kh_pkgs_t		*check = NULL;

	struct option longopts[] = {
@@ -276,23 +324,45 @@ exec_audit(int argc, char **argv)

	if (pkg_audit_process(audit) == EPKG_OK) {
		kh_foreach_value(check, pkg, {
-
			if (pkg_audit_is_vulnerable(audit, pkg, quiet, &sb, &affected)) {
+
			issues = NULL;
+
			if (pkg_audit_is_vulnerable(audit, pkg, &issues, quiet)) {
+
			const char *version;
				vuln ++;
-
				fflush(sb->fp);
-
				printf("%s", sb->buf);
+

+
				affected += issues->count;
+
				pkg_get(pkg, PKG_VERSION, &version);
+
				if (quiet) {
+
					if (version != NULL)
+
						pkg_printf("%n-%v\n", pkg, pkg);
+
						else
+
					pkg_printf("%s\n", pkg);
+
					continue;
+
				}
+

+
				pkg_printf("%n", pkg);
+
				if (version != NULL)
+
					pkg_printf("-%v", pkg);
+
				if (!quiet)
+
					printf(" is vulnerable");
+
				printf(":\n");
+

+
				LL_FOREACH(issues->issues, issue) {
+
					print_issue(pkg, issue);
+
				}

				if (recursive) {
					const char *name;
					kh_pkgs_t *seen = kh_init_pkgs();

					pkg_get(pkg, PKG_NAME, &name);
-
					printf("Packages that depend on %s: ", name);
+
					printf("  Packages that depend on %s: ", name);
					print_recursive_rdeps(check, pkg , seen, true);
+
					printf("\n\n");

					kh_destroy_pkgs(seen);
				}
-
				xstring_free(sb);
			}
+
			pkg_audit_issues_free(issues);
			pkg_free(pkg);
		});
		kh_destroy_pkgs(check);
modified src/upgrade.c
@@ -80,11 +80,11 @@ add_to_check(kh_pkgs_t *check, struct pkg *pkg)
static void
check_vulnerable(struct pkg_audit *audit, struct pkgdb *db, int sock)
{
+
	struct pkg_audit_issues	*issues;
	struct pkgdb_it	*it = NULL;
	struct pkg		*pkg = NULL;
	kh_pkgs_t		*check = NULL;
	const char		*uid;
-
	xstring		*sb;
	int				ret;
	FILE			*out;

@@ -149,12 +149,13 @@ check_vulnerable(struct pkg_audit *audit, struct pkgdb *db, int sock)

	if (pkg_audit_process(audit) == EPKG_OK) {
		kh_foreach_value(check, pkg, {
-
				if (pkg_audit_is_vulnerable(audit, pkg, true, &sb, NULL)) {
+
				issues = NULL;
+
				if (pkg_audit_is_vulnerable(audit, pkg, &issues, true)) {
					pkg_get(pkg, PKG_UNIQUEID, &uid);
					fprintf(out, "%s\n", uid);
					fflush(out);
-
					xstring_free(sb);
				}
+
				pkg_audit_issues_free(issues);
				pkg_free(pkg);
		});