Subject: veriexecgen: removing duplicate files
To: None <tech-userlevel@NetBSD.org>
From: M J Fleming <mjf@NetBSD.org>
List: tech-userlevel
Date: 10/29/2006 23:15:47
--SUOF0GtieIMvvwua
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi, currently veriexecgen will create a seperate entry in a fingerprintdb file 
for hard-links. The attached patch only adds one entry per inode/device number.
Is it safe to use inode/device pairs for this purpose? Comments?

Thanks,
Matt

--SUOF0GtieIMvvwua
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="veriexecgen.patch"

? usr.sbin/veriexecgen/.gdbinit
? usr.sbin/veriexecgen/veriexecgen
? usr.sbin/veriexecgen/veriexecgen.cat8
Index: usr.sbin/veriexecgen/veriexecgen.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/veriexecgen/veriexecgen.c,v
retrieving revision 1.6
diff -u -r1.6 veriexecgen.c
--- usr.sbin/veriexecgen/veriexecgen.c	23 Sep 2006 19:08:48 -0000	1.6
+++ usr.sbin/veriexecgen/veriexecgen.c	7 Oct 2006 14:56:32 -0000
@@ -40,11 +40,13 @@
 #include <sys/types.h>
 #include <sys/queue.h>
 #include <sys/stat.h>
+#include <sys/statvfs.h>
 #include <sys/dirent.h>
 #include <sys/verified_exec.h>
 
 #include <err.h>
 #include <errno.h>
+#include <fnmatch.h>
 #include <fts.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -65,11 +67,21 @@
 #define DEFAULT_SYSPATHS { "/bin", "/sbin", "/usr/bin", "/usr/sbin", \
 			   "/lib", "/usr/lib", "/libexec", "/usr/libexec", \
 			   NULL }
+#define DEFAULT_INTERPRETERS { "/bin/sh", "/bin/csh", "/bin/ksh",	\
+			      "/usr/pkg/bin/perl", "/usr/pkg/bin/python2.4", \
+			      NULL }
+#define DEFAULT_LIBS { "/lib/*", "/usr/lib/*", "/usr/pkg/lib/*", NULL }
+#define DEFAULT_SCRIPT_SUFFIX { ".sh", ".py", ".pl", NULL }
+
+#define PROGRAM			VERIEXEC_DIRECT
+#define INTERPRETER		VERIEXEC_INDIRECT
+#define SCRIPT			(VERIEXEC_DIRECT | VERIEXEC_FILE)
+#define LIBRARY			0x20
 
 struct fentry {
 	char filename[MAXPATHLEN];
 	char *hash_val;
-	int flags;
+	char *flags;
 	TAILQ_ENTRY(fentry) f;
 };
 TAILQ_HEAD(, fentry) fehead;
@@ -87,13 +99,26 @@
 	{ NULL, NULL },
 };
 
-int Aflag, aflag, Dflag, Fflag, rflag, Sflag, vflag;
+struct flags {
+	int script;
+	int lib;
+	int intrprtr;
+	int exec;
+	int local;
+};
+
+int Aflag, aflag, Dflag, Fflag, Iflag, iflag, Lflag, lflag, rflag;
+int Sflag, sflag, vflag, Xflag;
+
+char **interpreter_patterns = NULL;
+char **lib_patterns = NULL;
+char **scripts = NULL;
 
 static void
 usage(void)
 {
 	(void)fprintf(stderr,
-	    "usage: %s [-AaDrSv] [-d dir] [-o fingerprintdb]"
+	    "usage: %s [-AaDFIiLlrSsvX] [-d dir] [-o fingerprintdb]"
 	    " [-t algorithm]\n", getprogname());
 }
 
@@ -130,20 +155,89 @@
 	return h->filefunc(filename, NULL);
 }
 
+static char * 
+weigh_flags(struct flags f)
+{
+	char *buf = "";
+
+	if (!(f.local))
+		easprintf(&buf, "%sUNTRUSTED", *buf ? ", " : "");
+
+	if (f.script)
+		easprintf(&buf, "%s%sSCRIPT", buf, *buf ? ", " : "");
+	else if (f.lib)
+		easprintf(&buf, "%s%sLIBRARY", buf, *buf ? ", " : "");
+	else if (f.intrprtr)
+		easprintf(&buf, "%s%sINTERPRETER", buf, *buf ? ", " : "");
+	else if (f.exec)
+		easprintf(&buf, "%s%sPROGRAM", buf, *buf ? ", " : "");
+	else 
+		easprintf(&buf, "%s%sFILE", buf, *buf ? ", " : "");
+
+	return buf;
+}
+
 static int
+wildcard(char **list, char *path)
+{
+	int i;
+	char **a = list;
+
+	for (i = 0; a[i] != NULL; i++) {
+		if (!fnmatch(a[i], path, 0))
+			return 1;
+	}
+	return 0;
+}
+
+static char * 
 figure_flags(char *path, mode_t mode)
 {
-#ifdef notyet
+	char *p;
+	struct statvfs st;
+	struct flags f;
+
+	memset(&f, 0, sizeof(struct flags));
+
 	if (Fflag) {
 		/* Try to figure out right flag(s). */
-		return VERIEXEC_DIRECT;
-}
-#endif /* notyet */
+		if (statvfs(path, &st) == -1)
+			err(1, "could not stat %s", path);
+
+		if ((st.f_flag & MNT_LOCAL))
+			f.local = 1;
 
-	if (!IS_EXEC(mode))
-		return VERIEXEC_FILE;
-	else
-		return 0;
+		if (IS_EXEC(mode))
+			f.exec = 1;
+
+		if (Lflag) {
+			char *a[] = DEFAULT_LIBS;
+			f.lib = wildcard(a, path);
+		}
+
+		if (lflag && *lib_patterns != NULL)
+			f.lib = wildcard(lib_patterns, path);
+
+		if (Iflag) {
+			char *a[] = DEFAULT_INTERPRETERS;
+			f.intrprtr = wildcard(a, path);
+		}
+
+		if (iflag && *interpreter_patterns != NULL)
+			f.intrprtr = wildcard(interpreter_patterns, path);
+
+		if (Sflag && ((p = strchr(path, '.')) != NULL)) {
+			char *a[] = DEFAULT_SCRIPT_SUFFIX;
+			f.script = wildcard(a, p);
+		}
+
+		if (sflag && *scripts != NULL)
+			f.script = wildcard(scripts, path);
+
+	} else if (IS_EXEC(mode))
+		f.exec = 1;
+
+	return weigh_flags(f);
 }
 
 static int
@@ -168,7 +262,7 @@
 
 	if (file->fts_info == FTS_SL) {
 		if (stat(file->fts_path, &sb) == -1)
-			err(1, "Cannot stat symlink");
+			err(1, "Cannot stat symlink %s", file->fts_path);
 	} else
 		sb = *file->fts_statp;
 
@@ -225,15 +319,6 @@
 	fts_close(fh);
 }
 
-static char *
-flags2str(int flags)
-{
-	if (flags != 0)
-		return "FILE";
-	else
-		return "";
-}
-
 static void
 store_entries(char *dbfile, struct hash *hash)
 {
@@ -274,7 +359,7 @@
 			(void)printf("Adding %s.\n", e->filename);
 
 		(void)fprintf(fp, "%s %s %s %s\n", e->filename,
-			hash->hashname, e->hash_val, flags2str(e->flags));
+			hash->hashname, e->hash_val, e->flags);
 	}
 
 	(void)fclose(fp);
@@ -293,14 +378,15 @@
 int
 main(int argc, char **argv)
 {
-	int ch, total = 0;
+	int ch, stotal = 0, itotal = 0, sutotal = 0, ltotal = 0;
 	char *dbfile = NULL;
 	char **search_path = NULL;
 	struct hash *hash = NULL;
 
-	Aflag = aflag = Dflag = Fflag = rflag = Sflag = vflag = 0;
+	Aflag = aflag = Dflag = Fflag = Iflag = iflag = Lflag = lflag;
+	rflag = Sflag = sflag = vflag = Xflag = 0;
 
-	while ((ch = getopt(argc, argv, "AaDd:ho:rSt:v")) != -1) {
+	while ((ch = getopt(argc, argv, "AaDd:FhIiLl::o:rSs:t:vX")) != -1) {
 		switch (ch) {
 		case 'A':
 			Aflag = 1;
@@ -313,18 +399,34 @@
 			break;
 		case 'd':
 			search_path = erealloc(search_path, sizeof(char *) *
-			    (total + 1));
-			search_path[total] = optarg;
-			search_path[++total] = NULL;
+			    (stotal + 1));
+			search_path[stotal] = optarg;
+			search_path[++stotal] = NULL;
 			break;
-#ifdef notyet
 		case 'F':
 			Fflag = 1;
 			break;
-#endif /* notyet */
 		case 'h':
 			usage();
 			return 0;
+		case 'I':
+			Iflag = 1;
+			break;
+		case 'i':
+			iflag = 1;
+			interpreter_patterns = erealloc(interpreter_patterns,
+						sizeof(char *) * (itotal + 1));
+			interpreter_patterns[itotal++] = optarg;
+			break;
+		case 'L':
+			Lflag = 1;
+			break;
+		case 'l':
+			lflag = 1;
+			lib_patterns = erealloc(lib_patterns, sizeof(char *) *
+						(ltotal + 1));
+			lib_patterns[ltotal++] = optarg;
+			break;
 		case 'o':
 			dbfile = optarg;
 			break;
@@ -334,18 +436,31 @@
 		case 'S':
 			Sflag = 1;
 			break;
+		case 's':
+			sflag = 1;
+			scripts = erealloc(scripts,
+						sizeof(char *) * (sutotal + 1));
+			scripts[sutotal++] = optarg;
+			break;
 		case 't':
 			hash = find_hash(optarg);
 			break;
 		case 'v':
 			vflag = 1;
 			break;
+		case 'X':
+			Xflag = 1;
+			break;
 		default:
 			usage();
 			return 1;
 		}
 	}
 
+	/* -F implies -I and -S */
+	if (Fflag)
+		Iflag = Lflag = Sflag = 1;
+
 	if (dbfile == NULL)
 		dbfile = DEFAULT_DBFILE;
 
@@ -375,7 +490,7 @@
 
 	store_entries(dbfile, hash);
 
-	if (Sflag && chflags(dbfile, SF_IMMUTABLE) != 0)
+	if (Xflag && chflags(dbfile, SF_IMMUTABLE) != 0)
 		err(1, "Can't set immutable flag");
 
 	return 0;

--SUOF0GtieIMvvwua--