summaryrefslogtreecommitdiffstats
path: root/Utilities/cmcurl/lib/doh.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/doh.c')
-rw-r--r--Utilities/cmcurl/lib/doh.c157
1 files changed, 61 insertions, 96 deletions
diff --git a/Utilities/cmcurl/lib/doh.c b/Utilities/cmcurl/lib/doh.c
index aaa8f15..ebb2c24 100644
--- a/Utilities/cmcurl/lib/doh.c
+++ b/Utilities/cmcurl/lib/doh.c
@@ -35,13 +35,13 @@
#include "curl_base64.h"
#include "connect.h"
#include "strdup.h"
+#include "dynbuf.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
#define DNS_CLASS_IN 0x01
-#define DOH_MAX_RESPONSE_SIZE 3000 /* bytes */
#ifndef CURL_DISABLE_VERBOSE_STRINGS
static const char * const errors[]={
@@ -174,23 +174,14 @@ UNITTEST DOHcode doh_encode(const char *host,
}
static size_t
-doh_write_cb(void *contents, size_t size, size_t nmemb, void *userp)
+doh_write_cb(const void *contents, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
- struct dohresponse *mem = (struct dohresponse *)userp;
+ struct dynbuf *mem = (struct dynbuf *)userp;
- if((mem->size + realsize) > DOH_MAX_RESPONSE_SIZE)
- /* suspiciously much for us */
+ if(Curl_dyn_addn(mem, contents, realsize))
return 0;
- mem->memory = Curl_saferealloc(mem->memory, mem->size + realsize);
- if(!mem->memory)
- /* out of memory! */
- return 0;
-
- memcpy(&(mem->memory[mem->size]), contents, realsize);
- mem->size += realsize;
-
return realsize;
}
@@ -238,10 +229,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
}
p->dnstype = dnstype;
- p->serverdoh.memory = NULL;
- /* the memory will be grown as needed by realloc in the doh_write_cb
- function */
- p->serverdoh.size = 0;
+ Curl_dyn_init(&p->serverdoh, DYN_DOH_RESPONSE);
/* Note: this is code for sending the DoH request with GET but there's still
no logic that actually enables this. We should either add that ability or
@@ -272,7 +260,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
if(!result) {
/* pass in the struct pointer via a local variable to please coverity and
the gcc typecheck helpers */
- struct dohresponse *resp = &p->serverdoh;
+ struct dynbuf *resp = &p->serverdoh;
ERROR_CHECK_SETOPT(CURLOPT_URL, url);
ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);
ERROR_CHECK_SETOPT(CURLOPT_WRITEDATA, resp);
@@ -318,6 +306,9 @@ static CURLcode dohprobe(struct Curl_easy *data,
}
if(data->set.proxy_ssl.no_revoke)
ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
+ else if(data->set.proxy_ssl.revoke_best_effort)
+ ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS,
+ CURLSSLOPT_REVOKE_BEST_EFFORT);
if(data->set.str[STRING_SSL_CAPATH_PROXY]) {
ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAPATH,
data->set.str[STRING_SSL_CAPATH_PROXY]);
@@ -351,6 +342,8 @@ static CURLcode dohprobe(struct Curl_easy *data,
}
if(data->set.ssl.no_revoke)
ERROR_CHECK_SETOPT(CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
+ else if(data->set.ssl.revoke_best_effort)
+ ERROR_CHECK_SETOPT(CURLOPT_SSL_OPTIONS, CURLSSLOPT_REVOKE_BEST_EFFORT);
if(data->set.ssl.fsslctx)
ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx);
if(data->set.ssl.fsslctxp)
@@ -380,10 +373,10 @@ static CURLcode dohprobe(struct Curl_easy *data,
* 'Curl_addrinfo *' with the address information.
*/
-Curl_addrinfo *Curl_doh(struct connectdata *conn,
- const char *hostname,
- int port,
- int *waitp)
+struct Curl_addrinfo *Curl_doh(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
{
struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
@@ -396,6 +389,7 @@ Curl_addrinfo *Curl_doh(struct connectdata *conn,
/* start clean, consider allocating this struct on demand */
memset(&data->req.doh, 0, sizeof(struct dohdata));
+ conn->bits.doh = TRUE;
data->req.doh.host = hostname;
data->req.doh.port = port;
data->req.doh.headers =
@@ -434,7 +428,7 @@ Curl_addrinfo *Curl_doh(struct connectdata *conn,
return NULL;
}
-static DOHcode skipqname(unsigned char *doh, size_t dohlen,
+static DOHcode skipqname(const unsigned char *doh, size_t dohlen,
unsigned int *indexp)
{
unsigned char length;
@@ -458,12 +452,12 @@ static DOHcode skipqname(unsigned char *doh, size_t dohlen,
return DOH_OK;
}
-static unsigned short get16bit(unsigned char *doh, int index)
+static unsigned short get16bit(const unsigned char *doh, int index)
{
return (unsigned short)((doh[index] << 8) | doh[index + 1]);
}
-static unsigned int get32bit(unsigned char *doh, int index)
+static unsigned int get32bit(const unsigned char *doh, int index)
{
/* make clang and gcc optimize this to bswap by incrementing
the pointer first. */
@@ -475,7 +469,7 @@ static unsigned int get32bit(unsigned char *doh, int index)
return ( (unsigned)doh[0] << 24) | (doh[1] << 16) |(doh[2] << 8) | doh[3];
}
-static DOHcode store_a(unsigned char *doh, int index, struct dohentry *d)
+static DOHcode store_a(const unsigned char *doh, int index, struct dohentry *d)
{
/* silently ignore addresses over the limit */
if(d->numaddr < DOH_MAX_ADDR) {
@@ -487,7 +481,9 @@ static DOHcode store_a(unsigned char *doh, int index, struct dohentry *d)
return DOH_OK;
}
-static DOHcode store_aaaa(unsigned char *doh, int index, struct dohentry *d)
+static DOHcode store_aaaa(const unsigned char *doh,
+ int index,
+ struct dohentry *d)
{
/* silently ignore addresses over the limit */
if(d->numaddr < DOH_MAX_ADDR) {
@@ -499,38 +495,12 @@ static DOHcode store_aaaa(unsigned char *doh, int index, struct dohentry *d)
return DOH_OK;
}
-static DOHcode cnameappend(struct cnamestore *c,
- unsigned char *src,
- size_t len)
-{
- if(!c->alloc) {
- c->allocsize = len + 1;
- c->alloc = malloc(c->allocsize);
- if(!c->alloc)
- return DOH_OUT_OF_MEM;
- }
- else if(c->allocsize < (c->allocsize + len + 1)) {
- char *ptr;
- c->allocsize += len + 1;
- ptr = realloc(c->alloc, c->allocsize);
- if(!ptr) {
- free(c->alloc);
- return DOH_OUT_OF_MEM;
- }
- c->alloc = ptr;
- }
- memcpy(&c->alloc[c->len], src, len);
- c->len += len;
- c->alloc[c->len] = 0; /* keep it zero terminated */
- return DOH_OK;
-}
-
-static DOHcode store_cname(unsigned char *doh,
+static DOHcode store_cname(const unsigned char *doh,
size_t dohlen,
unsigned int index,
struct dohentry *d)
{
- struct cnamestore *c;
+ struct dynbuf *c;
unsigned int loop = 128; /* a valid DNS name can never loop this much */
unsigned char length;
@@ -559,18 +529,15 @@ static DOHcode store_cname(unsigned char *doh,
index++;
if(length) {
- DOHcode rc;
- if(c->len) {
- rc = cnameappend(c, (unsigned char *)".", 1);
- if(rc)
- return rc;
+ if(Curl_dyn_len(c)) {
+ if(Curl_dyn_add(c, "."))
+ return DOH_OUT_OF_MEM;
}
if((index + length) > dohlen)
return DOH_DNS_BAD_LABEL;
- rc = cnameappend(c, &doh[index], length);
- if(rc)
- return rc;
+ if(Curl_dyn_addn(c, &doh[index], length))
+ return DOH_OUT_OF_MEM;
index += length;
}
} while(length && --loop);
@@ -580,7 +547,7 @@ static DOHcode store_cname(unsigned char *doh,
return DOH_OK;
}
-static DOHcode rdata(unsigned char *doh,
+static DOHcode rdata(const unsigned char *doh,
size_t dohlen,
unsigned short rdlength,
unsigned short type,
@@ -623,14 +590,17 @@ static DOHcode rdata(unsigned char *doh,
return DOH_OK;
}
-static void init_dohentry(struct dohentry *de)
+UNITTEST void de_init(struct dohentry *de)
{
+ int i;
memset(de, 0, sizeof(*de));
de->ttl = INT_MAX;
+ for(i = 0; i < DOH_MAX_CNAME; i++)
+ Curl_dyn_init(&de->cname[i], DYN_DOH_CNAME);
}
-UNITTEST DOHcode doh_decode(unsigned char *doh,
+UNITTEST DOHcode doh_decode(const unsigned char *doh,
size_t dohlen,
DNStype dnstype,
struct dohentry *d)
@@ -770,12 +740,12 @@ UNITTEST DOHcode doh_decode(unsigned char *doh,
#ifndef CURL_DISABLE_VERBOSE_STRINGS
static void showdoh(struct Curl_easy *data,
- struct dohentry *d)
+ const struct dohentry *d)
{
int i;
infof(data, "TTL: %u seconds\n", d->ttl);
for(i = 0; i < d->numaddr; i++) {
- struct dohaddr *a = &d->addr[i];
+ const struct dohaddr *a = &d->addr[i];
if(a->type == DNS_TYPE_A) {
infof(data, "DOH A: %u.%u.%u.%u\n",
a->ip.v4[0], a->ip.v4[1],
@@ -801,7 +771,7 @@ static void showdoh(struct Curl_easy *data,
}
}
for(i = 0; i < d->numcname; i++) {
- infof(data, "CNAME: %s\n", d->cname[i].alloc);
+ infof(data, "CNAME: %s\n", Curl_dyn_ptr(&d->cname[i]));
}
}
#else
@@ -821,18 +791,19 @@ static void showdoh(struct Curl_easy *data,
* must be an associated call later to Curl_freeaddrinfo().
*/
-static Curl_addrinfo *
+static struct Curl_addrinfo *
doh2ai(const struct dohentry *de, const char *hostname, int port)
{
- Curl_addrinfo *ai;
- Curl_addrinfo *prevai = NULL;
- Curl_addrinfo *firstai = NULL;
+ struct Curl_addrinfo *ai;
+ struct Curl_addrinfo *prevai = NULL;
+ struct Curl_addrinfo *firstai = NULL;
struct sockaddr_in *addr;
#ifdef ENABLE_IPV6
struct sockaddr_in6 *addr6;
#endif
CURLcode result = CURLE_OK;
int i;
+ size_t hostlen = strlen(hostname) + 1; /* include zero terminator */
if(!de)
/* no input == no output! */
@@ -855,24 +826,14 @@ doh2ai(const struct dohentry *de, const char *hostname, int port)
addrtype = AF_INET;
}
- ai = calloc(1, sizeof(Curl_addrinfo));
+ ai = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen);
if(!ai) {
result = CURLE_OUT_OF_MEMORY;
break;
}
- ai->ai_canonname = strdup(hostname);
- if(!ai->ai_canonname) {
- result = CURLE_OUT_OF_MEMORY;
- free(ai);
- break;
- }
- ai->ai_addr = calloc(1, ss_size);
- if(!ai->ai_addr) {
- result = CURLE_OUT_OF_MEMORY;
- free(ai->ai_canonname);
- free(ai);
- break;
- }
+ ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
+ ai->ai_canonname = (void *)((char *)ai->ai_addr + ss_size);
+ memcpy(ai->ai_canonname, hostname, hostlen);
if(!firstai)
/* store the pointer we want to return from this function */
@@ -934,7 +895,7 @@ UNITTEST void de_cleanup(struct dohentry *d)
{
int i = 0;
for(i = 0; i < d->numcname; i++) {
- free(d->cname[i].alloc);
+ Curl_dyn_free(&d->cname[i]);
}
}
@@ -952,7 +913,9 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
CURLE_COULDNT_RESOLVE_HOST;
}
else if(!data->req.doh.pending) {
- DOHcode rc[DOH_PROBE_SLOTS];
+ DOHcode rc[DOH_PROBE_SLOTS] = {
+ DOH_OK, DOH_OK
+ };
struct dohentry de;
int slot;
/* remove DOH handles from multi handle and close them */
@@ -961,17 +924,19 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
Curl_close(&data->req.doh.probe[slot].easy);
}
/* parse the responses, create the struct and return it! */
- init_dohentry(&de);
+ de_init(&de);
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
- rc[slot] = doh_decode(data->req.doh.probe[slot].serverdoh.memory,
- data->req.doh.probe[slot].serverdoh.size,
- data->req.doh.probe[slot].dnstype,
+ struct dnsprobe *p = &data->req.doh.probe[slot];
+ if(!p->dnstype)
+ continue;
+ rc[slot] = doh_decode(Curl_dyn_uptr(&p->serverdoh),
+ Curl_dyn_len(&p->serverdoh),
+ p->dnstype,
&de);
- Curl_safefree(data->req.doh.probe[slot].serverdoh.memory);
+ Curl_dyn_free(&p->serverdoh);
if(rc[slot]) {
infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc[slot]),
- type2name(data->req.doh.probe[slot].dnstype),
- data->req.doh.host);
+ type2name(p->dnstype), data->req.doh.host);
}
} /* next slot */