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