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 #include <sys/types.h> 32 #include <sys/errno.h> 33 #include <sys/mac.h> 34 35 #include <unistd.h> 36 #include <string.h> 37 38 #include <security/mac_veriexec/mac_veriexec.h> 39 40 /** 41 * @brief get veriexec params for a process 42 * 43 * @return 44 * @li 0 if successful 45 */ 46 int 47 veriexec_get_pid_params(pid_t pid, 48 struct mac_veriexec_syscall_params *params) 49 { 50 struct mac_veriexec_syscall_params_args args; 51 52 if (params == NULL) 53 return EINVAL; 54 55 args.u.pid = pid; 56 args.params = params; 57 return mac_syscall(MAC_VERIEXEC_NAME, 58 MAC_VERIEXEC_GET_PARAMS_PID_SYSCALL, &args); 59 } 60 61 /** 62 * @brief get veriexec params for a process 63 * 64 * @return 65 * @li 0 if successful 66 */ 67 int 68 veriexec_get_path_params(const char *file, 69 struct mac_veriexec_syscall_params *params) 70 { 71 struct mac_veriexec_syscall_params_args args; 72 73 if (file == NULL || params == NULL) 74 return EINVAL; 75 76 args.u.filename = file; 77 args.params = params; 78 return mac_syscall(MAC_VERIEXEC_NAME, 79 MAC_VERIEXEC_GET_PARAMS_PATH_SYSCALL, &args); 80 } 81 82 /** 83 * @brief check if a process has label that contains what we want 84 * 85 * @return 86 * @li 0 if no 87 * @li 1 if yes 88 */ 89 int 90 veriexec_check_pid_label(pid_t pid, const char *want) 91 { 92 struct mac_veriexec_syscall_params params; 93 char *cp; 94 size_t n; 95 96 if (want != NULL && 97 veriexec_get_pid_params(pid, ¶ms) == 0) { 98 /* Does label contain [,]<want>[,] ? */ 99 if (params.labellen > 0 && 100 (cp = strstr(params.label, want)) != NULL) { 101 if (cp == params.label || cp[-1] == ',') { 102 n = strlen(want); 103 if (cp[n] == '\0' || cp[n] == ',') 104 return 1; /* yes */ 105 } 106 } 107 } 108 return 0; /* no */ 109 } 110 111 /** 112 * @brief check if a path has label that contains what we want 113 * 114 * @return 115 * @li 0 if no 116 * @li 1 if yes 117 */ 118 int 119 veriexec_check_path_label(const char *file, const char *want) 120 { 121 struct mac_veriexec_syscall_params params; 122 char *cp; 123 size_t n; 124 125 if (want != NULL && file != NULL && 126 veriexec_get_path_params(file, ¶ms) == 0) { 127 /* Does label contain [,]<want>[,] ? */ 128 if (params.labellen > 0 && 129 (cp = strstr(params.label, want)) != NULL) { 130 if (cp == params.label || cp[-1] == ',') { 131 n = strlen(want); 132 if (cp[n] == '\0' || cp[n] == ',') 133 return 1; /* yes */ 134 } 135 } 136 } 137 return 0; /* no */ 138 } 139 140 #ifdef UNIT_TEST 141 #include <stdlib.h> 142 #include <stdio.h> 143 #include <err.h> 144 145 static char * 146 hash2hex(char *type, unsigned char *digest) 147 { 148 static char buf[2*MAXFINGERPRINTLEN+1]; 149 size_t n; 150 int i; 151 152 if (strcmp(type, "SHA1") == 0) { 153 n = 20; 154 } else if (strcmp(type, "SHA256") == 0) { 155 n = 32; 156 } else if (strcmp(type, "SHA384") == 0) { 157 n = 48; 158 } 159 for (i = 0; i < n; i++) { 160 sprintf(&buf[2*i], "%02x", (unsigned)digest[i]); 161 } 162 return buf; 163 } 164 165 int 166 main(int argc, char *argv[]) 167 { 168 struct mac_veriexec_syscall_params params; 169 pid_t pid; 170 char *want = NULL; 171 int pflag = 0; 172 int error; 173 int c; 174 175 while ((c = getopt(argc, argv, "pw:")) != -1) { 176 switch (c) { 177 case 'p': 178 pflag = 1; 179 break; 180 case 'w': 181 want = optarg; 182 break; 183 default: 184 break; 185 } 186 } 187 for (; optind < argc; optind++) { 188 189 if (pflag) { 190 pid = atoi(argv[optind]); 191 if (want) { 192 error = veriexec_check_pid_label(pid, want); 193 printf("pid=%d want='%s': %d\n", 194 pid, want, error); 195 continue; 196 } 197 error = veriexec_get_pid_params(pid, ¶ms); 198 } else { 199 error = veriexec_get_path_params(argv[optind], ¶ms); 200 } 201 if (error) { 202 err(2, "%s, error=%d", argv[optind], error); 203 } 204 205 printf("arg=%s, type=%s, flags=%u, label='%s', fingerprint='%s'\n", 206 argv[optind], params.fp_type, (unsigned)params.flags, 207 params.label, 208 hash2hex(params.fp_type, params.fingerprint)); 209 } 210 return 0; 211 } 212 #endif 213