Author: sjg
Date: Tue Feb 26 06:17:23 2019
New Revision: 344567
URL: https://svnweb.freebsd.org/changeset/base/344567

Log:
  Add verifying manifest loader for mac_veriexec
  
  This tool will verify a signed manifest and load contents into
  mac_veriexec for storage
  
  Sponsored by: Juniper Networks
  Differential Revision:        D16575

Added:
  head/sbin/veriexec/
  head/sbin/veriexec/Makefile   (contents, props changed)
  head/sbin/veriexec/Makefile.depend   (contents, props changed)
  head/sbin/veriexec/manifest_lexer.l   (contents, props changed)
  head/sbin/veriexec/manifest_parser.y   (contents, props changed)
  head/sbin/veriexec/veriexec.8   (contents, props changed)
  head/sbin/veriexec/veriexec.c   (contents, props changed)
  head/sbin/veriexec/veriexec.h   (contents, props changed)
Modified:
  head/etc/mtree/BSD.include.dist
  head/include/Makefile
  head/sbin/Makefile

Modified: head/etc/mtree/BSD.include.dist
==============================================================================
--- head/etc/mtree/BSD.include.dist     Tue Feb 26 06:11:01 2019        
(r344566)
+++ head/etc/mtree/BSD.include.dist     Tue Feb 26 06:17:23 2019        
(r344567)
@@ -160,6 +160,8 @@
         ..
         usb
         ..
+        veriexec
+        ..
         vkbd
         ..
         wi
@@ -353,6 +355,8 @@
         mac_mls
         ..
         mac_partition
+        ..
+        mac_veriexec
         ..
     ..
     ssp

Modified: head/include/Makefile
==============================================================================
--- head/include/Makefile       Tue Feb 26 06:11:01 2019        (r344566)
+++ head/include/Makefile       Tue Feb 26 06:17:23 2019        (r344567)
@@ -47,7 +47,7 @@ LSUBDIRS=     cam/ata cam/mmc cam/nvme cam/scsi \
        dev/hwpmc dev/hyperv \
        dev/ic dev/iicbus dev/io dev/mfi dev/mmc dev/nvme \
        dev/ofw dev/pbio dev/pci ${_dev_powermac_nvram} dev/ppbus dev/smbus \
-       dev/speaker dev/tcp_log dev/vkbd dev/wi \
+       dev/speaker dev/tcp_log dev/veriexec dev/vkbd dev/wi \
        fs/devfs fs/fdescfs fs/msdosfs fs/nandfs fs/nfs fs/nullfs \
        fs/procfs fs/smbfs fs/udf fs/unionfs \
        geom/cache geom/concat geom/eli geom/gate geom/journal geom/label \
@@ -60,6 +60,7 @@ LSUBDIRS=     cam/ata cam/mmc cam/nvme cam/scsi \
        security/audit \
        security/mac_biba security/mac_bsdextended security/mac_lomac \
        security/mac_mls security/mac_partition \
+       security/mac_veriexec \
        sys/disk \
        ufs/ffs ufs/ufs
 
@@ -157,7 +158,7 @@ copies: .PHONY .META
                done; \
        fi
 .endfor
-.for i in ${LDIRS} 
${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/hyperv:Ndev/nand:Ndev/pci}
 ${LSUBSUBDIRS}
+.for i in ${LDIRS} 
${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/hyperv:Ndev/nand:Ndev/pci:Ndev/veriexec}
 ${LSUBSUBDIRS}
        cd ${SRCTOP}/sys; \
        ${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 $i/*.h \
            ${SDESTDIR}${INCLUDEDIR}/$i
@@ -196,6 +197,9 @@ copies: .PHONY .META
        cd ${SRCTOP}/sys/dev/pci; \
        ${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 pcireg.h \
            ${SDESTDIR}${INCLUDEDIR}/dev/pci
+       cd ${SRCTOP}/sys/dev/veriexec; \
+       ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 veriexec_ioctl.h \
+           ${SDESTDIR}${INCLUDEDIR}/dev/veriexec
        cd ${SRCTOP}/sys/fs/cd9660/; \
        ${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 *.h \
            ${SDESTDIR}${INCLUDEDIR}/isofs/cd9660
@@ -264,7 +268,7 @@ symlinks: .PHONY .META
                ${INSTALL_SYMLINK} ${TAG_ARGS} ../../../sys/$i/$$h 
${SDESTDIR}${INCLUDEDIR}/$i; \
        done
 .endfor
-.for i in 
${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/hyperv:Ndev/nand:Ndev/pci}
+.for i in 
${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/hyperv:Ndev/nand:Ndev/pci:Ndev/veriexec}
        cd ${SRCTOP}/sys/$i; \
        for h in *.h; do \
                ${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/$i/$$h 
${SDESTDIR}${INCLUDEDIR}/$i; \
@@ -311,6 +315,11 @@ symlinks: .PHONY .META
        for h in pcireg.h; do \
                ${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/dev/pci/$$h \
                    ${SDESTDIR}${INCLUDEDIR}/dev/pci; \
+       done
+       cd ${SRCTOP}/sys/dev/veriexec; \
+       for h in veriexec_ioctl.h; do \
+               ln -fs ../../../../sys/dev/veriexec/$$h \
+                   ${SDESTDIR}${INCLUDEDIR}/dev/veriexec; \
        done
 .for i in ${LSUBSUBDIRS}
        cd ${SRCTOP}/sys/$i; \

Modified: head/sbin/Makefile
==============================================================================
--- head/sbin/Makefile  Tue Feb 26 06:11:01 2019        (r344566)
+++ head/sbin/Makefile  Tue Feb 26 06:17:23 2019        (r344567)
@@ -87,6 +87,7 @@ SUBDIR.${MK_PF}+=     pfctl
 SUBDIR.${MK_PF}+=      pflogd
 SUBDIR.${MK_QUOTAS}+=  quotacheck
 SUBDIR.${MK_ROUTED}+=  routed
+SUBDIR.${MK_VERIEXEC}+=        veriexec
 SUBDIR.${MK_ZFS}+=     bectl
 SUBDIR.${MK_ZFS}+=     zfsbootcfg
 

Added: head/sbin/veriexec/Makefile
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sbin/veriexec/Makefile Tue Feb 26 06:17:23 2019        (r344567)
@@ -0,0 +1,20 @@
+# $FreeBSD$
+
+PROG=  veriexec
+MAN=   veriexec.8
+SRCS= \
+       veriexec.c \
+       manifest_parser.y \
+       manifest_lexer.l
+
+LIBADD+= veriexec secureboot bearssl
+
+NO_SHARED=
+
+.include <bsd.prog.mk>
+
+CFLAGS+= -I${.CURDIR} ${XCFLAGS.${.TARGET:T:R}:U}
+
+XCFLAGS.manifest_lexer+= -Wno-missing-variable-declarations \
+       -Wno-unneeded-internal-declaration
+XCFLAGS.manifest_parser+= -Wno-missing-variable-declarations

Added: head/sbin/veriexec/Makefile.depend
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sbin/veriexec/Makefile.depend  Tue Feb 26 06:17:23 2019        
(r344567)
@@ -0,0 +1,20 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+       gnu/lib/csu \
+       include \
+       include/xlocale \
+       lib/${CSU_DIR} \
+       lib/libbearssl \
+       lib/libc \
+       lib/libcompiler_rt \
+       lib/libsecureboot \
+       lib/libveriexec \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif

Added: head/sbin/veriexec/manifest_lexer.l
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sbin/veriexec/manifest_lexer.l Tue Feb 26 06:17:23 2019        
(r344567)
@@ -0,0 +1,151 @@
+%{
+/*-
+ * Copyright (c) 2004-2018, Juniper Networks, Inc.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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$
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "veriexec.h"
+#include "manifest_parser.h"
+
+#define YY_NO_UNPUT
+
+int lineno = 1;
+int bol = 1;
+extern int parser_version;
+ 
+void yyerror(const char *message);
+void warning(const char *message);
+int yylex(void);
+
+%}
+
+%%
+
+\n {
+       lineno++;
+       bol=1;
+       return EOL;
+}
+
+[/a-zA-Z0-9\.][^ \t\n=]*  {
+       yylval.string = strdup(yytext);
+       if (bol) {
+               bol=0;
+               return PATH;
+       } else
+               return STRING;
+}
+
+= {
+       return EQ;
+}
+
+
+[ \t\r] ;  /* eat white ones */
+
+#>[0-9]+ {
+        /*
+         * If we are older than the specified version
+         * ignore rest of line, otherwise just discard this token.
+         */
+        int skip = atoi(&yytext[2]);
+
+        VERBOSE(3, ("%s: skip if %d <= %d\n", yytext, parser_version, skip));
+        if (parser_version <= skip) {
+               /* treat as a comment, yyless() is cheaper than yyunput() */
+               yytext[yyleng - 1] = '#';
+               yyless(2);
+        }
+}
+
+#[^>\n].* ;      /* comment */
+
+.    yyerror("invalid character");
+
+%%
+
+static char *manifest_file = NULL;
+
+struct string_buf {
+       const char *buf;
+       size_t pos, size;
+};
+
+static int
+read_string_buf (void *token, char *dest, int count)
+{
+       struct string_buf *str_buf_p = (struct string_buf *)token;
+       ssize_t n;
+
+       if (count < 0)
+               return 0;
+
+       n = str_buf_p->size - str_buf_p->pos;
+       if (count < n)
+               n = count;
+
+       memcpy(dest, str_buf_p->buf + str_buf_p->pos, n);
+       str_buf_p->pos += n;
+
+       return n;
+}
+
+FILE *
+manifest_open (const char *file, const char *file_content)
+{
+       static struct string_buf str_buf;
+    
+       if (manifest_file) {
+               free(manifest_file);
+               fclose(yyin);
+       }
+
+       str_buf.buf  = file_content;
+       str_buf.pos  = 0;
+       str_buf.size = strlen(file_content);
+       yyin = fropen(&str_buf, read_string_buf);
+       if (yyin) {
+               manifest_file = strdup(file);
+               lineno = 1;
+               manifest_parser_init();
+       } else
+               manifest_file = NULL;
+       return yyin;
+}
+
+void
+yyerror(const char *string)
+{
+       fprintf(stderr, "%s: %d: %s at %s\n",
+           manifest_file, lineno, string, yytext);
+}
+
+int
+yywrap(void)
+{
+       return (1);
+}

Added: head/sbin/veriexec/manifest_parser.y
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sbin/veriexec/manifest_parser.y        Tue Feb 26 06:17:23 2019        
(r344567)
@@ -0,0 +1,301 @@
+%{
+/*-
+ * Copyright (c) 2004-2018, Juniper Networks, Inc.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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$
+ */
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <err.h>
+#include <sysexits.h>
+#include <libsecureboot.h>
+
+#include "veriexec.h"
+
+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);
+static int get_fingerprint_type(const char *fp_type);
+
+/* ioctl parameter struct */
+#ifdef MAXLABELLEN
+static struct verified_exec_label_params lparams;
+static struct verified_exec_params *params = &lparams.params;
+#else
+static struct verified_exec_params oparams;
+static struct verified_exec_params *params = &oparams;
+#endif
+
+#ifndef SHA256_DIGEST_LENGTH
+# define SHA_DIGEST_LENGTH br_sha1_SIZE
+# define SHA256_DIGEST_LENGTH br_sha256_SIZE
+# define SHA384_DIGEST_LENGTH br_sha384_SIZE
+#endif
+
+static int fmode;
+ 
+extern int lineno;
+extern int dev_fd;
+
+struct fingerprint_type {
+       const char *fp_type;
+       int fp_size;
+};
+
+/* static globals */
+static const struct fingerprint_type fingerprint_table[] = {
+       { "sha1", SHA_DIGEST_LENGTH },
+       { "sha256", SHA256_DIGEST_LENGTH },
+#if MAXFINGERPRINTLEN > 32
+       { "sha384", SHA384_DIGEST_LENGTH },
+#endif
+       { NULL, 0 }
+};
+
+/*
+ * Indicate to lexer our version.
+ * A token #>NUMBER will be consumed (and discared)
+ * by lexer if parser_version > NUMBER
+ * Otherwise the rest of the line will be discared
+ * as for a comment.
+ */
+int parser_version = 1;
+ 
+%}
+
+%union {
+       char *string;
+       int  intval;
+}
+
+%token EOL
+%token <string> EQ
+%token <string> PATH
+%token <string> STRING
+
+%%
+
+statement: /* empty */
+       | statement path attributes eol
+       | statement error eol {
+               yyclearin; /* discard lookahead */
+               yyerrok;   /* no more error */
+               fprintf(stderr,
+                   "skipping to next fingerprint\n");
+       }
+       ;
+
+attributes: /* empty */
+       | attributes flag
+       | attributes attr
+       ;
+
+attr: STRING EQ STRING
+{
+       int fptype;
+
+       fptype = get_fingerprint_type($1);
+
+       /*
+        * There's only one attribute we care about
+        */
+       if (fingerprint_table[fptype].fp_size) {
+               strlcpy(params->fp_type, $1, sizeof(params->fp_type));
+               if (convert($3, fingerprint_table[fptype].fp_size,
+                       params->fingerprint) < 0) {
+                       yyerror("bad fingerprint");
+                       YYERROR;
+               }
+       } else if (strcmp($1, "label") == 0) {
+               static int warned_labels = 0;
+
+#ifdef VERIEXEC_LABEL
+               strlcpy(lparams.label, $3, sizeof(lparams.label));
+               VERBOSE(3, ("version=%d label=%s\n", VeriexecVersion,
+                       lparams.label));
+               if (VeriexecVersion > 1) {
+                       params->flags |= VERIEXEC_LABEL;
+               } else
+#endif
+               if (!warned_labels) {
+                       warnx("ignoring labels");
+                       warned_labels = 1;
+               }
+       } else if (strcmp($1, "mode") == 0) {
+               fmode = (int)strtol($3, NULL, 8);
+       }
+};
+
+flag: STRING
+{
+       /*
+        * indirect only matters if the interpreter itself is not
+        * executable.
+        */
+       if (!strcmp($1, "indirect")) {
+               params->flags |= VERIEXEC_INDIRECT;
+       } else if (!strcmp($1, "no_ptrace")) {
+               params->flags |= VERIEXEC_NOTRACE;
+       } else if (!strcmp($1, "trusted")) {
+               params->flags |= VERIEXEC_TRUSTED;
+       } else if (!strcmp($1, "no_fips")) {
+#ifdef VERIEXEC_NOFIPS
+               params->flags |= VERIEXEC_NOFIPS;
+#endif
+       }
+}
+;
+
+path: PATH 
+{
+       if (strlen($1) >= MAXPATHLEN) {
+               yyerror("Path >= MAXPATHLEN");
+               YYERROR;
+       }
+       /*
+        * The majority of files in the manifest are relative
+        * to the package mount point, but we want absolute paths.
+        * Prepending '/' is actually all we need.
+        */
+       if (snprintf(params->file, sizeof(params->file), "%s%s%s",
+               Cdir ? Cdir : "",
+               ($1[0] == '/') ? "" : "/",
+               $1) >= (int)sizeof(params->file)) {
+               errx(EX_DATAERR, "cannot form pathname");
+       }
+       params->flags = 0;
+       fmode = -1;                     /* unknown */
+};
+
+eol: EOL
+{
+       if (!YYRECOVERING()) { /* Don't do the ioctl if we saw an error */
+               do_ioctl();
+       }
+       params->fp_type[0] = '\0';      /* invalidate it */
+};
+
+%%
+
+void
+manifest_parser_init(void)
+{
+       params->fp_type[0] = '\0';      /* invalidate it */
+}
+
+int
+get_fingerprint_type(const char *fp_type)
+{
+       int i;
+
+       for (i = 0; fingerprint_table[i].fp_type; i++)
+               if (!strcmp(fp_type, fingerprint_table[i].fp_type))
+                       break;
+
+       return (i);
+}
+
+/*
+ * 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)
+{
+       struct stat st;
+
+       if (params->fp_type[0] == '\0') {
+               VERBOSE(1,("skipping %s\n", params->file));
+               return;
+       }
+
+       /*
+        * See if the path is executable, if not put it on the FILE list.
+        */
+       if (fmode > 0) {
+               if (!(fmode & (S_IXUSR|S_IXGRP|S_IXOTH))) {
+                       params->flags |= VERIEXEC_FILE;
+               }
+       } else if (stat(params->file, &st) == 0) {
+               if (!(st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))) {
+                       params->flags |= VERIEXEC_FILE;
+               }
+       }
+       /*
+        * We may be forcing some flags...
+        */
+       params->flags |= ForceFlags;
+       VERBOSE(1, ("loading %s for %s %s flags=%#x\n",
+               params->fp_type,
+               (params->flags == VERIEXEC_FILE) ? "file" : "executable",
+               params->file, params->flags));
+
+#ifdef VERIEXEC_LABEL
+       if (params->flags & VERIEXEC_LABEL) {
+               if (ioctl(dev_fd, VERIEXEC_LABEL_LOAD, &lparams) < 0)
+                       warn("cannot update veriexec label for %s",
+                           params->file);
+       } else
+#endif
+       if (ioctl(dev_fd, VERIEXEC_SIGNED_LOAD, params) < 0)
+               warn("cannot update veriexec for %s", params->file);
+       params->fp_type[0] = '\0';
+}

Added: head/sbin/veriexec/veriexec.8
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sbin/veriexec/veriexec.8       Tue Feb 26 06:17:23 2019        
(r344567)
@@ -0,0 +1,146 @@
+.\"-
+.\" Copyright (c) 2018, Juniper Networks, Inc.
+.\"
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" "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 COPYRIGHT
+.\" OWNER OR CONTRIBUTORS 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 July 4, 2018
+.Dt VERIEXEC 8
+.Os
+.Sh NAME
+.Nm veriexec
+.Nd manipulate state of mac_veriexec
+.Sh SYNOPSIS
+.Nm
+.Op Fl v
+.Op Fl C Ar directory
+.Pa manifest
+.Nm
+.Fl z Ar state
+.Nm
+.Fl i Ar state
+.Nm
+.Fl x
+.Ar file ...
+.Sh DESCRIPTION
+.Nm
+is a utility to query or manipulate the state of
+.Xr mac_veriexec 4 .
+.Pp
+The first form is for loading a
+.Pa manifest .
+.Nm
+first verifies a digital signature of the
+.Ar manifest
+and if successful, parses it and feeds its content to kernel.
+.Pp
+The second form with
+.Fl z
+is used to modify the
+.Ar state ,
+and with
+.Fl i
+to query the current
+.Ar state .
+.Pp
+The final form with
+.Fl x
+is used to test whether
+.Ar file
+is verified or not.
+This requires
+.Xr mac_veriexec 4
+to be in the
+.Ql active
+or
+.Ql enforce
+state.
+.Pp
+The possible states
+are:
+.Bl -tag -width enforce
+.It Ar loaded
+set automatically when first
+.Pa manifest
+has been loaded.
+.It Ar active
+.Xr mac_veriexec 4
+will begin checking files.
+This state can only be entered from the
+.Ar loaded
+state.
+.It Ar enforce
+.Xr mac_veriexec 4
+will fail attempts to
+.Xr exec 2
+or
+.Xr open 2
+files with
+.Dv O_VERIFY
+unless verified.
+.It Ar locked
+prevent loading of any more manifests.
+.El
+.Sh MANIFESTS
+The manifest contains a mapping of relative pathnames to fingerprints
+with optional flags.
+For example:
+.Bd -literal -offset indent
+sbin/veriexec sha256=f22136...c0ff71 no_ptrace
+usr/bin/python sha256=5944d9...876525 indirect
+sbin/somedaemon sha256=77fc2f...63f5687 label=mod1/val1,mod2/val2
+.Ed
+The supported flags are:
+.Bl -tag -width indirect
+.It Ql indirect
+the executable cannot be run directly,
+but can be used as an interpreter for example via:
+.Bd -literal -offset indent
+#!/usr/bin/python
+.Ed
+.It Ql no_ptrace
+do not allow running executable under a debugger.
+Useful for any application critical to the security state of system.
+.El
+.Pp
+The
+.Ql label
+argument allows associating a
+.Xr maclabel 7
+with the executable.
+Neither
+.Nm
+nor
+.Xr mac_veriexec 4
+(if it supports labels)
+pay any attention to the content of the label
+they are provided for the use of other
+.Xr mac 4
+modules.
+.Sh HISTORY
+The Verified Exec system first appeared in NetBSD.
+This utility derrives from the one found in Junos.
+The key difference is the requirement that manifest files
+be digitally signed.
+
+

Added: head/sbin/veriexec/veriexec.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sbin/veriexec/veriexec.c       Tue Feb 26 06:17:23 2019        
(r344567)
@@ -0,0 +1,177 @@
+/*-
+ * Copyright (c) 2018, Juniper Networks, Inc.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <paths.h>
+#include <err.h>
+#include <syslog.h>
+#include <libsecureboot.h>
+#include <libveriexec.h>
+
+#include "veriexec.h"
+
+int dev_fd = -1;
+int ForceFlags = 0;
+int Verbose = 0;
+int VeriexecVersion = 0;
+
+const char *Cdir = NULL;
+
+static int
+veriexec_load(const char *manifest)
+{
+       unsigned char *content;
+       int rc;
+
+       content = verify_signed(manifest, VEF_VERBOSE);
+       if (!content)
+               errx(EX_USAGE, "cannot verify %s", manifest);
+       if (manifest_open(manifest, content)) {
+               rc = yyparse();
+       } else {
+               err(EX_NOINPUT, "cannot load %s", manifest);
+       }
+       free(content);
+       return (rc);
+}
+
+int
+main(int argc, char *argv[])
+{
+       unsigned long ctl;
+       int c;
+       int x;
+
+       dev_fd = open(_PATH_DEV_VERIEXEC, O_WRONLY, 0);
+
+       while ((c = getopt(argc, argv, "C:i:x:vz:")) != -1) {
+               switch (c) {
+               case 'C':
+                       Cdir = optarg;
+                       break;
+               case 'i':
+                       if (dev_fd < 0) {
+                               err(EX_UNAVAILABLE, "cannot open veriexec");
+                       }
+                       if (ioctl(dev_fd, VERIEXEC_GETSTATE, &x)) {
+                               err(EX_UNAVAILABLE,
+                                   "Cannot get veriexec state");
+                       }
+                       switch (optarg[0]) {
+                       case 'a':       /* active */
+                               ctl = VERIEXEC_STATE_ACTIVE;
+                               break;
+                       case 'e':       /* enforce */
+                               ctl = VERIEXEC_STATE_ENFORCE;
+                               break;
+                       case 'l':       /* loaded/locked */
+                               ctl = (strncmp(optarg, "lock", 4)) ?
+                                   VERIEXEC_STATE_LOCKED :
+                                   VERIEXEC_STATE_LOADED;
+                               break;
+                       default:
+                               errx(EX_USAGE, "unknown state %s", optarg);
+                               break;
+                       }
+                       exit((x & ctl) == 0);
+                       break;
+               case 'v':
+                       Verbose++;
+                       break;
+               case 'x':
+                       /*
+                        * -x says all other args are paths to check.
+                        */
+                       for (x = 0; optind < argc; optind++) {
+                               if (veriexec_check_path(argv[optind])) {
+                                       warn("%s", argv[optind]);
+                                       x = 2;
+                               }
+                       }
+                       exit(x);
+                       break;
+               case 'z':
+                       switch (optarg[0]) {
+                       case 'a':       /* active */
+                               ctl = VERIEXEC_ACTIVE;
+                               break;
+                       case 'd':       /* debug* */
+                               ctl = (strstr(optarg, "off")) ?
+                                   VERIEXEC_DEBUG_OFF : VERIEXEC_DEBUG_ON;
+                               if (optind < argc && ctl == VERIEXEC_DEBUG_ON) {
+                                       x = atoi(argv[optind]);
+                                       if (x == 0)
+                                               ctl = VERIEXEC_DEBUG_OFF;
+                               }
+                               break;
+                       case 'e':       /* enforce */
+                               ctl = VERIEXEC_ENFORCE;
+                               break;
+                       case 'g':
+                               ctl = VERIEXEC_GETSTATE; /* get state */
+                               break;
+                       case 'l':       /* lock */
+                               ctl = VERIEXEC_LOCK;
+                               break;
+                       default:
+                               errx(EX_USAGE, "unknown command %s", optarg);
+                               break;
+                       }
+                       if (dev_fd < 0) {
+                               err(EX_UNAVAILABLE, "cannot open veriexec");
+                       }
+                       if (ioctl(dev_fd, ctl, &x)) {
+                               err(EX_UNAVAILABLE, "cannot %s veriexec", 
optarg);
+                       }
+                       if (ctl == VERIEXEC_DEBUG_ON ||
+                           ctl == VERIEXEC_DEBUG_OFF) {
+                               printf("debug is: %d\n", x);
+                       } else if (ctl == VERIEXEC_GETSTATE) {
+                               printf("%#o\n", x);
+                       }
+                       exit(EX_OK);
+                       break;
+               }
+       }
+       openlog(getprogname(), LOG_PID, LOG_AUTH);
+       if (ve_trust_init() < 1)
+               errx(EX_OSFILE, "cannot initialize trust store");
+#ifdef VERIEXEC_GETVERSION
+       if (ioctl(dev_fd, VERIEXEC_GETVERSION, &VeriexecVersion)) {
+               VeriexecVersion = 0;    /* unknown */
+       }
+#endif
+
+       for (; optind < argc; optind++) {
+               if (veriexec_load(argv[optind])) {
+                       err(EX_DATAERR, "cannot load %s", argv[optind]);
+               }
+       }
+       exit(EX_OK);
+}

Added: head/sbin/veriexec/veriexec.h
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sbin/veriexec/veriexec.h       Tue Feb 26 06:17:23 2019        
(r344567)
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2018, Juniper Networks, Inc.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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$
+ */
+
+#ifndef __VERIEXEC_H__
+#define __VERIEXEC_H__
+
+#include <sys/ioctl.h>
+#include <dev/veriexec/veriexec_ioctl.h>
+
+extern int dev_fd;
+extern int parser_version;
+extern int ForceFlags;
+extern int Verbose;
+extern int VeriexecVersion;
+extern const char *Cdir;
+
+#define VERBOSE(n, x) if (Verbose > n) printf x
+
+FILE * manifest_open (const char *file, const char *file_content);
+void manifest_parser_init(void);
+int yyparse(void);
+extern FILE *yyin;
+
+#endif
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to