clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name match.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/ssh/ssh-keysign/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.bin/ssh/ssh-keysign/.. -D WITH_OPENSSL -D WITH_ZLIB -D ENABLE_PKCS11 -D HAVE_DLOPEN -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/usr/src/usr.bin/ssh/ssh-keysign/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/ssh/ssh-keysign/../match.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | #include <sys/types.h> |
39 | |
40 | #include <ctype.h> |
41 | #include <stdlib.h> |
42 | #include <string.h> |
43 | #include <stdarg.h> |
44 | #include <stdio.h> |
45 | |
46 | #include "xmalloc.h" |
47 | #include "match.h" |
48 | #include "misc.h" |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | int |
55 | match_pattern(const char *s, const char *pattern) |
56 | { |
57 | for (;;) { |
58 | |
59 | if (!*pattern) |
60 | return !*s; |
61 | |
62 | if (*pattern == '*') { |
63 | |
64 | while (*pattern == '*') |
65 | pattern++; |
66 | |
67 | |
68 | if (!*pattern) |
69 | return 1; |
70 | |
71 | |
72 | if (*pattern != '?' && *pattern != '*') { |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | for (; *s; s++) |
79 | if (*s == *pattern && |
80 | match_pattern(s + 1, pattern + 1)) |
81 | return 1; |
82 | |
83 | return 0; |
84 | } |
85 | |
86 | |
87 | |
88 | |
89 | for (; *s; s++) |
90 | if (match_pattern(s, pattern)) |
91 | return 1; |
92 | |
93 | return 0; |
94 | } |
95 | |
96 | |
97 | |
98 | |
99 | if (!*s) |
100 | return 0; |
101 | |
102 | |
103 | if (*pattern != '?' && *pattern != *s) |
104 | return 0; |
105 | |
106 | |
107 | s++; |
108 | pattern++; |
109 | } |
110 | |
111 | } |
112 | |
113 | |
114 | |
115 | |
116 | |
117 | |
118 | |
119 | int |
120 | match_pattern_list(const char *string, const char *pattern, int dolower) |
121 | { |
122 | char sub[1024]; |
123 | int negated; |
124 | int got_positive; |
125 | u_int i, subi, len = strlen(pattern); |
126 | |
127 | got_positive = 0; |
128 | for (i = 0; i < len;) { |
129 | |
130 | if (pattern[i] == '!') { |
131 | negated = 1; |
132 | i++; |
133 | } else |
134 | negated = 0; |
135 | |
136 | |
137 | |
138 | |
139 | |
140 | for (subi = 0; |
141 | i < len && subi < sizeof(sub) - 1 && pattern[i] != ','; |
142 | subi++, i++) |
143 | sub[subi] = dolower && isupper((u_char)pattern[i]) ? |
144 | tolower((u_char)pattern[i]) : pattern[i]; |
145 | |
146 | if (subi >= sizeof(sub) - 1) |
147 | return 0; |
148 | |
149 | |
150 | if (i < len && pattern[i] == ',') |
151 | i++; |
152 | |
153 | |
154 | sub[subi] = '\0'; |
155 | |
156 | |
157 | if (match_pattern(string, sub)) { |
158 | if (negated) |
159 | return -1; |
160 | else |
161 | got_positive = 1; |
162 | } |
163 | } |
164 | |
165 | |
166 | |
167 | |
168 | |
169 | return got_positive; |
170 | } |
171 | |
172 | |
173 | int |
174 | match_usergroup_pattern_list(const char *string, const char *pattern) |
175 | { |
176 | |
177 | return match_pattern_list(string, pattern, 0); |
178 | } |
179 | |
180 | |
181 | |
182 | |
183 | |
184 | |
185 | |
186 | int |
187 | match_hostname(const char *host, const char *pattern) |
188 | { |
189 | char *hostcopy = xstrdup(host); |
190 | int r; |
191 | |
192 | lowercase(hostcopy); |
193 | r = match_pattern_list(hostcopy, pattern, 1); |
194 | free(hostcopy); |
195 | return r; |
196 | } |
197 | |
198 | |
199 | |
200 | |
201 | |
202 | |
203 | int |
204 | match_host_and_ip(const char *host, const char *ipaddr, |
205 | const char *patterns) |
206 | { |
207 | int mhost, mip; |
208 | |
209 | if ((mip = addr_match_list(ipaddr, patterns)) == -2) |
210 | return -1; |
211 | else if (host == NULL || ipaddr == NULL || mip == -1) |
212 | return 0; |
213 | |
214 | |
215 | if ((mhost = match_hostname(host, patterns)) == -1) |
216 | return 0; |
217 | |
218 | if (mhost == 0 && mip == 0) |
219 | return 0; |
220 | return 1; |
221 | } |
222 | |
223 | |
224 | |
225 | |
226 | |
227 | |
228 | int |
229 | match_user(const char *user, const char *host, const char *ipaddr, |
230 | const char *pattern) |
231 | { |
232 | char *p, *pat; |
233 | int ret; |
234 | |
235 | |
236 | if (user == NULL && host == NULL && ipaddr == NULL) { |
237 | if ((p = strchr(pattern, '@')) != NULL && |
238 | match_host_and_ip(NULL, NULL, p + 1) < 0) |
239 | return -1; |
240 | return 0; |
241 | } |
242 | |
243 | if ((p = strchr(pattern, '@')) == NULL) |
244 | return match_pattern(user, pattern); |
245 | |
246 | pat = xstrdup(pattern); |
247 | p = strchr(pat, '@'); |
248 | *p++ = '\0'; |
249 | |
250 | if ((ret = match_pattern(user, pat)) == 1) |
251 | ret = match_host_and_ip(host, ipaddr, p); |
252 | free(pat); |
253 | |
254 | return ret; |
255 | } |
256 | |
257 | |
258 | |
259 | |
260 | |
261 | #define MAX_PROP 40 |
262 | #define SEP "," |
263 | char * |
264 | match_list(const char *client, const char *server, u_int *next) |
265 | { |
266 | char *sproposals[MAX_PROP]; |
267 | char *c, *s, *p, *ret, *cp, *sp; |
268 | int i, j, nproposals; |
269 | |
270 | c = cp = xstrdup(client); |
| 1 | The value of 'cp' is assigned to 'c' | |
|
271 | s = sp = xstrdup(server); |
272 | |
273 | for ((p = strsep(&sp, SEP)), i=0; p && *p != '\0'; |
| |
274 | (p = strsep(&sp, SEP)), i++) { |
275 | if (i < MAX_PROP) |
276 | sproposals[i] = p; |
277 | else |
278 | break; |
279 | } |
280 | nproposals = i; |
281 | |
282 | for ((p = strsep(&cp, SEP)), i=0; p && *p != '\0'; |
| |
283 | (p = strsep(&cp, SEP)), i++) { |
284 | for (j = 0; j < nproposals; j++) { |
285 | if (strcmp(p, sproposals[j]) == 0) { |
286 | ret = xstrdup(p); |
287 | if (next != NULL) |
288 | *next = (cp == NULL) ? |
289 | strlen(c) : (u_int)(cp - c); |
290 | free(c); |
291 | free(s); |
292 | return ret; |
293 | } |
294 | } |
295 | } |
296 | if (next != NULL) |
| 4 | | Assuming 'next' is not equal to NULL | |
|
| |
297 | *next = strlen(c); |
| 6 | | Null pointer passed as 1st argument to string length function |
|
298 | free(c); |
299 | free(s); |
300 | return NULL; |
301 | } |
302 | |
303 | |
304 | |
305 | |
306 | |
307 | |
308 | |
309 | |
310 | static char * |
311 | filter_list(const char *proposal, const char *filter, int denylist) |
312 | { |
313 | size_t len = strlen(proposal) + 1; |
314 | char *fix_prop = malloc(len); |
315 | char *orig_prop = strdup(proposal); |
316 | char *cp, *tmp; |
317 | int r; |
318 | |
319 | if (fix_prop == NULL || orig_prop == NULL) { |
320 | free(orig_prop); |
321 | free(fix_prop); |
322 | return NULL; |
323 | } |
324 | |
325 | tmp = orig_prop; |
326 | *fix_prop = '\0'; |
327 | while ((cp = strsep(&tmp, ",")) != NULL) { |
328 | r = match_pattern_list(cp, filter, 0); |
329 | if ((denylist && r != 1) || (!denylist && r == 1)) { |
330 | if (*fix_prop != '\0') |
331 | strlcat(fix_prop, ",", len); |
332 | strlcat(fix_prop, cp, len); |
333 | } |
334 | } |
335 | free(orig_prop); |
336 | return fix_prop; |
337 | } |
338 | |
339 | |
340 | |
341 | |
342 | |
343 | char * |
344 | match_filter_denylist(const char *proposal, const char *filter) |
345 | { |
346 | return filter_list(proposal, filter, 1); |
347 | } |
348 | |
349 | |
350 | |
351 | |
352 | |
353 | char * |
354 | match_filter_allowlist(const char *proposal, const char *filter) |
355 | { |
356 | return filter_list(proposal, filter, 0); |
357 | } |