2 * Copyright (c) 2018, Juniper Networks, Inc.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
17 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 #include <sys/cdefs.h>
26 __FBSDID("$FreeBSD$");
34 #include <libsecureboot.h>
35 #include <libveriexec.h>
36 #include <sys/types.h>
40 /* Globals that are shared with manifest_parser.c */
44 int VeriexecVersion = 0;
45 const char *Cdir = NULL;
48 * @brief Print help message describing program's usage
50 * @return always returns code 0
56 "Usage:\tveriexec [-h] [-i state] [-C] [-xv state|verbosity] [path]\n");
62 * @brief Load a veriexec manifest
63 * @param manifest Pointer to the location of the manifest file
64 * @retval the error code returned from the parser
67 veriexec_load(const char *manifest)
69 unsigned char *content;
72 content = verify_signed(manifest, VEF_VERBOSE);
74 errx(EX_USAGE, "cannot verify %s", manifest);
75 if (manifest_open(manifest, (const char *)content)) {
78 err(EX_NOINPUT, "cannot load %s", manifest);
85 * @brief Get the veriexec state for the supplied argument
86 * @param arg_text String containing the argument to be processed
87 * @retval The veriexec state number for the specified argument
90 veriexec_state_query(const char *arg_text)
95 len = strlen(arg_text);
97 if (strncmp(arg_text, "active", len) == 0)
98 state |= VERIEXEC_STATE_ACTIVE;
99 else if (strncmp(arg_text, "enforce", len) == 0)
100 state |= VERIEXEC_STATE_ENFORCE;
101 if (strncmp(arg_text, "loaded", len) == 0)
102 state |= VERIEXEC_STATE_LOADED;
103 if (strncmp(arg_text, "locked", len) == 0)
104 state |= VERIEXEC_STATE_LOCKED;
105 if (state == 0 || __bitcount(state) > 1)
106 errx(EX_USAGE, "Unknown state \'%s\'", arg_text);
112 * @brief Get the veriexec command state for the supplied argument
113 * @param arg_text String containing the argument to be processed
114 * @retval The veriexec command state for the specified argument
117 veriexec_state_modify(const char *arg_text)
122 len = strlen(arg_text);
124 if (strncmp(arg_text, "active", len) == 0)
125 state = VERIEXEC_ACTIVE;
126 else if (strncmp(arg_text, "enforce", len) == 0)
127 state = VERIEXEC_ENFORCE;
128 else if (strncmp(arg_text, "getstate", len) == 0)
129 state = VERIEXEC_GETSTATE;
130 else if (strncmp(arg_text, "lock", len) == 0)
131 state = VERIEXEC_LOCK;
133 errx(EX_USAGE, "Unknown command \'%s\'", arg_text);
139 main(int argc, char *argv[])
141 long long converted_int;
147 return (veriexec_usage());
149 dev_fd = open(_PATH_DEV_VERIEXEC, O_WRONLY, 0);
151 while ((c = getopt(argc, argv, "hC:i:xvz:")) != -1) {
154 /* Print usage info */
156 return (veriexec_usage());
158 /* Get the provided directory argument */
163 /* Query the current state */
166 err(EX_UNAVAILABLE, "cannot open veriexec");
168 if (ioctl(dev_fd, VERIEXEC_GETSTATE, &x)) {
170 "Cannot get veriexec state");
173 state = veriexec_state_query(optarg);
175 exit((x & state) == 0);
178 /* Increase the verbosity */
183 /* Check veriexec paths */
186 * -x says all other args are paths to check.
188 for (x = EX_OK; optind < argc; optind++) {
189 if (veriexec_check_path(argv[optind])) {
190 warn("%s", argv[optind]);
197 /* Modify the state */
199 if (strncmp(optarg, "debug", strlen(optarg)) == 0) {
204 "Missing mac_veriexec verbosity level \'N\', veriexec -z debug N, where N is \'off\' or the value 0 or greater");
206 if (strncmp(argv[optind], "off", strlen(argv[optind])) == 0) {
207 state = VERIEXEC_DEBUG_OFF;
210 state = VERIEXEC_DEBUG_ON;
212 converted_int = strtonum(argv[optind], 0, INT_MAX, &error);
215 errx(EX_USAGE, "Conversion error for argument \'%s\' : %s",
216 argv[optind], error);
218 x = (int) converted_int;
222 state = VERIEXEC_DEBUG_OFF;
225 state = veriexec_state_modify(optarg);
228 err(EX_UNAVAILABLE, "Cannot open veriexec");
229 if (ioctl(dev_fd, state, &x))
230 err(EX_UNAVAILABLE, "Cannot %s veriexec", optarg);
232 if (state == VERIEXEC_DEBUG_ON || state == VERIEXEC_DEBUG_OFF)
233 printf("mac_veriexec debug verbosity level: %d\n", x);
234 else if (state == VERIEXEC_GETSTATE)
235 printf("Veriexec state (octal) : %#o\n", x);
241 /* Missing argument, print usage info.*/
249 printf("Verbosity level : %d\n", Verbose);
252 err(EX_UNAVAILABLE, "Cannot open veriexec");
254 openlog(getprogname(), LOG_PID, LOG_AUTH);
255 if (ve_trust_init() < 1)
256 errx(EX_OSFILE, "cannot initialize trust store");
257 #ifdef VERIEXEC_GETVERSION
258 if (ioctl(dev_fd, VERIEXEC_GETVERSION, &VeriexecVersion)) {
259 VeriexecVersion = 0; /* unknown */
263 for (; optind < argc; optind++) {
264 if (veriexec_load(argv[optind])) {
265 err(EX_DATAERR, "cannot load %s", argv[optind]);