1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2021-2023, Juniper Networks, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 #include <sys/types.h> 33 #include <sys/errno.h> 34 #include <sys/mac.h> 35 36 #include <unistd.h> 37 #include <string.h> 38 39 #include <security/mac_veriexec/mac_veriexec.h> 40 41 /** 42 * @brief get veriexec params for a process 43 * 44 * @return 45 * @li 0 if successful 46 */ 47 int 48 veriexec_get_pid_params(pid_t pid, 49 struct mac_veriexec_syscall_params *params) 50 { 51 struct mac_veriexec_syscall_params_args args; 52 53 if (params == NULL) 54 return EINVAL; 55 56 args.u.pid = pid; 57 args.params = params; 58 return mac_syscall(MAC_VERIEXEC_NAME, 59 MAC_VERIEXEC_GET_PARAMS_PID_SYSCALL, &args); 60 } 61 62 /** 63 * @brief get veriexec params for a process 64 * 65 * @return 66 * @li 0 if successful 67 */ 68 int 69 veriexec_get_path_params(const char *file, 70 struct mac_veriexec_syscall_params *params) 71 { 72 struct mac_veriexec_syscall_params_args args; 73 74 if (file == NULL || params == NULL) 75 return EINVAL; 76 77 args.u.filename = file; 78 args.params = params; 79 return mac_syscall(MAC_VERIEXEC_NAME, 80 MAC_VERIEXEC_GET_PARAMS_PATH_SYSCALL, &args); 81 } 82 83 /** 84 * @brief check if a process has label that contains what we want 85 * 86 * @return 87 * @li 0 if no 88 * @li 1 if yes 89 */ 90 int 91 veriexec_check_pid_label(pid_t pid, const char *want) 92 { 93 struct mac_veriexec_syscall_params params; 94 char *cp; 95 size_t n; 96 97 if (want != NULL && 98 veriexec_get_pid_params(pid, ¶ms) == 0) { 99 /* Does label contain [,]<want>[,] ? */ 100 if (params.labellen > 0 && 101 (cp = strstr(params.label, want)) != NULL) { 102 if (cp == params.label || cp[-1] == ',') { 103 n = strlen(want); 104 if (cp[n] == '\0' || cp[n] == ',') 105 return 1; /* yes */ 106 } 107 } 108 } 109 return 0; /* no */ 110 } 111 112 /** 113 * @brief check if a path has label that contains what we want 114 * 115 * @return 116 * @li 0 if no 117 * @li 1 if yes 118 */ 119 int 120 veriexec_check_path_label(const char *file, const char *want) 121 { 122 struct mac_veriexec_syscall_params params; 123 char *cp; 124 size_t n; 125 126 if (want != NULL && file != NULL && 127 veriexec_get_path_params(file, ¶ms) == 0) { 128 /* Does label contain [,]<want>[,] ? */ 129 if (params.labellen > 0 && 130 (cp = strstr(params.label, want)) != NULL) { 131 if (cp == params.label || cp[-1] == ',') { 132 n = strlen(want); 133 if (cp[n] == '\0' || cp[n] == ',') 134 return 1; /* yes */ 135 } 136 } 137 } 138 return 0; /* no */ 139 } 140 141 #ifdef UNIT_TEST 142 #include <stdlib.h> 143 #include <stdio.h> 144 #include <err.h> 145 146 static char * 147 hash2hex(char *type, unsigned char *digest) 148 { 149 static char buf[2*MAXFINGERPRINTLEN+1]; 150 size_t n; 151 int i; 152 153 if (strcmp(type, "SHA1") == 0) { 154 n = 20; 155 } else if (strcmp(type, "SHA256") == 0) { 156 n = 32; 157 } else if (strcmp(type, "SHA384") == 0) { 158 n = 48; 159 } 160 for (i = 0; i < n; i++) { 161 sprintf(&buf[2*i], "%02x", (unsigned)digest[i]); 162 } 163 return buf; 164 } 165 166 int 167 main(int argc, char *argv[]) 168 { 169 struct mac_veriexec_syscall_params params; 170 pid_t pid; 171 char *want = NULL; 172 int pflag = 0; 173 int error; 174 int c; 175 176 while ((c = getopt(argc, argv, "pw:")) != -1) { 177 switch (c) { 178 case 'p': 179 pflag = 1; 180 break; 181 case 'w': 182 want = optarg; 183 break; 184 default: 185 break; 186 } 187 } 188 for (; optind < argc; optind++) { 189 190 if (pflag) { 191 pid = atoi(argv[optind]); 192 if (want) { 193 error = veriexec_check_pid_label(pid, want); 194 printf("pid=%d want='%s': %d\n", 195 pid, want, error); 196 continue; 197 } 198 error = veriexec_get_pid_params(pid, ¶ms); 199 } else { 200 error = veriexec_get_path_params(argv[optind], ¶ms); 201 } 202 if (error) { 203 err(2, "%s, error=%d", argv[optind], error); 204 } 205 206 printf("arg=%s, type=%s, flags=%u, label='%s', fingerprint='%s'\n", 207 argv[optind], params.fp_type, (unsigned)params.flags, 208 params.label, 209 hash2hex(params.fp_type, params.fingerprint)); 210 } 211 return 0; 212 } 213 #endif 214