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 | } |