svn commit: r335402 - head/sbin/veriexecctl

Stephen J. Kiernan stevek at FreeBSD.org
Wed Jun 20 01:08:56 UTC 2018


Author: stevek
Date: Wed Jun 20 01:08:54 2018
New Revision: 335402
URL: https://svnweb.freebsd.org/changeset/base/335402

Log:
  This application (veriexecctl) handles reading a fingerprints file
  containing paths, fingerprints, and optional option flags which in turn
  get pushed into the MAC/veriexec meta-data store via the veriexec device.
  
  The format of the fingerprints file is as follows:
  path type fingerprint options
  
  The type of fingerprint supported depends on what MAC/veriexec fingerprint
  modules have been loaded into the system. The veriexecctl application is
  able to determine which ones are available by consulting the
  security.mac.veriexec.algorithms sysctl.
  
  The following options are currently supported in MAC/veriexec and by the
  veriexecctl application:
  
  indirect
    If this option is set then the executable cannot be invoked directly, it
    can only be used as an interpreter in shell scripts.
  file
    Indicates that the fingerprint is associated with a file, not an
    executable. Files have their fingerprints verified during open(2) and are
    automatically made read only. This option may be used to verify shared
    libraries have not been tampered with.
  no_ptrace
    If this option is set then the executable cannot be traced with the
    ptrace(2) process tracing and debugging call.
  trusted
    If this option is set then the executable is allowed to write to the
    mem(4) devices. By default, when verified execution is enforced, no
    process is allowed to write to the mem(4) devices.
  
  The options are not case sensitive.
  
  Reviewed by:	jtl, wblock
  Obtained from:	Juniper Networks, Inc.
  Differential Revision:	https://reviews.freebsd.org/D8575

Added:
  head/sbin/veriexecctl/
  head/sbin/veriexecctl/Makefile   (contents, props changed)
  head/sbin/veriexecctl/veriexecctl.8   (contents, props changed)
  head/sbin/veriexecctl/veriexecctl.c   (contents, props changed)
  head/sbin/veriexecctl/veriexecctl_conf.l   (contents, props changed)
  head/sbin/veriexecctl/veriexecctl_parse.y   (contents, props changed)

Added: head/sbin/veriexecctl/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sbin/veriexecctl/Makefile	Wed Jun 20 01:08:54 2018	(r335402)
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+PROG=	veriexecctl
+MAN=	veriexecctl.8
+SRCS=	veriexecctl_parse.y veriexecctl_conf.l veriexecctl.c
+
+WARNS?=	3
+
+LIBADD=	l
+
+.include <bsd.prog.mk>

Added: head/sbin/veriexecctl/veriexecctl.8
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sbin/veriexecctl/veriexecctl.8	Wed Jun 20 01:08:54 2018	(r335402)
@@ -0,0 +1,121 @@
+.\" $NetBSD: veriexecctl.8,v 1.5 2004/03/06 23:40:13 wiz Exp $
+.\"
+.\" Copyright (c) 1999
+.\"	Brett Lymn - blymn at baea.com.au, brett_lymn at yahoo.com.au
+.\"
+.\" This code is donated to The NetBSD Foundation by the author.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. The name of the Author may not be used to endorse or promote
+.\"    products derived from this software without specific prior written
+.\"    permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 19, 2018
+.Dt VERIEXECCTL 8
+.Os
+.Sh NAME
+.Nm veriexecctl
+.Nd load verified exec fingerprints
+.Sh SYNOPSIS
+.Nm
+.Ar fingerprints
+.Sh DESCRIPTION
+The
+.Nm
+command loads an in-kernel metadata store of the fingerprints
+given in the
+.Ar fingerprints
+file.
+The kernel can then calculate the fingerprint of programs at time of
+execution or files that are opened with
+.Dv O_VERIFY
+and verify whether the fingerprints match.
+.Pp
+The
+.Ar fingerprints
+file contains lines of fields separated by one or more whitespace
+characters:
+.Pp
+.Dl path	type	fingerprint	options
+.Bl -tag -width fingerprint
+.It Em path
+Full path to the file.
+.It Em type
+Type of fingerprint used.
+Currently this may be any of rmd160, sha1, sha256, sha384, or sha512.
+Availability of these fingerprint types is dependent on kernel support.
+The
+.Va security.mac.veriexec.algorithms
+sysctl is consulted to determine the list of valid fingerprint types.
+.It Em fingerprint
+A hexadecimal representation of the fingerprint for the file.
+.It Em options
+Associated options for the file.
+Currently there are four valid options:
+.Bl -tag -width INDIRECT
+.It Pa INDIRECT
+If this option is set then the executable cannot be invoked directly, it
+can only be used as an interpreter in shell scripts.
+.It Pa FILE
+Indicates that the fingerprint is associated with a file, not an
+executable.
+Files have their fingerprints verified during
+.Xr open 2
+and are automatically made read only.
+This option may be used to verify shared libraries have not been
+tampered with.
+.It Pa NO_PTRACE
+If this option is set then the executable cannot be traced with the
+.Xr ptrace 2 process tracing and debugging call.
+.It Pa TRUSTED
+If this option is set then the executable is allowed to write to the
+.Xr mem 4
+devices.
+By default, when verified execution is enforced, no process
+is allowed to write to the
+.Xr mem 4
+devices.
+.El
+.El
+.Pp
+There must be only one executable/fingerprint pair per line.
+Comments are indicated by the first character of a line being a
+.Sq \&#
+character.
+.Sh FILES
+.Bl -tag -width /dev/veriexec -compact
+.It Pa /dev/veriexec
+verified executable device node
+.El
+.Sh SEE ALSO
+.Xr sysctl 3
+.Sh HISTORY
+.Nm
+first appeared in
+.Nx 2.0 .
+.Sh NOTES
+.Nm
+requires the kernel to have been configured with the
+.Dv MAC_VERIEXEC
+option and the veriexec pseudo-device.

Added: head/sbin/veriexecctl/veriexecctl.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sbin/veriexecctl/veriexecctl.c	Wed Jun 20 01:08:54 2018	(r335402)
@@ -0,0 +1,144 @@
+/*-
+ * $FreeBSD$
+ *
+ * Copyright (c) 2015, Juniper Networks, Inc.
+ * All rights reserved.
+ *
+ * Copyright (c) 1998-1999 Brett Lymn
+ *                         (blymn at baea.com.au, brett_lymn at yahoo.com.au)
+ * All rights reserved.
+ *
+ * Originally derived from:
+ *	$NetBSD: veriexecctl.c,v 1.5 2004/03/06 11:57:14 blymn Exp $
+ *
+ * This code has been donated to The NetBSD Foundation by the Author.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/sysctl.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <err.h>
+#include <paths.h>
+#include <sysexits.h>
+
+#include <dev/veriexec/veriexec_ioctl.h>
+
+/* globals */
+int fd;
+extern FILE *yyin;
+int yyparse(void);
+
+const char **algorithms;
+
+static void
+parse_algorithms(void)
+{
+	static char buf[BUFSIZ];
+	size_t len = sizeof(buf);
+	char *bufp;
+	int count, indx;
+
+	if (sysctlbyname("security.mac.veriexec.algorithms", buf, &len, NULL,
+	    0) == -1)
+		err(EXIT_FAILURE,
+		    "Unable to determine any available algorithms");
+	if (len >= sizeof(buf))
+		err(EXIT_FAILURE, "Too many algorithms");
+
+	bufp = buf;
+	count = 0;
+	while (strsep(&bufp, " ") != NULL)
+		count++;
+
+	algorithms = malloc(sizeof(const char *) * (count + 1));
+	if (algorithms == NULL)
+		err(EX_SOFTWARE, "memory allocation failed");
+
+	indx = 0;
+	for (bufp = buf; *bufp != '\0'; bufp += strlen(bufp) + 1)
+		algorithms[indx++] = bufp;
+}
+
+int
+main(int argc, char *argv[])
+{
+	int ctl = 0;
+	int x = 0;
+	
+	if (argv[1] == NULL) {
+		fprintf(stderr, "usage: veriexecctl signature_file\n");
+		return (1);
+	}
+
+	fd = open(_PATH_DEV_VERIEXEC, O_WRONLY, 0);
+	if (fd < 0) {
+		err(EX_UNAVAILABLE, "Open of veriexec device %s failed",
+		    _PATH_DEV_VERIEXEC);
+	}
+
+	if (strncmp(argv[1], "--", 2) == 0) {
+		switch (argv[1][2]) {
+		case 'a':		/* --active */
+			ctl = VERIEXEC_ACTIVE;
+			break;
+		case 'd':		/* --debug* */
+			ctl = (strstr(argv[1], "off")) ?
+				VERIEXEC_DEBUG_OFF : VERIEXEC_DEBUG_ON;
+			if (argc > 2 && ctl == VERIEXEC_DEBUG_ON) {
+				x = atoi(argv[2]);
+			}
+			break;
+		case 'e':		/* --enforce */
+			ctl = VERIEXEC_ENFORCE;
+			break;
+		case 'l':		/* --lock */
+			ctl = VERIEXEC_LOCK;
+			break;
+		}
+		if (ctl) {
+			if (ioctl(fd, ctl, &x)) {
+				err(EXIT_FAILURE, "Cannot %s veriexec",
+				    argv[1]);
+			}
+			if (ctl == VERIEXEC_DEBUG_ON) {
+				printf("debug is: %d\n", x);
+			}
+			return (0);
+		}
+	} else if (strcmp(argv[1], "-")) {
+		if ((yyin = fopen(argv[1], "r")) == NULL) {
+			err(EXIT_FAILURE, "Opening signature file %s failed",
+			    argv[1]);
+		}
+	}
+
+	parse_algorithms();
+
+	yyparse();
+        return (0);
+}

Added: head/sbin/veriexecctl/veriexecctl_conf.l
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sbin/veriexecctl/veriexecctl_conf.l	Wed Jun 20 01:08:54 2018	(r335402)
@@ -0,0 +1,54 @@
+%{
+/*
+ * $FreeBSD$
+ *
+ * Configuration file lexer for Verified exec
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "veriexecctl_parse.h"
+
+int lineno = 1;
+
+void yyerror(const char *message);
+void warning(const char *message);
+int yylex __P((void));
+
+%}
+
+%%
+
+path     { return PATH; }
+string   { return STRING; }
+eol      { return EOL; }
+
+\/[^ 	]+  {
+	yylval.string = strdup(yytext);
+	return PATH;
+}
+
+[0-9a-zA-Z]+  {
+	yylval.string = strdup(yytext);
+	return STRING;
+}
+
+\n      {
+	lineno++;  /* for error reporting */
+	return EOL;
+}
+
+[ \t\r] ;  /* eat white ones */
+
+#.* ;      /* comment */
+
+.    yyerror("invalid character");
+
+%%
+
+void yyerror(const char *string)
+{
+  fprintf(stderr, "%d: %s at %s\n", lineno, string, yytext);
+}

Added: head/sbin/veriexecctl/veriexecctl_parse.y
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sbin/veriexecctl/veriexecctl_parse.y	Wed Jun 20 01:08:54 2018	(r335402)
@@ -0,0 +1,184 @@
+%{
+/*
+ * $FreeBSD$
+ *
+ * Copyright (c) 2015, Juniper Networks, Inc.
+ * All rights reserved.
+ *
+ * Originally derived from:
+ * 	$NetBSD: veriexecctl_parse.y,v 1.3 2004/03/06 11:59:30 blymn Exp $
+ *
+ * Parser for verified exec fingerprint file.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <dev/veriexec/veriexec_ioctl.h>
+
+/* yacc internal function */
+int yylex(void);
+void yyerror(const char *);
+
+/* function prototypes */
+static int convert(char *fp, unsigned int count, unsigned char *out);
+static void do_ioctl(void);
+
+/* ioctl parameter struct */
+static struct verified_exec_params params;
+extern int fd;
+extern int lineno;
+extern const char **algorithms;
+
+%}
+
+%union {
+  char *string;
+  int  intval;
+}
+
+%token EOL
+%token <string> PATH
+%token <string> STRING
+
+%%
+
+statement: /* empty */
+  | statement path type fingerprint flags eol
+  | statement error eol {
+	yyclearin; /* discard lookahead */
+	yyerrok;   /* no more error */
+	fprintf(stderr, "skipping to next fingerprint\n");
+  }
+  ;
+
+path: PATH 
+{
+	if (strlen($1) >= MAXPATHLEN) {
+		yyerror("Path >= MAXPATHLEN");
+		YYERROR;
+	}
+	strncpy(params.file, $1, MAXPATHLEN);
+};
+
+type: STRING
+{
+	const char **algop;
+
+	for (algop = algorithms; *algop != NULL; algop++) {
+		if (strcasecmp($1, *algop) == 0) {
+			strlcpy(params.fp_type, $1, sizeof(params.fp_type));
+			break;
+		}
+	}
+	if (*algop == NULL) {
+		yyerror("bad fingerprint type");
+		YYERROR;
+	}
+};
+
+fingerprint: STRING
+{
+	if (convert($1, MAXFINGERPRINTLEN, params.fingerprint) < 0) {
+		yyerror("bad fingerprint");
+		YYERROR;
+	}
+};
+
+flags: /* empty */
+	| flag_spec flags;
+
+flag_spec: STRING
+{
+	if (strcasecmp($1, "indirect") == 0)
+		params.flags |= VERIEXEC_INDIRECT;
+	else if (strcasecmp($1, "file") == 0)
+		params.flags |= VERIEXEC_FILE;
+	else if (strcasecmp($1, "no_ptrace") == 0)
+		params.flags |= VERIEXEC_NOTRACE;
+	else if (strcasecmp($1, "trusted") == 0)
+		params.flags |= VERIEXEC_TRUSTED;
+	else {
+		yyeror("bad flag specification");
+		YYERROR;
+	}
+};
+
+eol: EOL
+{
+	if (!YYRECOVERING()) /* Don't do the ioctl if we saw an error */
+		do_ioctl();
+};
+
+%%
+		
+/*
+ * Convert: takes the hexadecimal string pointed to by fp and converts
+ * it to a "count" byte binary number which is stored in the array pointed to
+ * by out.  Returns -1 if the conversion fails.
+ */
+static int
+convert(char *fp, unsigned int count, unsigned char *out)
+{
+        unsigned int i;
+	int value;
+
+        for (i = 0; i < count; i++) {
+		value = 0;
+                if (isdigit(fp[i * 2]))
+			value += fp[i * 2] - '0';
+                else if (isxdigit(fp[i * 2]))
+                        value = 10 + tolower(fp[i * 2]) - 'a';
+                else
+			return (-1);
+
+		value <<= 4;
+                if (isdigit(fp[i * 2 + 1]))
+			value += fp[i * 2 + 1] - '0';
+                else if (isxdigit(fp[i * 2 + 1]))
+                        value = 10 + tolower(fp[i * 2 + 1]) - 'a';
+                else
+			return (-1);
+
+		out[i] = value;
+        }
+        
+        return (i);
+}
+
+/*
+ * Perform the load of the fingerprint.  Assumes that the fingerprint
+ * pseudo-device is opened and the file handle is in fd.
+ */
+static void
+do_ioctl(void)
+{
+	if (ioctl(fd, VERIEXEC_LOAD, &params) < 0)
+		fprintf(stderr,	"Ioctl failed with error `%s' on file %s\n",
+			strerror(errno), params.file);
+	bzero(&params, sizeof(params));
+}


More information about the svn-src-head mailing list