xref: /freebsd/lib/libveriexec/veriexec_get.c (revision 1d386b48)
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, &params) == 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, &params) == 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, &params);
198 		} else {
199 			error = veriexec_get_path_params(argv[optind], &params);
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