Skip to content

Commit ce8927d

Browse files
committed
fuzz_doh: fuzz DNS-over-HTTPS response decoding
1 parent e7ffaa6 commit ce8927d

File tree

2 files changed

+140
-0
lines changed

2 files changed

+140
-0
lines changed

Makefile.am

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ FUZZPROGS = curl_fuzzer \
3939
curl_fuzzer_altsvc \
4040
curl_fuzzer_base64 \
4141
curl_fuzzer_dict \
42+
curl_fuzzer_doh \
4243
curl_fuzzer_file \
4344
curl_fuzzer_ftp \
4445
curl_fuzzer_gopher \
@@ -145,6 +146,10 @@ curl_fuzzer_base64_SOURCES = fuzz_base64.cc
145146
curl_fuzzer_base64_CXXFLAGS = $(COMMON_FLAGS)
146147
curl_fuzzer_base64_LDADD = $(COMMON_LDADD)
147148

149+
curl_fuzzer_doh_SOURCES = fuzz_doh.cc
150+
curl_fuzzer_doh_CXXFLAGS = $(COMMON_FLAGS)
151+
curl_fuzzer_doh_LDADD = $(COMMON_LDADD)
152+
148153
# Create the seed corpora zip files.
149154
zip:
150155
BUILD_ROOT=$(PWD) scripts/create_zip.sh

fuzz_doh.cc

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/***************************************************************************
2+
* _ _ ____ _
3+
* Project ___| | | | _ \| |
4+
* / __| | | | |_) | |
5+
* | (__| |_| | _ <| |___
6+
* \___|\___/|_| \_\_____|
7+
*
8+
* Copyright (C) 2017, Max Dymond, <[email protected]>, et al.
9+
*
10+
* This software is licensed as described in the file COPYING, which
11+
* you should have received as part of this distribution. The terms
12+
* are also available at https://curl.se/docs/copyright.html.
13+
*
14+
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
15+
* copies of the Software, and permit persons to whom the Software is
16+
* furnished to do so, under the terms of the COPYING file.
17+
*
18+
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19+
* KIND, either express or implied.
20+
*
21+
***************************************************************************/
22+
23+
extern "C"
24+
{
25+
#include <stdlib.h>
26+
#include <signal.h>
27+
#include <string.h>
28+
#include <unistd.h>
29+
#include <inttypes.h>
30+
#include <curl/curl.h>
31+
#include <assert.h>
32+
#define WARN_UNUSED_RESULT /* hack */
33+
#define DEBUGBUILD
34+
#include "curl/lib/dynbuf.h"
35+
36+
typedef enum {
37+
DOH_OK,
38+
DOH_DNS_BAD_LABEL, /* 1 */
39+
DOH_DNS_OUT_OF_RANGE, /* 2 */
40+
DOH_DNS_LABEL_LOOP, /* 3 */
41+
DOH_TOO_SMALL_BUFFER, /* 4 */
42+
DOH_OUT_OF_MEM, /* 5 */
43+
DOH_DNS_RDATA_LEN, /* 6 */
44+
DOH_DNS_MALFORMAT, /* 7 */
45+
DOH_DNS_BAD_RCODE, /* 8 - no such name */
46+
DOH_DNS_UNEXPECTED_TYPE, /* 9 */
47+
DOH_DNS_UNEXPECTED_CLASS, /* 10 */
48+
DOH_NO_CONTENT, /* 11 */
49+
DOH_DNS_BAD_ID, /* 12 */
50+
DOH_DNS_NAME_TOO_LONG /* 13 */
51+
} DOHcode;
52+
53+
typedef enum {
54+
DNS_TYPE_A = 1,
55+
DNS_TYPE_NS = 2,
56+
DNS_TYPE_CNAME = 5,
57+
DNS_TYPE_AAAA = 28,
58+
DNS_TYPE_DNAME = 39 /* RFC6672 */
59+
} DNStype;
60+
61+
/* one of these for each DoH request */
62+
struct dnsprobe {
63+
CURL *easy;
64+
DNStype dnstype;
65+
unsigned char dohbuffer[512];
66+
size_t dohlen;
67+
struct dynbuf serverdoh;
68+
};
69+
70+
#define DOH_MAX_ADDR 24
71+
#define DOH_MAX_CNAME 4
72+
73+
struct dohaddr {
74+
int type;
75+
union {
76+
unsigned char v4[4]; /* network byte order */
77+
unsigned char v6[16];
78+
} ip;
79+
};
80+
81+
struct dohentry {
82+
struct dynbuf cname[DOH_MAX_CNAME];
83+
struct dohaddr addr[DOH_MAX_ADDR];
84+
int numaddr;
85+
unsigned int ttl;
86+
int numcname;
87+
//char padding[1000];
88+
};
89+
90+
91+
DOHcode doh_encode(const char *host,
92+
DNStype dnstype,
93+
unsigned char *dnsp, /* buffer */
94+
size_t len, /* buffer size */
95+
size_t *olen); /* output length */
96+
DOHcode doh_decode(const unsigned char *doh,
97+
size_t dohlen,
98+
DNStype dnstype,
99+
struct dohentry *d);
100+
void de_init(struct dohentry *d);
101+
void de_cleanup(struct dohentry *d);
102+
}
103+
104+
#include <string>
105+
106+
/* #define DEBUG(STMT) STMT */
107+
#define DEBUG(STMT)
108+
109+
110+
/**
111+
* Fuzzing entry point. This function is passed a buffer containing a test
112+
* case. This test case should drive the CURL fnmatch function.
113+
*/
114+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
115+
{
116+
struct dohentry d;
117+
DOHcode fnrc;
118+
119+
de_init(&d);
120+
fnrc = doh_decode(data, size, DNS_TYPE_A, &d);
121+
(void)fnrc;
122+
DEBUG(printf("doh_decode returned %d for A\n", fnrc));
123+
124+
fnrc = doh_decode(data, size, DNS_TYPE_NS, &d);
125+
(void)fnrc;
126+
DEBUG(printf("doh_decode returned %d for NS\n", fnrc));
127+
128+
fnrc = doh_decode(data, size, DNS_TYPE_AAAA, &d);
129+
(void)fnrc;
130+
DEBUG(printf("doh_decode returned %d for AAAA\n", fnrc));
131+
132+
de_cleanup(&d);
133+
134+
return 0;
135+
}

0 commit comments

Comments
 (0)