/src/openssh/regress/misc/fuzz-harness/hostfile_fuzz.cc
Line | Count | Source |
1 | | /* Copyright 2026 Google LLC |
2 | | Licensed under the Apache License, Version 2.0 (the "License"); |
3 | | you may not use this file except in compliance with the License. |
4 | | You may obtain a copy of the License at |
5 | | http://www.apache.org/licenses/LICENSE-2.0 |
6 | | Unless required by applicable law or agreed to in writing, software |
7 | | distributed under the License is distributed on an "AS IS" BASIS, |
8 | | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
9 | | See the License for the specific language governing permissions and |
10 | | limitations under the License. |
11 | | */ |
12 | | |
13 | | #include <stdio.h> |
14 | | #include <stddef.h> |
15 | | #include <stdint.h> |
16 | | #include <stdlib.h> |
17 | | #include <string.h> |
18 | | |
19 | | extern "C" { |
20 | | |
21 | | #include "hostfile.h" |
22 | | #include "sshkey.h" |
23 | | #include "log.h" |
24 | | |
25 | | static int log_initialized = 0; |
26 | | |
27 | | static int |
28 | | noop_cb(struct hostkey_foreach_line *l, void *ctx) |
29 | 90.7k | { |
30 | 90.7k | (void)l; (void)ctx; |
31 | 90.7k | return 0; |
32 | 90.7k | } |
33 | | |
34 | | int |
35 | | LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
36 | 1.85k | { |
37 | 1.85k | if (!log_initialized) { |
38 | 1 | log_init("hostfile_fuzz", SYSLOG_LEVEL_QUIET, |
39 | 1 | SYSLOG_FACILITY_AUTH, 0); |
40 | 1 | log_initialized = 1; |
41 | 1 | } |
42 | | |
43 | | /* Drive every HKF_WANT_* combination on each input. */ |
44 | 1.85k | static const u_int flag_combos[] = { |
45 | 1.85k | 0, |
46 | 1.85k | HKF_WANT_MATCH, |
47 | 1.85k | HKF_WANT_PARSE_KEY, |
48 | 1.85k | HKF_WANT_MATCH | HKF_WANT_PARSE_KEY, |
49 | 1.85k | }; |
50 | 9.28k | for (size_t i = 0; i < sizeof(flag_combos)/sizeof(flag_combos[0]); i++) { |
51 | 7.42k | FILE *f = fmemopen((void *)data, size, "r"); |
52 | 7.42k | if (f == NULL) |
53 | 0 | continue; |
54 | 7.42k | const char *host = (flag_combos[i] & HKF_WANT_MATCH) ? |
55 | 7.42k | "example.com" : NULL; |
56 | 7.42k | (void)hostkeys_foreach_file("/fuzz", f, noop_cb, NULL, |
57 | 7.42k | host, "127.0.0.1", flag_combos[i], 0); |
58 | 7.42k | fclose(f); |
59 | 7.42k | } |
60 | | |
61 | | /* Higher-level wrapper that adds record_hostkey on top of foreach. */ |
62 | 1.85k | { |
63 | 1.85k | FILE *f = fmemopen((void *)data, size, "r"); |
64 | 1.85k | if (f != NULL) { |
65 | 1.85k | struct hostkeys *hk = init_hostkeys(); |
66 | 1.85k | if (hk != NULL) { |
67 | 1.85k | load_hostkeys_file(hk, "example.com", |
68 | 1.85k | "/fuzz", f, 0); |
69 | 1.85k | free_hostkeys(hk); |
70 | 1.85k | } |
71 | 1.85k | fclose(f); |
72 | 1.85k | } |
73 | 1.85k | } |
74 | | |
75 | | /* Drive host_hash + extract_salt on a bounded hostname-shaped slice. */ |
76 | 1.85k | if (size > 0) { |
77 | 1.85k | size_t n = size < 256 ? size : 256; |
78 | 1.85k | char *hb = (char *)malloc(n + 1); |
79 | 1.85k | if (hb != NULL) { |
80 | 1.85k | memcpy(hb, data, n); |
81 | 1.85k | hb[n] = '\0'; |
82 | 1.85k | char *h = host_hash("example.com", hb, 0); |
83 | 1.85k | free(h); |
84 | 1.85k | free(hb); |
85 | 1.85k | } |
86 | 1.85k | } |
87 | | |
88 | 1.85k | return 0; |
89 | 1.85k | } |
90 | | |
91 | | } // extern "C" |